@aglyn/plugins-commerce 1.0.0-beta.143
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/LICENSE +201 -0
- package/README.md +10 -0
- package/package.json +57 -0
- package/src/index.d.ts +38 -0
- package/src/index.js +38 -0
- package/src/index.js.map +1 -0
- package/src/lib/components/account.d.ts +31 -0
- package/src/lib/components/account.js +645 -0
- package/src/lib/components/account.js.map +1 -0
- package/src/lib/components/cart.d.ts +38 -0
- package/src/lib/components/cart.js +851 -0
- package/src/lib/components/cart.js.map +1 -0
- package/src/lib/components/commerce-console-page.d.ts +32 -0
- package/src/lib/components/commerce-console-page.js +296 -0
- package/src/lib/components/commerce-console-page.js.map +1 -0
- package/src/lib/components/commerce-console-sections.d.ts +34 -0
- package/src/lib/components/commerce-console-sections.js +62 -0
- package/src/lib/components/commerce-console-sections.js.map +1 -0
- package/src/lib/components/console/catalog-organization-card.component.d.ts +14 -0
- package/src/lib/components/console/catalog-organization-card.component.js +1087 -0
- package/src/lib/components/console/catalog-organization-card.component.js.map +1 -0
- package/src/lib/components/console/commerce-analytics-card.component.d.ts +27 -0
- package/src/lib/components/console/commerce-analytics-card.component.js +310 -0
- package/src/lib/components/console/commerce-analytics-card.component.js.map +1 -0
- package/src/lib/components/console/commerce-glance-card.component.d.ts +20 -0
- package/src/lib/components/console/commerce-glance-card.component.js +340 -0
- package/src/lib/components/console/commerce-glance-card.component.js.map +1 -0
- package/src/lib/components/console/commerce-stat-tile.component.d.ts +37 -0
- package/src/lib/components/console/commerce-stat-tile.component.js +72 -0
- package/src/lib/components/console/commerce-stat-tile.component.js.map +1 -0
- package/src/lib/components/console/discounts-card.component.d.ts +14 -0
- package/src/lib/components/console/discounts-card.component.js +443 -0
- package/src/lib/components/console/discounts-card.component.js.map +1 -0
- package/src/lib/components/console/entitlement-gate.component.d.ts +76 -0
- package/src/lib/components/console/entitlement-gate.component.js +115 -0
- package/src/lib/components/console/entitlement-gate.component.js.map +1 -0
- package/src/lib/components/console/gift-cards-card.component.d.ts +29 -0
- package/src/lib/components/console/gift-cards-card.component.js +379 -0
- package/src/lib/components/console/gift-cards-card.component.js.map +1 -0
- package/src/lib/components/console/host-coupons-card.component.d.ts +14 -0
- package/src/lib/components/console/host-coupons-card.component.js +252 -0
- package/src/lib/components/console/host-coupons-card.component.js.map +1 -0
- package/src/lib/components/console/host-orders-card.component.d.ts +13 -0
- package/src/lib/components/console/host-orders-card.component.js +861 -0
- package/src/lib/components/console/host-orders-card.component.js.map +1 -0
- package/src/lib/components/console/locations-card.component.d.ts +14 -0
- package/src/lib/components/console/locations-card.component.js +256 -0
- package/src/lib/components/console/locations-card.component.js.map +1 -0
- package/src/lib/components/console/member-posts-card.component.d.ts +8 -0
- package/src/lib/components/console/member-posts-card.component.js +283 -0
- package/src/lib/components/console/member-posts-card.component.js.map +1 -0
- package/src/lib/components/console/newest-site-users-card.component.d.ts +36 -0
- package/src/lib/components/console/newest-site-users-card.component.js +126 -0
- package/src/lib/components/console/newest-site-users-card.component.js.map +1 -0
- package/src/lib/components/console/order-detail-dialog.component.d.ts +28 -0
- package/src/lib/components/console/order-detail-dialog.component.js +976 -0
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -0
- package/src/lib/components/console/paid-media.d.ts +127 -0
- package/src/lib/components/console/paid-media.js +397 -0
- package/src/lib/components/console/paid-media.js.map +1 -0
- package/src/lib/components/console/payments-settings-card.component.d.ts +13 -0
- package/src/lib/components/console/payments-settings-card.component.js +295 -0
- package/src/lib/components/console/payments-settings-card.component.js.map +1 -0
- package/src/lib/components/console/pos-page.component.d.ts +13 -0
- package/src/lib/components/console/pos-page.component.js +916 -0
- package/src/lib/components/console/pos-page.component.js.map +1 -0
- package/src/lib/components/console/product-editor-dialog.component.d.ts +32 -0
- package/src/lib/components/console/product-editor-dialog.component.js +1374 -0
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -0
- package/src/lib/components/console/products-hub-card.component.d.ts +16 -0
- package/src/lib/components/console/products-hub-card.component.js +1280 -0
- package/src/lib/components/console/products-hub-card.component.js.map +1 -0
- package/src/lib/components/console/products-hub-zone.component.d.ts +50 -0
- package/src/lib/components/console/products-hub-zone.component.js +200 -0
- package/src/lib/components/console/products-hub-zone.component.js.map +1 -0
- package/src/lib/components/console/recovery-queue-card.component.d.ts +39 -0
- package/src/lib/components/console/recovery-queue-card.component.js +262 -0
- package/src/lib/components/console/recovery-queue-card.component.js.map +1 -0
- package/src/lib/components/console/registers-card.component.d.ts +21 -0
- package/src/lib/components/console/registers-card.component.js +296 -0
- package/src/lib/components/console/registers-card.component.js.map +1 -0
- package/src/lib/components/console/reservations-card.component.d.ts +14 -0
- package/src/lib/components/console/reservations-card.component.js +650 -0
- package/src/lib/components/console/reservations-card.component.js.map +1 -0
- package/src/lib/components/console/reviews-moderation-card.component.d.ts +8 -0
- package/src/lib/components/console/reviews-moderation-card.component.js +235 -0
- package/src/lib/components/console/reviews-moderation-card.component.js.map +1 -0
- package/src/lib/components/console/shipping-settings-card.component.d.ts +38 -0
- package/src/lib/components/console/shipping-settings-card.component.js +560 -0
- package/src/lib/components/console/shipping-settings-card.component.js.map +1 -0
- package/src/lib/components/console/stock-movements-card.component.d.ts +31 -0
- package/src/lib/components/console/stock-movements-card.component.js +333 -0
- package/src/lib/components/console/stock-movements-card.component.js.map +1 -0
- package/src/lib/components/console/store-settings-card.component.d.ts +14 -0
- package/src/lib/components/console/store-settings-card.component.js +300 -0
- package/src/lib/components/console/store-settings-card.component.js.map +1 -0
- package/src/lib/components/console/storefront-tax-summary-card.component.d.ts +73 -0
- package/src/lib/components/console/storefront-tax-summary-card.component.js +408 -0
- package/src/lib/components/console/storefront-tax-summary-card.component.js.map +1 -0
- package/src/lib/components/console/suppliers-card.component.d.ts +8 -0
- package/src/lib/components/console/suppliers-card.component.js +328 -0
- package/src/lib/components/console/suppliers-card.component.js.map +1 -0
- package/src/lib/components/console/tax-settings-card.component.d.ts +14 -0
- package/src/lib/components/console/tax-settings-card.component.js +473 -0
- package/src/lib/components/console/tax-settings-card.component.js.map +1 -0
- package/src/lib/components/gate.d.ts +39 -0
- package/src/lib/components/gate.js +202 -0
- package/src/lib/components/gate.js.map +1 -0
- package/src/lib/components/gated-video.d.ts +40 -0
- package/src/lib/components/gated-video.js +366 -0
- package/src/lib/components/gated-video.js.map +1 -0
- package/src/lib/components/member-feed.d.ts +32 -0
- package/src/lib/components/member-feed.js +198 -0
- package/src/lib/components/member-feed.js.map +1 -0
- package/src/lib/components/member-recovery.d.ts +35 -0
- package/src/lib/components/member-recovery.js +313 -0
- package/src/lib/components/member-recovery.js.map +1 -0
- package/src/lib/components/member-signin.d.ts +35 -0
- package/src/lib/components/member-signin.js +257 -0
- package/src/lib/components/member-signin.js.map +1 -0
- package/src/lib/components/member-signup.d.ts +34 -0
- package/src/lib/components/member-signup.js +287 -0
- package/src/lib/components/member-signup.js.map +1 -0
- package/src/lib/components/newsletter-signup.d.ts +39 -0
- package/src/lib/components/newsletter-signup.js +229 -0
- package/src/lib/components/newsletter-signup.js.map +1 -0
- package/src/lib/components/product-detail.d.ts +38 -0
- package/src/lib/components/product-detail.js +1022 -0
- package/src/lib/components/product-detail.js.map +1 -0
- package/src/lib/components/product-grid.d.ts +67 -0
- package/src/lib/components/product-grid.js +909 -0
- package/src/lib/components/product-grid.js.map +1 -0
- package/src/lib/components/product-reviews.d.ts +32 -0
- package/src/lib/components/product-reviews.js +349 -0
- package/src/lib/components/product-reviews.js.map +1 -0
- package/src/lib/components/related-products.d.ts +33 -0
- package/src/lib/components/related-products.js +232 -0
- package/src/lib/components/related-products.js.map +1 -0
- package/src/lib/components/reservation-widget.d.ts +33 -0
- package/src/lib/components/reservation-widget.js +418 -0
- package/src/lib/components/reservation-widget.js.map +1 -0
- package/src/lib/components/storefront-payment-element-fallback.d.ts +18 -0
- package/src/lib/components/storefront-payment-element-fallback.js +51 -0
- package/src/lib/components/storefront-payment-element-fallback.js.map +1 -0
- package/src/lib/components/storefront-payment-element.d.ts +78 -0
- package/src/lib/components/storefront-payment-element.js +156 -0
- package/src/lib/components/storefront-payment-element.js.map +1 -0
- package/src/lib/components/wishlist.d.ts +46 -0
- package/src/lib/components/wishlist.js +304 -0
- package/src/lib/components/wishlist.js.map +1 -0
- package/src/lib/constants/bundle-common.d.ts +18 -0
- package/src/lib/constants/bundle-common.js +18 -0
- package/src/lib/constants/bundle-common.js.map +1 -0
- package/src/lib/constants/product-filters.d.ts +35 -0
- package/src/lib/constants/product-filters.js +109 -0
- package/src/lib/constants/product-filters.js.map +1 -0
- package/src/lib/model/commerce-cart.d.ts +52 -0
- package/src/lib/model/commerce-cart.js +102 -0
- package/src/lib/model/commerce-cart.js.map +1 -0
- package/src/lib/model/commerce-connect-transfer.d.ts +243 -0
- package/src/lib/model/commerce-connect-transfer.js +231 -0
- package/src/lib/model/commerce-connect-transfer.js.map +1 -0
- package/src/lib/model/commerce-discounts.d.ts +164 -0
- package/src/lib/model/commerce-discounts.js +231 -0
- package/src/lib/model/commerce-discounts.js.map +1 -0
- package/src/lib/model/commerce-dispute.d.ts +124 -0
- package/src/lib/model/commerce-dispute.js +225 -0
- package/src/lib/model/commerce-dispute.js.map +1 -0
- package/src/lib/model/commerce-gift-cards.d.ts +107 -0
- package/src/lib/model/commerce-gift-cards.js +121 -0
- package/src/lib/model/commerce-gift-cards.js.map +1 -0
- package/src/lib/model/commerce-io.d.ts +36 -0
- package/src/lib/model/commerce-io.js +245 -0
- package/src/lib/model/commerce-io.js.map +1 -0
- package/src/lib/model/commerce-orders.d.ts +1040 -0
- package/src/lib/model/commerce-orders.js +1022 -0
- package/src/lib/model/commerce-orders.js.map +1 -0
- package/src/lib/model/commerce-promotions.d.ts +188 -0
- package/src/lib/model/commerce-promotions.js +199 -0
- package/src/lib/model/commerce-promotions.js.map +1 -0
- package/src/lib/model/commerce-reservations.d.ts +175 -0
- package/src/lib/model/commerce-reservations.js +157 -0
- package/src/lib/model/commerce-reservations.js.map +1 -0
- package/src/lib/model/commerce-shipping.d.ts +316 -0
- package/src/lib/model/commerce-shipping.js +484 -0
- package/src/lib/model/commerce-shipping.js.map +1 -0
- package/src/lib/model/commerce-stock-holds.d.ts +199 -0
- package/src/lib/model/commerce-stock-holds.js +190 -0
- package/src/lib/model/commerce-stock-holds.js.map +1 -0
- package/src/lib/model/commerce-subscription-status.d.ts +67 -0
- package/src/lib/model/commerce-subscription-status.js +76 -0
- package/src/lib/model/commerce-subscription-status.js.map +1 -0
- package/src/lib/model/commerce-tax-decision.d.ts +222 -0
- package/src/lib/model/commerce-tax-decision.js +165 -0
- package/src/lib/model/commerce-tax-decision.js.map +1 -0
- package/src/lib/model/commerce-tax.d.ts +176 -0
- package/src/lib/model/commerce-tax.js +92 -0
- package/src/lib/model/commerce-tax.js.map +1 -0
- package/src/lib/model/commerce.d.ts +551 -0
- package/src/lib/model/commerce.js +739 -0
- package/src/lib/model/commerce.js.map +1 -0
- package/src/lib/model/index.d.ts +40 -0
- package/src/lib/model/index.js +40 -0
- package/src/lib/model/index.js.map +1 -0
- package/src/lib/model/order-figures.d.ts +48 -0
- package/src/lib/model/order-figures.js +74 -0
- package/src/lib/model/order-figures.js.map +1 -0
- package/src/lib/model/plugin-permissions.d.ts +23 -0
- package/src/lib/model/plugin-permissions.js +34 -0
- package/src/lib/model/plugin-permissions.js.map +1 -0
- package/src/lib/model/purchase-analytics.d.ts +186 -0
- package/src/lib/model/purchase-analytics.js +216 -0
- package/src/lib/model/purchase-analytics.js.map +1 -0
- package/src/lib/plugin-config.d.ts +62 -0
- package/src/lib/plugin-config.js +78 -0
- package/src/lib/plugin-config.js.map +1 -0
- package/src/lib/plugin.d.ts +28 -0
- package/src/lib/plugin.js +147 -0
- package/src/lib/plugin.js.map +1 -0
- package/src/lib/server/billing-webhook.d.ts +26 -0
- package/src/lib/server/billing-webhook.js +4011 -0
- package/src/lib/server/billing-webhook.js.map +1 -0
- package/src/lib/server/cancel-order.d.ts +87 -0
- package/src/lib/server/cancel-order.js +368 -0
- package/src/lib/server/cancel-order.js.map +1 -0
- package/src/lib/server/cart-checkout.d.ts +25 -0
- package/src/lib/server/cart-checkout.js +976 -0
- package/src/lib/server/cart-checkout.js.map +1 -0
- package/src/lib/server/cart-cookie.d.ts +32 -0
- package/src/lib/server/cart-cookie.js +77 -0
- package/src/lib/server/cart-cookie.js.map +1 -0
- package/src/lib/server/cart.d.ts +34 -0
- package/src/lib/server/cart.js +181 -0
- package/src/lib/server/cart.js.map +1 -0
- package/src/lib/server/catalog.d.ts +127 -0
- package/src/lib/server/catalog.js +277 -0
- package/src/lib/server/catalog.js.map +1 -0
- package/src/lib/server/checkout.d.ts +36 -0
- package/src/lib/server/checkout.js +915 -0
- package/src/lib/server/checkout.js.map +1 -0
- package/src/lib/server/connect.d.ts +26 -0
- package/src/lib/server/connect.js +238 -0
- package/src/lib/server/connect.js.map +1 -0
- package/src/lib/server/contact-refund.d.ts +117 -0
- package/src/lib/server/contact-refund.js +196 -0
- package/src/lib/server/contact-refund.js.map +1 -0
- package/src/lib/server/download.d.ts +39 -0
- package/src/lib/server/download.js +206 -0
- package/src/lib/server/download.js.map +1 -0
- package/src/lib/server/draft-order.d.ts +26 -0
- package/src/lib/server/draft-order.js +706 -0
- package/src/lib/server/draft-order.js.map +1 -0
- package/src/lib/server/feed.d.ts +24 -0
- package/src/lib/server/feed.js +59 -0
- package/src/lib/server/feed.js.map +1 -0
- package/src/lib/server/fulfill-order.d.ts +97 -0
- package/src/lib/server/fulfill-order.js +235 -0
- package/src/lib/server/fulfill-order.js.map +1 -0
- package/src/lib/server/gate.d.ts +36 -0
- package/src/lib/server/gate.js +112 -0
- package/src/lib/server/gate.js.map +1 -0
- package/src/lib/server/gift-cards.d.ts +42 -0
- package/src/lib/server/gift-cards.js +219 -0
- package/src/lib/server/gift-cards.js.map +1 -0
- package/src/lib/server/low-stock.d.ts +49 -0
- package/src/lib/server/low-stock.js +60 -0
- package/src/lib/server/low-stock.js.map +1 -0
- package/src/lib/server/manual-tax-rate.d.ts +82 -0
- package/src/lib/server/manual-tax-rate.js +113 -0
- package/src/lib/server/manual-tax-rate.js.map +1 -0
- package/src/lib/server/member-feed.d.ts +24 -0
- package/src/lib/server/member-feed.js +72 -0
- package/src/lib/server/member-feed.js.map +1 -0
- package/src/lib/server/member-name-search.d.ts +37 -0
- package/src/lib/server/member-name-search.js +42 -0
- package/src/lib/server/member-name-search.js.map +1 -0
- package/src/lib/server/member-post.d.ts +23 -0
- package/src/lib/server/member-post.js +166 -0
- package/src/lib/server/member-post.js.map +1 -0
- package/src/lib/server/membership-account.d.ts +37 -0
- package/src/lib/server/membership-account.js +148 -0
- package/src/lib/server/membership-account.js.map +1 -0
- package/src/lib/server/membership-admin-password.d.ts +33 -0
- package/src/lib/server/membership-admin-password.js +202 -0
- package/src/lib/server/membership-admin-password.js.map +1 -0
- package/src/lib/server/membership-content.d.ts +23 -0
- package/src/lib/server/membership-content.js +105 -0
- package/src/lib/server/membership-content.js.map +1 -0
- package/src/lib/server/membership-login.d.ts +19 -0
- package/src/lib/server/membership-login.js +137 -0
- package/src/lib/server/membership-login.js.map +1 -0
- package/src/lib/server/membership-logout.d.ts +19 -0
- package/src/lib/server/membership-logout.js +35 -0
- package/src/lib/server/membership-logout.js.map +1 -0
- package/src/lib/server/membership-recover.d.ts +60 -0
- package/src/lib/server/membership-recover.js +244 -0
- package/src/lib/server/membership-recover.js.map +1 -0
- package/src/lib/server/membership-register.d.ts +22 -0
- package/src/lib/server/membership-register.js +241 -0
- package/src/lib/server/membership-register.js.map +1 -0
- package/src/lib/server/membership-reset.d.ts +26 -0
- package/src/lib/server/membership-reset.js +88 -0
- package/src/lib/server/membership-reset.js.map +1 -0
- package/src/lib/server/membership-wishlist.d.ts +23 -0
- package/src/lib/server/membership-wishlist.js +89 -0
- package/src/lib/server/membership-wishlist.js.map +1 -0
- package/src/lib/server/membership.d.ts +96 -0
- package/src/lib/server/membership.js +222 -0
- package/src/lib/server/membership.js.map +1 -0
- package/src/lib/server/native-checkout.d.ts +170 -0
- package/src/lib/server/native-checkout.js +193 -0
- package/src/lib/server/native-checkout.js.map +1 -0
- package/src/lib/server/newsletter.d.ts +23 -0
- package/src/lib/server/newsletter.js +323 -0
- package/src/lib/server/newsletter.js.map +1 -0
- package/src/lib/server/notify-restock.d.ts +22 -0
- package/src/lib/server/notify-restock.js +84 -0
- package/src/lib/server/notify-restock.js.map +1 -0
- package/src/lib/server/order-analytics.d.ts +134 -0
- package/src/lib/server/order-analytics.js +263 -0
- package/src/lib/server/order-analytics.js.map +1 -0
- package/src/lib/server/order-figures.d.ts +33 -0
- package/src/lib/server/order-figures.js +220 -0
- package/src/lib/server/order-figures.js.map +1 -0
- package/src/lib/server/paid-media-delivery.d.ts +173 -0
- package/src/lib/server/paid-media-delivery.js +212 -0
- package/src/lib/server/paid-media-delivery.js.map +1 -0
- package/src/lib/server/pos-order.d.ts +54 -0
- package/src/lib/server/pos-order.js +1137 -0
- package/src/lib/server/pos-order.js.map +1 -0
- package/src/lib/server/process-abandoned.d.ts +54 -0
- package/src/lib/server/process-abandoned.js +222 -0
- package/src/lib/server/process-abandoned.js.map +1 -0
- package/src/lib/server/process-restock.d.ts +42 -0
- package/src/lib/server/process-restock.js +219 -0
- package/src/lib/server/process-restock.js.map +1 -0
- package/src/lib/server/product-card.d.ts +29 -0
- package/src/lib/server/product-card.js +54 -0
- package/src/lib/server/product-card.js.map +1 -0
- package/src/lib/server/product.d.ts +70 -0
- package/src/lib/server/product.js +105 -0
- package/src/lib/server/product.js.map +1 -0
- package/src/lib/server/promotion-hold.d.ts +144 -0
- package/src/lib/server/promotion-hold.js +174 -0
- package/src/lib/server/promotion-hold.js.map +1 -0
- package/src/lib/server/reconcile-stock.d.ts +106 -0
- package/src/lib/server/reconcile-stock.js +349 -0
- package/src/lib/server/reconcile-stock.js.map +1 -0
- package/src/lib/server/refund.d.ts +45 -0
- package/src/lib/server/refund.js +607 -0
- package/src/lib/server/refund.js.map +1 -0
- package/src/lib/server/related.d.ts +24 -0
- package/src/lib/server/related.js +104 -0
- package/src/lib/server/related.js.map +1 -0
- package/src/lib/server/reservation-availability.d.ts +23 -0
- package/src/lib/server/reservation-availability.js +111 -0
- package/src/lib/server/reservation-availability.js.map +1 -0
- package/src/lib/server/reserve-stock.d.ts +156 -0
- package/src/lib/server/reserve-stock.js +146 -0
- package/src/lib/server/reserve-stock.js.map +1 -0
- package/src/lib/server/reserve.d.ts +25 -0
- package/src/lib/server/reserve.js +426 -0
- package/src/lib/server/reserve.js.map +1 -0
- package/src/lib/server/restock-flag.d.ts +202 -0
- package/src/lib/server/restock-flag.js +449 -0
- package/src/lib/server/restock-flag.js.map +1 -0
- package/src/lib/server/reviews.d.ts +51 -0
- package/src/lib/server/reviews.js +132 -0
- package/src/lib/server/reviews.js.map +1 -0
- package/src/lib/server/site-page-enricher.d.ts +42 -0
- package/src/lib/server/site-page-enricher.js +149 -0
- package/src/lib/server/site-page-enricher.js.map +1 -0
- package/src/lib/server/site-page-resolver.d.ts +26 -0
- package/src/lib/server/site-page-resolver.js +223 -0
- package/src/lib/server/site-page-resolver.js.map +1 -0
- package/src/lib/server/stock-hold.d.ts +127 -0
- package/src/lib/server/stock-hold.js +258 -0
- package/src/lib/server/stock-hold.js.map +1 -0
- package/src/lib/server/storefront-tax-record.d.ts +22 -0
- package/src/lib/server/storefront-tax-record.js +218 -0
- package/src/lib/server/storefront-tax-record.js.map +1 -0
- package/src/lib/server/storefront-tax.d.ts +197 -0
- package/src/lib/server/storefront-tax.js +245 -0
- package/src/lib/server/storefront-tax.js.map +1 -0
- package/src/lib/server/stream.d.ts +25 -0
- package/src/lib/server/stream.js +191 -0
- package/src/lib/server/stream.js.map +1 -0
- package/src/lib/server/subscription-portal.d.ts +24 -0
- package/src/lib/server/subscription-portal.js +91 -0
- package/src/lib/server/subscription-portal.js.map +1 -0
- package/src/lib/server/supplier-outbox.d.ts +190 -0
- package/src/lib/server/supplier-outbox.js +342 -0
- package/src/lib/server/supplier-outbox.js.map +1 -0
- package/src/lib/server/supplier-update.d.ts +23 -0
- package/src/lib/server/supplier-update.js +289 -0
- package/src/lib/server/supplier-update.js.map +1 -0
- package/src/lib/server/tax-profile.d.ts +29 -0
- package/src/lib/server/tax-profile.js +40 -0
- package/src/lib/server/tax-profile.js.map +1 -0
- package/src/lib/server.d.ts +32 -0
- package/src/lib/server.js +311 -0
- package/src/lib/server.js.map +1 -0
- package/src/lib/site.d.ts +27 -0
- package/src/lib/site.js +134 -0
- package/src/lib/site.js.map +1 -0
- package/src/lib/utils/escape-html.d.ts +41 -0
- package/src/lib/utils/escape-html.js +41 -0
- package/src/lib/utils/escape-html.js.map +1 -0
- package/src/lib/utils/generate-preset-id.d.ts +19 -0
- package/src/lib/utils/generate-preset-id.js +25 -0
- package/src/lib/utils/generate-preset-id.js.map +1 -0
- package/src/lib/utils/member-continue.d.ts +45 -0
- package/src/lib/utils/member-continue.js +49 -0
- package/src/lib/utils/member-continue.js.map +1 -0
- package/src/lib/utils/use-storefront-purchase-event.d.ts +60 -0
- package/src/lib/utils/use-storefront-purchase-event.js +142 -0
- package/src/lib/utils/use-storefront-purchase-event.js.map +1 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* How a storefront destination charge splits between Aglyn and the merchant —
|
|
18
|
+
* and, when Stripe Tax is on, why the split cannot be expressed as a fee
|
|
19
|
+
* (AGL-1956).
|
|
20
|
+
*
|
|
21
|
+
* ## The defect this module exists to close
|
|
22
|
+
*
|
|
23
|
+
* Every storefront checkout is a DESTINATION charge created on AGLYN's
|
|
24
|
+
* platform account: platform secret key, no `Stripe-Account` header, no
|
|
25
|
+
* `on_behalf_of`, with `payment_intent_data[transfer_data][destination]`
|
|
26
|
+
* naming the merchant's connected account. On a `mode: 'stripe'` store the
|
|
27
|
+
* session also carries `automatic_tax[enabled]`, and AGL-1904 MEASURED what
|
|
28
|
+
* that means: the tax is computed against **Aglyn's** registrations, reported
|
|
29
|
+
* as `automatic_tax.liability: { type: "self" }`, and is **Aglyn's to remit**.
|
|
30
|
+
* See `../server/storefront-tax.ts` for the two-arm experiment.
|
|
31
|
+
*
|
|
32
|
+
* The sessions then set `payment_intent_data[application_fee_amount]`. On a
|
|
33
|
+
* destination charge that form means Stripe transfers the **whole charge** to
|
|
34
|
+
* the connected account and debits the fee at the destination — measured, and
|
|
35
|
+
* recorded at `billing-webhook.ts` (the AGL-1794 note: "`transfer.amount`
|
|
36
|
+
* equals `charge.amount`"). `amount_total` INCLUDES the Stripe Tax.
|
|
37
|
+
*
|
|
38
|
+
* So on every taxed storefront sale the sales tax Aglyn owes the state was
|
|
39
|
+
* transferred to the merchant, and only the commission came back. Aglyn was
|
|
40
|
+
* left holding the liability and none of the money. This is the same trap the
|
|
41
|
+
* marketplace plugin found and closed in AGL-1544, and the fix here is the
|
|
42
|
+
* same one: **a fixed `transfer_data[amount]`, and no `application_fee_amount`
|
|
43
|
+
* at all** — because the fee form makes Stripe do the arithmetic on a total
|
|
44
|
+
* that has the tax inside it.
|
|
45
|
+
*
|
|
46
|
+
* ## Only ONE of the two knobs may do the arithmetic
|
|
47
|
+
*
|
|
48
|
+
* `application_fee_amount` says "give the merchant everything except this".
|
|
49
|
+
* `transfer_data[amount]` says "give the merchant exactly this". They are two
|
|
50
|
+
* spellings of the same split and Stripe rejects a PaymentIntent carrying
|
|
51
|
+
* both, so the emitter below is written as a single choice with no path that
|
|
52
|
+
* can emit the pair. Which one is correct depends entirely on WHICH SIDE of
|
|
53
|
+
* the split holds the unknown:
|
|
54
|
+
*
|
|
55
|
+
* - **Merchant owes the tax** (`manual` mode, or no tax at all). The
|
|
56
|
+
* variable part — the merchant's tax line — is the merchant's own money.
|
|
57
|
+
* Fixing the FEE is exact: Aglyn keeps its commission and every cent of
|
|
58
|
+
* variance stays where it belongs.
|
|
59
|
+
* - **Aglyn owes the tax** (`stripe` mode). The variable part is now
|
|
60
|
+
* AGLYN's money, and a fixed fee hands all of it to the merchant. Fixing
|
|
61
|
+
* the TRANSFER is what keeps it.
|
|
62
|
+
*
|
|
63
|
+
* ## The residual, stated out loud: shopper-chosen shipping
|
|
64
|
+
*
|
|
65
|
+
* Neither knob can be exact on a Stripe Tax sale that also offers a CHOICE of
|
|
66
|
+
* shipping rates, because at session-creation time two numbers are unknown —
|
|
67
|
+
* the tax (Aglyn's) and which shipping option the shopper will pick (the
|
|
68
|
+
* merchant's) — and there is only one knob left to fix. Whichever is fixed,
|
|
69
|
+
* the other side's variance lands on the wrong party:
|
|
70
|
+
*
|
|
71
|
+
* - Fixing the FEE misallocates the ENTIRE tax, on EVERY taxed sale,
|
|
72
|
+
* unbounded. That is the defect above.
|
|
73
|
+
* - Fixing the TRANSFER misallocates at most `dearest − cheapest` shipping,
|
|
74
|
+
* and only on a store that offers more than one rate.
|
|
75
|
+
*
|
|
76
|
+
* The transfer is therefore fixed at the CHEAPEST option, never the dearest.
|
|
77
|
+
* Not a preference — the dearest is unsafe: a transfer of
|
|
78
|
+
* `goods + dearest − fee` can EXCEED a charge where the shopper picked the
|
|
79
|
+
* cheapest, and Stripe rejects a transfer larger than its charge, which would
|
|
80
|
+
* fail the payment outright rather than mis-split it. The cheapest is always
|
|
81
|
+
* payable, because the shopper's actual shipping can only be higher.
|
|
82
|
+
*
|
|
83
|
+
* The bounded remainder — a shopper who upgraded shipping on a Stripe Tax
|
|
84
|
+
* store — is money owed to the MERCHANT that Aglyn is holding. It is recorded
|
|
85
|
+
* on the session as `metadata[transferCents]` and
|
|
86
|
+
* `metadata[transferShippingCents]` so it is derivable per order rather than
|
|
87
|
+
* lost, and closing it needs a top-up transfer at
|
|
88
|
+
* `checkout.session.completed`, which is a new outbound money path and is
|
|
89
|
+
* deliberately NOT bundled with this fix. Tracked on AGL-1956.
|
|
90
|
+
*
|
|
91
|
+
* Pure and total: integer cents in, integer cents out, no clamping surprises
|
|
92
|
+
* except the documented floor at zero.
|
|
93
|
+
*/ /** Which party's registrations the tax on this sale was computed against. */ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
94
|
+
/**
|
|
95
|
+
* What the merchant is paid, in cents, when AGLYN owes the tax.
|
|
96
|
+
*
|
|
97
|
+
* `goods + cheapest shipping − fee`, floored at zero. The floor is a real
|
|
98
|
+
* case, not defensive padding: `resolveTransactionFeeCents` adds Stripe's
|
|
99
|
+
* fixed 30¢ card cost, so a sub-dollar order can carry a fee worth more than
|
|
100
|
+
* the goods. The merchant is paid nothing on such an order, which is the
|
|
101
|
+
* honest outcome — Aglyn is out of pocket on it either way — and it must
|
|
102
|
+
* never be expressed as a NEGATIVE transfer, which Stripe rejects.
|
|
103
|
+
*/ export function platformLiableTransferCents(split) {
|
|
104
|
+
var _split_merchantGoodsCents, _split_shippingFloorCents, _split_feeCents;
|
|
105
|
+
const goods = Math.max(0, Math.round(Number((_split_merchantGoodsCents = split.merchantGoodsCents) != null ? _split_merchantGoodsCents : 0)));
|
|
106
|
+
const shipping = Math.max(0, Math.round(Number((_split_shippingFloorCents = split.shippingFloorCents) != null ? _split_shippingFloorCents : 0)));
|
|
107
|
+
const fee = Math.max(0, Math.round(Number((_split_feeCents = split.feeCents) != null ? _split_feeCents : 0)));
|
|
108
|
+
return Math.max(0, goods + shipping - fee);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Which party's registrations a subscription invoice's tax was computed
|
|
112
|
+
* against — the same `taxOwner` distinction `destinationChargeParams` makes,
|
|
113
|
+
* read off the invoice instead of off the store's settings.
|
|
114
|
+
*
|
|
115
|
+
* `automatic_tax.enabled` is THE discriminator and the tax lines are never it,
|
|
116
|
+
* for the reason `storefront-tax.ts` states at length: a MANUAL-rate
|
|
117
|
+
* subscription carries a real Stripe Tax Rate on its line (AGL-1751), so every
|
|
118
|
+
* cycle it bills arrives with a populated `total_taxes[]` that is
|
|
119
|
+
* indistinguishable from a Stripe Tax one by shape. Reading the lines would
|
|
120
|
+
* reverse the merchant's OWN tax out of their payout on every cycle — the
|
|
121
|
+
* failure that steals from the merchant rather than from the state.
|
|
122
|
+
*
|
|
123
|
+
* `liability.type === 'account'` means Stripe computed against the CONNECTED
|
|
124
|
+
* account's registrations, so the tax is theirs and stays with them. `self`,
|
|
125
|
+
* and an absent liability (older API versions omit the field, where the only
|
|
126
|
+
* account a platform-created invoice could be liable under is the platform),
|
|
127
|
+
* mean Aglyn. This mirrors `storefrontTaxRow` exactly, deliberately: the filed
|
|
128
|
+
* tax record and the reversal must not be able to disagree about who owed it.
|
|
129
|
+
*/ export function subscriptionInvoiceTaxOwner(invoice) {
|
|
130
|
+
var _source_automatic_tax, _source_automatic_tax_liability, _source_automatic_tax1;
|
|
131
|
+
const source = invoice;
|
|
132
|
+
if ((source == null ? void 0 : (_source_automatic_tax = source.automatic_tax) == null ? void 0 : _source_automatic_tax.enabled) !== true) return 'merchant';
|
|
133
|
+
return (source == null ? void 0 : (_source_automatic_tax1 = source.automatic_tax) == null ? void 0 : (_source_automatic_tax_liability = _source_automatic_tax1.liability) == null ? void 0 : _source_automatic_tax_liability.type) === 'account' ? 'merchant' : 'platform';
|
|
134
|
+
}
|
|
135
|
+
/** See `SubscriptionTaxReversalDecision`. */ export function subscriptionInvoiceTaxReversal(invoice) {
|
|
136
|
+
const source = invoice;
|
|
137
|
+
if (subscriptionInvoiceTaxOwner(source) === 'merchant') {
|
|
138
|
+
return {
|
|
139
|
+
kind: 'skip',
|
|
140
|
+
reason: 'merchant-tax'
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
const settle = (cents)=>cents > 0 ? {
|
|
144
|
+
kind: 'reverse',
|
|
145
|
+
taxCents: cents
|
|
146
|
+
} : {
|
|
147
|
+
kind: 'skip',
|
|
148
|
+
reason: 'no-tax'
|
|
149
|
+
};
|
|
150
|
+
// `typeof === 'number'` and NOT `Number(…)`, because `Number(null)` is a
|
|
151
|
+
// finite 0 and `null` is how an absent field arrives over JSON. Treating it
|
|
152
|
+
// as a stated zero is precisely the swallow this type exists to prevent.
|
|
153
|
+
const scalar = source == null ? void 0 : source.tax;
|
|
154
|
+
if (typeof scalar === 'number' && Number.isFinite(scalar)) {
|
|
155
|
+
return settle(Math.round(scalar));
|
|
156
|
+
}
|
|
157
|
+
// `total_taxes` replaced `total_tax_amounts`, which replaced the scalar; they
|
|
158
|
+
// do not coexist, so this cannot double-count.
|
|
159
|
+
const lines = Array.isArray(source == null ? void 0 : source.total_taxes) ? source.total_taxes : Array.isArray(source == null ? void 0 : source.total_tax_amounts) ? source.total_tax_amounts : null;
|
|
160
|
+
if (lines) {
|
|
161
|
+
let sum = 0;
|
|
162
|
+
for (const line of lines){
|
|
163
|
+
var _ref;
|
|
164
|
+
const amount = Number((_ref = line == null ? void 0 : line.amount) != null ? _ref : NaN);
|
|
165
|
+
// One unreadable line poisons the sum: a partial total would reverse
|
|
166
|
+
// LESS than the state is owed and look like a successful correction.
|
|
167
|
+
if (!Number.isFinite(amount)) {
|
|
168
|
+
return {
|
|
169
|
+
kind: 'unreadable',
|
|
170
|
+
reason: 'a tax line on the invoice states no readable `amount`'
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
sum += amount;
|
|
174
|
+
}
|
|
175
|
+
return settle(Math.round(sum));
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
kind: 'unreadable',
|
|
179
|
+
reason: 'the invoice enables automatic tax but states no `tax`, `total_taxes` ' + 'or `total_tax_amounts` — the Stripe API version may have moved the field'
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* The cheapest rate on a resolved shipping plan, in cents. `0` for a plan with
|
|
184
|
+
* no options, which is also the right transfer contribution for a store that
|
|
185
|
+
* charges no shipping.
|
|
186
|
+
*/ export function shippingFloorCents(options = []) {
|
|
187
|
+
if (options.length === 0) return 0;
|
|
188
|
+
return options.reduce((least, option)=>{
|
|
189
|
+
var _ref;
|
|
190
|
+
return Math.min(least, Math.max(0, Math.round(Number((_ref = option == null ? void 0 : option.amountCents) != null ? _ref : 0))));
|
|
191
|
+
}, Number.POSITIVE_INFINITY);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* The Connect keys for a storefront destination charge — the destination, and
|
|
195
|
+
* EXACTLY ONE of `application_fee_amount` / `transfer_data[amount]`.
|
|
196
|
+
*
|
|
197
|
+
* Emitted from one place so no checkout path can pick the wrong knob on its
|
|
198
|
+
* own, and so the pair can never both appear (Stripe rejects that, and the two
|
|
199
|
+
* would be contradicting each other about the same split).
|
|
200
|
+
*
|
|
201
|
+
* The `metadata[transferCents]` companion is deliberately NOT emitted here —
|
|
202
|
+
* each caller owns its own metadata block, and the value is
|
|
203
|
+
* `platformLiableTransferCents(split)`.
|
|
204
|
+
*/ export function destinationChargeParams(split) {
|
|
205
|
+
var _split_feeCents;
|
|
206
|
+
const destination = {
|
|
207
|
+
'payment_intent_data[transfer_data][destination]': String(split.accountId)
|
|
208
|
+
};
|
|
209
|
+
const fee = Math.max(0, Math.round(Number((_split_feeCents = split.feeCents) != null ? _split_feeCents : 0)));
|
|
210
|
+
if (split.taxOwner === 'platform') {
|
|
211
|
+
// AGLYN OWES THE TAX, SO AGLYN MUST KEEP IT (AGL-1956). A fixed transfer
|
|
212
|
+
// is the only form that expresses that: `application_fee_amount` would
|
|
213
|
+
// make Stripe compute `amount_total − fee`, and `amount_total` has the
|
|
214
|
+
// Stripe Tax inside it. Emitted even when it is zero — a zero transfer is
|
|
215
|
+
// a real, correct answer for a sub-dollar order (see
|
|
216
|
+
// `platformLiableTransferCents`), and OMITTING the key would silently
|
|
217
|
+
// restore the full-charge transfer this whole module exists to prevent.
|
|
218
|
+
return _extends({}, destination, {
|
|
219
|
+
'payment_intent_data[transfer_data][amount]': String(platformLiableTransferCents(split))
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
// The merchant owns the tax on this sale, so the merchant may hold it: the
|
|
223
|
+
// fee form is exact here and is left byte-identical to what these paths
|
|
224
|
+
// sent before AGL-1956. Stripe rejects a zero application fee, so a fee that
|
|
225
|
+
// rounded to nothing sends no key at all.
|
|
226
|
+
return _extends({}, destination, fee > 0 ? {
|
|
227
|
+
'payment_intent_data[application_fee_amount]': String(fee)
|
|
228
|
+
} : {});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
//# sourceMappingURL=commerce-connect-transfer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/model/commerce-connect-transfer.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * How a storefront destination charge splits between Aglyn and the merchant —\n * and, when Stripe Tax is on, why the split cannot be expressed as a fee\n * (AGL-1956).\n *\n * ## The defect this module exists to close\n *\n * Every storefront checkout is a DESTINATION charge created on AGLYN's\n * platform account: platform secret key, no `Stripe-Account` header, no\n * `on_behalf_of`, with `payment_intent_data[transfer_data][destination]`\n * naming the merchant's connected account. On a `mode: 'stripe'` store the\n * session also carries `automatic_tax[enabled]`, and AGL-1904 MEASURED what\n * that means: the tax is computed against **Aglyn's** registrations, reported\n * as `automatic_tax.liability: { type: \"self\" }`, and is **Aglyn's to remit**.\n * See `../server/storefront-tax.ts` for the two-arm experiment.\n *\n * The sessions then set `payment_intent_data[application_fee_amount]`. On a\n * destination charge that form means Stripe transfers the **whole charge** to\n * the connected account and debits the fee at the destination — measured, and\n * recorded at `billing-webhook.ts` (the AGL-1794 note: \"`transfer.amount`\n * equals `charge.amount`\"). `amount_total` INCLUDES the Stripe Tax.\n *\n * So on every taxed storefront sale the sales tax Aglyn owes the state was\n * transferred to the merchant, and only the commission came back. Aglyn was\n * left holding the liability and none of the money. This is the same trap the\n * marketplace plugin found and closed in AGL-1544, and the fix here is the\n * same one: **a fixed `transfer_data[amount]`, and no `application_fee_amount`\n * at all** — because the fee form makes Stripe do the arithmetic on a total\n * that has the tax inside it.\n *\n * ## Only ONE of the two knobs may do the arithmetic\n *\n * `application_fee_amount` says \"give the merchant everything except this\".\n * `transfer_data[amount]` says \"give the merchant exactly this\". They are two\n * spellings of the same split and Stripe rejects a PaymentIntent carrying\n * both, so the emitter below is written as a single choice with no path that\n * can emit the pair. Which one is correct depends entirely on WHICH SIDE of\n * the split holds the unknown:\n *\n * - **Merchant owes the tax** (`manual` mode, or no tax at all). The\n * variable part — the merchant's tax line — is the merchant's own money.\n * Fixing the FEE is exact: Aglyn keeps its commission and every cent of\n * variance stays where it belongs.\n * - **Aglyn owes the tax** (`stripe` mode). The variable part is now\n * AGLYN's money, and a fixed fee hands all of it to the merchant. Fixing\n * the TRANSFER is what keeps it.\n *\n * ## The residual, stated out loud: shopper-chosen shipping\n *\n * Neither knob can be exact on a Stripe Tax sale that also offers a CHOICE of\n * shipping rates, because at session-creation time two numbers are unknown —\n * the tax (Aglyn's) and which shipping option the shopper will pick (the\n * merchant's) — and there is only one knob left to fix. Whichever is fixed,\n * the other side's variance lands on the wrong party:\n *\n * - Fixing the FEE misallocates the ENTIRE tax, on EVERY taxed sale,\n * unbounded. That is the defect above.\n * - Fixing the TRANSFER misallocates at most `dearest − cheapest` shipping,\n * and only on a store that offers more than one rate.\n *\n * The transfer is therefore fixed at the CHEAPEST option, never the dearest.\n * Not a preference — the dearest is unsafe: a transfer of\n * `goods + dearest − fee` can EXCEED a charge where the shopper picked the\n * cheapest, and Stripe rejects a transfer larger than its charge, which would\n * fail the payment outright rather than mis-split it. The cheapest is always\n * payable, because the shopper's actual shipping can only be higher.\n *\n * The bounded remainder — a shopper who upgraded shipping on a Stripe Tax\n * store — is money owed to the MERCHANT that Aglyn is holding. It is recorded\n * on the session as `metadata[transferCents]` and\n * `metadata[transferShippingCents]` so it is derivable per order rather than\n * lost, and closing it needs a top-up transfer at\n * `checkout.session.completed`, which is a new outbound money path and is\n * deliberately NOT bundled with this fix. Tracked on AGL-1956.\n *\n * Pure and total: integer cents in, integer cents out, no clamping surprises\n * except the documented floor at zero.\n */\n\n/** Which party's registrations the tax on this sale was computed against. */\nexport type StorefrontTaxOwner = 'platform' | 'merchant'\n\nexport interface DestinationChargeSplit {\n /** The merchant's connected account id. */\n accountId: string\n /**\n * Aglyn's take in cents — the advertised platform fee plus the passed-through\n * card cost (`resolveTransactionFeeCents`). Never negative.\n */\n feeCents: number\n /**\n * `platform` when the session carries `automatic_tax[enabled]` and Stripe\n * Tax computes against Aglyn's registrations (AGL-1904). `merchant` for a\n * `manual` rate the merchant set and owes, and for an untaxed sale.\n */\n taxOwner: StorefrontTaxOwner\n /**\n * What Stripe will charge for the GOODS — after any coupon is priced in, and\n * excluding shipping and every tax line. The merchant's money.\n */\n merchantGoodsCents: number\n /**\n * The CHEAPEST shipping option offered on this session, or 0 when the\n * merchant offers none. See the module note on why this is the cheapest and\n * not the dearest.\n */\n shippingFloorCents?: number\n}\n\n/**\n * What the merchant is paid, in cents, when AGLYN owes the tax.\n *\n * `goods + cheapest shipping − fee`, floored at zero. The floor is a real\n * case, not defensive padding: `resolveTransactionFeeCents` adds Stripe's\n * fixed 30¢ card cost, so a sub-dollar order can carry a fee worth more than\n * the goods. The merchant is paid nothing on such an order, which is the\n * honest outcome — Aglyn is out of pocket on it either way — and it must\n * never be expressed as a NEGATIVE transfer, which Stripe rejects.\n */\nexport function platformLiableTransferCents(\n split: Pick<\n DestinationChargeSplit,\n 'feeCents' | 'merchantGoodsCents' | 'shippingFloorCents'\n >,\n): number {\n const goods = Math.max(0, Math.round(Number(split.merchantGoodsCents ?? 0)))\n const shipping = Math.max(0, Math.round(Number(split.shippingFloorCents ?? 0)))\n const fee = Math.max(0, Math.round(Number(split.feeCents ?? 0)))\n return Math.max(0, goods + shipping - fee)\n}\n\n/**\n * What a paid SUBSCRIPTION invoice says about the tax on it, and therefore\n * whether the platform has to pull that tax back out of the transfer\n * (AGL-1956).\n *\n * ## Why the recurring path needs a different instrument entirely\n *\n * Everything above is about a knob set when the charge is CREATED. A Stripe\n * Subscription has neither knob: it accepts no `transfer_data[amount]`, only\n * `application_fee_percent`. On a destination charge that means Stripe\n * transfers the WHOLE charge to the connected account and debits the fee at\n * the destination, and the charge has the Stripe Tax inside it — so the\n * merchant is handed the state's money on every taxed cycle. `checkout.ts`\n * therefore excludes subscriptions from `destinationChargeParams` and leaves\n * them on the fee form.\n *\n * AGL-2317 makes that strictly worse, not better. It refunds the part of the\n * application fee that was taken on tax and shipping BACK to the connected\n * account, which is right on its own terms (Aglyn's advertised cut is a cut of\n * sales) but means the merchant ends the cycle holding **one hundred percent**\n * of a tax Aglyn is the one registered to remit.\n *\n * ## The money is already at the merchant, so the correction is a REVERSAL\n *\n * Worth stating explicitly, because the sign is easy to get backwards and this\n * module documents a residual that runs the OTHER way. The shipping residual\n * above is a case where the transfer was FIXED too low and the merchant is\n * owed more — that one needs a top-up. This is the opposite: the fee form\n * OVER-transfers, the tax is physically sitting in the connected account's\n * balance, and the only instrument that moves it back to the platform is a\n * transfer reversal. A top-up here would pay the merchant the tax twice.\n *\n * ## Three answers, never two\n *\n * The whole point of the three-state is that **a missing tax field must not\n * read as \"no tax\"**. Stripe removed the scalar `invoice.tax` in favour of\n * `total_taxes[]`, and which spelling an endpoint receives is dashboard\n * configuration this repo cannot see. A reader that reached for one field and\n * defaulted the miss to `0` would answer \"no reversal\" on every invoice after\n * a Stripe version bump nobody here can observe — a swallowed read rendering\n * as a measured zero, with the money going the wrong way and nothing looking\n * wrong. So an invoice that claims automatic tax while stating NO tax field at\n * all is `unreadable`, and the caller is required to make noise about it.\n *\n * A `tax: 0`, or a present-but-empty `total_taxes: []`, is a real answer and\n * is `skip`. That is also what a $0 or fully-discounted invoice produces, which\n * is why the no-op costs nothing.\n *\n * Pure and total: no throw, no clamping beyond the documented floor at zero.\n */\nexport type SubscriptionTaxReversalDecision =\n /** Aglyn owes this tax and the merchant is holding it. Pull back exactly this. */\n | { kind: 'reverse'; taxCents: number }\n /** Nothing to do, and nothing wrong. No network call is warranted. */\n | { kind: 'skip'; reason: 'merchant-tax' | 'no-tax' }\n /** The invoice claims tax it will not state. LOUD, never silent. */\n | { kind: 'unreadable'; reason: string }\n\n/**\n * Which party's registrations a subscription invoice's tax was computed\n * against — the same `taxOwner` distinction `destinationChargeParams` makes,\n * read off the invoice instead of off the store's settings.\n *\n * `automatic_tax.enabled` is THE discriminator and the tax lines are never it,\n * for the reason `storefront-tax.ts` states at length: a MANUAL-rate\n * subscription carries a real Stripe Tax Rate on its line (AGL-1751), so every\n * cycle it bills arrives with a populated `total_taxes[]` that is\n * indistinguishable from a Stripe Tax one by shape. Reading the lines would\n * reverse the merchant's OWN tax out of their payout on every cycle — the\n * failure that steals from the merchant rather than from the state.\n *\n * `liability.type === 'account'` means Stripe computed against the CONNECTED\n * account's registrations, so the tax is theirs and stays with them. `self`,\n * and an absent liability (older API versions omit the field, where the only\n * account a platform-created invoice could be liable under is the platform),\n * mean Aglyn. This mirrors `storefrontTaxRow` exactly, deliberately: the filed\n * tax record and the reversal must not be able to disagree about who owed it.\n */\nexport function subscriptionInvoiceTaxOwner(\n invoice: unknown,\n): StorefrontTaxOwner {\n const source = invoice as any\n if (source?.automatic_tax?.enabled !== true) return 'merchant'\n return source?.automatic_tax?.liability?.type === 'account'\n ? 'merchant'\n : 'platform'\n}\n\n/** See `SubscriptionTaxReversalDecision`. */\nexport function subscriptionInvoiceTaxReversal(\n invoice: unknown,\n): SubscriptionTaxReversalDecision {\n const source = invoice as any\n if (subscriptionInvoiceTaxOwner(source) === 'merchant') {\n return { kind: 'skip', reason: 'merchant-tax' }\n }\n const settle = (cents: number): SubscriptionTaxReversalDecision =>\n cents > 0\n ? { kind: 'reverse', taxCents: cents }\n : { kind: 'skip', reason: 'no-tax' }\n\n // `typeof === 'number'` and NOT `Number(…)`, because `Number(null)` is a\n // finite 0 and `null` is how an absent field arrives over JSON. Treating it\n // as a stated zero is precisely the swallow this type exists to prevent.\n const scalar = source?.tax\n if (typeof scalar === 'number' && Number.isFinite(scalar)) {\n return settle(Math.round(scalar))\n }\n // `total_taxes` replaced `total_tax_amounts`, which replaced the scalar; they\n // do not coexist, so this cannot double-count.\n const lines = Array.isArray(source?.total_taxes)\n ? source.total_taxes\n : Array.isArray(source?.total_tax_amounts)\n ? source.total_tax_amounts\n : null\n if (lines) {\n let sum = 0\n for (const line of lines) {\n const amount = Number((line as any)?.amount ?? NaN)\n // One unreadable line poisons the sum: a partial total would reverse\n // LESS than the state is owed and look like a successful correction.\n if (!Number.isFinite(amount)) {\n return {\n kind: 'unreadable',\n reason: 'a tax line on the invoice states no readable `amount`',\n }\n }\n sum += amount\n }\n return settle(Math.round(sum))\n }\n return {\n kind: 'unreadable',\n reason:\n 'the invoice enables automatic tax but states no `tax`, `total_taxes` ' +\n 'or `total_tax_amounts` — the Stripe API version may have moved the field',\n }\n}\n\n/**\n * The cheapest rate on a resolved shipping plan, in cents. `0` for a plan with\n * no options, which is also the right transfer contribution for a store that\n * charges no shipping.\n */\nexport function shippingFloorCents(\n options: readonly { amountCents?: unknown }[] = [],\n): number {\n if (options.length === 0) return 0\n return options.reduce(\n (least, option) =>\n Math.min(\n least,\n Math.max(0, Math.round(Number(option?.amountCents ?? 0))),\n ),\n Number.POSITIVE_INFINITY,\n )\n}\n\n/**\n * The Connect keys for a storefront destination charge — the destination, and\n * EXACTLY ONE of `application_fee_amount` / `transfer_data[amount]`.\n *\n * Emitted from one place so no checkout path can pick the wrong knob on its\n * own, and so the pair can never both appear (Stripe rejects that, and the two\n * would be contradicting each other about the same split).\n *\n * The `metadata[transferCents]` companion is deliberately NOT emitted here —\n * each caller owns its own metadata block, and the value is\n * `platformLiableTransferCents(split)`.\n */\nexport function destinationChargeParams(\n split: DestinationChargeSplit,\n): Record<string, string> {\n const destination = {\n 'payment_intent_data[transfer_data][destination]': String(split.accountId),\n }\n const fee = Math.max(0, Math.round(Number(split.feeCents ?? 0)))\n if (split.taxOwner === 'platform') {\n // AGLYN OWES THE TAX, SO AGLYN MUST KEEP IT (AGL-1956). A fixed transfer\n // is the only form that expresses that: `application_fee_amount` would\n // make Stripe compute `amount_total − fee`, and `amount_total` has the\n // Stripe Tax inside it. Emitted even when it is zero — a zero transfer is\n // a real, correct answer for a sub-dollar order (see\n // `platformLiableTransferCents`), and OMITTING the key would silently\n // restore the full-charge transfer this whole module exists to prevent.\n return {\n ...destination,\n 'payment_intent_data[transfer_data][amount]': String(\n platformLiableTransferCents(split),\n ),\n }\n }\n // The merchant owns the tax on this sale, so the merchant may hold it: the\n // fee form is exact here and is left byte-identical to what these paths\n // sent before AGL-1956. Stripe rejects a zero application fee, so a fee that\n // rounded to nothing sends no key at all.\n return {\n ...destination,\n ...(fee > 0\n ? { 'payment_intent_data[application_fee_amount]': String(fee) }\n : {}),\n }\n}\n"],"names":["platformLiableTransferCents","split","goods","Math","max","round","Number","merchantGoodsCents","shipping","shippingFloorCents","fee","feeCents","subscriptionInvoiceTaxOwner","invoice","source","automatic_tax","enabled","liability","type","subscriptionInvoiceTaxReversal","kind","reason","settle","cents","taxCents","scalar","tax","isFinite","lines","Array","isArray","total_taxes","total_tax_amounts","sum","line","amount","NaN","options","length","reduce","least","option","min","amountCents","POSITIVE_INFINITY","destinationChargeParams","destination","String","accountId","taxOwner"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6EC,GAED,2EAA2E;AA8B3E;;;;;;;;;CASC,GACD,OAAO,SAASA,4BACdC,KAGC;QAE2CA,2BACGA,2BACLA;IAF1C,MAAMC,QAAQC,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,CAACC,QAAOL,4BAAAA,MAAMM,kBAAkB,YAAxBN,4BAA4B;IACxE,MAAMO,WAAWL,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,CAACC,QAAOL,4BAAAA,MAAMQ,kBAAkB,YAAxBR,4BAA4B;IAC3E,MAAMS,MAAMP,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,CAACC,QAAOL,kBAAAA,MAAMU,QAAQ,YAAdV,kBAAkB;IAC5D,OAAOE,KAAKC,GAAG,CAAC,GAAGF,QAAQM,WAAWE;AACxC;AA4DA;;;;;;;;;;;;;;;;;;;CAmBC,GACD,OAAO,SAASE,4BACdC,OAAgB;QAGZC,uBACGA,iCAAAA;IAFP,MAAMA,SAASD;IACf,IAAIC,CAAAA,2BAAAA,wBAAAA,OAAQC,aAAa,qBAArBD,sBAAuBE,OAAO,MAAK,MAAM,OAAO;IACpD,OAAOF,CAAAA,2BAAAA,yBAAAA,OAAQC,aAAa,sBAArBD,kCAAAA,uBAAuBG,SAAS,qBAAhCH,gCAAkCI,IAAI,MAAK,YAC9C,aACA;AACN;AAEA,2CAA2C,GAC3C,OAAO,SAASC,+BACdN,OAAgB;IAEhB,MAAMC,SAASD;IACf,IAAID,4BAA4BE,YAAY,YAAY;QACtD,OAAO;YAAEM,MAAM;YAAQC,QAAQ;QAAe;IAChD;IACA,MAAMC,SAAS,CAACC,QACdA,QAAQ,IACJ;YAAEH,MAAM;YAAWI,UAAUD;QAAM,IACnC;YAAEH,MAAM;YAAQC,QAAQ;QAAS;IAEvC,yEAAyE;IACzE,4EAA4E;IAC5E,yEAAyE;IACzE,MAAMI,SAASX,0BAAAA,OAAQY,GAAG;IAC1B,IAAI,OAAOD,WAAW,YAAYnB,OAAOqB,QAAQ,CAACF,SAAS;QACzD,OAAOH,OAAOnB,KAAKE,KAAK,CAACoB;IAC3B;IACA,8EAA8E;IAC9E,+CAA+C;IAC/C,MAAMG,QAAQC,MAAMC,OAAO,CAAChB,0BAAAA,OAAQiB,WAAW,IAC3CjB,OAAOiB,WAAW,GAClBF,MAAMC,OAAO,CAAChB,0BAAAA,OAAQkB,iBAAiB,IACrClB,OAAOkB,iBAAiB,GACxB;IACN,IAAIJ,OAAO;QACT,IAAIK,MAAM;QACV,KAAK,MAAMC,QAAQN,MAAO;;YACxB,MAAMO,SAAS7B,eAAQ4B,wBAAD,AAACA,KAAcC,MAAM,mBAAIC;YAC/C,qEAAqE;YACrE,qEAAqE;YACrE,IAAI,CAAC9B,OAAOqB,QAAQ,CAACQ,SAAS;gBAC5B,OAAO;oBACLf,MAAM;oBACNC,QAAQ;gBACV;YACF;YACAY,OAAOE;QACT;QACA,OAAOb,OAAOnB,KAAKE,KAAK,CAAC4B;IAC3B;IACA,OAAO;QACLb,MAAM;QACNC,QACE,0EACA;IACJ;AACF;AAEA;;;;CAIC,GACD,OAAO,SAASZ,mBACd4B,UAAgD,EAAE;IAElD,IAAIA,QAAQC,MAAM,KAAK,GAAG,OAAO;IACjC,OAAOD,QAAQE,MAAM,CACnB,CAACC,OAAOC;;eACNtC,KAAKuC,GAAG,CACNF,OACArC,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,CAACC,eAAOmC,0BAAAA,OAAQE,WAAW,mBAAI;OAEzDrC,OAAOsC,iBAAiB;AAE5B;AAEA;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,wBACd5C,KAA6B;QAKaA;IAH1C,MAAM6C,cAAc;QAClB,mDAAmDC,OAAO9C,MAAM+C,SAAS;IAC3E;IACA,MAAMtC,MAAMP,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,CAACC,QAAOL,kBAAAA,MAAMU,QAAQ,YAAdV,kBAAkB;IAC5D,IAAIA,MAAMgD,QAAQ,KAAK,YAAY;QACjC,yEAAyE;QACzE,uEAAuE;QACvE,uEAAuE;QACvE,0EAA0E;QAC1E,qDAAqD;QACrD,sEAAsE;QACtE,wEAAwE;QACxE,OAAO,aACFH;YACH,8CAA8CC,OAC5C/C,4BAA4BC;;IAGlC;IACA,2EAA2E;IAC3E,wEAAwE;IACxE,6EAA6E;IAC7E,0CAA0C;IAC1C,OAAO,aACF6C,aACCpC,MAAM,IACN;QAAE,+CAA+CqC,OAAOrC;IAAK,IAC7D,CAAC;AAET"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Discounts engine v2 (AGL-305): code-based AND automatic promotions
|
|
19
|
+
* with scoping, schedules, and usage limits, superseding the AGL-96
|
|
20
|
+
* percent-only coupons (which keep working through the legacy path).
|
|
21
|
+
* One resolver serves cart, checkout, and POS. Docs live at
|
|
22
|
+
* `hosts/{hostId}/discounts`. Pure — callers own I/O and redemption
|
|
23
|
+
* increments.
|
|
24
|
+
*/
|
|
25
|
+
import { type PromotionHold } from './commerce-promotions';
|
|
26
|
+
export type DiscountKind = 'percent' | 'fixed' | 'free_shipping';
|
|
27
|
+
/** `hosts/{hostId}/discounts/{id}` doc. */
|
|
28
|
+
export interface HostDiscount {
|
|
29
|
+
/** Uppercase entry code; absent = automatic (applies to every cart). */
|
|
30
|
+
code?: string;
|
|
31
|
+
/** Display name for automatic promotions ("Summer sale"). */
|
|
32
|
+
name?: string;
|
|
33
|
+
kind: DiscountKind;
|
|
34
|
+
/** percent kind: 1-100. */
|
|
35
|
+
valuePct?: number;
|
|
36
|
+
/** fixed kind: cents off the items subtotal. */
|
|
37
|
+
valueCents?: number;
|
|
38
|
+
/** Only carts at/above this subtotal qualify. */
|
|
39
|
+
minSubtotalCents?: number;
|
|
40
|
+
/** Scope: at least one cart line must be one of these products. */
|
|
41
|
+
productIds?: string[];
|
|
42
|
+
maxRedemptions?: number;
|
|
43
|
+
redemptions?: number;
|
|
44
|
+
/**
|
|
45
|
+
* In-flight claims on the remaining slots (AGL-2453), keyed by checkout
|
|
46
|
+
* attempt. Counted as redeemed by {@link applies} for as long as they stand,
|
|
47
|
+
* which is what stops N concurrent checkouts all passing a cap of one.
|
|
48
|
+
*/
|
|
49
|
+
holds?: Record<string, PromotionHold>;
|
|
50
|
+
startAtMs?: number;
|
|
51
|
+
endAtMs?: number;
|
|
52
|
+
enabled?: boolean;
|
|
53
|
+
}
|
|
54
|
+
/** A discount proposed for a store, before anyone has switched it on (AGL-2916). */
|
|
55
|
+
export interface ProposedDiscount {
|
|
56
|
+
name: string;
|
|
57
|
+
/** The code a shopper types, or `null` for a discount that applies on its own. */
|
|
58
|
+
code: string | null;
|
|
59
|
+
kind: DiscountKind;
|
|
60
|
+
valuePct: number | null;
|
|
61
|
+
valueCents: number | null;
|
|
62
|
+
minSubtotalCents: number | null;
|
|
63
|
+
}
|
|
64
|
+
/** A stored discount as the discounts card writes one: an automatic discount's code is `null`. */
|
|
65
|
+
export type StoredDiscount = Omit<HostDiscount, 'code'> & {
|
|
66
|
+
code: string | null;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* The document a proposed discount is created as (AGL-2916): switched OFF,
|
|
70
|
+
* with no redemptions, its code in the shape the discounts card stores, and
|
|
71
|
+
* only the value its kind reads. A person switches it on from the discounts
|
|
72
|
+
* card. `null` for a proposal no discount can be made from: a percentage
|
|
73
|
+
* outside 1 to 100, or an amount off of nothing.
|
|
74
|
+
*/
|
|
75
|
+
export declare function switchedOffDiscount(proposal: ProposedDiscount): StoredDiscount | null;
|
|
76
|
+
export interface DiscountContext {
|
|
77
|
+
/** Entered code, if any (case-insensitive). */
|
|
78
|
+
code?: string;
|
|
79
|
+
subtotalCents: number;
|
|
80
|
+
/** Product ids present in the cart (scope checks). */
|
|
81
|
+
productIds: string[];
|
|
82
|
+
/**
|
|
83
|
+
* What each cart line is worth, for pricing a SCOPED discount.
|
|
84
|
+
*
|
|
85
|
+
* Required whenever a discount carries `productIds`, and the reason is that
|
|
86
|
+
* `subtotalCents` alone cannot price one: a scope names some of the cart, so
|
|
87
|
+
* the discount is worth some of the cart. A caller that omits these gets a
|
|
88
|
+
* refusal rather than a whole-cart discount — see `discountBenefit`.
|
|
89
|
+
*/
|
|
90
|
+
lines?: readonly {
|
|
91
|
+
productId: string;
|
|
92
|
+
amountCents: number;
|
|
93
|
+
}[];
|
|
94
|
+
nowMs?: number;
|
|
95
|
+
}
|
|
96
|
+
export interface ResolvedDiscount {
|
|
97
|
+
discount: HostDiscount;
|
|
98
|
+
discountId: string;
|
|
99
|
+
discountCents: number;
|
|
100
|
+
freeShipping: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* What this discount confers, as one value. `discountCents` and
|
|
103
|
+
* `freeShipping` are projections of it and are kept because callers read
|
|
104
|
+
* them; the benefit is what a caller should GATE on, because it is the only
|
|
105
|
+
* one of the three that can say "nothing, and here is why".
|
|
106
|
+
*/
|
|
107
|
+
benefit: DiscountBenefit;
|
|
108
|
+
/** Why a specifically-entered code failed; unset when one applied. */
|
|
109
|
+
codeProblem?: string;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* WHAT A DISCOUNT ACTUALLY CONFERS, named rather than implied.
|
|
113
|
+
*
|
|
114
|
+
* The whole point of this type is that "nothing" is a STATED outcome with a
|
|
115
|
+
* reason, not the number zero. `valueCents` used to answer a bare `number`,
|
|
116
|
+
* and every kind it did not understand — `free_shipping` included — answered
|
|
117
|
+
* `0`. The cart's apply-block gates on `discountCents > 0`, and the
|
|
118
|
+
* invalid-code 400 beside it only fires when NO discount resolved at all, so a
|
|
119
|
+
* free-shipping code took neither branch: it resolved successfully, conferred
|
|
120
|
+
* nothing, raised no error, and the shopper paid full shipping. A silent zero
|
|
121
|
+
* cannot be told from "this discount is worth nothing", which is exactly the
|
|
122
|
+
* distinction a money path has to make.
|
|
123
|
+
*
|
|
124
|
+
* So a caller cannot read a benefit without also seeing the `none` case, and a
|
|
125
|
+
* kind this build does not recognise reports itself instead of underpaying.
|
|
126
|
+
*/
|
|
127
|
+
export type DiscountBenefit =
|
|
128
|
+
/** Cents off the items subtotal. Always > 0 — a zero lands on `none`. */
|
|
129
|
+
{
|
|
130
|
+
kind: 'amount';
|
|
131
|
+
centsOff: number;
|
|
132
|
+
}
|
|
133
|
+
/** The shopper pays no shipping, whichever rate they pick. */
|
|
134
|
+
| {
|
|
135
|
+
kind: 'free-shipping';
|
|
136
|
+
}
|
|
137
|
+
/** Resolvable, but worth nothing. The caller must refuse, never proceed. */
|
|
138
|
+
| {
|
|
139
|
+
kind: 'none';
|
|
140
|
+
reason: string;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* The single derivation of what one discount is worth against one subtotal.
|
|
144
|
+
*
|
|
145
|
+
* Exhaustive over {@link DiscountKind} by construction: the `never` binding
|
|
146
|
+
* below fails the BUILD when a kind is added to the union and not handled
|
|
147
|
+
* here, so the next `free_shipping` cannot reach production as a silent zero.
|
|
148
|
+
* The runtime arm underneath it is not redundant — Firestore documents are not
|
|
149
|
+
* typechecked, and a `kind` written by a newer build than the one reading it
|
|
150
|
+
* arrives as an ordinary unrecognised string.
|
|
151
|
+
*/
|
|
152
|
+
export declare function discountBenefit(discount: HostDiscount, subtotalCents: number, lines?: readonly {
|
|
153
|
+
productId: string;
|
|
154
|
+
amountCents: number;
|
|
155
|
+
}[]): DiscountBenefit;
|
|
156
|
+
/**
|
|
157
|
+
* Best applicable discount: an entered code wins when valid (its
|
|
158
|
+
* failure reason is surfaced); otherwise the largest automatic
|
|
159
|
+
* promotion applies. Discounts never stack — Squarespace/Shopify
|
|
160
|
+
* baseline semantics.
|
|
161
|
+
*/
|
|
162
|
+
export declare function resolveDiscount(discounts: Array<HostDiscount & {
|
|
163
|
+
$id: string;
|
|
164
|
+
}>, context: DiscountContext): ResolvedDiscount | null;
|