@doswiftly/storefront-sdk 14.0.0 → 15.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 +55 -0
- package/dist/core/auth/auth-client.d.ts +13 -1
- package/dist/core/auth/auth-client.d.ts.map +1 -1
- package/dist/core/auth/auth-client.js +16 -1
- package/dist/core/auth/types.d.ts +18 -52
- package/dist/core/auth/types.d.ts.map +1 -1
- package/dist/core/auth/types.js +0 -3
- package/dist/core/cart/cart-client.d.ts +50 -1
- package/dist/core/cart/cart-client.d.ts.map +1 -1
- package/dist/core/cart/cart-client.js +63 -1
- package/dist/core/cart/types.d.ts +75 -391
- package/dist/core/cart/types.d.ts.map +1 -1
- package/dist/core/cart/types.js +0 -8
- package/dist/core/generated/operation-types.d.ts +4428 -0
- package/dist/core/generated/operation-types.d.ts.map +1 -0
- package/dist/core/generated/operation-types.js +4 -0
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/operations/auth.d.ts +7 -0
- package/dist/core/operations/auth.d.ts.map +1 -1
- package/dist/core/operations/auth.js +68 -0
- package/dist/core/operations/cart.d.ts +30 -0
- package/dist/core/operations/cart.d.ts.map +1 -1
- package/dist/core/operations/cart.js +147 -0
- package/dist/react/hooks/use-cart.d.ts +78 -0
- package/dist/react/hooks/use-cart.d.ts.map +1 -0
- package/dist/react/hooks/use-cart.js +121 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -0
- package/package.json +7 -1
|
@@ -12,12 +12,42 @@
|
|
|
12
12
|
* Drift detection: PreToolUse hook validuje strings przeciwko storefront-operations/schema.graphql.
|
|
13
13
|
*/
|
|
14
14
|
export declare const CART_QUERY: string;
|
|
15
|
+
/**
|
|
16
|
+
* cartAvailableShippingMethods — cart-aware shipping discovery for the
|
|
17
|
+
* checkout shipping step. Backend uses the cart's contents (subtotal,
|
|
18
|
+
* physical-item weight) and surfaces a `DIGITAL_ONLY_NO_SHIPPING` userError
|
|
19
|
+
* when the cart has no shippable items. Each method carries `deliveryType`
|
|
20
|
+
* so the storefront can render a pickup-point / locker picker without
|
|
21
|
+
* inferring the type from the method name.
|
|
22
|
+
*/
|
|
23
|
+
export declare const CART_AVAILABLE_SHIPPING_METHODS_QUERY: string;
|
|
24
|
+
/**
|
|
25
|
+
* availablePaymentMethods — shop-level list of active payment methods
|
|
26
|
+
* (default + sorted by merchant position). Independent of cart contents
|
|
27
|
+
* today; storefront fetches once for the checkout payment step.
|
|
28
|
+
*/
|
|
29
|
+
export declare const AVAILABLE_PAYMENT_METHODS_QUERY: string;
|
|
30
|
+
/**
|
|
31
|
+
* orderByToken — guest order lookup by opaque access token (returned by
|
|
32
|
+
* `cartComplete.order.accessToken`). Optional `email` adds defense-in-depth:
|
|
33
|
+
* if supplied it must match the order's buyer email case-insensitively, else
|
|
34
|
+
* the query returns `null` (same shape as an invalid token). Rate-limited by
|
|
35
|
+
* the backend (5/min per IP+shop); no cache (`Cache-Control: no-store`).
|
|
36
|
+
*/
|
|
37
|
+
export declare const ORDER_BY_TOKEN_QUERY: string;
|
|
15
38
|
export declare const CART_CREATE: string;
|
|
16
39
|
export declare const CART_ADD_LINES: string;
|
|
17
40
|
export declare const CART_UPDATE_LINES: string;
|
|
18
41
|
export declare const CART_REMOVE_LINES: string;
|
|
19
42
|
export declare const CART_DISCOUNT_CODES_UPDATE: string;
|
|
20
43
|
export declare const CART_UPDATE_NOTE: string;
|
|
44
|
+
/**
|
|
45
|
+
* cartUpdateAttributes — replaces (NOT merges) the cart's custom `[{ key, value }]`
|
|
46
|
+
* attribute pairs. Free-form metadata visible to the merchant in admin: delivery
|
|
47
|
+
* instructions, gift-wrap flags, B2B PO numbers. Backend limit: 250 pairs / 255-char
|
|
48
|
+
* keys (rejected with `CART_ATTRIBUTES_LIMIT_EXCEEDED` userError).
|
|
49
|
+
*/
|
|
50
|
+
export declare const CART_UPDATE_ATTRIBUTES: string;
|
|
21
51
|
export declare const CART_UPDATE_BUYER_IDENTITY: string;
|
|
22
52
|
export declare const CART_SET_SHIPPING_ADDRESS: string;
|
|
23
53
|
export declare const CART_SET_BILLING_ADDRESS: 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;AA0XH,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,QAWtB,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,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,QASzB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,QAoBtC,CAAC"}
|
|
@@ -138,6 +138,14 @@ const CART_DISCOUNT_ALLOCATION_FRAGMENT = `
|
|
|
138
138
|
amount { ...Money }
|
|
139
139
|
}
|
|
140
140
|
`;
|
|
141
|
+
const PICKUP_POINT_FRAGMENT = `
|
|
142
|
+
fragment PickupPoint on PickupPoint {
|
|
143
|
+
provider
|
|
144
|
+
pointId
|
|
145
|
+
name
|
|
146
|
+
address
|
|
147
|
+
}
|
|
148
|
+
`;
|
|
141
149
|
const MAILING_ADDRESS_FRAGMENT = `
|
|
142
150
|
fragment MailingAddress on MailingAddress {
|
|
143
151
|
id
|
|
@@ -155,7 +163,11 @@ const MAILING_ADDRESS_FRAGMENT = `
|
|
|
155
163
|
postalCode
|
|
156
164
|
phone
|
|
157
165
|
isDefault
|
|
166
|
+
taxId
|
|
167
|
+
vatNumber
|
|
168
|
+
pickupPoint { ...PickupPoint }
|
|
158
169
|
}
|
|
170
|
+
${PICKUP_POINT_FRAGMENT}
|
|
159
171
|
`;
|
|
160
172
|
const CART_SHIPPING_METHOD_FRAGMENT = `
|
|
161
173
|
fragment CartShippingMethod on CartShippingMethod {
|
|
@@ -166,6 +178,7 @@ const CART_SHIPPING_METHOD_FRAGMENT = `
|
|
|
166
178
|
`;
|
|
167
179
|
const CART_APPLIED_GIFT_CARD_FRAGMENT = `
|
|
168
180
|
fragment CartAppliedGiftCard on CartAppliedGiftCard {
|
|
181
|
+
id
|
|
169
182
|
maskedCode
|
|
170
183
|
lastCharacters
|
|
171
184
|
appliedAmount { ...Money }
|
|
@@ -263,6 +276,70 @@ const CART_WARNING_FRAGMENT = `
|
|
|
263
276
|
target
|
|
264
277
|
}
|
|
265
278
|
`;
|
|
279
|
+
const SHIPPING_CARRIER_FRAGMENT = `
|
|
280
|
+
fragment ShippingCarrier on ShippingCarrier {
|
|
281
|
+
id
|
|
282
|
+
name
|
|
283
|
+
logoUrl
|
|
284
|
+
serviceCode
|
|
285
|
+
}
|
|
286
|
+
`;
|
|
287
|
+
const DELIVERY_ESTIMATE_FRAGMENT = `
|
|
288
|
+
fragment DeliveryEstimate on DeliveryEstimate {
|
|
289
|
+
minDays
|
|
290
|
+
maxDays
|
|
291
|
+
description
|
|
292
|
+
}
|
|
293
|
+
`;
|
|
294
|
+
const FREE_SHIPPING_PROGRESS_FRAGMENT = `
|
|
295
|
+
fragment FreeShippingProgress on FreeShippingProgress {
|
|
296
|
+
qualifies
|
|
297
|
+
currentAmount { ...Money }
|
|
298
|
+
threshold { ...Money }
|
|
299
|
+
remaining { ...Money }
|
|
300
|
+
progressPercent
|
|
301
|
+
message
|
|
302
|
+
}
|
|
303
|
+
${MONEY_FRAGMENT}
|
|
304
|
+
`;
|
|
305
|
+
const AVAILABLE_SHIPPING_METHOD_FRAGMENT = `
|
|
306
|
+
fragment AvailableShippingMethod on AvailableShippingMethod {
|
|
307
|
+
id
|
|
308
|
+
name
|
|
309
|
+
description
|
|
310
|
+
deliveryType
|
|
311
|
+
carrier { ...ShippingCarrier }
|
|
312
|
+
price { ...Money }
|
|
313
|
+
isFree
|
|
314
|
+
estimatedDelivery { ...DeliveryEstimate }
|
|
315
|
+
freeShippingProgress { ...FreeShippingProgress }
|
|
316
|
+
sortOrder
|
|
317
|
+
}
|
|
318
|
+
${SHIPPING_CARRIER_FRAGMENT}
|
|
319
|
+
${MONEY_FRAGMENT}
|
|
320
|
+
${DELIVERY_ESTIMATE_FRAGMENT}
|
|
321
|
+
${FREE_SHIPPING_PROGRESS_FRAGMENT}
|
|
322
|
+
`;
|
|
323
|
+
const PAYMENT_METHOD_FRAGMENT = `
|
|
324
|
+
fragment PaymentMethod on PaymentMethod {
|
|
325
|
+
id
|
|
326
|
+
name
|
|
327
|
+
provider
|
|
328
|
+
type
|
|
329
|
+
icon
|
|
330
|
+
description
|
|
331
|
+
isDefault
|
|
332
|
+
supportedCurrencies
|
|
333
|
+
position
|
|
334
|
+
}
|
|
335
|
+
`;
|
|
336
|
+
const AVAILABLE_PAYMENT_METHODS_FRAGMENT = `
|
|
337
|
+
fragment AvailablePaymentMethods on AvailablePaymentMethods {
|
|
338
|
+
methods { ...PaymentMethod }
|
|
339
|
+
defaultMethod { ...PaymentMethod }
|
|
340
|
+
}
|
|
341
|
+
${PAYMENT_METHOD_FRAGMENT}
|
|
342
|
+
`;
|
|
266
343
|
const PAYMENT_SESSION_FRAGMENT = `
|
|
267
344
|
fragment PaymentSession on PaymentSession {
|
|
268
345
|
id
|
|
@@ -286,6 +363,58 @@ export const CART_QUERY = composeOperation(`
|
|
|
286
363
|
}
|
|
287
364
|
${CART_FRAGMENT}
|
|
288
365
|
`);
|
|
366
|
+
/**
|
|
367
|
+
* cartAvailableShippingMethods — cart-aware shipping discovery for the
|
|
368
|
+
* checkout shipping step. Backend uses the cart's contents (subtotal,
|
|
369
|
+
* physical-item weight) and surfaces a `DIGITAL_ONLY_NO_SHIPPING` userError
|
|
370
|
+
* when the cart has no shippable items. Each method carries `deliveryType`
|
|
371
|
+
* so the storefront can render a pickup-point / locker picker without
|
|
372
|
+
* inferring the type from the method name.
|
|
373
|
+
*/
|
|
374
|
+
export const CART_AVAILABLE_SHIPPING_METHODS_QUERY = composeOperation(`
|
|
375
|
+
query CartAvailableShippingMethods($cartId: ID!, $address: ShippingAddressInput!) {
|
|
376
|
+
cart(id: $cartId) {
|
|
377
|
+
id
|
|
378
|
+
requiresShipping
|
|
379
|
+
availableShippingMethods(address: $address) {
|
|
380
|
+
methods { ...AvailableShippingMethod }
|
|
381
|
+
freeShippingProgress { ...FreeShippingProgress }
|
|
382
|
+
userErrors { ...UserError }
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
${AVAILABLE_SHIPPING_METHOD_FRAGMENT}
|
|
387
|
+
${FREE_SHIPPING_PROGRESS_FRAGMENT}
|
|
388
|
+
${USER_ERROR_FRAGMENT}
|
|
389
|
+
`);
|
|
390
|
+
/**
|
|
391
|
+
* availablePaymentMethods — shop-level list of active payment methods
|
|
392
|
+
* (default + sorted by merchant position). Independent of cart contents
|
|
393
|
+
* today; storefront fetches once for the checkout payment step.
|
|
394
|
+
*/
|
|
395
|
+
export const AVAILABLE_PAYMENT_METHODS_QUERY = composeOperation(`
|
|
396
|
+
query AvailablePaymentMethods {
|
|
397
|
+
availablePaymentMethods {
|
|
398
|
+
...AvailablePaymentMethods
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
${AVAILABLE_PAYMENT_METHODS_FRAGMENT}
|
|
402
|
+
`);
|
|
403
|
+
/**
|
|
404
|
+
* orderByToken — guest order lookup by opaque access token (returned by
|
|
405
|
+
* `cartComplete.order.accessToken`). Optional `email` adds defense-in-depth:
|
|
406
|
+
* if supplied it must match the order's buyer email case-insensitively, else
|
|
407
|
+
* the query returns `null` (same shape as an invalid token). Rate-limited by
|
|
408
|
+
* the backend (5/min per IP+shop); no cache (`Cache-Control: no-store`).
|
|
409
|
+
*/
|
|
410
|
+
export const ORDER_BY_TOKEN_QUERY = composeOperation(`
|
|
411
|
+
query OrderByToken($token: String!, $email: String) {
|
|
412
|
+
orderByToken(token: $token, email: $email) {
|
|
413
|
+
...Order
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
${ORDER_FRAGMENT}
|
|
417
|
+
`);
|
|
289
418
|
// ---------------------------------------------------------------------------
|
|
290
419
|
// Mutations
|
|
291
420
|
// ---------------------------------------------------------------------------
|
|
@@ -361,6 +490,24 @@ export const CART_UPDATE_NOTE = composeOperation(`
|
|
|
361
490
|
${USER_ERROR_FRAGMENT}
|
|
362
491
|
${CART_WARNING_FRAGMENT}
|
|
363
492
|
`);
|
|
493
|
+
/**
|
|
494
|
+
* cartUpdateAttributes — replaces (NOT merges) the cart's custom `[{ key, value }]`
|
|
495
|
+
* attribute pairs. Free-form metadata visible to the merchant in admin: delivery
|
|
496
|
+
* instructions, gift-wrap flags, B2B PO numbers. Backend limit: 250 pairs / 255-char
|
|
497
|
+
* keys (rejected with `CART_ATTRIBUTES_LIMIT_EXCEEDED` userError).
|
|
498
|
+
*/
|
|
499
|
+
export const CART_UPDATE_ATTRIBUTES = composeOperation(`
|
|
500
|
+
mutation CartUpdateAttributes($id: ID!, $attributes: [CartAttributeInput!]!) {
|
|
501
|
+
cartUpdateAttributes(id: $id, attributes: $attributes) {
|
|
502
|
+
cart { ...Cart }
|
|
503
|
+
userErrors { ...UserError }
|
|
504
|
+
warnings { ...CartWarning }
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
${CART_FRAGMENT}
|
|
508
|
+
${USER_ERROR_FRAGMENT}
|
|
509
|
+
${CART_WARNING_FRAGMENT}
|
|
510
|
+
`);
|
|
364
511
|
export const CART_UPDATE_BUYER_IDENTITY = composeOperation(`
|
|
365
512
|
mutation CartUpdateBuyerIdentity($id: ID!, $buyerIdentity: CartBuyerIdentityInput!) {
|
|
366
513
|
cartUpdateBuyerIdentity(id: $id, buyerIdentity: $buyerIdentity) {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useCart — server-driven cart hook bound to an explicit `cartId`.
|
|
3
|
+
*
|
|
4
|
+
* Sister of {@link useCartManager}: same `CartClient` actions, different
|
|
5
|
+
* lifecycle. `useCartManager` reads the cart id from the `cart-id` cookie and
|
|
6
|
+
* runs auto-recovery on stale carts (cookie-first flow — browser-rendered
|
|
7
|
+
* storefront). `useCart` takes the cart id as a prop and never touches the
|
|
8
|
+
* cookie, which is what SSR, deep-link recovery, and admin "view this cart"
|
|
9
|
+
* UIs need.
|
|
10
|
+
*
|
|
11
|
+
* State management follows the platform's store pattern: a vanilla Zustand
|
|
12
|
+
* store is created per hook mount via `useMemo` (component-scoped, no
|
|
13
|
+
* module-level singleton — Inv-3 of the SDK), and React subscribes through
|
|
14
|
+
* `useStore`. Changing `cartId` recreates the store; refetches are explicit
|
|
15
|
+
* (`refetch()` or any mutation triggers one).
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* // Server component / route handler hands the cartId to the client tree.
|
|
20
|
+
* function CheckoutPage({ cartId }: { cartId: string }) {
|
|
21
|
+
* const { cart, isLoading, error, addItems, updateAttributes } = useCart(cartId);
|
|
22
|
+
*
|
|
23
|
+
* if (isLoading) return <Spinner />;
|
|
24
|
+
* if (error) return <ErrorBanner error={error} />;
|
|
25
|
+
* if (!cart) return null;
|
|
26
|
+
*
|
|
27
|
+
* return <CheckoutForm cart={cart} onAdd={addItems} onAttrs={updateAttributes} />;
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
import type { CartMutationOutcome } from '../../core/cart/cart-client';
|
|
32
|
+
import type { Cart, CartAddressInput, CartAttributeInput, CartBuyerIdentityInput, CartLineInput, CartLineUpdateInput } from '../../core/cart/types';
|
|
33
|
+
/** Names of mutations exposed by the hook — useful for telemetry / spinners. */
|
|
34
|
+
export type ServerCartOperation = 'fetch' | 'addItems' | 'updateItems' | 'removeItems' | 'updateBuyerIdentity' | 'setShippingAddress' | 'updateDiscountCodes' | 'updateNote' | 'updateAttributes';
|
|
35
|
+
export interface UseCartOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Fetch the cart automatically when the hook mounts. Set to `false` when the
|
|
38
|
+
* server has already pre-rendered the cart and you want to seed the store
|
|
39
|
+
* instead of double-fetching. Default `true`.
|
|
40
|
+
*/
|
|
41
|
+
autoFetch?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Pre-loaded cart used as the initial store value — e.g. the cart already
|
|
44
|
+
* resolved on the server during SSR. Combine with `autoFetch: false` to avoid
|
|
45
|
+
* a duplicate round-trip on hydration.
|
|
46
|
+
*/
|
|
47
|
+
initialCart?: Cart | null;
|
|
48
|
+
}
|
|
49
|
+
export interface UseCartResult {
|
|
50
|
+
/** Currently loaded cart, or null before the first fetch / when not found. */
|
|
51
|
+
cart: Cart | null;
|
|
52
|
+
/** True while any operation (fetch or mutation) is in flight. */
|
|
53
|
+
isLoading: boolean;
|
|
54
|
+
/** Last error from any operation, or null. */
|
|
55
|
+
error: Error | null;
|
|
56
|
+
/** Which operation produced the current `isLoading` / `error`, if any. */
|
|
57
|
+
operation: ServerCartOperation | null;
|
|
58
|
+
/** Re-fetch the cart from the backend. Resolves with the fresh cart or null. */
|
|
59
|
+
refetch: () => Promise<Cart | null>;
|
|
60
|
+
/** Append line items to the cart. Resolves with `{ cart, warnings }`. */
|
|
61
|
+
addItems: (lines: CartLineInput[]) => Promise<CartMutationOutcome>;
|
|
62
|
+
/** Update line items (quantity, attributes) by their line IDs. */
|
|
63
|
+
updateItems: (lines: CartLineUpdateInput[]) => Promise<CartMutationOutcome>;
|
|
64
|
+
/** Remove line items by their line IDs. */
|
|
65
|
+
removeItems: (lineIds: string[]) => Promise<CartMutationOutcome>;
|
|
66
|
+
/** Update buyer identity (email, phone, country, customer link, language). */
|
|
67
|
+
updateBuyerIdentity: (buyerIdentity: CartBuyerIdentityInput) => Promise<CartMutationOutcome>;
|
|
68
|
+
/** Set the shipping address (full replace). */
|
|
69
|
+
setShippingAddress: (address: CartAddressInput) => Promise<CartMutationOutcome>;
|
|
70
|
+
/** Apply discount codes (replace-all — pass `[]` to clear). */
|
|
71
|
+
updateDiscountCodes: (codes: string[]) => Promise<CartMutationOutcome>;
|
|
72
|
+
/** Update the cart note / gift message. */
|
|
73
|
+
updateNote: (note: string) => Promise<CartMutationOutcome>;
|
|
74
|
+
/** Replace the cart's custom `{ key, value }` attribute pairs. */
|
|
75
|
+
updateAttributes: (attributes: CartAttributeInput[]) => Promise<CartMutationOutcome>;
|
|
76
|
+
}
|
|
77
|
+
export declare function useCart(cartId: string, options?: UseCartOptions): UseCartResult;
|
|
78
|
+
//# sourceMappingURL=use-cart.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-cart.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/use-cart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AASH,OAAO,KAAK,EAAc,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACnF,OAAO,KAAK,EACV,IAAI,EACJ,gBAAgB,EAChB,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;AAM/B,gFAAgF;AAChF,MAAM,MAAM,mBAAmB,GAC3B,OAAO,GACP,UAAU,GACV,aAAa,GACb,aAAa,GACb,qBAAqB,GACrB,oBAAoB,GACpB,qBAAqB,GACrB,YAAY,GACZ,kBAAkB,CAAC;AAEvB,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,iEAAiE;IACjE,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,0EAA0E;IAC1E,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAEtC,gFAAgF;IAChF,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACpC,yEAAyE;IACzE,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACnE,kEAAkE;IAClE,WAAW,EAAE,CAAC,KAAK,EAAE,mBAAmB,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC5E,2CAA2C;IAC3C,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACjE,8EAA8E;IAC9E,mBAAmB,EAAE,CAAC,aAAa,EAAE,sBAAsB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC7F,+CAA+C;IAC/C,kBAAkB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAChF,+DAA+D;IAC/D,mBAAmB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACvE,2CAA2C;IAC3C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC3D,kEAAkE;IAClE,gBAAgB,EAAE,CAAC,UAAU,EAAE,kBAAkB,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACtF;AAoFD,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,aAAa,CA4CnF"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useCart — server-driven cart hook bound to an explicit `cartId`.
|
|
3
|
+
*
|
|
4
|
+
* Sister of {@link useCartManager}: same `CartClient` actions, different
|
|
5
|
+
* lifecycle. `useCartManager` reads the cart id from the `cart-id` cookie and
|
|
6
|
+
* runs auto-recovery on stale carts (cookie-first flow — browser-rendered
|
|
7
|
+
* storefront). `useCart` takes the cart id as a prop and never touches the
|
|
8
|
+
* cookie, which is what SSR, deep-link recovery, and admin "view this cart"
|
|
9
|
+
* UIs need.
|
|
10
|
+
*
|
|
11
|
+
* State management follows the platform's store pattern: a vanilla Zustand
|
|
12
|
+
* store is created per hook mount via `useMemo` (component-scoped, no
|
|
13
|
+
* module-level singleton — Inv-3 of the SDK), and React subscribes through
|
|
14
|
+
* `useStore`. Changing `cartId` recreates the store; refetches are explicit
|
|
15
|
+
* (`refetch()` or any mutation triggers one).
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* // Server component / route handler hands the cartId to the client tree.
|
|
20
|
+
* function CheckoutPage({ cartId }: { cartId: string }) {
|
|
21
|
+
* const { cart, isLoading, error, addItems, updateAttributes } = useCart(cartId);
|
|
22
|
+
*
|
|
23
|
+
* if (isLoading) return <Spinner />;
|
|
24
|
+
* if (error) return <ErrorBanner error={error} />;
|
|
25
|
+
* if (!cart) return null;
|
|
26
|
+
*
|
|
27
|
+
* return <CheckoutForm cart={cart} onAdd={addItems} onAttrs={updateAttributes} />;
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
'use client';
|
|
32
|
+
import { useEffect, useMemo } from 'react';
|
|
33
|
+
import { createStore } from 'zustand/vanilla';
|
|
34
|
+
import { useStore } from 'zustand';
|
|
35
|
+
import { useStorefrontClientContext } from '../providers/storefront-client-provider';
|
|
36
|
+
function createServerCartStore(opts) {
|
|
37
|
+
const { cartClient, cartId, initialCart } = opts;
|
|
38
|
+
const store = createStore(() => ({
|
|
39
|
+
cart: initialCart ?? null,
|
|
40
|
+
isLoading: false,
|
|
41
|
+
error: null,
|
|
42
|
+
operation: null,
|
|
43
|
+
}));
|
|
44
|
+
async function run(operation, exec) {
|
|
45
|
+
store.setState({ isLoading: true, error: null, operation });
|
|
46
|
+
try {
|
|
47
|
+
const result = await exec();
|
|
48
|
+
store.setState({ isLoading: false, error: null, operation: null });
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
53
|
+
store.setState({ isLoading: false, error, operation });
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function runMutation(operation, exec) {
|
|
58
|
+
const outcome = await run(operation, exec);
|
|
59
|
+
store.setState({ cart: outcome.cart });
|
|
60
|
+
return outcome;
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
store,
|
|
64
|
+
async refetch() {
|
|
65
|
+
const cart = await run('fetch', () => cartClient.get(cartId));
|
|
66
|
+
store.setState({ cart });
|
|
67
|
+
return cart;
|
|
68
|
+
},
|
|
69
|
+
addItems: (lines) => runMutation('addItems', () => cartClient.addItems(cartId, lines)),
|
|
70
|
+
updateItems: (lines) => runMutation('updateItems', () => cartClient.updateItems(cartId, lines)),
|
|
71
|
+
removeItems: (lineIds) => runMutation('removeItems', () => cartClient.removeItems(cartId, lineIds)),
|
|
72
|
+
updateBuyerIdentity: (buyerIdentity) => runMutation('updateBuyerIdentity', () => cartClient.updateBuyerIdentity(cartId, buyerIdentity)),
|
|
73
|
+
setShippingAddress: (address) => runMutation('setShippingAddress', () => cartClient.setShippingAddress({ cartId, address })),
|
|
74
|
+
updateDiscountCodes: (codes) => runMutation('updateDiscountCodes', () => cartClient.updateDiscountCodes(cartId, codes)),
|
|
75
|
+
updateNote: (note) => runMutation('updateNote', () => cartClient.updateNote(cartId, note)),
|
|
76
|
+
updateAttributes: (attributes) => runMutation('updateAttributes', () => cartClient.updateAttributes(cartId, attributes)),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Hook
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
export function useCart(cartId, options = {}) {
|
|
83
|
+
const { cartClient } = useStorefrontClientContext();
|
|
84
|
+
const { autoFetch = true, initialCart } = options;
|
|
85
|
+
// Recreate the store when `cartId` or the underlying client changes. The
|
|
86
|
+
// useMemo dependency list captures store identity (component-scoped, not
|
|
87
|
+
// module-level — Inv-3). Mutations capture the store instance for stable
|
|
88
|
+
// references via the api object.
|
|
89
|
+
const api = useMemo(() => createServerCartStore({ cartClient, cartId, initialCart }),
|
|
90
|
+
// initialCart deliberately excluded — it only seeds the FIRST mount; we do
|
|
91
|
+
// not want to reset the store when the parent re-renders with a stale
|
|
92
|
+
// server snapshot.
|
|
93
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
94
|
+
[cartClient, cartId]);
|
|
95
|
+
const state = useStore(api.store);
|
|
96
|
+
// Initial fetch — runs once per (cartId, cartClient) pair when autoFetch is
|
|
97
|
+
// enabled. Catches and stores any error via the runner; the caller observes
|
|
98
|
+
// it through `error` rather than an unhandled promise.
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
if (!autoFetch)
|
|
101
|
+
return;
|
|
102
|
+
api.refetch().catch(() => {
|
|
103
|
+
// already captured in store state via the runner
|
|
104
|
+
});
|
|
105
|
+
}, [api, autoFetch]);
|
|
106
|
+
return {
|
|
107
|
+
cart: state.cart,
|
|
108
|
+
isLoading: state.isLoading,
|
|
109
|
+
error: state.error,
|
|
110
|
+
operation: state.operation,
|
|
111
|
+
refetch: api.refetch,
|
|
112
|
+
addItems: api.addItems,
|
|
113
|
+
updateItems: api.updateItems,
|
|
114
|
+
removeItems: api.removeItems,
|
|
115
|
+
updateBuyerIdentity: api.updateBuyerIdentity,
|
|
116
|
+
setShippingAddress: api.setShippingAddress,
|
|
117
|
+
updateDiscountCodes: api.updateDiscountCodes,
|
|
118
|
+
updateNote: api.updateNote,
|
|
119
|
+
updateAttributes: api.updateAttributes,
|
|
120
|
+
};
|
|
121
|
+
}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export { useLogin, type UseLoginOptions, type UseLoginReturn } from './hooks/use
|
|
|
20
20
|
export { useLogout, type UseLogoutOptions, type UseLogoutReturn } from './hooks/use-logout';
|
|
21
21
|
export { useRefreshToken, type UseRefreshTokenOptions, type UseRefreshTokenReturn } from './hooks/use-refresh-token';
|
|
22
22
|
export { useCartManager, type CartManagerOperation, type CartManagerStatus, type UseCartManagerResult } from './hooks/use-cart-manager';
|
|
23
|
+
export { useCart, type UseCartOptions, type UseCartResult, type ServerCartOperation } from './hooks/use-cart';
|
|
23
24
|
export { useStorefrontClient } from './hooks/use-storefront-client';
|
|
24
25
|
export { useCurrency } from './hooks/use-currency';
|
|
25
26
|
export { useAuthStore, useAuthStoreApi, useAuthHydrated } from './stores/store-context';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"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"}
|
|
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
|
@@ -22,6 +22,7 @@ export { useLogin } from './hooks/use-login';
|
|
|
22
22
|
export { useLogout } from './hooks/use-logout';
|
|
23
23
|
export { useRefreshToken } from './hooks/use-refresh-token';
|
|
24
24
|
export { useCartManager } from './hooks/use-cart-manager';
|
|
25
|
+
export { useCart } from './hooks/use-cart';
|
|
25
26
|
export { useStorefrontClient } from './hooks/use-storefront-client';
|
|
26
27
|
export { useCurrency } from './hooks/use-currency';
|
|
27
28
|
// Store hooks (Context-based)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doswiftly/storefront-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "15.1.0",
|
|
4
4
|
"description": "Storefront runtime SDK for DoSwiftly Commerce — layered transport, middleware pipeline, React providers, Zustand stores, cache strategies. 0 runtime dependencies in core.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -41,16 +41,21 @@
|
|
|
41
41
|
"author": "DoSwiftly Team",
|
|
42
42
|
"license": "MIT",
|
|
43
43
|
"devDependencies": {
|
|
44
|
+
"@graphql-codegen/cli": "^5.0.0",
|
|
45
|
+
"@graphql-codegen/typescript": "^4.0.0",
|
|
46
|
+
"@graphql-codegen/typescript-operations": "^4.0.0",
|
|
44
47
|
"@testing-library/react": "^16.1.0",
|
|
45
48
|
"@types/node": "^22.10.2",
|
|
46
49
|
"@types/react": "^18.3.0 || ^19.0.0",
|
|
47
50
|
"@types/react-dom": "^19.0.0",
|
|
48
51
|
"@vitest/coverage-v8": "^4.1.0",
|
|
49
52
|
"fast-check": "^3.23.2",
|
|
53
|
+
"graphql": "^16.13.2",
|
|
50
54
|
"jsdom": "^25.0.1",
|
|
51
55
|
"next": "^16.2.3",
|
|
52
56
|
"react": "^19.0.0",
|
|
53
57
|
"react-dom": "^19.0.0",
|
|
58
|
+
"tsx": "^4.0.0",
|
|
54
59
|
"typescript": "^5.7.2",
|
|
55
60
|
"vitest": "^4.1.0",
|
|
56
61
|
"zustand": "^5.0.2"
|
|
@@ -70,6 +75,7 @@
|
|
|
70
75
|
"scripts": {
|
|
71
76
|
"build": "tsc",
|
|
72
77
|
"build:only": "tsc",
|
|
78
|
+
"codegen": "tsx scripts/codegen.mts",
|
|
73
79
|
"dev": "tsc --watch",
|
|
74
80
|
"clean": "rm -rf dist",
|
|
75
81
|
"test": "vitest run",
|