/** * Add-to-cart refusals the shopper has to be told about. * * Lives in `core/` and returns a CODE, never a message: `ui/` owns the copy, so * each design maps this to its own `productDetail.*` string rather than showing * the raw API sentence. Shared by the product page hook and the grid quick-add. */ export type AddToCartError = 'CART_FULL' | 'FAILED'; /** * The API's stable, machine-readable error code for a failed call, or * `undefined` when the failure carried none (a network drop, a timeout, an * older backend). * * Where it comes from: the API answers an error as * `{ statusCode, code, message, details?, timestamp, path }`, and the SDK hands * that whole body back as `BrainerceError.details`. So the code lives one level * in, at `err.details.code` — not on the error itself. Read it rather than the * message: the message is human-readable prose that changes freely (and is * English regardless of the shopper's language), the code does not. */ export function getErrorCode(err: unknown): string | undefined { const body = (err as { details?: { code?: unknown } } | null)?.details; return typeof body?.code === 'string' ? body.code : undefined; } /** * A storefront cart holds at most 50 DISTINCT product lines. The 51st add is * refused with `400 CART_LINE_LIMIT_REACHED`. * * The cap applies to storefront traffic only (`storeId` and `vc_*` modes). It * does NOT block quantity changes or removals, so "remove something first" is * advice the shopper can actually act on. * * The message match is a FALLBACK, kept only for the window where a storefront * built from this template talks to a backend older than the code. Once the * backend carrying `CART_LINE_LIMIT_REACHED` is live everywhere, the regex can * go: every storefront talks to the current API, so the code is always there. * It cannot produce a false `CART_FULL` in the meantime, which is why it costs * nothing to keep until then. * * Anything unrecognised falls through to `FAILED`, which is still a visible * message rather than the silence this replaced. */ export function toAddToCartError(err: unknown): AddToCartError { if (getErrorCode(err) === 'CART_LINE_LIMIT_REACHED') return 'CART_FULL'; const message = (err as { message?: string } | null)?.message ?? ''; return /cart can hold at most/i.test(message) ? 'CART_FULL' : 'FAILED'; }