platform-types 1.10.762 → 1.10.764
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/ai.d.ts +2 -174
- package/dist/audit.d.ts +2 -1
- package/dist/cjs/index.js +0 -1
- package/dist/cjs/kitRecipe.js +1 -2
- package/dist/cjs/order.js +3 -3
- package/dist/cjs/product.js +13 -1
- package/dist/cjs/socket.js +0 -7
- package/dist/cjs/subscription.js +1 -3
- package/dist/cjs/wire.js +1 -3
- package/dist/collection.d.ts +2 -1
- package/dist/customer.d.ts +2 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/kitRecipe.d.ts +1 -2
- package/dist/kitRecipe.js +1 -2
- package/dist/maintenance.d.ts +4 -9
- package/dist/notification.d.ts +3 -5
- package/dist/order.d.ts +3 -3
- package/dist/order.js +3 -3
- package/dist/platform.d.ts +2 -5
- package/dist/product.d.ts +63 -4
- package/dist/product.js +12 -0
- package/dist/reminder.d.ts +5 -4
- package/dist/socket.d.ts +1 -1
- package/dist/socket.js +0 -7
- package/dist/store.d.ts +5 -19
- package/dist/storefrontDesign.d.ts +3 -2
- package/dist/subscription.d.ts +3 -3
- package/dist/subscription.js +1 -3
- package/dist/wire.d.ts +0 -4
- package/dist/wire.js +0 -2
- package/package.json +1 -1
- package/dist/cjs/whatsapp.js +0 -70
- package/dist/whatsapp.d.ts +0 -148
- package/dist/whatsapp.js +0 -67
package/dist/ai.d.ts
CHANGED
|
@@ -621,184 +621,12 @@ declare global {
|
|
|
621
621
|
/** Email body: trimmed, non-empty, within the send path's body bound. */
|
|
622
622
|
body: string;
|
|
623
623
|
}
|
|
624
|
-
interface WhatsAppOrderDraftRequest {
|
|
625
|
-
/** Meta's message id of an INBOUND message this store received. The server re-reads its text. */
|
|
626
|
-
messageId: string;
|
|
627
|
-
/** `CUST` + 6–10 digits. Prices the draft at the list a cart prices this customer at (a missing, 0 or deleted list is PUBLICO 1); absent → the store default. */
|
|
628
|
-
customerId?: string;
|
|
629
|
-
}
|
|
630
|
-
/**
|
|
631
|
-
* One product a parsed item could be. Every field but `score` is read off the
|
|
632
|
-
* store's own product row and priced by the server — never model output.
|
|
633
|
-
*/
|
|
634
|
-
interface WhatsAppOrderDraftMatch {
|
|
635
|
-
productId: string;
|
|
636
|
-
sku: string;
|
|
637
|
-
name: string;
|
|
638
|
-
/** Unit price at the customer's list, in `currency`. Indicative: the order create path re-prices. */
|
|
639
|
-
amount: number;
|
|
640
|
-
currency: string;
|
|
641
|
-
/** Token-overlap similarity of the item phrase and the product name, 0–1. Best first. */
|
|
642
|
-
score: number;
|
|
643
|
-
}
|
|
644
|
-
interface WhatsAppOrderDraftItem {
|
|
645
|
-
/** The product as the model read it from the message, at most 120 characters. Display it, never parse it. */
|
|
646
|
-
text: string;
|
|
647
|
-
/** A whole number of units, 1–999, or `null` when the model's reading was not one — never guessed. */
|
|
648
|
-
quantity: number | null;
|
|
649
|
-
/** The model's own confidence in this item, 0–1. */
|
|
650
|
-
confidence: number;
|
|
651
|
-
/** At most three, best first. Empty when nothing sellable matched. */
|
|
652
|
-
matches: WhatsAppOrderDraftMatch[];
|
|
653
|
-
/** The first match is close enough to stand as the line without a person choosing. */
|
|
654
|
-
matched: boolean;
|
|
655
|
-
}
|
|
656
|
-
/**
|
|
657
|
-
* Why a person must take the conversation over, in this order:
|
|
658
|
-
* - `requested` — the customer asked to talk to someone.
|
|
659
|
-
* - `not_an_order` — the message asks for no products.
|
|
660
|
-
* - `no_items` — it reads as an order, but no product could be picked out.
|
|
661
|
-
* - `low_confidence` — the model is below 0.7 on at least one item.
|
|
662
|
-
* - `invalid_quantity` — at least one item's quantity is `null`.
|
|
663
|
-
* - `no_match` — nothing sellable matched at least one item.
|
|
664
|
-
* - `weak_match` — at least one item has matches, none close enough to stand alone.
|
|
665
|
-
*/
|
|
666
|
-
type WhatsAppOrderDraftHandoffReason = 'requested' | 'not_an_order' | 'no_items' | 'low_confidence' | 'invalid_quantity' | 'no_match' | 'weak_match';
|
|
667
|
-
/**
|
|
668
|
-
* `data` payload of the success envelope. ⚠️ A DRAFT: nothing was placed,
|
|
669
|
-
* reserved or sent. Every draft still needs a staff member to place the
|
|
670
|
-
* order; `handoff.needed` says one must also talk to the customer.
|
|
671
|
-
*/
|
|
672
|
-
interface WhatsAppOrderDraftResponse {
|
|
673
|
-
messageId: string;
|
|
674
|
-
intent: 'order' | 'human' | 'other';
|
|
675
|
-
items: WhatsAppOrderDraftItem[];
|
|
676
|
-
handoff: {
|
|
677
|
-
needed: boolean;
|
|
678
|
-
reasons: WhatsAppOrderDraftHandoffReason[];
|
|
679
|
-
};
|
|
680
|
-
/** More than 10 items were read; the rest were dropped. */
|
|
681
|
-
truncated: boolean;
|
|
682
|
-
/** The model that read the message. */
|
|
683
|
-
model: string;
|
|
684
|
-
/** Echoed when sent. */
|
|
685
|
-
customerId?: string;
|
|
686
|
-
}
|
|
687
|
-
/**
|
|
688
|
-
* The `error` codes this endpoint answers, beyond `GatingErrorCode`
|
|
689
|
-
* (`PLAN_UPGRADE_REQUIRED` for `aiFeatures` or `whatsappCommerce`,
|
|
690
|
-
* `IMPERSONATION_READONLY`).
|
|
691
|
-
*
|
|
692
|
-
* FREE — no model call was made:
|
|
693
|
-
* - `VALIDATION_FAILED` · 400.
|
|
694
|
-
* - `AI_OPT_OUT` · 403 — AI is off for this store, or its state could not be read.
|
|
695
|
-
* - `WHATSAPP_MESSAGE_NOT_FOUND` · 404 — no INBOUND message of this store has that id.
|
|
696
|
-
* - `WHATSAPP_MESSAGE_NOT_TEXT` · 422 — the message has no text (a photo, a sticker).
|
|
697
|
-
* - `WHATSAPP_ORDER_DRAFT_MESSAGE_TOO_LONG` · 422 — over 1000 characters.
|
|
698
|
-
* - `CUSTOMER_NOT_FOUND` · 404 — `customerId` names no active customer of this store.
|
|
699
|
-
* - `COST_CEILING_EXCEEDED` · 403 or 503 — see `AiCostCeilingRefusal`.
|
|
700
|
-
* - `AI_WHATSAPP_ORDER_DRAFT_DISABLED` · 503 — the platform kill-switch for
|
|
701
|
-
* this feature is off. Distinct from a ceiling: nothing was spent and no
|
|
702
|
-
* budget is exhausted. Like `AI_OPT_OUT`, it is checked AFTER the stored
|
|
703
|
-
* draft is read, so a message that already has a `ready` draft is still
|
|
704
|
-
* answered with it (200, no spend) while the switch is off. The automatic
|
|
705
|
-
* worker checks it before it claims the message and skips it — no draft
|
|
706
|
-
* row, no frame — so the message stays undrafted until a staff `POST`.
|
|
707
|
-
* - `AI_UNAVAILABLE` · 503 — the platform could not make the model call at
|
|
708
|
-
* all (a server-side fault, the same code on every AI endpoint). Nothing
|
|
709
|
-
* was sent or spent; the message's claim is settled `failed`, so a later
|
|
710
|
-
* `POST` drafts it. The automatic worker writes no draft row for it at all
|
|
711
|
-
* and retries the message itself.
|
|
712
|
-
* - `WHATSAPP_ORDER_DRAFT_PENDING` · 409 — the message is being drafted right
|
|
713
|
-
* now (by the automatic worker or another request); carries
|
|
714
|
-
* `status: 'pending'`. Wait for the `whatsapp-order-draft` frame or retry.
|
|
715
|
-
* A `pending` claim older than 60 s is dead (its invocation timed out
|
|
716
|
-
* before settling) and the next `POST` takes it over instead.
|
|
717
|
-
*
|
|
718
|
-
* A `POST` for a message that already has a `ready` stored draft answers
|
|
719
|
-
* that draft (200) and spends nothing; only an absent, `failed` or stale one is
|
|
720
|
-
* drafted again. A `failed` draft whose call was METERED (below) is spent on
|
|
721
|
-
* a second time when a `POST` retries it — the worker never does.
|
|
722
|
-
*
|
|
723
|
-
* METERED — the call ran and its output was refused:
|
|
724
|
-
* - `WHATSAPP_ORDER_DRAFT_BLOCKED` · 422 — the guardrail refused; carries `reason`
|
|
725
|
-
* (filter type names only).
|
|
726
|
-
* - `WHATSAPP_ORDER_DRAFT_GENERATION_FAILED` · 502 — the output did not parse.
|
|
727
|
-
*/
|
|
728
|
-
type WhatsAppOrderDraftErrorCode = 'VALIDATION_FAILED' | 'AI_OPT_OUT' | 'WHATSAPP_MESSAGE_NOT_FOUND' | 'WHATSAPP_MESSAGE_NOT_TEXT' | 'WHATSAPP_ORDER_DRAFT_MESSAGE_TOO_LONG' | 'CUSTOMER_NOT_FOUND' | 'COST_CEILING_EXCEEDED' | 'AI_WHATSAPP_ORDER_DRAFT_DISABLED' | 'AI_UNAVAILABLE' | 'WHATSAPP_ORDER_DRAFT_PENDING' | 'WHATSAPP_ORDER_DRAFT_BLOCKED' | 'WHATSAPP_ORDER_DRAFT_GENERATION_FAILED';
|
|
729
|
-
/**
|
|
730
|
-
* The one stored draft of a message — built by the automatic worker when
|
|
731
|
-
* the message arrived (stores with `config.whatsappOrderAutoDraft` on) or
|
|
732
|
-
* by a staff `POST /whatsapp/order-draft`. Read at `GET
|
|
733
|
-
* /whatsapp/order-draft?messageId=`. The worker pushes it as the
|
|
734
|
-
* `whatsapp-order-draft` frame when it settles, through `wsPostStore` with
|
|
735
|
-
* `audience: 'operator'` — the store's operator sockets, never the
|
|
736
|
-
* customer's. Kept as long as the message it reads (90 days).
|
|
737
|
-
*
|
|
738
|
-
* - `pending` — being drafted; no `draft`, no `error`.
|
|
739
|
-
* - `ready` — `draft` is set. Still a DRAFT: staff place the order.
|
|
740
|
-
* - `failed` — `error` is set, one of `WhatsAppOrderDraftErrorCode` or
|
|
741
|
-
* `WHATSAPP_ORDER_DRAFT_FAILED` for an unexpected fault. The worker never
|
|
742
|
-
* retries it; a staff `POST` does.
|
|
743
|
-
*/
|
|
744
|
-
interface WhatsAppStoredOrderDraft {
|
|
745
|
-
messageId: string;
|
|
746
|
-
status: 'pending' | 'ready' | 'failed';
|
|
747
|
-
draft?: WhatsAppOrderDraftResponse;
|
|
748
|
-
error?: string;
|
|
749
|
-
/** Epoch ms. */
|
|
750
|
-
createdAt: number;
|
|
751
|
-
/** Epoch ms. */
|
|
752
|
-
updatedAt: number;
|
|
753
|
-
}
|
|
754
|
-
/** Staff sends a priced quote to the sender of one stored inbound WhatsApp message. No AI spend. */
|
|
755
|
-
interface WhatsAppOrderConfirmationRequest {
|
|
756
|
-
messageId: string;
|
|
757
|
-
presupuestoId: string;
|
|
758
|
-
paymentMethod?: number;
|
|
759
|
-
deliveryMethod?: number;
|
|
760
|
-
}
|
|
761
|
-
type WhatsAppOrderConfirmationStatus = 'sending' | 'awaiting' | 'confirming' | 'confirmed' | 'cancelled' | 'changes_requested' | 'expired' | 'superseded' | 'failed';
|
|
762
|
-
/**
|
|
763
|
-
* Public confirmation returned by POST /whatsapp/order-draft/confirmation and
|
|
764
|
-
* emitted to operator sockets. The private nonce and sender number never reach
|
|
765
|
-
* this shape. An accepted staff-authored quote is converted through the existing
|
|
766
|
-
* atomic order service; an AI parse cannot create an order.
|
|
767
|
-
*/
|
|
768
|
-
interface WhatsAppOrderConfirmation {
|
|
769
|
-
messageId: string;
|
|
770
|
-
presupuestoId: string;
|
|
771
|
-
status: WhatsAppOrderConfirmationStatus;
|
|
772
|
-
customerId: string;
|
|
773
|
-
paymentMethod?: number;
|
|
774
|
-
deliveryMethod?: number;
|
|
775
|
-
sentBy: {
|
|
776
|
-
userId: string;
|
|
777
|
-
fullName: string;
|
|
778
|
-
};
|
|
779
|
-
/** Epoch ms; the earlier of the quote expiry and 24 hours after sending. */
|
|
780
|
-
expiresAt: number;
|
|
781
|
-
sentMessageId?: string;
|
|
782
|
-
orderId?: string;
|
|
783
|
-
/** A stable refusal code, never a raw provider message or customer text. */
|
|
784
|
-
error?: string;
|
|
785
|
-
createdAt: number;
|
|
786
|
-
updatedAt: number;
|
|
787
|
-
}
|
|
788
|
-
/**
|
|
789
|
-
* Route refusals in addition to the existing entitlement/impersonation codes.
|
|
790
|
-
* `…_DISABLED` (503) is the `whatsappOrderConfirmationEnabled` platform switch;
|
|
791
|
-
* `…_RECIPIENT_MISMATCH` (409) is a quote whose customer phone is not the
|
|
792
|
-
* source message's sender; `…_SETTLED` (409) carries the final confirmation
|
|
793
|
-
* in `data` (confirmed, cancelled, superseded, or failed after the tap).
|
|
794
|
-
*/
|
|
795
|
-
type WhatsAppOrderConfirmationErrorCode = 'VALIDATION_FAILED' | 'ADMIN_REQUIRED' | 'WHATSAPP_MESSAGE_NOT_FOUND' | 'PRESUPUESTO_NOT_FOUND' | 'PRESUPUESTO_NOT_MUTABLE' | 'CUSTOMER_NOT_FOUND' | 'PAYMENT_METHOD_NOT_FOUND' | 'DELIVERY_METHOD_NOT_FOUND' | 'WHATSAPP_WINDOW_CLOSED' | 'WHATSAPP_ORDER_CONFIRMATION_DISABLED' | 'WHATSAPP_ORDER_CONFIRMATION_RECIPIENT_MISMATCH' | 'WHATSAPP_ORDER_CONFIRMATION_PENDING' | 'WHATSAPP_ORDER_CONFIRMATION_SETTLED' | 'PLATFORM_INTEGRATION_DISABLED' | 'WHATSAPP_NOT_CONNECTED' | 'WHATSAPP_RECIPIENT_NOT_ALLOWED' | 'WHATSAPP_SEND_UNCONFIRMED' | 'WHATSAPP_SEND_FAILED' | 'WHATSAPP_TEMPLATE_NOT_APPROVED' | 'WHATSAPP_RECIPIENT_OPTED_OUT' | 'WHATSAPP_RATE_LIMITED' | 'WHATSAPP_ACCOUNT_SUSPENDED' | 'WHATSAPP_TOKEN_REJECTED';
|
|
796
624
|
/**
|
|
797
625
|
* The ONE spent-budget refusal every AI spend route answers —
|
|
798
626
|
* `POST /products/enrich`, `/reports/narrative`, `/marketing/copy`,
|
|
799
627
|
* `/reminders/draft`, `/suppliers/doc-extract`,
|
|
800
|
-
* `/suppliers/price-list-extract
|
|
801
|
-
*
|
|
628
|
+
* `/suppliers/price-list-extract` and `/presupuestos/draft`, and any AI route
|
|
629
|
+
* added later. There is no second spelling and no 429 for it.
|
|
802
630
|
*
|
|
803
631
|
* - 403 — the TENANT's own ceiling. Carries `feature`, `upsell` and `period`.
|
|
804
632
|
* `upsell` is true only for `monthly`: a daily tenant ceiling is one
|
package/dist/audit.d.ts
CHANGED
|
@@ -58,7 +58,8 @@ declare global {
|
|
|
58
58
|
*
|
|
59
59
|
* - `operator` — a store user acting through the App. Actor is that user.
|
|
60
60
|
* - `platform` — a MANAGER acting through `/platform/*`. Actor is that user.
|
|
61
|
-
* - `customer` — a web
|
|
61
|
+
* - `customer` — a web or storefront customer (older rows also carry ones who
|
|
62
|
+
* ordered through the since-removed WhatsApp checkout). Actor is the
|
|
62
63
|
* `CUST…` id with `fullName: ''` ALWAYS: an `AUDIT#` row has no TTL and is
|
|
63
64
|
* not reached by erasure, so a stored customer name could never be erased.
|
|
64
65
|
* Render the name from the live customer row.
|
package/dist/cjs/index.js
CHANGED
|
@@ -122,7 +122,6 @@ __exportStar(require("./userActivity.js"), exports);
|
|
|
122
122
|
__exportStar(require("./valuation.js"), exports);
|
|
123
123
|
__exportStar(require("./webhook.js"), exports);
|
|
124
124
|
__exportStar(require("./wire.js"), exports);
|
|
125
|
-
__exportStar(require("./whatsapp.js"), exports);
|
|
126
125
|
__exportStar(require("./workItem.js"), exports);
|
|
127
126
|
__exportStar(require("./zone.js"), exports);
|
|
128
127
|
__exportStar(require("./provinces.js"), exports);
|
package/dist/cjs/kitRecipe.js
CHANGED
|
@@ -28,8 +28,7 @@ const product_ts_1 = require("./product.js");
|
|
|
28
28
|
*
|
|
29
29
|
* - `counter` — the operator basket and `POST /orders`, which the app's POS and
|
|
30
30
|
* the mobile app share;
|
|
31
|
-
* - `storefront` — the shopper cart and the web checkout.
|
|
32
|
-
* and order drafts still leave kits out.
|
|
31
|
+
* - `storefront` — the shopper cart and the web checkout.
|
|
33
32
|
*/
|
|
34
33
|
exports.KIT_SALE_CHANNELS = ['counter', 'storefront'];
|
|
35
34
|
/**
|
package/dist/cjs/order.js
CHANGED
|
@@ -364,14 +364,14 @@ exports.orderFulfilmentProgress = orderFulfilmentProgress;
|
|
|
364
364
|
* `data.shiftId`. Logged; reconcile the queued sale by hand.
|
|
365
365
|
* - `ORDER_CURRENCY_NOT_SUBSCRIBED` · 400 — the sale's currency has no
|
|
366
366
|
* subscription in the store's `currencies`. Logged.
|
|
367
|
-
* - `PAYMENT_METHODS_NOT_CONFIGURED` · 409 — `tenders` sent, or storefront
|
|
368
|
-
*
|
|
367
|
+
* - `PAYMENT_METHODS_NOT_CONFIGURED` · 409 — `tenders` sent, or storefront
|
|
368
|
+
* checkout attempted, while the store has no payment methods at
|
|
369
369
|
* all. Storefront checkout carries `data: {}` and refuses before the cart read.
|
|
370
370
|
* - `PAYMENT_METHOD_NOT_FOUND` · 400 — a tender leg's `method`, or storefront
|
|
371
371
|
* checkout's `paymentMethod`, names none of the store's payment methods.
|
|
372
372
|
* Storefront checkout carries `data: {}` and refuses before the cart read.
|
|
373
373
|
*
|
|
374
|
-
* Storefront
|
|
374
|
+
* Storefront checkout business refusals. None allocates an order
|
|
375
375
|
* id, redeems a coupon or writes an order; none is logged as an error:
|
|
376
376
|
* - `DELIVERY_METHOD_NOT_FOUND` · 400 — `deliveryMethod` is not in the store's
|
|
377
377
|
* delivery catalogue, including an absent/empty catalogue. `data: {}`;
|
package/dist/cjs/product.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PRODUCT_MEDIA_INVALID_REASONS = exports.MAX_PRODUCT_PICTURE_ALT_CHARS = exports.PRODUCT_UPSERT_ERROR_CODES = exports.PRODUCT_UPSERT_ROW_ERROR_CODES = exports.PRODUCT_UPSERT_ROW_CAP = exports.PUBLIC_PRODUCT_BY_SLUG_ERROR_CODES = exports.PRODUCT_PUBLISH_OVERDUE_AFTER_MS = exports.PRODUCT_PUBLISH_AT_MAX_AHEAD_MS = exports.PRODUCT_POST_ERROR_CODES = exports.PRODUCT_IDENTITY_ERROR_CODES = exports.PRODUCT_EXPORT_ERROR_CODES = exports.PRODUCT_CATALOG_EXPORT_COLUMNS = exports.MAX_BASE_QUANTITY = exports.BASE_QUANTITY_DECIMAL_PLACES = void 0;
|
|
3
|
+
exports.PRODUCT_MEDIA_INVALID_REASONS = exports.MAX_PRODUCT_PICTURE_ALT_CHARS = exports.PRODUCT_UPSERT_ERROR_CODES = exports.PRODUCT_UPSERT_ROW_ERROR_CODES = exports.PRODUCT_UPSERT_ROW_CAP = exports.PUBLIC_PRODUCT_SUGGEST_ERROR_CODES = exports.PUBLIC_PRODUCT_BY_SLUG_ERROR_CODES = exports.PRODUCT_PUBLISH_OVERDUE_AFTER_MS = exports.PRODUCT_PUBLISH_AT_MAX_AHEAD_MS = exports.PRODUCT_POST_ERROR_CODES = exports.PRODUCT_IDENTITY_ERROR_CODES = exports.PRODUCT_EXPORT_ERROR_CODES = exports.PRODUCT_CATALOG_EXPORT_COLUMNS = exports.DISCOVERY_SORTS = exports.MAX_BASE_QUANTITY = exports.BASE_QUANTITY_DECIMAL_PLACES = void 0;
|
|
4
4
|
/** Maximum decimal places in a canonical base quantity; inputs are exact, never rounded. */
|
|
5
5
|
exports.BASE_QUANTITY_DECIMAL_PLACES = 6;
|
|
6
6
|
/** Absolute base-quantity input bound; signed adjustments admit the negative of this value. */
|
|
7
7
|
exports.MAX_BASE_QUANTITY = 1_000_000;
|
|
8
|
+
/**
|
|
9
|
+
* The `sort` values Web `GET /products?mode=discover` serves. `newest` is
|
|
10
|
+
* descending product id; name and price sorts are not served (no index can
|
|
11
|
+
* order them inside one bounded request).
|
|
12
|
+
*/
|
|
13
|
+
exports.DISCOVERY_SORTS = ['newest'];
|
|
8
14
|
/**
|
|
9
15
|
* The CSV header of `GET /products?mode=export`, in file order.
|
|
10
16
|
*
|
|
@@ -161,6 +167,12 @@ exports.PUBLIC_PRODUCT_BY_SLUG_ERROR_CODES = [
|
|
|
161
167
|
'PRODUCT_NOT_FOUND',
|
|
162
168
|
'PRODUCT_LOOKUP_INCOMPLETE',
|
|
163
169
|
];
|
|
170
|
+
/** Refusals of Web `GET /products?mode=suggest`: 400, 400, 503. */
|
|
171
|
+
exports.PUBLIC_PRODUCT_SUGGEST_ERROR_CODES = [
|
|
172
|
+
'VALIDATION_FAILED',
|
|
173
|
+
'INVALID_SUGGEST_QUERY',
|
|
174
|
+
'PRODUCT_LOOKUP_INCOMPLETE',
|
|
175
|
+
];
|
|
164
176
|
/** Rows one `POST /products { mode: 'upsert' }` request takes; a longer file is sent in chunks. */
|
|
165
177
|
exports.PRODUCT_UPSERT_ROW_CAP = 200;
|
|
166
178
|
/**
|
package/dist/cjs/socket.js
CHANGED
|
@@ -501,13 +501,6 @@ exports.SOCKET_ACTIONS = [
|
|
|
501
501
|
// Notifications & messaging.
|
|
502
502
|
'notifications',
|
|
503
503
|
'support-message',
|
|
504
|
-
/**
|
|
505
|
-
* An automatic WhatsApp order draft settled (`ready` or `failed`). The
|
|
506
|
-
* operator sockets of the store only; `data` is a `WhatsAppStoredOrderDraft`.
|
|
507
|
-
*/
|
|
508
|
-
'whatsapp-order-draft',
|
|
509
|
-
/** Staff quote confirmation state; operator audience only, data: WhatsAppOrderConfirmation. */
|
|
510
|
-
'whatsapp-order-confirmation',
|
|
511
504
|
// Payments & providers.
|
|
512
505
|
'payment_received',
|
|
513
506
|
// Operator-only observation invalidation; never a receipt or customer frame.
|
package/dist/cjs/subscription.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* - Feature keys now match the BE wire format directly (renamed afip→afipInvoicing,
|
|
26
26
|
* cash→cashManagement, reportsAdvanced→advancedReports as of 2026-04-26). The interim
|
|
27
27
|
* paymentIntegrations key was split into domesticPayments + stripePayments.
|
|
28
|
-
* New keys
|
|
28
|
+
* New keys aiFeatures/mobileApp/customDomain are
|
|
29
29
|
* declared here even when their epics haven't shipped — the matrix can set
|
|
30
30
|
* enabled:false until they do.
|
|
31
31
|
*/
|
|
@@ -113,7 +113,6 @@ exports.FEATURE_KEYS = [
|
|
|
113
113
|
'importExport',
|
|
114
114
|
'domesticPayments',
|
|
115
115
|
'stripePayments',
|
|
116
|
-
'whatsappCommerce',
|
|
117
116
|
'aiFeatures',
|
|
118
117
|
'mobileApp',
|
|
119
118
|
'customBranding',
|
|
@@ -133,5 +132,4 @@ exports.FEATURE_KEYS = [
|
|
|
133
132
|
'webhooks',
|
|
134
133
|
'maxOrdersMonth',
|
|
135
134
|
'maxInvoicesMonth',
|
|
136
|
-
'whatsappMessages',
|
|
137
135
|
];
|
package/dist/cjs/wire.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* describes the result in the same edit.
|
|
19
19
|
*/
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.ROW_TTL_KEYS = exports.USER_TOTP_INTERNAL_KEYS = exports.STORE_TIENDANUBE_SECRET_KEYS = exports.
|
|
21
|
+
exports.ROW_TTL_KEYS = exports.USER_TOTP_INTERNAL_KEYS = exports.STORE_TIENDANUBE_SECRET_KEYS = exports.STORE_MERCADOLIBRE_SECRET_KEYS = exports.STORE_GMAIL_SECRET_KEYS = exports.STORE_MP_SECRET_KEYS = exports.STORE_AFIP_SECRET_KEYS = exports.RESPONSE_STRIPPED_KEYS = void 0;
|
|
22
22
|
/**
|
|
23
23
|
* The seven keys `response()` deletes from `body.data`.
|
|
24
24
|
*
|
|
@@ -67,8 +67,6 @@ exports.STORE_MERCADOLIBRE_SECRET_KEYS = [
|
|
|
67
67
|
'refreshTokenEncrypted',
|
|
68
68
|
'refreshAttemptAt',
|
|
69
69
|
];
|
|
70
|
-
/** WhatsApp's only secret field on `Store.integrations.whatsapp`. */
|
|
71
|
-
exports.STORE_WHATSAPP_SECRET_KEYS = ['accessToken'];
|
|
72
70
|
/**
|
|
73
71
|
* KMS-ciphertext TiendaNube OAuth credential on `Store.integrations.tiendanube`.
|
|
74
72
|
* A single `accessTokenEncrypted` — TiendaNube issues no refresh token, so there
|
package/dist/collection.d.ts
CHANGED
|
@@ -28,7 +28,8 @@ declare global {
|
|
|
28
28
|
* nothing with it and list everything the rest selects. `inOffer` and
|
|
29
29
|
* `inStock` are the string `'true'`, as on that read.
|
|
30
30
|
*/
|
|
31
|
-
|
|
31
|
+
/** A stored discovery query: the filters only — never `sort` (a collection answers in discovery order). */
|
|
32
|
+
type CollectionQuery = Omit<PublicProductDiscoverInput, 'mode' | 'startKey' | 'sort'>;
|
|
32
33
|
interface Collection {
|
|
33
34
|
storeId: string;
|
|
34
35
|
/** `COL` + at least six digits, minted by the api. */
|
package/dist/customer.d.ts
CHANGED
|
@@ -420,8 +420,8 @@ declare global {
|
|
|
420
420
|
* already makes on this row.
|
|
421
421
|
*
|
|
422
422
|
* ⚠️ Fed ONLY by a `ReminderRecord` with `kind: 'reminder'` — a delivered
|
|
423
|
-
* collections chase on ANY channel (the email leg or the
|
|
424
|
-
* WhatsApp leg), so
|
|
423
|
+
* collections chase on ANY channel (the email leg, or on older rows the
|
|
424
|
+
* since-removed WhatsApp leg), so every leg shared one cooldown. It is absent on a
|
|
425
425
|
* customer who was never chased, and that is correct rather than missing:
|
|
426
426
|
* populating it from transactional mail would read as "already chased" to
|
|
427
427
|
* a collections operator who would then skip a debtor.
|
package/dist/index.d.ts
CHANGED
|
@@ -98,7 +98,6 @@ export * from './userActivity.ts';
|
|
|
98
98
|
export * from './valuation.ts';
|
|
99
99
|
export * from './webhook.ts';
|
|
100
100
|
export * from './wire.ts';
|
|
101
|
-
export * from './whatsapp.ts';
|
|
102
101
|
export * from './workItem.ts';
|
|
103
102
|
export * from './zone.ts';
|
|
104
103
|
export * from './provinces.ts';
|
package/dist/index.js
CHANGED
|
@@ -106,7 +106,6 @@ export * from "./userActivity.js";
|
|
|
106
106
|
export * from "./valuation.js";
|
|
107
107
|
export * from "./webhook.js";
|
|
108
108
|
export * from "./wire.js";
|
|
109
|
-
export * from "./whatsapp.js";
|
|
110
109
|
export * from "./workItem.js";
|
|
111
110
|
export * from "./zone.js";
|
|
112
111
|
export * from "./provinces.js";
|
package/dist/kitRecipe.d.ts
CHANGED
|
@@ -24,8 +24,7 @@
|
|
|
24
24
|
*
|
|
25
25
|
* - `counter` — the operator basket and `POST /orders`, which the app's POS and
|
|
26
26
|
* the mobile app share;
|
|
27
|
-
* - `storefront` — the shopper cart and the web checkout.
|
|
28
|
-
* and order drafts still leave kits out.
|
|
27
|
+
* - `storefront` — the shopper cart and the web checkout.
|
|
29
28
|
*/
|
|
30
29
|
export declare const KIT_SALE_CHANNELS: readonly ["counter", "storefront"];
|
|
31
30
|
/**
|
package/dist/kitRecipe.js
CHANGED
|
@@ -25,8 +25,7 @@ import { MAX_BASE_QUANTITY } from "./product.js";
|
|
|
25
25
|
*
|
|
26
26
|
* - `counter` — the operator basket and `POST /orders`, which the app's POS and
|
|
27
27
|
* the mobile app share;
|
|
28
|
-
* - `storefront` — the shopper cart and the web checkout.
|
|
29
|
-
* and order drafts still leave kits out.
|
|
28
|
+
* - `storefront` — the shopper cart and the web checkout.
|
|
30
29
|
*/
|
|
31
30
|
export const KIT_SALE_CHANNELS = ['counter', 'storefront'];
|
|
32
31
|
/**
|
package/dist/maintenance.d.ts
CHANGED
|
@@ -18,15 +18,10 @@ declare global {
|
|
|
18
18
|
/**
|
|
19
19
|
* A channel a maintenance broadcast can actually leave the platform on.
|
|
20
20
|
*
|
|
21
|
-
* ⚠️ `'whatsapp'` is deliberately ABSENT
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* per message: a fleet-wide fan-out through it would be N inline Graph API
|
|
26
|
-
* calls inside one request, against a template that does not exist yet.
|
|
27
|
-
* Declaring the channel here before either is true would let a caller ask
|
|
28
|
-
* for a send this service cannot make and would have to refuse at runtime.
|
|
29
|
-
* Adding the member later is purely additive for every consumer.
|
|
21
|
+
* ⚠️ `'whatsapp'` is deliberately ABSENT: the platform has no WhatsApp send
|
|
22
|
+
* path, so declaring it would let a caller ask for a send this service cannot
|
|
23
|
+
* make and would have to refuse at runtime. Adding the member later is purely
|
|
24
|
+
* additive for every consumer.
|
|
30
25
|
*/
|
|
31
26
|
type MaintenanceBroadcastChannel = 'email' | 'sms';
|
|
32
27
|
/**
|
package/dist/notification.d.ts
CHANGED
|
@@ -341,13 +341,11 @@ declare global {
|
|
|
341
341
|
* What the outbound seam (`notify()`) knew about one call the moment its
|
|
342
342
|
* transport returned. It is never a delivery receipt: `enqueued` and
|
|
343
343
|
* `handed-off` say a queue or a sender took the message, and `sent` says the
|
|
344
|
-
* provider accepted it. Later SES events arrive through `EMAILEVENT
|
|
345
|
-
* WhatsApp status callbacks update the established `WHATSAPP#` history.
|
|
344
|
+
* provider accepted it. Later SES events arrive through `EMAILEVENT#`.
|
|
346
345
|
*/
|
|
347
346
|
type NotifyDeliveryOutcome = 'sent' | 'suppressed' | 'not-sent' | 'enqueued' | 'handed-off' | 'failed';
|
|
348
347
|
/** Why a channel did not deliver, including send-time preference refusals. */
|
|
349
348
|
type NotifyNotSentReason = 'skipped-by-preference' | 'demo' | 'suppressed' | 'refused';
|
|
350
|
-
type NotifyWhatsAppSuppressionReason = 'allowlist-missing' | 'recipient-malformed' | 'recipient-not-allowlisted';
|
|
351
349
|
/**
|
|
352
350
|
* A recorded transport outcome or send-time preference refusal — the
|
|
353
351
|
* wire half of the `NOTIFY#{storeId}` delivery row. The stored row,
|
|
@@ -362,14 +360,14 @@ declare global {
|
|
|
362
360
|
* `transport`, plus a count.
|
|
363
361
|
*/
|
|
364
362
|
interface NotifyDelivery {
|
|
365
|
-
transport: 'email' | 'queue' | 'ses' | 'ses-marketing' | 'push'
|
|
363
|
+
transport: 'email' | 'queue' | 'ses' | 'ses-marketing' | 'push';
|
|
366
364
|
/** The closed audience enum `notify()` accepts. */
|
|
367
365
|
audience: 'store-customer' | 'account-holder' | 'store-operator' | 'platform-staff' | 'marketing-recipient';
|
|
368
366
|
/** The producer's event name. Never recipient data. */
|
|
369
367
|
logTag: string;
|
|
370
368
|
outcome: NotifyDeliveryOutcome;
|
|
371
369
|
/** Only when `outcome` is `'not-sent'` or `'suppressed'`. */
|
|
372
|
-
reason?: NotifyNotSentReason
|
|
370
|
+
reason?: NotifyNotSentReason;
|
|
373
371
|
/** Provider channel for sent email; semantic channel for preference skips. */
|
|
374
372
|
channel?: 'gmail' | 'ses' | NotificationPreferenceChannel;
|
|
375
373
|
/** Only when SES returned one. The join key to `EMAILEVENT#`. */
|
package/dist/order.d.ts
CHANGED
|
@@ -2722,14 +2722,14 @@ export declare const orderFulfilmentProgress: (order: OrderFulfilmentProgressInp
|
|
|
2722
2722
|
* `data.shiftId`. Logged; reconcile the queued sale by hand.
|
|
2723
2723
|
* - `ORDER_CURRENCY_NOT_SUBSCRIBED` · 400 — the sale's currency has no
|
|
2724
2724
|
* subscription in the store's `currencies`. Logged.
|
|
2725
|
-
* - `PAYMENT_METHODS_NOT_CONFIGURED` · 409 — `tenders` sent, or storefront
|
|
2726
|
-
*
|
|
2725
|
+
* - `PAYMENT_METHODS_NOT_CONFIGURED` · 409 — `tenders` sent, or storefront
|
|
2726
|
+
* checkout attempted, while the store has no payment methods at
|
|
2727
2727
|
* all. Storefront checkout carries `data: {}` and refuses before the cart read.
|
|
2728
2728
|
* - `PAYMENT_METHOD_NOT_FOUND` · 400 — a tender leg's `method`, or storefront
|
|
2729
2729
|
* checkout's `paymentMethod`, names none of the store's payment methods.
|
|
2730
2730
|
* Storefront checkout carries `data: {}` and refuses before the cart read.
|
|
2731
2731
|
*
|
|
2732
|
-
* Storefront
|
|
2732
|
+
* Storefront checkout business refusals. None allocates an order
|
|
2733
2733
|
* id, redeems a coupon or writes an order; none is logged as an error:
|
|
2734
2734
|
* - `DELIVERY_METHOD_NOT_FOUND` · 400 — `deliveryMethod` is not in the store's
|
|
2735
2735
|
* delivery catalogue, including an absent/empty catalogue. `data: {}`;
|
package/dist/order.js
CHANGED
|
@@ -357,14 +357,14 @@ export const orderFulfilmentProgress = (order) => {
|
|
|
357
357
|
* `data.shiftId`. Logged; reconcile the queued sale by hand.
|
|
358
358
|
* - `ORDER_CURRENCY_NOT_SUBSCRIBED` · 400 — the sale's currency has no
|
|
359
359
|
* subscription in the store's `currencies`. Logged.
|
|
360
|
-
* - `PAYMENT_METHODS_NOT_CONFIGURED` · 409 — `tenders` sent, or storefront
|
|
361
|
-
*
|
|
360
|
+
* - `PAYMENT_METHODS_NOT_CONFIGURED` · 409 — `tenders` sent, or storefront
|
|
361
|
+
* checkout attempted, while the store has no payment methods at
|
|
362
362
|
* all. Storefront checkout carries `data: {}` and refuses before the cart read.
|
|
363
363
|
* - `PAYMENT_METHOD_NOT_FOUND` · 400 — a tender leg's `method`, or storefront
|
|
364
364
|
* checkout's `paymentMethod`, names none of the store's payment methods.
|
|
365
365
|
* Storefront checkout carries `data: {}` and refuses before the cart read.
|
|
366
366
|
*
|
|
367
|
-
* Storefront
|
|
367
|
+
* Storefront checkout business refusals. None allocates an order
|
|
368
368
|
* id, redeems a coupon or writes an order; none is logged as an error:
|
|
369
369
|
* - `DELIVERY_METHOD_NOT_FOUND` · 400 — `deliveryMethod` is not in the store's
|
|
370
370
|
* delivery catalogue, including an absent/empty catalogue. `data: {}`;
|
package/dist/platform.d.ts
CHANGED
|
@@ -88,8 +88,8 @@ export interface ReseedConstraintsOpBody extends PlatformOperatorReason {
|
|
|
88
88
|
*/
|
|
89
89
|
export interface RotateWebhookKeyOpBody extends PlatformOperatorReason {
|
|
90
90
|
mode: 'rotate-webhook-key';
|
|
91
|
-
provider: 'mercadopago' | 'stripe'
|
|
92
|
-
/** Required for `stripe`
|
|
91
|
+
provider: 'mercadopago' | 'stripe';
|
|
92
|
+
/** Required for `stripe` (provider-issued); optional override for `mercadopago`. Never echoed or audited. */
|
|
93
93
|
newSecret?: string;
|
|
94
94
|
/** Must equal `provider`. Required — absent or wrong is `400 CONFIRMATION_MISMATCH`. */
|
|
95
95
|
confirm: string;
|
|
@@ -460,9 +460,6 @@ export interface TenantHealthEnvelope {
|
|
|
460
460
|
connected: boolean;
|
|
461
461
|
oauthExpiresAt: number | null;
|
|
462
462
|
};
|
|
463
|
-
whatsapp: {
|
|
464
|
-
enabled: boolean;
|
|
465
|
-
};
|
|
466
463
|
sms: {
|
|
467
464
|
enabled: boolean;
|
|
468
465
|
};
|
package/dist/product.d.ts
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
export declare const BASE_QUANTITY_DECIMAL_PLACES = 6;
|
|
3
3
|
/** Absolute base-quantity input bound; signed adjustments admit the negative of this value. */
|
|
4
4
|
export declare const MAX_BASE_QUANTITY = 1000000;
|
|
5
|
+
/**
|
|
6
|
+
* The `sort` values Web `GET /products?mode=discover` serves. `newest` is
|
|
7
|
+
* descending product id; name and price sorts are not served (no index can
|
|
8
|
+
* order them inside one bounded request).
|
|
9
|
+
*/
|
|
10
|
+
export declare const DISCOVERY_SORTS: readonly ["newest"];
|
|
11
|
+
export type DiscoverySort = (typeof DISCOVERY_SORTS)[number];
|
|
5
12
|
declare global {
|
|
6
13
|
type ProductUnitsErrorCode = 'UNIT_REVISION_STALE' | 'UNIT_FACTOR_INVALID' | 'UNIT_FACTOR_MISMATCH' | 'UNIT_INCOMPATIBLE_DIMENSION' | 'UNIT_QUANTITY_UNREPRESENTABLE' | 'UNIT_QUANTITY_NOT_WHOLE';
|
|
7
14
|
type ProductUnit = 'each' | 'gram' | 'kilogram' | 'millilitre' | 'litre' | 'metre';
|
|
@@ -247,23 +254,72 @@ declare global {
|
|
|
247
254
|
* while no product carries it.
|
|
248
255
|
*/
|
|
249
256
|
tagId?: string;
|
|
250
|
-
/**
|
|
257
|
+
/**
|
|
258
|
+
* Only products on offer at the caller's own price: a promo window open now
|
|
259
|
+
* on the one price slot the caller is priced at (a guest's is the store
|
|
260
|
+
* default list). A promo on another list does not count.
|
|
261
|
+
*/
|
|
251
262
|
inOffer?: 'true';
|
|
252
263
|
/** Only products the online stock authority can sell now; services always pass. */
|
|
253
264
|
inStock?: 'true';
|
|
254
265
|
/** Only products explicitly marked as new; an absent flag does not pass. */
|
|
255
266
|
isNew?: 'true';
|
|
256
|
-
/**
|
|
267
|
+
/**
|
|
268
|
+
* A member of `DISCOVERY_SORTS`. `newest` = descending product id (mint
|
|
269
|
+
* order), on every filter combination. A well-formed value the api does not
|
|
270
|
+
* serve is 400 `DISCOVERY_SORT_UNSUPPORTED` ({@link DiscoverySortRefusal});
|
|
271
|
+
* one not matching `^[a-z_]{1,32}$` is 400 `INVALID_DISCOVERY_QUERY`. An
|
|
272
|
+
* empty value is absent. Bound into the cursor when present.
|
|
273
|
+
*/
|
|
274
|
+
sort?: string;
|
|
275
|
+
/** The previous response's `LastEvaluatedKey`, under the SAME filters and sort; else 400 INVALID_CURSOR. */
|
|
257
276
|
startKey?: string;
|
|
258
277
|
}
|
|
259
278
|
/** One page of a discovery walk; `data` can be empty while `LastEvaluatedKey` is set. */
|
|
260
279
|
interface PublicProductDiscoverResponse {
|
|
261
280
|
message: string;
|
|
262
|
-
/** Public price/projection and online stock, in index order. */
|
|
281
|
+
/** Public price/projection and online stock, in `sort` order, else index order. */
|
|
263
282
|
data: PublicProduct[];
|
|
283
|
+
/** The sort applied — present only when the request carried one. */
|
|
284
|
+
sort?: (typeof DISCOVERY_SORTS)[number];
|
|
264
285
|
/** Present while rows remain; absent means the walk is complete. */
|
|
265
286
|
LastEvaluatedKey?: string;
|
|
266
287
|
}
|
|
288
|
+
/** Anonymous Web GET /products typeahead; the tenant comes from the public store context. */
|
|
289
|
+
interface PublicProductSuggestInput {
|
|
290
|
+
mode: 'suggest';
|
|
291
|
+
/** Trimmed, 2–64 chars, at least one search term after the split; else 400 INVALID_SUGGEST_QUERY. */
|
|
292
|
+
q: string;
|
|
293
|
+
/** Integer 1–10, default 8; anything else 400 INVALID_SUGGEST_QUERY. */
|
|
294
|
+
limit?: string;
|
|
295
|
+
}
|
|
296
|
+
/** Why a suggestion matched; drives ranking and the storefront's highlight. */
|
|
297
|
+
type PublicProductSuggestMatch = 'barcode' | 'sku' | 'name' | 'text';
|
|
298
|
+
/** One typeahead row: identity and display only — never a price, stock or offer flag. */
|
|
299
|
+
type PublicProductSuggestion = Pick<PublicProduct, 'slug' | 'sku' | 'thumbnailUrl'> & {
|
|
300
|
+
productId: string;
|
|
301
|
+
name: string;
|
|
302
|
+
/** Why it matched; drives ranking and the storefront's highlight. */
|
|
303
|
+
match: PublicProductSuggestMatch;
|
|
304
|
+
};
|
|
305
|
+
interface PublicProductSuggestResponse {
|
|
306
|
+
message: string;
|
|
307
|
+
/** Ranked barcode > sku > name > text, ties newest first; never more than `limit`. No cursor. */
|
|
308
|
+
data: PublicProductSuggestion[];
|
|
309
|
+
/**
|
|
310
|
+
* Present when the text walk stopped with catalogue rows unread (page
|
|
311
|
+
* budget, the soft deadline or a full `limit`): a better match may exist.
|
|
312
|
+
*/
|
|
313
|
+
truncated?: true;
|
|
314
|
+
}
|
|
315
|
+
/** Refusals of Web `GET /products?mode=discover`. */
|
|
316
|
+
type DiscoveryErrorCode = 'INVALID_DISCOVERY_QUERY' | 'INVALID_CURSOR' | 'DISCOVERY_SORT_UNSUPPORTED';
|
|
317
|
+
/** 400 body for a well-formed `sort` the api does not serve; `supportedSorts` lists what it does. */
|
|
318
|
+
interface DiscoverySortRefusal {
|
|
319
|
+
message: string;
|
|
320
|
+
error: 'DISCOVERY_SORT_UNSUPPORTED';
|
|
321
|
+
supportedSorts: (typeof DISCOVERY_SORTS)[number][];
|
|
322
|
+
}
|
|
267
323
|
/** Write shape for product create/update — carries the transient picture-removal control. */
|
|
268
324
|
type ProductUpsertInput = Omit<Partial<Product>, 'pictures' | 'thumbnailUrl' | 'publishAt' | 'units' | 'unitRevisionGeneration'> & {
|
|
269
325
|
/** Omitted preserves the declaration; null clears it only when the product is unused. */
|
|
@@ -774,7 +830,7 @@ declare global {
|
|
|
774
830
|
/**
|
|
775
831
|
* Most units of this product ONE sale may carry, summed across every line of
|
|
776
832
|
* the operation. Enforced server-side on every local sale entry point
|
|
777
|
-
* (order create, storefront
|
|
833
|
+
* (order create, storefront checkout, presupuesto conversion,
|
|
778
834
|
* service delivery, and quantity-increasing edits), which refuse
|
|
779
835
|
* `409 PRODUCT_SALE_LIMIT_EXCEEDED` — see {@link ProductSaleLimitRefusal}.
|
|
780
836
|
*
|
|
@@ -1519,6 +1575,9 @@ export declare const PRODUCT_PUBLISH_OVERDUE_AFTER_MS: number;
|
|
|
1519
1575
|
*/
|
|
1520
1576
|
export declare const PUBLIC_PRODUCT_BY_SLUG_ERROR_CODES: readonly ["VALIDATION_FAILED", "INVALID_SLUG", "PRODUCT_NOT_FOUND", "PRODUCT_LOOKUP_INCOMPLETE"];
|
|
1521
1577
|
export type PublicProductBySlugErrorCode = (typeof PUBLIC_PRODUCT_BY_SLUG_ERROR_CODES)[number];
|
|
1578
|
+
/** Refusals of Web `GET /products?mode=suggest`: 400, 400, 503. */
|
|
1579
|
+
export declare const PUBLIC_PRODUCT_SUGGEST_ERROR_CODES: readonly ["VALIDATION_FAILED", "INVALID_SUGGEST_QUERY", "PRODUCT_LOOKUP_INCOMPLETE"];
|
|
1580
|
+
export type PublicProductSuggestErrorCode = (typeof PUBLIC_PRODUCT_SUGGEST_ERROR_CODES)[number];
|
|
1522
1581
|
/** Rows one `POST /products { mode: 'upsert' }` request takes; a longer file is sent in chunks. */
|
|
1523
1582
|
export declare const PRODUCT_UPSERT_ROW_CAP = 200;
|
|
1524
1583
|
/**
|
package/dist/product.js
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
export const BASE_QUANTITY_DECIMAL_PLACES = 6;
|
|
3
3
|
/** Absolute base-quantity input bound; signed adjustments admit the negative of this value. */
|
|
4
4
|
export const MAX_BASE_QUANTITY = 1_000_000;
|
|
5
|
+
/**
|
|
6
|
+
* The `sort` values Web `GET /products?mode=discover` serves. `newest` is
|
|
7
|
+
* descending product id; name and price sorts are not served (no index can
|
|
8
|
+
* order them inside one bounded request).
|
|
9
|
+
*/
|
|
10
|
+
export const DISCOVERY_SORTS = ['newest'];
|
|
5
11
|
/**
|
|
6
12
|
* The CSV header of `GET /products?mode=export`, in file order.
|
|
7
13
|
*
|
|
@@ -158,6 +164,12 @@ export const PUBLIC_PRODUCT_BY_SLUG_ERROR_CODES = [
|
|
|
158
164
|
'PRODUCT_NOT_FOUND',
|
|
159
165
|
'PRODUCT_LOOKUP_INCOMPLETE',
|
|
160
166
|
];
|
|
167
|
+
/** Refusals of Web `GET /products?mode=suggest`: 400, 400, 503. */
|
|
168
|
+
export const PUBLIC_PRODUCT_SUGGEST_ERROR_CODES = [
|
|
169
|
+
'VALIDATION_FAILED',
|
|
170
|
+
'INVALID_SUGGEST_QUERY',
|
|
171
|
+
'PRODUCT_LOOKUP_INCOMPLETE',
|
|
172
|
+
];
|
|
161
173
|
/** Rows one `POST /products { mode: 'upsert' }` request takes; a longer file is sent in chunks. */
|
|
162
174
|
export const PRODUCT_UPSERT_ROW_CAP = 200;
|
|
163
175
|
/**
|
package/dist/reminder.d.ts
CHANGED
|
@@ -2,10 +2,11 @@ declare global {
|
|
|
2
2
|
/**
|
|
3
3
|
* Which dispatcher actually delivered. Only the send helper knows this.
|
|
4
4
|
*
|
|
5
|
-
* `'whatsapp'` is
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* message went to, digits only, not an email
|
|
5
|
+
* ⚠️ `'whatsapp'` is HISTORY only. Nothing sends or records it any more, but the
|
|
6
|
+
* automatic payment reminder once had a WhatsApp leg, and the rows it wrote are
|
|
7
|
+
* durable and still read back in a customer's reminder history. On such a row
|
|
8
|
+
* `to` is the phone number the message went to, digits only, not an email
|
|
9
|
+
* address. Handle the member; never expect a new row to carry it.
|
|
9
10
|
*/
|
|
10
11
|
type ReminderChannel = 'gmail' | 'ses' | 'whatsapp';
|
|
11
12
|
/**
|
package/dist/socket.d.ts
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* A client must ignore actions it does not own rather than assume it
|
|
27
27
|
* receives all of them.
|
|
28
28
|
*/
|
|
29
|
-
export declare const SOCKET_ACTIONS: readonly ["account", "appointments", "appointmentWaitlist", "attendance", "attributes", "automation-rules", "baskets", "cart", "brands", "cash", "catalogOperation", "categories", "campaigns", "customers", "customerNote", "customerAddress", "customerContact", "deliveries", "globals", "inventory", "invoices", "literals", "loyalty", "orders", "presupuestos", "products", "promotions", "segments", "returns", "rma", "templates", "services", "service-templates", "shifts", "stores", "suppliers", "supplier-invoice", "support", "surveys", "users", "warehouses", "zones", "favorites", "webhooks", "account-delete", "baskets-delete", "cart-delete", "log-delete", "notifications", "support-message", "
|
|
29
|
+
export declare const SOCKET_ACTIONS: readonly ["account", "appointments", "appointmentWaitlist", "attendance", "attributes", "automation-rules", "baskets", "cart", "brands", "cash", "catalogOperation", "categories", "campaigns", "customers", "customerNote", "customerAddress", "customerContact", "deliveries", "globals", "inventory", "invoices", "literals", "loyalty", "orders", "presupuestos", "products", "promotions", "segments", "returns", "rma", "templates", "services", "service-templates", "shifts", "stores", "suppliers", "supplier-invoice", "support", "surveys", "users", "warehouses", "zones", "favorites", "webhooks", "account-delete", "baskets-delete", "cart-delete", "log-delete", "notifications", "support-message", "payment_received", "mp_payment_status_changed", "payment_linked", "payment_unlinked", "mercadopago", "mercadopago_dynamic_qr_created", "mercadopago_static_qr_created", "mp_hook_log_appended", "mp_ipn_log_appended", "orderPaymentAttempt", "paymentAttemptChanged", "stripe", "subscription", "caea", "print", "print-order", "print-invoice", "print-product", "print-tag", "print_job_failed", "request_printers", "printers_changed", "agent_status_changed", "print_rules_changed", "printers_active", "agent_command", "maintenance", "currency_auto_updated", "drain_progress", "integration_event_appended", "userActivityRecorded", "mercadolibre_settlement_period", "customDomain", "purchaseOrders", "cycleCounts", "stockTransfers", "workItems"];
|
|
30
30
|
/** Union of every server→client data-frame action. */
|
|
31
31
|
export type SocketAction = (typeof SOCKET_ACTIONS)[number];
|
|
32
32
|
/**
|
package/dist/socket.js
CHANGED
|
@@ -498,13 +498,6 @@ export const SOCKET_ACTIONS = [
|
|
|
498
498
|
// Notifications & messaging.
|
|
499
499
|
'notifications',
|
|
500
500
|
'support-message',
|
|
501
|
-
/**
|
|
502
|
-
* An automatic WhatsApp order draft settled (`ready` or `failed`). The
|
|
503
|
-
* operator sockets of the store only; `data` is a `WhatsAppStoredOrderDraft`.
|
|
504
|
-
*/
|
|
505
|
-
'whatsapp-order-draft',
|
|
506
|
-
/** Staff quote confirmation state; operator audience only, data: WhatsAppOrderConfirmation. */
|
|
507
|
-
'whatsapp-order-confirmation',
|
|
508
501
|
// Payments & providers.
|
|
509
502
|
'payment_received',
|
|
510
503
|
// Operator-only observation invalidation; never a receipt or customer frame.
|
package/dist/store.d.ts
CHANGED
|
@@ -270,16 +270,10 @@ declare global {
|
|
|
270
270
|
* at send time and failing CLOSED.
|
|
271
271
|
*
|
|
272
272
|
* - `channels` — which legs the chase runs on. ABSENT means `['email']`, so a
|
|
273
|
-
* store that never set it behaves exactly as before
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
* `whatsappMessages` meter, a connected MercadoPago account, a ledger in
|
|
278
|
-
* ARS, and per customer a `marketing.consent.whatsapp` stamp with
|
|
279
|
-
* `marketing.whatsapp === true` and a phone. Both legs share one cooldown
|
|
280
|
-
* (`Customer.lastReminderAt`). On a store with both channels the email leg
|
|
281
|
-
* wins the period: a customer it can chase gets the email only, and the
|
|
282
|
-
* WhatsApp leg covers the customers email cannot reach (no address).
|
|
273
|
+
* store that never set it behaves exactly as before; `'email'` is the only
|
|
274
|
+
* leg. ⚠️ A store saved while a `'whatsapp'` leg still existed can carry that
|
|
275
|
+
* member until its next save: the chase ignores it, and `PATCH /store` accepts
|
|
276
|
+
* it and drops it (a list naming ONLY it saves as `frequency: 'none'`).
|
|
283
277
|
*/
|
|
284
278
|
interface PaymentRemindersConfig {
|
|
285
279
|
frequency?: 'none' | 'weekly' | 'monthly';
|
|
@@ -288,7 +282,7 @@ declare global {
|
|
|
288
282
|
channels?: PaymentReminderChannel[];
|
|
289
283
|
}
|
|
290
284
|
/** A leg of the automatic payment reminder — see `PaymentRemindersConfig.channels`. */
|
|
291
|
-
type PaymentReminderChannel = 'email'
|
|
285
|
+
type PaymentReminderChannel = 'email';
|
|
292
286
|
/**
|
|
293
287
|
* Cut-offs and window for the periodic ABC (Pareto) classification of the
|
|
294
288
|
* catalogue. Every member is optional and absence falls back to the api's
|
|
@@ -879,13 +873,6 @@ declare global {
|
|
|
879
873
|
* storefront.
|
|
880
874
|
*/
|
|
881
875
|
publicContact?: boolean;
|
|
882
|
-
/**
|
|
883
|
-
* Draft an order automatically from every inbound WhatsApp text message.
|
|
884
|
-
* Off unless an admin turns it on. Still needs the `aiFeatures` and
|
|
885
|
-
* `whatsappCommerce` entitlements, and `aiOptOut` still wins. Drafts are
|
|
886
|
-
* never placed or sent: staff confirm each one.
|
|
887
|
-
*/
|
|
888
|
-
whatsappOrderAutoDraft?: boolean;
|
|
889
876
|
/**
|
|
890
877
|
* Per-category × per-channel notification/feedback defaults; absent ⇒
|
|
891
878
|
* FE falls back to all-on. FE-read only — `PATCH /store` validates shape only.
|
|
@@ -1251,7 +1238,6 @@ declare global {
|
|
|
1251
1238
|
interface StoreIntegrations {
|
|
1252
1239
|
afip?: Afip;
|
|
1253
1240
|
mercadopago?: Mercadopago;
|
|
1254
|
-
whatsapp?: WhatsAppConfig;
|
|
1255
1241
|
sms?: SmsIntegration;
|
|
1256
1242
|
gmail?: Gmail;
|
|
1257
1243
|
mercadolibre?: Mercadolibre;
|
|
@@ -663,11 +663,12 @@ declare global {
|
|
|
663
663
|
* The codes a catalogue operation answers through its public web route's own core, as that
|
|
664
664
|
* route does: 404 `PRODUCT_NOT_FOUND` / `PRODUCT_GROUP_NOT_FOUND` / `COLLECTION_NOT_FOUND`,
|
|
665
665
|
* 400 `INVALID_CURSOR` / `INVALID_DISCOVERY_QUERY` / `INVALID_UPDATED_AT` (an `incomes`
|
|
666
|
-
* `updatedAt` that is not digits within the safe-integer range)
|
|
666
|
+
* `updatedAt` that is not digits within the safe-integer range) / `DISCOVERY_SORT_UNSUPPORTED`
|
|
667
|
+
* (a `products` read with a well-formed `sort` the api does not serve), 409 `CURSOR_STALE` (a
|
|
667
668
|
* collection that changed between the reads bracketing a page) and 503
|
|
668
669
|
* `PRODUCT_LOOKUP_INCOMPLETE`.
|
|
669
670
|
*/
|
|
670
|
-
type StorefrontPreviewCatalogueErrorCode = 'PRODUCT_NOT_FOUND' | 'PRODUCT_GROUP_NOT_FOUND' | 'COLLECTION_NOT_FOUND' | 'INVALID_CURSOR' | 'INVALID_DISCOVERY_QUERY' | 'INVALID_UPDATED_AT' | 'CURSOR_STALE' | 'PRODUCT_LOOKUP_INCOMPLETE';
|
|
671
|
+
type StorefrontPreviewCatalogueErrorCode = 'PRODUCT_NOT_FOUND' | 'PRODUCT_GROUP_NOT_FOUND' | 'COLLECTION_NOT_FOUND' | 'INVALID_CURSOR' | 'INVALID_DISCOVERY_QUERY' | 'INVALID_UPDATED_AT' | 'DISCOVERY_SORT_UNSUPPORTED' | 'CURSOR_STALE' | 'PRODUCT_LOOKUP_INCOMPLETE';
|
|
671
672
|
interface StorefrontPreviewReadFailure {
|
|
672
673
|
message: string;
|
|
673
674
|
error: StorefrontPreviewReadErrorCode | StorefrontPreviewCatalogueErrorCode;
|
package/dist/subscription.d.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* - Feature keys now match the BE wire format directly (renamed afip→afipInvoicing,
|
|
25
25
|
* cash→cashManagement, reportsAdvanced→advancedReports as of 2026-04-26). The interim
|
|
26
26
|
* paymentIntegrations key was split into domesticPayments + stripePayments.
|
|
27
|
-
* New keys
|
|
27
|
+
* New keys aiFeatures/mobileApp/customDomain are
|
|
28
28
|
* declared here even when their epics haven't shipped — the matrix can set
|
|
29
29
|
* enabled:false until they do.
|
|
30
30
|
*/
|
|
@@ -100,7 +100,7 @@ declare global {
|
|
|
100
100
|
* exhausts this union (a `switch`, a `Record<FeatureKey, …>`) still has to
|
|
101
101
|
* handle the new member in the same change.
|
|
102
102
|
*/
|
|
103
|
-
type FeatureKey = 'maxOrdersMonth' | 'maxInvoicesMonth' | '
|
|
103
|
+
type FeatureKey = 'maxOrdersMonth' | 'maxInvoicesMonth' | 'maxProducts' | 'maxUsers' | 'maxCustomers' | 'maxWarehouses' | 'priceListsMax' | 'webhooks' | 'afipInvoicing' | 'suppliers' | 'domesticPayments' | 'stripePayments' | 'cashManagement' | 'importExport' | 'advancedReports' | 'customBranding' | 'prioritySupport' | 'aiFeatures' | 'mobileApp' | 'customDomain' | 'advancedPricing' | 'marketplaceChannels' | 'storefront' | 'loyalty' | 'marketing' | 'mandatory2fa';
|
|
104
104
|
/** Resolved entitlements for a specific tenant (matrix + overrides applied). */
|
|
105
105
|
type ResolvedEntitlements = Record<FeatureKey, Entitlement>;
|
|
106
106
|
/**
|
|
@@ -1236,7 +1236,7 @@ export declare const isPaidPlanTier: (value: unknown) => value is PaidPlanTier;
|
|
|
1236
1236
|
* metered / lifetime cap PASSES THROUGH — a new cap silently unbounded.
|
|
1237
1237
|
* Checklist: `docs/PLANS_AND_ENTITLEMENTS.md` in the api repo.
|
|
1238
1238
|
*/
|
|
1239
|
-
export declare const FEATURE_KEYS: readonly ["afipInvoicing", "suppliers", "advancedReports", "cashManagement", "importExport", "domesticPayments", "stripePayments", "
|
|
1239
|
+
export declare const FEATURE_KEYS: readonly ["afipInvoicing", "suppliers", "advancedReports", "cashManagement", "importExport", "domesticPayments", "stripePayments", "aiFeatures", "mobileApp", "customBranding", "customDomain", "prioritySupport", "advancedPricing", "marketplaceChannels", "storefront", "loyalty", "marketing", "mandatory2fa", "maxUsers", "maxProducts", "maxCustomers", "maxWarehouses", "priceListsMax", "webhooks", "maxOrdersMonth", "maxInvoicesMonth"];
|
|
1240
1240
|
type AssertNoUncoveredFeatureKey<T extends never> = T;
|
|
1241
1241
|
export type UncoveredFeatureKeys = AssertNoUncoveredFeatureKey<Exclude<FeatureKey, (typeof FEATURE_KEYS)[number]>>;
|
|
1242
1242
|
export {};
|
package/dist/subscription.js
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* - Feature keys now match the BE wire format directly (renamed afip→afipInvoicing,
|
|
25
25
|
* cash→cashManagement, reportsAdvanced→advancedReports as of 2026-04-26). The interim
|
|
26
26
|
* paymentIntegrations key was split into domesticPayments + stripePayments.
|
|
27
|
-
* New keys
|
|
27
|
+
* New keys aiFeatures/mobileApp/customDomain are
|
|
28
28
|
* declared here even when their epics haven't shipped — the matrix can set
|
|
29
29
|
* enabled:false until they do.
|
|
30
30
|
*/
|
|
@@ -109,7 +109,6 @@ export const FEATURE_KEYS = [
|
|
|
109
109
|
'importExport',
|
|
110
110
|
'domesticPayments',
|
|
111
111
|
'stripePayments',
|
|
112
|
-
'whatsappCommerce',
|
|
113
112
|
'aiFeatures',
|
|
114
113
|
'mobileApp',
|
|
115
114
|
'customBranding',
|
|
@@ -129,5 +128,4 @@ export const FEATURE_KEYS = [
|
|
|
129
128
|
'webhooks',
|
|
130
129
|
'maxOrdersMonth',
|
|
131
130
|
'maxInvoicesMonth',
|
|
132
|
-
'whatsappMessages',
|
|
133
131
|
];
|
package/dist/wire.d.ts
CHANGED
|
@@ -43,8 +43,6 @@ export declare const STORE_MP_SECRET_KEYS: readonly ["accessToken", "code", "ref
|
|
|
43
43
|
export declare const STORE_GMAIL_SECRET_KEYS: readonly ["refreshTokenEncrypted", "accessTokenEncrypted"];
|
|
44
44
|
/** KMS-ciphertext Mercadolibre OAuth credentials + the single-flight refresh marker. */
|
|
45
45
|
export declare const STORE_MERCADOLIBRE_SECRET_KEYS: readonly ["accessTokenEncrypted", "refreshTokenEncrypted", "refreshAttemptAt"];
|
|
46
|
-
/** WhatsApp's only secret field on `Store.integrations.whatsapp`. */
|
|
47
|
-
export declare const STORE_WHATSAPP_SECRET_KEYS: readonly ["accessToken"];
|
|
48
46
|
/**
|
|
49
47
|
* KMS-ciphertext TiendaNube OAuth credential on `Store.integrations.tiendanube`.
|
|
50
48
|
* A single `accessTokenEncrypted` — TiendaNube issues no refresh token, so there
|
|
@@ -94,8 +92,6 @@ declare global {
|
|
|
94
92
|
* because the type has to describe what actually arrives.
|
|
95
93
|
*/
|
|
96
94
|
type StoreMercadolibreSecretKey = (typeof STORE_MERCADOLIBRE_SECRET_KEYS)[number];
|
|
97
|
-
/** The one credential key stripped from `Store.integrations.whatsapp` before it crosses a wire. */
|
|
98
|
-
type StoreWhatsappSecretKey = (typeof STORE_WHATSAPP_SECRET_KEYS)[number];
|
|
99
95
|
/** The one KMS-ciphertext key stripped from `Store.integrations.tiendanube` before it crosses a wire. */
|
|
100
96
|
type StoreTiendanubeSecretKey = (typeof STORE_TIENDANUBE_SECRET_KEYS)[number];
|
|
101
97
|
/** A TOTP sub-key stripped from `User.totp` before a USER row crosses a wire. */
|
package/dist/wire.js
CHANGED
|
@@ -64,8 +64,6 @@ export const STORE_MERCADOLIBRE_SECRET_KEYS = [
|
|
|
64
64
|
'refreshTokenEncrypted',
|
|
65
65
|
'refreshAttemptAt',
|
|
66
66
|
];
|
|
67
|
-
/** WhatsApp's only secret field on `Store.integrations.whatsapp`. */
|
|
68
|
-
export const STORE_WHATSAPP_SECRET_KEYS = ['accessToken'];
|
|
69
67
|
/**
|
|
70
68
|
* KMS-ciphertext TiendaNube OAuth credential on `Store.integrations.tiendanube`.
|
|
71
69
|
* A single `accessTokenEncrypted` — TiendaNube issues no refresh token, so there
|
package/package.json
CHANGED
package/dist/cjs/whatsapp.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Published WhatsApp surface — the tenant-facing connection config and the
|
|
4
|
-
* tenant's own template send (`POST /whatsapp/send`).
|
|
5
|
-
*
|
|
6
|
-
* ⚠️ **Meta's inbound webhook payload is NOT here and must not come back.**
|
|
7
|
-
* The twelve shapes Meta POSTs to `/whatsapp` — the entry/change/value
|
|
8
|
-
* envelope, the contact, message, document, audio, image, status, error,
|
|
9
|
-
* conversation and pricing leaves — live in
|
|
10
|
-
* `./internal/whatsappWebhook.ts`, prefixed `WhatsAppWebhook*` and excluded
|
|
11
|
-
* from the published build. They are inbound (the provider answering us), so
|
|
12
|
-
* they fail `./internal/README.md`'s own test for what may be published, and
|
|
13
|
-
* their bare names MERGED with globals in every consumer: a published
|
|
14
|
-
* `interface Document` made `document.filename` compile and type as `string`
|
|
15
|
-
* against `lib.dom`'s `Document`, returning `undefined` at runtime.
|
|
16
|
-
*/
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.WHATSAPP_SEND_ERROR_CODES = void 0;
|
|
19
|
-
/**
|
|
20
|
-
* `POST /whatsapp/send` refusals, beyond the cross-cutting `GATING_ERROR_CODES`
|
|
21
|
-
* (notably `PLAN_LIMIT_EXCEEDED` for the `whatsappMessages` monthly cap).
|
|
22
|
-
*
|
|
23
|
-
* - `VALIDATION_FAILED` · 400 — including a body naming both or neither of
|
|
24
|
-
* `to` / `customerId`.
|
|
25
|
-
* - `IDEMPOTENCY_KEY_REQUIRED` · 400 — no `Idempotency-Key` header. The
|
|
26
|
-
* idempotency wrapper's own codes (`INVALID_IDEMPOTENCY_KEY`,
|
|
27
|
-
* `IDEMPOTENCY_KEY_REUSE`, `IDEMPOTENCY_IN_PROGRESS`, `IDEMPOTENCY_KEY_FAILED`,
|
|
28
|
-
* `IDEMPOTENCY_LOCK_CONTENTION`) apply too. `IDEMPOTENCY_KEY_FAILED` (409)
|
|
29
|
-
* means an earlier attempt under this key may have reached Meta: check the
|
|
30
|
-
* recipient's chat before sending again under a NEW key.
|
|
31
|
-
* - `PLATFORM_INTEGRATION_DISABLED` · 503 — WhatsApp is switched off
|
|
32
|
-
* platform-wide by SINFACTURA.
|
|
33
|
-
* - `WHATSAPP_NOT_CONNECTED` · 409 — the calling store has no connected
|
|
34
|
-
* WhatsApp, or a connection with no stored token after a disconnect. Disable
|
|
35
|
-
* the send control. ⚠️ Never falls back to the platform number.
|
|
36
|
-
* - `WHATSAPP_TOKEN_REJECTED` · 409 — connected, but Meta refused the stored
|
|
37
|
-
* token. Reconnect.
|
|
38
|
-
* - `CUSTOMER_NOT_FOUND` · 404 / `WHATSAPP_RECIPIENT_PHONE_MISSING` · 400 — a bad
|
|
39
|
-
* id versus a real customer with no usable number.
|
|
40
|
-
* - `WHATSAPP_RECIPIENT_NOT_ALLOWED` · 403 — non-production stages only: the
|
|
41
|
-
* number is not on that stage's test allowlist. Nothing was sent.
|
|
42
|
-
* - `WHATSAPP_TEMPLATE_NOT_APPROVED` · 422 — not approved, paused, disabled,
|
|
43
|
-
* wrong language or wrong parameter count (Meta does not tell these apart).
|
|
44
|
-
* - `WHATSAPP_RECIPIENT_OPTED_OUT` · 409 — the recipient cannot receive it.
|
|
45
|
-
* - `WHATSAPP_RATE_LIMITED` · 429 — throughput cap; retry later.
|
|
46
|
-
* - `WHATSAPP_ACCOUNT_SUSPENDED` · 403 — the WhatsApp Business account or the
|
|
47
|
-
* number itself is restricted.
|
|
48
|
-
* - `WHATSAPP_SEND_FAILED` · 502 — any other Meta 4xx refusal; carries `metaCode`.
|
|
49
|
-
* - `WHATSAPP_SEND_UNCONFIRMED` · 502 — the request reached Meta and its outcome
|
|
50
|
-
* is unknown: no answer came back, Meta answered 5xx, or Meta accepted it
|
|
51
|
-
* without a message id.
|
|
52
|
-
* The message may have been delivered, so the key is sealed:
|
|
53
|
-
* a retry under it answers `IDEMPOTENCY_KEY_FAILED` rather than re-sending.
|
|
54
|
-
*/
|
|
55
|
-
exports.WHATSAPP_SEND_ERROR_CODES = [
|
|
56
|
-
'VALIDATION_FAILED',
|
|
57
|
-
'IDEMPOTENCY_KEY_REQUIRED',
|
|
58
|
-
'PLATFORM_INTEGRATION_DISABLED',
|
|
59
|
-
'WHATSAPP_NOT_CONNECTED',
|
|
60
|
-
'WHATSAPP_TOKEN_REJECTED',
|
|
61
|
-
'CUSTOMER_NOT_FOUND',
|
|
62
|
-
'WHATSAPP_RECIPIENT_PHONE_MISSING',
|
|
63
|
-
'WHATSAPP_RECIPIENT_NOT_ALLOWED',
|
|
64
|
-
'WHATSAPP_TEMPLATE_NOT_APPROVED',
|
|
65
|
-
'WHATSAPP_RECIPIENT_OPTED_OUT',
|
|
66
|
-
'WHATSAPP_RATE_LIMITED',
|
|
67
|
-
'WHATSAPP_ACCOUNT_SUSPENDED',
|
|
68
|
-
'WHATSAPP_SEND_FAILED',
|
|
69
|
-
'WHATSAPP_SEND_UNCONFIRMED',
|
|
70
|
-
];
|
package/dist/whatsapp.d.ts
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Published WhatsApp surface — the tenant-facing connection config and the
|
|
3
|
-
* tenant's own template send (`POST /whatsapp/send`).
|
|
4
|
-
*
|
|
5
|
-
* ⚠️ **Meta's inbound webhook payload is NOT here and must not come back.**
|
|
6
|
-
* The twelve shapes Meta POSTs to `/whatsapp` — the entry/change/value
|
|
7
|
-
* envelope, the contact, message, document, audio, image, status, error,
|
|
8
|
-
* conversation and pricing leaves — live in
|
|
9
|
-
* `./internal/whatsappWebhook.ts`, prefixed `WhatsAppWebhook*` and excluded
|
|
10
|
-
* from the published build. They are inbound (the provider answering us), so
|
|
11
|
-
* they fail `./internal/README.md`'s own test for what may be published, and
|
|
12
|
-
* their bare names MERGED with globals in every consumer: a published
|
|
13
|
-
* `interface Document` made `document.filename` compile and type as `string`
|
|
14
|
-
* against `lib.dom`'s `Document`, returning `undefined` at runtime.
|
|
15
|
-
*/
|
|
16
|
-
declare global {
|
|
17
|
-
/**
|
|
18
|
-
* Per-tenant WhatsApp Business connection + plan tier.
|
|
19
|
-
*
|
|
20
|
-
* ⚠️ **Treat every member as potentially absent on a real row.** Rows
|
|
21
|
-
* predate the connect flow that populates this block, and writes here are
|
|
22
|
-
* forward-only — an older tenant keeps its original shape rather than being
|
|
23
|
-
* backfilled. This is a property of the stored data, not a statement about
|
|
24
|
-
* which release shipped the writer, so it does not go stale.
|
|
25
|
-
*
|
|
26
|
-
* ⚠️ The Meta access token is deliberately absent. It is written by the
|
|
27
|
-
* per-tenant OAuth callback and stripped by `sanitizeStoreRow` at every
|
|
28
|
-
* STORE-row wire boundary, so a consumer never receives it;
|
|
29
|
-
* `WhatsAppConfigRow` (api-internal, unpublished) is what the api's own
|
|
30
|
-
* senders read. Declaring it here described a field that never arrives.
|
|
31
|
-
*/
|
|
32
|
-
interface WhatsAppConfig {
|
|
33
|
-
wabaId: string;
|
|
34
|
-
phoneNumberId: string;
|
|
35
|
-
verifiedName: string;
|
|
36
|
-
/**
|
|
37
|
-
* Meta's quality signal for the number.
|
|
38
|
-
*
|
|
39
|
-
* ⚠️ `'UNKNOWN'` is a real Meta value, not a placeholder — it is what a
|
|
40
|
-
* number with no traffic yet reports, so every freshly connected tenant
|
|
41
|
-
* starts here. Render it as "no data", never fold it into `'GREEN'`:
|
|
42
|
-
* coercing it makes a brand-new number indistinguishable from a
|
|
43
|
-
* healthy one, and the coercion is invisible at the read site.
|
|
44
|
-
*/
|
|
45
|
-
qualityRating: 'GREEN' | 'YELLOW' | 'RED' | 'UNKNOWN';
|
|
46
|
-
status: 'connected' | 'disconnected' | 'suspended';
|
|
47
|
-
tier: 'free' | 'pro' | 'enterprise';
|
|
48
|
-
/** ISO timestamp. */
|
|
49
|
-
connectedAt: string;
|
|
50
|
-
/** ISO timestamp. */
|
|
51
|
-
disconnectedAt?: string;
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Request body for `POST /whatsapp/send` — the TENANT's own template send,
|
|
55
|
-
* under `adminToken`, from the calling store's own connected number.
|
|
56
|
-
*
|
|
57
|
-
* ⚠️ The request must carry an `Idempotency-Key` header — without one it is
|
|
58
|
-
* refused `400 IDEMPOTENCY_KEY_REQUIRED`. Meta is called before anything is
|
|
59
|
-
* written, so a retried request with no key would send the message twice.
|
|
60
|
-
*
|
|
61
|
-
* ⚠️ There is no `storeId` member and there must never be one. The sending
|
|
62
|
-
* store is the authorizer's; a body-supplied one is the shape that would let
|
|
63
|
-
* a tenant address another tenant's number.
|
|
64
|
-
*
|
|
65
|
-
* ⚠️ Template only. Outside Meta's 24-hour customer-service window a free-form
|
|
66
|
-
* message is refused, and every case this serves (invoice reminder, payment
|
|
67
|
-
* link, order confirmation) is outside it — so there is no free-text member.
|
|
68
|
-
*
|
|
69
|
-
* Exactly one of `to` / `customerId` is required.
|
|
70
|
-
*/
|
|
71
|
-
interface WhatsAppSendRequest {
|
|
72
|
-
/** Meta-approved template NAME, as registered against the store's own WhatsApp Business account. */
|
|
73
|
-
template: string;
|
|
74
|
-
/**
|
|
75
|
-
* Language code of the approved translation. Defaults to `'es'`.
|
|
76
|
-
*
|
|
77
|
-
* ⚠️ Meta matches a template by (name, language) PAIR — an approved template
|
|
78
|
-
* requested in the wrong language is refused exactly like one that was never
|
|
79
|
-
* approved (`WHATSAPP_TEMPLATE_NOT_APPROVED`).
|
|
80
|
-
*/
|
|
81
|
-
languageCode?: string;
|
|
82
|
-
/**
|
|
83
|
-
* BODY placeholders, in `{{1}}`, `{{2}}`, … order.
|
|
84
|
-
*
|
|
85
|
-
* ⚠️ ORDER IS THE BINDING — Meta positions them, so an amount where a due
|
|
86
|
-
* date belongs is accepted, delivered and wrong.
|
|
87
|
-
*/
|
|
88
|
-
parameters?: string[];
|
|
89
|
-
/** Recipient, digits with country code (`5491150123456`). Mutually exclusive with `customerId`. */
|
|
90
|
-
to?: string;
|
|
91
|
-
/** Recipient by id, resolved against the CALLING store's own customers. */
|
|
92
|
-
customerId?: string;
|
|
93
|
-
/** Display name for the message-log row only; never sent to Meta. */
|
|
94
|
-
name?: string;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* `data` of a successful `POST /whatsapp/send`.
|
|
98
|
-
*
|
|
99
|
-
* (Named for the template send, not `WhatsAppSendResult`: that name belongs
|
|
100
|
-
* to the api-internal send seam and has a different shape.)
|
|
101
|
-
*/
|
|
102
|
-
interface WhatsAppTemplateSendResult {
|
|
103
|
-
/** Meta's message id — the handle every later delivery-status webhook carries. */
|
|
104
|
-
messageId: string;
|
|
105
|
-
template: string;
|
|
106
|
-
/** ms epoch of the accepted send. */
|
|
107
|
-
sentAt: number;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* `POST /whatsapp/send` refusals, beyond the cross-cutting `GATING_ERROR_CODES`
|
|
112
|
-
* (notably `PLAN_LIMIT_EXCEEDED` for the `whatsappMessages` monthly cap).
|
|
113
|
-
*
|
|
114
|
-
* - `VALIDATION_FAILED` · 400 — including a body naming both or neither of
|
|
115
|
-
* `to` / `customerId`.
|
|
116
|
-
* - `IDEMPOTENCY_KEY_REQUIRED` · 400 — no `Idempotency-Key` header. The
|
|
117
|
-
* idempotency wrapper's own codes (`INVALID_IDEMPOTENCY_KEY`,
|
|
118
|
-
* `IDEMPOTENCY_KEY_REUSE`, `IDEMPOTENCY_IN_PROGRESS`, `IDEMPOTENCY_KEY_FAILED`,
|
|
119
|
-
* `IDEMPOTENCY_LOCK_CONTENTION`) apply too. `IDEMPOTENCY_KEY_FAILED` (409)
|
|
120
|
-
* means an earlier attempt under this key may have reached Meta: check the
|
|
121
|
-
* recipient's chat before sending again under a NEW key.
|
|
122
|
-
* - `PLATFORM_INTEGRATION_DISABLED` · 503 — WhatsApp is switched off
|
|
123
|
-
* platform-wide by SINFACTURA.
|
|
124
|
-
* - `WHATSAPP_NOT_CONNECTED` · 409 — the calling store has no connected
|
|
125
|
-
* WhatsApp, or a connection with no stored token after a disconnect. Disable
|
|
126
|
-
* the send control. ⚠️ Never falls back to the platform number.
|
|
127
|
-
* - `WHATSAPP_TOKEN_REJECTED` · 409 — connected, but Meta refused the stored
|
|
128
|
-
* token. Reconnect.
|
|
129
|
-
* - `CUSTOMER_NOT_FOUND` · 404 / `WHATSAPP_RECIPIENT_PHONE_MISSING` · 400 — a bad
|
|
130
|
-
* id versus a real customer with no usable number.
|
|
131
|
-
* - `WHATSAPP_RECIPIENT_NOT_ALLOWED` · 403 — non-production stages only: the
|
|
132
|
-
* number is not on that stage's test allowlist. Nothing was sent.
|
|
133
|
-
* - `WHATSAPP_TEMPLATE_NOT_APPROVED` · 422 — not approved, paused, disabled,
|
|
134
|
-
* wrong language or wrong parameter count (Meta does not tell these apart).
|
|
135
|
-
* - `WHATSAPP_RECIPIENT_OPTED_OUT` · 409 — the recipient cannot receive it.
|
|
136
|
-
* - `WHATSAPP_RATE_LIMITED` · 429 — throughput cap; retry later.
|
|
137
|
-
* - `WHATSAPP_ACCOUNT_SUSPENDED` · 403 — the WhatsApp Business account or the
|
|
138
|
-
* number itself is restricted.
|
|
139
|
-
* - `WHATSAPP_SEND_FAILED` · 502 — any other Meta 4xx refusal; carries `metaCode`.
|
|
140
|
-
* - `WHATSAPP_SEND_UNCONFIRMED` · 502 — the request reached Meta and its outcome
|
|
141
|
-
* is unknown: no answer came back, Meta answered 5xx, or Meta accepted it
|
|
142
|
-
* without a message id.
|
|
143
|
-
* The message may have been delivered, so the key is sealed:
|
|
144
|
-
* a retry under it answers `IDEMPOTENCY_KEY_FAILED` rather than re-sending.
|
|
145
|
-
*/
|
|
146
|
-
export declare const WHATSAPP_SEND_ERROR_CODES: readonly ["VALIDATION_FAILED", "IDEMPOTENCY_KEY_REQUIRED", "PLATFORM_INTEGRATION_DISABLED", "WHATSAPP_NOT_CONNECTED", "WHATSAPP_TOKEN_REJECTED", "CUSTOMER_NOT_FOUND", "WHATSAPP_RECIPIENT_PHONE_MISSING", "WHATSAPP_RECIPIENT_NOT_ALLOWED", "WHATSAPP_TEMPLATE_NOT_APPROVED", "WHATSAPP_RECIPIENT_OPTED_OUT", "WHATSAPP_RATE_LIMITED", "WHATSAPP_ACCOUNT_SUSPENDED", "WHATSAPP_SEND_FAILED", "WHATSAPP_SEND_UNCONFIRMED"];
|
|
147
|
-
export type WhatsAppSendErrorCode = (typeof WHATSAPP_SEND_ERROR_CODES)[number];
|
|
148
|
-
export {};
|
package/dist/whatsapp.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Published WhatsApp surface — the tenant-facing connection config and the
|
|
3
|
-
* tenant's own template send (`POST /whatsapp/send`).
|
|
4
|
-
*
|
|
5
|
-
* ⚠️ **Meta's inbound webhook payload is NOT here and must not come back.**
|
|
6
|
-
* The twelve shapes Meta POSTs to `/whatsapp` — the entry/change/value
|
|
7
|
-
* envelope, the contact, message, document, audio, image, status, error,
|
|
8
|
-
* conversation and pricing leaves — live in
|
|
9
|
-
* `./internal/whatsappWebhook.ts`, prefixed `WhatsAppWebhook*` and excluded
|
|
10
|
-
* from the published build. They are inbound (the provider answering us), so
|
|
11
|
-
* they fail `./internal/README.md`'s own test for what may be published, and
|
|
12
|
-
* their bare names MERGED with globals in every consumer: a published
|
|
13
|
-
* `interface Document` made `document.filename` compile and type as `string`
|
|
14
|
-
* against `lib.dom`'s `Document`, returning `undefined` at runtime.
|
|
15
|
-
*/
|
|
16
|
-
/**
|
|
17
|
-
* `POST /whatsapp/send` refusals, beyond the cross-cutting `GATING_ERROR_CODES`
|
|
18
|
-
* (notably `PLAN_LIMIT_EXCEEDED` for the `whatsappMessages` monthly cap).
|
|
19
|
-
*
|
|
20
|
-
* - `VALIDATION_FAILED` · 400 — including a body naming both or neither of
|
|
21
|
-
* `to` / `customerId`.
|
|
22
|
-
* - `IDEMPOTENCY_KEY_REQUIRED` · 400 — no `Idempotency-Key` header. The
|
|
23
|
-
* idempotency wrapper's own codes (`INVALID_IDEMPOTENCY_KEY`,
|
|
24
|
-
* `IDEMPOTENCY_KEY_REUSE`, `IDEMPOTENCY_IN_PROGRESS`, `IDEMPOTENCY_KEY_FAILED`,
|
|
25
|
-
* `IDEMPOTENCY_LOCK_CONTENTION`) apply too. `IDEMPOTENCY_KEY_FAILED` (409)
|
|
26
|
-
* means an earlier attempt under this key may have reached Meta: check the
|
|
27
|
-
* recipient's chat before sending again under a NEW key.
|
|
28
|
-
* - `PLATFORM_INTEGRATION_DISABLED` · 503 — WhatsApp is switched off
|
|
29
|
-
* platform-wide by SINFACTURA.
|
|
30
|
-
* - `WHATSAPP_NOT_CONNECTED` · 409 — the calling store has no connected
|
|
31
|
-
* WhatsApp, or a connection with no stored token after a disconnect. Disable
|
|
32
|
-
* the send control. ⚠️ Never falls back to the platform number.
|
|
33
|
-
* - `WHATSAPP_TOKEN_REJECTED` · 409 — connected, but Meta refused the stored
|
|
34
|
-
* token. Reconnect.
|
|
35
|
-
* - `CUSTOMER_NOT_FOUND` · 404 / `WHATSAPP_RECIPIENT_PHONE_MISSING` · 400 — a bad
|
|
36
|
-
* id versus a real customer with no usable number.
|
|
37
|
-
* - `WHATSAPP_RECIPIENT_NOT_ALLOWED` · 403 — non-production stages only: the
|
|
38
|
-
* number is not on that stage's test allowlist. Nothing was sent.
|
|
39
|
-
* - `WHATSAPP_TEMPLATE_NOT_APPROVED` · 422 — not approved, paused, disabled,
|
|
40
|
-
* wrong language or wrong parameter count (Meta does not tell these apart).
|
|
41
|
-
* - `WHATSAPP_RECIPIENT_OPTED_OUT` · 409 — the recipient cannot receive it.
|
|
42
|
-
* - `WHATSAPP_RATE_LIMITED` · 429 — throughput cap; retry later.
|
|
43
|
-
* - `WHATSAPP_ACCOUNT_SUSPENDED` · 403 — the WhatsApp Business account or the
|
|
44
|
-
* number itself is restricted.
|
|
45
|
-
* - `WHATSAPP_SEND_FAILED` · 502 — any other Meta 4xx refusal; carries `metaCode`.
|
|
46
|
-
* - `WHATSAPP_SEND_UNCONFIRMED` · 502 — the request reached Meta and its outcome
|
|
47
|
-
* is unknown: no answer came back, Meta answered 5xx, or Meta accepted it
|
|
48
|
-
* without a message id.
|
|
49
|
-
* The message may have been delivered, so the key is sealed:
|
|
50
|
-
* a retry under it answers `IDEMPOTENCY_KEY_FAILED` rather than re-sending.
|
|
51
|
-
*/
|
|
52
|
-
export const WHATSAPP_SEND_ERROR_CODES = [
|
|
53
|
-
'VALIDATION_FAILED',
|
|
54
|
-
'IDEMPOTENCY_KEY_REQUIRED',
|
|
55
|
-
'PLATFORM_INTEGRATION_DISABLED',
|
|
56
|
-
'WHATSAPP_NOT_CONNECTED',
|
|
57
|
-
'WHATSAPP_TOKEN_REJECTED',
|
|
58
|
-
'CUSTOMER_NOT_FOUND',
|
|
59
|
-
'WHATSAPP_RECIPIENT_PHONE_MISSING',
|
|
60
|
-
'WHATSAPP_RECIPIENT_NOT_ALLOWED',
|
|
61
|
-
'WHATSAPP_TEMPLATE_NOT_APPROVED',
|
|
62
|
-
'WHATSAPP_RECIPIENT_OPTED_OUT',
|
|
63
|
-
'WHATSAPP_RATE_LIMITED',
|
|
64
|
-
'WHATSAPP_ACCOUNT_SUSPENDED',
|
|
65
|
-
'WHATSAPP_SEND_FAILED',
|
|
66
|
-
'WHATSAPP_SEND_UNCONFIRMED',
|
|
67
|
-
];
|