sinfactura-types 1.10.488 → 1.10.489

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.
@@ -312,8 +312,9 @@ exports.SOCKET_ACTIONS = [
312
312
  */
313
313
  'presupuestos',
314
314
  /**
315
- * A product row changed. Sent in TWO shapes, and a consumer must handle both
316
- * — see {@link ProductStockFrameData}.
315
+ * A product row changed. Sent in TWO shapes to an operator and a THIRD to a
316
+ * shopper, and a consumer must handle each — see {@link ProductStockFrameData}
317
+ * and {@link ProductRemovedFrameData}.
317
318
  *
318
319
  * 1. **Full row** — the whole `Product`. Sent by the paths that create or
319
320
  * re-state a row: `products/_post.ts` (create, edit, disable),
@@ -349,12 +350,25 @@ exports.SOCKET_ACTIONS = [
349
350
  * order create, edit, void, return and return-disposition paths, the web
350
351
  * cancel, `/inventory` movements, the purchase-order receipt and cycle-count
351
352
  * finalization reach customer sockets too (`wsPostStoreCustomers`, which
352
- * suppresses a row by reading `hiddenFromStorefront` off the payload);
353
+ * replaces a hidden or disabled row with shape 3 by reading
354
+ * `hiddenFromStorefront` / `disabled` off the payload);
353
355
  * service-order parts and status, presupuesto conversion, MercadoLibre stock,
354
356
  * the price-list cascade and the product CSV import's announcement are
355
357
  * operator-only. A customer's copy is
356
358
  * `scrubForCustomer`'d, so `cost` is absent there — never rely on its
357
359
  * presence to tell the shapes apart.
360
+ *
361
+ * 3. **Removal marker** — {@link ProductRemovedFrameData}, SHOPPER-ONLY
362
+ * (operators still see the two shapes above). When
363
+ * either shape above carries a truthy `hiddenFromStorefront` or `disabled`,
364
+ * `wsPostStoreCustomers` replaces it, per customer connection, with
365
+ * `{ storeId, productId, removed: true, changed: 'removed' }` and nothing
366
+ * else. Key on `data.removed === true` BEFORE treating a frame as a row or
367
+ * a patch: drop the product from every cached list and mark its page
368
+ * unavailable. It is emitted on EVERY write to a hidden or disabled
369
+ * product, not only on the transition, so receiving it for a product the
370
+ * client does not hold is normal and must be a no-op. An operator socket
371
+ * never receives this shape.
358
372
  */
359
373
  'products',
360
374
  /**
@@ -636,9 +650,13 @@ exports.isSocketAction = isSocketAction;
636
650
  * it stand still across a whole day of sales; order by `lastMovementAt`, or do
637
651
  * not order these frames at all.
638
652
  *
639
- * ⚠️ Neither name is a DynamoDB reserved word, so the joined projection needs
640
- * no `ExpressionAttributeNames` alias. Adding one that IS reserved (`status`,
641
- * `size`, `name`, …) breaks every read at once — alias it at the join site.
653
+ * ⚠️ The api aliases `disabled` at the join site (`#disabled`) by convention —
654
+ * it is NOT on DynamoDB's reserved list (`DISABLE` is), but the alias costs
655
+ * nothing and keeps the join site the one place a name is aliased. A member
656
+ * that IS reserved (`status`, `size`, `name`, …) must be aliased there too, or
657
+ * it breaks every read at once. It is carried, like `hiddenFromStorefront`, so the shopper
658
+ * fan-out can turn a stock movement on a disabled product into a
659
+ * {@link ProductRemovedFrameData} marker instead of a priced patch.
642
660
  */
643
661
  exports.PRODUCT_STOCK_FRAME_FIELDS = [
644
662
  'stock',
@@ -646,6 +664,7 @@ exports.PRODUCT_STOCK_FRAME_FIELDS = [
646
664
  'cost',
647
665
  'currency',
648
666
  'hiddenFromStorefront',
667
+ 'disabled',
649
668
  'updatedAt',
650
669
  'lastMovementAt',
651
670
  ];
package/dist/socket.d.ts CHANGED
@@ -119,11 +119,15 @@ export interface SocketMessage<T = unknown> {
119
119
  * it stand still across a whole day of sales; order by `lastMovementAt`, or do
120
120
  * not order these frames at all.
121
121
  *
122
- * ⚠️ Neither name is a DynamoDB reserved word, so the joined projection needs
123
- * no `ExpressionAttributeNames` alias. Adding one that IS reserved (`status`,
124
- * `size`, `name`, …) breaks every read at once — alias it at the join site.
122
+ * ⚠️ The api aliases `disabled` at the join site (`#disabled`) by convention —
123
+ * it is NOT on DynamoDB's reserved list (`DISABLE` is), but the alias costs
124
+ * nothing and keeps the join site the one place a name is aliased. A member
125
+ * that IS reserved (`status`, `size`, `name`, …) must be aliased there too, or
126
+ * it breaks every read at once. It is carried, like `hiddenFromStorefront`, so the shopper
127
+ * fan-out can turn a stock movement on a disabled product into a
128
+ * {@link ProductRemovedFrameData} marker instead of a priced patch.
125
129
  */
126
- export declare const PRODUCT_STOCK_FRAME_FIELDS: readonly ["stock", "prices", "cost", "currency", "hiddenFromStorefront", "updatedAt", "lastMovementAt"];
130
+ export declare const PRODUCT_STOCK_FRAME_FIELDS: readonly ["stock", "prices", "cost", "currency", "hiddenFromStorefront", "disabled", "updatedAt", "lastMovementAt"];
127
131
  /**
128
132
  * `data` of a **partial** `products` frame — the projection every stock-moving
129
133
  * write announces, and the only `products` shape that is not a whole `Product`.
@@ -139,6 +143,26 @@ export declare const PRODUCT_STOCK_FRAME_FIELDS: readonly ["stock", "prices", "c
139
143
  */
140
144
  export interface ProductStockFrameData extends Pick<Product, 'storeId' | 'productId'>, Partial<Pick<Product, (typeof PRODUCT_STOCK_FRAME_FIELDS)[number]>> {
141
145
  }
146
+ /**
147
+ * `data` of a **removal** `products` frame — the only shape a shopper socket
148
+ * receives for a product that is hidden from the storefront or disabled.
149
+ *
150
+ * ⚠️ SHOPPER-ONLY, and deliberately carries nothing but identity: no name,
151
+ * price, pictures, stock or cost. A hidden or disabled product's DATA never
152
+ * reaches a shopper; only this marker does. Key on `removed === true` and drop
153
+ * the product from cached lists; mark its page unavailable. `changed` is the
154
+ * typed marker a client's frame router places the frame by.
155
+ *
156
+ * ⚠️ Sent on every write to such a product, not only the transition, so it is
157
+ * idempotent by design: a marker for a product the client never held is a
158
+ * no-op.
159
+ */
160
+ export interface ProductRemovedFrameData {
161
+ storeId: string;
162
+ productId: string;
163
+ removed: true;
164
+ changed: 'removed';
165
+ }
142
166
  /**
143
167
  * The `/logs` read mode a `log-delete` frame can refer to.
144
168
  *
package/dist/socket.js CHANGED
@@ -309,8 +309,9 @@ export const SOCKET_ACTIONS = [
309
309
  */
310
310
  'presupuestos',
311
311
  /**
312
- * A product row changed. Sent in TWO shapes, and a consumer must handle both
313
- * — see {@link ProductStockFrameData}.
312
+ * A product row changed. Sent in TWO shapes to an operator and a THIRD to a
313
+ * shopper, and a consumer must handle each — see {@link ProductStockFrameData}
314
+ * and {@link ProductRemovedFrameData}.
314
315
  *
315
316
  * 1. **Full row** — the whole `Product`. Sent by the paths that create or
316
317
  * re-state a row: `products/_post.ts` (create, edit, disable),
@@ -346,12 +347,25 @@ export const SOCKET_ACTIONS = [
346
347
  * order create, edit, void, return and return-disposition paths, the web
347
348
  * cancel, `/inventory` movements, the purchase-order receipt and cycle-count
348
349
  * finalization reach customer sockets too (`wsPostStoreCustomers`, which
349
- * suppresses a row by reading `hiddenFromStorefront` off the payload);
350
+ * replaces a hidden or disabled row with shape 3 by reading
351
+ * `hiddenFromStorefront` / `disabled` off the payload);
350
352
  * service-order parts and status, presupuesto conversion, MercadoLibre stock,
351
353
  * the price-list cascade and the product CSV import's announcement are
352
354
  * operator-only. A customer's copy is
353
355
  * `scrubForCustomer`'d, so `cost` is absent there — never rely on its
354
356
  * presence to tell the shapes apart.
357
+ *
358
+ * 3. **Removal marker** — {@link ProductRemovedFrameData}, SHOPPER-ONLY
359
+ * (operators still see the two shapes above). When
360
+ * either shape above carries a truthy `hiddenFromStorefront` or `disabled`,
361
+ * `wsPostStoreCustomers` replaces it, per customer connection, with
362
+ * `{ storeId, productId, removed: true, changed: 'removed' }` and nothing
363
+ * else. Key on `data.removed === true` BEFORE treating a frame as a row or
364
+ * a patch: drop the product from every cached list and mark its page
365
+ * unavailable. It is emitted on EVERY write to a hidden or disabled
366
+ * product, not only on the transition, so receiving it for a product the
367
+ * client does not hold is normal and must be a no-op. An operator socket
368
+ * never receives this shape.
355
369
  */
356
370
  'products',
357
371
  /**
@@ -632,9 +646,13 @@ export const isSocketAction = (value) => typeof value === 'string' && SOCKET_ACT
632
646
  * it stand still across a whole day of sales; order by `lastMovementAt`, or do
633
647
  * not order these frames at all.
634
648
  *
635
- * ⚠️ Neither name is a DynamoDB reserved word, so the joined projection needs
636
- * no `ExpressionAttributeNames` alias. Adding one that IS reserved (`status`,
637
- * `size`, `name`, …) breaks every read at once — alias it at the join site.
649
+ * ⚠️ The api aliases `disabled` at the join site (`#disabled`) by convention —
650
+ * it is NOT on DynamoDB's reserved list (`DISABLE` is), but the alias costs
651
+ * nothing and keeps the join site the one place a name is aliased. A member
652
+ * that IS reserved (`status`, `size`, `name`, …) must be aliased there too, or
653
+ * it breaks every read at once. It is carried, like `hiddenFromStorefront`, so the shopper
654
+ * fan-out can turn a stock movement on a disabled product into a
655
+ * {@link ProductRemovedFrameData} marker instead of a priced patch.
638
656
  */
639
657
  export const PRODUCT_STOCK_FRAME_FIELDS = [
640
658
  'stock',
@@ -642,6 +660,7 @@ export const PRODUCT_STOCK_FRAME_FIELDS = [
642
660
  'cost',
643
661
  'currency',
644
662
  'hiddenFromStorefront',
663
+ 'disabled',
645
664
  'updatedAt',
646
665
  'lastMovementAt',
647
666
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sinfactura-types",
3
- "version": "1.10.488",
3
+ "version": "1.10.489",
4
4
  "description": "Shared wire and entity contracts for the SINFACTURA platform.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",