@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,92 @@
|
|
|
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
|
+
* Taxes v1 (AGL-285): manual rates per region resolved most-specific
|
|
18
|
+
* first (country+state beats country), or Stripe Tax automatic
|
|
19
|
+
* calculation when the host opts in. Settings live on the
|
|
20
|
+
* `hosts/{hostId}/settings/store` doc under `tax`. Pure — checkout and
|
|
21
|
+
* POS call these; Stripe Tax mode bypasses them entirely.
|
|
22
|
+
*/ /**
|
|
23
|
+
* The highest percentage this accepts. A rate above 100% is a decimal-point
|
|
24
|
+
* typo (`825` for `8.25`), not a jurisdiction, and multiplying a guest's
|
|
25
|
+
* deposit by nine because of one is a far worse failure than collecting
|
|
26
|
+
* nothing. Out of range resolves to OFF rather than being clamped to a number
|
|
27
|
+
* the merchant did not choose — and the editor says so on screen, so the
|
|
28
|
+
* refusal is never silent.
|
|
29
|
+
*/ export const FLAT_TAX_MAX_PCT = 100;
|
|
30
|
+
/** True when a typed percentage is one this will actually apply. */ export function isUsableFlatTaxPct(pct) {
|
|
31
|
+
const value = Number(pct);
|
|
32
|
+
return Number.isFinite(value) && value > 0 && value <= FLAT_TAX_MAX_PCT;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Tax cents for a flat merchant rate on one charged amount, EXCLUSIVE — added
|
|
36
|
+
* on top of the price, never back-calculated out of it.
|
|
37
|
+
*
|
|
38
|
+
* `pricesIncludeTax` is deliberately not consulted: it is a goods-pricing
|
|
39
|
+
* setting, and honouring it here would mean a merchant types a lodging rate,
|
|
40
|
+
* saves, and the guest's total does not move — a setting that reads as
|
|
41
|
+
* configured while collecting nothing is the AGL-1999 failure restated.
|
|
42
|
+
*
|
|
43
|
+
* Pure and total. Unusable input answers zero and never throws.
|
|
44
|
+
*/ export function resolveFlatTaxCents(rate, chargeCents, fallbackLabel) {
|
|
45
|
+
const pct = Number(rate == null ? void 0 : rate.pct);
|
|
46
|
+
if (!isUsableFlatTaxPct(pct)) return {
|
|
47
|
+
taxCents: 0,
|
|
48
|
+
label: '',
|
|
49
|
+
pct: 0
|
|
50
|
+
};
|
|
51
|
+
const taxCents = computeTaxCents(chargeCents, pct, false);
|
|
52
|
+
if (!(taxCents > 0)) return {
|
|
53
|
+
taxCents: 0,
|
|
54
|
+
label: '',
|
|
55
|
+
pct: 0
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
taxCents,
|
|
59
|
+
label: ((rate == null ? void 0 : rate.label) || fallbackLabel).slice(0, 120),
|
|
60
|
+
pct
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Most-specific matching rate, or null (no tax). */ export function resolveTaxRate(settings, address) {
|
|
64
|
+
var _address_country, _address_state, _settings_rates;
|
|
65
|
+
if (!settings || settings.mode === 'stripe') return null;
|
|
66
|
+
const country = ((_address_country = address.country) != null ? _address_country : '').toUpperCase();
|
|
67
|
+
const state = ((_address_state = address.state) != null ? _address_state : '').toUpperCase();
|
|
68
|
+
if (!country) return null;
|
|
69
|
+
let match = null;
|
|
70
|
+
for (const rate of (_settings_rates = settings.rates) != null ? _settings_rates : []){
|
|
71
|
+
if (rate.country.toUpperCase() !== country) continue;
|
|
72
|
+
if (rate.state) {
|
|
73
|
+
if (rate.state.toUpperCase() === state) return rate;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
match = match != null ? match : rate;
|
|
77
|
+
}
|
|
78
|
+
return match;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Tax cents for a taxable amount. Exclusive pricing adds on top;
|
|
82
|
+
* inclusive pricing back-calculates the contained tax (for receipts —
|
|
83
|
+
* the charge total does not change).
|
|
84
|
+
*/ export function computeTaxCents(taxableCents, pct, pricesIncludeTax = false) {
|
|
85
|
+
if (!(pct > 0) || !(taxableCents > 0)) return 0;
|
|
86
|
+
if (pricesIncludeTax) {
|
|
87
|
+
return Math.round(taxableCents - taxableCents / (1 + pct / 100));
|
|
88
|
+
}
|
|
89
|
+
return Math.round(taxableCents * pct / 100);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
//# sourceMappingURL=commerce-tax.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/model/commerce-tax.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 * Taxes v1 (AGL-285): manual rates per region resolved most-specific\n * first (country+state beats country), or Stripe Tax automatic\n * calculation when the host opts in. Settings live on the\n * `hosts/{hostId}/settings/store` doc under `tax`. Pure — checkout and\n * POS call these; Stripe Tax mode bypasses them entirely.\n */\n\nexport interface TaxRate {\n /** ISO-3166 alpha-2, e.g. 'US'. */\n country: string\n /** Region/state code, e.g. 'TX'; absent = whole country. */\n state?: string\n /** Percent, e.g. 8.25. */\n pct: number\n /** Receipt label, e.g. 'TX sales tax'. */\n label?: string\n}\n\n/**\n * A FLAT, merchant-entered rate for a regime the goods sales-tax machinery\n * above does not describe (AGL-1969 lodging, AGL-2028 services).\n *\n * ## Why this is not another `TaxRate`\n *\n * `rates[]` is a SALES tax table resolved against an address, most-specific\n * first. Lodging (occupancy/hotel tax) and service tax are separate regimes\n * with their own rates, their own registration and their own return, and the\n * number a merchant typed into the goods table is not the right number for a\n * night or an appointment. Reading `rates[]` for either would be confidently\n * wrong rather than merely absent — which is exactly why `reserve.ts` and\n * `bookings/server.ts` charged nothing at all until the merchant was given a\n * field of their own to answer in.\n *\n * ## Off is the default and the default is load-bearing\n *\n * An absent, zero, negative, non-finite or out-of-range `pct` resolves to\n * ZERO. Nothing an existing merchant is charging today moves because this\n * shipped; a rate applies only once a merchant has typed one and saved.\n *\n * ## It is always MANUAL, in every store mode\n *\n * Deliberately independent of `TaxSettings.mode`. Stripe Tax cannot compute\n * either regime from these sessions — it needs a lodging or service tax code\n * no handler here sends — so a `mode: 'stripe'` store would otherwise have no\n * way to collect them at all. Riding as an ordinary line item makes the\n * derived `taxMode` read `manual`: the merchant's own rate, never computed\n * against Aglyn's registrations (AGL-1904).\n *\n * ## Aglyn takes NO position on what is owed\n *\n * This is a calculator the merchant configures, records and can read back. It\n * states no view on whether a jurisdiction imposes the tax, on who must\n * register, or on who must remit — those attach by operation of law and\n * belong to counsel (AGL-1904).\n *\n * ⚠️ The sentence that used to stand here — \"Terms §10.3 already puts the\n * question on the merchant\" — is FALSE as of 2026-08-24 (AGL-1956). Aglyn\n * accepts marketplace-facilitator status, ToS §10.3 no longer assigns sales\n * tax to the merchant, and the new ToS §10.7 says Aglyn calculates, collects\n * and remits it WHERE IT HAS A FACILITATOR OBLIGATION. Do not cite §10.3 as\n * authority for merchant-facing tax copy again.\n *\n * What is still true, and is why this module did not change: these FLAT RATES\n * are the manual/lodging/service path, which never touches Aglyn's\n * registrations and is not what §10.7 covers. The rates a merchant types here\n * remain theirs to determine.\n *\n * The merchant-facing copy this note used to call an OWED follow-up is DONE.\n * `storefront-tax-summary-card.component.tsx` said \"Aglyn does not make that\n * determination for you\" and was rewritten to §10.7 in `f7e5465f5`.\n * `tax-settings-card.component.tsx` was read and needed no change — it governs\n * exactly these flat lodging/service rates, which §10.7 does not reach, so it\n * was already saying the right thing about the right taxes. Recorded rather\n * than deleted: the next reader should not have to re-derive that the second\n * card's silence is correct rather than overlooked.\n */\nexport interface FlatTaxRate {\n /** Percent, e.g. 6. Absent or non-positive = off, which is the default. */\n pct?: number\n /** Receipt label, e.g. 'Occupancy tax'. */\n label?: string\n}\n\n/** What a flat rate resolved to for one charge. */\nexport interface ResolvedFlatTax {\n taxCents: number\n /** The label to put on the receipt line; empty when there is no tax. */\n label: string\n /** The percentage actually applied — 0 when the rate is off or invalid. */\n pct: number\n}\n\n/**\n * The highest percentage this accepts. A rate above 100% is a decimal-point\n * typo (`825` for `8.25`), not a jurisdiction, and multiplying a guest's\n * deposit by nine because of one is a far worse failure than collecting\n * nothing. Out of range resolves to OFF rather than being clamped to a number\n * the merchant did not choose — and the editor says so on screen, so the\n * refusal is never silent.\n */\nexport const FLAT_TAX_MAX_PCT = 100\n\n/** True when a typed percentage is one this will actually apply. */\nexport function isUsableFlatTaxPct(pct: unknown): boolean {\n const value = Number(pct)\n return Number.isFinite(value) && value > 0 && value <= FLAT_TAX_MAX_PCT\n}\n\n/**\n * Tax cents for a flat merchant rate on one charged amount, EXCLUSIVE — added\n * on top of the price, never back-calculated out of it.\n *\n * `pricesIncludeTax` is deliberately not consulted: it is a goods-pricing\n * setting, and honouring it here would mean a merchant types a lodging rate,\n * saves, and the guest's total does not move — a setting that reads as\n * configured while collecting nothing is the AGL-1999 failure restated.\n *\n * Pure and total. Unusable input answers zero and never throws.\n */\nexport function resolveFlatTaxCents(\n rate: FlatTaxRate | undefined | null,\n chargeCents: number,\n fallbackLabel: string,\n): ResolvedFlatTax {\n const pct = Number(rate?.pct)\n if (!isUsableFlatTaxPct(pct)) return { taxCents: 0, label: '', pct: 0 }\n const taxCents = computeTaxCents(chargeCents, pct, false)\n if (!(taxCents > 0)) return { taxCents: 0, label: '', pct: 0 }\n return {\n taxCents,\n label: (rate?.label || fallbackLabel).slice(0, 120),\n pct,\n }\n}\n\nexport interface TaxSettings {\n /**\n * 'manual' rates below, 'stripe' for Stripe Tax automatic, or 'none' —\n * an EXPLICIT decision not to collect (AGL-1999). `undefined` is not a\n * fourth mode: it means nobody has decided, and `storefrontTaxDecision`\n * refuses the sale rather than zero-rating it silently.\n */\n mode?: 'manual' | 'stripe' | 'none'\n /** Displayed prices already include tax (VAT-style). */\n pricesIncludeTax?: boolean\n /**\n * Store origin (AGL-285): the legacy single-product checkout taxes by\n * origin because the buyer address arrives inside Stripe Checkout;\n * Checkout v2 (AGL-296) collects the address first and taxes by\n * destination.\n */\n origin?: TaxAddress\n rates?: TaxRate[]\n /**\n * OCCUPANCY / LODGING tax on a reservation deposit (AGL-1969). Off unless\n * the merchant sets it — see `FlatTaxRate`. Read by `reserve.ts` only.\n */\n lodging?: FlatTaxRate\n /**\n * SERVICE tax on a paid booking (AGL-2028). Off unless the merchant sets\n * it — see `FlatTaxRate`. Read by the bookings plugin only.\n *\n * ITS EXISTENCE IS THE OPT-IN. AGL-2000 declined to apply the goods\n * `rates[]` to an appointment partly because nothing said the merchant\n * meant those settings to cover bookings — they are another plugin's\n * surface. A field of its own, labelled for services and blank until\n * somebody fills it in, is the merchant saying so explicitly. Reading\n * `rates[]` for a booking is still wrong and still nothing does it.\n */\n service?: FlatTaxRate\n}\n\nexport interface TaxAddress {\n country?: string\n state?: string\n}\n\n/** Most-specific matching rate, or null (no tax). */\nexport function resolveTaxRate(\n settings: TaxSettings | undefined,\n address: TaxAddress,\n): TaxRate | null {\n if (!settings || settings.mode === 'stripe') return null\n const country = (address.country ?? '').toUpperCase()\n const state = (address.state ?? '').toUpperCase()\n if (!country) return null\n let match: TaxRate | null = null\n for (const rate of settings.rates ?? []) {\n if (rate.country.toUpperCase() !== country) continue\n if (rate.state) {\n if (rate.state.toUpperCase() === state) return rate\n continue\n }\n match = match ?? rate\n }\n return match\n}\n\n/**\n * Tax cents for a taxable amount. Exclusive pricing adds on top;\n * inclusive pricing back-calculates the contained tax (for receipts —\n * the charge total does not change).\n */\nexport function computeTaxCents(\n taxableCents: number,\n pct: number,\n pricesIncludeTax = false,\n): number {\n if (!(pct > 0) || !(taxableCents > 0)) return 0\n if (pricesIncludeTax) {\n return Math.round(taxableCents - taxableCents / (1 + pct / 100))\n }\n return Math.round((taxableCents * pct) / 100)\n}\n"],"names":["FLAT_TAX_MAX_PCT","isUsableFlatTaxPct","pct","value","Number","isFinite","resolveFlatTaxCents","rate","chargeCents","fallbackLabel","taxCents","label","computeTaxCents","slice","resolveTaxRate","settings","address","mode","country","toUpperCase","state","match","rates","taxableCents","pricesIncludeTax","Math","round"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;CAMC,GAuFD;;;;;;;CAOC,GACD,OAAO,MAAMA,mBAAmB,IAAG;AAEnC,kEAAkE,GAClE,OAAO,SAASC,mBAAmBC,GAAY;IAC7C,MAAMC,QAAQC,OAAOF;IACrB,OAAOE,OAAOC,QAAQ,CAACF,UAAUA,QAAQ,KAAKA,SAASH;AACzD;AAEA;;;;;;;;;;CAUC,GACD,OAAO,SAASM,oBACdC,IAAoC,EACpCC,WAAmB,EACnBC,aAAqB;IAErB,MAAMP,MAAME,OAAOG,wBAAAA,KAAML,GAAG;IAC5B,IAAI,CAACD,mBAAmBC,MAAM,OAAO;QAAEQ,UAAU;QAAGC,OAAO;QAAIT,KAAK;IAAE;IACtE,MAAMQ,WAAWE,gBAAgBJ,aAAaN,KAAK;IACnD,IAAI,CAAEQ,CAAAA,WAAW,CAAA,GAAI,OAAO;QAAEA,UAAU;QAAGC,OAAO;QAAIT,KAAK;IAAE;IAC7D,OAAO;QACLQ;QACAC,OAAO,AAACJ,CAAAA,CAAAA,wBAAAA,KAAMI,KAAK,KAAIF,aAAY,EAAGI,KAAK,CAAC,GAAG;QAC/CX;IACF;AACF;AA4CA,mDAAmD,GACnD,OAAO,SAASY,eACdC,QAAiC,EACjCC,OAAmB;QAGFA,kBACFA,gBAGID;IALnB,IAAI,CAACA,YAAYA,SAASE,IAAI,KAAK,UAAU,OAAO;IACpD,MAAMC,UAAU,EAACF,mBAAAA,QAAQE,OAAO,YAAfF,mBAAmB,IAAIG,WAAW;IACnD,MAAMC,QAAQ,EAACJ,iBAAAA,QAAQI,KAAK,YAAbJ,iBAAiB,IAAIG,WAAW;IAC/C,IAAI,CAACD,SAAS,OAAO;IACrB,IAAIG,QAAwB;IAC5B,KAAK,MAAMd,SAAQQ,kBAAAA,SAASO,KAAK,YAAdP,kBAAkB,EAAE,CAAE;QACvC,IAAIR,KAAKW,OAAO,CAACC,WAAW,OAAOD,SAAS;QAC5C,IAAIX,KAAKa,KAAK,EAAE;YACd,IAAIb,KAAKa,KAAK,CAACD,WAAW,OAAOC,OAAO,OAAOb;YAC/C;QACF;QACAc,QAAQA,gBAAAA,QAASd;IACnB;IACA,OAAOc;AACT;AAEA;;;;CAIC,GACD,OAAO,SAAST,gBACdW,YAAoB,EACpBrB,GAAW,EACXsB,mBAAmB,KAAK;IAExB,IAAI,CAAEtB,CAAAA,MAAM,CAAA,KAAM,CAAEqB,CAAAA,eAAe,CAAA,GAAI,OAAO;IAC9C,IAAIC,kBAAkB;QACpB,OAAOC,KAAKC,KAAK,CAACH,eAAeA,eAAgB,CAAA,IAAIrB,MAAM,GAAE;IAC/D;IACA,OAAOuB,KAAKC,KAAK,CAAC,AAACH,eAAerB,MAAO;AAC3C"}
|
|
@@ -0,0 +1,551 @@
|
|
|
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
|
+
* Commerce catalog v1 (AGL-276): products with options/variants,
|
|
19
|
+
* hierarchical categories, tags, and manual/smart collections. Pure
|
|
20
|
+
* model + helpers — no I/O; the products hub and storefront APIs operate
|
|
21
|
+
* over these shapes. Documents live under `hosts/{hostId}/products`,
|
|
22
|
+
* `.../productCategories`, and `.../collections`; the legacy Commerce
|
|
23
|
+
* Starter product doc (AGL-90: name/priceUsd/inventory) lifts into this
|
|
24
|
+
* shape via `liftLegacyProduct`, so existing docs keep working.
|
|
25
|
+
*/
|
|
26
|
+
/** Product price ceiling (whole USD). */
|
|
27
|
+
export declare const COMMERCE_MAX_PRICE_USD = 10000;
|
|
28
|
+
export type ProductType = 'physical' | 'digital' | 'service';
|
|
29
|
+
export type ProductStatus = 'draft' | 'active' | 'archived';
|
|
30
|
+
/** One axis of variation, e.g. { name: 'Size', values: ['S','M','L'] }. */
|
|
31
|
+
export interface ProductOption {
|
|
32
|
+
name: string;
|
|
33
|
+
values: string[];
|
|
34
|
+
}
|
|
35
|
+
/** A sellable configuration of a product (every product has ≥ 1). */
|
|
36
|
+
export interface ProductVariant {
|
|
37
|
+
/** Stable id unique within the product (never reused after delete). */
|
|
38
|
+
id: string;
|
|
39
|
+
/** Option selections keyed by option name; {} for the default variant. */
|
|
40
|
+
options?: Record<string, string>;
|
|
41
|
+
sku?: string;
|
|
42
|
+
barcode?: string;
|
|
43
|
+
priceUsd: number;
|
|
44
|
+
/** Strike-through price; a sale badge shows when > priceUsd. */
|
|
45
|
+
compareAtPriceUsd?: number;
|
|
46
|
+
weightGrams?: number;
|
|
47
|
+
/** null/undefined = untracked; 0 = sold out (matches AGL-96). */
|
|
48
|
+
inventory?: number | null;
|
|
49
|
+
/**
|
|
50
|
+
* Per-location stock (AGL-286); `inventory` stays the summed
|
|
51
|
+
* denormalization. Absent = single default location.
|
|
52
|
+
*/
|
|
53
|
+
inventoryByLocation?: Record<string, number>;
|
|
54
|
+
/** Media-library image URL shown when this variant is selected. */
|
|
55
|
+
imageUrl?: string;
|
|
56
|
+
}
|
|
57
|
+
/** `hosts/{hostId}/locations/{id}` doc (AGL-286). */
|
|
58
|
+
export interface InventoryLocation {
|
|
59
|
+
name: string;
|
|
60
|
+
isDefault?: boolean;
|
|
61
|
+
address?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* `hosts/{hostId}/registers/{id}` doc (AGL-472): a named point-of-sale
|
|
65
|
+
* register. Creation is capped by the plan's `posRegisters` quota (Pro 1,
|
|
66
|
+
* Business 2, Advanced 5; raised by a per-org entitlement override for the
|
|
67
|
+
* $89/mo add-on), enforced server-side by the resources route. Each POS
|
|
68
|
+
* sale stamps its `registerId` so takings are attributable per register.
|
|
69
|
+
*/
|
|
70
|
+
export interface PosRegister {
|
|
71
|
+
name: string;
|
|
72
|
+
/** Optional default inventory location this register sells from. */
|
|
73
|
+
locationId?: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The register ids within the plan's `posRegisters` cap (AGL-482), ranked
|
|
77
|
+
* by creation order — the same ordering `pos-order.ts` enforces at sale
|
|
78
|
+
* time. Registers beyond the cap (e.g. after a Business→Pro downgrade) are
|
|
79
|
+
* excluded so the console/POS can dim or hide them instead of surfacing a
|
|
80
|
+
* checkout 403. `cap` of `Infinity` returns all.
|
|
81
|
+
*/
|
|
82
|
+
export declare function registersWithinCap(registers: Array<{
|
|
83
|
+
$id: string;
|
|
84
|
+
createdAt?: any;
|
|
85
|
+
}>, cap: number): Set<string>;
|
|
86
|
+
/**
|
|
87
|
+
* `hosts/{hostId}/suppliers/{id}` doc (AGL-289): where dropshipped
|
|
88
|
+
* order lines route on payment. Email and webhook are both optional but
|
|
89
|
+
* one must be set for routing to do anything; webhook payloads are
|
|
90
|
+
* HMAC-SHA256-signed with `webhookSecret`.
|
|
91
|
+
*/
|
|
92
|
+
export interface HostSupplier {
|
|
93
|
+
name: string;
|
|
94
|
+
email?: string;
|
|
95
|
+
webhookUrl?: string;
|
|
96
|
+
webhookSecret?: string;
|
|
97
|
+
}
|
|
98
|
+
/** `hosts/{hostId}/products/{id}` doc. */
|
|
99
|
+
export interface HostProduct {
|
|
100
|
+
name: string;
|
|
101
|
+
/** Host-unique URL segment for /products/{slug}. */
|
|
102
|
+
slug: string;
|
|
103
|
+
description?: string;
|
|
104
|
+
type: ProductType;
|
|
105
|
+
status: ProductStatus;
|
|
106
|
+
/** Ordered media-library image URLs (first = primary). */
|
|
107
|
+
mediaUrls?: string[];
|
|
108
|
+
categoryIds?: string[];
|
|
109
|
+
tags?: string[];
|
|
110
|
+
options?: ProductOption[];
|
|
111
|
+
variants: ProductVariant[];
|
|
112
|
+
/** Per-product overrides for PDP meta tags (AGL-299 consumes). */
|
|
113
|
+
seo?: {
|
|
114
|
+
title?: string;
|
|
115
|
+
description?: string;
|
|
116
|
+
imageUrl?: string;
|
|
117
|
+
};
|
|
118
|
+
/** Supplier for dropship routing (AGL-289). */
|
|
119
|
+
supplierId?: string;
|
|
120
|
+
/** Out-of-stock behavior (AGL-281): deny (default) or allow backorder. */
|
|
121
|
+
oversellPolicy?: 'deny' | 'backorder';
|
|
122
|
+
/** Never taxed regardless of tax settings (AGL-285). */
|
|
123
|
+
taxExempt?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Digital delivery (AGL-302): downloadable files for `digital`
|
|
126
|
+
* products. Buyers always download the CURRENT list, so uploading a
|
|
127
|
+
* new version re-delivers to everyone.
|
|
128
|
+
*/
|
|
129
|
+
digitalFiles?: Array<{
|
|
130
|
+
url: string;
|
|
131
|
+
fileName: string;
|
|
132
|
+
version?: string;
|
|
133
|
+
}>;
|
|
134
|
+
/** Max download attempts per order line; absent = unlimited. */
|
|
135
|
+
downloadLimit?: number;
|
|
136
|
+
/**
|
|
137
|
+
* Recurring billing (AGL-303): buyers subscribe instead of buying
|
|
138
|
+
* once; an active subscription is the entitlement content gating
|
|
139
|
+
* checks (AGL-309).
|
|
140
|
+
*/
|
|
141
|
+
subscription?: {
|
|
142
|
+
interval: 'month' | 'year';
|
|
143
|
+
trialDays?: number;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Buyer-chosen billing (AGL-545): with `subscription` set, true lets
|
|
147
|
+
* the buyer pick one-time OR subscribe on the PDP (default one-time);
|
|
148
|
+
* absent/false keeps the product subscription-only.
|
|
149
|
+
*/
|
|
150
|
+
subscriptionOptional?: boolean;
|
|
151
|
+
/** Members-only videos (AGL-315), streamed via short-TTL links. */
|
|
152
|
+
gatedVideos?: Array<{
|
|
153
|
+
url: string;
|
|
154
|
+
title?: string;
|
|
155
|
+
}>;
|
|
156
|
+
/** Manual related products for the upsell block (AGL-325). */
|
|
157
|
+
relatedProductIds?: string[];
|
|
158
|
+
/** Buying this issues a gift-card code for its price (AGL-322). */
|
|
159
|
+
giftCard?: boolean;
|
|
160
|
+
/** Tracked-total at/below this alerts host managers (AGL-281). */
|
|
161
|
+
lowStockThreshold?: number;
|
|
162
|
+
createdAtMs?: number;
|
|
163
|
+
updatedAtMs?: number;
|
|
164
|
+
deletedAt?: number | null;
|
|
165
|
+
/** Legacy Commerce Starter fields kept so old docs read back (AGL-90). */
|
|
166
|
+
priceUsd?: number;
|
|
167
|
+
inventory?: number | null;
|
|
168
|
+
imageUrl?: string;
|
|
169
|
+
}
|
|
170
|
+
/** `hosts/{hostId}/productCategories/{id}` doc (tree via parentId). */
|
|
171
|
+
export interface ProductCategory {
|
|
172
|
+
name: string;
|
|
173
|
+
slug: string;
|
|
174
|
+
parentId?: string | null;
|
|
175
|
+
order?: number;
|
|
176
|
+
}
|
|
177
|
+
export type CollectionRuleField = 'tag' | 'categoryId' | 'priceUsd' | 'name' | 'type';
|
|
178
|
+
export type CollectionRuleOp = 'eq' | 'neq' | 'lt' | 'gt' | 'contains';
|
|
179
|
+
export interface CollectionRule {
|
|
180
|
+
field: CollectionRuleField;
|
|
181
|
+
op: CollectionRuleOp;
|
|
182
|
+
value: string | number;
|
|
183
|
+
}
|
|
184
|
+
/** `hosts/{hostId}/collections/{id}` doc. */
|
|
185
|
+
export interface HostCollection {
|
|
186
|
+
name: string;
|
|
187
|
+
slug: string;
|
|
188
|
+
description?: string;
|
|
189
|
+
mode: 'manual' | 'smart';
|
|
190
|
+
/** Manual mode: explicit ordered membership. */
|
|
191
|
+
productIds?: string[];
|
|
192
|
+
/** Smart mode: rules evaluated over active products. */
|
|
193
|
+
rules?: CollectionRule[];
|
|
194
|
+
/** Smart mode: true = every rule must match (default), false = any. */
|
|
195
|
+
matchAll?: boolean;
|
|
196
|
+
/** Media-library image URL for the collection card/landing hero. */
|
|
197
|
+
imageUrl?: string;
|
|
198
|
+
order?: number;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Payment-provider seam (AGL-284): checkout/session creation goes
|
|
202
|
+
* through a provider id so PayPal (etc.) can slot in without reworking
|
|
203
|
+
* callers. Stripe is the only implementation today; store settings
|
|
204
|
+
* (AGL-295) will carry the selection when a second provider exists.
|
|
205
|
+
*/
|
|
206
|
+
export type PaymentProviderId = 'stripe';
|
|
207
|
+
export interface PaymentCheckoutRequest {
|
|
208
|
+
provider: PaymentProviderId;
|
|
209
|
+
hostId: string;
|
|
210
|
+
amountCents: number;
|
|
211
|
+
feeCents: number;
|
|
212
|
+
productName: string;
|
|
213
|
+
successUrl: string;
|
|
214
|
+
cancelUrl: string;
|
|
215
|
+
metadata?: Record<string, string>;
|
|
216
|
+
}
|
|
217
|
+
/** Variant ceiling per product (Shopify parity). */
|
|
218
|
+
export declare const COMMERCE_MAX_VARIANTS = 100;
|
|
219
|
+
export declare const COMMERCE_MAX_OPTIONS = 3;
|
|
220
|
+
export declare const COMMERCE_MAX_OPTION_VALUES = 25;
|
|
221
|
+
export declare const COMMERCE_SLUG_MAX_LENGTH = 80;
|
|
222
|
+
/** Lowercase-kebab slug from a product/category/collection name. */
|
|
223
|
+
export declare function commerceSlug(name: string): string;
|
|
224
|
+
/**
|
|
225
|
+
* The search keys a product write carries, so the catalog can be searched by
|
|
226
|
+
* the QUERY rather than by the rows a listener happened to fetch (AGL-2501).
|
|
227
|
+
*
|
|
228
|
+
* The hub lists `limit(500)`, and the search compared what that returned — so
|
|
229
|
+
* a product past the window answered "no products match", which reads as the
|
|
230
|
+
* product not existing rather than as the search not reaching it. Filtering
|
|
231
|
+
* server-side needs fields Firestore can index, and neither of the two things
|
|
232
|
+
* a merchant searches by is one:
|
|
233
|
+
*
|
|
234
|
+
* - A NAME needs case-insensitive contains, which Firestore has no operator
|
|
235
|
+
* for. `nameSearchFields` denormalizes it into the three shapes that are
|
|
236
|
+
* indexable — an exact key, word-prefix tokens for `array-contains`, and
|
|
237
|
+
* the key reversed so "ends with" becomes a prefix range.
|
|
238
|
+
* - A SKU lives inside `variants`, an array of OBJECTS, and Firestore cannot
|
|
239
|
+
* query a field inside one. Flattened here into a top-level array so a SKU
|
|
240
|
+
* is one `array-contains`.
|
|
241
|
+
*
|
|
242
|
+
* ⛔ A SKU therefore matches WHOLE, not as a substring: "abc-123" finds it and
|
|
243
|
+
* "123" does not. That is the right way round for a SKU, which is a value
|
|
244
|
+
* somebody copies rather than half-remembers — unlike a name, where the tokens
|
|
245
|
+
* above buy word-prefix matching precisely because names are half-remembered.
|
|
246
|
+
*
|
|
247
|
+
* `barcodes` is the same flattening for the same reason, and it is the one the
|
|
248
|
+
* register depends on: a keyboard-wedge scanner types the code and presses
|
|
249
|
+
* Enter, so the lookup has to be exact and has to reach the whole catalog. A
|
|
250
|
+
* scan is never a half-remembered value.
|
|
251
|
+
*
|
|
252
|
+
* Lower-cased because the translator lower-cases the typed query before it
|
|
253
|
+
* builds the `array-contains`; stored and typed have to be normalized the same
|
|
254
|
+
* way or the two silently disagree.
|
|
255
|
+
*
|
|
256
|
+
* ⚠️ Each array is OMITTED when a product has none, rather than written as
|
|
257
|
+
* `[]`. `isNotEmpty` is served as `!= null`, and an empty array is not null —
|
|
258
|
+
* so a product with no SKUs at all would answer "has a SKU" for every row.
|
|
259
|
+
*
|
|
260
|
+
* ⚠️ Spread this at EVERY write that sets a product's name or variants. A
|
|
261
|
+
* write that sets the name without it leaves the keys describing the previous
|
|
262
|
+
* name, and the product becomes findable only by what it used to be called.
|
|
263
|
+
*/
|
|
264
|
+
export declare function productSearchFields(product: {
|
|
265
|
+
name: string;
|
|
266
|
+
variants?: ProductVariant[];
|
|
267
|
+
}): {
|
|
268
|
+
name: string;
|
|
269
|
+
nameLower: string;
|
|
270
|
+
nameTokens: string[];
|
|
271
|
+
nameReversed: string;
|
|
272
|
+
skus?: string[];
|
|
273
|
+
barcodes?: string[];
|
|
274
|
+
};
|
|
275
|
+
/**
|
|
276
|
+
* Cartesian product of option values → the variant option combinations
|
|
277
|
+
* the products hub materializes into a variants matrix. Empty/absent
|
|
278
|
+
* options yield a single default combination ({}).
|
|
279
|
+
*/
|
|
280
|
+
export declare function expandVariantMatrix(options: ProductOption[] | undefined): Array<Record<string, string>>;
|
|
281
|
+
/**
|
|
282
|
+
* The option axes renamed, with every variant's selection carried to the new
|
|
283
|
+
* name in place (AGL-3066).
|
|
284
|
+
*
|
|
285
|
+
* A variant keeps its selections keyed by option NAME, so a rename has to move
|
|
286
|
+
* each key rather than rebuild the matrix: a rebuild matches variants by name
|
|
287
|
+
* and value, finds none under the new name, and replaces every variant with a
|
|
288
|
+
* new id holding the first variant's price and stock and no SKU, barcode,
|
|
289
|
+
* compare-at price or weight. Moving the key keeps the id every order line
|
|
290
|
+
* and stock movement refers to, and every field a person set.
|
|
291
|
+
*
|
|
292
|
+
* `names` holds one entry per option, in order; an entry that is not a string
|
|
293
|
+
* keeps that option's name. Each selection keeps its position among a
|
|
294
|
+
* variant's selections, because a variant is labeled by them in order.
|
|
295
|
+
*
|
|
296
|
+
* Two options may share a name for a moment while a person types. A variant
|
|
297
|
+
* cannot hold two selections under one name, so while the new names are not
|
|
298
|
+
* all different nothing is moved, and `validateProduct` refuses the product.
|
|
299
|
+
* The selection left under the old name is found again by its value once the
|
|
300
|
+
* names differ, so typing through a duplicate loses nothing.
|
|
301
|
+
*/
|
|
302
|
+
export declare function renameProductOptions(product: Pick<HostProduct, 'options' | 'variants'>, names: ReadonlyArray<string | null | undefined>): Pick<HostProduct, 'options' | 'variants'>;
|
|
303
|
+
/**
|
|
304
|
+
* Whether a variant has a price a sale can charge (AGL-2916).
|
|
305
|
+
*
|
|
306
|
+
* A product proposed by AI is created with every price left empty for the
|
|
307
|
+
* merchant to set, so a stored variant can lack one. `Number(undefined)` is
|
|
308
|
+
* no price, and neither is `null`, which `Number` reads as zero: a sale door
|
|
309
|
+
* that priced either would charge nothing, or fail at the processor.
|
|
310
|
+
*/
|
|
311
|
+
export declare function variantHasPrice(variant: object | null | undefined): boolean;
|
|
312
|
+
/** Whether any variant of a product still needs its price set (AGL-2916). */
|
|
313
|
+
export declare function productPriceMissing(product: {
|
|
314
|
+
variants?: readonly object[];
|
|
315
|
+
}): boolean;
|
|
316
|
+
/** Copy proposed for a product, by field (AGL-2916). A field left out is left alone. */
|
|
317
|
+
export interface ProductCopyValues {
|
|
318
|
+
description?: string;
|
|
319
|
+
tags?: string[];
|
|
320
|
+
categoryIds?: string[];
|
|
321
|
+
/** One name per option the product has, in order. */
|
|
322
|
+
optionNames?: string[];
|
|
323
|
+
seoTitle?: string;
|
|
324
|
+
seoDescription?: string;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* The fields proposed copy changes on a product (AGL-2916), in the shape the
|
|
328
|
+
* editor stores them: only the fields `values` names. Tags and categories are
|
|
329
|
+
* each kept once; the search listing keeps its share image; and option names
|
|
330
|
+
* rename the product's options through `renameProductOptions`, keeping every
|
|
331
|
+
* variant, only when they name each option once with a name of its own.
|
|
332
|
+
*/
|
|
333
|
+
export declare function productCopyPatch(product: Pick<HostProduct, 'options' | 'variants' | 'seo'>, values: ProductCopyValues): Partial<Pick<HostProduct, 'description' | 'tags' | 'categoryIds' | 'seo' | 'options' | 'variants'>>;
|
|
334
|
+
/** A product proposed for a store, before anyone has priced it (AGL-2916). */
|
|
335
|
+
export interface ProposedProduct {
|
|
336
|
+
name: string;
|
|
337
|
+
type: ProductType;
|
|
338
|
+
description: string;
|
|
339
|
+
tags: string[];
|
|
340
|
+
options: ProductOption[];
|
|
341
|
+
seoTitle: string;
|
|
342
|
+
seoDescription: string;
|
|
343
|
+
}
|
|
344
|
+
/** A new product whose variants carry no price yet. */
|
|
345
|
+
export type UnpricedProductDraft = Omit<HostProduct, 'variants'> & {
|
|
346
|
+
variants: Array<Omit<ProductVariant, 'priceUsd'>>;
|
|
347
|
+
};
|
|
348
|
+
/**
|
|
349
|
+
* The document a proposed product is created as (AGL-2916): a `draft`, under
|
|
350
|
+
* a slug no product in `takenSlugs` has, with one variant for each
|
|
351
|
+
* combination of its options and NO price on any of them. Prices are the
|
|
352
|
+
* merchant's to set: the editor refuses to save the product until every
|
|
353
|
+
* variant has one, and no sale door sells a variant without one
|
|
354
|
+
* (`variantHasPrice`). The search keys travel with the name, as on every
|
|
355
|
+
* create path.
|
|
356
|
+
*/
|
|
357
|
+
export declare function unpricedProductDraft(proposal: ProposedProduct, takenSlugs: ReadonlySet<string>, nowMs: number): UnpricedProductDraft;
|
|
358
|
+
/** Variant whose option selections match exactly; undefined if none. */
|
|
359
|
+
export declare function findVariant(product: Pick<HostProduct, 'variants'>, selections: Record<string, string>): ProductVariant | undefined;
|
|
360
|
+
/** [min, max] price across variants; [0, 0] when there are none. */
|
|
361
|
+
export declare function productPriceRange(product: Pick<HostProduct, 'variants'>): [number, number];
|
|
362
|
+
/** Sum of tracked inventory; null when every variant is untracked. */
|
|
363
|
+
export declare function productInventory(product: Pick<HostProduct, 'variants'>): number | null;
|
|
364
|
+
/**
|
|
365
|
+
* Reasons an inventory adjustment doc may carry (AGL-281).
|
|
366
|
+
*
|
|
367
|
+
* `cancellation` is the only one written automatically in the PLUS direction
|
|
368
|
+
* (AGL-1808): cancelling an order the transition rules prove was never
|
|
369
|
+
* fulfilled puts back exactly what the sale took. It is deliberately not
|
|
370
|
+
* `refund` — no money moved — and not `correction`, which is what a merchant
|
|
371
|
+
* picks when the count disagreed with the shelf for a reason nobody recorded.
|
|
372
|
+
* Kept out of the "Adjust stock" dialog's menu on purpose: a merchant reaching
|
|
373
|
+
* for it by hand means something else happened.
|
|
374
|
+
*/
|
|
375
|
+
export type InventoryAdjustmentReason = 'sale' | 'refund' | 'restock' | 'correction' | 'damage' | 'cancellation';
|
|
376
|
+
/** `hosts/{hostId}/inventoryAdjustments/{id}` doc. */
|
|
377
|
+
export interface InventoryAdjustment {
|
|
378
|
+
productId: string;
|
|
379
|
+
variantId: string;
|
|
380
|
+
/** Positive = stock added, negative = removed. */
|
|
381
|
+
delta: number;
|
|
382
|
+
/**
|
|
383
|
+
* What the count ACTUALLY moved by, when the floor in
|
|
384
|
+
* `adjustVariantInventory` absorbed part of `delta` (AGL-2149). Written only
|
|
385
|
+
* when the two differ, which for a sale means a backorder product that sold
|
|
386
|
+
* past zero: `delta` stays the units sold — that is the merchant's stock
|
|
387
|
+
* history and it must keep saying "3 went out the door" — while this says how
|
|
388
|
+
* many of them the count could give up.
|
|
389
|
+
*
|
|
390
|
+
* A REVERSAL MUST READ THIS, NOT `delta`. Restoring `delta` on a backorder
|
|
391
|
+
* sale that the floor swallowed invents inventory that never existed: 0 sells
|
|
392
|
+
* 3, the count stays 0, and a `+3` on cancellation leaves 3 units nobody has.
|
|
393
|
+
* Absent on every row written before AGL-2149 and on every row where nothing
|
|
394
|
+
* was clamped, so `appliedDelta ?? delta` is the reader.
|
|
395
|
+
*/
|
|
396
|
+
appliedDelta?: number;
|
|
397
|
+
reason: InventoryAdjustmentReason;
|
|
398
|
+
/** Order id for sale/refund adjustments. */
|
|
399
|
+
orderId?: string;
|
|
400
|
+
/** Location for multi-location stock (AGL-286); absent = default. */
|
|
401
|
+
locationId?: string;
|
|
402
|
+
atMs: number;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Whether `quantity` of a variant is purchasable (AGL-281): untracked
|
|
406
|
+
* stock always is; tracked stock honors the product's oversell policy.
|
|
407
|
+
*/
|
|
408
|
+
export declare function canPurchase(product: Pick<HostProduct, 'variants' | 'oversellPolicy'>, variantId: string | undefined, quantity?: number): boolean;
|
|
409
|
+
/**
|
|
410
|
+
* What the register has to SAY about a line it is about to sell (AGL-2357).
|
|
411
|
+
*
|
|
412
|
+
* ## The defect
|
|
413
|
+
*
|
|
414
|
+
* `pos-order.ts` contains no `canPurchase` call. Every storefront door gates on
|
|
415
|
+
* it; the register does not, so a merchant who set `oversellPolicy: 'deny'` in
|
|
416
|
+
* the product editor silently got `backorder` at the counter — the count floors
|
|
417
|
+
* at zero underneath and nothing anywhere says so.
|
|
418
|
+
*
|
|
419
|
+
* ## The decision, and why it is a shortfall and not a refusal
|
|
420
|
+
*
|
|
421
|
+
* Warn, never block. A till is the wrong place for a stale number to stop a
|
|
422
|
+
* real sale: the cashier is holding the goods, the physical shelf is the truth,
|
|
423
|
+
* and refusing loses a sale over data that is behind. But "deny" must at least
|
|
424
|
+
* SAY something. So this reports the shortfall and the caller sells anyway.
|
|
425
|
+
* Honouring the policy with a manager-level override is the post-launch shape
|
|
426
|
+
* (AGL-2372) and wants an audit trail this deliberately does not build.
|
|
427
|
+
*
|
|
428
|
+
* ## Why the test is `canPurchase`
|
|
429
|
+
*
|
|
430
|
+
* Exactly the gate the register was missing, and no wider. An untracked variant
|
|
431
|
+
* has no number to be short against, and a `backorder` product's merchant chose
|
|
432
|
+
* to sell past zero — warning them would be noise about a setting they set on
|
|
433
|
+
* purpose. So a shortfall is reported only where a purchase would have been
|
|
434
|
+
* refused anywhere else in the product.
|
|
435
|
+
*/
|
|
436
|
+
export interface StockShortfall {
|
|
437
|
+
productId: string;
|
|
438
|
+
variantId?: string;
|
|
439
|
+
/** Product name at the time of sale, for a message the cashier can read. */
|
|
440
|
+
name: string;
|
|
441
|
+
variantLabel?: string;
|
|
442
|
+
/** Units the cashier is ringing up. */
|
|
443
|
+
requested: number;
|
|
444
|
+
/** Units the count says are on the shelf; never negative. */
|
|
445
|
+
available: number;
|
|
446
|
+
}
|
|
447
|
+
export declare function stockShortfall(product: Pick<HostProduct, 'variants' | 'oversellPolicy'>, variantId: string | undefined, quantity?: number): {
|
|
448
|
+
available: number;
|
|
449
|
+
} | null;
|
|
450
|
+
/**
|
|
451
|
+
* Whether stock tracking MEANS anything on a product (AGL-1744).
|
|
452
|
+
*
|
|
453
|
+
* `canPurchase` above gates every checkout on stock, subscription sessions
|
|
454
|
+
* included, but nothing ever decrements for a subscription — not on the
|
|
455
|
+
* initial charge (the `commerce-subscription` webhook branch deliberately
|
|
456
|
+
* writes no order and touches no inventory, AGL-1732) and not on renewal
|
|
457
|
+
* (`invoice.payment_succeeded` is unhandled repo-wide, AGL-1743). So on a
|
|
458
|
+
* subscription-only product that gate is permanently satisfied: one unit of
|
|
459
|
+
* stock sells an unlimited number of subscriptions, and the count never
|
|
460
|
+
* moves however many boxes ship. The merchant set a number, the system
|
|
461
|
+
* checks it on every sale, and the number is never true.
|
|
462
|
+
*
|
|
463
|
+
* AGL-1750 resolved the half AGL-1744 had to leave open: every paid invoice
|
|
464
|
+
* of a PHYSICAL subscription now mints an order and decrements its variant's
|
|
465
|
+
* stock (the `invoice.paid` branch of the commerce webhook), opening cycle
|
|
466
|
+
* included. So the honest split is now three-way:
|
|
467
|
+
*
|
|
468
|
+
* - `subscriptionOptional` ("Both") products have a real one-time path —
|
|
469
|
+
* the cart only ever builds `mode: 'payment'` sessions, and buy-now with
|
|
470
|
+
* `billing: 'once'` records a plain order — and that path decrements
|
|
471
|
+
* honestly. Withdrawing stock tracking there would delete a working
|
|
472
|
+
* control and re-open the AGL-1711 oversell on the half that works.
|
|
473
|
+
* - a PHYSICAL subscription box consumes a unit every cycle, and since
|
|
474
|
+
* AGL-1750 the cycle's own order decrements it — the count moves as the
|
|
475
|
+
* boxes ship, so the number the merchant sets is kept true again.
|
|
476
|
+
* - a DIGITAL or SERVICE subscription-only product still has no
|
|
477
|
+
* decrementing path anywhere, so the field stays withdrawn there: one
|
|
478
|
+
* unit would still sell unlimited subscriptions.
|
|
479
|
+
*
|
|
480
|
+
* This says nothing about what `canPurchase` returns — that is the gate for
|
|
481
|
+
* every other purchase path and is deliberately untouched. This is a console
|
|
482
|
+
* predicate: it stops the editor inviting a merchant to set a number the
|
|
483
|
+
* system will never keep true.
|
|
484
|
+
*/
|
|
485
|
+
export declare function stockTrackingApplies(product: Pick<HostProduct, 'subscription' | 'subscriptionOptional' | 'type'>): boolean;
|
|
486
|
+
/** Buyer's requested billing mode on a checkout POST (AGL-545). */
|
|
487
|
+
export type CheckoutBillingChoice = 'once' | 'subscribe';
|
|
488
|
+
/**
|
|
489
|
+
* Resolves the Stripe Checkout mode for a product + the buyer's
|
|
490
|
+
* requested billing choice (AGL-545). The product doc is authoritative:
|
|
491
|
+
* - no `subscription` → always one-time (the request field is ignored)
|
|
492
|
+
* - `subscription` without `subscriptionOptional` → always subscription
|
|
493
|
+
* (a forged `billing: 'once'` cannot buy a subscription product once)
|
|
494
|
+
* - `subscriptionOptional` → the buyer chooses; absent/invalid choices
|
|
495
|
+
* default to one-time, matching the PDP default.
|
|
496
|
+
*/
|
|
497
|
+
export declare function resolveCheckoutBillingMode(product: Pick<HostProduct, 'subscription' | 'subscriptionOptional'>, requested?: string | null): 'payment' | 'subscription';
|
|
498
|
+
/**
|
|
499
|
+
* Applies a stock delta to one variant, flooring at zero (race-window
|
|
500
|
+
* sales can't drive the display negative), and returns the new variants
|
|
501
|
+
* array — callers persist it plus the `productInventory` denormalization.
|
|
502
|
+
* With `locationId`, the delta lands in that location's bucket and the
|
|
503
|
+
* flat `inventory` re-sums across locations (AGL-286).
|
|
504
|
+
*/
|
|
505
|
+
export declare function adjustVariantInventory(product: Pick<HostProduct, 'variants'>, variantId: string, delta: number, locationId?: string): ProductVariant[];
|
|
506
|
+
/**
|
|
507
|
+
* What `adjustVariantInventory` will ACTUALLY move the count by (AGL-2149).
|
|
508
|
+
*
|
|
509
|
+
* The floor in that helper is not a rounding detail, it is a silent absorber. A
|
|
510
|
+
* backorder product (`oversellPolicy: 'backorder'`, which `canPurchase` admits
|
|
511
|
+
* at any stock level) sitting at 0 sells 3: `Math.max(0, 0 + -3)` is 0, so the
|
|
512
|
+
* count does not move — correctly, since inventory is a shelf count and shelves
|
|
513
|
+
* do not go negative — but the ledger row said `-3` and every reversal read it
|
|
514
|
+
* as three units to put back. Cancelling that order handed the merchant 3 units
|
|
515
|
+
* that never existed and a stock badge that offers them for sale.
|
|
516
|
+
*
|
|
517
|
+
* Removing the floor is not the alternative: every reader of `inventory` — the
|
|
518
|
+
* badges, `canPurchase`, `productInventory`, `isLowStock` — assumes it cannot
|
|
519
|
+
* go negative, and a negative count would be a far wider change than the bug.
|
|
520
|
+
* So the clamp stays and the amount it absorbed is recorded instead.
|
|
521
|
+
*
|
|
522
|
+
* Deliberately mirrors `adjustVariantInventory`'s own arithmetic, including
|
|
523
|
+
* which field the clamp applies to in the location-tracked case, so the two
|
|
524
|
+
* cannot disagree about what happened.
|
|
525
|
+
*/
|
|
526
|
+
export declare function appliedVariantInventoryDelta(product: Pick<HostProduct, 'variants'>, variantId: string, delta: number, locationId?: string): number;
|
|
527
|
+
/**
|
|
528
|
+
* Moves stock between two locations of a tracked variant (AGL-286).
|
|
529
|
+
* Quantity clamps to what the source location holds; the flat total is
|
|
530
|
+
* unchanged by construction.
|
|
531
|
+
*/
|
|
532
|
+
export declare function transferVariantInventory(product: Pick<HostProduct, 'variants'>, variantId: string, fromLocationId: string, toLocationId: string, quantity: number): ProductVariant[];
|
|
533
|
+
/** True when tracked stock is at/below the product's alert threshold. */
|
|
534
|
+
export declare function isLowStock(product: Pick<HostProduct, 'variants' | 'lowStockThreshold'>): boolean;
|
|
535
|
+
/**
|
|
536
|
+
* Smart-collection membership: draft/archived/deleted products never
|
|
537
|
+
* match; manual collections answer from productIds.
|
|
538
|
+
*/
|
|
539
|
+
export declare function matchesCollection(product: HostProduct, collection: HostCollection, productId?: string): boolean;
|
|
540
|
+
/**
|
|
541
|
+
* Lifts a legacy Commerce Starter doc (AGL-90: flat name/priceUsd/
|
|
542
|
+
* inventory/imageUrl) into the catalog shape with a single default
|
|
543
|
+
* variant. Already-lifted docs pass through unchanged.
|
|
544
|
+
*/
|
|
545
|
+
export declare function liftLegacyProduct(raw: Partial<HostProduct> & {
|
|
546
|
+
name?: string;
|
|
547
|
+
}): HostProduct;
|
|
548
|
+
/** Actionable error, or null when the product is storable. */
|
|
549
|
+
export declare function validateProduct(product: HostProduct): string | null;
|
|
550
|
+
/** Actionable error, or null when the collection is storable. */
|
|
551
|
+
export declare function validateCollection(collection: HostCollection): string | null;
|