@doswiftly/storefront-sdk 19.2.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 +45 -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 +237 -4
- package/dist/core/generated/operation-types.d.ts.map +1 -1
- 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 +65 -0
- 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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 20.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 486afc8: Cart access is now capability-based: a cart is reached with its id **and** a one-time secret instead of being tied to the signed-in customer. This fixes two long-standing cart bugs — a guest inheriting a previous visitor's cart id getting "cart not found", and a signed-in buyer being told to sign in again on their own cart — and aligns the cart contract with the industry norm.
|
|
8
|
+
|
|
9
|
+
**Why**: the `cart-id` cookie outlives the auth session and is shared across tabs and workers, so gating cart writes on the customer made carts brittle. The cart token is now a bearer capability; the customer link is enrichment only. There are no more "unauthenticated"/"forbidden" cart errors — a missing or expired cart, or a missing or wrong secret, returns a single `CART_NOT_FOUND`, which the SDK already auto-recovers from by creating a fresh cart.
|
|
10
|
+
|
|
11
|
+
**The SDK handles the secret for you.** `useCartManager`, the browser cart cookie store, and the client/server middleware read and persist it automatically. The breaking points below matter only if you read the `cart-id` cookie yourself, run server-side cart reads, or built on the removed session-error path.
|
|
12
|
+
|
|
13
|
+
**Breaking**
|
|
14
|
+
1. **Composite cart cookie.** The `cart-id` cookie value is now `"<cartId>.<secret>"`. If you read it directly (for example in a Server Component), parse it with the new `parseCartCookieValue()` / `readCartCredentials()` instead of treating the raw value as the cart id. A legacy plain-id cookie still parses (with `cartSecret: null`) and degrades to a fresh cart on the next write.
|
|
15
|
+
2. **Server-side cart reads must forward the secret.** SSR / edge cart reads now need the secret header or they come back empty. Add `serverCartSecretMiddleware(await readCartCredentials())` to your server client middleware (next to your currency / language middleware).
|
|
16
|
+
3. **The cart session-error path is removed.** `CART_UNAUTHENTICATED` no longer exists in the contract, and with it the recovery runner's `onSessionExpired` listener, the `CartSessionRequiredError` class, the `isCartSessionError` predicate and the `CART_SESSION_ERROR_CODES` constant. If you handled a "cart needs sign-in" signal, remove it — a stale or unreachable cart now flows through the normal `CART_NOT_FOUND` recovery you already have. (The auth-level session refresh — `sessionRetryMiddleware`, `useSessionExpired`, `createSessionExpiredEmitter` — is unchanged; it handles the customer token, not the cart.)
|
|
17
|
+
4. **`ensureCart` shape.** A custom `ensureCart` passed to `createCartRecoveryRunner` must now return `{ cart, secret }` (the create outcome) rather than just the cart, so the runner can persist the secret.
|
|
18
|
+
|
|
19
|
+
**New**
|
|
20
|
+
- `CartClient.create()` now returns the one-time `secret` alongside the cart.
|
|
21
|
+
- `CartClient.merge(guestCartId)` — on login, fold the customer's prior cart into the guest cart (quantities sum per variant, guest checkout fields win, the guest cart id and secret are kept so the stored cookie stays valid). Requires an authenticated request.
|
|
22
|
+
- `CartClient.downgradeOnLogout(cartId)` — on logout, clear the customer link, contact details, addresses and saved-payment selection while keeping items, coupons, shipping method, currency, notes and the secret. `useLogout` now calls this automatically before signing out, so customer details do not linger in the cart on a shared device.
|
|
23
|
+
- `CartClient.recoveryRedeem(token)` — redeem a signed cart-recovery link; the cart secret is rotated and the new one is revealed once (persist it into the cookie).
|
|
24
|
+
- `cartSecretMiddleware`, `serverCartSecretMiddleware`, `readCartCredentials`, `parseCartCookieValue`, `formatCartCookieValue` and the `CartCredentials` type for working with the secret directly.
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- 17f4832: Two cart-cookie robustness fixes for capability-based carts:
|
|
29
|
+
- **A malformed `cart-id` cookie no longer breaks the GraphQL client.** A corrupt cookie value (for example a stray `%` left by another tool, or a hand-crafted bad value) made `getCookie` throw while reading the cart secret on every request, taking down the whole request pipeline for that browser until the cookie was cleared. The cookie is now treated as absent when it can't be decoded, so a fresh cart is created as intended.
|
|
30
|
+
- **A server-known cart seed can now carry the cart secret.** When you seed a cart id from the server (via `useCartManager({ initialCartId })`, `<CartManagerProvider initialCartId>`, or `createCartRecoveryRunner({ initialCartId })`), you can pass the composite `"<cartId>.<secret>"` value — the same value stored in the `cart-id` cookie — instead of a bare id. The seed is persisted as a composite cookie so reads and writes send the secret and reach the seeded cart. This unblocks magic-link checkout, embedded-iframe, customer-service "view this cart", and server-side dev-seed flows where the cart id is known up front.
|
|
31
|
+
|
|
32
|
+
Migration: no changes required for existing code. A bare-id seed keeps its previous behaviour (it degrades to a fresh cart on the first write, since the secret is required to reach an existing cart). To make a seeded cart reachable, read the raw `cart-id` cookie server-side and pass it through unchanged, or build the value with `formatCartCookieValue({ cartId, cartSecret })`.
|
|
33
|
+
|
|
34
|
+
- 933492b: Deprecate the `createCartStore` cart-state system in favour of `useCartManager`.
|
|
35
|
+
|
|
36
|
+
`createCartStore` — and its `CartProvider` / `useCartStore` / `useCartStoreApi`
|
|
37
|
+
helpers — predate capability-based carts: the store does not carry the cart secret,
|
|
38
|
+
so mutations against a capability cart fail. These exports are now marked
|
|
39
|
+
`@deprecated` and will be removed in a future major release.
|
|
40
|
+
|
|
41
|
+
Migration: switch to `useCartManager` (React), which manages the cart secret, the
|
|
42
|
+
`cart-id` cookie, and stale-cart recovery automatically and exposes the full cart +
|
|
43
|
+
checkout lifecycle. For a framework-agnostic core, use `createCartRecoveryRunner`.
|
|
44
|
+
No runtime behaviour changes in this release — the deprecation only adds IDE hints.
|
|
45
|
+
|
|
46
|
+
- 486afc8: `Order` now actually returns the `discountAllocations` breakdown it documents. The per-code discount allocations were added to the order contract previously, but the SDK's `Order` selection did not request the field, so it always came back empty. The order confirmation page can now render the same per-code discount rows the buyer saw on the cart.
|
|
47
|
+
|
|
3
48
|
## 19.2.0
|
|
4
49
|
|
|
5
50
|
### Minor Changes
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Session-expired event channel — auth-level pub/sub (0-deps core).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* (`useSessionExpired`) and react (notify + redirect to sign-in).
|
|
4
|
+
* Fires when the CUSTOMER auth session can no longer be kept alive — the
|
|
5
|
+
* proactive scheduler's refresh failed on tab wake, or a reactive refresh after
|
|
6
|
+
* a 401 also failed. Storefronts subscribe once globally (`useSessionExpired`)
|
|
7
|
+
* and react (notify + redirect to sign-in).
|
|
9
8
|
*
|
|
10
|
-
*
|
|
11
|
-
* +
|
|
12
|
-
* DOM. The provider owns the instance (`useRef` + Context, Inv-3) — never a
|
|
13
|
-
* module-level singleton.
|
|
9
|
+
* 0-deps (Inv-1): plain `Set` + closure, no React / DOM. The provider owns the
|
|
10
|
+
* instance (`useRef` + Context, Inv-3) — never a module-level singleton.
|
|
14
11
|
*/
|
|
15
12
|
export type SessionExpiredReason =
|
|
16
13
|
/** Proactive scheduler tried to refresh on tab wake but the session was already gone. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-events.d.ts","sourceRoot":"","sources":["../../../src/core/auth/session-events.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"session-events.d.ts","sourceRoot":"","sources":["../../../src/core/auth/session-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,oBAAoB;AAC9B,yFAAyF;AACvF,qBAAqB;AACvB,0FAA0F;GACxF,yBAAyB;AAC3B,8EAA8E;GAC5E,uBAAuB,CAAC;AAE5B,MAAM,WAAW,mBAAmB;IAClC,6CAA6C;IAC7C,MAAM,EAAE,oBAAoB,CAAC;IAC7B,sEAAsE;IACtE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACvC,4EAA4E;IAC5E,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACvE;AAED,wBAAgB,2BAA2B,IAAI,qBAAqB,CAoBnE"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Session-expired event channel — auth-level pub/sub (0-deps core).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* (`useSessionExpired`) and react (notify + redirect to sign-in).
|
|
4
|
+
* Fires when the CUSTOMER auth session can no longer be kept alive — the
|
|
5
|
+
* proactive scheduler's refresh failed on tab wake, or a reactive refresh after
|
|
6
|
+
* a 401 also failed. Storefronts subscribe once globally (`useSessionExpired`)
|
|
7
|
+
* and react (notify + redirect to sign-in).
|
|
9
8
|
*
|
|
10
|
-
*
|
|
11
|
-
* +
|
|
12
|
-
* DOM. The provider owns the instance (`useRef` + Context, Inv-3) — never a
|
|
13
|
-
* module-level singleton.
|
|
9
|
+
* 0-deps (Inv-1): plain `Set` + closure, no React / DOM. The provider owns the
|
|
10
|
+
* instance (`useRef` + Context, Inv-3) — never a module-level singleton.
|
|
14
11
|
*/
|
|
15
12
|
export function createSessionExpiredEmitter() {
|
|
16
13
|
const listeners = new Set();
|
|
@@ -31,6 +31,16 @@ export interface CartMutationOutcome {
|
|
|
31
31
|
cart: Cart;
|
|
32
32
|
warnings: CartWarning[];
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Outcome of an operation that reveals a one-time cart access secret — cart
|
|
36
|
+
* creation and recovery redemption. `secret` is the raw secret to persist into
|
|
37
|
+
* the composite `cart-id` cookie; it is shown only here and cannot be retrieved
|
|
38
|
+
* again. The SDK cart manager persists it for you; a direct API caller must
|
|
39
|
+
* store it immediately.
|
|
40
|
+
*/
|
|
41
|
+
export interface CartSecretRevealOutcome extends CartMutationOutcome {
|
|
42
|
+
secret: string | null;
|
|
43
|
+
}
|
|
34
44
|
/**
|
|
35
45
|
* cartComplete result — `order` is the Order created from the cart, non-null on
|
|
36
46
|
* success (`complete()` throws via `assertNoUserErrors` before returning if the
|
|
@@ -93,9 +103,11 @@ export declare class CartClient {
|
|
|
93
103
|
*/
|
|
94
104
|
getOrderByToken(token: string, email?: string): Promise<Order | null>;
|
|
95
105
|
/**
|
|
96
|
-
* Create a new cart, optionally with initial lines.
|
|
106
|
+
* Create a new cart, optionally with initial lines. The result carries the
|
|
107
|
+
* one-time `secret` (the cart access capability) — persist it into the
|
|
108
|
+
* composite `cart-id` cookie. The SDK cart manager does this for you.
|
|
97
109
|
*/
|
|
98
|
-
create(input?: CartCreateInput): Promise<
|
|
110
|
+
create(input?: CartCreateInput): Promise<CartSecretRevealOutcome>;
|
|
99
111
|
/**
|
|
100
112
|
* Add line items to an existing cart.
|
|
101
113
|
*/
|
|
@@ -129,6 +141,31 @@ export declare class CartClient {
|
|
|
129
141
|
* Update buyer identity (email, phone, country, customer link, languageCode).
|
|
130
142
|
*/
|
|
131
143
|
updateBuyerIdentity(cartId: string, buyerIdentity: CartBuyerIdentityInput): Promise<CartMutationOutcome>;
|
|
144
|
+
/**
|
|
145
|
+
* Merge the customer's prior cart into the guest cart on login. The guest
|
|
146
|
+
* cart survives (same id + secret → the stored cookie stays valid),
|
|
147
|
+
* quantities sum per variant, guest checkout fields win. Requires an
|
|
148
|
+
* authenticated request — throws (`StorefrontError`) on
|
|
149
|
+
* `CART_MERGE_REQUIRES_AUTH` (anonymous) or `CART_CURRENCY_MISMATCH`
|
|
150
|
+
* (different currencies). Inspect `err.userErrors[0].code`.
|
|
151
|
+
*/
|
|
152
|
+
merge(guestCartId: string): Promise<CartMutationOutcome>;
|
|
153
|
+
/**
|
|
154
|
+
* Downgrade a cart to guest on logout — clears the customer association,
|
|
155
|
+
* contact details, addresses and saved-payment selection while keeping line
|
|
156
|
+
* items, coupons, shipping method, currency and notes. The access secret is
|
|
157
|
+
* NOT rotated, so the stored cookie stays valid. Capability-gated by the
|
|
158
|
+
* `x-cart-secret` header (a missing / wrong secret throws `CART_NOT_FOUND`).
|
|
159
|
+
*/
|
|
160
|
+
downgradeOnLogout(cartId: string): Promise<CartMutationOutcome>;
|
|
161
|
+
/**
|
|
162
|
+
* Redeem a signed cart-recovery link. On success the cart secret is rotated
|
|
163
|
+
* and the result carries the NEW one-time `secret` — persist it into the
|
|
164
|
+
* composite `cart-id` cookie (the old secret stops working). Invalid /
|
|
165
|
+
* expired links throw a `StorefrontError` carrying `userErrors` without
|
|
166
|
+
* leaking cart content.
|
|
167
|
+
*/
|
|
168
|
+
recoveryRedeem(token: string): Promise<CartSecretRevealOutcome>;
|
|
132
169
|
/**
|
|
133
170
|
* Set shipping address on the cart. Full replace (not patch). Triggers cart
|
|
134
171
|
* re-pricing (tax recalculation per address country/region).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cart-client.d.ts","sourceRoot":"","sources":["../../../src/core/cart/cart-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EACV,IAAI,EACJ,eAAe,EACf,aAAa,EACb,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAClB,2BAA2B,EAC3B,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAC5B,8BAA8B,EAC9B,sBAAsB,EACtB,uBAAuB,EACvB,gCAAgC,EAChC,iBAAiB,EACjB,WAAW,EACX,KAAK,EACL,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,+BAA+B,EAC/B,uBAAuB,EACvB,oBAAoB,EACrB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"cart-client.d.ts","sourceRoot":"","sources":["../../../src/core/cart/cart-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
import { assertNoUserErrors } from '../helpers/assert-no-user-errors';
|
|
25
|
-
import { CART_QUERY, ORDER_BY_TOKEN_QUERY, CART_AVAILABLE_SHIPPING_METHODS_QUERY, AVAILABLE_PAYMENT_METHODS_QUERY, CART_CREATE, CART_ADD_LINES, CART_UPDATE_LINES, CART_REMOVE_LINES, CART_DISCOUNT_CODES_UPDATE, CART_UPDATE_NOTE, CART_UPDATE_ATTRIBUTES, CART_UPDATE_BUYER_IDENTITY, CART_SET_SHIPPING_ADDRESS, CART_SET_BILLING_ADDRESS, CART_SELECT_SHIPPING_METHOD, CART_SELECT_PAYMENT_METHOD, CART_CLEAR_PAYMENT_SELECTION, CART_APPLY_GIFT_CARD, CART_REMOVE_GIFT_CARD, CART_UPDATE_GIFT_CARD_RECIPIENT, CART_COMPLETE, CART_VALIDATE_DISCOUNT_CODE, PAYMENT_CREATE, } from '../operations/cart';
|
|
25
|
+
import { CART_QUERY, ORDER_BY_TOKEN_QUERY, CART_AVAILABLE_SHIPPING_METHODS_QUERY, AVAILABLE_PAYMENT_METHODS_QUERY, CART_CREATE, CART_ADD_LINES, CART_UPDATE_LINES, CART_REMOVE_LINES, CART_DISCOUNT_CODES_UPDATE, CART_UPDATE_NOTE, CART_UPDATE_ATTRIBUTES, CART_UPDATE_BUYER_IDENTITY, CART_MERGE, CART_DOWNGRADE_ON_LOGOUT, CART_RECOVERY_REDEEM, CART_SET_SHIPPING_ADDRESS, CART_SET_BILLING_ADDRESS, CART_SELECT_SHIPPING_METHOD, CART_SELECT_PAYMENT_METHOD, CART_CLEAR_PAYMENT_SELECTION, CART_APPLY_GIFT_CARD, CART_REMOVE_GIFT_CARD, CART_UPDATE_GIFT_CARD_RECIPIENT, CART_COMPLETE, CART_VALIDATE_DISCOUNT_CODE, PAYMENT_CREATE, } from '../operations/cart';
|
|
26
26
|
export class CartClient {
|
|
27
27
|
client;
|
|
28
28
|
constructor(client) {
|
|
@@ -87,12 +87,18 @@ export class CartClient {
|
|
|
87
87
|
return data.orderByToken;
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
|
-
* Create a new cart, optionally with initial lines.
|
|
90
|
+
* Create a new cart, optionally with initial lines. The result carries the
|
|
91
|
+
* one-time `secret` (the cart access capability) — persist it into the
|
|
92
|
+
* composite `cart-id` cookie. The SDK cart manager does this for you.
|
|
91
93
|
*/
|
|
92
94
|
async create(input) {
|
|
93
95
|
const data = await this.client.mutate(CART_CREATE, { input: input ?? {} });
|
|
94
96
|
assertNoUserErrors(data.cartCreate);
|
|
95
|
-
return {
|
|
97
|
+
return {
|
|
98
|
+
cart: data.cartCreate.cart,
|
|
99
|
+
secret: data.cartCreate.secret ?? null,
|
|
100
|
+
warnings: data.cartCreate.warnings ?? [],
|
|
101
|
+
};
|
|
96
102
|
}
|
|
97
103
|
/**
|
|
98
104
|
* Add line items to an existing cart.
|
|
@@ -156,6 +162,50 @@ export class CartClient {
|
|
|
156
162
|
return { cart: data.cartUpdateBuyerIdentity.cart, warnings: data.cartUpdateBuyerIdentity.warnings ?? [] };
|
|
157
163
|
}
|
|
158
164
|
// -------------------------------------------------------------------------
|
|
165
|
+
// Guest ↔ customer transitions (capability model)
|
|
166
|
+
// -------------------------------------------------------------------------
|
|
167
|
+
/**
|
|
168
|
+
* Merge the customer's prior cart into the guest cart on login. The guest
|
|
169
|
+
* cart survives (same id + secret → the stored cookie stays valid),
|
|
170
|
+
* quantities sum per variant, guest checkout fields win. Requires an
|
|
171
|
+
* authenticated request — throws (`StorefrontError`) on
|
|
172
|
+
* `CART_MERGE_REQUIRES_AUTH` (anonymous) or `CART_CURRENCY_MISMATCH`
|
|
173
|
+
* (different currencies). Inspect `err.userErrors[0].code`.
|
|
174
|
+
*/
|
|
175
|
+
async merge(guestCartId) {
|
|
176
|
+
const data = await this.client.mutate(CART_MERGE, { guestCartId });
|
|
177
|
+
assertNoUserErrors(data.cartMerge);
|
|
178
|
+
return { cart: data.cartMerge.cart, warnings: data.cartMerge.warnings ?? [] };
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Downgrade a cart to guest on logout — clears the customer association,
|
|
182
|
+
* contact details, addresses and saved-payment selection while keeping line
|
|
183
|
+
* items, coupons, shipping method, currency and notes. The access secret is
|
|
184
|
+
* NOT rotated, so the stored cookie stays valid. Capability-gated by the
|
|
185
|
+
* `x-cart-secret` header (a missing / wrong secret throws `CART_NOT_FOUND`).
|
|
186
|
+
*/
|
|
187
|
+
async downgradeOnLogout(cartId) {
|
|
188
|
+
const data = await this.client.mutate(CART_DOWNGRADE_ON_LOGOUT, { cartId });
|
|
189
|
+
assertNoUserErrors(data.cartDowngradeOnLogout);
|
|
190
|
+
return { cart: data.cartDowngradeOnLogout.cart, warnings: data.cartDowngradeOnLogout.warnings ?? [] };
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Redeem a signed cart-recovery link. On success the cart secret is rotated
|
|
194
|
+
* and the result carries the NEW one-time `secret` — persist it into the
|
|
195
|
+
* composite `cart-id` cookie (the old secret stops working). Invalid /
|
|
196
|
+
* expired links throw a `StorefrontError` carrying `userErrors` without
|
|
197
|
+
* leaking cart content.
|
|
198
|
+
*/
|
|
199
|
+
async recoveryRedeem(token) {
|
|
200
|
+
const data = await this.client.mutate(CART_RECOVERY_REDEEM, { token });
|
|
201
|
+
assertNoUserErrors(data.cartRecoveryRedeem);
|
|
202
|
+
return {
|
|
203
|
+
cart: data.cartRecoveryRedeem.cart,
|
|
204
|
+
secret: data.cartRecoveryRedeem.secret ?? null,
|
|
205
|
+
warnings: data.cartRecoveryRedeem.warnings ?? [],
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
// -------------------------------------------------------------------------
|
|
159
209
|
// Phase 3 — Cart completion lifecycle methods
|
|
160
210
|
// -------------------------------------------------------------------------
|
|
161
211
|
/**
|
|
@@ -37,8 +37,9 @@ import type { Cart, CartCreateInput } from './types';
|
|
|
37
37
|
/**
|
|
38
38
|
* Cart error codes that require recreation of the cart resource.
|
|
39
39
|
*
|
|
40
|
-
* - `CART_NOT_FOUND` — cart expired, missing, or
|
|
41
|
-
*
|
|
40
|
+
* - `CART_NOT_FOUND` — cart expired, missing, or the access secret was absent
|
|
41
|
+
* or did not match. The backend returns one uniform code so it never leaks
|
|
42
|
+
* whether a given cart exists.
|
|
42
43
|
* - `ALREADY_COMPLETED` — cart status not in `{ACTIVE, RECOVERED}` (CONVERTED
|
|
43
44
|
* after checkout, EXPIRED via TTL, or ABANDONED by purge worker).
|
|
44
45
|
*
|
|
@@ -55,54 +56,6 @@ export type CartRecoverableErrorCode = (typeof CART_RECOVERABLE_ERROR_CODES)[num
|
|
|
55
56
|
* `StorefrontError` carries at least one userError with a recoverable code.
|
|
56
57
|
*/
|
|
57
58
|
export declare function isCartRecoverableError(err: unknown): err is StorefrontError;
|
|
58
|
-
/**
|
|
59
|
-
* Cart error codes that signal a missing or invalid auth context on a
|
|
60
|
-
* customer-owned cart — distinct from cart-resource recovery
|
|
61
|
-
* (`CART_RECOVERABLE_ERROR_CODES`).
|
|
62
|
-
*
|
|
63
|
-
* - `CART_UNAUTHENTICATED` — anonymous request OR present-but-invalid token
|
|
64
|
-
* (expired JWT, malformed). The cart resource is intact and reachable
|
|
65
|
-
* again after re-auth.
|
|
66
|
-
*
|
|
67
|
-
* Storefronts SHOULD preserve the `cart-id` cookie when handling these
|
|
68
|
-
* codes and prompt sign-in — the same cart resumes after a successful login.
|
|
69
|
-
*/
|
|
70
|
-
export declare const CART_SESSION_ERROR_CODES: readonly ["CART_UNAUTHENTICATED"];
|
|
71
|
-
export type CartSessionErrorCode = (typeof CART_SESSION_ERROR_CODES)[number];
|
|
72
|
-
/**
|
|
73
|
-
* Type-safe predicate for "this error means the session is gone, but the
|
|
74
|
-
* cart resource is intact". Distinct from `isCartRecoverableError`
|
|
75
|
-
* (cart-resource recovery) — `isCartSessionError` matches auth-recoverable
|
|
76
|
-
* codes that should trigger re-auth flow, NOT cart cookie cleanup.
|
|
77
|
-
*
|
|
78
|
-
* Inspects `err.userErrors[].code` (structured field) — never matches against
|
|
79
|
-
* `err.message` (locale-dependent, non-stable).
|
|
80
|
-
*/
|
|
81
|
-
export declare function isCartSessionError(err: unknown): err is StorefrontError;
|
|
82
|
-
/**
|
|
83
|
-
* Event fired when the runner observes a session error (`CART_UNAUTHENTICATED`).
|
|
84
|
-
* Cart-id cookie is NOT cleared — the cart resource is intact and the buyer
|
|
85
|
-
* should be prompted to re-authenticate; after a successful login the same
|
|
86
|
-
* cart resumes.
|
|
87
|
-
*/
|
|
88
|
-
export interface CartSessionExpiredEvent {
|
|
89
|
-
/** Cart id from the cookie at the time of the failure (null when no cart was set). */
|
|
90
|
-
oldCartId: string | null;
|
|
91
|
-
/** Operation name from `CartRecoveryOperation.name` if provided, otherwise 'unknown'. */
|
|
92
|
-
operation: string;
|
|
93
|
-
/** Original `StorefrontError` carrying the `CART_UNAUTHENTICATED` userError. */
|
|
94
|
-
cause: unknown;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Thrown when a cart operation fails with a session error
|
|
98
|
-
* (`CART_UNAUTHENTICATED`). Distinct from `CartRecoveryNotPossibleError`
|
|
99
|
-
* (cart-resource issue) — storefronts should redirect to a sign-in flow
|
|
100
|
-
* and retry the operation after re-auth.
|
|
101
|
-
*/
|
|
102
|
-
export declare class CartSessionRequiredError extends Error {
|
|
103
|
-
readonly cause: unknown;
|
|
104
|
-
constructor(cause: unknown, message?: string);
|
|
105
|
-
}
|
|
106
59
|
/**
|
|
107
60
|
* Cookie I/O port. Caller's responsibility — core never touches `document.cookie`.
|
|
108
61
|
*
|
|
@@ -118,9 +71,15 @@ export declare class CartSessionRequiredError extends Error {
|
|
|
118
71
|
export interface CartCookieStore {
|
|
119
72
|
/** Returns the persisted cart id or null. Must be synchronous. */
|
|
120
73
|
get(): string | null;
|
|
121
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* Persists the cart id. When `options.secret` is provided the implementation
|
|
76
|
+
* stores the composite `<cartId>.<secret>` value — the cart access secret is
|
|
77
|
+
* revealed only on create / recovery redeem, so this is the only place it is
|
|
78
|
+
* written. `options.maxAge` defaults to platform `CART_COOKIE_MAX_AGE`.
|
|
79
|
+
*/
|
|
122
80
|
set(cartId: string, options?: {
|
|
123
81
|
maxAge?: number;
|
|
82
|
+
secret?: string | null;
|
|
124
83
|
}): void;
|
|
125
84
|
/** Removes the cookie. Called when the current cart became unrecoverable. */
|
|
126
85
|
clear(): void;
|
|
@@ -145,10 +104,13 @@ export interface CartRecoveryOperation<T> {
|
|
|
145
104
|
run: (cartId: string) => Promise<T>;
|
|
146
105
|
/**
|
|
147
106
|
* Optional atomic "create new cart and run with payload in one go" strategy.
|
|
148
|
-
* Define for replay-safe operations; omit for state-dependent ones.
|
|
107
|
+
* Define for replay-safe operations; omit for state-dependent ones. Return
|
|
108
|
+
* the fresh cart's one-time `secret` so the runner persists the composite
|
|
109
|
+
* cookie (the recovered cart is reachable on the next mutation).
|
|
149
110
|
*/
|
|
150
111
|
recreateAndRun?: (cartClient: CartClient) => Promise<{
|
|
151
112
|
cart: Cart;
|
|
113
|
+
secret?: string | null;
|
|
152
114
|
result: T;
|
|
153
115
|
}>;
|
|
154
116
|
/** Optional diagnostic label surfaced in `CartExpiredEvent.operation`. */
|
|
@@ -179,24 +141,30 @@ export interface ExecuteWithCartRecoveryOptions<T> {
|
|
|
179
141
|
cartClient: CartClient;
|
|
180
142
|
cookieStore: CartCookieStore;
|
|
181
143
|
operation: CartRecoveryOperation<T>;
|
|
182
|
-
/**
|
|
183
|
-
|
|
144
|
+
/**
|
|
145
|
+
* Initial-create fallback when the cookie is empty. Defaults to
|
|
146
|
+
* `cartClient.create()`. Must return the created cart together with its
|
|
147
|
+
* one-time `secret` so the runner persists the composite cookie.
|
|
148
|
+
*/
|
|
149
|
+
ensureCart?: () => Promise<{
|
|
150
|
+
cart: Cart;
|
|
151
|
+
secret?: string | null;
|
|
152
|
+
}>;
|
|
184
153
|
/** Cookie `maxAge` override propagated to `cookieStore.set`. */
|
|
185
154
|
cookieMaxAge?: number;
|
|
186
155
|
/** Optional listener fired before the runner throws `CartRecoveryNotPossibleError`. */
|
|
187
156
|
onExpired?: (event: CartExpiredEvent) => void;
|
|
188
|
-
/**
|
|
189
|
-
* Optional listener fired before the runner throws
|
|
190
|
-
* `CartSessionRequiredError`. Distinct from `onExpired` — the cart
|
|
191
|
-
* resource is intact, but the session/auth context is missing or invalid.
|
|
192
|
-
* Storefront should redirect to sign-in and retry the operation after
|
|
193
|
-
* re-auth; the same cart resumes.
|
|
194
|
-
*/
|
|
195
|
-
onSessionExpired?: (event: CartSessionExpiredEvent) => void;
|
|
196
157
|
/**
|
|
197
158
|
* Server-known cart-id seed used when the cookie store is empty. Cookie
|
|
198
159
|
* wins when present; the seed only fills the gap on first interaction.
|
|
199
160
|
*
|
|
161
|
+
* Accepts either a bare cart id (`"<cartId>"`) or the composite cookie value
|
|
162
|
+
* (`"<cartId>.<secret>"`). When the seed carries a secret, the runner persists
|
|
163
|
+
* the composite cookie so subsequent reads and writes send the access secret
|
|
164
|
+
* and reach the seeded cart. A bare cart id is persisted as-is and degrades to
|
|
165
|
+
* a fresh cart on the next write (the secret is required to reach an existing
|
|
166
|
+
* cart).
|
|
167
|
+
*
|
|
200
168
|
* On Phase 0 the runner eagerly copies the seed into the cookie store so
|
|
201
169
|
* cross-tab tabs observe the same cart-id and recovery semantics match
|
|
202
170
|
* the standard cookie-driven path. If the seed is stale the recovery
|
|
@@ -231,13 +199,6 @@ export interface CartRecoveryRunner {
|
|
|
231
199
|
* fails. Returns an unsubscribe function. Multiple subscribers are supported.
|
|
232
200
|
*/
|
|
233
201
|
onExpired(listener: (event: CartExpiredEvent) => void): () => void;
|
|
234
|
-
/**
|
|
235
|
-
* Subscribe to `session-expired` events fired when the runner observes a
|
|
236
|
-
* `CART_UNAUTHENTICATED` userError (cart resource intact, re-auth required).
|
|
237
|
-
* The cart-id cookie is preserved so the same cart resumes after a successful
|
|
238
|
-
* sign-in. Returns an unsubscribe function. Multiple subscribers are supported.
|
|
239
|
-
*/
|
|
240
|
-
onSessionExpired(listener: (event: CartSessionExpiredEvent) => void): () => void;
|
|
241
202
|
/** Underlying cart client (for advanced flows / read-only helpers). */
|
|
242
203
|
readonly cartClient: CartClient;
|
|
243
204
|
/** Underlying cookie store (for advanced flows). */
|
|
@@ -246,8 +207,15 @@ export interface CartRecoveryRunner {
|
|
|
246
207
|
export interface CreateCartRecoveryRunnerOptions {
|
|
247
208
|
cartClient: CartClient;
|
|
248
209
|
cookieStore: CartCookieStore;
|
|
249
|
-
/**
|
|
250
|
-
|
|
210
|
+
/**
|
|
211
|
+
* Initial-create payload override (default: empty cart). Must return the
|
|
212
|
+
* created cart together with its one-time `secret` so the runner persists
|
|
213
|
+
* the composite cookie.
|
|
214
|
+
*/
|
|
215
|
+
ensureCart?: () => Promise<{
|
|
216
|
+
cart: Cart;
|
|
217
|
+
secret?: string | null;
|
|
218
|
+
}>;
|
|
251
219
|
/** Cookie `maxAge` propagated to all `cookieStore.set` calls. */
|
|
252
220
|
cookieMaxAge?: number;
|
|
253
221
|
/**
|
|
@@ -283,6 +251,7 @@ export declare function createCartRecoveryRunner(options: CreateCartRecoveryRunn
|
|
|
283
251
|
*/
|
|
284
252
|
export declare function recreateWithInput(input: CartCreateInput): (cartClient: CartClient) => Promise<{
|
|
285
253
|
cart: Cart;
|
|
254
|
+
secret: string | null;
|
|
286
255
|
result: CartMutationOutcome;
|
|
287
256
|
}>;
|
|
288
257
|
/**
|
|
@@ -291,6 +260,7 @@ export declare function recreateWithInput(input: CartCreateInput): (cartClient:
|
|
|
291
260
|
*/
|
|
292
261
|
export declare function recreateWithLines(lines: NonNullable<CartCreateInput['lines']>, extraInput?: Omit<CartCreateInput, 'lines'>): (cartClient: CartClient) => Promise<{
|
|
293
262
|
cart: Cart;
|
|
263
|
+
secret: string | null;
|
|
294
264
|
result: CartMutationOutcome;
|
|
295
265
|
}>;
|
|
296
266
|
//# sourceMappingURL=cart-recovery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cart-recovery.d.ts","sourceRoot":"","sources":["../../../src/core/cart/cart-recovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"cart-recovery.d.ts","sourceRoot":"","sources":["../../../src/core/cart/cart-recovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAOrD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,4BAA4B,kDAAmD,CAAC;AAE7F,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,4BAA4B,CAAC,CAAC,MAAM,CAAC,CAAC;AAQrF;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,eAAe,CAM3E;AAMD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,GAAG,IAAI,MAAM,GAAG,IAAI,CAAC;IACrB;;;;;OAKG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IACjF,6EAA6E;IAC7E,KAAK,IAAI,IAAI,CAAC;CACf;AAMD;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC,4CAA4C;IAC5C,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACpC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CACf,UAAU,EAAE,UAAU,KACnB,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IAChE,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,MAAM,MAAM,yBAAyB,GACjC,iBAAiB,GACjB,iBAAiB,GACjB,mBAAmB,CAAC;AAExB;;;;GAIG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,MAAM,EAAE,yBAAyB,CAAC;IAC3C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;gBAEZ,MAAM,EAAE,yBAAyB,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM;CAMhF;AAaD,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,MAAM,EAAE,yBAAyB,CAAC;IAClC,4FAA4F;IAC5F,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,yFAAyF;IACzF,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,KAAK,EAAE,OAAO,CAAC;CAChB;AAmCD,MAAM,WAAW,8BAA8B,CAAC,CAAC;IAC/C,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACpC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IACnE,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uFAAuF;IACvF,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC9C;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AA8BD;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,CAAC,EAC7C,IAAI,EAAE,8BAA8B,CAAC,CAAC,CAAC,GACtC,OAAO,CAAC,CAAC,CAAC,CA0FZ;AAMD,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5D;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAChC;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACnE,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,oDAAoD;IACpD,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;CACvC;AAED,MAAM,WAAW,+BAA+B;IAC9C,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,eAAe,CAAC;IAC7B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IACnE,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,+BAA+B,GACvC,kBAAkB,CAgEpB;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,IAEpD,YAAY,UAAU,KACrB,OAAO,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAI/E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,WAAW,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,EAC5C,UAAU,GAAE,IAAI,CAAC,eAAe,EAAE,OAAO,CAAM,gBAbjC,UAAU,KACrB,OAAO,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAe/E"}
|