@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 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/model/commerce-dispute.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 type { HostOrder, OrderDispute } from './commerce-orders'\n\n/**\n * Reading a chargeback back out of an order (AGL-1796).\n *\n * AGL-1787 decided that a lost dispute leaves the order `status: 'refunded'`,\n * because five entitlement gates match that literal and a new status would\n * have escaped all of them. The cost of that decision is paid HERE: a merchant\n * opening the order sees \"Refunded\", the one word that says they chose it.\n * The distinction rides on the `dispute` record beside the status, and these\n * are the pure readers that turn it back into something a console can say.\n *\n * Kept out of `commerce-orders.ts` on the same principle the model directory\n * already follows — cart, discounts, shipping and tax each own a file — and\n * because this is presentation-shaped: it answers \"what should the merchant be\n * told\", not \"what is true of the order\".\n *\n * Dates render as `YYYY-MM-DD` through `toISOString`, which is what the\n * webhook's own timeline entries do. Deterministic, and the console shows\n * these strings beside those entries.\n */\n\n/**\n * Stripe dispute statuses that mean it is over.\n *\n * `warning_*` statuses belong to an inquiry that has not become a dispute yet;\n * `warning_closed` is the one that ends. The other `warning_*` values\n * (`warning_needs_response`, `warning_under_review`) are OPEN, which is why\n * this is a settled-list rather than a \"starts with warning\" test.\n */\nconst SETTLED_DISPUTE_STATUSES = new Set(['won', 'lost', 'warning_closed'])\n\n/** How the merchant should read a dispute at a glance. */\nexport type OrderDisputeTone = 'open' | 'lost' | 'won' | 'settled'\n\n/**\n * A dispute Stripe has not decided yet — the case with a DEADLINE attached.\n *\n * Three independent signals, all of which must say \"open\", because saying\n * \"evidence due\" about a settled dispute is the one error with a cost: it\n * sends a merchant to gather documents for a case that is closed. `outcome`\n * and `closedAtMs` are both written by `charge.dispute.closed` and `status` is\n * overwritten with the outcome, so a record that disagrees with itself is\n * malformed — and this resolves a malformed record to \"settled\", the answer\n * that cannot waste anyone's afternoon.\n *\n * Note `evidenceDueByMs` is NOT one of the signals: Stripe sends\n * `evidence_details.due_by` on the `closed` event too, so a closed dispute\n * still carries a deadline and testing for one would report every settled\n * dispute as open.\n */\nexport function isOrderDisputeOpen(dispute?: OrderDispute): boolean {\n if (!dispute) return false\n if (dispute.outcome) return false\n if (dispute.closedAtMs) return false\n return !SETTLED_DISPUTE_STATUSES.has(String(dispute.status ?? ''))\n}\n\n/** Whether this order has a dispute still running against it. */\nexport function orderHasOpenDispute(\n order: Pick<HostOrder, 'dispute'>,\n): boolean {\n return isOrderDisputeOpen(order?.dispute)\n}\n\n/**\n * The OPEN statuses that belong to an INQUIRY — the pre-dispute phase, where\n * no chargeback exists yet and no funds have been pulled.\n *\n * An explicit list rather than a \"starts with warning\" test, for the same\n * reason as `SETTLED_DISPUTE_STATUSES` above: `warning_closed` also starts\n * with `warning`, and an unknown future status must not be mistaken for a\n * refundable inquiry by its prefix.\n */\nconst OPEN_INQUIRY_STATUSES = new Set([\n 'warning_needs_response',\n 'warning_under_review',\n])\n\n/**\n * Whether a refund on this order must be REFUSED because of its dispute\n * (AGL-1809).\n *\n * Not the same question as `orderHasOpenDispute`, and the difference is the\n * whole decision. A formal open dispute (`needs_response`, `under_review`)\n * means the bank has already pulled the disputed funds and Stripe's refund\n * API refuses the charge outright (`charge_disputed` — \"The charge you're\n * attempting to refund has been charged back\"); a refund alongside it would\n * pay the shopper twice, once by the refund and once by the chargeback. An\n * open INQUIRY is the opposite case: no money has moved, Stripe permits the\n * refund, and its docs name \"issuing a full refund\" as the way to resolve an\n * inquiry before it escalates — refusing that would forbid the recommended\n * exit. Settled disputes refuse nothing here: a lost one already moved the\n * order to `refunded` (the status guard's job), and a won or closed one left\n * the charge refundable again.\n *\n * An open dispute whose status is unrecognised blocks — on a question of\n * sending money twice, an unknown state fails closed.\n */\nexport function orderDisputeBlocksRefund(\n order: Pick<HostOrder, 'dispute'>,\n): boolean {\n if (!orderHasOpenDispute(order)) return false\n return !OPEN_INQUIRY_STATUSES.has(String(order.dispute?.status ?? ''))\n}\n\n/** What the console renders beside an order's status when a dispute exists. */\nexport interface OrderDisputeBadge {\n tone: OrderDisputeTone\n /** Short chip label, e.g. `Chargeback open`, `Charged back`. */\n label: string\n /** A sentence for the tooltip: reason, amount, deadline or outcome. */\n detail: string\n /** The deadline, present ONLY while the dispute is open. */\n evidenceDueByMs?: number\n /**\n * Whole days until evidence is due, negative once the deadline has passed.\n * Present only alongside `evidenceDueByMs`.\n */\n evidenceDaysLeft?: number\n}\n\n/** `product_not_received` reads as `product not received`. */\nfunction humanReason(reason?: string): string {\n return String(reason ?? '')\n .replace(/_/g, ' ')\n .trim()\n}\n\nconst isoDay = (ms: number) => new Date(ms).toISOString().slice(0, 10)\n\nconst usd = (cents: number) => `$${(Math.max(0, cents) / 100).toFixed(2)}`\n\n/**\n * The badge for an order's dispute, or `null` when there is none.\n *\n * `nowMs` is a parameter rather than a `Date.now()` call so the deadline\n * arithmetic is testable without freezing the clock.\n */\nexport function describeOrderDispute(\n order: Pick<HostOrder, 'dispute'>,\n nowMs: number = Date.now(),\n): OrderDisputeBadge | null {\n const dispute = order?.dispute\n if (!dispute) return null\n const reason = humanReason(dispute.reason)\n const because = reason ? ` (${reason})` : ''\n\n if (isOrderDisputeOpen(dispute)) {\n const dueBy = Number(dispute.evidenceDueByMs ?? 0)\n // `Math.ceil` so a deadline eight hours away reads as \"1 day left\" rather\n // than \"0\" — rounding a live deadline down to zero reads as expired.\n const daysLeft =\n dueBy > 0 ? Math.ceil((dueBy - nowMs) / 86_400_000) : undefined\n return {\n tone: 'open',\n label: 'Chargeback open',\n detail:\n `${usd(dispute.amountCents)} disputed${because}, opened ` +\n `${isoDay(dispute.openedAtMs)}. ` +\n (dueBy > 0\n ? `Evidence is due to Stripe by ${isoDay(dueBy)}` +\n (daysLeft !== undefined && daysLeft >= 0\n ? ` — ${daysLeft} day${daysLeft === 1 ? '' : 's'} left.`\n : ' — that deadline has passed.')\n : 'Respond in the Stripe dashboard while the case is open.'),\n ...(dueBy > 0\n ? { evidenceDueByMs: dueBy, evidenceDaysLeft: daysLeft }\n : {}),\n }\n }\n\n const outcome = String(dispute.outcome ?? dispute.status ?? '')\n const closed = dispute.closedAtMs ? ` on ${isoDay(dispute.closedAtMs)}` : ''\n if (outcome === 'lost') {\n const reversed = Number(dispute.reversedCents ?? 0)\n return {\n tone: 'lost',\n label: 'Charged back',\n // The reversed figure can be LESS than the disputed one: AGL-1787 caps\n // the reversal against what is left, so a partly-refunded order loses\n // only the remainder. Saying only the disputed amount would overstate\n // what left the merchant's books.\n detail:\n `Dispute lost${closed}. ${usd(reversed)} was taken back` +\n `${because}` +\n (reversed < dispute.amountCents\n ? ` (of ${usd(dispute.amountCents)} disputed — the rest was already refunded).`\n : '.'),\n }\n }\n if (outcome === 'won') {\n return {\n tone: 'won',\n label: 'Dispute won',\n detail: `Dispute won${closed}${because} — no money was reversed.`,\n }\n }\n return {\n tone: 'settled',\n label: 'Dispute closed',\n detail:\n `Dispute closed${closed}${because}` +\n (outcome ? ` as ${humanReason(outcome)}` : '') +\n ' — no money was reversed.',\n }\n}\n\n/** What the orders list needs to raise the alarm, over a window of orders. */\nexport interface OpenDisputeSummary {\n /** Orders with a dispute still running. */\n count: number\n /** The soonest evidence deadline among them, when any carries one. */\n soonestDueByMs?: number\n /** Whole days to `soonestDueByMs`; negative once it has passed. */\n soonestDaysLeft?: number\n /** True when at least one deadline is already behind us. */\n overdue: boolean\n}\n\n/**\n * Count the open disputes in a window of orders and find the tightest\n * deadline (AGL-1796).\n *\n * A filter only helps a merchant who already suspects there is something to\n * filter FOR, and an evidence window is days long — so the orders list has to\n * say it unprompted. Computed over every loaded order rather than the visible\n * ones: a merchant filtered to \"delivered\" still needs to know a dispute is\n * running on a `paid` one.\n */\nexport function summariseOpenDisputes(\n orders: ReadonlyArray<Pick<HostOrder, 'dispute'>>,\n nowMs: number = Date.now(),\n): OpenDisputeSummary {\n let count = 0\n let soonestDueByMs: number | undefined\n for (const order of orders ?? []) {\n if (!orderHasOpenDispute(order)) continue\n count += 1\n const dueBy = Number(order.dispute?.evidenceDueByMs ?? 0)\n if (dueBy > 0 && (soonestDueByMs === undefined || dueBy < soonestDueByMs)) {\n soonestDueByMs = dueBy\n }\n }\n if (soonestDueByMs === undefined) return { count, overdue: false }\n const soonestDaysLeft = Math.ceil((soonestDueByMs - nowMs) / 86_400_000)\n return {\n count,\n soonestDueByMs,\n soonestDaysLeft,\n overdue: soonestDueByMs < nowMs,\n }\n}\n\n/** Money off this order, split by the door it left through. */\nexport interface OrderReversalSplit {\n /** Cents refunded by a decision the merchant made. */\n refundedCents: number\n /** Cents taken back by a lost chargeback. */\n chargedBackCents: number\n}\n\n/**\n * Split `order.refundedCents` into the part the merchant chose and the part\n * a chargeback took.\n *\n * AGL-1787 writes BOTH into `refundedCents`, deliberately — money reversed is\n * money reversed, and the CSV, the analytics card and the member drawer all\n * want the total. Only the label needs the split, and `dispute.reversedCents`\n * is the piece to subtract.\n *\n * The chargeback share is clamped to the recorded total, so a `reversedCents`\n * larger than `refundedCents` (which can only mean the two fields disagree)\n * yields a zero refund line rather than a negative one.\n */\nexport function splitOrderReversal(\n order: Pick<HostOrder, 'refundedCents' | 'dispute'>,\n): OrderReversalSplit {\n const total = Math.max(0, Number(order?.refundedCents ?? 0) || 0)\n const chargedBackCents = Math.min(\n total,\n Math.max(0, Number(order?.dispute?.reversedCents ?? 0) || 0),\n )\n return { refundedCents: total - chargedBackCents, chargedBackCents }\n}\n"],"names":["SETTLED_DISPUTE_STATUSES","Set","isOrderDisputeOpen","dispute","outcome","closedAtMs","has","String","status","orderHasOpenDispute","order","OPEN_INQUIRY_STATUSES","orderDisputeBlocksRefund","humanReason","reason","replace","trim","isoDay","ms","Date","toISOString","slice","usd","cents","Math","max","toFixed","describeOrderDispute","nowMs","now","because","dueBy","Number","evidenceDueByMs","daysLeft","ceil","undefined","tone","label","detail","amountCents","openedAtMs","evidenceDaysLeft","closed","reversed","reversedCents","summariseOpenDisputes","orders","count","soonestDueByMs","overdue","soonestDaysLeft","splitOrderReversal","total","refundedCents","chargedBackCents","min"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAID;;;;;;;;;;;;;;;;;;CAkBC,GAED;;;;;;;CAOC,GACD,MAAMA,2BAA2B,IAAIC,IAAI;IAAC;IAAO;IAAQ;CAAiB;AAK1E;;;;;;;;;;;;;;;CAeC,GACD,OAAO,SAASC,mBAAmBC,OAAsB;QAIXA;IAH5C,IAAI,CAACA,SAAS,OAAO;IACrB,IAAIA,QAAQC,OAAO,EAAE,OAAO;IAC5B,IAAID,QAAQE,UAAU,EAAE,OAAO;IAC/B,OAAO,CAACL,yBAAyBM,GAAG,CAACC,QAAOJ,kBAAAA,QAAQK,MAAM,YAAdL,kBAAkB;AAChE;AAEA,+DAA+D,GAC/D,OAAO,SAASM,oBACdC,KAAiC;IAEjC,OAAOR,mBAAmBQ,yBAAAA,MAAOP,OAAO;AAC1C;AAEA;;;;;;;;CAQC,GACD,MAAMQ,wBAAwB,IAAIV,IAAI;IACpC;IACA;CACD;AAED;;;;;;;;;;;;;;;;;;;CAmBC,GACD,OAAO,SAASW,yBACdF,KAAiC;;QAGQA;IADzC,IAAI,CAACD,oBAAoBC,QAAQ,OAAO;IACxC,OAAO,CAACC,sBAAsBL,GAAG,CAACC,gBAAOG,iBAAAA,MAAMP,OAAO,qBAAbO,eAAeF,MAAM,mBAAI;AACpE;AAkBA,4DAA4D,GAC5D,SAASK,YAAYC,MAAe;IAClC,OAAOP,OAAOO,iBAAAA,SAAU,IACrBC,OAAO,CAAC,MAAM,KACdC,IAAI;AACT;AAEA,MAAMC,SAAS,CAACC,KAAe,IAAIC,KAAKD,IAAIE,WAAW,GAAGC,KAAK,CAAC,GAAG;AAEnE,MAAMC,MAAM,CAACC,QAAkB,CAAC,CAAC,EAAE,AAACC,CAAAA,KAAKC,GAAG,CAAC,GAAGF,SAAS,GAAE,EAAGG,OAAO,CAAC,IAAI;AAE1E;;;;;CAKC,GACD,OAAO,SAASC,qBACdjB,KAAiC,EACjCkB,QAAgBT,KAAKU,GAAG,EAAE;QA+BH1B,MAAAA;IA7BvB,MAAMA,UAAUO,yBAAAA,MAAOP,OAAO;IAC9B,IAAI,CAACA,SAAS,OAAO;IACrB,MAAMW,SAASD,YAAYV,QAAQW,MAAM;IACzC,MAAMgB,UAAUhB,SAAS,CAAC,EAAE,EAAEA,OAAO,CAAC,CAAC,GAAG;IAE1C,IAAIZ,mBAAmBC,UAAU;YACVA;QAArB,MAAM4B,QAAQC,QAAO7B,2BAAAA,QAAQ8B,eAAe,YAAvB9B,2BAA2B;QAChD,0EAA0E;QAC1E,qEAAqE;QACrE,MAAM+B,WACJH,QAAQ,IAAIP,KAAKW,IAAI,CAAC,AAACJ,CAAAA,QAAQH,KAAI,IAAK,YAAcQ;QACxD,OAAO;YACLC,MAAM;YACNC,OAAO;YACPC,QACE,GAAGjB,IAAInB,QAAQqC,WAAW,EAAE,SAAS,EAAEV,QAAQ,SAAS,CAAC,GACzD,GAAGb,OAAOd,QAAQsC,UAAU,EAAE,EAAE,CAAC,GAChCV,CAAAA,QAAQ,IACL,CAAC,6BAA6B,EAAEd,OAAOc,QAAQ,GAC9CG,CAAAA,aAAaE,aAAaF,YAAY,IACnC,CAAC,GAAG,EAAEA,SAAS,IAAI,EAAEA,aAAa,IAAI,KAAK,IAAI,MAAM,CAAC,GACtD,8BAA6B,IACjC,yDAAwD;WAC1DH,QAAQ,IACR;YAAEE,iBAAiBF;YAAOW,kBAAkBR;QAAS,IACrD,CAAC;IAET;IAEA,MAAM9B,UAAUG,QAAOJ,QAAAA,mBAAAA,QAAQC,OAAO,YAAfD,mBAAmBA,QAAQK,MAAM,YAAjCL,OAAqC;IAC5D,MAAMwC,SAASxC,QAAQE,UAAU,GAAG,CAAC,IAAI,EAAEY,OAAOd,QAAQE,UAAU,GAAG,GAAG;IAC1E,IAAID,YAAY,QAAQ;YACED;QAAxB,MAAMyC,WAAWZ,QAAO7B,yBAAAA,QAAQ0C,aAAa,YAArB1C,yBAAyB;QACjD,OAAO;YACLkC,MAAM;YACNC,OAAO;YACP,uEAAuE;YACvE,sEAAsE;YACtE,sEAAsE;YACtE,kCAAkC;YAClCC,QACE,CAAC,YAAY,EAAEI,OAAO,EAAE,EAAErB,IAAIsB,UAAU,eAAe,CAAC,GACxD,GAAGd,SAAS,GACXc,CAAAA,WAAWzC,QAAQqC,WAAW,GAC3B,CAAC,KAAK,EAAElB,IAAInB,QAAQqC,WAAW,EAAE,2CAA2C,CAAC,GAC7E,GAAE;QACV;IACF;IACA,IAAIpC,YAAY,OAAO;QACrB,OAAO;YACLiC,MAAM;YACNC,OAAO;YACPC,QAAQ,CAAC,WAAW,EAAEI,SAASb,QAAQ,yBAAyB,CAAC;QACnE;IACF;IACA,OAAO;QACLO,MAAM;QACNC,OAAO;QACPC,QACE,CAAC,cAAc,EAAEI,SAASb,SAAS,GAClC1B,CAAAA,UAAU,CAAC,IAAI,EAAES,YAAYT,UAAU,GAAG,EAAC,IAC5C;IACJ;AACF;AAcA;;;;;;;;;CASC,GACD,OAAO,SAAS0C,sBACdC,MAAiD,EACjDnB,QAAgBT,KAAKU,GAAG,EAAE;IAE1B,IAAImB,QAAQ;IACZ,IAAIC;IACJ,KAAK,MAAMvC,SAASqC,iBAAAA,SAAU,EAAE,CAAE;;YAGXrC;QAFrB,IAAI,CAACD,oBAAoBC,QAAQ;QACjCsC,SAAS;QACT,MAAMjB,QAAQC,gBAAOtB,iBAAAA,MAAMP,OAAO,qBAAbO,eAAeuB,eAAe,mBAAI;QACvD,IAAIF,QAAQ,KAAMkB,CAAAA,mBAAmBb,aAAaL,QAAQkB,cAAa,GAAI;YACzEA,iBAAiBlB;QACnB;IACF;IACA,IAAIkB,mBAAmBb,WAAW,OAAO;QAAEY;QAAOE,SAAS;IAAM;IACjE,MAAMC,kBAAkB3B,KAAKW,IAAI,CAAC,AAACc,CAAAA,iBAAiBrB,KAAI,IAAK;IAC7D,OAAO;QACLoB;QACAC;QACAE;QACAD,SAASD,iBAAiBrB;IAC5B;AACF;AAUA;;;;;;;;;;;;CAYC,GACD,OAAO,SAASwB,mBACd1C,KAAmD;;QAK9BA;IAHrB,MAAM2C,QAAQ7B,KAAKC,GAAG,CAAC,GAAGO,eAAOtB,yBAAAA,MAAO4C,aAAa,mBAAI,MAAM;IAC/D,MAAMC,mBAAmB/B,KAAKgC,GAAG,CAC/BH,OACA7B,KAAKC,GAAG,CAAC,GAAGO,gBAAOtB,0BAAAA,iBAAAA,MAAOP,OAAO,qBAAdO,eAAgBmC,aAAa,oBAAI,MAAM;IAE5D,OAAO;QAAES,eAAeD,QAAQE;QAAkBA;IAAiB;AACrE"}
@@ -0,0 +1,107 @@
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
+ * Gift-card hold arithmetic (AGL-2449).
19
+ *
20
+ * A gift card is CASH, and until this module existed it was the one limited
21
+ * resource in the order path with no reserve at all. `cart-checkout.ts` read
22
+ * `balanceCents` with a plain `.get()`, minted a Stripe coupon for that much,
23
+ * and the webhook decremented the card minutes later with a bare
24
+ * `FieldValue.increment(-N)`. The increment is atomic, so nothing was ever
25
+ * LOST — but nothing ever CHECKED either, so two checkouts entering the same
26
+ * code both read $50, both got $50 off, and the card settled at `-$50`. The
27
+ * merchant shipped $100 of goods against a $50 card, and the outstanding
28
+ * liability total went negative — the exact corruption `redeemExistingOrRecord`
29
+ * already reasons about for a DELETED card, arriving through a live one.
30
+ *
31
+ * The stock fix (AGL-2320) could not be copied here: stock is decremented after
32
+ * the money has moved and therefore cannot refuse, so it locks and reports the
33
+ * shortfall. A gift card is applied BEFORE Stripe is contacted, so this door can
34
+ * still say no — and refusing is the only thing that actually keeps the money.
35
+ *
36
+ * So the balance is HELD at checkout and SETTLED at the webhook, both in one
37
+ * transaction against one document. Holds live in a map on the card itself
38
+ * keyed by Stripe session id, which is what keeps this to a single-document
39
+ * transaction: no fan-out, no second collection, no index.
40
+ *
41
+ * ## Why holds expire rather than being swept
42
+ *
43
+ * An abandoned checkout must not stand a customer's money off indefinitely, and
44
+ * a sweep job is the wrong instrument: `process-abandoned.ts` is the only
45
+ * existing sweep and it returns 501 when SMTP is unconfigured, so a
46
+ * release that depended on it would not run at all for a self-hosted store with
47
+ * no mail transport. Instead every hold carries `expiresAtMs` and EVERY read
48
+ * prunes, so the release is a consequence of the next read rather than of a job
49
+ * that may never run. A card nobody touches again holds nothing that matters,
50
+ * because nobody is reading it either.
51
+ *
52
+ * The TTL matches Stripe's Checkout Session lifetime rather than something
53
+ * shorter. A hold that lapsed while its session was still payable would reopen
54
+ * the very window this closes — the shopper pays a session whose hold has
55
+ * evaporated and the balance is spent twice again.
56
+ */
57
+ /** One in-flight claim on a card's balance, keyed by Stripe session id. */
58
+ export interface GiftCardHold {
59
+ cents: number;
60
+ expiresAtMs: number;
61
+ }
62
+ /** `hosts/{hostId}/giftCards/{code}` doc, as far as redemption cares. */
63
+ export interface HostGiftCard {
64
+ balanceCents?: number;
65
+ /** Session id → hold. Absent on every card issued before AGL-2449. */
66
+ holds?: Record<string, GiftCardHold>;
67
+ voidedAtMs?: number;
68
+ }
69
+ /**
70
+ * Stripe Checkout Sessions expire 24h after creation, so a hold outlives any
71
+ * session that can still be paid. See the module docblock for why a shorter
72
+ * TTL is not the safer choice it looks like.
73
+ */
74
+ export declare const GIFT_CARD_HOLD_TTL_MS: number;
75
+ /**
76
+ * The card's holds with the lapsed ones dropped.
77
+ *
78
+ * Total, not a filter over a trusted shape: a hold whose `expiresAtMs` is
79
+ * absent or non-numeric is treated as EXPIRED rather than eternal, so a
80
+ * malformed row releases the money instead of stranding it. The one direction
81
+ * that cannot be wrong is the one that keeps a customer from spending their own
82
+ * balance forever.
83
+ */
84
+ export declare function pruneGiftCardHolds(holds: Record<string, GiftCardHold> | undefined, nowMs: number): Record<string, GiftCardHold>;
85
+ /**
86
+ * What a NEW checkout may apply: the balance less every hold still standing.
87
+ *
88
+ * Never negative. A card whose holds already exceed its balance (possible only
89
+ * on a card voided mid-flight, where the console zeroes `balanceCents` while
90
+ * holds stand) reads as empty rather than as a debt to be collected.
91
+ */
92
+ export declare function giftCardAvailableCents(card: HostGiftCard | undefined, nowMs: number): number;
93
+ /**
94
+ * What settling `sessionId` should actually take off the card.
95
+ *
96
+ * Capped at the live balance, not at the hold, and that is the point of the
97
+ * function. The hold is what this session RESERVED; the balance is what the
98
+ * card can still give up. They diverge when the card was voided or hand-adjusted
99
+ * between the hold and the payment, and in that window paying out the hold would
100
+ * drive the balance negative — reintroducing the corrupted liability aggregate
101
+ * from the other side.
102
+ *
103
+ * A session with no hold settles ZERO. That is the redelivery case (the first
104
+ * delivery consumed it) and the pre-AGL-2449 case (a session that predates
105
+ * holds), and both must be no-ops rather than a second decrement.
106
+ */
107
+ export declare function giftCardSettlementCents(card: HostGiftCard | undefined, sessionId: string, _nowMs: number): number;
@@ -0,0 +1,121 @@
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
+ * Gift-card hold arithmetic (AGL-2449).
18
+ *
19
+ * A gift card is CASH, and until this module existed it was the one limited
20
+ * resource in the order path with no reserve at all. `cart-checkout.ts` read
21
+ * `balanceCents` with a plain `.get()`, minted a Stripe coupon for that much,
22
+ * and the webhook decremented the card minutes later with a bare
23
+ * `FieldValue.increment(-N)`. The increment is atomic, so nothing was ever
24
+ * LOST — but nothing ever CHECKED either, so two checkouts entering the same
25
+ * code both read $50, both got $50 off, and the card settled at `-$50`. The
26
+ * merchant shipped $100 of goods against a $50 card, and the outstanding
27
+ * liability total went negative — the exact corruption `redeemExistingOrRecord`
28
+ * already reasons about for a DELETED card, arriving through a live one.
29
+ *
30
+ * The stock fix (AGL-2320) could not be copied here: stock is decremented after
31
+ * the money has moved and therefore cannot refuse, so it locks and reports the
32
+ * shortfall. A gift card is applied BEFORE Stripe is contacted, so this door can
33
+ * still say no — and refusing is the only thing that actually keeps the money.
34
+ *
35
+ * So the balance is HELD at checkout and SETTLED at the webhook, both in one
36
+ * transaction against one document. Holds live in a map on the card itself
37
+ * keyed by Stripe session id, which is what keeps this to a single-document
38
+ * transaction: no fan-out, no second collection, no index.
39
+ *
40
+ * ## Why holds expire rather than being swept
41
+ *
42
+ * An abandoned checkout must not stand a customer's money off indefinitely, and
43
+ * a sweep job is the wrong instrument: `process-abandoned.ts` is the only
44
+ * existing sweep and it returns 501 when SMTP is unconfigured, so a
45
+ * release that depended on it would not run at all for a self-hosted store with
46
+ * no mail transport. Instead every hold carries `expiresAtMs` and EVERY read
47
+ * prunes, so the release is a consequence of the next read rather than of a job
48
+ * that may never run. A card nobody touches again holds nothing that matters,
49
+ * because nobody is reading it either.
50
+ *
51
+ * The TTL matches Stripe's Checkout Session lifetime rather than something
52
+ * shorter. A hold that lapsed while its session was still payable would reopen
53
+ * the very window this closes — the shopper pays a session whose hold has
54
+ * evaporated and the balance is spent twice again.
55
+ */ /** One in-flight claim on a card's balance, keyed by Stripe session id. */ /**
56
+ * Stripe Checkout Sessions expire 24h after creation, so a hold outlives any
57
+ * session that can still be paid. See the module docblock for why a shorter
58
+ * TTL is not the safer choice it looks like.
59
+ */ export const GIFT_CARD_HOLD_TTL_MS = 24 * 60 * 60 * 1000;
60
+ /** One money figure off an untrusted document, as whole non-negative cents. */ function cents(value) {
61
+ const number = Math.round(Number(value));
62
+ return Number.isFinite(number) && number > 0 ? number : 0;
63
+ }
64
+ /**
65
+ * The card's holds with the lapsed ones dropped.
66
+ *
67
+ * Total, not a filter over a trusted shape: a hold whose `expiresAtMs` is
68
+ * absent or non-numeric is treated as EXPIRED rather than eternal, so a
69
+ * malformed row releases the money instead of stranding it. The one direction
70
+ * that cannot be wrong is the one that keeps a customer from spending their own
71
+ * balance forever.
72
+ */ export function pruneGiftCardHolds(holds, nowMs) {
73
+ const live = {};
74
+ for (const [sessionId, hold] of Object.entries(holds != null ? holds : {})){
75
+ const expiresAtMs = Number(hold == null ? void 0 : hold.expiresAtMs);
76
+ if (!Number.isFinite(expiresAtMs) || expiresAtMs <= nowMs) continue;
77
+ const amount = cents(hold == null ? void 0 : hold.cents);
78
+ if (amount > 0) live[sessionId] = {
79
+ cents: amount,
80
+ expiresAtMs
81
+ };
82
+ }
83
+ return live;
84
+ }
85
+ /**
86
+ * What a NEW checkout may apply: the balance less every hold still standing.
87
+ *
88
+ * Never negative. A card whose holds already exceed its balance (possible only
89
+ * on a card voided mid-flight, where the console zeroes `balanceCents` while
90
+ * holds stand) reads as empty rather than as a debt to be collected.
91
+ */ export function giftCardAvailableCents(card, nowMs) {
92
+ const held = Object.values(pruneGiftCardHolds(card == null ? void 0 : card.holds, nowMs)).reduce((sum, hold)=>sum + hold.cents, 0);
93
+ return Math.max(0, cents(card == null ? void 0 : card.balanceCents) - held);
94
+ }
95
+ /**
96
+ * What settling `sessionId` should actually take off the card.
97
+ *
98
+ * Capped at the live balance, not at the hold, and that is the point of the
99
+ * function. The hold is what this session RESERVED; the balance is what the
100
+ * card can still give up. They diverge when the card was voided or hand-adjusted
101
+ * between the hold and the payment, and in that window paying out the hold would
102
+ * drive the balance negative — reintroducing the corrupted liability aggregate
103
+ * from the other side.
104
+ *
105
+ * A session with no hold settles ZERO. That is the redelivery case (the first
106
+ * delivery consumed it) and the pre-AGL-2449 case (a session that predates
107
+ * holds), and both must be no-ops rather than a second decrement.
108
+ */ export function giftCardSettlementCents(card, sessionId, // Deliberately unused, and kept so this reads as the sibling of
109
+ // `giftCardAvailableCents` at every call site. The asymmetry IS the rule
110
+ // below: availability is a question about now, settlement is not.
111
+ _nowMs) {
112
+ var _ref;
113
+ // NOT pruned: a hold that lapsed while its session sat unpaid is still owed
114
+ // once that session is paid. Expiry governs what a NEW checkout may claim,
115
+ // never whether a completed payment is honoured — dropping it here would take
116
+ // the discount from the shopper and give nothing back to the merchant.
117
+ const hold = ((_ref = card == null ? void 0 : card.holds) != null ? _ref : {})[sessionId];
118
+ return Math.min(cents(hold == null ? void 0 : hold.cents), cents(card == null ? void 0 : card.balanceCents));
119
+ }
120
+
121
+ //# sourceMappingURL=commerce-gift-cards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/model/commerce-gift-cards.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Gift-card hold arithmetic (AGL-2449).\n *\n * A gift card is CASH, and until this module existed it was the one limited\n * resource in the order path with no reserve at all. `cart-checkout.ts` read\n * `balanceCents` with a plain `.get()`, minted a Stripe coupon for that much,\n * and the webhook decremented the card minutes later with a bare\n * `FieldValue.increment(-N)`. The increment is atomic, so nothing was ever\n * LOST — but nothing ever CHECKED either, so two checkouts entering the same\n * code both read $50, both got $50 off, and the card settled at `-$50`. The\n * merchant shipped $100 of goods against a $50 card, and the outstanding\n * liability total went negative — the exact corruption `redeemExistingOrRecord`\n * already reasons about for a DELETED card, arriving through a live one.\n *\n * The stock fix (AGL-2320) could not be copied here: stock is decremented after\n * the money has moved and therefore cannot refuse, so it locks and reports the\n * shortfall. A gift card is applied BEFORE Stripe is contacted, so this door can\n * still say no — and refusing is the only thing that actually keeps the money.\n *\n * So the balance is HELD at checkout and SETTLED at the webhook, both in one\n * transaction against one document. Holds live in a map on the card itself\n * keyed by Stripe session id, which is what keeps this to a single-document\n * transaction: no fan-out, no second collection, no index.\n *\n * ## Why holds expire rather than being swept\n *\n * An abandoned checkout must not stand a customer's money off indefinitely, and\n * a sweep job is the wrong instrument: `process-abandoned.ts` is the only\n * existing sweep and it returns 501 when SMTP is unconfigured, so a\n * release that depended on it would not run at all for a self-hosted store with\n * no mail transport. Instead every hold carries `expiresAtMs` and EVERY read\n * prunes, so the release is a consequence of the next read rather than of a job\n * that may never run. A card nobody touches again holds nothing that matters,\n * because nobody is reading it either.\n *\n * The TTL matches Stripe's Checkout Session lifetime rather than something\n * shorter. A hold that lapsed while its session was still payable would reopen\n * the very window this closes — the shopper pays a session whose hold has\n * evaporated and the balance is spent twice again.\n */\n\n/** One in-flight claim on a card's balance, keyed by Stripe session id. */\nexport interface GiftCardHold {\n cents: number\n expiresAtMs: number\n}\n\n/** `hosts/{hostId}/giftCards/{code}` doc, as far as redemption cares. */\nexport interface HostGiftCard {\n balanceCents?: number\n /** Session id → hold. Absent on every card issued before AGL-2449. */\n holds?: Record<string, GiftCardHold>\n voidedAtMs?: number\n}\n\n/**\n * Stripe Checkout Sessions expire 24h after creation, so a hold outlives any\n * session that can still be paid. See the module docblock for why a shorter\n * TTL is not the safer choice it looks like.\n */\nexport const GIFT_CARD_HOLD_TTL_MS = 24 * 60 * 60 * 1000\n\n/** One money figure off an untrusted document, as whole non-negative cents. */\nfunction cents(value: unknown): number {\n const number = Math.round(Number(value))\n return Number.isFinite(number) && number > 0 ? number : 0\n}\n\n/**\n * The card's holds with the lapsed ones dropped.\n *\n * Total, not a filter over a trusted shape: a hold whose `expiresAtMs` is\n * absent or non-numeric is treated as EXPIRED rather than eternal, so a\n * malformed row releases the money instead of stranding it. The one direction\n * that cannot be wrong is the one that keeps a customer from spending their own\n * balance forever.\n */\nexport function pruneGiftCardHolds(\n holds: Record<string, GiftCardHold> | undefined,\n nowMs: number,\n): Record<string, GiftCardHold> {\n const live: Record<string, GiftCardHold> = {}\n for (const [sessionId, hold] of Object.entries(holds ?? {})) {\n const expiresAtMs = Number(hold?.expiresAtMs)\n if (!Number.isFinite(expiresAtMs) || expiresAtMs <= nowMs) continue\n const amount = cents(hold?.cents)\n if (amount > 0) live[sessionId] = { cents: amount, expiresAtMs }\n }\n return live\n}\n\n/**\n * What a NEW checkout may apply: the balance less every hold still standing.\n *\n * Never negative. A card whose holds already exceed its balance (possible only\n * on a card voided mid-flight, where the console zeroes `balanceCents` while\n * holds stand) reads as empty rather than as a debt to be collected.\n */\nexport function giftCardAvailableCents(\n card: HostGiftCard | undefined,\n nowMs: number,\n): number {\n const held = Object.values(pruneGiftCardHolds(card?.holds, nowMs)).reduce(\n (sum, hold) => sum + hold.cents,\n 0,\n )\n return Math.max(0, cents(card?.balanceCents) - held)\n}\n\n/**\n * What settling `sessionId` should actually take off the card.\n *\n * Capped at the live balance, not at the hold, and that is the point of the\n * function. The hold is what this session RESERVED; the balance is what the\n * card can still give up. They diverge when the card was voided or hand-adjusted\n * between the hold and the payment, and in that window paying out the hold would\n * drive the balance negative — reintroducing the corrupted liability aggregate\n * from the other side.\n *\n * A session with no hold settles ZERO. That is the redelivery case (the first\n * delivery consumed it) and the pre-AGL-2449 case (a session that predates\n * holds), and both must be no-ops rather than a second decrement.\n */\nexport function giftCardSettlementCents(\n card: HostGiftCard | undefined,\n sessionId: string,\n // Deliberately unused, and kept so this reads as the sibling of\n // `giftCardAvailableCents` at every call site. The asymmetry IS the rule\n // below: availability is a question about now, settlement is not.\n _nowMs: number,\n): number {\n // NOT pruned: a hold that lapsed while its session sat unpaid is still owed\n // once that session is paid. Expiry governs what a NEW checkout may claim,\n // never whether a completed payment is honoured — dropping it here would take\n // the discount from the shopper and give nothing back to the merchant.\n const hold = (card?.holds ?? {})[sessionId]\n return Math.min(cents(hold?.cents), cents(card?.balanceCents))\n}\n"],"names":["GIFT_CARD_HOLD_TTL_MS","cents","value","number","Math","round","Number","isFinite","pruneGiftCardHolds","holds","nowMs","live","sessionId","hold","Object","entries","expiresAtMs","amount","giftCardAvailableCents","card","held","values","reduce","sum","max","balanceCents","giftCardSettlementCents","_nowMs","min"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCC,GAED,yEAAyE,GAczE;;;;CAIC,GACD,OAAO,MAAMA,wBAAwB,KAAK,KAAK,KAAK,KAAI;AAExD,6EAA6E,GAC7E,SAASC,MAAMC,KAAc;IAC3B,MAAMC,SAASC,KAAKC,KAAK,CAACC,OAAOJ;IACjC,OAAOI,OAAOC,QAAQ,CAACJ,WAAWA,SAAS,IAAIA,SAAS;AAC1D;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASK,mBACdC,KAA+C,EAC/CC,KAAa;IAEb,MAAMC,OAAqC,CAAC;IAC5C,KAAK,MAAM,CAACC,WAAWC,KAAK,IAAIC,OAAOC,OAAO,CAACN,gBAAAA,QAAS,CAAC,GAAI;QAC3D,MAAMO,cAAcV,OAAOO,wBAAAA,KAAMG,WAAW;QAC5C,IAAI,CAACV,OAAOC,QAAQ,CAACS,gBAAgBA,eAAeN,OAAO;QAC3D,MAAMO,SAAShB,MAAMY,wBAAAA,KAAMZ,KAAK;QAChC,IAAIgB,SAAS,GAAGN,IAAI,CAACC,UAAU,GAAG;YAAEX,OAAOgB;YAAQD;QAAY;IACjE;IACA,OAAOL;AACT;AAEA;;;;;;CAMC,GACD,OAAO,SAASO,uBACdC,IAA8B,EAC9BT,KAAa;IAEb,MAAMU,OAAON,OAAOO,MAAM,CAACb,mBAAmBW,wBAAAA,KAAMV,KAAK,EAAEC,QAAQY,MAAM,CACvE,CAACC,KAAKV,OAASU,MAAMV,KAAKZ,KAAK,EAC/B;IAEF,OAAOG,KAAKoB,GAAG,CAAC,GAAGvB,MAAMkB,wBAAAA,KAAMM,YAAY,IAAIL;AACjD;AAEA;;;;;;;;;;;;;CAaC,GACD,OAAO,SAASM,wBACdP,IAA8B,EAC9BP,SAAiB,EACjB,gEAAgE;AAChE,yEAAyE;AACzE,kEAAkE;AAClEe,MAAc;;IAEd,4EAA4E;IAC5E,2EAA2E;IAC3E,8EAA8E;IAC9E,uEAAuE;IACvE,MAAMd,OAAO,SAACM,wBAAAA,KAAMV,KAAK,mBAAI,CAAC,EAAE,CAACG,UAAU;IAC3C,OAAOR,KAAKwB,GAAG,CAAC3B,MAAMY,wBAAAA,KAAMZ,KAAK,GAAGA,MAAMkB,wBAAAA,KAAMM,YAAY;AAC9D"}
@@ -0,0 +1,36 @@
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
+ * Catalog CSV import/export (AGL-282) speaking Shopify's product CSV
19
+ * dialect — the migration wedge for switchers: `Handle` groups variant
20
+ * rows into one product, `Option1..3 Name/Value` build the option axes,
21
+ * `Variant *` columns carry per-variant data, and repeated-handle rows
22
+ * with only `Image Src` add media. Export mirrors the same columns so
23
+ * round-trips are lossless for the fields both sides share.
24
+ */
25
+ import { type HostProduct } from './commerce';
26
+ export declare const PRODUCT_CSV_HEADER: readonly ["Handle", "Title", "Body (HTML)", "Type", "Tags", "Published", "Option1 Name", "Option1 Value", "Option2 Name", "Option2 Value", "Option3 Name", "Option3 Value", "Variant SKU", "Variant Barcode", "Variant Price", "Variant Compare At Price", "Variant Inventory Qty", "Variant Grams", "Image Src"];
27
+ /** One row per variant; extra image rows follow Shopify's convention. */
28
+ export declare function productsToCsv(products: Array<HostProduct & {
29
+ $id?: string;
30
+ }>): string;
31
+ export interface ProductCsvImport {
32
+ products: HostProduct[];
33
+ /** Row-anchored problems; importable products still parse. */
34
+ errors: string[];
35
+ }
36
+ export declare function parseProductsCsv(text: string): ProductCsvImport;
@@ -0,0 +1,245 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ /**
18
+ * Catalog CSV import/export (AGL-282) speaking Shopify's product CSV
19
+ * dialect — the migration wedge for switchers: `Handle` groups variant
20
+ * rows into one product, `Option1..3 Name/Value` build the option axes,
21
+ * `Variant *` columns carry per-variant data, and repeated-handle rows
22
+ * with only `Image Src` add media. Export mirrors the same columns so
23
+ * round-trips are lossless for the fields both sides share.
24
+ */ import { commerceSlug, validateProduct } from "./commerce.js";
25
+ import { parseCsv } from "@aglyn/aglyn/app-utils/dataset-csv";
26
+ export const PRODUCT_CSV_HEADER = [
27
+ 'Handle',
28
+ 'Title',
29
+ 'Body (HTML)',
30
+ 'Type',
31
+ 'Tags',
32
+ 'Published',
33
+ 'Option1 Name',
34
+ 'Option1 Value',
35
+ 'Option2 Name',
36
+ 'Option2 Value',
37
+ 'Option3 Name',
38
+ 'Option3 Value',
39
+ 'Variant SKU',
40
+ 'Variant Barcode',
41
+ 'Variant Price',
42
+ 'Variant Compare At Price',
43
+ 'Variant Inventory Qty',
44
+ 'Variant Grams',
45
+ 'Image Src'
46
+ ];
47
+ function csvCell(value) {
48
+ const text = value == null ? '' : String(value);
49
+ return /[",\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
50
+ }
51
+ /** One row per variant; extra image rows follow Shopify's convention. */ export function productsToCsv(products) {
52
+ const lines = [
53
+ PRODUCT_CSV_HEADER.join(',')
54
+ ];
55
+ for (const product of products){
56
+ var _product_options, _product_mediaUrls;
57
+ const options = (_product_options = product.options) != null ? _product_options : [];
58
+ product.variants.forEach((variant, index)=>{
59
+ var _product_description, _product_tags, _variant_sku, _variant_barcode, _variant_compareAtPriceUsd, _variant_inventory, _variant_weightGrams, _ref;
60
+ var _product_mediaUrls;
61
+ const optionCells = [];
62
+ for(let axis = 0; axis < 3; axis += 1){
63
+ var _ref1, _ref2;
64
+ var _variant_options;
65
+ const option = options[axis];
66
+ optionCells.push(index === 0 ? (_ref1 = option == null ? void 0 : option.name) != null ? _ref1 : '' : '', option ? (_ref2 = (_variant_options = variant.options) == null ? void 0 : _variant_options[option.name]) != null ? _ref2 : '' : '');
67
+ }
68
+ lines.push([
69
+ csvCell(product.slug),
70
+ csvCell(index === 0 ? product.name : ''),
71
+ csvCell(index === 0 ? (_product_description = product.description) != null ? _product_description : '' : ''),
72
+ csvCell(index === 0 ? product.type : ''),
73
+ csvCell(index === 0 ? ((_product_tags = product.tags) != null ? _product_tags : []).join(', ') : ''),
74
+ csvCell(index === 0 ? String(product.status === 'active') : ''),
75
+ ...optionCells.map(csvCell),
76
+ csvCell((_variant_sku = variant.sku) != null ? _variant_sku : ''),
77
+ csvCell((_variant_barcode = variant.barcode) != null ? _variant_barcode : ''),
78
+ csvCell(variant.priceUsd),
79
+ csvCell((_variant_compareAtPriceUsd = variant.compareAtPriceUsd) != null ? _variant_compareAtPriceUsd : ''),
80
+ csvCell((_variant_inventory = variant.inventory) != null ? _variant_inventory : ''),
81
+ csvCell((_variant_weightGrams = variant.weightGrams) != null ? _variant_weightGrams : ''),
82
+ csvCell(index === 0 ? (_ref = (_product_mediaUrls = product.mediaUrls) == null ? void 0 : _product_mediaUrls[0]) != null ? _ref : '' : '')
83
+ ].join(','));
84
+ });
85
+ for (const url of ((_product_mediaUrls = product.mediaUrls) != null ? _product_mediaUrls : []).slice(1)){
86
+ lines.push([
87
+ csvCell(product.slug),
88
+ ...Array(PRODUCT_CSV_HEADER.length - 2).fill(''),
89
+ csvCell(url)
90
+ ].join(','));
91
+ }
92
+ }
93
+ return lines.join('\n');
94
+ }
95
+ /** Case-insensitive column lookup so hand-edited headers still map. */ function headerIndex(header) {
96
+ const map = new Map();
97
+ header.forEach((cell, index)=>map.set(cell.trim().toLowerCase(), index));
98
+ return map;
99
+ }
100
+ export function parseProductsCsv(text) {
101
+ const rows = parseCsv(text);
102
+ if (rows.length < 2) {
103
+ return {
104
+ products: [],
105
+ errors: [
106
+ 'No data rows found'
107
+ ]
108
+ };
109
+ }
110
+ const columns = headerIndex(rows[0]);
111
+ const cell = (row, name)=>{
112
+ var _row_index;
113
+ const index = columns.get(name.toLowerCase());
114
+ return index == null ? '' : ((_row_index = row[index]) != null ? _row_index : '').trim();
115
+ };
116
+ if (!columns.has('handle') || !columns.has('title')) {
117
+ return {
118
+ products: [],
119
+ errors: [
120
+ 'Missing required columns: Handle, Title'
121
+ ]
122
+ };
123
+ }
124
+ const byHandle = new Map();
125
+ const errors = [];
126
+ rows.slice(1).forEach((row, rowIndex)=>{
127
+ var _product_mediaUrls;
128
+ const line = rowIndex + 2;
129
+ const handle = commerceSlug(cell(row, 'handle'));
130
+ if (!handle) {
131
+ if (row.some((value)=>value.trim())) {
132
+ errors.push(`Row ${line}: missing Handle`);
133
+ }
134
+ return;
135
+ }
136
+ let product = byHandle.get(handle);
137
+ const title = cell(row, 'title');
138
+ if (!product) {
139
+ if (!title) {
140
+ // Image-only continuation row for a product we never saw.
141
+ errors.push(`Row ${line}: first row for "${handle}" needs a Title`);
142
+ return;
143
+ }
144
+ const published = cell(row, 'published').toLowerCase();
145
+ const type = cell(row, 'type').toLowerCase();
146
+ product = {
147
+ name: title,
148
+ slug: handle,
149
+ description: cell(row, 'body (html)') || undefined,
150
+ type: [
151
+ 'physical',
152
+ 'digital',
153
+ 'service'
154
+ ].includes(type) ? type : 'physical',
155
+ status: published === 'false' ? 'draft' : 'active',
156
+ tags: cell(row, 'tags') ? cell(row, 'tags').split(',').map((tag)=>tag.trim()).filter(Boolean) : undefined,
157
+ options: [],
158
+ variants: [],
159
+ mediaUrls: []
160
+ };
161
+ byHandle.set(handle, product);
162
+ }
163
+ const imageSrc = cell(row, 'image src');
164
+ if (imageSrc && !((_product_mediaUrls = product.mediaUrls) != null ? _product_mediaUrls : []).includes(imageSrc)) {
165
+ var _product_mediaUrls1;
166
+ product.mediaUrls = [
167
+ ...(_product_mediaUrls1 = product.mediaUrls) != null ? _product_mediaUrls1 : [],
168
+ imageSrc
169
+ ];
170
+ }
171
+ const priceRaw = cell(row, 'variant price');
172
+ const hasVariant = priceRaw !== '' || cell(row, 'variant sku') !== '';
173
+ if (!hasVariant) return;
174
+ const options = {};
175
+ for(let axis = 1; axis <= 3; axis += 1){
176
+ var _product_options_;
177
+ const name = cell(row, `option${axis} name`);
178
+ const value = cell(row, `option${axis} value`);
179
+ if (name && product.options[axis - 1] == null) {
180
+ product.options[axis - 1] = {
181
+ name,
182
+ values: []
183
+ };
184
+ }
185
+ const optionName = (_product_options_ = product.options[axis - 1]) == null ? void 0 : _product_options_.name;
186
+ if (optionName && value) {
187
+ options[optionName] = value;
188
+ const axisOption = product.options[axis - 1];
189
+ if (!axisOption.values.includes(value)) {
190
+ axisOption.values.push(value);
191
+ }
192
+ }
193
+ }
194
+ const price = Number(priceRaw);
195
+ if (!Number.isFinite(price) || price < 0) {
196
+ errors.push(`Row ${line}: invalid Variant Price "${priceRaw}"`);
197
+ return;
198
+ }
199
+ const qtyRaw = cell(row, 'variant inventory qty');
200
+ const compareRaw = cell(row, 'variant compare at price');
201
+ const gramsRaw = cell(row, 'variant grams');
202
+ const variant = _extends({
203
+ id: `v${product.variants.length + 1}`
204
+ }, Object.keys(options).length ? {
205
+ options
206
+ } : {}, {
207
+ priceUsd: price
208
+ }, cell(row, 'variant sku') ? {
209
+ sku: cell(row, 'variant sku')
210
+ } : {}, cell(row, 'variant barcode') ? {
211
+ barcode: cell(row, 'variant barcode')
212
+ } : {}, compareRaw && Number.isFinite(Number(compareRaw)) ? {
213
+ compareAtPriceUsd: Number(compareRaw)
214
+ } : {}, {
215
+ inventory: qtyRaw === '' ? null : Math.max(0, Math.round(Number(qtyRaw)))
216
+ }, gramsRaw && Number.isFinite(Number(gramsRaw)) ? {
217
+ weightGrams: Number(gramsRaw)
218
+ } : {});
219
+ product.variants.push(variant);
220
+ });
221
+ const products = [];
222
+ for (const [handle, product] of byHandle){
223
+ var _product_options, _ref;
224
+ var _product_mediaUrls;
225
+ product.options = ((_product_options = product.options) != null ? _product_options : []).filter(Boolean);
226
+ if (product.options.length === 0) delete product.options;
227
+ if (((_ref = (_product_mediaUrls = product.mediaUrls) == null ? void 0 : _product_mediaUrls.length) != null ? _ref : 0) === 0) delete product.mediaUrls;
228
+ if (product.variants.length === 0) {
229
+ errors.push(`"${handle}": no variant rows (needs Variant Price)`);
230
+ continue;
231
+ }
232
+ const problem = validateProduct(product);
233
+ if (problem) {
234
+ errors.push(`"${handle}": ${problem}`);
235
+ continue;
236
+ }
237
+ products.push(product);
238
+ }
239
+ return {
240
+ products,
241
+ errors
242
+ };
243
+ }
244
+
245
+ //# sourceMappingURL=commerce-io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/model/commerce-io.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Catalog CSV import/export (AGL-282) speaking Shopify's product CSV\n * dialect — the migration wedge for switchers: `Handle` groups variant\n * rows into one product, `Option1..3 Name/Value` build the option axes,\n * `Variant *` columns carry per-variant data, and repeated-handle rows\n * with only `Image Src` add media. Export mirrors the same columns so\n * round-trips are lossless for the fields both sides share.\n */\n\nimport {\n commerceSlug,\n validateProduct,\n type HostProduct,\n type ProductOption,\n type ProductStatus,\n type ProductVariant,\n} from './commerce'\nimport { parseCsv } from '@aglyn/aglyn/app-utils/dataset-csv'\n\nexport const PRODUCT_CSV_HEADER = [\n 'Handle',\n 'Title',\n 'Body (HTML)',\n 'Type',\n 'Tags',\n 'Published',\n 'Option1 Name',\n 'Option1 Value',\n 'Option2 Name',\n 'Option2 Value',\n 'Option3 Name',\n 'Option3 Value',\n 'Variant SKU',\n 'Variant Barcode',\n 'Variant Price',\n 'Variant Compare At Price',\n 'Variant Inventory Qty',\n 'Variant Grams',\n 'Image Src',\n] as const\n\nfunction csvCell(value: unknown): string {\n const text = value == null ? '' : String(value)\n return /[\",\\n]/.test(text) ? `\"${text.replace(/\"/g, '\"\"')}\"` : text\n}\n\n/** One row per variant; extra image rows follow Shopify's convention. */\nexport function productsToCsv(\n products: Array<HostProduct & { $id?: string }>,\n): string {\n const lines = [PRODUCT_CSV_HEADER.join(',')]\n for (const product of products) {\n const options = product.options ?? []\n product.variants.forEach((variant, index) => {\n const optionCells: string[] = []\n for (let axis = 0; axis < 3; axis += 1) {\n const option = options[axis]\n optionCells.push(\n index === 0 ? (option?.name ?? '') : '',\n option ? (variant.options?.[option.name] ?? '') : '',\n )\n }\n lines.push(\n [\n csvCell(product.slug),\n csvCell(index === 0 ? product.name : ''),\n csvCell(index === 0 ? (product.description ?? '') : ''),\n csvCell(index === 0 ? product.type : ''),\n csvCell(index === 0 ? (product.tags ?? []).join(', ') : ''),\n csvCell(index === 0 ? String(product.status === 'active') : ''),\n ...optionCells.map(csvCell),\n csvCell(variant.sku ?? ''),\n csvCell(variant.barcode ?? ''),\n csvCell(variant.priceUsd),\n csvCell(variant.compareAtPriceUsd ?? ''),\n csvCell(variant.inventory ?? ''),\n csvCell(variant.weightGrams ?? ''),\n csvCell(index === 0 ? (product.mediaUrls?.[0] ?? '') : ''),\n ].join(','),\n )\n })\n for (const url of (product.mediaUrls ?? []).slice(1)) {\n lines.push(\n [\n csvCell(product.slug),\n ...Array(PRODUCT_CSV_HEADER.length - 2).fill(''),\n csvCell(url),\n ].join(','),\n )\n }\n }\n return lines.join('\\n')\n}\n\nexport interface ProductCsvImport {\n products: HostProduct[]\n /** Row-anchored problems; importable products still parse. */\n errors: string[]\n}\n\n/** Case-insensitive column lookup so hand-edited headers still map. */\nfunction headerIndex(header: string[]): Map<string, number> {\n const map = new Map<string, number>()\n header.forEach((cell, index) =>\n map.set(cell.trim().toLowerCase(), index),\n )\n return map\n}\n\nexport function parseProductsCsv(text: string): ProductCsvImport {\n const rows = parseCsv(text)\n if (rows.length < 2) {\n return { products: [], errors: ['No data rows found'] }\n }\n const columns = headerIndex(rows[0])\n const cell = (row: string[], name: string): string => {\n const index = columns.get(name.toLowerCase())\n return index == null ? '' : (row[index] ?? '').trim()\n }\n if (!columns.has('handle') || !columns.has('title')) {\n return {\n products: [],\n errors: ['Missing required columns: Handle, Title'],\n }\n }\n\n const byHandle = new Map<string, HostProduct>()\n const errors: string[] = []\n rows.slice(1).forEach((row, rowIndex) => {\n const line = rowIndex + 2\n const handle = commerceSlug(cell(row, 'handle'))\n if (!handle) {\n if (row.some((value) => value.trim())) {\n errors.push(`Row ${line}: missing Handle`)\n }\n return\n }\n let product = byHandle.get(handle)\n const title = cell(row, 'title')\n if (!product) {\n if (!title) {\n // Image-only continuation row for a product we never saw.\n errors.push(`Row ${line}: first row for \"${handle}\" needs a Title`)\n return\n }\n const published = cell(row, 'published').toLowerCase()\n const type = cell(row, 'type').toLowerCase()\n product = {\n name: title,\n slug: handle,\n description: cell(row, 'body (html)') || undefined,\n type: ['physical', 'digital', 'service'].includes(type)\n ? (type as HostProduct['type'])\n : 'physical',\n status: (published === 'false'\n ? 'draft'\n : 'active') as ProductStatus,\n tags: cell(row, 'tags')\n ? cell(row, 'tags')\n .split(',')\n .map((tag) => tag.trim())\n .filter(Boolean)\n : undefined,\n options: [],\n variants: [],\n mediaUrls: [],\n }\n byHandle.set(handle, product)\n }\n\n const imageSrc = cell(row, 'image src')\n if (imageSrc && !(product.mediaUrls ?? []).includes(imageSrc)) {\n product.mediaUrls = [...(product.mediaUrls ?? []), imageSrc]\n }\n\n const priceRaw = cell(row, 'variant price')\n const hasVariant = priceRaw !== '' || cell(row, 'variant sku') !== ''\n if (!hasVariant) return\n\n const options: Record<string, string> = {}\n for (let axis = 1; axis <= 3; axis += 1) {\n const name = cell(row, `option${axis} name`)\n const value = cell(row, `option${axis} value`)\n if (name && product.options![axis - 1] == null) {\n product.options![axis - 1] = { name, values: [] }\n }\n const optionName = product.options![axis - 1]?.name\n if (optionName && value) {\n options[optionName] = value\n const axisOption = product.options![axis - 1] as ProductOption\n if (!axisOption.values.includes(value)) {\n axisOption.values.push(value)\n }\n }\n }\n\n const price = Number(priceRaw)\n if (!Number.isFinite(price) || price < 0) {\n errors.push(`Row ${line}: invalid Variant Price \"${priceRaw}\"`)\n return\n }\n const qtyRaw = cell(row, 'variant inventory qty')\n const compareRaw = cell(row, 'variant compare at price')\n const gramsRaw = cell(row, 'variant grams')\n const variant: ProductVariant = {\n id: `v${product.variants.length + 1}`,\n ...(Object.keys(options).length ? { options } : {}),\n priceUsd: price,\n ...(cell(row, 'variant sku') ? { sku: cell(row, 'variant sku') } : {}),\n ...(cell(row, 'variant barcode')\n ? { barcode: cell(row, 'variant barcode') }\n : {}),\n ...(compareRaw && Number.isFinite(Number(compareRaw))\n ? { compareAtPriceUsd: Number(compareRaw) }\n : {}),\n inventory: qtyRaw === '' ? null : Math.max(0, Math.round(Number(qtyRaw))),\n ...(gramsRaw && Number.isFinite(Number(gramsRaw))\n ? { weightGrams: Number(gramsRaw) }\n : {}),\n }\n product.variants.push(variant)\n })\n\n const products: HostProduct[] = []\n for (const [handle, product] of byHandle) {\n product.options = (product.options ?? []).filter(Boolean)\n if (product.options.length === 0) delete product.options\n if ((product.mediaUrls?.length ?? 0) === 0) delete product.mediaUrls\n if (product.variants.length === 0) {\n errors.push(`\"${handle}\": no variant rows (needs Variant Price)`)\n continue\n }\n const problem = validateProduct(product)\n if (problem) {\n errors.push(`\"${handle}\": ${problem}`)\n continue\n }\n products.push(product)\n }\n return { products, errors }\n}\n"],"names":["commerceSlug","validateProduct","parseCsv","PRODUCT_CSV_HEADER","csvCell","value","text","String","test","replace","productsToCsv","products","lines","join","product","options","variants","forEach","variant","index","optionCells","axis","option","push","name","slug","description","type","tags","status","map","sku","barcode","priceUsd","compareAtPriceUsd","inventory","weightGrams","mediaUrls","url","slice","Array","length","fill","headerIndex","header","Map","cell","set","trim","toLowerCase","parseProductsCsv","rows","errors","columns","row","get","has","byHandle","rowIndex","line","handle","some","title","published","undefined","includes","split","tag","filter","Boolean","imageSrc","priceRaw","hasVariant","values","optionName","axisOption","price","Number","isFinite","qtyRaw","compareRaw","gramsRaw","id","Object","keys","Math","max","round","problem"],"mappings":"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"}