@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,144 @@
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
+ * Reserve-then-settle for promotion redemption slots (AGL-2453).
19
+ *
20
+ * The I/O half of `model/commerce-promotions.ts` — read that file first; it
21
+ * carries the decision this one implements. Three call sites share it, and
22
+ * sharing is the point: the typed coupon (`coupons/{code}`), the automatic
23
+ * AGL-305 discount (`discounts/{id}`) and buy-now's coupon are three doors onto
24
+ * the same counter, and a hold placed at one of them has to be visible at the
25
+ * other two. Three copies of this transaction would be three chances for one of
26
+ * them to drift back to a plain `.get()`.
27
+ */
28
+ /** What a placed hold gives back to the caller. */
29
+ export interface PromotionSlotHold {
30
+ /**
31
+ * The key the hold was stored under, or `''` when the promotion is uncapped
32
+ * and no hold was needed. Carried in the session metadata so the webhook can
33
+ * settle exactly this reservation; its absence is what tells the webhook to
34
+ * fall back to the unconditional increment.
35
+ */
36
+ holdKey: string;
37
+ /**
38
+ * Drop the hold. Called by every refusal BELOW the checkout claim, and by
39
+ * `checkout.session.expired`. Best-effort and never throws: the TTL is the
40
+ * backstop, and tidying a reservation must not turn a clean 400 into a 500.
41
+ */
42
+ release: () => Promise<void>;
43
+ }
44
+ /**
45
+ * Why a slot could not be claimed.
46
+ *
47
+ * - `exhausted` — every slot is spoken for, by a settled redemption or a live
48
+ * hold. The one refusal a shopper is told about by name.
49
+ * - `missing` — the promotion document is gone, deleted between the resolver's
50
+ * read and this transaction.
51
+ * - `error` — Firestore refused. The discount is REFUSED rather than given
52
+ * away uncounted: a promotion applied against a counter that could not be
53
+ * reserved is the defect this file exists to close.
54
+ */
55
+ export type PromotionSlotRefusal = 'exhausted' | 'missing' | 'error';
56
+ /**
57
+ * Written as a two-member union with `reason` on BOTH members rather than a
58
+ * `{ ok: true } & PromotionSlotHold` intersection. Discriminated-union
59
+ * narrowing does not reach through the intersection under this repo's compiler
60
+ * settings (`strictNullChecks` is off repo-wide), so the intersection form
61
+ * compiled to `Property 'reason' does not exist` at every call site.
62
+ */
63
+ export type PromotionSlotOutcome = {
64
+ ok: true;
65
+ reason?: undefined;
66
+ holdKey: string;
67
+ release: () => Promise<void>;
68
+ } | {
69
+ ok: false;
70
+ reason: PromotionSlotRefusal;
71
+ };
72
+ /**
73
+ * A stable per-attempt hold key.
74
+ *
75
+ * `claim.stripeKey` when the client sent an Idempotency-Key, so a retry of one
76
+ * attempt re-claims its OWN slot rather than being refused by it. When it did
77
+ * not, a fresh random key per request — NOT the literal string `'null'`, which
78
+ * is what `String(claim.stripeKey)` yields and which would make every keyless
79
+ * shopper on the site share one hold. Sharing a hold key is the defect: two
80
+ * shoppers would each read the other's reservation as their own retry and both
81
+ * pass a cap of one.
82
+ *
83
+ * A keyless retry therefore holds a second slot. That is the safe direction —
84
+ * it over-reserves and releases on refusal or expiry — and the keyless path is
85
+ * already recorded as a real hole in `api-idempotency.ts` (AGL-2163) rather
86
+ * than something this fix can close.
87
+ */
88
+ export declare function promotionHoldKey(stripeKey: string | null): string;
89
+ /**
90
+ * Claim one redemption slot, or refuse.
91
+ *
92
+ * The re-check and the write are ONE transaction over the SAME document, which
93
+ * is the whole fix: the old code read the counter with a plain `.get()` at
94
+ * session creation and the webhook incremented it minutes later without ever
95
+ * re-asking. Firestore aborts and re-runs this callback if the promotion
96
+ * changed between the read and the commit, so two checkouts contending for the
97
+ * last slot cannot both observe it free.
98
+ *
99
+ * An UNCAPPED promotion writes nothing at all and returns an empty `holdKey`.
100
+ * There is no slot to reserve, and keeping the unlimited case off this write
101
+ * path keeps the fix's blast radius on the capped case.
102
+ */
103
+ export declare function holdPromotionSlot(options: {
104
+ firestore: FirebaseFirestore.Firestore;
105
+ ref: FirebaseFirestore.DocumentReference;
106
+ holdKey: string;
107
+ nowMs?: number;
108
+ /** Label for the failure log; never shown to a shopper. */
109
+ label: string;
110
+ }): Promise<PromotionSlotOutcome>;
111
+ /**
112
+ * Give a slot back.
113
+ *
114
+ * A bare merge-set with the delete sentinel rather than a transaction: removing
115
+ * one key is not a read-modify-write, and a release must not be able to fail
116
+ * the response it is tidying up after. Swallows its own error for the same
117
+ * reason — the TTL still releases the slot.
118
+ */
119
+ export declare function releasePromotionHold(ref: FirebaseFirestore.DocumentReference, holdKey: string): Promise<void>;
120
+ /** What a settlement did, for the caller's orphan reporting. */
121
+ export type PromotionSettlement =
122
+ /** The hold was found and converted into a redemption. */
123
+ 'settled'
124
+ /** No hold under this key: a redelivery, already counted. Do nothing. */
125
+ | 'already-settled'
126
+ /** The promotion document is gone; the redemption cannot be recorded. */
127
+ | 'missing'
128
+ /** Firestore refused; the hold stands and lapses on its own. */
129
+ | 'error';
130
+ /**
131
+ * Convert a held slot into a counted redemption.
132
+ *
133
+ * Idempotent under Stripe's at-least-once delivery, which is the property
134
+ * `reconcile-stock.ts:52-58` asks any webhook-side guard on these counters to
135
+ * have: the redemption is owed only by the presence of the HOLD, so a second
136
+ * delivery finds none and takes nothing. The increment and the removal are one
137
+ * write, so there is no window in which the slot is both counted and held.
138
+ */
139
+ export declare function settlePromotionSlot(options: {
140
+ firestore: FirebaseFirestore.Firestore;
141
+ ref: FirebaseFirestore.DocumentReference;
142
+ holdKey: string;
143
+ label: string;
144
+ }): Promise<PromotionSettlement>;
@@ -0,0 +1,174 @@
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
+ */ import * as CommerceModel from "../model/index.js";
18
+ import { firebaseAdmin } from "@aglyn/tenant-data-admin";
19
+ import { randomUUID } from "crypto";
20
+ /**
21
+ * A stable per-attempt hold key.
22
+ *
23
+ * `claim.stripeKey` when the client sent an Idempotency-Key, so a retry of one
24
+ * attempt re-claims its OWN slot rather than being refused by it. When it did
25
+ * not, a fresh random key per request — NOT the literal string `'null'`, which
26
+ * is what `String(claim.stripeKey)` yields and which would make every keyless
27
+ * shopper on the site share one hold. Sharing a hold key is the defect: two
28
+ * shoppers would each read the other's reservation as their own retry and both
29
+ * pass a cap of one.
30
+ *
31
+ * A keyless retry therefore holds a second slot. That is the safe direction —
32
+ * it over-reserves and releases on refusal or expiry — and the keyless path is
33
+ * already recorded as a real hole in `api-idempotency.ts` (AGL-2163) rather
34
+ * than something this fix can close.
35
+ */ export function promotionHoldKey(stripeKey) {
36
+ return stripeKey || `anon-${randomUUID()}`;
37
+ }
38
+ /**
39
+ * Claim one redemption slot, or refuse.
40
+ *
41
+ * The re-check and the write are ONE transaction over the SAME document, which
42
+ * is the whole fix: the old code read the counter with a plain `.get()` at
43
+ * session creation and the webhook incremented it minutes later without ever
44
+ * re-asking. Firestore aborts and re-runs this callback if the promotion
45
+ * changed between the read and the commit, so two checkouts contending for the
46
+ * last slot cannot both observe it free.
47
+ *
48
+ * An UNCAPPED promotion writes nothing at all and returns an empty `holdKey`.
49
+ * There is no slot to reserve, and keeping the unlimited case off this write
50
+ * path keeps the fix's blast radius on the capped case.
51
+ */ export async function holdPromotionSlot(options) {
52
+ var _options_nowMs;
53
+ const { firestore, ref, holdKey, label } = options;
54
+ const nowMs = (_options_nowMs = options.nowMs) != null ? _options_nowMs : Date.now();
55
+ const outcome = await firestore.runTransaction(async (transaction)=>{
56
+ var _fresh_data, _promotion_holds;
57
+ const fresh = await transaction.get(ref);
58
+ if (!fresh.exists) return 'missing';
59
+ const promotion = (_fresh_data = fresh.data()) != null ? _fresh_data : {};
60
+ // Uncapped: nothing to reserve, and nothing written. The webhook keeps
61
+ // the plain `increment(1)` for these, exactly as before this issue.
62
+ if (CommerceModel.promotionRemainingSlots(promotion, nowMs, holdKey) == null) {
63
+ return 'uncapped';
64
+ }
65
+ // This attempt's own prior hold does not stand in its way — a retry must
66
+ // be able to re-claim what it already reserved, or the second press of
67
+ // the same button refuses the shopper a slot they are already holding.
68
+ if (CommerceModel.promotionExhausted(promotion, nowMs, holdKey)) {
69
+ return 'exhausted';
70
+ }
71
+ // Lapsed holds are removed by SENTINEL, never by writing back a locally
72
+ // pruned copy of the map: `set(…, { merge: true })` DEEP-merges nested
73
+ // maps, so an object with the key removed leaves the stored key exactly
74
+ // where it was. Correctness does not depend on the sweep — every read
75
+ // prunes again — but without it the document grows one dead key per
76
+ // abandoned checkout, forever. The same sentinel is load-bearing at
77
+ // SETTLEMENT below, where writing back a pruned map would leave the hold
78
+ // standing and let a webhook redelivery count the redemption twice.
79
+ const live = CommerceModel.prunePromotionHolds(promotion.holds, nowMs);
80
+ const swept = {};
81
+ for (const stale of Object.keys((_promotion_holds = promotion.holds) != null ? _promotion_holds : {})){
82
+ if (stale !== holdKey && !live[stale]) {
83
+ swept[stale] = firebaseAdmin.firestore.FieldValue.delete();
84
+ }
85
+ }
86
+ transaction.set(ref, {
87
+ holds: _extends({}, swept, {
88
+ [holdKey]: {
89
+ expiresAtMs: nowMs + CommerceModel.PROMOTION_HOLD_TTL_MS
90
+ }
91
+ })
92
+ }, {
93
+ merge: true
94
+ });
95
+ return 'held';
96
+ }).catch((error)=>{
97
+ console.error('Promotion hold failed', label, error);
98
+ return 'error';
99
+ });
100
+ if (outcome === 'uncapped') {
101
+ return {
102
+ ok: true,
103
+ holdKey: '',
104
+ release: async ()=>undefined
105
+ };
106
+ }
107
+ if (outcome === 'held') {
108
+ return {
109
+ ok: true,
110
+ holdKey,
111
+ release: ()=>releasePromotionHold(ref, holdKey)
112
+ };
113
+ }
114
+ return {
115
+ ok: false,
116
+ reason: outcome
117
+ };
118
+ }
119
+ /**
120
+ * Give a slot back.
121
+ *
122
+ * A bare merge-set with the delete sentinel rather than a transaction: removing
123
+ * one key is not a read-modify-write, and a release must not be able to fail
124
+ * the response it is tidying up after. Swallows its own error for the same
125
+ * reason — the TTL still releases the slot.
126
+ */ export async function releasePromotionHold(ref, holdKey) {
127
+ if (!holdKey) return;
128
+ await ref.set({
129
+ holds: {
130
+ [holdKey]: firebaseAdmin.firestore.FieldValue.delete()
131
+ }
132
+ }, {
133
+ merge: true
134
+ }).catch((error)=>{
135
+ console.error('Promotion hold release failed', ref.path, error);
136
+ });
137
+ }
138
+ /**
139
+ * Convert a held slot into a counted redemption.
140
+ *
141
+ * Idempotent under Stripe's at-least-once delivery, which is the property
142
+ * `reconcile-stock.ts:52-58` asks any webhook-side guard on these counters to
143
+ * have: the redemption is owed only by the presence of the HOLD, so a second
144
+ * delivery finds none and takes nothing. The increment and the removal are one
145
+ * write, so there is no window in which the slot is both counted and held.
146
+ */ export async function settlePromotionSlot(options) {
147
+ const { firestore, ref, holdKey, label } = options;
148
+ return await firestore.runTransaction(async (transaction)=>{
149
+ var _fresh_data;
150
+ const fresh = await transaction.get(ref);
151
+ if (!fresh.exists) return 'missing';
152
+ const promotion = (_fresh_data = fresh.data()) != null ? _fresh_data : {};
153
+ if (!CommerceModel.promotionSettles(promotion, holdKey)) {
154
+ return 'already-settled';
155
+ }
156
+ transaction.set(ref, {
157
+ redemptions: firebaseAdmin.firestore.FieldValue.increment(1),
158
+ // `FieldValue.delete()`, NOT a pruned copy of the map — see the note
159
+ // in `holdPromotionSlot`. A merged-back object would leave the hold
160
+ // standing and a redelivery would increment a SECOND time.
161
+ holds: {
162
+ [holdKey]: firebaseAdmin.firestore.FieldValue.delete()
163
+ }
164
+ }, {
165
+ merge: true
166
+ });
167
+ return 'settled';
168
+ }).catch((error)=>{
169
+ console.error('Promotion settlement failed', label, error);
170
+ return 'error';
171
+ });
172
+ }
173
+
174
+ //# sourceMappingURL=promotion-hold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/promotion-hold.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\nimport * as CommerceModel from '../model'\nimport { firebaseAdmin } from '@aglyn/tenant-data-admin'\nimport { randomUUID } from 'crypto'\n\n/**\n * Reserve-then-settle for promotion redemption slots (AGL-2453).\n *\n * The I/O half of `model/commerce-promotions.ts` — read that file first; it\n * carries the decision this one implements. Three call sites share it, and\n * sharing is the point: the typed coupon (`coupons/{code}`), the automatic\n * AGL-305 discount (`discounts/{id}`) and buy-now's coupon are three doors onto\n * the same counter, and a hold placed at one of them has to be visible at the\n * other two. Three copies of this transaction would be three chances for one of\n * them to drift back to a plain `.get()`.\n */\n\n/** What a placed hold gives back to the caller. */\nexport interface PromotionSlotHold {\n /**\n * The key the hold was stored under, or `''` when the promotion is uncapped\n * and no hold was needed. Carried in the session metadata so the webhook can\n * settle exactly this reservation; its absence is what tells the webhook to\n * fall back to the unconditional increment.\n */\n holdKey: string\n /**\n * Drop the hold. Called by every refusal BELOW the checkout claim, and by\n * `checkout.session.expired`. Best-effort and never throws: the TTL is the\n * backstop, and tidying a reservation must not turn a clean 400 into a 500.\n */\n release: () => Promise<void>\n}\n\n/**\n * Why a slot could not be claimed.\n *\n * - `exhausted` — every slot is spoken for, by a settled redemption or a live\n * hold. The one refusal a shopper is told about by name.\n * - `missing` — the promotion document is gone, deleted between the resolver's\n * read and this transaction.\n * - `error` — Firestore refused. The discount is REFUSED rather than given\n * away uncounted: a promotion applied against a counter that could not be\n * reserved is the defect this file exists to close.\n */\nexport type PromotionSlotRefusal = 'exhausted' | 'missing' | 'error'\n\n/**\n * Written as a two-member union with `reason` on BOTH members rather than a\n * `{ ok: true } & PromotionSlotHold` intersection. Discriminated-union\n * narrowing does not reach through the intersection under this repo's compiler\n * settings (`strictNullChecks` is off repo-wide), so the intersection form\n * compiled to `Property 'reason' does not exist` at every call site.\n */\nexport type PromotionSlotOutcome =\n | { ok: true; reason?: undefined; holdKey: string; release: () => Promise<void> }\n | { ok: false; reason: PromotionSlotRefusal }\n\n/**\n * A stable per-attempt hold key.\n *\n * `claim.stripeKey` when the client sent an Idempotency-Key, so a retry of one\n * attempt re-claims its OWN slot rather than being refused by it. When it did\n * not, a fresh random key per request — NOT the literal string `'null'`, which\n * is what `String(claim.stripeKey)` yields and which would make every keyless\n * shopper on the site share one hold. Sharing a hold key is the defect: two\n * shoppers would each read the other's reservation as their own retry and both\n * pass a cap of one.\n *\n * A keyless retry therefore holds a second slot. That is the safe direction —\n * it over-reserves and releases on refusal or expiry — and the keyless path is\n * already recorded as a real hole in `api-idempotency.ts` (AGL-2163) rather\n * than something this fix can close.\n */\nexport function promotionHoldKey(stripeKey: string | null): string {\n return stripeKey || `anon-${randomUUID()}`\n}\n\n/**\n * Claim one redemption slot, or refuse.\n *\n * The re-check and the write are ONE transaction over the SAME document, which\n * is the whole fix: the old code read the counter with a plain `.get()` at\n * session creation and the webhook incremented it minutes later without ever\n * re-asking. Firestore aborts and re-runs this callback if the promotion\n * changed between the read and the commit, so two checkouts contending for the\n * last slot cannot both observe it free.\n *\n * An UNCAPPED promotion writes nothing at all and returns an empty `holdKey`.\n * There is no slot to reserve, and keeping the unlimited case off this write\n * path keeps the fix's blast radius on the capped case.\n */\nexport async function holdPromotionSlot(options: {\n firestore: FirebaseFirestore.Firestore\n ref: FirebaseFirestore.DocumentReference\n holdKey: string\n nowMs?: number\n /** Label for the failure log; never shown to a shopper. */\n label: string\n}): Promise<PromotionSlotOutcome> {\n const { firestore, ref, holdKey, label } = options\n const nowMs = options.nowMs ?? Date.now()\n const outcome = await firestore\n .runTransaction(async (transaction) => {\n const fresh = await transaction.get(ref)\n if (!fresh.exists) return 'missing' as const\n const promotion = (fresh.data() ?? {}) as CommerceModel.HeldPromotion\n // Uncapped: nothing to reserve, and nothing written. The webhook keeps\n // the plain `increment(1)` for these, exactly as before this issue.\n if (\n CommerceModel.promotionRemainingSlots(promotion, nowMs, holdKey) == null\n ) {\n return 'uncapped' as const\n }\n // This attempt's own prior hold does not stand in its way — a retry must\n // be able to re-claim what it already reserved, or the second press of\n // the same button refuses the shopper a slot they are already holding.\n if (CommerceModel.promotionExhausted(promotion, nowMs, holdKey)) {\n return 'exhausted' as const\n }\n // Lapsed holds are removed by SENTINEL, never by writing back a locally\n // pruned copy of the map: `set(…, { merge: true })` DEEP-merges nested\n // maps, so an object with the key removed leaves the stored key exactly\n // where it was. Correctness does not depend on the sweep — every read\n // prunes again — but without it the document grows one dead key per\n // abandoned checkout, forever. The same sentinel is load-bearing at\n // SETTLEMENT below, where writing back a pruned map would leave the hold\n // standing and let a webhook redelivery count the redemption twice.\n const live = CommerceModel.prunePromotionHolds(promotion.holds, nowMs)\n const swept: Record<string, unknown> = {}\n for (const stale of Object.keys(promotion.holds ?? {})) {\n if (stale !== holdKey && !live[stale]) {\n swept[stale] = firebaseAdmin.firestore.FieldValue.delete()\n }\n }\n transaction.set(\n ref,\n {\n holds: {\n ...swept,\n [holdKey]: {\n expiresAtMs: nowMs + CommerceModel.PROMOTION_HOLD_TTL_MS,\n },\n },\n },\n { merge: true },\n )\n return 'held' as const\n })\n .catch((error: unknown) => {\n console.error('Promotion hold failed', label, error)\n return 'error' as const\n })\n if (outcome === 'uncapped') {\n return { ok: true, holdKey: '', release: async () => undefined }\n }\n if (outcome === 'held') {\n return { ok: true, holdKey, release: () => releasePromotionHold(ref, holdKey) }\n }\n return { ok: false, reason: outcome }\n}\n\n/**\n * Give a slot back.\n *\n * A bare merge-set with the delete sentinel rather than a transaction: removing\n * one key is not a read-modify-write, and a release must not be able to fail\n * the response it is tidying up after. Swallows its own error for the same\n * reason — the TTL still releases the slot.\n */\nexport async function releasePromotionHold(\n ref: FirebaseFirestore.DocumentReference,\n holdKey: string,\n): Promise<void> {\n if (!holdKey) return\n await ref\n .set(\n { holds: { [holdKey]: firebaseAdmin.firestore.FieldValue.delete() } },\n { merge: true },\n )\n .catch((error: unknown) => {\n console.error('Promotion hold release failed', ref.path, error)\n })\n}\n\n/** What a settlement did, for the caller's orphan reporting. */\nexport type PromotionSettlement =\n /** The hold was found and converted into a redemption. */\n | 'settled'\n /** No hold under this key: a redelivery, already counted. Do nothing. */\n | 'already-settled'\n /** The promotion document is gone; the redemption cannot be recorded. */\n | 'missing'\n /** Firestore refused; the hold stands and lapses on its own. */\n | 'error'\n\n/**\n * Convert a held slot into a counted redemption.\n *\n * Idempotent under Stripe's at-least-once delivery, which is the property\n * `reconcile-stock.ts:52-58` asks any webhook-side guard on these counters to\n * have: the redemption is owed only by the presence of the HOLD, so a second\n * delivery finds none and takes nothing. The increment and the removal are one\n * write, so there is no window in which the slot is both counted and held.\n */\nexport async function settlePromotionSlot(options: {\n firestore: FirebaseFirestore.Firestore\n ref: FirebaseFirestore.DocumentReference\n holdKey: string\n label: string\n}): Promise<PromotionSettlement> {\n const { firestore, ref, holdKey, label } = options\n return await firestore\n .runTransaction(async (transaction) => {\n const fresh = await transaction.get(ref)\n if (!fresh.exists) return 'missing' as const\n const promotion = (fresh.data() ?? {}) as CommerceModel.HeldPromotion\n if (!CommerceModel.promotionSettles(promotion, holdKey)) {\n return 'already-settled' as const\n }\n transaction.set(\n ref,\n {\n redemptions: firebaseAdmin.firestore.FieldValue.increment(1),\n // `FieldValue.delete()`, NOT a pruned copy of the map — see the note\n // in `holdPromotionSlot`. A merged-back object would leave the hold\n // standing and a redelivery would increment a SECOND time.\n holds: {\n [holdKey]: firebaseAdmin.firestore.FieldValue.delete(),\n },\n },\n { merge: true },\n )\n return 'settled' as const\n })\n .catch((error: unknown) => {\n console.error('Promotion settlement failed', label, error)\n return 'error' as const\n })\n}\n"],"names":["CommerceModel","firebaseAdmin","randomUUID","promotionHoldKey","stripeKey","holdPromotionSlot","options","firestore","ref","holdKey","label","nowMs","Date","now","outcome","runTransaction","transaction","fresh","promotion","get","exists","data","promotionRemainingSlots","promotionExhausted","live","prunePromotionHolds","holds","swept","stale","Object","keys","FieldValue","delete","set","expiresAtMs","PROMOTION_HOLD_TTL_MS","merge","catch","error","console","ok","release","undefined","releasePromotionHold","reason","path","settlePromotionSlot","promotionSettles","redemptions","increment"],"mappings":"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"}
@@ -0,0 +1,106 @@
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 PluginJobHostGate } from '@aglyn/aglyn/server';
18
+ export interface MissingSaleDecrement {
19
+ hostId: string;
20
+ orderId: string;
21
+ /** The merchant-facing sequential number, when the doc carries one. */
22
+ orderNumber: number | null;
23
+ orderStatus: string;
24
+ orderCreatedAtMs: number;
25
+ productId: string;
26
+ /** Live product name — the order's snapshot name is used as a fallback. */
27
+ productName: string;
28
+ variantId: string;
29
+ /** Units the order says were sold, and the shelf therefore still holds. */
30
+ quantity: number;
31
+ }
32
+ export interface StockReconciliationResult {
33
+ ordersScanned: number;
34
+ /** Orders that reached the ledger comparison (post status/grace filter). */
35
+ ordersChecked: number;
36
+ missing: MissingSaleDecrement[];
37
+ /**
38
+ * The ledger read hit its limit before reaching back as far as the oldest
39
+ * order considered, so orders older than the ledger window were DROPPED
40
+ * rather than judged against rows that were never read.
41
+ *
42
+ * Recorded and reported rather than swallowed, for the AGL-2321 reason:
43
+ * `siteSizeTruncated` exists because a number that is silently a lower
44
+ * bound is worse than one that says so. A truncated pass under-reports; it
45
+ * must never be read as "all matched".
46
+ */
47
+ ledgerTruncated: boolean;
48
+ }
49
+ /**
50
+ * Compares one host's recently-decremented orders against the
51
+ * `reason: 'sale'` rows joined to them, and reports the lines whose decrement
52
+ * is missing.
53
+ *
54
+ * Reads are bounded and cheap in the healthy case: two collection queries per
55
+ * host, and a product read ONLY for a line that already looks divergent.
56
+ *
57
+ * Two equality-free queries so the automatic single-field indexes answer them
58
+ * (the `cancel-order.ts` rule): `orderBy(createdAtMs desc).limit()` and
59
+ * `orderBy(atMs desc).limit()`, with the status test applied in memory over
60
+ * the handful of documents that come back.
61
+ */
62
+ export declare function reconcileHostStockDecrements(options: {
63
+ firestore: any;
64
+ hostRef: any;
65
+ hostId: string;
66
+ nowMs?: number;
67
+ graceMs?: number;
68
+ orderLimit?: number;
69
+ ledgerLimit?: number;
70
+ }): Promise<StockReconciliationResult>;
71
+ /**
72
+ * Reports a host's divergences to its managers, once per order.
73
+ *
74
+ * The marker in `hosts/{hostId}/inventoryReconciliation/{orderId}` is the only
75
+ * write this whole pass makes, and it lives in a collection nothing else on
76
+ * the platform reads or writes — the detector must not be able to affect the
77
+ * money path it is watching. Without it a beat would re-nag every hour about
78
+ * an order the merchant has already corrected, and an alert that repeats
79
+ * forever is one that gets muted.
80
+ */
81
+ export declare function reportMissingSaleDecrements(hostId: string, missing: readonly MissingSaleDecrement[]): Promise<number>;
82
+ export interface StockReconciliationScan {
83
+ hosts: number;
84
+ ordersScanned: number;
85
+ missingLines: number;
86
+ reportedOrders: number;
87
+ truncatedHosts: number;
88
+ /** Hosts left unreconciled because they are locked (AGL-2495). */
89
+ skippedLocked: number;
90
+ }
91
+ /**
92
+ * The platform beat: the most recent orders across every host, grouped by
93
+ * host and reconciled one host at a time.
94
+ *
95
+ * Ordered by `createdAtMs` and NOT filtered by status, because an equality
96
+ * filter plus an ordering is a composite index and the ordering alone is a
97
+ * field override — the same trade `cancel-order.ts` takes. Every order writer
98
+ * in the plugin stamps `createdAtMs` (cart, buy-now, draft, POS cash, POS
99
+ * card, subscription cycle), so nothing is invisible to the ordering.
100
+ */
101
+ export declare function scanStockDecrements(
102
+ /** The lockdown gate, injected by the caller (AGL-2495). Not optional. */
103
+ gate: PluginJobHostGate, options?: {
104
+ orderLimit?: number;
105
+ nowMs?: number;
106
+ }): Promise<StockReconciliationScan>;