@doswiftly/storefront-sdk 19.1.0 → 20.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/CHANGELOG.md +119 -0
- package/dist/core/auth/session-events.d.ts +6 -9
- package/dist/core/auth/session-events.d.ts.map +1 -1
- package/dist/core/auth/session-events.js +6 -9
- package/dist/core/cart/cart-client.d.ts +39 -2
- package/dist/core/cart/cart-client.d.ts.map +1 -1
- package/dist/core/cart/cart-client.js +53 -3
- package/dist/core/cart/cart-recovery.d.ts +41 -71
- package/dist/core/cart/cart-recovery.d.ts.map +1 -1
- package/dist/core/cart/cart-recovery.js +37 -95
- package/dist/core/cart/cookie-config.d.ts +29 -3
- package/dist/core/cart/cookie-config.d.ts.map +1 -1
- package/dist/core/cart/cookie-config.js +35 -3
- package/dist/core/generated/operation-types.d.ts +268 -4
- package/dist/core/generated/operation-types.d.ts.map +1 -1
- package/dist/core/generated/operation-types.js +8 -0
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -2
- package/dist/core/middleware/cart-secret.d.ts +43 -0
- package/dist/core/middleware/cart-secret.d.ts.map +1 -0
- package/dist/core/middleware/cart-secret.js +55 -0
- package/dist/core/middleware/session-retry.d.ts +2 -2
- package/dist/core/middleware/session-retry.js +2 -2
- package/dist/core/operations/cart.d.ts +23 -0
- package/dist/core/operations/cart.d.ts.map +1 -1
- package/dist/core/operations/cart.js +71 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/react/cookies.d.ts +6 -0
- package/dist/react/cookies.d.ts.map +1 -1
- package/dist/react/cookies.js +23 -4
- package/dist/react/hooks/use-cart-manager.d.ts +20 -13
- package/dist/react/hooks/use-cart-manager.d.ts.map +1 -1
- package/dist/react/hooks/use-cart-manager.js +14 -12
- package/dist/react/hooks/use-logout.d.ts +7 -5
- package/dist/react/hooks/use-logout.d.ts.map +1 -1
- package/dist/react/hooks/use-logout.js +37 -7
- package/dist/react/providers/cart-manager-provider.d.ts +3 -0
- package/dist/react/providers/cart-manager-provider.d.ts.map +1 -1
- package/dist/react/providers/storefront-client-provider.d.ts.map +1 -1
- package/dist/react/providers/storefront-client-provider.js +6 -0
- package/dist/react/server/cookie-readers.d.ts +20 -0
- package/dist/react/server/cookie-readers.d.ts.map +1 -1
- package/dist/react/server/cookie-readers.js +22 -1
- package/dist/react/server/index.d.ts +2 -1
- package/dist/react/server/index.d.ts.map +1 -1
- package/dist/react/server/index.js +4 -1
- package/dist/react/stores/cart.context.d.ts +5 -0
- package/dist/react/stores/cart.context.d.ts.map +1 -1
- package/dist/react/stores/cart.context.js +5 -0
- package/dist/react/stores/cart.store.d.ts +6 -0
- package/dist/react/stores/cart.store.d.ts.map +1 -1
- package/dist/react/stores/cart.store.js +6 -0
- package/package.json +1 -1
|
@@ -42,6 +42,7 @@ export const CartStatus = {
|
|
|
42
42
|
Recovered: 'RECOVERED'
|
|
43
43
|
};
|
|
44
44
|
export const CartWarningCode = {
|
|
45
|
+
DiscountCodeNotApplicable: 'DISCOUNT_CODE_NOT_APPLICABLE',
|
|
45
46
|
MerchandiseNotAvailable: 'MERCHANDISE_NOT_AVAILABLE',
|
|
46
47
|
MerchandiseNotEnoughStock: 'MERCHANDISE_NOT_ENOUGH_STOCK',
|
|
47
48
|
PaymentsAmountRegionMismatch: 'PAYMENTS_AMOUNT_REGION_MISMATCH',
|
|
@@ -300,6 +301,7 @@ export const DiscountErrorCode = {
|
|
|
300
301
|
Inactive: 'INACTIVE',
|
|
301
302
|
MinimumOrderNotMet: 'MINIMUM_ORDER_NOT_MET',
|
|
302
303
|
MinimumQuantityNotMet: 'MINIMUM_QUANTITY_NOT_MET',
|
|
304
|
+
NotApplicableToCart: 'NOT_APPLICABLE_TO_CART',
|
|
303
305
|
NotFound: 'NOT_FOUND',
|
|
304
306
|
NotStarted: 'NOT_STARTED',
|
|
305
307
|
ShopNotFound: 'SHOP_NOT_FOUND',
|
|
@@ -477,6 +479,12 @@ export const PaymentProvider = {
|
|
|
477
479
|
export const PaymentWarningCode = {
|
|
478
480
|
InstrumentClearedForRetry: 'INSTRUMENT_CLEARED_FOR_RETRY'
|
|
479
481
|
};
|
|
482
|
+
export const PickupSelectionMode = {
|
|
483
|
+
/** No browser widget — query points server-side (by city / postal code) and render your own list. `widgetToken` / `scriptUrl` are null for this mode. */
|
|
484
|
+
Search: 'SEARCH',
|
|
485
|
+
/** Render the carrier map widget (e.g. InPost Geowidget) initialised with `pickupConfig.widgetToken` + `pickupConfig.scriptUrl`. The buyer picks a point on the map. */
|
|
486
|
+
Widget: 'WIDGET'
|
|
487
|
+
};
|
|
480
488
|
export const ProductOptionInputType = {
|
|
481
489
|
ColorSwatch: 'COLOR_SWATCH',
|
|
482
490
|
Select: 'SELECT',
|
package/dist/core/index.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export type { StorefrontClient, StorefrontClientConfig, Middleware, ExecuteFn, G
|
|
|
38
38
|
export { createRemoteDebugTransport } from './client/remote-debug-transport';
|
|
39
39
|
export type { RemoteDebugTransport, RemoteDebugTransportConfig } from './client/remote-debug-transport';
|
|
40
40
|
export { authMiddleware } from './middleware/auth';
|
|
41
|
+
export { cartSecretMiddleware, serverCartSecretMiddleware, CART_SECRET_HEADER, } from './middleware/cart-secret';
|
|
41
42
|
export { currencyMiddleware } from './middleware/currency';
|
|
42
43
|
export { languageMiddleware } from './middleware/language';
|
|
43
44
|
export { botProtectionMiddleware, BOT_PROTECTION_HEADER, type BotProtectionTokenProvider, type BotProtectionConfig, type BotProtectionProviderConfig, type BotProtectionMiddlewareOptions, type FailStrategy, } from './middleware/bot-protection';
|
|
@@ -50,7 +51,7 @@ export { FallbackBotProtectionManager } from './bot-protection/fallback-manager'
|
|
|
50
51
|
export { StorefrontError, ErrorCodes, type StorefrontErrorOptions } from './errors';
|
|
51
52
|
export { cacheNone, cacheShort, cacheLong, cachePrivate, cacheCustom, generateCacheControlHeader, type CacheOverrides, } from './cache';
|
|
52
53
|
export { CartClient } from './cart/cart-client';
|
|
53
|
-
export type { CartMutationOutcome, CartCompleteOutcome } from './cart/cart-client';
|
|
54
|
+
export type { CartMutationOutcome, CartSecretRevealOutcome, CartCompleteOutcome, } from './cart/cart-client';
|
|
54
55
|
export { CART_RECOVERABLE_ERROR_CODES, isCartRecoverableError, executeWithCartRecovery, createCartRecoveryRunner, CartRecoveryNotPossibleError, recreateWithInput, recreateWithLines, } from './cart/cart-recovery';
|
|
55
56
|
export type { CartRecoverableErrorCode, CartCookieStore, CartRecoveryOperation, CartRecoveryFailureReason, CartExpiredEvent, CartRecoveryRunner, CreateCartRecoveryRunnerOptions, ExecuteWithCartRecoveryOptions, } from './cart/cart-recovery';
|
|
56
57
|
export type { Cart, CartLine, CartLineConnection, ProductVariant, ProductVariantWeight, ImageThumbnail, PageInfo, AttributeSelection, CartLineCost, CartCost, CartBuyerIdentity, CartDiscountCode, CartDiscountAllocation, SelectedOption, Money, CartWarning, CartShippingMethod, CartAppliedGiftCard, CartSelectedPaymentMethod, Order, PaymentSession, PaymentMethod, AvailablePaymentMethods, AvailableShippingMethod, AvailableShippingMethodsPayload, DeliveryEstimate, ShippingCarrier, FreeShippingProgress, PickupPoint, CartLineInput, CartLineUpdateInput, CartCreateInput, CartBuyerIdentityInput, CartAttributeInput, CartAttributeSelectionInput, CartAddressInput, CartSetShippingAddressInput, CartSetBillingAddressInput, CartSelectShippingMethodInput, CartSelectPaymentMethodInput, CartApplyGiftCardInput, CartRemoveGiftCardInput, CartUpdateGiftCardRecipientInput, CartCompleteInput, PaymentCreateInput, ShippingAddressInput, PickupPointInput, PaymentErrorCode, DiscountValidationResult, DiscountInfo, DiscountValidationError, } from './cart/types';
|
|
@@ -65,7 +66,7 @@ export { formatPrice, formatPriceRange, formatAmount, formatDate, formatDateTime
|
|
|
65
66
|
export { AUTH_COOKIE_NAME, AUTH_COOKIE_DEFAULTS, type AuthCookieConfig, REFRESH_COOKIE_NAME, REFRESH_COOKIE_DEFAULTS, type RefreshCookieConfig, SESSION_EXPIRY_COOKIE_NAME, SESSION_EXPIRY_COOKIE_DEFAULTS, type SessionExpiryCookieConfig, } from './auth/cookie-config';
|
|
66
67
|
export { LANGUAGE_COOKIE_NAME, LANGUAGE_COOKIE_MAX_AGE, LANGUAGE_HEADER_NAME } from './language/cookie-config';
|
|
67
68
|
export { CURRENCY_COOKIE_NAME, CURRENCY_COOKIE_MAX_AGE, CURRENCY_HEADER_NAME } from './currency/cookie-config';
|
|
68
|
-
export { CART_COOKIE_NAME, CART_COOKIE_MAX_AGE } from './cart/cookie-config';
|
|
69
|
+
export { CART_COOKIE_NAME, CART_COOKIE_MAX_AGE, parseCartCookieValue, formatCartCookieValue, type CartCredentials, } from './cart/cookie-config';
|
|
69
70
|
export { matchesRoute, type RouteProtectionConfig } from './auth/routes';
|
|
70
71
|
export { createSetTokenHandler, createClearTokenHandler, createWhoamiHandler, originAllowlistValidator, trustedForwardedHostValidator, } from './auth/handlers';
|
|
71
72
|
export type { OriginValidator, OriginValidatorContext } from './auth/handlers';
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,YAAY,EACV,gBAAgB,EAChB,sBAAsB,EACtB,UAAU,EACV,SAAS,EACT,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,kBAAkB,EAClB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAIxB,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,YAAY,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAGxG,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAChC,KAAK,8BAA8B,EACnC,KAAK,YAAY,GAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAG9F,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AAGjF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGpF,OAAO,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,YAAY,EACZ,WAAW,EACX,0BAA0B,EAC1B,KAAK,cAAc,GACpB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"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"}
|
package/dist/core/index.js
CHANGED
|
@@ -40,6 +40,7 @@ export { createStorefrontClient } from './client/create-client';
|
|
|
40
40
|
export { createRemoteDebugTransport } from './client/remote-debug-transport';
|
|
41
41
|
// Middleware
|
|
42
42
|
export { authMiddleware } from './middleware/auth';
|
|
43
|
+
export { cartSecretMiddleware, serverCartSecretMiddleware, CART_SECRET_HEADER, } from './middleware/cart-secret';
|
|
43
44
|
export { currencyMiddleware } from './middleware/currency';
|
|
44
45
|
export { languageMiddleware } from './middleware/language';
|
|
45
46
|
export { botProtectionMiddleware, BOT_PROTECTION_HEADER, } from './middleware/bot-protection';
|
|
@@ -81,8 +82,8 @@ export { AUTH_COOKIE_NAME, AUTH_COOKIE_DEFAULTS, REFRESH_COOKIE_NAME, REFRESH_CO
|
|
|
81
82
|
export { LANGUAGE_COOKIE_NAME, LANGUAGE_COOKIE_MAX_AGE, LANGUAGE_HEADER_NAME } from './language/cookie-config';
|
|
82
83
|
// Currency config
|
|
83
84
|
export { CURRENCY_COOKIE_NAME, CURRENCY_COOKIE_MAX_AGE, CURRENCY_HEADER_NAME } from './currency/cookie-config';
|
|
84
|
-
// Cart cookie config
|
|
85
|
-
export { CART_COOKIE_NAME, CART_COOKIE_MAX_AGE } from './cart/cookie-config';
|
|
85
|
+
// Cart cookie config + composite value parser/formatter (`<cartId>.<secret>`)
|
|
86
|
+
export { CART_COOKIE_NAME, CART_COOKIE_MAX_AGE, parseCartCookieValue, formatCartCookieValue, } from './cart/cookie-config';
|
|
86
87
|
// Auth route matching
|
|
87
88
|
export { matchesRoute } from './auth/routes';
|
|
88
89
|
// Auth cookie handlers (API route factories)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cart-secret middleware — attaches the `x-cart-secret` header carrying the
|
|
3
|
+
* cart access secret. Possession of the secret is what authorizes cart
|
|
4
|
+
* operations; the cart id alone is not enough.
|
|
5
|
+
*
|
|
6
|
+
* Two variants share one header contract:
|
|
7
|
+
*
|
|
8
|
+
* - **Client** (`cartSecretMiddleware`) resolves the secret lazily on every
|
|
9
|
+
* request from a getter, so a rotated secret (recovery redeem writing a new
|
|
10
|
+
* composite cookie) is picked up without rebuilding the client — same lazy
|
|
11
|
+
* pattern as `authMiddleware`.
|
|
12
|
+
*
|
|
13
|
+
* - **Server** (`serverCartSecretMiddleware`) takes the credentials already
|
|
14
|
+
* read from the request cookies (`readCartCredentials`). SSR / edge runtimes
|
|
15
|
+
* resolve the cookie once per request rather than polling a store, so the
|
|
16
|
+
* secret is captured at construction time.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { cartSecretMiddleware, parseCartCookieValue, getCookie, CART_COOKIE_NAME } from '@doswiftly/storefront-sdk';
|
|
21
|
+
*
|
|
22
|
+
* client.use(cartSecretMiddleware(() => parseCartCookieValue(getCookie(CART_COOKIE_NAME))?.cartSecret ?? null));
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
import type { Middleware } from '../client/types';
|
|
26
|
+
import type { CartCredentials } from '../cart/cookie-config';
|
|
27
|
+
/** Request header carrying the cart access secret. */
|
|
28
|
+
export declare const CART_SECRET_HEADER = "x-cart-secret";
|
|
29
|
+
/**
|
|
30
|
+
* Client cart-secret middleware. `getSecret` is read on every request so a
|
|
31
|
+
* rotated secret is picked up without rebuilding the pipeline. No header is
|
|
32
|
+
* sent when the secret is absent (legacy plain-id cookie) — the backend then
|
|
33
|
+
* treats the cart as unreachable and the SDK recreates one.
|
|
34
|
+
*/
|
|
35
|
+
export declare function cartSecretMiddleware(getSecret: () => string | null | undefined): Middleware;
|
|
36
|
+
/**
|
|
37
|
+
* Server cart-secret middleware. Takes the credentials already read from the
|
|
38
|
+
* request cookies (`readCartCredentials`) — prepend it to a server client so
|
|
39
|
+
* SSR / edge cart reads carry the secret. No header is sent when credentials
|
|
40
|
+
* are null or carry no secret.
|
|
41
|
+
*/
|
|
42
|
+
export declare function serverCartSecretMiddleware(credentials: CartCredentials | null): Middleware;
|
|
43
|
+
//# sourceMappingURL=cart-secret.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cart-secret.d.ts","sourceRoot":"","sources":["../../../src/core/middleware/cart-secret.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,sDAAsD;AACtD,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAElD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GACzC,UAAU,CAQZ;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,eAAe,GAAG,IAAI,GAClC,UAAU,CAOZ"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cart-secret middleware — attaches the `x-cart-secret` header carrying the
|
|
3
|
+
* cart access secret. Possession of the secret is what authorizes cart
|
|
4
|
+
* operations; the cart id alone is not enough.
|
|
5
|
+
*
|
|
6
|
+
* Two variants share one header contract:
|
|
7
|
+
*
|
|
8
|
+
* - **Client** (`cartSecretMiddleware`) resolves the secret lazily on every
|
|
9
|
+
* request from a getter, so a rotated secret (recovery redeem writing a new
|
|
10
|
+
* composite cookie) is picked up without rebuilding the client — same lazy
|
|
11
|
+
* pattern as `authMiddleware`.
|
|
12
|
+
*
|
|
13
|
+
* - **Server** (`serverCartSecretMiddleware`) takes the credentials already
|
|
14
|
+
* read from the request cookies (`readCartCredentials`). SSR / edge runtimes
|
|
15
|
+
* resolve the cookie once per request rather than polling a store, so the
|
|
16
|
+
* secret is captured at construction time.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { cartSecretMiddleware, parseCartCookieValue, getCookie, CART_COOKIE_NAME } from '@doswiftly/storefront-sdk';
|
|
21
|
+
*
|
|
22
|
+
* client.use(cartSecretMiddleware(() => parseCartCookieValue(getCookie(CART_COOKIE_NAME))?.cartSecret ?? null));
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
/** Request header carrying the cart access secret. */
|
|
26
|
+
export const CART_SECRET_HEADER = 'x-cart-secret';
|
|
27
|
+
/**
|
|
28
|
+
* Client cart-secret middleware. `getSecret` is read on every request so a
|
|
29
|
+
* rotated secret is picked up without rebuilding the pipeline. No header is
|
|
30
|
+
* sent when the secret is absent (legacy plain-id cookie) — the backend then
|
|
31
|
+
* treats the cart as unreachable and the SDK recreates one.
|
|
32
|
+
*/
|
|
33
|
+
export function cartSecretMiddleware(getSecret) {
|
|
34
|
+
return (request, next) => {
|
|
35
|
+
const secret = getSecret();
|
|
36
|
+
if (secret) {
|
|
37
|
+
request.headers[CART_SECRET_HEADER] = secret;
|
|
38
|
+
}
|
|
39
|
+
return next(request);
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Server cart-secret middleware. Takes the credentials already read from the
|
|
44
|
+
* request cookies (`readCartCredentials`) — prepend it to a server client so
|
|
45
|
+
* SSR / edge cart reads carry the secret. No header is sent when credentials
|
|
46
|
+
* are null or carry no secret.
|
|
47
|
+
*/
|
|
48
|
+
export function serverCartSecretMiddleware(credentials) {
|
|
49
|
+
return (request, next) => {
|
|
50
|
+
if (credentials?.cartSecret) {
|
|
51
|
+
request.headers[CART_SECRET_HEADER] = credentials.cartSecret;
|
|
52
|
+
}
|
|
53
|
+
return next(request);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
* (`useSessionRefresh`) is the protection and this middleware stays inert. It
|
|
27
27
|
* activates wherever a request really does return 401 — e.g. the same-origin
|
|
28
28
|
* BFF refresh route — keeping reactive recovery forward-compatible with no
|
|
29
|
-
* backend change.
|
|
30
|
-
* (
|
|
29
|
+
* backend change. This is purely the customer auth session; cart access is a
|
|
30
|
+
* separate capability (the cart secret) and has no session-loss path.
|
|
31
31
|
*/
|
|
32
32
|
import type { Middleware } from '../client/types';
|
|
33
33
|
import type { SessionExpiredEvent } from '../auth/session-events';
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
* (`useSessionRefresh`) is the protection and this middleware stays inert. It
|
|
27
27
|
* activates wherever a request really does return 401 — e.g. the same-origin
|
|
28
28
|
* BFF refresh route — keeping reactive recovery forward-compatible with no
|
|
29
|
-
* backend change.
|
|
30
|
-
* (
|
|
29
|
+
* backend change. This is purely the customer auth session; cart access is a
|
|
30
|
+
* separate capability (the cart secret) and has no session-loss path.
|
|
31
31
|
*/
|
|
32
32
|
import { StorefrontError } from '../errors';
|
|
33
33
|
/**
|
|
@@ -49,6 +49,29 @@ export declare const CART_UPDATE_NOTE: string;
|
|
|
49
49
|
*/
|
|
50
50
|
export declare const CART_UPDATE_ATTRIBUTES: string;
|
|
51
51
|
export declare const CART_UPDATE_BUYER_IDENTITY: string;
|
|
52
|
+
/**
|
|
53
|
+
* cartMerge — on login, fold the customer's prior cart into the guest cart.
|
|
54
|
+
* The guest cart survives (its id + secret are kept, so the stored cookie stays
|
|
55
|
+
* valid); quantities sum per variant and guest checkout fields win. Requires
|
|
56
|
+
* authentication. Branch on `userErrors[].code`: `CART_MERGE_REQUIRES_AUTH`,
|
|
57
|
+
* `CART_CURRENCY_MISMATCH`, `CART_NOT_FOUND`.
|
|
58
|
+
*/
|
|
59
|
+
export declare const CART_MERGE: string;
|
|
60
|
+
/**
|
|
61
|
+
* cartDowngradeOnLogout — on logout, strip the customer association, contact
|
|
62
|
+
* details, addresses and saved-payment selection from the cart while keeping
|
|
63
|
+
* line items, coupons, shipping method, currency and notes. The access secret
|
|
64
|
+
* is NOT rotated, so the stored cookie stays valid. Capability-gated by the
|
|
65
|
+
* `x-cart-secret` header.
|
|
66
|
+
*/
|
|
67
|
+
export declare const CART_DOWNGRADE_ON_LOGOUT: string;
|
|
68
|
+
/**
|
|
69
|
+
* cartRecoveryRedeem — redeem a signed recovery link. On success the cart
|
|
70
|
+
* secret is rotated and the new `secret` is revealed once (the old one stops
|
|
71
|
+
* working); persist it into the composite cookie. Invalid / expired links
|
|
72
|
+
* return `userErrors` without leaking cart content.
|
|
73
|
+
*/
|
|
74
|
+
export declare const CART_RECOVERY_REDEEM: string;
|
|
52
75
|
export declare const CART_SET_SHIPPING_ADDRESS: string;
|
|
53
76
|
export declare const CART_SET_BILLING_ADDRESS: string;
|
|
54
77
|
export declare const CART_SELECT_SHIPPING_METHOD: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cart.d.ts","sourceRoot":"","sources":["../../../src/core/operations/cart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"cart.d.ts","sourceRoot":"","sources":["../../../src/core/operations/cart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAqbH,eAAO,MAAM,UAAU,QAOrB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,qCAAqC,QAehD,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,QAO1C,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,QAO/B,CAAC;AAMH,eAAO,MAAM,WAAW,QAYtB,CAAC;AAEH,eAAO,MAAM,cAAc,QAWzB,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAW5B,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAW5B,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAEH,eAAO,MAAM,gBAAgB,QAW3B,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,QAWjC,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAMH;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAWrB,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,QAWnC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,QAY/B,CAAC;AAMH,eAAO,MAAM,yBAAyB,QAWpC,CAAC;AAEH,eAAO,MAAM,wBAAwB,QAWnC,CAAC;AAEH,eAAO,MAAM,2BAA2B,QAWtC,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAEH,eAAO,MAAM,oBAAoB,QAW/B,CAAC;AAEH,eAAO,MAAM,qBAAqB,QAWhC,CAAC;AAEH,eAAO,MAAM,+BAA+B,QAW1C,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,QAWxB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QAWzB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAWvC,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,QAoBtC,CAAC"}
|
|
@@ -274,6 +274,10 @@ const ORDER_FRAGMENT = `
|
|
|
274
274
|
expiredAt
|
|
275
275
|
shippingAddress { ...MailingAddress }
|
|
276
276
|
itemCount
|
|
277
|
+
discountAllocations {
|
|
278
|
+
discountCode
|
|
279
|
+
amount { ...Money }
|
|
280
|
+
}
|
|
277
281
|
canCreatePayment
|
|
278
282
|
paymentMethodType
|
|
279
283
|
}
|
|
@@ -327,6 +331,12 @@ const AVAILABLE_SHIPPING_METHOD_FRAGMENT = `
|
|
|
327
331
|
name
|
|
328
332
|
description
|
|
329
333
|
deliveryType
|
|
334
|
+
pickupConfig {
|
|
335
|
+
provider
|
|
336
|
+
selectionMode
|
|
337
|
+
widgetToken
|
|
338
|
+
scriptUrl
|
|
339
|
+
}
|
|
330
340
|
carrier { ...ShippingCarrier }
|
|
331
341
|
price { ...Money }
|
|
332
342
|
isFree
|
|
@@ -469,6 +479,7 @@ export const CART_CREATE = composeOperation(`
|
|
|
469
479
|
mutation CartCreate($input: CartCreateInput) {
|
|
470
480
|
cartCreate(input: $input) {
|
|
471
481
|
cart { ...Cart }
|
|
482
|
+
secret
|
|
472
483
|
userErrors { ...UserError }
|
|
473
484
|
warnings { ...CartWarning }
|
|
474
485
|
}
|
|
@@ -568,6 +579,66 @@ export const CART_UPDATE_BUYER_IDENTITY = composeOperation(`
|
|
|
568
579
|
${CART_WARNING_FRAGMENT}
|
|
569
580
|
`);
|
|
570
581
|
// ---------------------------------------------------------------------------
|
|
582
|
+
// Guest ↔ customer transitions (capability model)
|
|
583
|
+
// ---------------------------------------------------------------------------
|
|
584
|
+
/**
|
|
585
|
+
* cartMerge — on login, fold the customer's prior cart into the guest cart.
|
|
586
|
+
* The guest cart survives (its id + secret are kept, so the stored cookie stays
|
|
587
|
+
* valid); quantities sum per variant and guest checkout fields win. Requires
|
|
588
|
+
* authentication. Branch on `userErrors[].code`: `CART_MERGE_REQUIRES_AUTH`,
|
|
589
|
+
* `CART_CURRENCY_MISMATCH`, `CART_NOT_FOUND`.
|
|
590
|
+
*/
|
|
591
|
+
export const CART_MERGE = composeOperation(`
|
|
592
|
+
mutation CartMerge($guestCartId: ID!) {
|
|
593
|
+
cartMerge(guestCartId: $guestCartId) {
|
|
594
|
+
cart { ...Cart }
|
|
595
|
+
userErrors { ...UserError }
|
|
596
|
+
warnings { ...CartWarning }
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
${CART_FRAGMENT}
|
|
600
|
+
${USER_ERROR_FRAGMENT}
|
|
601
|
+
${CART_WARNING_FRAGMENT}
|
|
602
|
+
`);
|
|
603
|
+
/**
|
|
604
|
+
* cartDowngradeOnLogout — on logout, strip the customer association, contact
|
|
605
|
+
* details, addresses and saved-payment selection from the cart while keeping
|
|
606
|
+
* line items, coupons, shipping method, currency and notes. The access secret
|
|
607
|
+
* is NOT rotated, so the stored cookie stays valid. Capability-gated by the
|
|
608
|
+
* `x-cart-secret` header.
|
|
609
|
+
*/
|
|
610
|
+
export const CART_DOWNGRADE_ON_LOGOUT = composeOperation(`
|
|
611
|
+
mutation CartDowngradeOnLogout($cartId: ID!) {
|
|
612
|
+
cartDowngradeOnLogout(cartId: $cartId) {
|
|
613
|
+
cart { ...Cart }
|
|
614
|
+
userErrors { ...UserError }
|
|
615
|
+
warnings { ...CartWarning }
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
${CART_FRAGMENT}
|
|
619
|
+
${USER_ERROR_FRAGMENT}
|
|
620
|
+
${CART_WARNING_FRAGMENT}
|
|
621
|
+
`);
|
|
622
|
+
/**
|
|
623
|
+
* cartRecoveryRedeem — redeem a signed recovery link. On success the cart
|
|
624
|
+
* secret is rotated and the new `secret` is revealed once (the old one stops
|
|
625
|
+
* working); persist it into the composite cookie. Invalid / expired links
|
|
626
|
+
* return `userErrors` without leaking cart content.
|
|
627
|
+
*/
|
|
628
|
+
export const CART_RECOVERY_REDEEM = composeOperation(`
|
|
629
|
+
mutation CartRecoveryRedeem($token: String!) {
|
|
630
|
+
cartRecoveryRedeem(token: $token) {
|
|
631
|
+
cart { ...Cart }
|
|
632
|
+
secret
|
|
633
|
+
userErrors { ...UserError }
|
|
634
|
+
warnings { ...CartWarning }
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
${CART_FRAGMENT}
|
|
638
|
+
${USER_ERROR_FRAGMENT}
|
|
639
|
+
${CART_WARNING_FRAGMENT}
|
|
640
|
+
`);
|
|
641
|
+
// ---------------------------------------------------------------------------
|
|
571
642
|
// Phase 3 — Cart completion lifecycle mutations
|
|
572
643
|
// ---------------------------------------------------------------------------
|
|
573
644
|
export const CART_SET_SHIPPING_ADDRESS = composeOperation(`
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/react/cookies.d.ts
CHANGED
|
@@ -8,6 +8,12 @@
|
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
10
|
* Get cookie value by name (client-side only).
|
|
11
|
+
*
|
|
12
|
+
* A malformed percent-encoding (e.g. `%` or `%zz`) makes `decodeURIComponent`
|
|
13
|
+
* throw a `URIError`. Since this runs on every request (the cart secret getter
|
|
14
|
+
* reads the cart cookie here), a corrupt cookie value is treated as absent —
|
|
15
|
+
* returns `null` rather than throwing, so the caller can fall back to recreating
|
|
16
|
+
* the cookie instead of breaking the whole request pipeline.
|
|
11
17
|
*/
|
|
12
18
|
export declare function getCookie(name: string): string | null;
|
|
13
19
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/react/cookies.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH
|
|
1
|
+
{"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/react/cookies.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUrD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACpF,IAAI,CAON;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAM,GAAG,IAAI,CAG3D;AAQD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD,MAAM,WAAW,6BAA6B;IAC5C;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,CAAC,EAAE,6BAA6B,GACtC,eAAe,CAmBjB"}
|
package/dist/react/cookies.js
CHANGED
|
@@ -8,12 +8,26 @@
|
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
10
|
* Get cookie value by name (client-side only).
|
|
11
|
+
*
|
|
12
|
+
* A malformed percent-encoding (e.g. `%` or `%zz`) makes `decodeURIComponent`
|
|
13
|
+
* throw a `URIError`. Since this runs on every request (the cart secret getter
|
|
14
|
+
* reads the cart cookie here), a corrupt cookie value is treated as absent —
|
|
15
|
+
* returns `null` rather than throwing, so the caller can fall back to recreating
|
|
16
|
+
* the cookie instead of breaking the whole request pipeline.
|
|
11
17
|
*/
|
|
12
18
|
export function getCookie(name) {
|
|
13
19
|
if (typeof document === 'undefined')
|
|
14
20
|
return null;
|
|
15
21
|
const match = document.cookie.match(new RegExp(`(?:^|;\\s*)${name}=([^;]*)`));
|
|
16
|
-
|
|
22
|
+
if (!match)
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
return decodeURIComponent(match[1]);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Malformed encoding — behave as if the cookie were not present.
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
17
31
|
}
|
|
18
32
|
/**
|
|
19
33
|
* Set cookie (client-side only).
|
|
@@ -37,7 +51,7 @@ export function deleteCookie(name, path = '/') {
|
|
|
37
51
|
return;
|
|
38
52
|
document.cookie = `${name}=;max-age=0;path=${path}`;
|
|
39
53
|
}
|
|
40
|
-
import { CART_COOKIE_NAME, CART_COOKIE_MAX_AGE } from '../core/cart/cookie-config';
|
|
54
|
+
import { CART_COOKIE_NAME, CART_COOKIE_MAX_AGE, parseCartCookieValue, formatCartCookieValue, } from '../core/cart/cookie-config';
|
|
41
55
|
import { cookieDebugEvent } from '../core/client/remote-debug-transport';
|
|
42
56
|
/**
|
|
43
57
|
* Build a browser-side `CartCookieStore` backed by `document.cookie`.
|
|
@@ -61,10 +75,15 @@ import { cookieDebugEvent } from '../core/client/remote-debug-transport';
|
|
|
61
75
|
export function createBrowserCartCookieStore(options) {
|
|
62
76
|
const emit = options?.onDebug;
|
|
63
77
|
return {
|
|
64
|
-
|
|
78
|
+
// The cookie value is composite (`<cartId>.<secret>`); expose only the cart
|
|
79
|
+
// id (the secret travels in the `x-cart-secret` header via middleware).
|
|
80
|
+
get: () => parseCartCookieValue(getCookie(CART_COOKIE_NAME))?.cartId ?? null,
|
|
65
81
|
set: (cartId, setOptions) => {
|
|
66
82
|
const maxAge = setOptions?.maxAge ?? CART_COOKIE_MAX_AGE;
|
|
67
|
-
|
|
83
|
+
const secret = setOptions?.secret;
|
|
84
|
+
const value = secret ? formatCartCookieValue({ cartId, cartSecret: secret }) : cartId;
|
|
85
|
+
setCookie(CART_COOKIE_NAME, value, { maxAge });
|
|
86
|
+
// Debug logs the cart id only — never the secret.
|
|
68
87
|
emit?.(cookieDebugEvent(CART_COOKIE_NAME, 'set', cartId, maxAge));
|
|
69
88
|
},
|
|
70
89
|
clear: () => {
|
|
@@ -43,11 +43,14 @@
|
|
|
43
43
|
*
|
|
44
44
|
* Pass `{ initialCartId }` to seed the hook with a cart-id resolved server-side
|
|
45
45
|
* (read from URL params in a Route Handler, env var for dev fixtures, parent
|
|
46
|
-
* `postMessage` for embedded iframe, admin "view this cart" lookup). The
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
46
|
+
* `postMessage` for embedded iframe, admin "view this cart" lookup). The seed
|
|
47
|
+
* may be a bare cart id or the composite `"<cartId>.<secret>"` cookie value —
|
|
48
|
+
* pass the composite when the cart secret is known server-side so reads and
|
|
49
|
+
* writes reach the seeded cart (a bare id degrades to a fresh cart on the first
|
|
50
|
+
* write). The hook applies priority `cookie wins → seed → auto-create`. The
|
|
51
|
+
* seed is eagerly written to the cart-id cookie so cross-tab tabs and standard
|
|
52
|
+
* recovery semantics operate on a canonical value. A stale seed goes through
|
|
53
|
+
* the same recovery flow as a stale cookie — `addItem` auto-replays through
|
|
51
54
|
* `cartCreate({ lines })`, state-dependent ops bail with `cart-expired`.
|
|
52
55
|
*
|
|
53
56
|
* Mirrors the `<StorefrontProvider initialAccessToken>` pattern for the
|
|
@@ -127,12 +130,11 @@ export type CartManagerStatus = {
|
|
|
127
130
|
* instead of wrapping each call site.
|
|
128
131
|
*
|
|
129
132
|
* `onMutationError` fires only for failures you can surface to the buyer: its
|
|
130
|
-
* `error` carries a backend-translated message. Cart expiry
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
* error callback either.
|
|
133
|
+
* `error` carries a backend-translated message. Cart expiry is delivered
|
|
134
|
+
* through its own dedicated channel (`onExpired`) — it carries an SDK-internal
|
|
135
|
+
* message and does NOT trigger `onMutationError`. A transient missing-cart
|
|
136
|
+
* error that the manager recovers from (by recreating the cart) resolves as
|
|
137
|
+
* success, so it never reaches the error callback either.
|
|
136
138
|
*
|
|
137
139
|
* Callbacks are invoked defensively: a throwing callback never rejects the
|
|
138
140
|
* underlying mutation.
|
|
@@ -144,8 +146,7 @@ export interface CartManagerLifecycleCallbacks {
|
|
|
144
146
|
onMutationSuccess?: (operation: CartManagerOperation) => void;
|
|
145
147
|
/**
|
|
146
148
|
* Fired when an operation fails with a buyer-surfaceable error. Cart expiry
|
|
147
|
-
*
|
|
148
|
-
* instead, not here.
|
|
149
|
+
* is routed to `onExpired` instead, not here.
|
|
149
150
|
*/
|
|
150
151
|
onMutationError?: (operation: CartManagerOperation, error: Error) => void;
|
|
151
152
|
}
|
|
@@ -160,6 +161,12 @@ export interface UseCartManagerOptions extends CartManagerLifecycleCallbacks {
|
|
|
160
161
|
* first interaction. Eagerly promoted to the cookie store so cross-tab
|
|
161
162
|
* tabs and standard recovery semantics operate on a canonical value.
|
|
162
163
|
*
|
|
164
|
+
* Accepts either a bare cart id (`"<cartId>"`) or the composite cookie
|
|
165
|
+
* value (`"<cartId>.<secret>"`). Pass the composite when the cart secret is
|
|
166
|
+
* known server-side (e.g. read from the `cart-id` cookie in a Server
|
|
167
|
+
* Component) so reads and writes reach the seeded cart; a bare id degrades
|
|
168
|
+
* to a fresh cart on the first write.
|
|
169
|
+
*
|
|
163
170
|
* See the hook-level `@example Server-known cart-id` block for the full
|
|
164
171
|
* Server-Component → Client-Component data flow. Use for env seed (dev),
|
|
165
172
|
* magic-link checkout, embedded iframe (parent supplies cart-id),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-cart-manager.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-cart-manager.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"use-cart-manager.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-cart-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,11 +43,14 @@
|
|
|
43
43
|
*
|
|
44
44
|
* Pass `{ initialCartId }` to seed the hook with a cart-id resolved server-side
|
|
45
45
|
* (read from URL params in a Route Handler, env var for dev fixtures, parent
|
|
46
|
-
* `postMessage` for embedded iframe, admin "view this cart" lookup). The
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
46
|
+
* `postMessage` for embedded iframe, admin "view this cart" lookup). The seed
|
|
47
|
+
* may be a bare cart id or the composite `"<cartId>.<secret>"` cookie value —
|
|
48
|
+
* pass the composite when the cart secret is known server-side so reads and
|
|
49
|
+
* writes reach the seeded cart (a bare id degrades to a fresh cart on the first
|
|
50
|
+
* write). The hook applies priority `cookie wins → seed → auto-create`. The
|
|
51
|
+
* seed is eagerly written to the cart-id cookie so cross-tab tabs and standard
|
|
52
|
+
* recovery semantics operate on a canonical value. A stale seed goes through
|
|
53
|
+
* the same recovery flow as a stale cookie — `addItem` auto-replays through
|
|
51
54
|
* `cartCreate({ lines })`, state-dependent ops bail with `cart-expired`.
|
|
52
55
|
*
|
|
53
56
|
* Mirrors the `<StorefrontProvider initialAccessToken>` pattern for the
|
|
@@ -88,7 +91,7 @@
|
|
|
88
91
|
'use client';
|
|
89
92
|
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
90
93
|
import { useStorefrontClientContext } from '../providers/storefront-client-provider';
|
|
91
|
-
import { createCartRecoveryRunner, recreateWithInput, CartRecoveryNotPossibleError,
|
|
94
|
+
import { createCartRecoveryRunner, recreateWithInput, CartRecoveryNotPossibleError, } from '../../core/cart/cart-recovery';
|
|
92
95
|
import { createBrowserCartCookieStore } from '../cookies';
|
|
93
96
|
/**
|
|
94
97
|
* Invoke an optional lifecycle callback without letting a thrown callback
|
|
@@ -105,14 +108,13 @@ function safeInvoke(run) {
|
|
|
105
108
|
}
|
|
106
109
|
}
|
|
107
110
|
/**
|
|
108
|
-
* Cart expiry (`CartRecoveryNotPossibleError`)
|
|
109
|
-
* (`
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* meant to be surfaceable to the buyer.
|
|
111
|
+
* Cart expiry (`CartRecoveryNotPossibleError`) is surfaced through its own
|
|
112
|
+
* dedicated channel (`onExpired`) and carries an SDK-internal English message.
|
|
113
|
+
* It is NOT routed to `onMutationError`, whose error is meant to be surfaceable
|
|
114
|
+
* to the buyer.
|
|
113
115
|
*/
|
|
114
116
|
function isDedicatedChannelError(err) {
|
|
115
|
-
return err instanceof CartRecoveryNotPossibleError
|
|
117
|
+
return err instanceof CartRecoveryNotPossibleError;
|
|
116
118
|
}
|
|
117
119
|
export function useCartManager(options) {
|
|
118
120
|
const { cartClient } = useStorefrontClientContext();
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useLogout — focused hook for the logout flow.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Downgrades the active cart to guest (clearing the customer's contact details,
|
|
5
|
+
* addresses and saved-payment selection so they do not linger on a shared
|
|
6
|
+
* device), then calls the auth client logout (which clears the backend's
|
|
7
|
+
* httpOnly cookie), invokes the consumer's `onClearToken` callback (BFF), and
|
|
8
|
+
* resets the local auth store. Even when the backend request fails, the local
|
|
9
|
+
* state is cleared (defensive — better to log a user out than leave them in a
|
|
10
|
+
* half state).
|
|
9
11
|
*
|
|
10
12
|
* @example
|
|
11
13
|
* ```tsx
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-logout.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-logout.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"use-logout.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-logout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAiCH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,eAAe;IAC9B,sFAAsF;IACtF,MAAM,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IACpC,oDAAoD;IACpD,YAAY,EAAE,OAAO,CAAC;IACtB,gFAAgF;IAChF,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,eAAe,CAmCzE"}
|