@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,484 @@
|
|
|
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
|
+
* Shipping v1 (AGL-288): zones own countries; rates belong to a zone and
|
|
18
|
+
* price as flat, free-over-threshold, or subtotal/weight tiers. Settings
|
|
19
|
+
* live on `hosts/{hostId}/settings/store` under `shipping`. Pure.
|
|
20
|
+
*
|
|
21
|
+
* `resolveShippingRates` is the per-destination resolver;
|
|
22
|
+
* `resolveCheckoutShippingOptions` is the Stripe Checkout adapter,
|
|
23
|
+
* `planCheckoutShipping` decides which destinations one session may serve,
|
|
24
|
+
* `appendCheckoutShippingParams` emits it onto a session, and
|
|
25
|
+
* `summarizeShippingCoverage` answers the same question for the console, so a
|
|
26
|
+
* merchant can see which destinations their zones refuse. AGL-288 shipped this
|
|
27
|
+
* model with no production call site at all — the doc comment here claimed the
|
|
28
|
+
* cart estimator, checkout and POS pickup used it, and none of them did, so
|
|
29
|
+
* nothing ever read the settings a merchant saved and no shipping was ever
|
|
30
|
+
* charged. Cart checkout calls it (AGL-1707), buy-now calls it for physical
|
|
31
|
+
* one-time products (AGL-1720), and a draft order's payment link calls it for
|
|
32
|
+
* physical products (AGL-1792).
|
|
33
|
+
*
|
|
34
|
+
* POS DOES NOT, AND SHOULD NOT (AGL-1792). A register has no destination
|
|
35
|
+
* anywhere in it — no address field, no delivery choice — and all three
|
|
36
|
+
* tenders settle at the counter: cash, a card QR the customer scans while
|
|
37
|
+
* standing there, and a room folio collected at check-out. There is nothing to
|
|
38
|
+
* price a parcel against, so the only rate POS could resolve is the free
|
|
39
|
+
* `Local pickup` one this module appends, which is 0¢ and would add a step to
|
|
40
|
+
* a register flow in exchange for nothing. A POS sale that must be shipped is
|
|
41
|
+
* a draft order.
|
|
42
|
+
*/ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
43
|
+
/**
|
|
44
|
+
* The rate id appended for local pickup (AGL-2325).
|
|
45
|
+
*
|
|
46
|
+
* Exported because pickup is the one entry in a resolved list that is NOT a
|
|
47
|
+
* shipping promise: it is appended AFTER and INDEPENDENT of zone matching, so
|
|
48
|
+
* it resolves for every destination on earth. Anything asking "does this store
|
|
49
|
+
* ship there" — the checkout refusal, the console coverage card — has to be
|
|
50
|
+
* able to tell it apart from a rate, or it reads a merchant who offers
|
|
51
|
+
* collection as a merchant who delivers worldwide.
|
|
52
|
+
*/ export const LOCAL_PICKUP_RATE_ID = 'pickup';
|
|
53
|
+
/**
|
|
54
|
+
* One stored country code, normalised (AGL-2298).
|
|
55
|
+
*
|
|
56
|
+
* TRIMMED as well as upper-cased. The console trims on save, so this only
|
|
57
|
+
* matters for a document written any other way — an import, the REST API, a
|
|
58
|
+
* hand edit — but the failure it produces is silent and expensive: `' US'`
|
|
59
|
+
* upper-cases to `' US'`, matches nothing, and the store refuses every US
|
|
60
|
+
* shopper with "This store does not ship to the United States" while its
|
|
61
|
+
* settings card shows `US` right there.
|
|
62
|
+
*/ const zoneCode = (code)=>String(code != null ? code : '').trim().toUpperCase();
|
|
63
|
+
/** Whether a stored code is the rest-of-world wildcard. */ const isWildcard = (code)=>zoneCode(code) === '*';
|
|
64
|
+
function zoneMatches(zone, country) {
|
|
65
|
+
var _zone_countries;
|
|
66
|
+
return ((_zone_countries = zone.countries) != null ? _zone_countries : []).some((code)=>isWildcard(code) || zoneCode(code) === country);
|
|
67
|
+
}
|
|
68
|
+
function tierAmount(tiers, value) {
|
|
69
|
+
const sorted = [
|
|
70
|
+
...tiers != null ? tiers : []
|
|
71
|
+
].sort((a, b)=>a.upTo - b.upTo);
|
|
72
|
+
for (const tier of sorted){
|
|
73
|
+
if (value <= tier.upTo) return tier.amountCents;
|
|
74
|
+
}
|
|
75
|
+
// Beyond the last tier the rate does not apply (merchant should add a
|
|
76
|
+
// catch-all tier with a large upTo).
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Rates available for a destination + cart, cheapest first. Specific
|
|
81
|
+
* country zones beat '*' zones: when any specific zone matches, '*'
|
|
82
|
+
* zones are ignored (rest-of-world semantics).
|
|
83
|
+
*
|
|
84
|
+
* Local pickup is appended AFTER and INDEPENDENT of zone matching, so this
|
|
85
|
+
* list is never empty for a merchant who offers it, at any destination. That
|
|
86
|
+
* is correct for a resolver — a shopper anywhere may choose to come and
|
|
87
|
+
* collect — but it means A NON-EMPTY RESULT IS NOT A PROMISE TO SHIP THERE.
|
|
88
|
+
* Callers deciding whether a destination is served must filter pickup out
|
|
89
|
+
* first; `planCheckoutShipping` and `summarizeShippingCoverage` do (AGL-2325).
|
|
90
|
+
*/ export function resolveShippingRates(settings, destinationCountry, cart) {
|
|
91
|
+
var _settings_zones, _settings_rates;
|
|
92
|
+
if (!settings || !destinationCountry) return [];
|
|
93
|
+
const country = destinationCountry.toUpperCase();
|
|
94
|
+
const zones = (_settings_zones = settings.zones) != null ? _settings_zones : [];
|
|
95
|
+
// A zone is SPECIFIC when it names this country outright — not merely when
|
|
96
|
+
// it is "not wildcard-only" (AGL-2298). The old test was `!every(code ===
|
|
97
|
+
// '*')`, so a zone spelled `['*','US']` counted as specific for all six
|
|
98
|
+
// destinations (it matches every country through the `*`) and suppressed
|
|
99
|
+
// every genuine rest-of-world zone globally. Asking the narrower question
|
|
100
|
+
// makes such a zone specific for `US` and wildcard for the rest, which is
|
|
101
|
+
// what its two entries actually say.
|
|
102
|
+
const specific = zones.filter((zone)=>{
|
|
103
|
+
var _zone_countries;
|
|
104
|
+
return ((_zone_countries = zone.countries) != null ? _zone_countries : []).some((code)=>zoneCode(code) === country);
|
|
105
|
+
});
|
|
106
|
+
const matched = specific.length ? specific : zones.filter((zone)=>zoneMatches(zone, country));
|
|
107
|
+
const zoneIds = new Set(matched.map((zone)=>zone.id));
|
|
108
|
+
const resolved = [];
|
|
109
|
+
for (const rate of (_settings_rates = settings.rates) != null ? _settings_rates : []){
|
|
110
|
+
if (!zoneIds.has(rate.zoneId)) continue;
|
|
111
|
+
let amountCents = null;
|
|
112
|
+
switch(rate.kind){
|
|
113
|
+
case 'flat':
|
|
114
|
+
var _rate_amountCents;
|
|
115
|
+
amountCents = Math.max(0, Math.round((_rate_amountCents = rate.amountCents) != null ? _rate_amountCents : 0));
|
|
116
|
+
break;
|
|
117
|
+
case 'free_over':
|
|
118
|
+
var _rate_amountCents1;
|
|
119
|
+
amountCents = rate.freeOverCents != null && cart.subtotalCents >= rate.freeOverCents ? 0 : Math.max(0, Math.round((_rate_amountCents1 = rate.amountCents) != null ? _rate_amountCents1 : 0));
|
|
120
|
+
break;
|
|
121
|
+
case 'price_tiers':
|
|
122
|
+
amountCents = tierAmount(rate.tiers, cart.subtotalCents);
|
|
123
|
+
break;
|
|
124
|
+
case 'weight_tiers':
|
|
125
|
+
var _cart_totalGrams;
|
|
126
|
+
amountCents = tierAmount(rate.tiers, (_cart_totalGrams = cart.totalGrams) != null ? _cart_totalGrams : 0);
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
if (amountCents == null) continue;
|
|
130
|
+
resolved.push({
|
|
131
|
+
rateId: rate.id,
|
|
132
|
+
name: rate.name,
|
|
133
|
+
amountCents
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
if (settings.localPickup) {
|
|
137
|
+
resolved.push({
|
|
138
|
+
rateId: LOCAL_PICKUP_RATE_ID,
|
|
139
|
+
name: 'Local pickup',
|
|
140
|
+
amountCents: 0
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return resolved.sort((a, b)=>a.amountCents - b.amountCents);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The resolved options that actually carry a parcel (AGL-2325).
|
|
147
|
+
*
|
|
148
|
+
* Safe to apply AFTER `MAX_CHECKOUT_SHIPPING_OPTIONS` truncation: pickup is
|
|
149
|
+
* 0¢ and sorts first, so it occupies at most one of the five slots and a
|
|
150
|
+
* merchant with any shippable rate at all keeps at least one of them.
|
|
151
|
+
*/ function shippableOnly(options) {
|
|
152
|
+
return options.filter((option)=>option.rateId !== LOCAL_PICKUP_RATE_ID);
|
|
153
|
+
}
|
|
154
|
+
/** Stripe Checkout accepts at most 5 `shipping_options` on one session. */ export const MAX_CHECKOUT_SHIPPING_OPTIONS = 5;
|
|
155
|
+
/**
|
|
156
|
+
* Destinations a storefront Checkout Session collects an address for, and
|
|
157
|
+
* therefore the destinations shipping rates are resolved against (AGL-1707).
|
|
158
|
+
*
|
|
159
|
+
* NOT narrowed to the zones the merchant configured: narrowing would block
|
|
160
|
+
* checkouts that complete today, turning a money fix into lost sales. The
|
|
161
|
+
* wider list only means a shopper outside the merchant's zones is offered some
|
|
162
|
+
* rate rather than none. Shared by cart checkout and buy-now (AGL-1720) so the
|
|
163
|
+
* two paths cannot drift into offering different destinations.
|
|
164
|
+
*/ export const CHECKOUT_SHIPPING_COUNTRIES = [
|
|
165
|
+
'US',
|
|
166
|
+
'CA',
|
|
167
|
+
'GB',
|
|
168
|
+
'AU',
|
|
169
|
+
'DE',
|
|
170
|
+
'FR'
|
|
171
|
+
];
|
|
172
|
+
/**
|
|
173
|
+
* The rates to declare as `shipping_options` on a Stripe Checkout Session
|
|
174
|
+
* (AGL-1707), unioned over `destinationCountries`. Stripe charges shipping
|
|
175
|
+
* ONLY when the session declares them.
|
|
176
|
+
*
|
|
177
|
+
* A UNION IS ONLY HONEST OVER DESTINATIONS THE SESSION IS ALSO RESTRICTED TO.
|
|
178
|
+
* Called with every collectable country while the session accepted an address
|
|
179
|
+
* in any of them — which is what AGL-1707 shipped — it offers a shopper in one
|
|
180
|
+
* zone a rate belonging to another, and Stripe applies whichever the shopper
|
|
181
|
+
* picks (a `shipping_rate_data` carries no country of its own, so nothing
|
|
182
|
+
* downstream re-checks it against the address). That is AGL-1721. Callers now
|
|
183
|
+
* reach this through `planCheckoutShipping`, which pairs the country list it
|
|
184
|
+
* unions over with the country list the session allows, so the two cannot
|
|
185
|
+
* disagree. Do not call it directly from a handler.
|
|
186
|
+
*
|
|
187
|
+
* Returns `[]` for a merchant who has configured nothing, and the caller must
|
|
188
|
+
* then declare no `shipping_options` at all rather than an empty array — a
|
|
189
|
+
* merchant who never set shipping up keeps a session identical to today's.
|
|
190
|
+
*/ export function resolveCheckoutShippingOptions(settings, destinationCountries, cart) {
|
|
191
|
+
if (!settings) return [];
|
|
192
|
+
const byRateId = new Map();
|
|
193
|
+
for (const country of destinationCountries){
|
|
194
|
+
for (const rate of resolveShippingRates(settings, country, cart)){
|
|
195
|
+
// Stripe requires a display name, and a rate id is the dedupe key —
|
|
196
|
+
// the console lets a merchant add a blank row, so neither is assured.
|
|
197
|
+
if (!rate.rateId || !rate.name) continue;
|
|
198
|
+
const amountCents = Math.max(0, Math.round(Number(rate.amountCents) || 0));
|
|
199
|
+
const existing = byRateId.get(rate.rateId);
|
|
200
|
+
// One rate resolving differently for two countries should not be
|
|
201
|
+
// possible (a zone selects a rate, it does not reprice one), but if it
|
|
202
|
+
// ever is, keep the dearer. Under-charging is the defect being fixed.
|
|
203
|
+
if (!existing || amountCents > existing.amountCents) {
|
|
204
|
+
byRateId.set(rate.rateId, _extends({}, rate, {
|
|
205
|
+
amountCents
|
|
206
|
+
}));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return [
|
|
211
|
+
...byRateId.values()
|
|
212
|
+
]// Cheapest first, id as a tie-break so the emitted params are stable.
|
|
213
|
+
.sort((a, b)=>a.amountCents - b.amountCents || a.rateId.localeCompare(b.rateId))// Past Stripe's cap the dearest are dropped, which is the harmless end
|
|
214
|
+
// to lose: a shopper offered the cheap options would have taken one.
|
|
215
|
+
.slice(0, MAX_CHECKOUT_SHIPPING_OPTIONS);
|
|
216
|
+
}
|
|
217
|
+
/** Shopper-facing names for the collectable destinations (AGL-1721). */ export const CHECKOUT_SHIPPING_COUNTRY_NAMES = {
|
|
218
|
+
US: 'United States',
|
|
219
|
+
CA: 'Canada',
|
|
220
|
+
GB: 'United Kingdom',
|
|
221
|
+
AU: 'Australia',
|
|
222
|
+
DE: 'Germany',
|
|
223
|
+
FR: 'France'
|
|
224
|
+
};
|
|
225
|
+
/**
|
|
226
|
+
* A destination a shopper declared, or `undefined` for anything this session
|
|
227
|
+
* could not collect an address for anyway. Never throws: an unknown code is
|
|
228
|
+
* an undeclared destination, not an error, so a stale storefront that posts
|
|
229
|
+
* one is answered by the plan below rather than by a 400 nobody can act on.
|
|
230
|
+
*/ export function normalizeCheckoutShippingCountry(value) {
|
|
231
|
+
// `typeof` rather than `String(value)`: a JSON body is caller-shaped, and
|
|
232
|
+
// `String(['US'])` is 'US'. Coercing would let an array declare a
|
|
233
|
+
// destination, which is not a spelling any storefront sends.
|
|
234
|
+
if (typeof value !== 'string') return undefined;
|
|
235
|
+
const code = value.trim().toUpperCase();
|
|
236
|
+
return CHECKOUT_SHIPPING_COUNTRIES.includes(code) ? code : undefined;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Whether this merchant prices shipping AT ALL (AGL-2232).
|
|
240
|
+
*
|
|
241
|
+
* A pure question about the SETTINGS, deliberately taking no cart, and that is
|
|
242
|
+
* the whole point of it existing. `planCheckoutShipping` used to ask "does any
|
|
243
|
+
* rate resolve for any destination?" and pass the live cart into the probe, so
|
|
244
|
+
* a cart that exhausted every tier made the probe empty too — and an empty
|
|
245
|
+
* probe reads as "this merchant never set shipping up", the one case that must
|
|
246
|
+
* complete with no `shipping_options` and nothing charged. A 3 kg order at a
|
|
247
|
+
* store whose weight tiers stop at 2 kg therefore shipped free, silently, on
|
|
248
|
+
* every one of the three doors.
|
|
249
|
+
*
|
|
250
|
+
* Answered from the stored zones and rates instead: a rate bound to a zone
|
|
251
|
+
* that exists, or local pickup, means the merchant made a shipping decision
|
|
252
|
+
* and a cart their table cannot price is a REFUSAL. A merchant with no zones,
|
|
253
|
+
* no rates and no pickup has made no such decision, and their session stays
|
|
254
|
+
* byte-identical to the one AGL-1707 shipped.
|
|
255
|
+
*/ export function merchantPricesShipping(settings) {
|
|
256
|
+
var _settings_zones, _settings_rates;
|
|
257
|
+
if (!settings) return false;
|
|
258
|
+
if (settings.localPickup) return true;
|
|
259
|
+
const zoneIds = new Set(((_settings_zones = settings.zones) != null ? _settings_zones : []).map((zone)=>zone.id));
|
|
260
|
+
// A rate whose `zoneId` names no zone is unreachable by every resolver here,
|
|
261
|
+
// so it is not evidence of a decision — counting it would refuse carts at a
|
|
262
|
+
// store with nothing but orphaned rows.
|
|
263
|
+
return ((_settings_rates = settings.rates) != null ? _settings_rates : []).some((rate)=>zoneIds.has(rate.zoneId));
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* What a shopper is told when `cart-unpriceable` refuses (AGL-2232).
|
|
267
|
+
*
|
|
268
|
+
* One string, shared by all three doors, because the three used to phrase the
|
|
269
|
+
* two existing refusals identically and drifting here would make the same
|
|
270
|
+
* store say different things depending on which button was pressed. It names
|
|
271
|
+
* the cart rather than the destination on purpose — a `Ship to` select cannot
|
|
272
|
+
* fix a parcel no tier covers, so the refusal deliberately does NOT set
|
|
273
|
+
* `needsShippingCountry`.
|
|
274
|
+
*/ export const CART_UNPRICEABLE_SHIPPING_MESSAGE = 'This store cannot price shipping for this order — it falls outside every ' + 'shipping rate the store has set up. Try removing an item, or contact the ' + 'store.';
|
|
275
|
+
/** Identity of a resolved list, for comparing two destinations' offers. */ function optionsKey(options) {
|
|
276
|
+
return options.map((option)=>`${option.rateId}:${option.amountCents}`).join('|');
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* The whole shipping half of a Checkout Session: which destinations it may
|
|
280
|
+
* accept an address for, and which rates it may charge (AGL-1721).
|
|
281
|
+
*
|
|
282
|
+
* THE INVARIANT IS THAT EVERY RETURNED OPTION IS VALID FOR EVERY RETURNED
|
|
283
|
+
* COUNTRY. Stripe offers a session's `shipping_options` to whoever reaches the
|
|
284
|
+
* page and charges whichever the shopper picks — it does not filter them by
|
|
285
|
+
* the address entered, and there is no field on a `shipping_rate_data` that
|
|
286
|
+
* would let it. So the ONLY place a zone can be enforced is here, by choosing
|
|
287
|
+
* the two lists together: narrowing the allowed countries to the declared
|
|
288
|
+
* destination is what makes the rates offered for it unpickable by anyone
|
|
289
|
+
* else. Filtering the rate list alone would leave a session that still accepts
|
|
290
|
+
* a French address against a US rate.
|
|
291
|
+
*
|
|
292
|
+
* Three shapes come out of it:
|
|
293
|
+
*
|
|
294
|
+
* 1. A merchant whose rates resolve the SAME for every collectable country —
|
|
295
|
+
* one zone, a single '*' zone, or none at all — needs no destination and
|
|
296
|
+
* keeps the session AGL-1707 shipped, byte for byte. The issue notes this
|
|
297
|
+
* is the common configuration, and it is the one that must not regress.
|
|
298
|
+
* 2. A declared destination resolves exactly, and the session is restricted
|
|
299
|
+
* to it. A caller may not skip the restriction: the country arrives in a
|
|
300
|
+
* request body a shopper can craft, so a session that took the country's
|
|
301
|
+
* cheap rate while still accepting any address would hand that shopper
|
|
302
|
+
* the defect on purpose.
|
|
303
|
+
* 3. Otherwise the caller must refuse — see `refusal`. Refusing is not lost
|
|
304
|
+
* revenue in either case: with rates that differ by zone there is no
|
|
305
|
+
* correct amount to charge without knowing where the parcel is going, and
|
|
306
|
+
* the union AGL-1707 shipped chose the wrong one silently.
|
|
307
|
+
*
|
|
308
|
+
* `cart.subtotalCents` is the PRE-discount items total, matching what the cart
|
|
309
|
+
* displays, so a free-over threshold means what the shopper saw it mean.
|
|
310
|
+
*/ export function planCheckoutShipping(settings, cart, destinationCountry) {
|
|
311
|
+
const countries = CHECKOUT_SHIPPING_COUNTRIES;
|
|
312
|
+
const destination = normalizeCheckoutShippingCountry(destinationCountry);
|
|
313
|
+
if (destination) {
|
|
314
|
+
const options = resolveCheckoutShippingOptions(settings, [
|
|
315
|
+
destination
|
|
316
|
+
], cart);
|
|
317
|
+
// REFUSAL IS DECIDED ON SHIPPABLE RATES, PICKUP IS OFFERED AFTERWARDS
|
|
318
|
+
// (AGL-2325). `resolveShippingRates` appends pickup independent of zone
|
|
319
|
+
// matching, so a merchant who turned it on had a non-empty list for every
|
|
320
|
+
// destination on earth and this branch returned before it could refuse
|
|
321
|
+
// anyone: a shopper in France picked `Local pickup — Free` on a physical
|
|
322
|
+
// order from a US-only store, Stripe collected their French address
|
|
323
|
+
// because the session still allowed it, and the merchant was paid nothing
|
|
324
|
+
// to carry the parcel there. Pickup is collection, not delivery, so it
|
|
325
|
+
// cannot answer "do you ship to France".
|
|
326
|
+
//
|
|
327
|
+
// `shipsElsewhere` is the same question the old probe asked, narrowed to
|
|
328
|
+
// shippable rates, and it keeps the same two-way fork: a merchant who
|
|
329
|
+
// configured NO shipping is not refusing anyone, so that store keeps
|
|
330
|
+
// completing exactly as it does today, while a merchant who ships
|
|
331
|
+
// elsewhere but not here is refusing and saying so is the honest answer.
|
|
332
|
+
// A merchant who ships NOWHERE is untouched by this: pickup-only is a
|
|
333
|
+
// real configuration — they deliver to no one and refuse no one — and it
|
|
334
|
+
// falls through to the offer below exactly as it did.
|
|
335
|
+
const shipsElsewhere = countries.some((country)=>shippableOnly(resolveCheckoutShippingOptions(settings, [
|
|
336
|
+
country
|
|
337
|
+
], cart)).length > 0);
|
|
338
|
+
if (shippableOnly(options).length === 0 && shipsElsewhere) {
|
|
339
|
+
return {
|
|
340
|
+
countries,
|
|
341
|
+
options: [],
|
|
342
|
+
refusal: 'destination-unserved'
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
if (options.length > 0) return {
|
|
346
|
+
countries: [
|
|
347
|
+
destination
|
|
348
|
+
],
|
|
349
|
+
options
|
|
350
|
+
};
|
|
351
|
+
// NOTHING resolves anywhere for this cart, and the two reasons that can be
|
|
352
|
+
// true of are opposite (AGL-2232). Asked of the SETTINGS rather than of
|
|
353
|
+
// this cart, because the probe above cannot tell them apart: a merchant
|
|
354
|
+
// who priced shipping and whose table simply does not reach this order is
|
|
355
|
+
// refusing, and used to be handed the "never set shipping up" branch.
|
|
356
|
+
return merchantPricesShipping(settings) ? {
|
|
357
|
+
countries,
|
|
358
|
+
options: [],
|
|
359
|
+
refusal: 'cart-unpriceable'
|
|
360
|
+
} : {
|
|
361
|
+
countries,
|
|
362
|
+
options: []
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
const offers = new Set(countries.map((country)=>optionsKey(resolveCheckoutShippingOptions(settings, [
|
|
366
|
+
country
|
|
367
|
+
], cart))));
|
|
368
|
+
// Compared as EMITTED — capped and sanitized — because that is the list a
|
|
369
|
+
// shopper can pick from. Two destinations whose rates differ only past
|
|
370
|
+
// Stripe's cap still offer the same five, and offering them is honest.
|
|
371
|
+
if (offers.size > 1) {
|
|
372
|
+
return {
|
|
373
|
+
countries,
|
|
374
|
+
options: [],
|
|
375
|
+
refusal: 'destination-required'
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
const union = resolveCheckoutShippingOptions(settings, countries, cart);
|
|
379
|
+
// Every destination agrees, and what they agree on is NOTHING. The same
|
|
380
|
+
// fork as the declared-destination branch above (AGL-2232): a store with no
|
|
381
|
+
// shipping settings completes untouched, a store whose rates cannot reach
|
|
382
|
+
// this cart refuses instead of carrying the parcel for free.
|
|
383
|
+
if (union.length === 0 && merchantPricesShipping(settings)) {
|
|
384
|
+
return {
|
|
385
|
+
countries,
|
|
386
|
+
options: [],
|
|
387
|
+
refusal: 'cart-unpriceable'
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
return {
|
|
391
|
+
countries,
|
|
392
|
+
options: union
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* A cart chosen so that every rate a merchant could have written resolves if
|
|
397
|
+
* it can resolve at all (AGL-1791). The settings page has no cart, and two of
|
|
398
|
+
* the four rate kinds price against one: `tierAmount` takes the first tier
|
|
399
|
+
* whose `upTo` is at least the value, so a zero subtotal and zero weight clear
|
|
400
|
+
* every tier a merchant would write, and a `free_over` rate resolves at any
|
|
401
|
+
* subtotal.
|
|
402
|
+
*
|
|
403
|
+
* That makes a coverage answer a LOWER BOUND on the gaps. A destination
|
|
404
|
+
* reported unserved is unserved for every cart; a destination reported served
|
|
405
|
+
* may still be refused for a cart dearer or heavier than the merchant's last
|
|
406
|
+
* tier. Erring in this direction is the deliberate half: the console must not
|
|
407
|
+
* warn a merchant whose settings are fine.
|
|
408
|
+
*/ const COVERAGE_PROBE_CART = {
|
|
409
|
+
subtotalCents: 0,
|
|
410
|
+
totalGrams: 0
|
|
411
|
+
};
|
|
412
|
+
/**
|
|
413
|
+
* Which of the collectable destinations a merchant's settings actually cover
|
|
414
|
+
* (AGL-1791), for a console surface to show them.
|
|
415
|
+
*
|
|
416
|
+
* Measured against `CHECKOUT_SHIPPING_COUNTRIES` and nothing wider: those six
|
|
417
|
+
* are the only destinations a storefront session collects an address for, so
|
|
418
|
+
* they are the only ones a merchant can lose an order to. Counting coverage
|
|
419
|
+
* against every country on earth would report a gap for destinations no
|
|
420
|
+
* shopper can reach checkout from.
|
|
421
|
+
*
|
|
422
|
+
* Answered through `resolveCheckoutShippingOptions` — the same function the
|
|
423
|
+
* session is built from — so a row the console allows but Stripe would reject
|
|
424
|
+
* (blank id, blank name) counts as the nothing it resolves to, and a specific
|
|
425
|
+
* zone with no rates still hides a `*` zone here exactly as it does at
|
|
426
|
+
* checkout.
|
|
427
|
+
*/ export function summarizeShippingCoverage(settings) {
|
|
428
|
+
var _ref;
|
|
429
|
+
const served = [];
|
|
430
|
+
const unserved = [];
|
|
431
|
+
const offers = new Set();
|
|
432
|
+
for (const country of CHECKOUT_SHIPPING_COUNTRIES){
|
|
433
|
+
const options = resolveCheckoutShippingOptions(settings, [
|
|
434
|
+
country
|
|
435
|
+
], COVERAGE_PROBE_CART);
|
|
436
|
+
// `asksDestination` is asked of the FULL list — pickup is a real option a
|
|
437
|
+
// shopper picks, so a merchant whose US destination offers a rate plus
|
|
438
|
+
// pickup while France offers only pickup genuinely does make checkout ask.
|
|
439
|
+
offers.add(optionsKey(options));
|
|
440
|
+
(shippableOnly(options).length > 0 ? served : unserved).push(country);
|
|
441
|
+
}
|
|
442
|
+
return {
|
|
443
|
+
served,
|
|
444
|
+
unserved: served.length > 0 ? unserved : [],
|
|
445
|
+
shipsNowhere: served.length === 0,
|
|
446
|
+
asksDestination: offers.size > 1,
|
|
447
|
+
offersLocalPickup: Boolean(settings == null ? void 0 : settings.localPickup),
|
|
448
|
+
hasRestOfWorldZone: ((_ref = settings == null ? void 0 : settings.zones) != null ? _ref : []).some((zone)=>zone.countries.some((code)=>code === '*'))
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Emit `shipping_address_collection[allowed_countries][n]` onto a session's
|
|
453
|
+
* form body. Stripe will not apply a `shipping_options` rate without an
|
|
454
|
+
* address to ship to, so the two always travel together — and the countries
|
|
455
|
+
* are the OTHER half of what makes a rate honest (AGL-1721), so pass the list
|
|
456
|
+
* `planCheckoutShipping` returned rather than defaulting it beside a rate list
|
|
457
|
+
* resolved for something narrower.
|
|
458
|
+
*/ export function appendShippingAddressCollectionParams(params, countries = CHECKOUT_SHIPPING_COUNTRIES) {
|
|
459
|
+
countries.forEach((code, index)=>{
|
|
460
|
+
params.set(`shipping_address_collection[allowed_countries][${index}]`, code);
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Emit resolved rates as `shipping_options` on a Checkout Session's form body.
|
|
465
|
+
*
|
|
466
|
+
* THIS IS THE ONLY THING THAT MAKES STRIPE CHARGE SHIPPING. Without these keys
|
|
467
|
+
* Stripe presents no shipping choice and `total_details.amount_shipping` is 0
|
|
468
|
+
* however many zones and rates the merchant saved (AGL-1707).
|
|
469
|
+
*
|
|
470
|
+
* An empty list emits NOTHING — not an empty array — so a merchant who
|
|
471
|
+
* configured no shipping keeps a session byte-identical to the one built
|
|
472
|
+
* before shipping was wired at all. That guarantee lives here rather than in
|
|
473
|
+
* each caller, so neither checkout path can lose it independently (AGL-1720).
|
|
474
|
+
*/ export function appendCheckoutShippingParams(params, options) {
|
|
475
|
+
options.forEach((option, index)=>{
|
|
476
|
+
const field = `shipping_options[${index}][shipping_rate_data]`;
|
|
477
|
+
params.set(`${field}[type]`, 'fixed_amount');
|
|
478
|
+
params.set(`${field}[display_name]`, option.name.slice(0, 100));
|
|
479
|
+
params.set(`${field}[fixed_amount][amount]`, String(option.amountCents));
|
|
480
|
+
params.set(`${field}[fixed_amount][currency]`, 'usd');
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
//# sourceMappingURL=commerce-shipping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/model/commerce-shipping.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 * Shipping v1 (AGL-288): zones own countries; rates belong to a zone and\n * price as flat, free-over-threshold, or subtotal/weight tiers. Settings\n * live on `hosts/{hostId}/settings/store` under `shipping`. Pure.\n *\n * `resolveShippingRates` is the per-destination resolver;\n * `resolveCheckoutShippingOptions` is the Stripe Checkout adapter,\n * `planCheckoutShipping` decides which destinations one session may serve,\n * `appendCheckoutShippingParams` emits it onto a session, and\n * `summarizeShippingCoverage` answers the same question for the console, so a\n * merchant can see which destinations their zones refuse. AGL-288 shipped this\n * model with no production call site at all — the doc comment here claimed the\n * cart estimator, checkout and POS pickup used it, and none of them did, so\n * nothing ever read the settings a merchant saved and no shipping was ever\n * charged. Cart checkout calls it (AGL-1707), buy-now calls it for physical\n * one-time products (AGL-1720), and a draft order's payment link calls it for\n * physical products (AGL-1792).\n *\n * POS DOES NOT, AND SHOULD NOT (AGL-1792). A register has no destination\n * anywhere in it — no address field, no delivery choice — and all three\n * tenders settle at the counter: cash, a card QR the customer scans while\n * standing there, and a room folio collected at check-out. There is nothing to\n * price a parcel against, so the only rate POS could resolve is the free\n * `Local pickup` one this module appends, which is 0¢ and would add a step to\n * a register flow in exchange for nothing. A POS sale that must be shipped is\n * a draft order.\n */\n\nexport interface ShippingZone {\n id: string\n name: string\n /** ISO-3166 alpha-2 codes; '*' = rest of world. */\n countries: string[]\n}\n\nexport interface ShippingTier {\n /** Tier applies while subtotal (cents) or weight (grams) ≤ this. */\n upTo: number\n amountCents: number\n}\n\nexport interface ShippingRate {\n id: string\n zoneId: string\n name: string\n kind: 'flat' | 'free_over' | 'price_tiers' | 'weight_tiers'\n /** flat + free_over base amount. */\n amountCents?: number\n /** free_over: order subtotal (cents) at/above which shipping is free. */\n freeOverCents?: number\n /** price_tiers (upTo = subtotal cents) / weight_tiers (upTo = grams). */\n tiers?: ShippingTier[]\n}\n\nexport interface ShippingSettings {\n zones?: ShippingZone[]\n rates?: ShippingRate[]\n /**\n * Offer free local pickup as a delivery choice. Does NOT widen where the\n * store ships: a destination no rate reaches is still refused (AGL-2325).\n */\n localPickup?: boolean\n}\n\nexport interface ResolvedShippingRate {\n rateId: string\n name: string\n amountCents: number\n}\n\n/**\n * The rate id appended for local pickup (AGL-2325).\n *\n * Exported because pickup is the one entry in a resolved list that is NOT a\n * shipping promise: it is appended AFTER and INDEPENDENT of zone matching, so\n * it resolves for every destination on earth. Anything asking \"does this store\n * ship there\" — the checkout refusal, the console coverage card — has to be\n * able to tell it apart from a rate, or it reads a merchant who offers\n * collection as a merchant who delivers worldwide.\n */\nexport const LOCAL_PICKUP_RATE_ID = 'pickup'\n\n/**\n * One stored country code, normalised (AGL-2298).\n *\n * TRIMMED as well as upper-cased. The console trims on save, so this only\n * matters for a document written any other way — an import, the REST API, a\n * hand edit — but the failure it produces is silent and expensive: `' US'`\n * upper-cases to `' US'`, matches nothing, and the store refuses every US\n * shopper with \"This store does not ship to the United States\" while its\n * settings card shows `US` right there.\n */\nconst zoneCode = (code: unknown): string => String(code ?? '').trim().toUpperCase()\n\n/** Whether a stored code is the rest-of-world wildcard. */\nconst isWildcard = (code: unknown): boolean => zoneCode(code) === '*'\n\nfunction zoneMatches(zone: ShippingZone, country: string): boolean {\n return (zone.countries ?? []).some(\n (code) => isWildcard(code) || zoneCode(code) === country,\n )\n}\n\nfunction tierAmount(\n tiers: ShippingTier[] | undefined,\n value: number,\n): number | null {\n const sorted = [...(tiers ?? [])].sort((a, b) => a.upTo - b.upTo)\n for (const tier of sorted) {\n if (value <= tier.upTo) return tier.amountCents\n }\n // Beyond the last tier the rate does not apply (merchant should add a\n // catch-all tier with a large upTo).\n return null\n}\n\n/**\n * Rates available for a destination + cart, cheapest first. Specific\n * country zones beat '*' zones: when any specific zone matches, '*'\n * zones are ignored (rest-of-world semantics).\n *\n * Local pickup is appended AFTER and INDEPENDENT of zone matching, so this\n * list is never empty for a merchant who offers it, at any destination. That\n * is correct for a resolver — a shopper anywhere may choose to come and\n * collect — but it means A NON-EMPTY RESULT IS NOT A PROMISE TO SHIP THERE.\n * Callers deciding whether a destination is served must filter pickup out\n * first; `planCheckoutShipping` and `summarizeShippingCoverage` do (AGL-2325).\n */\nexport function resolveShippingRates(\n settings: ShippingSettings | undefined,\n destinationCountry: string | undefined,\n cart: { subtotalCents: number; totalGrams?: number },\n): ResolvedShippingRate[] {\n if (!settings || !destinationCountry) return []\n const country = destinationCountry.toUpperCase()\n const zones = settings.zones ?? []\n // A zone is SPECIFIC when it names this country outright — not merely when\n // it is \"not wildcard-only\" (AGL-2298). The old test was `!every(code ===\n // '*')`, so a zone spelled `['*','US']` counted as specific for all six\n // destinations (it matches every country through the `*`) and suppressed\n // every genuine rest-of-world zone globally. Asking the narrower question\n // makes such a zone specific for `US` and wildcard for the rest, which is\n // what its two entries actually say.\n const specific = zones.filter((zone) =>\n (zone.countries ?? []).some((code) => zoneCode(code) === country),\n )\n const matched = specific.length\n ? specific\n : zones.filter((zone) => zoneMatches(zone, country))\n const zoneIds = new Set(matched.map((zone) => zone.id))\n const resolved: ResolvedShippingRate[] = []\n for (const rate of settings.rates ?? []) {\n if (!zoneIds.has(rate.zoneId)) continue\n let amountCents: number | null = null\n switch (rate.kind) {\n case 'flat':\n amountCents = Math.max(0, Math.round(rate.amountCents ?? 0))\n break\n case 'free_over':\n amountCents =\n rate.freeOverCents != null &&\n cart.subtotalCents >= rate.freeOverCents\n ? 0\n : Math.max(0, Math.round(rate.amountCents ?? 0))\n break\n case 'price_tiers':\n amountCents = tierAmount(rate.tiers, cart.subtotalCents)\n break\n case 'weight_tiers':\n amountCents = tierAmount(rate.tiers, cart.totalGrams ?? 0)\n break\n }\n if (amountCents == null) continue\n resolved.push({ rateId: rate.id, name: rate.name, amountCents })\n }\n if (settings.localPickup) {\n resolved.push({\n rateId: LOCAL_PICKUP_RATE_ID,\n name: 'Local pickup',\n amountCents: 0,\n })\n }\n return resolved.sort((a, b) => a.amountCents - b.amountCents)\n}\n\n/**\n * The resolved options that actually carry a parcel (AGL-2325).\n *\n * Safe to apply AFTER `MAX_CHECKOUT_SHIPPING_OPTIONS` truncation: pickup is\n * 0¢ and sorts first, so it occupies at most one of the five slots and a\n * merchant with any shippable rate at all keeps at least one of them.\n */\nfunction shippableOnly(\n options: readonly ResolvedShippingRate[],\n): ResolvedShippingRate[] {\n return options.filter((option) => option.rateId !== LOCAL_PICKUP_RATE_ID)\n}\n\n/** Stripe Checkout accepts at most 5 `shipping_options` on one session. */\nexport const MAX_CHECKOUT_SHIPPING_OPTIONS = 5\n\n/**\n * Destinations a storefront Checkout Session collects an address for, and\n * therefore the destinations shipping rates are resolved against (AGL-1707).\n *\n * NOT narrowed to the zones the merchant configured: narrowing would block\n * checkouts that complete today, turning a money fix into lost sales. The\n * wider list only means a shopper outside the merchant's zones is offered some\n * rate rather than none. Shared by cart checkout and buy-now (AGL-1720) so the\n * two paths cannot drift into offering different destinations.\n */\nexport const CHECKOUT_SHIPPING_COUNTRIES = [\n 'US',\n 'CA',\n 'GB',\n 'AU',\n 'DE',\n 'FR',\n] as const\n\n/**\n * The rates to declare as `shipping_options` on a Stripe Checkout Session\n * (AGL-1707), unioned over `destinationCountries`. Stripe charges shipping\n * ONLY when the session declares them.\n *\n * A UNION IS ONLY HONEST OVER DESTINATIONS THE SESSION IS ALSO RESTRICTED TO.\n * Called with every collectable country while the session accepted an address\n * in any of them — which is what AGL-1707 shipped — it offers a shopper in one\n * zone a rate belonging to another, and Stripe applies whichever the shopper\n * picks (a `shipping_rate_data` carries no country of its own, so nothing\n * downstream re-checks it against the address). That is AGL-1721. Callers now\n * reach this through `planCheckoutShipping`, which pairs the country list it\n * unions over with the country list the session allows, so the two cannot\n * disagree. Do not call it directly from a handler.\n *\n * Returns `[]` for a merchant who has configured nothing, and the caller must\n * then declare no `shipping_options` at all rather than an empty array — a\n * merchant who never set shipping up keeps a session identical to today's.\n */\nexport function resolveCheckoutShippingOptions(\n settings: ShippingSettings | undefined,\n destinationCountries: readonly string[],\n cart: { subtotalCents: number; totalGrams?: number },\n): ResolvedShippingRate[] {\n if (!settings) return []\n const byRateId = new Map<string, ResolvedShippingRate>()\n for (const country of destinationCountries) {\n for (const rate of resolveShippingRates(settings, country, cart)) {\n // Stripe requires a display name, and a rate id is the dedupe key —\n // the console lets a merchant add a blank row, so neither is assured.\n if (!rate.rateId || !rate.name) continue\n const amountCents = Math.max(0, Math.round(Number(rate.amountCents) || 0))\n const existing = byRateId.get(rate.rateId)\n // One rate resolving differently for two countries should not be\n // possible (a zone selects a rate, it does not reprice one), but if it\n // ever is, keep the dearer. Under-charging is the defect being fixed.\n if (!existing || amountCents > existing.amountCents) {\n byRateId.set(rate.rateId, { ...rate, amountCents })\n }\n }\n }\n return (\n [...byRateId.values()]\n // Cheapest first, id as a tie-break so the emitted params are stable.\n .sort(\n (a, b) =>\n a.amountCents - b.amountCents || a.rateId.localeCompare(b.rateId),\n )\n // Past Stripe's cap the dearest are dropped, which is the harmless end\n // to lose: a shopper offered the cheap options would have taken one.\n .slice(0, MAX_CHECKOUT_SHIPPING_OPTIONS)\n )\n}\n\n/** Shopper-facing names for the collectable destinations (AGL-1721). */\nexport const CHECKOUT_SHIPPING_COUNTRY_NAMES: Readonly<Record<string, string>> =\n {\n US: 'United States',\n CA: 'Canada',\n GB: 'United Kingdom',\n AU: 'Australia',\n DE: 'Germany',\n FR: 'France',\n }\n\n/**\n * A destination a shopper declared, or `undefined` for anything this session\n * could not collect an address for anyway. Never throws: an unknown code is\n * an undeclared destination, not an error, so a stale storefront that posts\n * one is answered by the plan below rather than by a 400 nobody can act on.\n */\nexport function normalizeCheckoutShippingCountry(\n value: unknown,\n): string | undefined {\n // `typeof` rather than `String(value)`: a JSON body is caller-shaped, and\n // `String(['US'])` is 'US'. Coercing would let an array declare a\n // destination, which is not a spelling any storefront sends.\n if (typeof value !== 'string') return undefined\n const code = value.trim().toUpperCase()\n return (CHECKOUT_SHIPPING_COUNTRIES as readonly string[]).includes(code)\n ? code\n : undefined\n}\n\nexport interface CheckoutShippingPlan {\n /** `shipping_address_collection[allowed_countries]` for this session. */\n countries: readonly string[]\n /** `shipping_options` for this session — valid for EVERY `countries` entry. */\n options: ResolvedShippingRate[]\n /**\n * Set when no session may be created at all:\n *\n * - `destination-required` — the merchant's rates differ by destination, so\n * there is no set of options honest for every address Stripe would accept.\n * Ask the shopper where they are shipping and plan again.\n * - `destination-unserved` — the merchant ships somewhere, but not there.\n * - `cart-unpriceable` — the merchant priced shipping, but no rate of theirs\n * resolves for THIS cart at ANY destination (AGL-2232). A tier table that\n * stops at 2 kg says nothing about a 3 kg parcel, and the honest answer is\n * to refuse rather than to ship it for nothing.\n */\n refusal?: 'destination-required' | 'destination-unserved' | 'cart-unpriceable'\n}\n\n/**\n * Whether this merchant prices shipping AT ALL (AGL-2232).\n *\n * A pure question about the SETTINGS, deliberately taking no cart, and that is\n * the whole point of it existing. `planCheckoutShipping` used to ask \"does any\n * rate resolve for any destination?\" and pass the live cart into the probe, so\n * a cart that exhausted every tier made the probe empty too — and an empty\n * probe reads as \"this merchant never set shipping up\", the one case that must\n * complete with no `shipping_options` and nothing charged. A 3 kg order at a\n * store whose weight tiers stop at 2 kg therefore shipped free, silently, on\n * every one of the three doors.\n *\n * Answered from the stored zones and rates instead: a rate bound to a zone\n * that exists, or local pickup, means the merchant made a shipping decision\n * and a cart their table cannot price is a REFUSAL. A merchant with no zones,\n * no rates and no pickup has made no such decision, and their session stays\n * byte-identical to the one AGL-1707 shipped.\n */\nexport function merchantPricesShipping(\n settings: ShippingSettings | undefined,\n): boolean {\n if (!settings) return false\n if (settings.localPickup) return true\n const zoneIds = new Set((settings.zones ?? []).map((zone) => zone.id))\n // A rate whose `zoneId` names no zone is unreachable by every resolver here,\n // so it is not evidence of a decision — counting it would refuse carts at a\n // store with nothing but orphaned rows.\n return (settings.rates ?? []).some((rate) => zoneIds.has(rate.zoneId))\n}\n\n/**\n * What a shopper is told when `cart-unpriceable` refuses (AGL-2232).\n *\n * One string, shared by all three doors, because the three used to phrase the\n * two existing refusals identically and drifting here would make the same\n * store say different things depending on which button was pressed. It names\n * the cart rather than the destination on purpose — a `Ship to` select cannot\n * fix a parcel no tier covers, so the refusal deliberately does NOT set\n * `needsShippingCountry`.\n */\nexport const CART_UNPRICEABLE_SHIPPING_MESSAGE =\n 'This store cannot price shipping for this order — it falls outside every ' +\n 'shipping rate the store has set up. Try removing an item, or contact the ' +\n 'store.'\n\n/** Identity of a resolved list, for comparing two destinations' offers. */\nfunction optionsKey(options: readonly ResolvedShippingRate[]): string {\n return options\n .map((option) => `${option.rateId}:${option.amountCents}`)\n .join('|')\n}\n\n/**\n * The whole shipping half of a Checkout Session: which destinations it may\n * accept an address for, and which rates it may charge (AGL-1721).\n *\n * THE INVARIANT IS THAT EVERY RETURNED OPTION IS VALID FOR EVERY RETURNED\n * COUNTRY. Stripe offers a session's `shipping_options` to whoever reaches the\n * page and charges whichever the shopper picks — it does not filter them by\n * the address entered, and there is no field on a `shipping_rate_data` that\n * would let it. So the ONLY place a zone can be enforced is here, by choosing\n * the two lists together: narrowing the allowed countries to the declared\n * destination is what makes the rates offered for it unpickable by anyone\n * else. Filtering the rate list alone would leave a session that still accepts\n * a French address against a US rate.\n *\n * Three shapes come out of it:\n *\n * 1. A merchant whose rates resolve the SAME for every collectable country —\n * one zone, a single '*' zone, or none at all — needs no destination and\n * keeps the session AGL-1707 shipped, byte for byte. The issue notes this\n * is the common configuration, and it is the one that must not regress.\n * 2. A declared destination resolves exactly, and the session is restricted\n * to it. A caller may not skip the restriction: the country arrives in a\n * request body a shopper can craft, so a session that took the country's\n * cheap rate while still accepting any address would hand that shopper\n * the defect on purpose.\n * 3. Otherwise the caller must refuse — see `refusal`. Refusing is not lost\n * revenue in either case: with rates that differ by zone there is no\n * correct amount to charge without knowing where the parcel is going, and\n * the union AGL-1707 shipped chose the wrong one silently.\n *\n * `cart.subtotalCents` is the PRE-discount items total, matching what the cart\n * displays, so a free-over threshold means what the shopper saw it mean.\n */\nexport function planCheckoutShipping(\n settings: ShippingSettings | undefined,\n cart: { subtotalCents: number; totalGrams?: number },\n destinationCountry?: unknown,\n): CheckoutShippingPlan {\n const countries = CHECKOUT_SHIPPING_COUNTRIES as readonly string[]\n const destination = normalizeCheckoutShippingCountry(destinationCountry)\n if (destination) {\n const options = resolveCheckoutShippingOptions(\n settings,\n [destination],\n cart,\n )\n // REFUSAL IS DECIDED ON SHIPPABLE RATES, PICKUP IS OFFERED AFTERWARDS\n // (AGL-2325). `resolveShippingRates` appends pickup independent of zone\n // matching, so a merchant who turned it on had a non-empty list for every\n // destination on earth and this branch returned before it could refuse\n // anyone: a shopper in France picked `Local pickup — Free` on a physical\n // order from a US-only store, Stripe collected their French address\n // because the session still allowed it, and the merchant was paid nothing\n // to carry the parcel there. Pickup is collection, not delivery, so it\n // cannot answer \"do you ship to France\".\n //\n // `shipsElsewhere` is the same question the old probe asked, narrowed to\n // shippable rates, and it keeps the same two-way fork: a merchant who\n // configured NO shipping is not refusing anyone, so that store keeps\n // completing exactly as it does today, while a merchant who ships\n // elsewhere but not here is refusing and saying so is the honest answer.\n // A merchant who ships NOWHERE is untouched by this: pickup-only is a\n // real configuration — they deliver to no one and refuse no one — and it\n // falls through to the offer below exactly as it did.\n const shipsElsewhere = countries.some(\n (country) =>\n shippableOnly(resolveCheckoutShippingOptions(settings, [country], cart))\n .length > 0,\n )\n if (shippableOnly(options).length === 0 && shipsElsewhere) {\n return { countries, options: [], refusal: 'destination-unserved' }\n }\n if (options.length > 0) return { countries: [destination], options }\n // NOTHING resolves anywhere for this cart, and the two reasons that can be\n // true of are opposite (AGL-2232). Asked of the SETTINGS rather than of\n // this cart, because the probe above cannot tell them apart: a merchant\n // who priced shipping and whose table simply does not reach this order is\n // refusing, and used to be handed the \"never set shipping up\" branch.\n return merchantPricesShipping(settings)\n ? { countries, options: [], refusal: 'cart-unpriceable' }\n : { countries, options: [] }\n }\n const offers = new Set(\n countries.map((country) =>\n optionsKey(resolveCheckoutShippingOptions(settings, [country], cart)),\n ),\n )\n // Compared as EMITTED — capped and sanitized — because that is the list a\n // shopper can pick from. Two destinations whose rates differ only past\n // Stripe's cap still offer the same five, and offering them is honest.\n if (offers.size > 1) {\n return { countries, options: [], refusal: 'destination-required' }\n }\n const union = resolveCheckoutShippingOptions(settings, countries, cart)\n // Every destination agrees, and what they agree on is NOTHING. The same\n // fork as the declared-destination branch above (AGL-2232): a store with no\n // shipping settings completes untouched, a store whose rates cannot reach\n // this cart refuses instead of carrying the parcel for free.\n if (union.length === 0 && merchantPricesShipping(settings)) {\n return { countries, options: [], refusal: 'cart-unpriceable' }\n }\n return { countries, options: union }\n}\n\n/**\n * A cart chosen so that every rate a merchant could have written resolves if\n * it can resolve at all (AGL-1791). The settings page has no cart, and two of\n * the four rate kinds price against one: `tierAmount` takes the first tier\n * whose `upTo` is at least the value, so a zero subtotal and zero weight clear\n * every tier a merchant would write, and a `free_over` rate resolves at any\n * subtotal.\n *\n * That makes a coverage answer a LOWER BOUND on the gaps. A destination\n * reported unserved is unserved for every cart; a destination reported served\n * may still be refused for a cart dearer or heavier than the merchant's last\n * tier. Erring in this direction is the deliberate half: the console must not\n * warn a merchant whose settings are fine.\n */\nconst COVERAGE_PROBE_CART = { subtotalCents: 0, totalGrams: 0 }\n\n/** What a merchant's saved zones and rates cost their shoppers (AGL-1791). */\nexport interface ShippingCoverage {\n /** Collectable destinations at least one rate reaches. */\n served: string[]\n /**\n * Collectable destinations CHECKOUT REFUSES — `destination-unserved`.\n *\n * EMPTY FOR A MERCHANT WHOSE RATES REACH NOWHERE, who is not misconfigured:\n * `planCheckoutShipping` refuses nobody when no rate resolves anywhere, so\n * that store charges no shipping and completes exactly as it always has.\n * The rule lives here rather than in the caller because reading `served`\n * against a bare partition is how a surface comes to warn every store that\n * does not ship.\n */\n unserved: string[]\n /** No rate reaches anywhere: no shipping is charged, and nobody refused. */\n shipsNowhere: boolean\n /**\n * Rates differ by destination, so the storefront asks the shopper where the\n * parcel is going before it can price one — a checkout step the merchant\n * added by saving these zones, and never chose.\n */\n asksDestination: boolean\n /** Some zone already claims rest of world, so `*` is not the missing piece. */\n hasRestOfWorldZone: boolean\n /**\n * The merchant offers local pickup, so checkout presents a free collection\n * choice at every destination it does not refuse (AGL-2325).\n *\n * Deliberately NOT folded into `served`: pickup resolves for every country\n * because it is appended independent of zone matching, so counting it as\n * coverage told a US-only merchant who had switched it on that checkout\n * \"can price shipping to every destination\", which is the sentence that\n * hid the defect. It is reported alongside instead, so the card can say\n * both true things: these destinations are refused, and pickup is offered\n * to the ones that are not.\n */\n offersLocalPickup: boolean\n}\n\n/**\n * Which of the collectable destinations a merchant's settings actually cover\n * (AGL-1791), for a console surface to show them.\n *\n * Measured against `CHECKOUT_SHIPPING_COUNTRIES` and nothing wider: those six\n * are the only destinations a storefront session collects an address for, so\n * they are the only ones a merchant can lose an order to. Counting coverage\n * against every country on earth would report a gap for destinations no\n * shopper can reach checkout from.\n *\n * Answered through `resolveCheckoutShippingOptions` — the same function the\n * session is built from — so a row the console allows but Stripe would reject\n * (blank id, blank name) counts as the nothing it resolves to, and a specific\n * zone with no rates still hides a `*` zone here exactly as it does at\n * checkout.\n */\nexport function summarizeShippingCoverage(\n settings: ShippingSettings | undefined,\n): ShippingCoverage {\n const served: string[] = []\n const unserved: string[] = []\n const offers = new Set<string>()\n for (const country of CHECKOUT_SHIPPING_COUNTRIES) {\n const options = resolveCheckoutShippingOptions(\n settings,\n [country],\n COVERAGE_PROBE_CART,\n )\n // `asksDestination` is asked of the FULL list — pickup is a real option a\n // shopper picks, so a merchant whose US destination offers a rate plus\n // pickup while France offers only pickup genuinely does make checkout ask.\n offers.add(optionsKey(options))\n // `served` is asked of the SHIPPABLE list, so that it answers the same\n // question `planCheckoutShipping` refuses on (AGL-2325).\n ;(shippableOnly(options).length > 0 ? served : unserved).push(country)\n }\n return {\n served,\n unserved: served.length > 0 ? unserved : [],\n shipsNowhere: served.length === 0,\n asksDestination: offers.size > 1,\n offersLocalPickup: Boolean(settings?.localPickup),\n hasRestOfWorldZone: (settings?.zones ?? []).some((zone) =>\n zone.countries.some((code) => code === '*'),\n ),\n }\n}\n\n/**\n * Emit `shipping_address_collection[allowed_countries][n]` onto a session's\n * form body. Stripe will not apply a `shipping_options` rate without an\n * address to ship to, so the two always travel together — and the countries\n * are the OTHER half of what makes a rate honest (AGL-1721), so pass the list\n * `planCheckoutShipping` returned rather than defaulting it beside a rate list\n * resolved for something narrower.\n */\nexport function appendShippingAddressCollectionParams(\n params: URLSearchParams,\n countries: readonly string[] = CHECKOUT_SHIPPING_COUNTRIES,\n): void {\n countries.forEach((code, index) => {\n params.set(`shipping_address_collection[allowed_countries][${index}]`, code)\n })\n}\n\n/**\n * Emit resolved rates as `shipping_options` on a Checkout Session's form body.\n *\n * THIS IS THE ONLY THING THAT MAKES STRIPE CHARGE SHIPPING. Without these keys\n * Stripe presents no shipping choice and `total_details.amount_shipping` is 0\n * however many zones and rates the merchant saved (AGL-1707).\n *\n * An empty list emits NOTHING — not an empty array — so a merchant who\n * configured no shipping keeps a session byte-identical to the one built\n * before shipping was wired at all. That guarantee lives here rather than in\n * each caller, so neither checkout path can lose it independently (AGL-1720).\n */\nexport function appendCheckoutShippingParams(\n params: URLSearchParams,\n options: readonly ResolvedShippingRate[],\n): void {\n options.forEach((option, index) => {\n const field = `shipping_options[${index}][shipping_rate_data]`\n params.set(`${field}[type]`, 'fixed_amount')\n params.set(`${field}[display_name]`, option.name.slice(0, 100))\n params.set(`${field}[fixed_amount][amount]`, String(option.amountCents))\n params.set(`${field}[fixed_amount][currency]`, 'usd')\n })\n}\n"],"names":["LOCAL_PICKUP_RATE_ID","zoneCode","code","String","trim","toUpperCase","isWildcard","zoneMatches","zone","country","countries","some","tierAmount","tiers","value","sorted","sort","a","b","upTo","tier","amountCents","resolveShippingRates","settings","destinationCountry","cart","zones","specific","filter","matched","length","zoneIds","Set","map","id","resolved","rate","rates","has","zoneId","kind","Math","max","round","freeOverCents","subtotalCents","totalGrams","push","rateId","name","localPickup","shippableOnly","options","option","MAX_CHECKOUT_SHIPPING_OPTIONS","CHECKOUT_SHIPPING_COUNTRIES","resolveCheckoutShippingOptions","destinationCountries","byRateId","Map","Number","existing","get","set","values","localeCompare","slice","CHECKOUT_SHIPPING_COUNTRY_NAMES","US","CA","GB","AU","DE","FR","normalizeCheckoutShippingCountry","undefined","includes","merchantPricesShipping","CART_UNPRICEABLE_SHIPPING_MESSAGE","optionsKey","join","planCheckoutShipping","destination","shipsElsewhere","refusal","offers","size","union","COVERAGE_PROBE_CART","summarizeShippingCoverage","served","unserved","add","shipsNowhere","asksDestination","offersLocalPickup","Boolean","hasRestOfWorldZone","appendShippingAddressCollectionParams","params","forEach","index","appendCheckoutShippingParams","field"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BC;AA4CD;;;;;;;;;CASC,GACD,OAAO,MAAMA,uBAAuB,SAAQ;AAE5C;;;;;;;;;CASC,GACD,MAAMC,WAAW,CAACC,OAA0BC,OAAOD,eAAAA,OAAQ,IAAIE,IAAI,GAAGC,WAAW;AAEjF,yDAAyD,GACzD,MAAMC,aAAa,CAACJ,OAA2BD,SAASC,UAAU;AAElE,SAASK,YAAYC,IAAkB,EAAEC,OAAe;QAC9CD;IAAR,OAAO,EAACA,kBAAAA,KAAKE,SAAS,YAAdF,kBAAkB,EAAE,EAAEG,IAAI,CAChC,CAACT,OAASI,WAAWJ,SAASD,SAASC,UAAUO;AAErD;AAEA,SAASG,WACPC,KAAiC,EACjCC,KAAa;IAEb,MAAMC,SAAS;WAAKF,gBAAAA,QAAS,EAAE;KAAE,CAACG,IAAI,CAAC,CAACC,GAAGC,IAAMD,EAAEE,IAAI,GAAGD,EAAEC,IAAI;IAChE,KAAK,MAAMC,QAAQL,OAAQ;QACzB,IAAID,SAASM,KAAKD,IAAI,EAAE,OAAOC,KAAKC,WAAW;IACjD;IACA,sEAAsE;IACtE,qCAAqC;IACrC,OAAO;AACT;AAEA;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,qBACdC,QAAsC,EACtCC,kBAAsC,EACtCC,IAAoD;QAItCF,iBAgBKA;IAlBnB,IAAI,CAACA,YAAY,CAACC,oBAAoB,OAAO,EAAE;IAC/C,MAAMf,UAAUe,mBAAmBnB,WAAW;IAC9C,MAAMqB,SAAQH,kBAAAA,SAASG,KAAK,YAAdH,kBAAkB,EAAE;IAClC,2EAA2E;IAC3E,0EAA0E;IAC1E,wEAAwE;IACxE,yEAAyE;IACzE,0EAA0E;IAC1E,0EAA0E;IAC1E,qCAAqC;IACrC,MAAMI,WAAWD,MAAME,MAAM,CAAC,CAACpB;YAC5BA;eAAD,EAACA,kBAAAA,KAAKE,SAAS,YAAdF,kBAAkB,EAAE,EAAEG,IAAI,CAAC,CAACT,OAASD,SAASC,UAAUO;;IAE3D,MAAMoB,UAAUF,SAASG,MAAM,GAC3BH,WACAD,MAAME,MAAM,CAAC,CAACpB,OAASD,YAAYC,MAAMC;IAC7C,MAAMsB,UAAU,IAAIC,IAAIH,QAAQI,GAAG,CAAC,CAACzB,OAASA,KAAK0B,EAAE;IACrD,MAAMC,WAAmC,EAAE;IAC3C,KAAK,MAAMC,SAAQb,kBAAAA,SAASc,KAAK,YAAdd,kBAAkB,EAAE,CAAE;QACvC,IAAI,CAACQ,QAAQO,GAAG,CAACF,KAAKG,MAAM,GAAG;QAC/B,IAAIlB,cAA6B;QACjC,OAAQe,KAAKI,IAAI;YACf,KAAK;oBACkCJ;gBAArCf,cAAcoB,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,EAACP,oBAAAA,KAAKf,WAAW,YAAhBe,oBAAoB;gBACzD;YACF,KAAK;oBAK0BA;gBAJ7Bf,cACEe,KAAKQ,aAAa,IAAI,QACtBnB,KAAKoB,aAAa,IAAIT,KAAKQ,aAAa,GACpC,IACAH,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,EAACP,qBAAAA,KAAKf,WAAW,YAAhBe,qBAAoB;gBACjD;YACF,KAAK;gBACHf,cAAcT,WAAWwB,KAAKvB,KAAK,EAAEY,KAAKoB,aAAa;gBACvD;YACF,KAAK;oBACkCpB;gBAArCJ,cAAcT,WAAWwB,KAAKvB,KAAK,GAAEY,mBAAAA,KAAKqB,UAAU,YAAfrB,mBAAmB;gBACxD;QACJ;QACA,IAAIJ,eAAe,MAAM;QACzBc,SAASY,IAAI,CAAC;YAAEC,QAAQZ,KAAKF,EAAE;YAAEe,MAAMb,KAAKa,IAAI;YAAE5B;QAAY;IAChE;IACA,IAAIE,SAAS2B,WAAW,EAAE;QACxBf,SAASY,IAAI,CAAC;YACZC,QAAQhD;YACRiD,MAAM;YACN5B,aAAa;QACf;IACF;IACA,OAAOc,SAASnB,IAAI,CAAC,CAACC,GAAGC,IAAMD,EAAEI,WAAW,GAAGH,EAAEG,WAAW;AAC9D;AAEA;;;;;;CAMC,GACD,SAAS8B,cACPC,OAAwC;IAExC,OAAOA,QAAQxB,MAAM,CAAC,CAACyB,SAAWA,OAAOL,MAAM,KAAKhD;AACtD;AAEA,yEAAyE,GACzE,OAAO,MAAMsD,gCAAgC,EAAC;AAE9C;;;;;;;;;CASC,GACD,OAAO,MAAMC,8BAA8B;IACzC;IACA;IACA;IACA;IACA;IACA;CACD,CAAS;AAEV;;;;;;;;;;;;;;;;;;CAkBC,GACD,OAAO,SAASC,+BACdjC,QAAsC,EACtCkC,oBAAuC,EACvChC,IAAoD;IAEpD,IAAI,CAACF,UAAU,OAAO,EAAE;IACxB,MAAMmC,WAAW,IAAIC;IACrB,KAAK,MAAMlD,WAAWgD,qBAAsB;QAC1C,KAAK,MAAMrB,QAAQd,qBAAqBC,UAAUd,SAASgB,MAAO;YAChE,oEAAoE;YACpE,sEAAsE;YACtE,IAAI,CAACW,KAAKY,MAAM,IAAI,CAACZ,KAAKa,IAAI,EAAE;YAChC,MAAM5B,cAAcoB,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,CAACiB,OAAOxB,KAAKf,WAAW,KAAK;YACvE,MAAMwC,WAAWH,SAASI,GAAG,CAAC1B,KAAKY,MAAM;YACzC,iEAAiE;YACjE,uEAAuE;YACvE,sEAAsE;YACtE,IAAI,CAACa,YAAYxC,cAAcwC,SAASxC,WAAW,EAAE;gBACnDqC,SAASK,GAAG,CAAC3B,KAAKY,MAAM,EAAE,aAAKZ;oBAAMf;;YACvC;QACF;IACF;IACA,OACE;WAAIqC,SAASM,MAAM;KAAG,AACpB,sEAAsE;KACrEhD,IAAI,CACH,CAACC,GAAGC,IACFD,EAAEI,WAAW,GAAGH,EAAEG,WAAW,IAAIJ,EAAE+B,MAAM,CAACiB,aAAa,CAAC/C,EAAE8B,MAAM,EAEpE,uEAAuE;IACvE,qEAAqE;KACpEkB,KAAK,CAAC,GAAGZ;AAEhB;AAEA,sEAAsE,GACtE,OAAO,MAAMa,kCACX;IACEC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;AACN,EAAC;AAEH;;;;;CAKC,GACD,OAAO,SAASC,iCACd5D,KAAc;IAEd,0EAA0E;IAC1E,kEAAkE;IAClE,6DAA6D;IAC7D,IAAI,OAAOA,UAAU,UAAU,OAAO6D;IACtC,MAAMzE,OAAOY,MAAMV,IAAI,GAAGC,WAAW;IACrC,OAAO,AAACkD,4BAAkDqB,QAAQ,CAAC1E,QAC/DA,OACAyE;AACN;AAsBA;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,SAASE,uBACdtD,QAAsC;QAIbA,iBAIjBA;IANR,IAAI,CAACA,UAAU,OAAO;IACtB,IAAIA,SAAS2B,WAAW,EAAE,OAAO;IACjC,MAAMnB,UAAU,IAAIC,IAAI,EAACT,kBAAAA,SAASG,KAAK,YAAdH,kBAAkB,EAAE,EAAEU,GAAG,CAAC,CAACzB,OAASA,KAAK0B,EAAE;IACpE,6EAA6E;IAC7E,4EAA4E;IAC5E,wCAAwC;IACxC,OAAO,EAACX,kBAAAA,SAASc,KAAK,YAAdd,kBAAkB,EAAE,EAAEZ,IAAI,CAAC,CAACyB,OAASL,QAAQO,GAAG,CAACF,KAAKG,MAAM;AACtE;AAEA;;;;;;;;;CASC,GACD,OAAO,MAAMuC,oCACX,8EACA,8EACA,SAAQ;AAEV,yEAAyE,GACzE,SAASC,WAAW3B,OAAwC;IAC1D,OAAOA,QACJnB,GAAG,CAAC,CAACoB,SAAW,GAAGA,OAAOL,MAAM,CAAC,CAAC,EAAEK,OAAOhC,WAAW,EAAE,EACxD2D,IAAI,CAAC;AACV;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCC,GACD,OAAO,SAASC,qBACd1D,QAAsC,EACtCE,IAAoD,EACpDD,kBAA4B;IAE5B,MAAMd,YAAY6C;IAClB,MAAM2B,cAAcR,iCAAiClD;IACrD,IAAI0D,aAAa;QACf,MAAM9B,UAAUI,+BACdjC,UACA;YAAC2D;SAAY,EACbzD;QAEF,sEAAsE;QACtE,wEAAwE;QACxE,0EAA0E;QAC1E,uEAAuE;QACvE,yEAAyE;QACzE,oEAAoE;QACpE,0EAA0E;QAC1E,uEAAuE;QACvE,yCAAyC;QACzC,EAAE;QACF,yEAAyE;QACzE,sEAAsE;QACtE,qEAAqE;QACrE,kEAAkE;QAClE,yEAAyE;QACzE,sEAAsE;QACtE,yEAAyE;QACzE,sDAAsD;QACtD,MAAM0D,iBAAiBzE,UAAUC,IAAI,CACnC,CAACF,UACC0C,cAAcK,+BAA+BjC,UAAU;gBAACd;aAAQ,EAAEgB,OAC/DK,MAAM,GAAG;QAEhB,IAAIqB,cAAcC,SAAStB,MAAM,KAAK,KAAKqD,gBAAgB;YACzD,OAAO;gBAAEzE;gBAAW0C,SAAS,EAAE;gBAAEgC,SAAS;YAAuB;QACnE;QACA,IAAIhC,QAAQtB,MAAM,GAAG,GAAG,OAAO;YAAEpB,WAAW;gBAACwE;aAAY;YAAE9B;QAAQ;QACnE,2EAA2E;QAC3E,wEAAwE;QACxE,wEAAwE;QACxE,0EAA0E;QAC1E,sEAAsE;QACtE,OAAOyB,uBAAuBtD,YAC1B;YAAEb;YAAW0C,SAAS,EAAE;YAAEgC,SAAS;QAAmB,IACtD;YAAE1E;YAAW0C,SAAS,EAAE;QAAC;IAC/B;IACA,MAAMiC,SAAS,IAAIrD,IACjBtB,UAAUuB,GAAG,CAAC,CAACxB,UACbsE,WAAWvB,+BAA+BjC,UAAU;YAACd;SAAQ,EAAEgB;IAGnE,0EAA0E;IAC1E,uEAAuE;IACvE,uEAAuE;IACvE,IAAI4D,OAAOC,IAAI,GAAG,GAAG;QACnB,OAAO;YAAE5E;YAAW0C,SAAS,EAAE;YAAEgC,SAAS;QAAuB;IACnE;IACA,MAAMG,QAAQ/B,+BAA+BjC,UAAUb,WAAWe;IAClE,wEAAwE;IACxE,4EAA4E;IAC5E,0EAA0E;IAC1E,6DAA6D;IAC7D,IAAI8D,MAAMzD,MAAM,KAAK,KAAK+C,uBAAuBtD,WAAW;QAC1D,OAAO;YAAEb;YAAW0C,SAAS,EAAE;YAAEgC,SAAS;QAAmB;IAC/D;IACA,OAAO;QAAE1E;QAAW0C,SAASmC;IAAM;AACrC;AAEA;;;;;;;;;;;;;CAaC,GACD,MAAMC,sBAAsB;IAAE3C,eAAe;IAAGC,YAAY;AAAE;AA0C9D;;;;;;;;;;;;;;;CAeC,GACD,OAAO,SAAS2C,0BACdlE,QAAsC;;IAEtC,MAAMmE,SAAmB,EAAE;IAC3B,MAAMC,WAAqB,EAAE;IAC7B,MAAMN,SAAS,IAAIrD;IACnB,KAAK,MAAMvB,WAAW8C,4BAA6B;QACjD,MAAMH,UAAUI,+BACdjC,UACA;YAACd;SAAQ,EACT+E;QAEF,0EAA0E;QAC1E,uEAAuE;QACvE,2EAA2E;QAC3EH,OAAOO,GAAG,CAACb,WAAW3B;QAGpBD,CAAAA,cAAcC,SAAStB,MAAM,GAAG,IAAI4D,SAASC,QAAO,EAAG5C,IAAI,CAACtC;IAChE;IACA,OAAO;QACLiF;QACAC,UAAUD,OAAO5D,MAAM,GAAG,IAAI6D,WAAW,EAAE;QAC3CE,cAAcH,OAAO5D,MAAM,KAAK;QAChCgE,iBAAiBT,OAAOC,IAAI,GAAG;QAC/BS,mBAAmBC,QAAQzE,4BAAAA,SAAU2B,WAAW;QAChD+C,oBAAoB,SAAC1E,4BAAAA,SAAUG,KAAK,mBAAI,EAAE,EAAEf,IAAI,CAAC,CAACH,OAChDA,KAAKE,SAAS,CAACC,IAAI,CAAC,CAACT,OAASA,SAAS;IAE3C;AACF;AAEA;;;;;;;CAOC,GACD,OAAO,SAASgG,sCACdC,MAAuB,EACvBzF,YAA+B6C,2BAA2B;IAE1D7C,UAAU0F,OAAO,CAAC,CAAClG,MAAMmG;QACvBF,OAAOpC,GAAG,CAAC,CAAC,+CAA+C,EAAEsC,MAAM,CAAC,CAAC,EAAEnG;IACzE;AACF;AAEA;;;;;;;;;;;CAWC,GACD,OAAO,SAASoG,6BACdH,MAAuB,EACvB/C,OAAwC;IAExCA,QAAQgD,OAAO,CAAC,CAAC/C,QAAQgD;QACvB,MAAME,QAAQ,CAAC,iBAAiB,EAAEF,MAAM,qBAAqB,CAAC;QAC9DF,OAAOpC,GAAG,CAAC,GAAGwC,MAAM,MAAM,CAAC,EAAE;QAC7BJ,OAAOpC,GAAG,CAAC,GAAGwC,MAAM,cAAc,CAAC,EAAElD,OAAOJ,IAAI,CAACiB,KAAK,CAAC,GAAG;QAC1DiC,OAAOpC,GAAG,CAAC,GAAGwC,MAAM,sBAAsB,CAAC,EAAEpG,OAAOkD,OAAOhC,WAAW;QACtE8E,OAAOpC,GAAG,CAAC,GAAGwC,MAAM,wBAAwB,CAAC,EAAE;IACjD;AACF"}
|