platform-types 1.10.718 → 1.10.719

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/dist/basket.d.ts CHANGED
@@ -76,4 +76,27 @@ declare global {
76
76
  */
77
77
  export declare const BASKET_ERROR_CODES: readonly ["VALIDATION_FAILED", "FOREIGN_INDEX_KEY_ATTRIBUTE", "CART_TARGET_REQUIRED", "CART_NOT_FOUND", "CART_REVIEW_INCOMPLETE", "CART_REVIEW_UNAVAILABLE", "CART_NOT_PARKED", "CART_ALREADY_PARKED", "TERMINAL_INDEX_UNAVAILABLE", "PRODUCT_NOT_FOUND", "PRODUCT_COST_UNKNOWN", "UNIT_QUANTITY_NOT_WHOLE", "BASKET_VERSION_CONFLICT", "BASKET_LINE_LIMIT", "BASKET_SIZE_LIMIT", "UNKNOWN_LINE", "INVALID_PRICE", "LINE_DISCOUNT_NOT_ALLOWED", "LINE_DISCOUNT_EXCEEDS_MAX", "FX_CONVERSION_UNAVAILABLE", "COUPON_NOT_FOUND", "COUPON_NOT_ACTIVE", "COUPON_EXPIRED", "COUPON_EXHAUSTED", "COUPON_MIN_SUBTOTAL", "COUPON_REQUIRES_CUSTOMER", "COUPON_BUDGET_EXHAUSTED", "COUPON_RATE_LIMITED", "COUPON_CURRENCY_MISMATCH", "PROMOTION_NOT_FOUND", "PROMOTION_NOT_ACTIVE", "PROMOTION_NOT_STARTED", "PROMOTION_EXPIRED", "PROMOTION_NOT_CART_APPLICABLE"];
78
78
  export type BasketErrorCode = (typeof BASKET_ERROR_CODES)[number];
79
+ /**
80
+ * The refusals the storefront's POST /basket { mode: 'resume', token } handler
81
+ * itself answers (an abandoned-cart recovery link). Middleware refusals
82
+ * (GATING_ERROR_CODES, STOREFRONT_UNAVAILABLE, validation) are separate, and so
83
+ * are the cart resolver's BasketErrorCode refusals, which the fold or
84
+ * reinstatement write forwards unchanged once ownership is proven (for example
85
+ * 409 BASKET_VERSION_CONFLICT, or 404 CART_NOT_FOUND carrying data.cartId when
86
+ * the fold target was deleted mid-request).
87
+ *
88
+ * - CART_RESUME_UNAVAILABLE (404): every reason the link cannot be honoured —
89
+ * invalid or expired token, another store, a cart that is gone, converted,
90
+ * owned by someone else, held by a till, or already folded into a cart that
91
+ * has since gone — with one identical body, so a
92
+ * forwarded email is never an existence oracle. Render one neutral message.
93
+ * - CART_RESUME_INCOMPLETE (503): the caller owns the cart, but whether a live
94
+ * cart should receive the recovered lines could not be proven — the read of
95
+ * the caller's carts stopped at its row ceiling (200 or more carts) or its
96
+ * time budget, or the strong re-read contradicted the index's pick. Nothing
97
+ * was written. A ceiling stop repeats until carts are reaped; the others
98
+ * clear on retry.
99
+ */
100
+ export declare const BASKET_RESUME_ERROR_CODES: readonly ["CART_RESUME_UNAVAILABLE", "CART_RESUME_INCOMPLETE"];
101
+ export type BasketResumeErrorCode = (typeof BASKET_RESUME_ERROR_CODES)[number];
79
102
  export {};
package/dist/basket.js CHANGED
@@ -46,3 +46,25 @@ export const BASKET_ERROR_CODES = [
46
46
  'PROMOTION_EXPIRED',
47
47
  'PROMOTION_NOT_CART_APPLICABLE',
48
48
  ];
49
+ /**
50
+ * The refusals the storefront's POST /basket { mode: 'resume', token } handler
51
+ * itself answers (an abandoned-cart recovery link). Middleware refusals
52
+ * (GATING_ERROR_CODES, STOREFRONT_UNAVAILABLE, validation) are separate, and so
53
+ * are the cart resolver's BasketErrorCode refusals, which the fold or
54
+ * reinstatement write forwards unchanged once ownership is proven (for example
55
+ * 409 BASKET_VERSION_CONFLICT, or 404 CART_NOT_FOUND carrying data.cartId when
56
+ * the fold target was deleted mid-request).
57
+ *
58
+ * - CART_RESUME_UNAVAILABLE (404): every reason the link cannot be honoured —
59
+ * invalid or expired token, another store, a cart that is gone, converted,
60
+ * owned by someone else, held by a till, or already folded into a cart that
61
+ * has since gone — with one identical body, so a
62
+ * forwarded email is never an existence oracle. Render one neutral message.
63
+ * - CART_RESUME_INCOMPLETE (503): the caller owns the cart, but whether a live
64
+ * cart should receive the recovered lines could not be proven — the read of
65
+ * the caller's carts stopped at its row ceiling (200 or more carts) or its
66
+ * time budget, or the strong re-read contradicted the index's pick. Nothing
67
+ * was written. A ceiling stop repeats until carts are reaped; the others
68
+ * clear on retry.
69
+ */
70
+ export const BASKET_RESUME_ERROR_CODES = ['CART_RESUME_UNAVAILABLE', 'CART_RESUME_INCOMPLETE'];
package/dist/cart.d.ts CHANGED
@@ -56,15 +56,17 @@ declare global {
56
56
  parkedBy?: string;
57
57
  /**
58
58
  * Epoch ms this ABANDONED cart's lines were folded into another cart by
59
- * `POST /basket` `{ mode: 'resume' }`. Set once and never cleared.
59
+ * `POST /basket` `{ mode: 'resume' }`. Set once; cleared again only when the
60
+ * fold it was claimed for was REFUSED before writing anything (so the link
61
+ * can fold the lines on retry).
60
62
  *
61
63
  * ⚠️ **It is a CONSUMPTION marker, not a timestamp anyone should render.**
62
64
  * The fold uses `merge`, which SUMS, and the abandoned row survives with
63
65
  * its lines for as long as the recovery link does — so without a marker a
64
66
  * refresh, a back-navigation or a component that mounts twice would re-add
65
67
  * every quantity, for days. The resume write sets this under
66
- * `attribute_not_exists(resumedAt)`, so exactly one caller can ever win and
67
- * every replay answers the cart the shopper already has.
68
+ * `attribute_not_exists(resumedAt)`, so exactly one caller wins each claim
69
+ * and every replay answers the cart the shopper already has.
68
70
  *
69
71
  * ⚠️ Absent on the OTHER resume path — a shopper with no second cart has
70
72
  * their own cart reinstated in place, which adds nothing and needs no
@@ -806,12 +808,23 @@ declare global {
806
808
  * an email, is HMAC-signed, expires, and carries `{ storeId, cartId }` and
807
809
  * nothing about a person.
808
810
  *
809
- * ⚠️ **Every refusal is the SAME 4xx and the same bare code** — an invalid or
810
- * expired token, a cart that no longer exists, a cart already converted to an
811
- * order, and a cart belonging to a DIFFERENT customer are indistinguishable on
812
- * the wire, deliberately. A recovery email gets forwarded; the response must
813
- * never tell the reader whether the cart is real. A consumer must therefore
814
- * render exactly one neutral message and must not try to explain the failure.
811
+ * ⚠️ **Every refusal about the LINK is the SAME 404 and the same bare code**
812
+ * (`CART_RESUME_UNAVAILABLE`) — an invalid or expired token, a cart that no
813
+ * longer exists, a cart already converted to an order or already folded into
814
+ * a cart since gone, and a cart belonging to a DIFFERENT customer are
815
+ * indistinguishable on the wire, deliberately. A recovery email gets
816
+ * forwarded; the response must never tell the reader whether the cart is
817
+ * real. A consumer must therefore render exactly one neutral message for it
818
+ * and must not try to explain the failure.
819
+ *
820
+ * Only AFTER ownership is proven can two other kinds of refusal appear, and a
821
+ * consumer may treat them as retryable: `503 CART_RESUME_INCOMPLETE` (the
822
+ * caller's other carts could not all be read, so no fold-or-reinstate choice
823
+ * was made and nothing was written) and the cart resolver's own
824
+ * {@link BasketErrorCode} refusals, forwarded unchanged from the fold or
825
+ * reinstatement write (e.g. `409 BASKET_VERSION_CONFLICT`, `404
826
+ * CART_NOT_FOUND` for a target deleted mid-request). See
827
+ * `BASKET_RESUME_ERROR_CODES`.
815
828
  *
816
829
  * ⚠️ On success it answers the ordinary {@link CartActionResponse}. If the
817
830
  * caller already holds another cart with lines, the recovered lines are FOLDED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BASKET_ERROR_CODES = void 0;
3
+ exports.BASKET_RESUME_ERROR_CODES = exports.BASKET_ERROR_CODES = void 0;
4
4
  /**
5
5
  * Domain refusals from POST /baskets (replacement, named actions and park/resume)
6
6
  * and GET /baskets?mode=review. Check GATING_ERROR_CODES separately for middleware
@@ -49,3 +49,25 @@ exports.BASKET_ERROR_CODES = [
49
49
  'PROMOTION_EXPIRED',
50
50
  'PROMOTION_NOT_CART_APPLICABLE',
51
51
  ];
52
+ /**
53
+ * The refusals the storefront's POST /basket { mode: 'resume', token } handler
54
+ * itself answers (an abandoned-cart recovery link). Middleware refusals
55
+ * (GATING_ERROR_CODES, STOREFRONT_UNAVAILABLE, validation) are separate, and so
56
+ * are the cart resolver's BasketErrorCode refusals, which the fold or
57
+ * reinstatement write forwards unchanged once ownership is proven (for example
58
+ * 409 BASKET_VERSION_CONFLICT, or 404 CART_NOT_FOUND carrying data.cartId when
59
+ * the fold target was deleted mid-request).
60
+ *
61
+ * - CART_RESUME_UNAVAILABLE (404): every reason the link cannot be honoured —
62
+ * invalid or expired token, another store, a cart that is gone, converted,
63
+ * owned by someone else, held by a till, or already folded into a cart that
64
+ * has since gone — with one identical body, so a
65
+ * forwarded email is never an existence oracle. Render one neutral message.
66
+ * - CART_RESUME_INCOMPLETE (503): the caller owns the cart, but whether a live
67
+ * cart should receive the recovered lines could not be proven — the read of
68
+ * the caller's carts stopped at its row ceiling (200 or more carts) or its
69
+ * time budget, or the strong re-read contradicted the index's pick. Nothing
70
+ * was written. A ceiling stop repeats until carts are reaped; the others
71
+ * clear on retry.
72
+ */
73
+ exports.BASKET_RESUME_ERROR_CODES = ['CART_RESUME_UNAVAILABLE', 'CART_RESUME_INCOMPLETE'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "platform-types",
3
- "version": "1.10.718",
3
+ "version": "1.10.719",
4
4
  "description": "Shared wire and entity contracts for the platform.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",