@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,607 @@
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 Aglyn from "@aglyn/aglyn/server";
18
+ import * as CommerceModel from "../model/index.js";
19
+ import { firebaseAdmin, getOrgForHost } from "@aglyn/tenant-data-admin";
20
+ import { resolveOrgPermissions } from "@aglyn/tenant-runtime/org-permissions";
21
+ import { createHash } from "crypto";
22
+ import { recordContactRefund } from "./contact-refund.js";
23
+ import { flagOrderRestock } from "./restock-flag.js";
24
+ // Leaf import, not the barrel, for the reason `contact-refund.ts` states about
25
+ // `updateExisting`: the specs in this library mock `@aglyn/tenant-data-admin`
26
+ // wholesale, and a permissive stub would turn a reversal that never happened
27
+ // green.
28
+ import { reverseEmailAttributedRevenue } from "@aglyn/tenant-data-admin/server/email-revenue-attribution";
29
+ /**
30
+ * Retires the licence keys a refund withdrew (AGL-2454).
31
+ *
32
+ * Reads the order back so the decision is made from what actually SETTLED
33
+ * rather than from what this request asked for — a concurrent partial may have
34
+ * closed a line between the two — and retires only the keys of products the
35
+ * order no longer entitles at all. `refundedProductIds` is deliberately strict
36
+ * about that: a buyer who returned one of two copies still holds the product,
37
+ * so nothing is retired for them.
38
+ *
39
+ * `revokedAtMs` with `assignedAtMs` left standing is the retired state. Keeping
40
+ * `assignedAtMs` matters: `assignLicenseKeys` claims from
41
+ * `where('assignedAtMs','==',null)`, so clearing it would put the key straight
42
+ * back in front of the next buyer — the reissue this must not do.
43
+ *
44
+ * Swallows everything. The refund has already moved money.
45
+ */ async function retireLicenseKeys(hostRef, orderRef, orderId) {
46
+ try {
47
+ var _data;
48
+ const fresh = CommerceModel.liftLegacyOrder((_data = (await orderRef.get()).data()) != null ? _data : {});
49
+ const withdrawn = new Set(CommerceModel.refundedProductIds(fresh));
50
+ if (withdrawn.size === 0) return 0;
51
+ const assigned = await hostRef.collection('licenseKeys').where('orderId', '==', orderId).limit(500).get();
52
+ let retired = 0;
53
+ for (const keySnapshot of assigned.docs){
54
+ var _keySnapshot_get;
55
+ if (!withdrawn.has(String((_keySnapshot_get = keySnapshot.get('productId')) != null ? _keySnapshot_get : ''))) continue;
56
+ // Already retired by an earlier partial, or by the merchant's own Revoke
57
+ // button. Skipped so a second refund does not restamp the timestamp and
58
+ // make the retirement look newer than it is.
59
+ if (keySnapshot.get('revokedAtMs') != null) continue;
60
+ await keySnapshot.ref.set({
61
+ revokedAtMs: Date.now(),
62
+ revokedOrderId: orderId
63
+ }, {
64
+ merge: true
65
+ }).catch(()=>undefined);
66
+ retired++;
67
+ }
68
+ if (retired > 0) {
69
+ await orderRef.update({
70
+ timeline: firebaseAdmin.firestore.FieldValue.arrayUnion({
71
+ atMs: Date.now(),
72
+ event: 'license-retired',
73
+ detail: `${retired} license key${retired === 1 ? '' : 's'} retired. ` + 'The buyer already holds the key string, so it is not returned ' + 'to the pool — reissuing it would give two people one secret.'
74
+ })
75
+ }).catch(()=>undefined);
76
+ }
77
+ return retired;
78
+ } catch (error) {
79
+ console.error('Licence key retirement failed', orderId, error);
80
+ return 0;
81
+ }
82
+ }
83
+ /**
84
+ * Order refunds (AGL-287): full or partial via Stripe, site-admin only
85
+ * (it moves money). Destination charges reverse the transfer and the
86
+ * platform fee proportionally. Full refunds transition the order to
87
+ * `refunded`; partial refunds accumulate `refundedCents` and stay in
88
+ * the current status.
89
+ *
90
+ * Two SEPARATE controls guard the money (AGL-1696), and conflating them is
91
+ * how the original went wrong:
92
+ *
93
+ * - The idempotency key stops a DUPLICATE refund — one attempt sent twice
94
+ * because the response was lost, the admin double-clicked, or a client
95
+ * retried. It is minted per attempt by the console and deliberately not
96
+ * derived from the order or the amount: two $10 refunds on a $50 order are
97
+ * two real refunds, exactly as a cashier ringing the same coffee twice is a
98
+ * real second sale.
99
+ * - The cap stops an OVER-refund — several partials summing past what was
100
+ * captured, including two admins refunding at once, where the two attempts
101
+ * are genuinely distinct and no key can help. That needs the counter read
102
+ * and written inside one transaction.
103
+ *
104
+ * The original had a cap that looked like both and was neither: it read
105
+ * `refundedCents` and wrote it back only AFTER the Stripe call, outside any
106
+ * transaction. A guard that reads state the guarded operation writes too late
107
+ * is not a guard — measured, two concurrent refunds each sent a full $50 to
108
+ * Stripe with no idempotency header on either.
109
+ */ export const refundHandler = async (req, res)=>{
110
+ var _req_headers_authorization, _req_body, _body_hostId, _body_orderId, _ref, _req_headers_idempotencykey;
111
+ if (req.method !== 'POST') {
112
+ return res.status(405).json({
113
+ error: 'Method not allowed'
114
+ });
115
+ }
116
+ if (!process.env.STRIPE_SECRET_KEY) {
117
+ return res.status(501).json({
118
+ error: 'Payments are not configured.'
119
+ });
120
+ }
121
+ const authorization = String((_req_headers_authorization = req.headers.authorization) != null ? _req_headers_authorization : '');
122
+ const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : undefined;
123
+ if (!idToken) return res.status(401).json({
124
+ error: 'Unauthenticated'
125
+ });
126
+ const body = typeof req.body === 'string' ? JSON.parse(req.body) : (_req_body = req.body) != null ? _req_body : {};
127
+ const hostId = String((_body_hostId = body.hostId) != null ? _body_hostId : '');
128
+ const orderId = String((_body_orderId = body.orderId) != null ? _body_orderId : '');
129
+ const amountCents = body.amountCents == null ? null : Number(body.amountCents);
130
+ /**
131
+ * Lines the admin is refunding BY NAME (AGL-2454), and therefore the lines
132
+ * whose digital entitlements come back. Optional: an amount-only refund is
133
+ * still a legal refund and still revokes nothing per-line — see the guard
134
+ * below for why that is a decision rather than an oversight.
135
+ */ const requestedLineIds = Array.isArray(body.lineItemIds) ? [
136
+ ...new Set(body.lineItemIds.map((value)=>Math.round(Number(value))).filter((value)=>Number.isFinite(value) && value >= 0))
137
+ ].sort((a, b)=>a - b) : [];
138
+ // One refund attempt, minted by the console. Node lowercases incoming
139
+ // headers, but read both spellings — the plugin API request type makes no
140
+ // promise about casing.
141
+ const idempotencyKey = String((_ref = (_req_headers_idempotencykey = req.headers['idempotency-key']) != null ? _req_headers_idempotencykey : req.headers['Idempotency-Key']) != null ? _ref : '').trim().slice(0, 200);
142
+ if (!hostId || !orderId) {
143
+ return res.status(400).json({
144
+ error: 'Missing hostId or orderId'
145
+ });
146
+ }
147
+ let claim = null;
148
+ try {
149
+ var _hostSnapshot_get, _order_lineItems, _order_paymentIntentId;
150
+ const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken);
151
+ const firestore = firebaseAdmin.app().firestore();
152
+ const hostRef = firestore.collection('hosts').doc(hostId);
153
+ const hostSnapshot = await hostRef.get();
154
+ if (!hostSnapshot.exists) {
155
+ return res.status(404).json({
156
+ error: 'Unknown site'
157
+ });
158
+ }
159
+ // TWO CHECKS, and they answer different questions (AGL-2372).
160
+ //
161
+ // The first is the HOST-level fact the Firestore rules also enforce, and
162
+ // it stays: `memberRoles` is the projection the rules read, so dropping it
163
+ // here would let this route and the database disagree.
164
+ const memberRole = ((_hostSnapshot_get = hostSnapshot.get('memberRoles')) != null ? _hostSnapshot_get : {})[decoded.uid];
165
+ if (memberRole !== 'admin') {
166
+ return res.status(403).json({
167
+ error: 'Refunds require a site admin'
168
+ });
169
+ }
170
+ // The second is WHOSE admin, and it is the one this gate was missing.
171
+ //
172
+ // `memberRoles` is a per-host projection of `hostAccess`, and
173
+ // `/api/hosts/members` will grant a SITE COLLABORATOR `admin` on one site
174
+ // (`hostAccess: { [hostId]: 'admin' }`, `allHosts: false`). That writes the
175
+ // literal string `'admin'` into `memberRoles[uid]` — byte-identical to an
176
+ // org owner's. So the check above cannot tell a contractor invited to run
177
+ // one microsite from the person who owns the business, and refunding is
178
+ // money leaving that business.
179
+ //
180
+ // `orgWide` is the discriminator, and it needs no new role: it is
181
+ // `isOrgWideMember` (AGL-1026) — owner/admin of the org, an explicit
182
+ // `allHosts` member, or the legacy pre-`allHosts` shape — and it is false
183
+ // for every scoped collaborator. Same pairing `pos-order.ts` uses.
184
+ //
185
+ // BOTH halves are required. `hostRole` is re-tested rather than assumed
186
+ // from `memberRole`: an org-wide member can still be scoped down to
187
+ // `editor` on this host, and `resolveOrgPermissions` is the resolver that
188
+ // knows it. It fails CLOSED on a lookup error when a host is named
189
+ // (AGL-506), and `denied()` returns `orgWide: false` / `hostRole: null`,
190
+ // so an absent membership refuses rather than folding to permitted.
191
+ const membership = await resolveOrgPermissions(decoded.uid, {
192
+ hostId
193
+ });
194
+ if (!membership.orgWide || membership.hostRole !== 'admin') {
195
+ return res.status(403).json({
196
+ error: 'Refunds require an admin of the whole workspace'
197
+ });
198
+ }
199
+ const orderRef = hostRef.collection('orders').doc(orderId);
200
+ const orderSnapshot = await orderRef.get();
201
+ if (!orderSnapshot.exists) {
202
+ return res.status(404).json({
203
+ error: 'Unknown order'
204
+ });
205
+ }
206
+ const order = CommerceModel.liftLegacyOrder(orderSnapshot.data());
207
+ // Replay a settled attempt before anything else can reject it. This read
208
+ // is only a short-circuit, never the dedupe primitive — the atomic
209
+ // `create()` below is. It has to run ahead of the status guard because a
210
+ // retried FULL refund would otherwise be answered "orders in refunded
211
+ // cannot refund", which is the right money outcome reported as a failure,
212
+ // and an admin who reads it as a failure refunds again by hand.
213
+ const claimRef = idempotencyKey ? firestore.collection('apiIdempotency').doc(createHash('sha256')// Scoped by the order, so a client that reused one key across
214
+ // two orders cannot dedupe two legitimately distinct refunds.
215
+ // NOT by the amount: that would swallow a real second partial.
216
+ .update(`refund:${hostId}:${orderId}:${idempotencyKey}`).digest('hex')) : null;
217
+ if (claimRef) {
218
+ const prior = await claimRef.get();
219
+ const priorResponse = prior.get('response');
220
+ if (priorResponse) {
221
+ var _prior_get;
222
+ return res.status(Number((_prior_get = prior.get('responseStatus')) != null ? _prior_get : 200)).json(priorResponse);
223
+ }
224
+ }
225
+ if (!CommerceModel.canTransitionOrder(order.status, 'refunded')) {
226
+ return res.status(409).json({
227
+ error: `Orders in "${order.status}" cannot refund`
228
+ });
229
+ }
230
+ // A refund does not withdraw a dispute (AGL-1809). While a chargeback is
231
+ // formally open the bank has already pulled the disputed funds, Stripe's
232
+ // refund API refuses the charge (`charge_disputed`), and a refund that did
233
+ // go through would pay the shopper twice — the merchant loses the refund
234
+ // AND the dispute plus its fee. Refused HERE, before the claim and the
235
+ // reservation, so a refusal burns no idempotency key and strands nothing:
236
+ // no state has been written yet (AGL-1754's contract). An open INQUIRY
237
+ // (`warning_*`) deliberately passes — no funds have moved and Stripe names
238
+ // a full refund as the way to resolve one before it escalates — and the
239
+ // status guard above already turns away a LOST dispute, which parked the
240
+ // order in `refunded`. This reads the pre-transaction snapshot; a dispute
241
+ // webhook racing this exact request is caught by the `charge_disputed`
242
+ // mapping on the Stripe response below.
243
+ if (CommerceModel.orderDisputeBlocksRefund(order)) {
244
+ return res.status(409).json({
245
+ error: 'A chargeback is open on this order, so it was not refunded. ' + 'Refunding would not withdraw the dispute — the bank has already ' + 'taken the disputed amount, and a refund on top of it would pay ' + 'the shopper twice. Respond to the dispute or accept it in the ' + 'Stripe dashboard; refund any remainder once it settles.'
246
+ });
247
+ }
248
+ // WHAT THE NAMED LINES ARE WORTH, AND WHY THE AMOUNT MAY NOT BE LESS
249
+ // (AGL-2454).
250
+ //
251
+ // A refund carries an amount, not lines — that is the blocker this issue
252
+ // names, and `restock-flag.ts:48-55` already records it for stock. It
253
+ // cannot be solved by inference: deciding for the merchant which lines a
254
+ // bare figure covers would be a guess about their goods. It CAN be solved
255
+ // by asking, which is what naming lines does, and the amount is then
256
+ // derived from them rather than typed beside them.
257
+ //
258
+ // An explicit `amountCents` may still be LARGER (the admin is refunding the
259
+ // line plus its share of tax or shipping, which this items-only sum does
260
+ // not include). It may not be SMALLER: revoking a line the refund did not
261
+ // actually cover is the silent over-revocation this issue forbids in the
262
+ // same breath as silent under-revocation.
263
+ const orderLines = (_order_lineItems = order.lineItems) != null ? _order_lineItems : [];
264
+ const invalidLine = requestedLineIds.find((index)=>index >= orderLines.length);
265
+ if (invalidLine != null) {
266
+ return res.status(400).json({
267
+ error: `Line ${invalidLine} is not on this order`
268
+ });
269
+ }
270
+ // NET OF THE ORDER'S DISCOUNT, not the list price.
271
+ //
272
+ // This was the bare `unitAmountCents x quantity`, which is what the line
273
+ // was LISTED at rather than what the buyer paid for it. On a discounted
274
+ // order the two differ, and both directions of the error land on the
275
+ // merchant: a $10 coupon over two $50 lines means each line cost $45, so
276
+ // refunding one at $50 gave back $5 that was never taken, and the order
277
+ // then held less than its remaining line was worth — so the second line
278
+ // refund hit the cap below and was refused outright, leaving the merchant
279
+ // unable to finish a refund they had already half-issued.
280
+ //
281
+ // `orderLineRefundCents` apportions the discount across every line by list
282
+ // value and returns the named lines' share, so refunding all of them sums
283
+ // to exactly what was charged and no cent is stranded or invented.
284
+ const namedLinesCents = CommerceModel.orderLineRefundCents(order, requestedLineIds);
285
+ if (requestedLineIds.length > 0 && amountCents != null && Math.round(amountCents) < namedLinesCents) {
286
+ return res.status(400).json({
287
+ error: 'That amount is less than the lines you selected are worth. ' + 'Refund the full value of those lines, or refund an amount ' + 'without selecting lines.'
288
+ });
289
+ }
290
+ const paymentIntentId = (_order_paymentIntentId = order.paymentIntentId) != null ? _order_paymentIntentId : // Legacy rows stored the checkout session as the doc id; resolve
291
+ // the payment intent from Stripe.
292
+ await (async ()=>{
293
+ const response = await fetch(`https://api.stripe.com/v1/checkout/sessions/${orderId}`, {
294
+ headers: {
295
+ Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}`
296
+ }
297
+ });
298
+ const session = await response.json();
299
+ return response.ok ? session == null ? void 0 : session.payment_intent : null;
300
+ })();
301
+ if (!paymentIntentId) {
302
+ return res.status(409).json({
303
+ error: 'No payment to refund'
304
+ });
305
+ }
306
+ // Point of no return: everything past here moves money. The claim is
307
+ // `create()` — Firestore rejects a create on an existing document, and
308
+ // that rejection IS the dedupe primitive. A read-then-write would race
309
+ // exactly the double-submit it exists to stop. Storage reuses the REST
310
+ // API's shape and its `orgId` field (AGL-618) rather than inventing a
311
+ // second replay store, so `eraseOrgIdempotencyKeys` (AGL-1448) already
312
+ // sweeps these on org erasure with no change there.
313
+ if (claimRef) {
314
+ const ownerOrg = await getOrgForHost(hostId);
315
+ try {
316
+ var _ref1;
317
+ var _ownerOrg_org;
318
+ await claimRef.create({
319
+ orgId: String((_ref1 = ownerOrg == null ? void 0 : (_ownerOrg_org = ownerOrg.org) == null ? void 0 : _ownerOrg_org.id) != null ? _ref1 : '') || null,
320
+ hostId,
321
+ orderId,
322
+ kind: 'commerce-refund',
323
+ status: 'pending',
324
+ createdAt: firebaseAdmin.firestore.FieldValue.serverTimestamp(),
325
+ createdAtMs: Date.now(),
326
+ // The second writer into `apiIdempotency` (AGL-1978). The shared
327
+ // `claimAttempt` stamps this too; this local copy has to as well,
328
+ // or refund claims are the one shape the TTL policy silently never
329
+ // reaches — a policy that governs most of a collection reads, from
330
+ // the outside, exactly like one that governs all of it.
331
+ expiresAt: Aglyn.apiIdempotencyExpiry()
332
+ });
333
+ } catch (unused) {
334
+ const prior = await claimRef.get();
335
+ const priorResponse = prior.get('response');
336
+ if (priorResponse) {
337
+ var _prior_get1;
338
+ return res.status(Number((_prior_get1 = prior.get('responseStatus')) != null ? _prior_get1 : 200)).json(priorResponse);
339
+ }
340
+ // In flight, or stranded by a process that died mid-refund. Fail
341
+ // CLOSED: the alternative is sending the money a second time.
342
+ return res.status(409).json({
343
+ error: 'This refund is already being processed'
344
+ });
345
+ }
346
+ claim = {
347
+ // The same digest goes to Stripe. That is the half that costs real
348
+ // money: it covers the window where our claim is written but the
349
+ // response never arrives, and makes Stripe replay its own refund
350
+ // instead of moving the funds again.
351
+ stripeKey: claimRef.id,
352
+ record: async (status, payload)=>{
353
+ await claimRef.set({
354
+ status: 'done',
355
+ responseStatus: status,
356
+ response: payload,
357
+ settledAtMs: Date.now()
358
+ }, {
359
+ merge: true
360
+ }).catch(()=>undefined);
361
+ },
362
+ release: async ()=>{
363
+ await claimRef.delete().catch(()=>undefined);
364
+ }
365
+ };
366
+ }
367
+ // RESERVE. The cap is read and written in one transaction, so two
368
+ // concurrent refunds cannot both see the same `refundedCents` — which is
369
+ // the whole failure the old ordering had, since it wrote the counter only
370
+ // after Stripe had already been asked to move the money. Reserving BEFORE
371
+ // the call rather than after also fails in the safe direction: a lost
372
+ // response leaves the amount counted, so the retry refunds less, never
373
+ // more.
374
+ let refundCents = 0;
375
+ let totalCents = 0;
376
+ await firestore.runTransaction(async (transaction)=>{
377
+ var _data, _ref, _fresh_amountCents, _fresh_refundedCents;
378
+ var _fresh_totals;
379
+ const fresh = CommerceModel.liftLegacyOrder((_data = (await transaction.get(orderRef)).data()) != null ? _data : {});
380
+ totalCents = (_ref = (_fresh_totals = fresh.totals) == null ? void 0 : _fresh_totals.totalCents) != null ? _ref : Number((_fresh_amountCents = fresh.amountCents) != null ? _fresh_amountCents : 0);
381
+ const alreadyRefunded = Number((_fresh_refundedCents = fresh.refundedCents) != null ? _fresh_refundedCents : 0);
382
+ const remaining = totalCents - alreadyRefunded;
383
+ // Named lines with no amount refund exactly what those lines are worth;
384
+ // named lines WITH an amount use the amount (already guarded above as
385
+ // no smaller than the lines). Neither is the whole order, which is what
386
+ // `amountCents == null` alone still means.
387
+ const asked = amountCents != null ? Math.round(amountCents) : requestedLineIds.length > 0 ? namedLinesCents : remaining;
388
+ refundCents = Math.min(asked, remaining);
389
+ if (!(refundCents > 0)) {
390
+ refundCents = 0;
391
+ return;
392
+ }
393
+ transaction.set(orderRef, {
394
+ refundedCents: alreadyRefunded + refundCents
395
+ }, {
396
+ merge: true
397
+ });
398
+ });
399
+ if (!(refundCents > 0)) {
400
+ // Nothing moved, so the attempt key is released rather than burned.
401
+ await (claim == null ? void 0 : claim.release());
402
+ return res.status(400).json({
403
+ error: 'Nothing left to refund'
404
+ });
405
+ }
406
+ // The cap bit into the named lines (AGL-2454): earlier partials have left
407
+ // less on this order than the selected lines are worth. REFUSED rather
408
+ // than refunded-and-revoked, because revoking a line for less than its
409
+ // value is precisely the silent over-revocation this issue forbids. The
410
+ // reservation is given back — the same compensation a Stripe refusal does
411
+ // below, and for the same reason: nothing has left the account yet.
412
+ if (requestedLineIds.length > 0 && refundCents < namedLinesCents) {
413
+ await firestore.runTransaction(async (transaction)=>{
414
+ var _get;
415
+ const current = Number((_get = (await transaction.get(orderRef)).get('refundedCents')) != null ? _get : 0);
416
+ transaction.set(orderRef, {
417
+ refundedCents: Math.max(0, current - refundCents)
418
+ }, {
419
+ merge: true
420
+ });
421
+ }).catch(()=>undefined);
422
+ await (claim == null ? void 0 : claim.release());
423
+ return res.status(409).json({
424
+ error: `Only $${(refundCents / 100).toFixed(2)} is left to refund on this ` + `order, and the lines you selected are worth $${(namedLinesCents / 100).toFixed(2)}. Refund an amount without selecting lines instead.`
425
+ });
426
+ }
427
+ const params = new URLSearchParams({
428
+ payment_intent: String(paymentIntentId),
429
+ amount: String(refundCents),
430
+ reverse_transfer: 'true',
431
+ refund_application_fee: 'true'
432
+ });
433
+ const response = await fetch('https://api.stripe.com/v1/refunds', {
434
+ method: 'POST',
435
+ headers: _extends({
436
+ Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}`,
437
+ 'Content-Type': 'application/x-www-form-urlencoded'
438
+ }, (claim == null ? void 0 : claim.stripeKey) ? {
439
+ 'Idempotency-Key': claim.stripeKey
440
+ } : {}),
441
+ body: params.toString()
442
+ });
443
+ const refund = await response.json();
444
+ if (!response.ok) {
445
+ var _ref2, _ref3;
446
+ var _refund_error, _refund_error1;
447
+ console.error('Stripe refund error', refund == null ? void 0 : refund.error);
448
+ // Stripe said no, so we KNOW no money moved: give the reservation back
449
+ // and let the same attempt be tried again.
450
+ await firestore.runTransaction(async (transaction)=>{
451
+ var _get;
452
+ const current = Number((_get = (await transaction.get(orderRef)).get('refundedCents')) != null ? _get : 0);
453
+ transaction.set(orderRef, {
454
+ refundedCents: Math.max(0, current - refundCents)
455
+ }, {
456
+ merge: true
457
+ });
458
+ }).catch(()=>undefined);
459
+ await (claim == null ? void 0 : claim.release());
460
+ // Stripe refusing BECAUSE OF A DISPUTE is the guard above arriving by
461
+ // the other door — our order document simply didn't know yet (webhook
462
+ // lag, or an order from before disputes were subscribed at all). Same
463
+ // answer, same accuracy: a 409 naming the dispute, not a 502 reading
464
+ // "The charge you're attempting to refund has been charged back", which
465
+ // an admin has no reason to connect to the Refund button they pressed.
466
+ const stripeCode = String((_ref2 = refund == null ? void 0 : (_refund_error = refund.error) == null ? void 0 : _refund_error.code) != null ? _ref2 : '');
467
+ if (stripeCode === 'charge_disputed' || stripeCode === 'refund_disputed_payment') {
468
+ return res.status(409).json({
469
+ error: 'Stripe refused this refund because the charge is disputed. ' + 'Respond to the dispute or accept it in the Stripe dashboard; ' + 'refund any remainder once it settles.'
470
+ });
471
+ }
472
+ return res.status(502).json({
473
+ error: (_ref3 = refund == null ? void 0 : (_refund_error1 = refund.error) == null ? void 0 : _refund_error1.message) != null ? _ref3 : 'Refund failed'
474
+ });
475
+ }
476
+ // SETTLE. Re-read inside the transaction: a concurrent partial may have
477
+ // reserved against the same order, and the timeline must be appended to
478
+ // whatever is there now rather than to the snapshot read at the top.
479
+ let refundedCents = 0;
480
+ let fullyRefunded = false;
481
+ let closedTheOrder = false;
482
+ await firestore.runTransaction(async (transaction)=>{
483
+ var _data, _fresh_refundedCents;
484
+ const fresh = CommerceModel.liftLegacyOrder((_data = (await transaction.get(orderRef)).data()) != null ? _data : {});
485
+ refundedCents = Number((_fresh_refundedCents = fresh.refundedCents) != null ? _fresh_refundedCents : 0);
486
+ fullyRefunded = refundedCents >= totalCents;
487
+ // Whether THIS settle moved the order into `refunded`, which is not the
488
+ // same question as whether the order is now fully refunded (AGL-1754).
489
+ // Two partials that between them close an order can both reserve before
490
+ // either settles, so both re-read the completed total and both compute
491
+ // `fullyRefunded`. Writing `status: 'refunded'` twice is harmless;
492
+ // incrementing a count twice is not. Reading the status inside the same
493
+ // transaction that writes it makes the flip observable exactly once.
494
+ closedTheOrder = fullyRefunded && fresh.status !== 'refunded';
495
+ transaction.set(orderRef, _extends({}, fullyRefunded ? {
496
+ status: 'refunded'
497
+ } : {}, requestedLineIds.length > 0 ? {
498
+ refundedLineItemIds: firebaseAdmin.firestore.FieldValue.arrayUnion(...requestedLineIds)
499
+ } : {}, {
500
+ timeline: CommerceModel.appendOrderEvent(fresh, 'refund', `$${(refundCents / 100).toFixed(2)} refunded` + (fullyRefunded ? ' (full)' : requestedLineIds.length > 0 ? ` — ${requestedLineIds.length} line${requestedLineIds.length === 1 ? '' : 's'} withdrawn` : ' — refunded by amount, no lines withdrawn'))
501
+ }), {
502
+ merge: true
503
+ });
504
+ });
505
+ const payload = {
506
+ refundedCents,
507
+ fullyRefunded
508
+ };
509
+ await (claim == null ? void 0 : claim.record(200, payload));
510
+ // LICENCE KEYS ARE RETIRED, NEVER RETURNED TO THE POOL (AGL-2454).
511
+ //
512
+ // `assignLicenseKeys` stamps `assignedAtMs`, `orderId` and `email` onto a
513
+ // pool document and nothing anywhere ever set them back — so a refunded
514
+ // order consumed the merchant's key forever, and a merchant who sold one
515
+ // key out of a hundred and refunded it had ninety-nine, permanently.
516
+ //
517
+ // Returning it to the pool is NOT the fix, and this is the decision the
518
+ // issue asked for: the key string was mailed in the receipt and cannot be
519
+ // invalidated by anything we own, so re-issuing it to the next paying
520
+ // customer would hand two people one working secret. That is worse than
521
+ // losing the key. A third state — retired: neither assigned to a live order
522
+ // nor available — is the honest record, and `revokedAtMs` already IS that
523
+ // state: the console's key dialog has written exactly this pair since it
524
+ // shipped, so this reuses the merchant's own vocabulary rather than
525
+ // inventing a second one.
526
+ //
527
+ // Best-effort and after the response is recorded, matching the contact and
528
+ // restock ledgers below: the money has moved and nothing here may fail a
529
+ // refund that already left the merchant's account.
530
+ await retireLicenseKeys(hostRef, orderRef, orderId);
531
+ // The customer's side of the ledger (AGL-1754). Everything above records
532
+ // the money on the ORDER; without this the buyer's `ltvCents` still counts
533
+ // a sale they returned, and only ever rises.
534
+ //
535
+ // Placed AFTER the attempt is recorded so a slow contacts write cannot
536
+ // strand the claim: a retry that arrives while this is in flight replays
537
+ // the recorded 200 instead of being turned away with "already being
538
+ // processed". Awaited rather than fired off with `void` — the handler is
539
+ // serverless, and work left running past the response is work the
540
+ // container may be frozen before it finishes. `recordContactRefund`
541
+ // swallows its own failures, so awaiting adds no way for this to fail a
542
+ // refund that has already left the merchant's account.
543
+ //
544
+ // Amount is THIS attempt's `refundCents`, already capped against what was
545
+ // left, so several partials sum to at most the order total — the same
546
+ // number the order's own `refundedCents` follows. The retried and racing
547
+ // cases need no key of their own: a keyed retry never reaches here (it
548
+ // replays at the claim), and a keyless one is a genuinely new refund that
549
+ // moved more money and should be counted.
550
+ await recordContactRefund({
551
+ hostId,
552
+ orderId,
553
+ email: order.customerEmail,
554
+ amountCents: refundCents,
555
+ closedTheOrder
556
+ });
557
+ /*
558
+ * The campaign's side of the same ledger.
559
+ *
560
+ * If a campaign was credited with this order, that credit is now partly
561
+ * or wholly wrong — a campaign cannot go on being paid for a sale the
562
+ * merchant reversed, and revenue attribution that only ever rises is the
563
+ * flattering half of a measurement. Recorded beside the gross rather than
564
+ * subtracted from it, for the reason `recordContactRefund` above records
565
+ * `refundedCents` beside `ltvCents`.
566
+ *
567
+ * Keyed by the ORDER and not by the buyer, so it needs no email and works
568
+ * for a guest checkout: the attribution record holds which campaign and
569
+ * which currency, and this reads them back. Same placement, same
570
+ * swallow-all contract and same awaited call as the two ledgers around
571
+ * it — nothing here may fail a refund that has already left the
572
+ * merchant's account.
573
+ */ await reverseEmailAttributedRevenue({
574
+ hostId,
575
+ orderId,
576
+ amountCents: refundCents,
577
+ closedTheOrder
578
+ });
579
+ // The shelf's side of the ledger (AGL-1797). The sale decremented variant
580
+ // inventory and nothing put it back, so a fully refunded order read one
581
+ // unit light forever. This FLAGS rather than releases — a refund with no
582
+ // return leaves the goods gone, and inventing stock the merchant does not
583
+ // have is worse than under-counting it — and the merchant answers from the
584
+ // stock adjustment they already have. Same placement and same swallow-all
585
+ // contract as the contact write above, for the same reason: the money has
586
+ // moved and the order records it, so nothing here may fail the refund.
587
+ await flagOrderRestock({
588
+ hostId,
589
+ orderId,
590
+ kind: 'refund',
591
+ closedTheOrder
592
+ });
593
+ return res.status(200).json(payload);
594
+ } catch (error) {
595
+ console.error(error);
596
+ // Deliberately NOT released, which is where this diverges from the POS
597
+ // sale path (AGL-1691). If the refund call threw we do not know whether
598
+ // Stripe moved the money, and the two failure directions are not
599
+ // symmetric: a stranded key costs a support ticket, a released one costs a
600
+ // second refund. The retry gets a 409 and a human reconciles.
601
+ return res.status(500).json({
602
+ error: 'Refund failed'
603
+ });
604
+ }
605
+ };
606
+
607
+ //# sourceMappingURL=refund.js.map