@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.
Files changed (417) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +10 -0
  3. package/package.json +57 -0
  4. package/src/index.d.ts +38 -0
  5. package/src/index.js +38 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/components/account.d.ts +31 -0
  8. package/src/lib/components/account.js +645 -0
  9. package/src/lib/components/account.js.map +1 -0
  10. package/src/lib/components/cart.d.ts +38 -0
  11. package/src/lib/components/cart.js +851 -0
  12. package/src/lib/components/cart.js.map +1 -0
  13. package/src/lib/components/commerce-console-page.d.ts +32 -0
  14. package/src/lib/components/commerce-console-page.js +296 -0
  15. package/src/lib/components/commerce-console-page.js.map +1 -0
  16. package/src/lib/components/commerce-console-sections.d.ts +34 -0
  17. package/src/lib/components/commerce-console-sections.js +62 -0
  18. package/src/lib/components/commerce-console-sections.js.map +1 -0
  19. package/src/lib/components/console/catalog-organization-card.component.d.ts +14 -0
  20. package/src/lib/components/console/catalog-organization-card.component.js +1087 -0
  21. package/src/lib/components/console/catalog-organization-card.component.js.map +1 -0
  22. package/src/lib/components/console/commerce-analytics-card.component.d.ts +27 -0
  23. package/src/lib/components/console/commerce-analytics-card.component.js +310 -0
  24. package/src/lib/components/console/commerce-analytics-card.component.js.map +1 -0
  25. package/src/lib/components/console/commerce-glance-card.component.d.ts +20 -0
  26. package/src/lib/components/console/commerce-glance-card.component.js +340 -0
  27. package/src/lib/components/console/commerce-glance-card.component.js.map +1 -0
  28. package/src/lib/components/console/commerce-stat-tile.component.d.ts +37 -0
  29. package/src/lib/components/console/commerce-stat-tile.component.js +72 -0
  30. package/src/lib/components/console/commerce-stat-tile.component.js.map +1 -0
  31. package/src/lib/components/console/discounts-card.component.d.ts +14 -0
  32. package/src/lib/components/console/discounts-card.component.js +443 -0
  33. package/src/lib/components/console/discounts-card.component.js.map +1 -0
  34. package/src/lib/components/console/entitlement-gate.component.d.ts +76 -0
  35. package/src/lib/components/console/entitlement-gate.component.js +115 -0
  36. package/src/lib/components/console/entitlement-gate.component.js.map +1 -0
  37. package/src/lib/components/console/gift-cards-card.component.d.ts +29 -0
  38. package/src/lib/components/console/gift-cards-card.component.js +379 -0
  39. package/src/lib/components/console/gift-cards-card.component.js.map +1 -0
  40. package/src/lib/components/console/host-coupons-card.component.d.ts +14 -0
  41. package/src/lib/components/console/host-coupons-card.component.js +252 -0
  42. package/src/lib/components/console/host-coupons-card.component.js.map +1 -0
  43. package/src/lib/components/console/host-orders-card.component.d.ts +13 -0
  44. package/src/lib/components/console/host-orders-card.component.js +861 -0
  45. package/src/lib/components/console/host-orders-card.component.js.map +1 -0
  46. package/src/lib/components/console/locations-card.component.d.ts +14 -0
  47. package/src/lib/components/console/locations-card.component.js +256 -0
  48. package/src/lib/components/console/locations-card.component.js.map +1 -0
  49. package/src/lib/components/console/member-posts-card.component.d.ts +8 -0
  50. package/src/lib/components/console/member-posts-card.component.js +283 -0
  51. package/src/lib/components/console/member-posts-card.component.js.map +1 -0
  52. package/src/lib/components/console/newest-site-users-card.component.d.ts +36 -0
  53. package/src/lib/components/console/newest-site-users-card.component.js +126 -0
  54. package/src/lib/components/console/newest-site-users-card.component.js.map +1 -0
  55. package/src/lib/components/console/order-detail-dialog.component.d.ts +28 -0
  56. package/src/lib/components/console/order-detail-dialog.component.js +976 -0
  57. package/src/lib/components/console/order-detail-dialog.component.js.map +1 -0
  58. package/src/lib/components/console/paid-media.d.ts +127 -0
  59. package/src/lib/components/console/paid-media.js +397 -0
  60. package/src/lib/components/console/paid-media.js.map +1 -0
  61. package/src/lib/components/console/payments-settings-card.component.d.ts +13 -0
  62. package/src/lib/components/console/payments-settings-card.component.js +295 -0
  63. package/src/lib/components/console/payments-settings-card.component.js.map +1 -0
  64. package/src/lib/components/console/pos-page.component.d.ts +13 -0
  65. package/src/lib/components/console/pos-page.component.js +916 -0
  66. package/src/lib/components/console/pos-page.component.js.map +1 -0
  67. package/src/lib/components/console/product-editor-dialog.component.d.ts +32 -0
  68. package/src/lib/components/console/product-editor-dialog.component.js +1374 -0
  69. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -0
  70. package/src/lib/components/console/products-hub-card.component.d.ts +16 -0
  71. package/src/lib/components/console/products-hub-card.component.js +1280 -0
  72. package/src/lib/components/console/products-hub-card.component.js.map +1 -0
  73. package/src/lib/components/console/products-hub-zone.component.d.ts +50 -0
  74. package/src/lib/components/console/products-hub-zone.component.js +200 -0
  75. package/src/lib/components/console/products-hub-zone.component.js.map +1 -0
  76. package/src/lib/components/console/recovery-queue-card.component.d.ts +39 -0
  77. package/src/lib/components/console/recovery-queue-card.component.js +262 -0
  78. package/src/lib/components/console/recovery-queue-card.component.js.map +1 -0
  79. package/src/lib/components/console/registers-card.component.d.ts +21 -0
  80. package/src/lib/components/console/registers-card.component.js +296 -0
  81. package/src/lib/components/console/registers-card.component.js.map +1 -0
  82. package/src/lib/components/console/reservations-card.component.d.ts +14 -0
  83. package/src/lib/components/console/reservations-card.component.js +650 -0
  84. package/src/lib/components/console/reservations-card.component.js.map +1 -0
  85. package/src/lib/components/console/reviews-moderation-card.component.d.ts +8 -0
  86. package/src/lib/components/console/reviews-moderation-card.component.js +235 -0
  87. package/src/lib/components/console/reviews-moderation-card.component.js.map +1 -0
  88. package/src/lib/components/console/shipping-settings-card.component.d.ts +38 -0
  89. package/src/lib/components/console/shipping-settings-card.component.js +560 -0
  90. package/src/lib/components/console/shipping-settings-card.component.js.map +1 -0
  91. package/src/lib/components/console/stock-movements-card.component.d.ts +31 -0
  92. package/src/lib/components/console/stock-movements-card.component.js +333 -0
  93. package/src/lib/components/console/stock-movements-card.component.js.map +1 -0
  94. package/src/lib/components/console/store-settings-card.component.d.ts +14 -0
  95. package/src/lib/components/console/store-settings-card.component.js +300 -0
  96. package/src/lib/components/console/store-settings-card.component.js.map +1 -0
  97. package/src/lib/components/console/storefront-tax-summary-card.component.d.ts +73 -0
  98. package/src/lib/components/console/storefront-tax-summary-card.component.js +408 -0
  99. package/src/lib/components/console/storefront-tax-summary-card.component.js.map +1 -0
  100. package/src/lib/components/console/suppliers-card.component.d.ts +8 -0
  101. package/src/lib/components/console/suppliers-card.component.js +328 -0
  102. package/src/lib/components/console/suppliers-card.component.js.map +1 -0
  103. package/src/lib/components/console/tax-settings-card.component.d.ts +14 -0
  104. package/src/lib/components/console/tax-settings-card.component.js +473 -0
  105. package/src/lib/components/console/tax-settings-card.component.js.map +1 -0
  106. package/src/lib/components/gate.d.ts +39 -0
  107. package/src/lib/components/gate.js +202 -0
  108. package/src/lib/components/gate.js.map +1 -0
  109. package/src/lib/components/gated-video.d.ts +40 -0
  110. package/src/lib/components/gated-video.js +366 -0
  111. package/src/lib/components/gated-video.js.map +1 -0
  112. package/src/lib/components/member-feed.d.ts +32 -0
  113. package/src/lib/components/member-feed.js +198 -0
  114. package/src/lib/components/member-feed.js.map +1 -0
  115. package/src/lib/components/member-recovery.d.ts +35 -0
  116. package/src/lib/components/member-recovery.js +313 -0
  117. package/src/lib/components/member-recovery.js.map +1 -0
  118. package/src/lib/components/member-signin.d.ts +35 -0
  119. package/src/lib/components/member-signin.js +257 -0
  120. package/src/lib/components/member-signin.js.map +1 -0
  121. package/src/lib/components/member-signup.d.ts +34 -0
  122. package/src/lib/components/member-signup.js +287 -0
  123. package/src/lib/components/member-signup.js.map +1 -0
  124. package/src/lib/components/newsletter-signup.d.ts +39 -0
  125. package/src/lib/components/newsletter-signup.js +229 -0
  126. package/src/lib/components/newsletter-signup.js.map +1 -0
  127. package/src/lib/components/product-detail.d.ts +38 -0
  128. package/src/lib/components/product-detail.js +1022 -0
  129. package/src/lib/components/product-detail.js.map +1 -0
  130. package/src/lib/components/product-grid.d.ts +67 -0
  131. package/src/lib/components/product-grid.js +909 -0
  132. package/src/lib/components/product-grid.js.map +1 -0
  133. package/src/lib/components/product-reviews.d.ts +32 -0
  134. package/src/lib/components/product-reviews.js +349 -0
  135. package/src/lib/components/product-reviews.js.map +1 -0
  136. package/src/lib/components/related-products.d.ts +33 -0
  137. package/src/lib/components/related-products.js +232 -0
  138. package/src/lib/components/related-products.js.map +1 -0
  139. package/src/lib/components/reservation-widget.d.ts +33 -0
  140. package/src/lib/components/reservation-widget.js +418 -0
  141. package/src/lib/components/reservation-widget.js.map +1 -0
  142. package/src/lib/components/storefront-payment-element-fallback.d.ts +18 -0
  143. package/src/lib/components/storefront-payment-element-fallback.js +51 -0
  144. package/src/lib/components/storefront-payment-element-fallback.js.map +1 -0
  145. package/src/lib/components/storefront-payment-element.d.ts +78 -0
  146. package/src/lib/components/storefront-payment-element.js +156 -0
  147. package/src/lib/components/storefront-payment-element.js.map +1 -0
  148. package/src/lib/components/wishlist.d.ts +46 -0
  149. package/src/lib/components/wishlist.js +304 -0
  150. package/src/lib/components/wishlist.js.map +1 -0
  151. package/src/lib/constants/bundle-common.d.ts +18 -0
  152. package/src/lib/constants/bundle-common.js +18 -0
  153. package/src/lib/constants/bundle-common.js.map +1 -0
  154. package/src/lib/constants/product-filters.d.ts +35 -0
  155. package/src/lib/constants/product-filters.js +109 -0
  156. package/src/lib/constants/product-filters.js.map +1 -0
  157. package/src/lib/model/commerce-cart.d.ts +52 -0
  158. package/src/lib/model/commerce-cart.js +102 -0
  159. package/src/lib/model/commerce-cart.js.map +1 -0
  160. package/src/lib/model/commerce-connect-transfer.d.ts +243 -0
  161. package/src/lib/model/commerce-connect-transfer.js +231 -0
  162. package/src/lib/model/commerce-connect-transfer.js.map +1 -0
  163. package/src/lib/model/commerce-discounts.d.ts +164 -0
  164. package/src/lib/model/commerce-discounts.js +231 -0
  165. package/src/lib/model/commerce-discounts.js.map +1 -0
  166. package/src/lib/model/commerce-dispute.d.ts +124 -0
  167. package/src/lib/model/commerce-dispute.js +225 -0
  168. package/src/lib/model/commerce-dispute.js.map +1 -0
  169. package/src/lib/model/commerce-gift-cards.d.ts +107 -0
  170. package/src/lib/model/commerce-gift-cards.js +121 -0
  171. package/src/lib/model/commerce-gift-cards.js.map +1 -0
  172. package/src/lib/model/commerce-io.d.ts +36 -0
  173. package/src/lib/model/commerce-io.js +245 -0
  174. package/src/lib/model/commerce-io.js.map +1 -0
  175. package/src/lib/model/commerce-orders.d.ts +1040 -0
  176. package/src/lib/model/commerce-orders.js +1022 -0
  177. package/src/lib/model/commerce-orders.js.map +1 -0
  178. package/src/lib/model/commerce-promotions.d.ts +188 -0
  179. package/src/lib/model/commerce-promotions.js +199 -0
  180. package/src/lib/model/commerce-promotions.js.map +1 -0
  181. package/src/lib/model/commerce-reservations.d.ts +175 -0
  182. package/src/lib/model/commerce-reservations.js +157 -0
  183. package/src/lib/model/commerce-reservations.js.map +1 -0
  184. package/src/lib/model/commerce-shipping.d.ts +316 -0
  185. package/src/lib/model/commerce-shipping.js +484 -0
  186. package/src/lib/model/commerce-shipping.js.map +1 -0
  187. package/src/lib/model/commerce-stock-holds.d.ts +199 -0
  188. package/src/lib/model/commerce-stock-holds.js +190 -0
  189. package/src/lib/model/commerce-stock-holds.js.map +1 -0
  190. package/src/lib/model/commerce-subscription-status.d.ts +67 -0
  191. package/src/lib/model/commerce-subscription-status.js +76 -0
  192. package/src/lib/model/commerce-subscription-status.js.map +1 -0
  193. package/src/lib/model/commerce-tax-decision.d.ts +222 -0
  194. package/src/lib/model/commerce-tax-decision.js +165 -0
  195. package/src/lib/model/commerce-tax-decision.js.map +1 -0
  196. package/src/lib/model/commerce-tax.d.ts +176 -0
  197. package/src/lib/model/commerce-tax.js +92 -0
  198. package/src/lib/model/commerce-tax.js.map +1 -0
  199. package/src/lib/model/commerce.d.ts +551 -0
  200. package/src/lib/model/commerce.js +739 -0
  201. package/src/lib/model/commerce.js.map +1 -0
  202. package/src/lib/model/index.d.ts +40 -0
  203. package/src/lib/model/index.js +40 -0
  204. package/src/lib/model/index.js.map +1 -0
  205. package/src/lib/model/order-figures.d.ts +48 -0
  206. package/src/lib/model/order-figures.js +74 -0
  207. package/src/lib/model/order-figures.js.map +1 -0
  208. package/src/lib/model/plugin-permissions.d.ts +23 -0
  209. package/src/lib/model/plugin-permissions.js +34 -0
  210. package/src/lib/model/plugin-permissions.js.map +1 -0
  211. package/src/lib/model/purchase-analytics.d.ts +186 -0
  212. package/src/lib/model/purchase-analytics.js +216 -0
  213. package/src/lib/model/purchase-analytics.js.map +1 -0
  214. package/src/lib/plugin-config.d.ts +62 -0
  215. package/src/lib/plugin-config.js +78 -0
  216. package/src/lib/plugin-config.js.map +1 -0
  217. package/src/lib/plugin.d.ts +28 -0
  218. package/src/lib/plugin.js +147 -0
  219. package/src/lib/plugin.js.map +1 -0
  220. package/src/lib/server/billing-webhook.d.ts +26 -0
  221. package/src/lib/server/billing-webhook.js +4011 -0
  222. package/src/lib/server/billing-webhook.js.map +1 -0
  223. package/src/lib/server/cancel-order.d.ts +87 -0
  224. package/src/lib/server/cancel-order.js +368 -0
  225. package/src/lib/server/cancel-order.js.map +1 -0
  226. package/src/lib/server/cart-checkout.d.ts +25 -0
  227. package/src/lib/server/cart-checkout.js +976 -0
  228. package/src/lib/server/cart-checkout.js.map +1 -0
  229. package/src/lib/server/cart-cookie.d.ts +32 -0
  230. package/src/lib/server/cart-cookie.js +77 -0
  231. package/src/lib/server/cart-cookie.js.map +1 -0
  232. package/src/lib/server/cart.d.ts +34 -0
  233. package/src/lib/server/cart.js +181 -0
  234. package/src/lib/server/cart.js.map +1 -0
  235. package/src/lib/server/catalog.d.ts +127 -0
  236. package/src/lib/server/catalog.js +277 -0
  237. package/src/lib/server/catalog.js.map +1 -0
  238. package/src/lib/server/checkout.d.ts +36 -0
  239. package/src/lib/server/checkout.js +915 -0
  240. package/src/lib/server/checkout.js.map +1 -0
  241. package/src/lib/server/connect.d.ts +26 -0
  242. package/src/lib/server/connect.js +238 -0
  243. package/src/lib/server/connect.js.map +1 -0
  244. package/src/lib/server/contact-refund.d.ts +117 -0
  245. package/src/lib/server/contact-refund.js +196 -0
  246. package/src/lib/server/contact-refund.js.map +1 -0
  247. package/src/lib/server/download.d.ts +39 -0
  248. package/src/lib/server/download.js +206 -0
  249. package/src/lib/server/download.js.map +1 -0
  250. package/src/lib/server/draft-order.d.ts +26 -0
  251. package/src/lib/server/draft-order.js +706 -0
  252. package/src/lib/server/draft-order.js.map +1 -0
  253. package/src/lib/server/feed.d.ts +24 -0
  254. package/src/lib/server/feed.js +59 -0
  255. package/src/lib/server/feed.js.map +1 -0
  256. package/src/lib/server/fulfill-order.d.ts +97 -0
  257. package/src/lib/server/fulfill-order.js +235 -0
  258. package/src/lib/server/fulfill-order.js.map +1 -0
  259. package/src/lib/server/gate.d.ts +36 -0
  260. package/src/lib/server/gate.js +112 -0
  261. package/src/lib/server/gate.js.map +1 -0
  262. package/src/lib/server/gift-cards.d.ts +42 -0
  263. package/src/lib/server/gift-cards.js +219 -0
  264. package/src/lib/server/gift-cards.js.map +1 -0
  265. package/src/lib/server/low-stock.d.ts +49 -0
  266. package/src/lib/server/low-stock.js +60 -0
  267. package/src/lib/server/low-stock.js.map +1 -0
  268. package/src/lib/server/manual-tax-rate.d.ts +82 -0
  269. package/src/lib/server/manual-tax-rate.js +113 -0
  270. package/src/lib/server/manual-tax-rate.js.map +1 -0
  271. package/src/lib/server/member-feed.d.ts +24 -0
  272. package/src/lib/server/member-feed.js +72 -0
  273. package/src/lib/server/member-feed.js.map +1 -0
  274. package/src/lib/server/member-name-search.d.ts +37 -0
  275. package/src/lib/server/member-name-search.js +42 -0
  276. package/src/lib/server/member-name-search.js.map +1 -0
  277. package/src/lib/server/member-post.d.ts +23 -0
  278. package/src/lib/server/member-post.js +166 -0
  279. package/src/lib/server/member-post.js.map +1 -0
  280. package/src/lib/server/membership-account.d.ts +37 -0
  281. package/src/lib/server/membership-account.js +148 -0
  282. package/src/lib/server/membership-account.js.map +1 -0
  283. package/src/lib/server/membership-admin-password.d.ts +33 -0
  284. package/src/lib/server/membership-admin-password.js +202 -0
  285. package/src/lib/server/membership-admin-password.js.map +1 -0
  286. package/src/lib/server/membership-content.d.ts +23 -0
  287. package/src/lib/server/membership-content.js +105 -0
  288. package/src/lib/server/membership-content.js.map +1 -0
  289. package/src/lib/server/membership-login.d.ts +19 -0
  290. package/src/lib/server/membership-login.js +137 -0
  291. package/src/lib/server/membership-login.js.map +1 -0
  292. package/src/lib/server/membership-logout.d.ts +19 -0
  293. package/src/lib/server/membership-logout.js +35 -0
  294. package/src/lib/server/membership-logout.js.map +1 -0
  295. package/src/lib/server/membership-recover.d.ts +60 -0
  296. package/src/lib/server/membership-recover.js +244 -0
  297. package/src/lib/server/membership-recover.js.map +1 -0
  298. package/src/lib/server/membership-register.d.ts +22 -0
  299. package/src/lib/server/membership-register.js +241 -0
  300. package/src/lib/server/membership-register.js.map +1 -0
  301. package/src/lib/server/membership-reset.d.ts +26 -0
  302. package/src/lib/server/membership-reset.js +88 -0
  303. package/src/lib/server/membership-reset.js.map +1 -0
  304. package/src/lib/server/membership-wishlist.d.ts +23 -0
  305. package/src/lib/server/membership-wishlist.js +89 -0
  306. package/src/lib/server/membership-wishlist.js.map +1 -0
  307. package/src/lib/server/membership.d.ts +96 -0
  308. package/src/lib/server/membership.js +222 -0
  309. package/src/lib/server/membership.js.map +1 -0
  310. package/src/lib/server/native-checkout.d.ts +170 -0
  311. package/src/lib/server/native-checkout.js +193 -0
  312. package/src/lib/server/native-checkout.js.map +1 -0
  313. package/src/lib/server/newsletter.d.ts +23 -0
  314. package/src/lib/server/newsletter.js +323 -0
  315. package/src/lib/server/newsletter.js.map +1 -0
  316. package/src/lib/server/notify-restock.d.ts +22 -0
  317. package/src/lib/server/notify-restock.js +84 -0
  318. package/src/lib/server/notify-restock.js.map +1 -0
  319. package/src/lib/server/order-analytics.d.ts +134 -0
  320. package/src/lib/server/order-analytics.js +263 -0
  321. package/src/lib/server/order-analytics.js.map +1 -0
  322. package/src/lib/server/order-figures.d.ts +33 -0
  323. package/src/lib/server/order-figures.js +220 -0
  324. package/src/lib/server/order-figures.js.map +1 -0
  325. package/src/lib/server/paid-media-delivery.d.ts +173 -0
  326. package/src/lib/server/paid-media-delivery.js +212 -0
  327. package/src/lib/server/paid-media-delivery.js.map +1 -0
  328. package/src/lib/server/pos-order.d.ts +54 -0
  329. package/src/lib/server/pos-order.js +1137 -0
  330. package/src/lib/server/pos-order.js.map +1 -0
  331. package/src/lib/server/process-abandoned.d.ts +54 -0
  332. package/src/lib/server/process-abandoned.js +222 -0
  333. package/src/lib/server/process-abandoned.js.map +1 -0
  334. package/src/lib/server/process-restock.d.ts +42 -0
  335. package/src/lib/server/process-restock.js +219 -0
  336. package/src/lib/server/process-restock.js.map +1 -0
  337. package/src/lib/server/product-card.d.ts +29 -0
  338. package/src/lib/server/product-card.js +54 -0
  339. package/src/lib/server/product-card.js.map +1 -0
  340. package/src/lib/server/product.d.ts +70 -0
  341. package/src/lib/server/product.js +105 -0
  342. package/src/lib/server/product.js.map +1 -0
  343. package/src/lib/server/promotion-hold.d.ts +144 -0
  344. package/src/lib/server/promotion-hold.js +174 -0
  345. package/src/lib/server/promotion-hold.js.map +1 -0
  346. package/src/lib/server/reconcile-stock.d.ts +106 -0
  347. package/src/lib/server/reconcile-stock.js +349 -0
  348. package/src/lib/server/reconcile-stock.js.map +1 -0
  349. package/src/lib/server/refund.d.ts +45 -0
  350. package/src/lib/server/refund.js +607 -0
  351. package/src/lib/server/refund.js.map +1 -0
  352. package/src/lib/server/related.d.ts +24 -0
  353. package/src/lib/server/related.js +104 -0
  354. package/src/lib/server/related.js.map +1 -0
  355. package/src/lib/server/reservation-availability.d.ts +23 -0
  356. package/src/lib/server/reservation-availability.js +111 -0
  357. package/src/lib/server/reservation-availability.js.map +1 -0
  358. package/src/lib/server/reserve-stock.d.ts +156 -0
  359. package/src/lib/server/reserve-stock.js +146 -0
  360. package/src/lib/server/reserve-stock.js.map +1 -0
  361. package/src/lib/server/reserve.d.ts +25 -0
  362. package/src/lib/server/reserve.js +426 -0
  363. package/src/lib/server/reserve.js.map +1 -0
  364. package/src/lib/server/restock-flag.d.ts +202 -0
  365. package/src/lib/server/restock-flag.js +449 -0
  366. package/src/lib/server/restock-flag.js.map +1 -0
  367. package/src/lib/server/reviews.d.ts +51 -0
  368. package/src/lib/server/reviews.js +132 -0
  369. package/src/lib/server/reviews.js.map +1 -0
  370. package/src/lib/server/site-page-enricher.d.ts +42 -0
  371. package/src/lib/server/site-page-enricher.js +149 -0
  372. package/src/lib/server/site-page-enricher.js.map +1 -0
  373. package/src/lib/server/site-page-resolver.d.ts +26 -0
  374. package/src/lib/server/site-page-resolver.js +223 -0
  375. package/src/lib/server/site-page-resolver.js.map +1 -0
  376. package/src/lib/server/stock-hold.d.ts +127 -0
  377. package/src/lib/server/stock-hold.js +258 -0
  378. package/src/lib/server/stock-hold.js.map +1 -0
  379. package/src/lib/server/storefront-tax-record.d.ts +22 -0
  380. package/src/lib/server/storefront-tax-record.js +218 -0
  381. package/src/lib/server/storefront-tax-record.js.map +1 -0
  382. package/src/lib/server/storefront-tax.d.ts +197 -0
  383. package/src/lib/server/storefront-tax.js +245 -0
  384. package/src/lib/server/storefront-tax.js.map +1 -0
  385. package/src/lib/server/stream.d.ts +25 -0
  386. package/src/lib/server/stream.js +191 -0
  387. package/src/lib/server/stream.js.map +1 -0
  388. package/src/lib/server/subscription-portal.d.ts +24 -0
  389. package/src/lib/server/subscription-portal.js +91 -0
  390. package/src/lib/server/subscription-portal.js.map +1 -0
  391. package/src/lib/server/supplier-outbox.d.ts +190 -0
  392. package/src/lib/server/supplier-outbox.js +342 -0
  393. package/src/lib/server/supplier-outbox.js.map +1 -0
  394. package/src/lib/server/supplier-update.d.ts +23 -0
  395. package/src/lib/server/supplier-update.js +289 -0
  396. package/src/lib/server/supplier-update.js.map +1 -0
  397. package/src/lib/server/tax-profile.d.ts +29 -0
  398. package/src/lib/server/tax-profile.js +40 -0
  399. package/src/lib/server/tax-profile.js.map +1 -0
  400. package/src/lib/server.d.ts +32 -0
  401. package/src/lib/server.js +311 -0
  402. package/src/lib/server.js.map +1 -0
  403. package/src/lib/site.d.ts +27 -0
  404. package/src/lib/site.js +134 -0
  405. package/src/lib/site.js.map +1 -0
  406. package/src/lib/utils/escape-html.d.ts +41 -0
  407. package/src/lib/utils/escape-html.js +41 -0
  408. package/src/lib/utils/escape-html.js.map +1 -0
  409. package/src/lib/utils/generate-preset-id.d.ts +19 -0
  410. package/src/lib/utils/generate-preset-id.js +25 -0
  411. package/src/lib/utils/generate-preset-id.js.map +1 -0
  412. package/src/lib/utils/member-continue.d.ts +45 -0
  413. package/src/lib/utils/member-continue.js +49 -0
  414. package/src/lib/utils/member-continue.js.map +1 -0
  415. package/src/lib/utils/use-storefront-purchase-event.d.ts +60 -0
  416. package/src/lib/utils/use-storefront-purchase-event.js +142 -0
  417. package/src/lib/utils/use-storefront-purchase-event.js.map +1 -0
@@ -0,0 +1,231 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ /**
18
+ * Discounts engine v2 (AGL-305): code-based AND automatic promotions
19
+ * with scoping, schedules, and usage limits, superseding the AGL-96
20
+ * percent-only coupons (which keep working through the legacy path).
21
+ * One resolver serves cart, checkout, and POS. Docs live at
22
+ * `hosts/{hostId}/discounts`. Pure — callers own I/O and redemption
23
+ * increments.
24
+ */ import { PROMOTION_EXHAUSTED_MESSAGE, promotionExhausted } from "./commerce-promotions.js";
25
+ /**
26
+ * The document a proposed discount is created as (AGL-2916): switched OFF,
27
+ * with no redemptions, its code in the shape the discounts card stores, and
28
+ * only the value its kind reads. A person switches it on from the discounts
29
+ * card. `null` for a proposal no discount can be made from: a percentage
30
+ * outside 1 to 100, or an amount off of nothing.
31
+ */ export function switchedOffDiscount(proposal) {
32
+ var _proposal_code, _proposal_minSubtotalCents;
33
+ const code = ((_proposal_code = proposal.code) != null ? _proposal_code : '').trim().toUpperCase().replace(/[^A-Z0-9_-]/g, '');
34
+ const minimum = Math.round(Number((_proposal_minSubtotalCents = proposal.minSubtotalCents) != null ? _proposal_minSubtotalCents : 0));
35
+ const base = _extends({
36
+ name: proposal.name.trim().slice(0, 80),
37
+ code: code || null,
38
+ kind: proposal.kind
39
+ }, minimum > 0 ? {
40
+ minSubtotalCents: minimum
41
+ } : {}, {
42
+ enabled: false,
43
+ redemptions: 0
44
+ });
45
+ if (proposal.kind === 'percent') {
46
+ const pct = Math.round(Number(proposal.valuePct));
47
+ return pct >= 1 && pct <= 100 ? _extends({}, base, {
48
+ valuePct: pct
49
+ }) : null;
50
+ }
51
+ if (proposal.kind === 'fixed') {
52
+ const cents = Math.round(Number(proposal.valueCents));
53
+ return cents > 0 ? _extends({}, base, {
54
+ valueCents: cents
55
+ }) : null;
56
+ }
57
+ return proposal.kind === 'free_shipping' ? base : null;
58
+ }
59
+ function applies(discount, context) {
60
+ var _context_nowMs;
61
+ var _discount_productIds;
62
+ const now = (_context_nowMs = context.nowMs) != null ? _context_nowMs : Date.now();
63
+ if (discount.enabled === false) return 'This discount is disabled';
64
+ if (discount.startAtMs != null && now < discount.startAtMs) {
65
+ return 'This discount has not started yet';
66
+ }
67
+ if (discount.endAtMs != null && now > discount.endAtMs) {
68
+ return 'This discount has expired';
69
+ }
70
+ // Holds count (AGL-2453). This read used to be `redemptions` alone, which is
71
+ // a figure that only moves once the webhook lands — minutes after this
72
+ // question is asked and answered. Every shopper who reached checkout while
73
+ // the counter sat one below the cap passed, so the cap bounded nothing but
74
+ // the paperwork. `promotionExhausted` counts the slots currently held by live
75
+ // checkouts as taken, which is the same question the in-transaction re-read
76
+ // asks below in `promotion-hold.ts` — deliberately the same function, so the
77
+ // pre-filter and the enforcement cannot drift.
78
+ if (promotionExhausted(discount, now)) {
79
+ return PROMOTION_EXHAUSTED_MESSAGE;
80
+ }
81
+ if (discount.minSubtotalCents != null && context.subtotalCents < discount.minSubtotalCents) {
82
+ return `Spend $${(discount.minSubtotalCents / 100).toFixed(2)} to use this`;
83
+ }
84
+ if (((_discount_productIds = discount.productIds) == null ? void 0 : _discount_productIds.length) && !context.productIds.some((id)=>discount.productIds.includes(id))) {
85
+ return 'This discount does not apply to your items';
86
+ }
87
+ return null;
88
+ }
89
+ /**
90
+ * The single derivation of what one discount is worth against one subtotal.
91
+ *
92
+ * Exhaustive over {@link DiscountKind} by construction: the `never` binding
93
+ * below fails the BUILD when a kind is added to the union and not handled
94
+ * here, so the next `free_shipping` cannot reach production as a silent zero.
95
+ * The runtime arm underneath it is not redundant — Firestore documents are not
96
+ * typechecked, and a `kind` written by a newer build than the one reading it
97
+ * arrives as an ordinary unrecognised string.
98
+ */ export function discountBenefit(discount, subtotalCents, lines) {
99
+ const kind = discount.kind;
100
+ if (kind === 'percent' || kind === 'fixed') {
101
+ var _discount_valuePct, _discount_valueCents;
102
+ // WHAT A SCOPE IS WORTH.
103
+ //
104
+ // `applies` already refuses a cart containing NONE of the scoped products,
105
+ // so the scope was never entirely dead — but the amount was still computed
106
+ // against the whole subtotal. A discount scoped to three products
107
+ // therefore discounted the entire basket the moment one of the three was
108
+ // in it: the merchant chose a scope, we charged as though they had not,
109
+ // and the margin went with it.
110
+ //
111
+ // A scoped discount with no line detail REFUSES rather than falling back
112
+ // to the whole subtotal. The fallback is the defect restated, and it would
113
+ // be a second pricing path for one feature split by what the caller
114
+ // happened to pass.
115
+ const scope = discount.productIds;
116
+ let base = subtotalCents;
117
+ if (scope == null ? void 0 : scope.length) {
118
+ if (!lines) {
119
+ return {
120
+ kind: 'none',
121
+ reason: 'this discount covers only some products, and the cart did not ' + 'say what each item costs'
122
+ };
123
+ }
124
+ base = lines.filter((line)=>scope.includes(line.productId)).reduce((sum, line)=>{
125
+ var _line_amountCents;
126
+ return sum + Math.max(0, Math.round(Number((_line_amountCents = line.amountCents) != null ? _line_amountCents : 0)));
127
+ }, 0);
128
+ }
129
+ const centsOff = kind === 'percent' ? Math.round(base * Math.min(100, Math.max(0, (_discount_valuePct = discount.valuePct) != null ? _discount_valuePct : 0)) / 100) : Math.min(base, Math.max(0, (_discount_valueCents = discount.valueCents) != null ? _discount_valueCents : 0));
130
+ // A discount configured to take nothing off — 0%, or a zero amount — is
131
+ // worth nothing, and saying so is what stops it being applied as a
132
+ // successful reduction of zero.
133
+ return centsOff > 0 ? {
134
+ kind: 'amount',
135
+ centsOff
136
+ } : {
137
+ kind: 'none',
138
+ reason: 'this discount takes nothing off the items in the cart'
139
+ };
140
+ }
141
+ if (kind === 'free_shipping') return {
142
+ kind: 'free-shipping'
143
+ };
144
+ // Unreachable while `DiscountKind` is fully handled above; the annotation is
145
+ // what makes adding a kind a compile error rather than a quiet no-op.
146
+ const unhandled = kind;
147
+ return {
148
+ kind: 'none',
149
+ reason: `this store has a discount of a kind this site cannot apply (${String(unhandled)})`
150
+ };
151
+ }
152
+ /**
153
+ * Best applicable discount: an entered code wins when valid (its
154
+ * failure reason is surfaced); otherwise the largest automatic
155
+ * promotion applies. Discounts never stack — Squarespace/Shopify
156
+ * baseline semantics.
157
+ */ export function resolveDiscount(discounts, context) {
158
+ var _context_code;
159
+ const entered = (_context_code = context.code) == null ? void 0 : _context_code.trim().toUpperCase();
160
+ if (entered) {
161
+ const coded = discounts.find((discount)=>{
162
+ var _discount_code;
163
+ return ((_discount_code = discount.code) == null ? void 0 : _discount_code.toUpperCase()) === entered;
164
+ });
165
+ if (!coded) return null;
166
+ const problem = applies(coded, context);
167
+ if (problem) {
168
+ return {
169
+ discount: coded,
170
+ discountId: coded.$id,
171
+ discountCents: 0,
172
+ freeShipping: false,
173
+ benefit: {
174
+ kind: 'none',
175
+ reason: problem
176
+ },
177
+ codeProblem: problem
178
+ };
179
+ }
180
+ const benefit = discountBenefit(coded, context.subtotalCents, context.lines);
181
+ // A code the shopper TYPED that turns out to be worth nothing is reported
182
+ // as a code problem, so it leaves through the caller's existing refusal
183
+ // rather than as a successful discount of zero. This is the free-shipping
184
+ // defect's actual exit: the caller's apply-block tests `discountCents > 0`
185
+ // and its invalid-code branch only fires when nothing resolved, so a
186
+ // benefit of `none` used to satisfy neither and the shopper was charged in
187
+ // full without a word.
188
+ if (benefit.kind === 'none') {
189
+ return {
190
+ discount: coded,
191
+ discountId: coded.$id,
192
+ discountCents: 0,
193
+ freeShipping: false,
194
+ benefit,
195
+ codeProblem: benefit.reason
196
+ };
197
+ }
198
+ return {
199
+ discount: coded,
200
+ discountId: coded.$id,
201
+ discountCents: benefit.kind === 'amount' ? benefit.centsOff : 0,
202
+ freeShipping: benefit.kind === 'free-shipping',
203
+ benefit
204
+ };
205
+ }
206
+ let best = null;
207
+ for (const discount of discounts){
208
+ if (discount.code) continue;
209
+ if (applies(discount, context)) continue;
210
+ const benefit = discountBenefit(discount, context.subtotalCents, context.lines);
211
+ // An automatic promotion worth nothing is passed over rather than reported:
212
+ // nobody asked for it, so there is no shopper to answer and a better one
213
+ // may still be in the list. An entered CODE is the opposite case and
214
+ // refuses above — the shopper made a request and is owed the reason.
215
+ if (benefit.kind === 'none') continue;
216
+ const cents = benefit.kind === 'amount' ? benefit.centsOff : 0;
217
+ const candidate = {
218
+ discount,
219
+ discountId: discount.$id,
220
+ discountCents: cents,
221
+ freeShipping: benefit.kind === 'free-shipping',
222
+ benefit
223
+ };
224
+ if (!best || cents > best.discountCents || candidate.freeShipping && !best.freeShipping && cents === best.discountCents) {
225
+ best = candidate;
226
+ }
227
+ }
228
+ return best;
229
+ }
230
+
231
+ //# sourceMappingURL=commerce-discounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/model/commerce-discounts.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 * Discounts engine v2 (AGL-305): code-based AND automatic promotions\n * with scoping, schedules, and usage limits, superseding the AGL-96\n * percent-only coupons (which keep working through the legacy path).\n * One resolver serves cart, checkout, and POS. Docs live at\n * `hosts/{hostId}/discounts`. Pure — callers own I/O and redemption\n * increments.\n */\n\nimport {\n PROMOTION_EXHAUSTED_MESSAGE,\n type PromotionHold,\n promotionExhausted,\n} from './commerce-promotions'\n\nexport type DiscountKind = 'percent' | 'fixed' | 'free_shipping'\n\n/** `hosts/{hostId}/discounts/{id}` doc. */\nexport interface HostDiscount {\n /** Uppercase entry code; absent = automatic (applies to every cart). */\n code?: string\n /** Display name for automatic promotions (\"Summer sale\"). */\n name?: string\n kind: DiscountKind\n /** percent kind: 1-100. */\n valuePct?: number\n /** fixed kind: cents off the items subtotal. */\n valueCents?: number\n /** Only carts at/above this subtotal qualify. */\n minSubtotalCents?: number\n /** Scope: at least one cart line must be one of these products. */\n productIds?: string[]\n maxRedemptions?: number\n redemptions?: number\n /**\n * In-flight claims on the remaining slots (AGL-2453), keyed by checkout\n * attempt. Counted as redeemed by {@link applies} for as long as they stand,\n * which is what stops N concurrent checkouts all passing a cap of one.\n */\n holds?: Record<string, PromotionHold>\n startAtMs?: number\n endAtMs?: number\n enabled?: boolean\n}\n\n/** A discount proposed for a store, before anyone has switched it on (AGL-2916). */\nexport interface ProposedDiscount {\n name: string\n /** The code a shopper types, or `null` for a discount that applies on its own. */\n code: string | null\n kind: DiscountKind\n valuePct: number | null\n valueCents: number | null\n minSubtotalCents: number | null\n}\n\n/** A stored discount as the discounts card writes one: an automatic discount's code is `null`. */\nexport type StoredDiscount = Omit<HostDiscount, 'code'> & { code: string | null }\n\n/**\n * The document a proposed discount is created as (AGL-2916): switched OFF,\n * with no redemptions, its code in the shape the discounts card stores, and\n * only the value its kind reads. A person switches it on from the discounts\n * card. `null` for a proposal no discount can be made from: a percentage\n * outside 1 to 100, or an amount off of nothing.\n */\nexport function switchedOffDiscount(proposal: ProposedDiscount): StoredDiscount | null {\n const code = (proposal.code ?? '').trim().toUpperCase().replace(/[^A-Z0-9_-]/g, '')\n const minimum = Math.round(Number(proposal.minSubtotalCents ?? 0))\n const base: StoredDiscount = {\n name: proposal.name.trim().slice(0, 80),\n code: code || null,\n kind: proposal.kind,\n ...(minimum > 0 ? { minSubtotalCents: minimum } : {}),\n enabled: false,\n redemptions: 0,\n }\n if (proposal.kind === 'percent') {\n const pct = Math.round(Number(proposal.valuePct))\n return pct >= 1 && pct <= 100 ? { ...base, valuePct: pct } : null\n }\n if (proposal.kind === 'fixed') {\n const cents = Math.round(Number(proposal.valueCents))\n return cents > 0 ? { ...base, valueCents: cents } : null\n }\n return proposal.kind === 'free_shipping' ? base : null\n}\n\nexport interface DiscountContext {\n /** Entered code, if any (case-insensitive). */\n code?: string\n subtotalCents: number\n /** Product ids present in the cart (scope checks). */\n productIds: string[]\n /**\n * What each cart line is worth, for pricing a SCOPED discount.\n *\n * Required whenever a discount carries `productIds`, and the reason is that\n * `subtotalCents` alone cannot price one: a scope names some of the cart, so\n * the discount is worth some of the cart. A caller that omits these gets a\n * refusal rather than a whole-cart discount — see `discountBenefit`.\n */\n lines?: readonly { productId: string; amountCents: number }[]\n nowMs?: number\n}\n\nexport interface ResolvedDiscount {\n discount: HostDiscount\n discountId: string\n discountCents: number\n freeShipping: boolean\n /**\n * What this discount confers, as one value. `discountCents` and\n * `freeShipping` are projections of it and are kept because callers read\n * them; the benefit is what a caller should GATE on, because it is the only\n * one of the three that can say \"nothing, and here is why\".\n */\n benefit: DiscountBenefit\n /** Why a specifically-entered code failed; unset when one applied. */\n codeProblem?: string\n}\n\nfunction applies(\n discount: HostDiscount,\n context: DiscountContext,\n): string | null {\n const now = context.nowMs ?? Date.now()\n if (discount.enabled === false) return 'This discount is disabled'\n if (discount.startAtMs != null && now < discount.startAtMs) {\n return 'This discount has not started yet'\n }\n if (discount.endAtMs != null && now > discount.endAtMs) {\n return 'This discount has expired'\n }\n // Holds count (AGL-2453). This read used to be `redemptions` alone, which is\n // a figure that only moves once the webhook lands — minutes after this\n // question is asked and answered. Every shopper who reached checkout while\n // the counter sat one below the cap passed, so the cap bounded nothing but\n // the paperwork. `promotionExhausted` counts the slots currently held by live\n // checkouts as taken, which is the same question the in-transaction re-read\n // asks below in `promotion-hold.ts` — deliberately the same function, so the\n // pre-filter and the enforcement cannot drift.\n if (promotionExhausted(discount, now)) {\n return PROMOTION_EXHAUSTED_MESSAGE\n }\n if (\n discount.minSubtotalCents != null &&\n context.subtotalCents < discount.minSubtotalCents\n ) {\n return `Spend $${(discount.minSubtotalCents / 100).toFixed(2)} to use this`\n }\n if (\n discount.productIds?.length &&\n !context.productIds.some((id) => discount.productIds!.includes(id))\n ) {\n return 'This discount does not apply to your items'\n }\n return null\n}\n\n/**\n * WHAT A DISCOUNT ACTUALLY CONFERS, named rather than implied.\n *\n * The whole point of this type is that \"nothing\" is a STATED outcome with a\n * reason, not the number zero. `valueCents` used to answer a bare `number`,\n * and every kind it did not understand — `free_shipping` included — answered\n * `0`. The cart's apply-block gates on `discountCents > 0`, and the\n * invalid-code 400 beside it only fires when NO discount resolved at all, so a\n * free-shipping code took neither branch: it resolved successfully, conferred\n * nothing, raised no error, and the shopper paid full shipping. A silent zero\n * cannot be told from \"this discount is worth nothing\", which is exactly the\n * distinction a money path has to make.\n *\n * So a caller cannot read a benefit without also seeing the `none` case, and a\n * kind this build does not recognise reports itself instead of underpaying.\n */\nexport type DiscountBenefit =\n /** Cents off the items subtotal. Always > 0 — a zero lands on `none`. */\n | { kind: 'amount'; centsOff: number }\n /** The shopper pays no shipping, whichever rate they pick. */\n | { kind: 'free-shipping' }\n /** Resolvable, but worth nothing. The caller must refuse, never proceed. */\n | { kind: 'none'; reason: string }\n\n/**\n * The single derivation of what one discount is worth against one subtotal.\n *\n * Exhaustive over {@link DiscountKind} by construction: the `never` binding\n * below fails the BUILD when a kind is added to the union and not handled\n * here, so the next `free_shipping` cannot reach production as a silent zero.\n * The runtime arm underneath it is not redundant — Firestore documents are not\n * typechecked, and a `kind` written by a newer build than the one reading it\n * arrives as an ordinary unrecognised string.\n */\nexport function discountBenefit(\n discount: HostDiscount,\n subtotalCents: number,\n lines?: readonly { productId: string; amountCents: number }[],\n): DiscountBenefit {\n const kind = discount.kind\n if (kind === 'percent' || kind === 'fixed') {\n // WHAT A SCOPE IS WORTH.\n //\n // `applies` already refuses a cart containing NONE of the scoped products,\n // so the scope was never entirely dead — but the amount was still computed\n // against the whole subtotal. A discount scoped to three products\n // therefore discounted the entire basket the moment one of the three was\n // in it: the merchant chose a scope, we charged as though they had not,\n // and the margin went with it.\n //\n // A scoped discount with no line detail REFUSES rather than falling back\n // to the whole subtotal. The fallback is the defect restated, and it would\n // be a second pricing path for one feature split by what the caller\n // happened to pass.\n const scope = discount.productIds\n let base = subtotalCents\n if (scope?.length) {\n if (!lines) {\n return {\n kind: 'none',\n reason:\n 'this discount covers only some products, and the cart did not ' +\n 'say what each item costs',\n }\n }\n base = lines\n .filter((line) => scope.includes(line.productId))\n .reduce(\n (sum, line) => sum + Math.max(0, Math.round(Number(line.amountCents ?? 0))),\n 0,\n )\n }\n const centsOff =\n kind === 'percent'\n ? Math.round(\n (base * Math.min(100, Math.max(0, discount.valuePct ?? 0))) / 100,\n )\n : Math.min(base, Math.max(0, discount.valueCents ?? 0))\n // A discount configured to take nothing off — 0%, or a zero amount — is\n // worth nothing, and saying so is what stops it being applied as a\n // successful reduction of zero.\n return centsOff > 0\n ? { kind: 'amount', centsOff }\n : {\n kind: 'none',\n reason: 'this discount takes nothing off the items in the cart',\n }\n }\n if (kind === 'free_shipping') return { kind: 'free-shipping' }\n // Unreachable while `DiscountKind` is fully handled above; the annotation is\n // what makes adding a kind a compile error rather than a quiet no-op.\n const unhandled: never = kind\n return {\n kind: 'none',\n reason: `this store has a discount of a kind this site cannot apply (${String(\n unhandled,\n )})`,\n }\n}\n\n/**\n * Best applicable discount: an entered code wins when valid (its\n * failure reason is surfaced); otherwise the largest automatic\n * promotion applies. Discounts never stack — Squarespace/Shopify\n * baseline semantics.\n */\nexport function resolveDiscount(\n discounts: Array<HostDiscount & { $id: string }>,\n context: DiscountContext,\n): ResolvedDiscount | null {\n const entered = context.code?.trim().toUpperCase()\n if (entered) {\n const coded = discounts.find(\n (discount) => discount.code?.toUpperCase() === entered,\n )\n if (!coded) return null\n const problem = applies(coded, context)\n if (problem) {\n return {\n discount: coded,\n discountId: coded.$id,\n discountCents: 0,\n freeShipping: false,\n benefit: { kind: 'none', reason: problem },\n codeProblem: problem,\n }\n }\n const benefit = discountBenefit(coded, context.subtotalCents, context.lines)\n // A code the shopper TYPED that turns out to be worth nothing is reported\n // as a code problem, so it leaves through the caller's existing refusal\n // rather than as a successful discount of zero. This is the free-shipping\n // defect's actual exit: the caller's apply-block tests `discountCents > 0`\n // and its invalid-code branch only fires when nothing resolved, so a\n // benefit of `none` used to satisfy neither and the shopper was charged in\n // full without a word.\n if (benefit.kind === 'none') {\n return {\n discount: coded,\n discountId: coded.$id,\n discountCents: 0,\n freeShipping: false,\n benefit,\n codeProblem: benefit.reason,\n }\n }\n return {\n discount: coded,\n discountId: coded.$id,\n discountCents: benefit.kind === 'amount' ? benefit.centsOff : 0,\n freeShipping: benefit.kind === 'free-shipping',\n benefit,\n }\n }\n let best: ResolvedDiscount | null = null\n for (const discount of discounts) {\n if (discount.code) continue\n if (applies(discount, context)) continue\n const benefit = discountBenefit(discount, context.subtotalCents, context.lines)\n // An automatic promotion worth nothing is passed over rather than reported:\n // nobody asked for it, so there is no shopper to answer and a better one\n // may still be in the list. An entered CODE is the opposite case and\n // refuses above — the shopper made a request and is owed the reason.\n if (benefit.kind === 'none') continue\n const cents = benefit.kind === 'amount' ? benefit.centsOff : 0\n const candidate: ResolvedDiscount = {\n discount,\n discountId: discount.$id,\n discountCents: cents,\n freeShipping: benefit.kind === 'free-shipping',\n benefit,\n }\n if (\n !best ||\n cents > best.discountCents ||\n (candidate.freeShipping && !best.freeShipping && cents === best.discountCents)\n ) {\n best = candidate\n }\n }\n return best\n}\n"],"names":["PROMOTION_EXHAUSTED_MESSAGE","promotionExhausted","switchedOffDiscount","proposal","code","trim","toUpperCase","replace","minimum","Math","round","Number","minSubtotalCents","base","name","slice","kind","enabled","redemptions","pct","valuePct","cents","valueCents","applies","discount","context","now","nowMs","Date","startAtMs","endAtMs","subtotalCents","toFixed","productIds","length","some","id","includes","discountBenefit","lines","scope","reason","filter","line","productId","reduce","sum","max","amountCents","centsOff","min","unhandled","String","resolveDiscount","discounts","entered","coded","find","problem","discountId","$id","discountCents","freeShipping","benefit","codeProblem","best","candidate"],"mappings":"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"}
@@ -0,0 +1,124 @@
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
+ import type { HostOrder, OrderDispute } from './commerce-orders';
18
+ /** How the merchant should read a dispute at a glance. */
19
+ export type OrderDisputeTone = 'open' | 'lost' | 'won' | 'settled';
20
+ /**
21
+ * A dispute Stripe has not decided yet — the case with a DEADLINE attached.
22
+ *
23
+ * Three independent signals, all of which must say "open", because saying
24
+ * "evidence due" about a settled dispute is the one error with a cost: it
25
+ * sends a merchant to gather documents for a case that is closed. `outcome`
26
+ * and `closedAtMs` are both written by `charge.dispute.closed` and `status` is
27
+ * overwritten with the outcome, so a record that disagrees with itself is
28
+ * malformed — and this resolves a malformed record to "settled", the answer
29
+ * that cannot waste anyone's afternoon.
30
+ *
31
+ * Note `evidenceDueByMs` is NOT one of the signals: Stripe sends
32
+ * `evidence_details.due_by` on the `closed` event too, so a closed dispute
33
+ * still carries a deadline and testing for one would report every settled
34
+ * dispute as open.
35
+ */
36
+ export declare function isOrderDisputeOpen(dispute?: OrderDispute): boolean;
37
+ /** Whether this order has a dispute still running against it. */
38
+ export declare function orderHasOpenDispute(order: Pick<HostOrder, 'dispute'>): boolean;
39
+ /**
40
+ * Whether a refund on this order must be REFUSED because of its dispute
41
+ * (AGL-1809).
42
+ *
43
+ * Not the same question as `orderHasOpenDispute`, and the difference is the
44
+ * whole decision. A formal open dispute (`needs_response`, `under_review`)
45
+ * means the bank has already pulled the disputed funds and Stripe's refund
46
+ * API refuses the charge outright (`charge_disputed` — "The charge you're
47
+ * attempting to refund has been charged back"); a refund alongside it would
48
+ * pay the shopper twice, once by the refund and once by the chargeback. An
49
+ * open INQUIRY is the opposite case: no money has moved, Stripe permits the
50
+ * refund, and its docs name "issuing a full refund" as the way to resolve an
51
+ * inquiry before it escalates — refusing that would forbid the recommended
52
+ * exit. Settled disputes refuse nothing here: a lost one already moved the
53
+ * order to `refunded` (the status guard's job), and a won or closed one left
54
+ * the charge refundable again.
55
+ *
56
+ * An open dispute whose status is unrecognised blocks — on a question of
57
+ * sending money twice, an unknown state fails closed.
58
+ */
59
+ export declare function orderDisputeBlocksRefund(order: Pick<HostOrder, 'dispute'>): boolean;
60
+ /** What the console renders beside an order's status when a dispute exists. */
61
+ export interface OrderDisputeBadge {
62
+ tone: OrderDisputeTone;
63
+ /** Short chip label, e.g. `Chargeback open`, `Charged back`. */
64
+ label: string;
65
+ /** A sentence for the tooltip: reason, amount, deadline or outcome. */
66
+ detail: string;
67
+ /** The deadline, present ONLY while the dispute is open. */
68
+ evidenceDueByMs?: number;
69
+ /**
70
+ * Whole days until evidence is due, negative once the deadline has passed.
71
+ * Present only alongside `evidenceDueByMs`.
72
+ */
73
+ evidenceDaysLeft?: number;
74
+ }
75
+ /**
76
+ * The badge for an order's dispute, or `null` when there is none.
77
+ *
78
+ * `nowMs` is a parameter rather than a `Date.now()` call so the deadline
79
+ * arithmetic is testable without freezing the clock.
80
+ */
81
+ export declare function describeOrderDispute(order: Pick<HostOrder, 'dispute'>, nowMs?: number): OrderDisputeBadge | null;
82
+ /** What the orders list needs to raise the alarm, over a window of orders. */
83
+ export interface OpenDisputeSummary {
84
+ /** Orders with a dispute still running. */
85
+ count: number;
86
+ /** The soonest evidence deadline among them, when any carries one. */
87
+ soonestDueByMs?: number;
88
+ /** Whole days to `soonestDueByMs`; negative once it has passed. */
89
+ soonestDaysLeft?: number;
90
+ /** True when at least one deadline is already behind us. */
91
+ overdue: boolean;
92
+ }
93
+ /**
94
+ * Count the open disputes in a window of orders and find the tightest
95
+ * deadline (AGL-1796).
96
+ *
97
+ * A filter only helps a merchant who already suspects there is something to
98
+ * filter FOR, and an evidence window is days long — so the orders list has to
99
+ * say it unprompted. Computed over every loaded order rather than the visible
100
+ * ones: a merchant filtered to "delivered" still needs to know a dispute is
101
+ * running on a `paid` one.
102
+ */
103
+ export declare function summariseOpenDisputes(orders: ReadonlyArray<Pick<HostOrder, 'dispute'>>, nowMs?: number): OpenDisputeSummary;
104
+ /** Money off this order, split by the door it left through. */
105
+ export interface OrderReversalSplit {
106
+ /** Cents refunded by a decision the merchant made. */
107
+ refundedCents: number;
108
+ /** Cents taken back by a lost chargeback. */
109
+ chargedBackCents: number;
110
+ }
111
+ /**
112
+ * Split `order.refundedCents` into the part the merchant chose and the part
113
+ * a chargeback took.
114
+ *
115
+ * AGL-1787 writes BOTH into `refundedCents`, deliberately — money reversed is
116
+ * money reversed, and the CSV, the analytics card and the member drawer all
117
+ * want the total. Only the label needs the split, and `dispute.reversedCents`
118
+ * is the piece to subtract.
119
+ *
120
+ * The chargeback share is clamped to the recorded total, so a `reversedCents`
121
+ * larger than `refundedCents` (which can only mean the two fields disagree)
122
+ * yields a zero refund line rather than a negative one.
123
+ */
124
+ export declare function splitOrderReversal(order: Pick<HostOrder, 'refundedCents' | 'dispute'>): OrderReversalSplit;
@@ -0,0 +1,225 @@
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
+ */ import { _ as _extends } from "@swc/helpers/_/_extends";
17
+ /**
18
+ * Reading a chargeback back out of an order (AGL-1796).
19
+ *
20
+ * AGL-1787 decided that a lost dispute leaves the order `status: 'refunded'`,
21
+ * because five entitlement gates match that literal and a new status would
22
+ * have escaped all of them. The cost of that decision is paid HERE: a merchant
23
+ * opening the order sees "Refunded", the one word that says they chose it.
24
+ * The distinction rides on the `dispute` record beside the status, and these
25
+ * are the pure readers that turn it back into something a console can say.
26
+ *
27
+ * Kept out of `commerce-orders.ts` on the same principle the model directory
28
+ * already follows — cart, discounts, shipping and tax each own a file — and
29
+ * because this is presentation-shaped: it answers "what should the merchant be
30
+ * told", not "what is true of the order".
31
+ *
32
+ * Dates render as `YYYY-MM-DD` through `toISOString`, which is what the
33
+ * webhook's own timeline entries do. Deterministic, and the console shows
34
+ * these strings beside those entries.
35
+ */ /**
36
+ * Stripe dispute statuses that mean it is over.
37
+ *
38
+ * `warning_*` statuses belong to an inquiry that has not become a dispute yet;
39
+ * `warning_closed` is the one that ends. The other `warning_*` values
40
+ * (`warning_needs_response`, `warning_under_review`) are OPEN, which is why
41
+ * this is a settled-list rather than a "starts with warning" test.
42
+ */ const SETTLED_DISPUTE_STATUSES = new Set([
43
+ 'won',
44
+ 'lost',
45
+ 'warning_closed'
46
+ ]);
47
+ /**
48
+ * A dispute Stripe has not decided yet — the case with a DEADLINE attached.
49
+ *
50
+ * Three independent signals, all of which must say "open", because saying
51
+ * "evidence due" about a settled dispute is the one error with a cost: it
52
+ * sends a merchant to gather documents for a case that is closed. `outcome`
53
+ * and `closedAtMs` are both written by `charge.dispute.closed` and `status` is
54
+ * overwritten with the outcome, so a record that disagrees with itself is
55
+ * malformed — and this resolves a malformed record to "settled", the answer
56
+ * that cannot waste anyone's afternoon.
57
+ *
58
+ * Note `evidenceDueByMs` is NOT one of the signals: Stripe sends
59
+ * `evidence_details.due_by` on the `closed` event too, so a closed dispute
60
+ * still carries a deadline and testing for one would report every settled
61
+ * dispute as open.
62
+ */ export function isOrderDisputeOpen(dispute) {
63
+ var _dispute_status;
64
+ if (!dispute) return false;
65
+ if (dispute.outcome) return false;
66
+ if (dispute.closedAtMs) return false;
67
+ return !SETTLED_DISPUTE_STATUSES.has(String((_dispute_status = dispute.status) != null ? _dispute_status : ''));
68
+ }
69
+ /** Whether this order has a dispute still running against it. */ export function orderHasOpenDispute(order) {
70
+ return isOrderDisputeOpen(order == null ? void 0 : order.dispute);
71
+ }
72
+ /**
73
+ * The OPEN statuses that belong to an INQUIRY — the pre-dispute phase, where
74
+ * no chargeback exists yet and no funds have been pulled.
75
+ *
76
+ * An explicit list rather than a "starts with warning" test, for the same
77
+ * reason as `SETTLED_DISPUTE_STATUSES` above: `warning_closed` also starts
78
+ * with `warning`, and an unknown future status must not be mistaken for a
79
+ * refundable inquiry by its prefix.
80
+ */ const OPEN_INQUIRY_STATUSES = new Set([
81
+ 'warning_needs_response',
82
+ 'warning_under_review'
83
+ ]);
84
+ /**
85
+ * Whether a refund on this order must be REFUSED because of its dispute
86
+ * (AGL-1809).
87
+ *
88
+ * Not the same question as `orderHasOpenDispute`, and the difference is the
89
+ * whole decision. A formal open dispute (`needs_response`, `under_review`)
90
+ * means the bank has already pulled the disputed funds and Stripe's refund
91
+ * API refuses the charge outright (`charge_disputed` — "The charge you're
92
+ * attempting to refund has been charged back"); a refund alongside it would
93
+ * pay the shopper twice, once by the refund and once by the chargeback. An
94
+ * open INQUIRY is the opposite case: no money has moved, Stripe permits the
95
+ * refund, and its docs name "issuing a full refund" as the way to resolve an
96
+ * inquiry before it escalates — refusing that would forbid the recommended
97
+ * exit. Settled disputes refuse nothing here: a lost one already moved the
98
+ * order to `refunded` (the status guard's job), and a won or closed one left
99
+ * the charge refundable again.
100
+ *
101
+ * An open dispute whose status is unrecognised blocks — on a question of
102
+ * sending money twice, an unknown state fails closed.
103
+ */ export function orderDisputeBlocksRefund(order) {
104
+ var _ref;
105
+ var _order_dispute;
106
+ if (!orderHasOpenDispute(order)) return false;
107
+ return !OPEN_INQUIRY_STATUSES.has(String((_ref = (_order_dispute = order.dispute) == null ? void 0 : _order_dispute.status) != null ? _ref : ''));
108
+ }
109
+ /** `product_not_received` reads as `product not received`. */ function humanReason(reason) {
110
+ return String(reason != null ? reason : '').replace(/_/g, ' ').trim();
111
+ }
112
+ const isoDay = (ms)=>new Date(ms).toISOString().slice(0, 10);
113
+ const usd = (cents)=>`$${(Math.max(0, cents) / 100).toFixed(2)}`;
114
+ /**
115
+ * The badge for an order's dispute, or `null` when there is none.
116
+ *
117
+ * `nowMs` is a parameter rather than a `Date.now()` call so the deadline
118
+ * arithmetic is testable without freezing the clock.
119
+ */ export function describeOrderDispute(order, nowMs = Date.now()) {
120
+ var _ref, _dispute_outcome;
121
+ const dispute = order == null ? void 0 : order.dispute;
122
+ if (!dispute) return null;
123
+ const reason = humanReason(dispute.reason);
124
+ const because = reason ? ` (${reason})` : '';
125
+ if (isOrderDisputeOpen(dispute)) {
126
+ var _dispute_evidenceDueByMs;
127
+ const dueBy = Number((_dispute_evidenceDueByMs = dispute.evidenceDueByMs) != null ? _dispute_evidenceDueByMs : 0);
128
+ // `Math.ceil` so a deadline eight hours away reads as "1 day left" rather
129
+ // than "0" — rounding a live deadline down to zero reads as expired.
130
+ const daysLeft = dueBy > 0 ? Math.ceil((dueBy - nowMs) / 86400000) : undefined;
131
+ return _extends({
132
+ tone: 'open',
133
+ label: 'Chargeback open',
134
+ detail: `${usd(dispute.amountCents)} disputed${because}, opened ` + `${isoDay(dispute.openedAtMs)}. ` + (dueBy > 0 ? `Evidence is due to Stripe by ${isoDay(dueBy)}` + (daysLeft !== undefined && daysLeft >= 0 ? ` — ${daysLeft} day${daysLeft === 1 ? '' : 's'} left.` : ' — that deadline has passed.') : 'Respond in the Stripe dashboard while the case is open.')
135
+ }, dueBy > 0 ? {
136
+ evidenceDueByMs: dueBy,
137
+ evidenceDaysLeft: daysLeft
138
+ } : {});
139
+ }
140
+ const outcome = String((_ref = (_dispute_outcome = dispute.outcome) != null ? _dispute_outcome : dispute.status) != null ? _ref : '');
141
+ const closed = dispute.closedAtMs ? ` on ${isoDay(dispute.closedAtMs)}` : '';
142
+ if (outcome === 'lost') {
143
+ var _dispute_reversedCents;
144
+ const reversed = Number((_dispute_reversedCents = dispute.reversedCents) != null ? _dispute_reversedCents : 0);
145
+ return {
146
+ tone: 'lost',
147
+ label: 'Charged back',
148
+ // The reversed figure can be LESS than the disputed one: AGL-1787 caps
149
+ // the reversal against what is left, so a partly-refunded order loses
150
+ // only the remainder. Saying only the disputed amount would overstate
151
+ // what left the merchant's books.
152
+ detail: `Dispute lost${closed}. ${usd(reversed)} was taken back` + `${because}` + (reversed < dispute.amountCents ? ` (of ${usd(dispute.amountCents)} disputed — the rest was already refunded).` : '.')
153
+ };
154
+ }
155
+ if (outcome === 'won') {
156
+ return {
157
+ tone: 'won',
158
+ label: 'Dispute won',
159
+ detail: `Dispute won${closed}${because} — no money was reversed.`
160
+ };
161
+ }
162
+ return {
163
+ tone: 'settled',
164
+ label: 'Dispute closed',
165
+ detail: `Dispute closed${closed}${because}` + (outcome ? ` as ${humanReason(outcome)}` : '') + ' — no money was reversed.'
166
+ };
167
+ }
168
+ /**
169
+ * Count the open disputes in a window of orders and find the tightest
170
+ * deadline (AGL-1796).
171
+ *
172
+ * A filter only helps a merchant who already suspects there is something to
173
+ * filter FOR, and an evidence window is days long — so the orders list has to
174
+ * say it unprompted. Computed over every loaded order rather than the visible
175
+ * ones: a merchant filtered to "delivered" still needs to know a dispute is
176
+ * running on a `paid` one.
177
+ */ export function summariseOpenDisputes(orders, nowMs = Date.now()) {
178
+ let count = 0;
179
+ let soonestDueByMs;
180
+ for (const order of orders != null ? orders : []){
181
+ var _ref;
182
+ var _order_dispute;
183
+ if (!orderHasOpenDispute(order)) continue;
184
+ count += 1;
185
+ const dueBy = Number((_ref = (_order_dispute = order.dispute) == null ? void 0 : _order_dispute.evidenceDueByMs) != null ? _ref : 0);
186
+ if (dueBy > 0 && (soonestDueByMs === undefined || dueBy < soonestDueByMs)) {
187
+ soonestDueByMs = dueBy;
188
+ }
189
+ }
190
+ if (soonestDueByMs === undefined) return {
191
+ count,
192
+ overdue: false
193
+ };
194
+ const soonestDaysLeft = Math.ceil((soonestDueByMs - nowMs) / 86400000);
195
+ return {
196
+ count,
197
+ soonestDueByMs,
198
+ soonestDaysLeft,
199
+ overdue: soonestDueByMs < nowMs
200
+ };
201
+ }
202
+ /**
203
+ * Split `order.refundedCents` into the part the merchant chose and the part
204
+ * a chargeback took.
205
+ *
206
+ * AGL-1787 writes BOTH into `refundedCents`, deliberately — money reversed is
207
+ * money reversed, and the CSV, the analytics card and the member drawer all
208
+ * want the total. Only the label needs the split, and `dispute.reversedCents`
209
+ * is the piece to subtract.
210
+ *
211
+ * The chargeback share is clamped to the recorded total, so a `reversedCents`
212
+ * larger than `refundedCents` (which can only mean the two fields disagree)
213
+ * yields a zero refund line rather than a negative one.
214
+ */ export function splitOrderReversal(order) {
215
+ var _ref, _ref1;
216
+ var _order_dispute;
217
+ const total = Math.max(0, Number((_ref = order == null ? void 0 : order.refundedCents) != null ? _ref : 0) || 0);
218
+ const chargedBackCents = Math.min(total, Math.max(0, Number((_ref1 = order == null ? void 0 : (_order_dispute = order.dispute) == null ? void 0 : _order_dispute.reversedCents) != null ? _ref1 : 0) || 0));
219
+ return {
220
+ refundedCents: total - chargedBackCents,
221
+ chargedBackCents
222
+ };
223
+ }
224
+
225
+ //# sourceMappingURL=commerce-dispute.js.map