sinfactura-types 1.10.113 → 1.10.115

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 (2) hide show
  1. package/dist/cart.d.ts +82 -1
  2. package/package.json +1 -1
package/dist/cart.d.ts CHANGED
@@ -154,7 +154,7 @@ declare global {
154
154
  * at the DynamoDB marshaller instead of at validation.
155
155
  * - `merge.items` is `min(1).max(50)`.
156
156
  */
157
- type CartActionRequest = CartActionAddLine | CartActionChangeQuantity | CartActionRemoveLine | CartActionClear | CartActionMerge | CartActionSaveLine | CartActionRestoreLine;
157
+ type CartActionRequest = CartActionAddLine | CartActionChangeQuantity | CartActionRemoveLine | CartActionClear | CartActionMerge | CartActionSaveLine | CartActionRestoreLine | CartActionRemoveSavedLine;
158
158
  /**
159
159
  * WHICH cart an OPERATOR action acts on — the half of the operator request
160
160
  * that `CartActionRequest` cannot carry.
@@ -267,6 +267,37 @@ declare global {
267
267
  mode: 'restoreLine';
268
268
  lineId: string;
269
269
  }
270
+ /**
271
+ * Removes a line from `savedLines` OUTRIGHT — the shelf's own delete.
272
+ *
273
+ * ⚠️ It exists because `removeLine` does NOT reach a saved line. That verb
274
+ * filters `lines` only, so handing it a saved `lineId` is an idempotent no-op
275
+ * `200` and the shelf is untouched — which left restore-then-remove as the
276
+ * only path off `savedLines`, and that path is not always available:
277
+ *
278
+ * - On a cart at `MAX_CART_LINES` the restore is refused
279
+ * `400 BASKET_LINE_LIMIT` and nothing is written, so a saved line on a full
280
+ * ticket was unreachable by any sequence of actions.
281
+ * - Saved lines spend `MAX_CART_BYTES`, and once the row is over it `saveLine`
282
+ * is refused too — so a shelf could become the thing consuming the budget
283
+ * with no way to shrink it.
284
+ *
285
+ * This verb touches `savedLines` alone, so the LINE guard cannot refuse it
286
+ * (the active count does not change) and it is a genuine reduction against the
287
+ * BYTE guard. That makes it the shelf's recovery path, not merely its
288
+ * convenience.
289
+ *
290
+ * ⚠️ It does NOT return the line to the cart. `restoreLine` is that verb; this
291
+ * one discards. A UI must not offer them behind the same affordance.
292
+ *
293
+ * A `lineId` that is not in `savedLines` is a no-op `200`, matching
294
+ * `removeLine`, `saveLine` and `restoreLine`.
295
+ */
296
+ interface CartActionRemoveSavedLine extends CartActionBase {
297
+ mode: 'removeSavedLine';
298
+ /** Names a line in `savedLines` — NOT in `lines`. */
299
+ lineId: string;
300
+ }
270
301
  /**
271
302
  * Empties `lines` to `[]`.
272
303
  *
@@ -340,10 +371,60 @@ declare global {
340
371
  available: number;
341
372
  reason: 'insufficientStock' | 'notOffered';
342
373
  }
374
+ /**
375
+ * WHY a product the request named did not make it onto the cart.
376
+ *
377
+ * ⚠️ The distinction that matters is REMEDIABLE vs NOT. `cartFull` is the
378
+ * shopper's to fix — remove a line and send it again — while the other two are
379
+ * facts about the catalogue that retrying cannot change. `droppedSkus` alone
380
+ * could not express that, so every consumer rendered one message for all of
381
+ * them, and the one that told the shopper "product not found" for a cart that
382
+ * was merely full was both wrong and unactionable.
383
+ *
384
+ * ⚠️ `notOffered` deliberately shares its spelling with
385
+ * `CartLineAvailability.reason`, because it is the same fact — the product is
386
+ * hidden from this channel. Two half-aligned vocabularies for one condition is
387
+ * the outcome this naming exists to avoid.
388
+ *
389
+ * ⚠️ Treat an UNRECOGNISED reason as unremediable rather than discarding the
390
+ * entry: a reason added later must degrade, not vanish, and guessing
391
+ * "remediable" would invite a retry loop that cannot succeed.
392
+ */
393
+ interface CartLineDrop {
394
+ productId: string;
395
+ /**
396
+ * - `productUnavailable` — no product row resolved at all (deleted, or never
397
+ * existed). Permanent from the caller's side.
398
+ * - `notOffered` — the product resolved but is `hiddenFromStorefront`, so it
399
+ * is not sellable on this channel. Also permanent from the caller's side,
400
+ * but a DIFFERENT fact: the product exists.
401
+ * - `cartFull` — the line was truncated because the resulting cart would
402
+ * exceed the line cap. `merge` is the only action that truncates; every
403
+ * other one refuses with `400 BASKET_LINE_LIMIT` instead. **Remediable.**
404
+ */
405
+ reason: 'productUnavailable' | 'notOffered' | 'cartFull';
406
+ }
343
407
  interface CartActionResponse {
344
408
  message: string;
345
409
  data: Cart;
410
+ /**
411
+ * ⚠️ KEPT, and kept as `string[]`. It is not replaced by `dropped` below
412
+ * and must not be: both consumers parse this as an array of strings today,
413
+ * and one of them filters non-strings out — so changing its element type
414
+ * would degrade that client to reporting NOTHING, silently, in the
415
+ * direction that hides the problem. The reason travels alongside instead.
416
+ */
346
417
  droppedSkus: string[];
418
+ /**
419
+ * The same drops as `droppedSkus`, each carrying WHY.
420
+ *
421
+ * ⚠️ REQUIRED and always present — an empty array when nothing dropped —
422
+ * for the same reason its two siblings are. One entry per entry in
423
+ * `droppedSkus`, in the same order, so a consumer that has already indexed
424
+ * one can zip them; new consumers should read this one and ignore
425
+ * `droppedSkus` entirely.
426
+ */
427
+ dropped: CartLineDrop[];
347
428
  availability: CartLineAvailability[];
348
429
  }
349
430
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sinfactura-types",
3
- "version": "1.10.113",
3
+ "version": "1.10.115",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",