@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.
Files changed (55) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/dist/core/auth/session-events.d.ts +6 -9
  3. package/dist/core/auth/session-events.d.ts.map +1 -1
  4. package/dist/core/auth/session-events.js +6 -9
  5. package/dist/core/cart/cart-client.d.ts +39 -2
  6. package/dist/core/cart/cart-client.d.ts.map +1 -1
  7. package/dist/core/cart/cart-client.js +53 -3
  8. package/dist/core/cart/cart-recovery.d.ts +41 -71
  9. package/dist/core/cart/cart-recovery.d.ts.map +1 -1
  10. package/dist/core/cart/cart-recovery.js +37 -95
  11. package/dist/core/cart/cookie-config.d.ts +29 -3
  12. package/dist/core/cart/cookie-config.d.ts.map +1 -1
  13. package/dist/core/cart/cookie-config.js +35 -3
  14. package/dist/core/generated/operation-types.d.ts +268 -4
  15. package/dist/core/generated/operation-types.d.ts.map +1 -1
  16. package/dist/core/generated/operation-types.js +8 -0
  17. package/dist/core/index.d.ts +3 -2
  18. package/dist/core/index.d.ts.map +1 -1
  19. package/dist/core/index.js +3 -2
  20. package/dist/core/middleware/cart-secret.d.ts +43 -0
  21. package/dist/core/middleware/cart-secret.d.ts.map +1 -0
  22. package/dist/core/middleware/cart-secret.js +55 -0
  23. package/dist/core/middleware/session-retry.d.ts +2 -2
  24. package/dist/core/middleware/session-retry.js +2 -2
  25. package/dist/core/operations/cart.d.ts +23 -0
  26. package/dist/core/operations/cart.d.ts.map +1 -1
  27. package/dist/core/operations/cart.js +71 -0
  28. package/dist/index.d.ts +1 -1
  29. package/dist/index.js +1 -1
  30. package/dist/react/cookies.d.ts +6 -0
  31. package/dist/react/cookies.d.ts.map +1 -1
  32. package/dist/react/cookies.js +23 -4
  33. package/dist/react/hooks/use-cart-manager.d.ts +20 -13
  34. package/dist/react/hooks/use-cart-manager.d.ts.map +1 -1
  35. package/dist/react/hooks/use-cart-manager.js +14 -12
  36. package/dist/react/hooks/use-logout.d.ts +7 -5
  37. package/dist/react/hooks/use-logout.d.ts.map +1 -1
  38. package/dist/react/hooks/use-logout.js +37 -7
  39. package/dist/react/providers/cart-manager-provider.d.ts +3 -0
  40. package/dist/react/providers/cart-manager-provider.d.ts.map +1 -1
  41. package/dist/react/providers/storefront-client-provider.d.ts.map +1 -1
  42. package/dist/react/providers/storefront-client-provider.js +6 -0
  43. package/dist/react/server/cookie-readers.d.ts +20 -0
  44. package/dist/react/server/cookie-readers.d.ts.map +1 -1
  45. package/dist/react/server/cookie-readers.js +22 -1
  46. package/dist/react/server/index.d.ts +2 -1
  47. package/dist/react/server/index.d.ts.map +1 -1
  48. package/dist/react/server/index.js +4 -1
  49. package/dist/react/stores/cart.context.d.ts +5 -0
  50. package/dist/react/stores/cart.context.d.ts.map +1 -1
  51. package/dist/react/stores/cart.context.js +5 -0
  52. package/dist/react/stores/cart.store.d.ts +6 -0
  53. package/dist/react/stores/cart.store.d.ts.map +1 -1
  54. package/dist/react/stores/cart.store.js +6 -0
  55. package/package.json +1 -1
@@ -1,11 +1,13 @@
1
1
  /**
2
2
  * useLogout — focused hook for the logout flow.
3
3
  *
4
- * Calls the auth client logout (which clears the backend's httpOnly cookie),
5
- * invokes the consumer's `onClearToken` callback (BFF), and resets the local
6
- * auth store. Even when the backend request fails, the local state is
7
- * cleared (defensive better to log a user out than leave them in a half
8
- * state).
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
@@ -18,8 +20,34 @@
18
20
  import { useCallback, useState } from 'react';
19
21
  import { useStorefrontClientContext } from '../providers/storefront-client-provider';
20
22
  import { useAuthStore } from '../stores/store-context';
23
+ import { getCookie } from '../cookies';
24
+ import { CART_COOKIE_NAME, parseCartCookieValue } from '../../core/cart/cookie-config';
25
+ /**
26
+ * Downgrade the active cart to guest before logout so customer PII (contact
27
+ * details, addresses, saved-payment selection) does not linger on a shared
28
+ * device. Best-effort with a single retry: the buyer must always be able to
29
+ * sign out, so any failure is logged and swallowed — never rethrown. No-op
30
+ * when there is no cart cookie. The cart secret rides along automatically via
31
+ * the client's cart-secret middleware.
32
+ */
33
+ async function downgradeCartBeforeLogout(cartClient) {
34
+ const cartId = parseCartCookieValue(getCookie(CART_COOKIE_NAME))?.cartId;
35
+ if (!cartId)
36
+ return;
37
+ for (let attempt = 0; attempt < 2; attempt++) {
38
+ try {
39
+ await cartClient.downgradeOnLogout(cartId);
40
+ return;
41
+ }
42
+ catch (err) {
43
+ if (attempt === 0)
44
+ continue; // one retry, then continue logout regardless
45
+ console.warn('[storefront-sdk] cart downgrade on logout failed; continuing logout', err);
46
+ }
47
+ }
48
+ }
21
49
  export function useLogout(options = {}) {
22
- const { authClient } = useStorefrontClientContext();
50
+ const { authClient, cartClient } = useStorefrontClientContext();
23
51
  const { clearAuth } = useAuthStore();
24
52
  const [isLoggingOut, setIsLoggingOut] = useState(false);
25
53
  const [error, setError] = useState(null);
@@ -27,6 +55,8 @@ export function useLogout(options = {}) {
27
55
  setError(null);
28
56
  setIsLoggingOut(true);
29
57
  try {
58
+ // Clear customer PII from the cart first (best-effort; never blocks logout).
59
+ await downgradeCartBeforeLogout(cartClient);
30
60
  // Auth context resolved server-side from cookie/Bearer — no token arg needed
31
61
  await authClient.logout();
32
62
  if (options.onClearToken) {
@@ -45,6 +75,6 @@ export function useLogout(options = {}) {
45
75
  finally {
46
76
  setIsLoggingOut(false);
47
77
  }
48
- }, [authClient, clearAuth, options]);
78
+ }, [authClient, cartClient, clearAuth, options]);
49
79
  return { logout, isLoggingOut, error };
50
80
  }
@@ -34,6 +34,9 @@ export interface CartManagerProviderProps extends CartManagerLifecycleCallbacks
34
34
  /**
35
35
  * Server-known cart-id seed forwarded to `useCartManager`. Used only when the
36
36
  * `cart-id` cookie is empty on mount — the cookie always wins when present.
37
+ * Accepts a bare cart id or the composite `"<cartId>.<secret>"` cookie value;
38
+ * pass the composite when the cart secret is known server-side so the seeded
39
+ * cart stays reachable on reads and writes.
37
40
  */
38
41
  initialCartId?: string | null;
39
42
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"cart-manager-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/cart-manager-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAK1D,MAAM,WAAW,wBAAyB,SAAQ,6BAA6B;IAC7E;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,aAAa,EACb,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,QAAQ,GACT,EAAE,wBAAwB,2CAU1B;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,oBAAoB,CAM5D"}
1
+ {"version":3,"file":"cart-manager-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/cart-manager-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAK1D,MAAM,WAAW,wBAAyB,SAAQ,6BAA6B;IAC7E;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,aAAa,EACb,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,QAAQ,GACT,EAAE,wBAAwB,2CAU1B;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,oBAAoB,CAM5D"}
@@ -1 +1 @@
1
- {"version":3,"file":"storefront-client-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/storefront-client-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAA6C,MAAM,OAAO,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAIzD,OAAO,EAA2B,KAAK,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAKhH,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAEpG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAE5E,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;CACxB;AAID,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,sBAAsB,CAAC;IAC/B;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;IAC1B,oEAAoE;IACpE,aAAa,CAAC,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAClD,+DAA+D;IAC/D,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,4HAA4H;IAC5H,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,MAAM,EACN,UAAU,EAAE,gBAAqB,EACjC,aAAa,EACb,uBAAuB,EACvB,qBAAqB,EACrB,YAAY,GACb,EAAE,6BAA6B,2CAyE/B;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,4BAA4B,CAMzE"}
1
+ {"version":3,"file":"storefront-client-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/storefront-client-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAA6C,MAAM,OAAO,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAOzD,OAAO,EAA2B,KAAK,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAKhH,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAEpG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAE5E,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;CACxB;AAID,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,sBAAsB,CAAC;IAC/B;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;IAC1B,oEAAoE;IACpE,aAAa,CAAC,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAClD,+DAA+D;IAC/D,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,4HAA4H;IAC5H,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,MAAM,EACN,UAAU,EAAE,gBAAqB,EACjC,aAAa,EACb,uBAAuB,EACvB,qBAAqB,EACrB,YAAY,GACb,EAAE,6BAA6B,2CA8E/B;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,4BAA4B,CAMzE"}
@@ -13,6 +13,9 @@ import { createStorefrontClient } from '../../core/client/create-client';
13
13
  import { CartClient } from '../../core/cart/cart-client';
14
14
  import { AuthClient } from '../../core/auth/auth-client';
15
15
  import { authMiddleware } from '../../core/middleware/auth';
16
+ import { cartSecretMiddleware } from '../../core/middleware/cart-secret';
17
+ import { CART_COOKIE_NAME, parseCartCookieValue } from '../../core/cart/cookie-config';
18
+ import { getCookie } from '../cookies';
16
19
  import { currencyMiddleware } from '../../core/middleware/currency';
17
20
  import { languageMiddleware } from '../../core/middleware/language';
18
21
  import { botProtectionMiddleware } from '../../core/middleware/bot-protection';
@@ -62,6 +65,9 @@ export function StorefrontClientProvider({ children, config, middleware: customM
62
65
  : []),
63
66
  // Header middleware (runs first)
64
67
  authMiddleware(() => authStore.getState().accessToken),
68
+ // Cart access secret — read lazily from the composite cart-id cookie so
69
+ // a rotated secret (recovery redeem) is picked up without rebuilding.
70
+ cartSecretMiddleware(() => parseCartCookieValue(getCookie(CART_COOKIE_NAME))?.cartSecret ?? null),
65
71
  currencyMiddleware(() => currencyStore.getState().currency),
66
72
  languageMiddleware(() => languageStore.getState().language),
67
73
  // Bot protection (if configured)
@@ -22,8 +22,28 @@
22
22
  * const cart = cartId ? await fetchCart(cartId) : null;
23
23
  * ```
24
24
  */
25
+ import { type CartCredentials } from '../../core/cart/cookie-config';
25
26
  /** Read the first-party `cart-id` cookie (server-first, client fallback). */
26
27
  export declare function readCartIdCookie(): Promise<string | null>;
28
+ /**
29
+ * Read the `cart-id` cookie and split the composite `<cartId>.<secret>` value
30
+ * into `{ cartId, cartSecret }`. Pass the result to `serverCartSecretMiddleware`
31
+ * so an SSR / edge cart read carries the secret (without it the backend treats
32
+ * the cart as unreachable and the read returns empty). Returns null when no
33
+ * cart cookie is present.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * import { getStorefrontClient } from '@doswiftly/storefront-sdk/react/server';
38
+ * import { readCartCredentials, serverCartSecretMiddleware } from '@doswiftly/storefront-sdk/react/server';
39
+ *
40
+ * const client = getStorefrontClient({
41
+ * apiUrl, shopSlug,
42
+ * middleware: [serverCartSecretMiddleware(await readCartCredentials())],
43
+ * });
44
+ * ```
45
+ */
46
+ export declare function readCartCredentials(): Promise<CartCredentials | null>;
27
47
  /** Read the first-party `preferred-currency` cookie (server-first, client fallback). */
28
48
  export declare function readCurrencyCookie(): Promise<string | null>;
29
49
  //# sourceMappingURL=cookie-readers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cookie-readers.d.ts","sourceRoot":"","sources":["../../../src/react/server/cookie-readers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAuBH,6EAA6E;AAC7E,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE/D;AAED,wFAAwF;AACxF,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEjE"}
1
+ {"version":3,"file":"cookie-readers.d.ts","sourceRoot":"","sources":["../../../src/react/server/cookie-readers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,+BAA+B,CAAC;AAqBvC,6EAA6E;AAC7E,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE/D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAE3E;AAED,wFAAwF;AACxF,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEjE"}
@@ -22,7 +22,7 @@
22
22
  * const cart = cartId ? await fetchCart(cartId) : null;
23
23
  * ```
24
24
  */
25
- import { CART_COOKIE_NAME } from '../../core/cart/cookie-config';
25
+ import { CART_COOKIE_NAME, parseCartCookieValue, } from '../../core/cart/cookie-config';
26
26
  import { CURRENCY_COOKIE_NAME } from '../../core/currency/cookie-config';
27
27
  import { getCookie } from '../cookies';
28
28
  /**
@@ -46,6 +46,27 @@ async function readCookieIsomorphic(name) {
46
46
  export async function readCartIdCookie() {
47
47
  return readCookieIsomorphic(CART_COOKIE_NAME);
48
48
  }
49
+ /**
50
+ * Read the `cart-id` cookie and split the composite `<cartId>.<secret>` value
51
+ * into `{ cartId, cartSecret }`. Pass the result to `serverCartSecretMiddleware`
52
+ * so an SSR / edge cart read carries the secret (without it the backend treats
53
+ * the cart as unreachable and the read returns empty). Returns null when no
54
+ * cart cookie is present.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * import { getStorefrontClient } from '@doswiftly/storefront-sdk/react/server';
59
+ * import { readCartCredentials, serverCartSecretMiddleware } from '@doswiftly/storefront-sdk/react/server';
60
+ *
61
+ * const client = getStorefrontClient({
62
+ * apiUrl, shopSlug,
63
+ * middleware: [serverCartSecretMiddleware(await readCartCredentials())],
64
+ * });
65
+ * ```
66
+ */
67
+ export async function readCartCredentials() {
68
+ return parseCartCookieValue(await readCookieIsomorphic(CART_COOKIE_NAME));
69
+ }
49
70
  /** Read the first-party `preferred-currency` cookie (server-first, client fallback). */
50
71
  export async function readCurrencyCookie() {
51
72
  return readCookieIsomorphic(CURRENCY_COOKIE_NAME);
@@ -1,6 +1,7 @@
1
1
  export { getStorefrontClient, type ServerClientOptions } from './get-storefront-client';
2
2
  export { createStorefrontAuthRoute, type StorefrontAuthRouteOptions, type StorefrontAuthRouteHandlers, } from './create-storefront-auth-route';
3
3
  export { getInitialAuth, type InitialAuth } from './get-initial-auth';
4
- export { readCartIdCookie, readCurrencyCookie } from './cookie-readers';
4
+ export { readCartIdCookie, readCartCredentials, readCurrencyCookie } from './cookie-readers';
5
+ export { serverCartSecretMiddleware } from '../../core/middleware/cart-secret';
5
6
  export { trustedForwardedHostValidator, originAllowlistValidator, type OriginValidator, type OriginValidatorContext, } from '../../core/auth/handlers';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGxF,OAAO,EACL,yBAAyB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,GACjC,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGxE,OAAO,EACL,6BAA6B,EAC7B,wBAAwB,EACxB,KAAK,eAAe,EACpB,KAAK,sBAAsB,GAC5B,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAGxF,OAAO,EACL,yBAAyB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,GACjC,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtE,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAI7F,OAAO,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAG/E,OAAO,EACL,6BAA6B,EAC7B,wBAAwB,EACxB,KAAK,eAAe,EACpB,KAAK,sBAAsB,GAC5B,MAAM,0BAA0B,CAAC"}
@@ -4,6 +4,9 @@ export { createStorefrontAuthRoute, } from './create-storefront-auth-route';
4
4
  // Server-only cold-start auth seed from the first-party cookies.
5
5
  export { getInitialAuth } from './get-initial-auth';
6
6
  // Server-first readers for the readable first-party cookies (cart-id, currency).
7
- export { readCartIdCookie, readCurrencyCookie } from './cookie-readers';
7
+ export { readCartIdCookie, readCartCredentials, readCurrencyCookie } from './cookie-readers';
8
+ // Server cart-secret middleware — prepend to `getStorefrontClient({ middleware })`
9
+ // with `await readCartCredentials()` so SSR / edge cart reads carry the secret.
10
+ export { serverCartSecretMiddleware } from '../../core/middleware/cart-secret';
8
11
  // Origin validators — wire CSRF defense-in-depth on the route handlers from a single import.
9
12
  export { trustedForwardedHostValidator, originAllowlistValidator, } from '../../core/auth/handlers';
@@ -1,4 +1,9 @@
1
1
  import type { CartState } from './cart.store';
2
+ /**
3
+ * @deprecated Provider and hooks for the legacy {@link createCartStore} cart system.
4
+ * Use `useCartManager` instead — see {@link createCartStore} for details. Removed in
5
+ * a future major release.
6
+ */
2
7
  export declare const CartProvider: {
3
8
  ({ store, children }: {
4
9
  store: import("zustand").StoreApi<CartState>;
@@ -1 +1 @@
1
- {"version":3,"file":"cart.context.d.ts","sourceRoot":"","sources":["../../../src/react/stores/cart.context.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,eAAO,MACK,YAAY;;;;;;GACZ,YAAY;;;GACd,eAAe,6CACqB,CAAC"}
1
+ {"version":3,"file":"cart.context.d.ts","sourceRoot":"","sources":["../../../src/react/stores/cart.context.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MACK,YAAY;;;;;;GACZ,YAAY;;;GACd,eAAe,6CACqB,CAAC"}
@@ -1,3 +1,8 @@
1
1
  'use client';
2
2
  import { createStoreContext } from '../helpers/create-store-context';
3
+ /**
4
+ * @deprecated Provider and hooks for the legacy {@link createCartStore} cart system.
5
+ * Use `useCartManager` instead — see {@link createCartStore} for details. Removed in
6
+ * a future major release.
7
+ */
3
8
  export const { Provider: CartProvider, useStore: useCartStore, useApi: useCartStoreApi, } = createStoreContext('CartStore');
@@ -114,5 +114,11 @@ export interface CartState {
114
114
  export declare const selectCartId: (state: CartState) => string | null;
115
115
  export declare const selectIsCartOpen: (state: CartState) => boolean;
116
116
  export declare const selectCartIsLoading: (state: CartState) => boolean;
117
+ /**
118
+ * @deprecated Use `useCartManager` instead. This store predates capability-based
119
+ * carts and does not carry the cart secret, so mutations against a capability cart
120
+ * fail. `useCartManager` (React) and `createCartRecoveryRunner` (framework-agnostic
121
+ * core) manage the cart secret automatically. Removed in a future major release.
122
+ */
117
123
  export declare function createCartStore(config: CartStoreConfig): import("zustand").StoreApi<CartState>;
118
124
  //# sourceMappingURL=cart.store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cart.store.d.ts","sourceRoot":"","sources":["../../../src/react/stores/cart.store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cart.store.d.ts","sourceRoot":"","sources":["../../../src/react/stores/cart.store.ts"],"names":[],"mappings":"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"}
@@ -54,6 +54,12 @@ export const selectCartIsLoading = (state) => state.isLoading;
54
54
  // ---------------------------------------------------------------------------
55
55
  // Factory
56
56
  // ---------------------------------------------------------------------------
57
+ /**
58
+ * @deprecated Use `useCartManager` instead. This store predates capability-based
59
+ * carts and does not carry the cart secret, so mutations against a capability cart
60
+ * fail. `useCartManager` (React) and `createCartRecoveryRunner` (framework-agnostic
61
+ * core) manage the cart secret automatically. Removed in a future major release.
62
+ */
57
63
  export function createCartStore(config) {
58
64
  // Deduplication for initCart only — first-create collision is the common
59
65
  // case (multiple components mounting and seeing an empty cookie). Recovery
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doswiftly/storefront-sdk",
3
- "version": "19.1.0",
3
+ "version": "20.0.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,