@aglyn/plugins-commerce 1.0.0-beta.285 → 1.0.0-beta.287

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 (420) hide show
  1. package/README.md +1 -1
  2. package/package.json +13 -13
  3. package/src/lib/components/cart.js +25 -12
  4. package/src/lib/components/cart.js.map +1 -1
  5. package/src/lib/components/commerce-console-page.js +70 -13
  6. package/src/lib/components/commerce-console-page.js.map +1 -1
  7. package/src/lib/components/console/order-detail-dialog.component.js +2 -1
  8. package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
  9. package/src/lib/components/console/payment-methods-card.component.js +1 -1
  10. package/src/lib/components/console/payment-methods-card.component.js.map +1 -1
  11. package/src/lib/components/console/pos/pos-cart-panel.component.d.ts +5 -0
  12. package/src/lib/components/console/pos/pos-cart-panel.component.js +18 -12
  13. package/src/lib/components/console/pos/pos-cart-panel.component.js.map +1 -1
  14. package/src/lib/components/console/pos/pos-hardware-api.d.ts +76 -5
  15. package/src/lib/components/console/pos/pos-hardware-api.js +53 -11
  16. package/src/lib/components/console/pos/pos-hardware-api.js.map +1 -1
  17. package/src/lib/components/console/pos/pos-hardware-buyer.component.d.ts +18 -0
  18. package/src/lib/components/console/pos/pos-hardware-buyer.component.js +629 -0
  19. package/src/lib/components/console/pos/pos-hardware-buyer.component.js.map +1 -0
  20. package/src/lib/components/console/pos/pos-hardware-sale-api.d.ts +162 -0
  21. package/src/lib/components/console/pos/pos-hardware-sale-api.js +122 -0
  22. package/src/lib/components/console/pos/pos-hardware-sale-api.js.map +1 -0
  23. package/src/lib/components/console/pos/pos-hardware-sale-terms.component.d.ts +39 -0
  24. package/src/lib/components/console/pos/pos-hardware-sale-terms.component.js +251 -0
  25. package/src/lib/components/console/pos/pos-hardware-sale-terms.component.js.map +1 -0
  26. package/src/lib/components/console/pos/use-pos-display.js +50 -0
  27. package/src/lib/components/console/pos/use-pos-display.js.map +1 -1
  28. package/src/lib/components/console/pos-cellular-control.component.d.ts +41 -0
  29. package/src/lib/components/console/pos-cellular-control.component.js +211 -0
  30. package/src/lib/components/console/pos-cellular-control.component.js.map +1 -0
  31. package/src/lib/components/console/pos-devices-card.component.d.ts +9 -1
  32. package/src/lib/components/console/pos-devices-card.component.js +47 -15
  33. package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
  34. package/src/lib/components/console/pos-display/pos-display-api.d.ts +6 -0
  35. package/src/lib/components/console/pos-display/pos-display-api.js +8 -1
  36. package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -1
  37. package/src/lib/components/console/pos-display-page.component.d.ts +13 -0
  38. package/src/lib/components/console/pos-display-page.component.js +44 -2
  39. package/src/lib/components/console/pos-display-page.component.js.map +1 -1
  40. package/src/lib/components/console/pos-hardware-card.component.d.ts +12 -4
  41. package/src/lib/components/console/pos-hardware-card.component.js +157 -36
  42. package/src/lib/components/console/pos-hardware-card.component.js.map +1 -1
  43. package/src/lib/components/console/pos-hardware-orders-staff-page.component.js +360 -80
  44. package/src/lib/components/console/pos-hardware-orders-staff-page.component.js.map +1 -1
  45. package/src/lib/components/console/pos-hardware-terms-page.component.d.ts +34 -0
  46. package/src/lib/components/console/pos-hardware-terms-page.component.js +257 -0
  47. package/src/lib/components/console/pos-hardware-terms-page.component.js.map +1 -0
  48. package/src/lib/components/console/pos-hardware-terms-sign-page.component.d.ts +27 -0
  49. package/src/lib/components/console/pos-hardware-terms-sign-page.component.js +104 -0
  50. package/src/lib/components/console/pos-hardware-terms-sign-page.component.js.map +1 -0
  51. package/src/lib/components/console/pos-hardware-waiting-card.component.d.ts +24 -0
  52. package/src/lib/components/console/pos-hardware-waiting-card.component.js +205 -0
  53. package/src/lib/components/console/pos-hardware-waiting-card.component.js.map +1 -0
  54. package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js +297 -201
  55. package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js.map +1 -1
  56. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.d.ts +3 -0
  57. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js +260 -92
  58. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js.map +1 -1
  59. package/src/lib/components/console/pos-ops/pos-operations-bar.component.d.ts +9 -0
  60. package/src/lib/components/console/pos-ops/pos-operations-bar.component.js +15 -6
  61. package/src/lib/components/console/pos-ops/pos-operations-bar.component.js.map +1 -1
  62. package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.d.ts +25 -0
  63. package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.js +136 -0
  64. package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.js.map +1 -0
  65. package/src/lib/components/console/pos-ops/pos-shift-panel.component.d.ts +6 -0
  66. package/src/lib/components/console/pos-ops/pos-shift-panel.component.js +48 -31
  67. package/src/lib/components/console/pos-ops/pos-shift-panel.component.js.map +1 -1
  68. package/src/lib/components/console/pos-page.component.d.ts +1 -1
  69. package/src/lib/components/console/pos-page.component.js +63 -12
  70. package/src/lib/components/console/pos-page.component.js.map +1 -1
  71. package/src/lib/components/console/pos-reader-splash-setting.component.js +1 -1
  72. package/src/lib/components/console/pos-reader-splash-setting.component.js.map +1 -1
  73. package/src/lib/components/console/product-check-in-fields.component.d.ts +4 -2
  74. package/src/lib/components/console/product-check-in-fields.component.js +60 -14
  75. package/src/lib/components/console/product-check-in-fields.component.js.map +1 -1
  76. package/src/lib/components/console/product-editor-dialog.component.js +44 -1
  77. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
  78. package/src/lib/components/console/product-hardware-sku-field.component.d.ts +19 -0
  79. package/src/lib/components/console/product-hardware-sku-field.component.js +92 -0
  80. package/src/lib/components/console/product-hardware-sku-field.component.js.map +1 -0
  81. package/src/lib/components/console/product-kiosk-offer-field.component.d.ts +22 -0
  82. package/src/lib/components/console/product-kiosk-offer-field.component.js +94 -0
  83. package/src/lib/components/console/product-kiosk-offer-field.component.js.map +1 -0
  84. package/src/lib/components/console/product-register-fields.component.d.ts +4 -0
  85. package/src/lib/components/console/product-register-fields.component.js +31 -2
  86. package/src/lib/components/console/product-register-fields.component.js.map +1 -1
  87. package/src/lib/components/console/products-hub-card.component.js +11 -2
  88. package/src/lib/components/console/products-hub-card.component.js.map +1 -1
  89. package/src/lib/components/console/register-hardware-card.component.d.ts +11 -0
  90. package/src/lib/components/console/register-hardware-card.component.js +56 -27
  91. package/src/lib/components/console/register-hardware-card.component.js.map +1 -1
  92. package/src/lib/components/console/reservation-guests-dialog.component.d.ts +28 -0
  93. package/src/lib/components/console/reservation-guests-dialog.component.js +189 -0
  94. package/src/lib/components/console/reservation-guests-dialog.component.js.map +1 -0
  95. package/src/lib/components/console/reservations-card.component.d.ts +9 -0
  96. package/src/lib/components/console/reservations-card.component.js +158 -23
  97. package/src/lib/components/console/reservations-card.component.js.map +1 -1
  98. package/src/lib/components/console/shippingeasy-card.component.js +1 -1
  99. package/src/lib/components/console/shippingeasy-card.component.js.map +1 -1
  100. package/src/lib/components/console/shipstation-card.component.d.ts +1 -1
  101. package/src/lib/components/console/shipstation-card.component.js +3 -3
  102. package/src/lib/components/console/shipstation-card.component.js.map +1 -1
  103. package/src/lib/components/product-detail.d.ts +4 -0
  104. package/src/lib/components/product-detail.js +40 -5
  105. package/src/lib/components/product-detail.js.map +1 -1
  106. package/src/lib/components/product-reviews.js +28 -11
  107. package/src/lib/components/product-reviews.js.map +1 -1
  108. package/src/lib/components/reservation-widget.js +28 -5
  109. package/src/lib/components/reservation-widget.js.map +1 -1
  110. package/src/lib/components/use-day-picker.d.ts +25 -0
  111. package/src/lib/components/use-day-picker.js +57 -0
  112. package/src/lib/components/use-day-picker.js.map +1 -0
  113. package/src/lib/constants/operator-alerts.d.ts +55 -0
  114. package/src/lib/constants/operator-alerts.js +156 -1
  115. package/src/lib/constants/operator-alerts.js.map +1 -1
  116. package/src/lib/declarations.console-server.js +54 -1
  117. package/src/lib/declarations.console-server.js.map +1 -1
  118. package/src/lib/declarations.d.ts +4 -2
  119. package/src/lib/declarations.js +11 -4
  120. package/src/lib/declarations.js.map +1 -1
  121. package/src/lib/declarations.server.js +9 -0
  122. package/src/lib/declarations.server.js.map +1 -1
  123. package/src/lib/model/commerce-cart.d.ts +9 -1
  124. package/src/lib/model/commerce-cart.js +4 -3
  125. package/src/lib/model/commerce-cart.js.map +1 -1
  126. package/src/lib/model/commerce-check-in-product.d.ts +26 -0
  127. package/src/lib/model/commerce-check-in-product.js +64 -2
  128. package/src/lib/model/commerce-check-in-product.js.map +1 -1
  129. package/src/lib/model/commerce-check-in-record.d.ts +127 -0
  130. package/src/lib/model/commerce-check-in-record.js +36 -0
  131. package/src/lib/model/commerce-check-in-record.js.map +1 -0
  132. package/src/lib/model/commerce-check-in.d.ts +91 -87
  133. package/src/lib/model/commerce-check-in.js +186 -62
  134. package/src/lib/model/commerce-check-in.js.map +1 -1
  135. package/src/lib/model/commerce-kiosk-offer.d.ts +31 -0
  136. package/src/lib/model/commerce-kiosk-offer.js +35 -0
  137. package/src/lib/model/commerce-kiosk-offer.js.map +1 -0
  138. package/src/lib/model/commerce-orders.d.ts +76 -0
  139. package/src/lib/model/commerce-orders.js +6 -0
  140. package/src/lib/model/commerce-orders.js.map +1 -1
  141. package/src/lib/model/commerce-pos-day-report.d.ts +54 -1
  142. package/src/lib/model/commerce-pos-day-report.js +39 -2
  143. package/src/lib/model/commerce-pos-day-report.js.map +1 -1
  144. package/src/lib/model/commerce-pos-offline.d.ts +1 -1
  145. package/src/lib/model/commerce-pos-offline.js +6 -1
  146. package/src/lib/model/commerce-pos-offline.js.map +1 -1
  147. package/src/lib/model/commerce-pos-ops.js +3 -2
  148. package/src/lib/model/commerce-pos-ops.js.map +1 -1
  149. package/src/lib/model/commerce-pos.d.ts +36 -3
  150. package/src/lib/model/commerce-pos.js +14 -6
  151. package/src/lib/model/commerce-pos.js.map +1 -1
  152. package/src/lib/model/commerce-receipt.js +3 -2
  153. package/src/lib/model/commerce-receipt.js.map +1 -1
  154. package/src/lib/model/commerce-reservations.d.ts +69 -4
  155. package/src/lib/model/commerce-reservations.js +57 -5
  156. package/src/lib/model/commerce-reservations.js.map +1 -1
  157. package/src/lib/model/commerce.d.ts +66 -0
  158. package/src/lib/model/commerce.js +15 -0
  159. package/src/lib/model/commerce.js.map +1 -1
  160. package/src/lib/model/order-list-fields.d.ts +11 -0
  161. package/src/lib/model/order-list-fields.js +17 -1
  162. package/src/lib/model/order-list-fields.js.map +1 -1
  163. package/src/lib/model/own-store-tax-summary.d.ts +152 -0
  164. package/src/lib/model/own-store-tax-summary.js +288 -0
  165. package/src/lib/model/own-store-tax-summary.js.map +1 -0
  166. package/src/lib/model/plugin-permissions.d.ts +67 -0
  167. package/src/lib/model/plugin-permissions.js +224 -7
  168. package/src/lib/model/plugin-permissions.js.map +1 -1
  169. package/src/lib/model/pos-cellular.d.ts +223 -0
  170. package/src/lib/model/pos-cellular.js +293 -0
  171. package/src/lib/model/pos-cellular.js.map +1 -0
  172. package/src/lib/model/pos-hardware-in-person.d.ts +98 -0
  173. package/src/lib/model/pos-hardware-in-person.js +224 -0
  174. package/src/lib/model/pos-hardware-in-person.js.map +1 -0
  175. package/src/lib/model/pos-hardware-tax-summary.d.ts +166 -0
  176. package/src/lib/model/pos-hardware-tax-summary.js +225 -0
  177. package/src/lib/model/pos-hardware-tax-summary.js.map +1 -0
  178. package/src/lib/model/pos-hardware-terms.d.ts +74 -0
  179. package/src/lib/model/pos-hardware-terms.js +115 -0
  180. package/src/lib/model/pos-hardware-terms.js.map +1 -0
  181. package/src/lib/model/pos-hardware.d.ts +349 -7
  182. package/src/lib/model/pos-hardware.js +291 -20
  183. package/src/lib/model/pos-hardware.js.map +1 -1
  184. package/src/lib/model/product-write.d.ts +10 -0
  185. package/src/lib/model/product-write.js +4 -2
  186. package/src/lib/model/product-write.js.map +1 -1
  187. package/src/lib/plugin.js +16 -0
  188. package/src/lib/plugin.js.map +1 -1
  189. package/src/lib/server/billing-webhook.js +25 -1
  190. package/src/lib/server/billing-webhook.js.map +1 -1
  191. package/src/lib/server/cancel-order.js +7 -5
  192. package/src/lib/server/cancel-order.js.map +1 -1
  193. package/src/lib/server/cart-checkout.js +20 -8
  194. package/src/lib/server/cart-checkout.js.map +1 -1
  195. package/src/lib/server/cart.js +29 -0
  196. package/src/lib/server/cart.js.map +1 -1
  197. package/src/lib/server/checkout.js +42 -13
  198. package/src/lib/server/checkout.js.map +1 -1
  199. package/src/lib/server/collection-membership.d.ts +4 -0
  200. package/src/lib/server/collection-membership.js +5 -10
  201. package/src/lib/server/collection-membership.js.map +1 -1
  202. package/src/lib/server/commerce-site-keys.d.ts +29 -0
  203. package/src/lib/server/commerce-site-keys.js +40 -0
  204. package/src/lib/server/commerce-site-keys.js.map +1 -0
  205. package/src/lib/server/draft-order.js +8 -5
  206. package/src/lib/server/draft-order.js.map +1 -1
  207. package/src/lib/server/fulfill-order.js +7 -5
  208. package/src/lib/server/fulfill-order.js.map +1 -1
  209. package/src/lib/server/gift-cards.js +8 -5
  210. package/src/lib/server/gift-cards.js.map +1 -1
  211. package/src/lib/server/local-fulfillment-status.js +9 -6
  212. package/src/lib/server/local-fulfillment-status.js.map +1 -1
  213. package/src/lib/server/member-post.js +6 -5
  214. package/src/lib/server/member-post.js.map +1 -1
  215. package/src/lib/server/membership-admin-password.d.ts +4 -2
  216. package/src/lib/server/membership-admin-password.js +10 -8
  217. package/src/lib/server/membership-admin-password.js.map +1 -1
  218. package/src/lib/server/membership-admin-remove.d.ts +7 -5
  219. package/src/lib/server/membership-admin-remove.js +9 -9
  220. package/src/lib/server/membership-admin-remove.js.map +1 -1
  221. package/src/lib/server/order-notifications.js +5 -2
  222. package/src/lib/server/order-notifications.js.map +1 -1
  223. package/src/lib/server/order-print.js +7 -5
  224. package/src/lib/server/order-print.js.map +1 -1
  225. package/src/lib/server/order-receipt-send.js +8 -5
  226. package/src/lib/server/order-receipt-send.js.map +1 -1
  227. package/src/lib/server/orders-shipping-prepare.js +9 -6
  228. package/src/lib/server/orders-shipping-prepare.js.map +1 -1
  229. package/src/lib/server/own-store-tax-return-source.d.ts +47 -0
  230. package/src/lib/server/own-store-tax-return-source.js +312 -0
  231. package/src/lib/server/own-store-tax-return-source.js.map +1 -0
  232. package/src/lib/server/payment-methods.js +13 -9
  233. package/src/lib/server/payment-methods.js.map +1 -1
  234. package/src/lib/server/pos-auth.d.ts +37 -6
  235. package/src/lib/server/pos-auth.js +40 -15
  236. package/src/lib/server/pos-auth.js.map +1 -1
  237. package/src/lib/server/pos-cellular-billing.d.ts +81 -0
  238. package/src/lib/server/pos-cellular-billing.js +711 -0
  239. package/src/lib/server/pos-cellular-billing.js.map +1 -0
  240. package/src/lib/server/pos-cellular-notify.d.ts +47 -0
  241. package/src/lib/server/pos-cellular-notify.js +150 -0
  242. package/src/lib/server/pos-cellular-notify.js.map +1 -0
  243. package/src/lib/server/pos-cellular.d.ts +88 -0
  244. package/src/lib/server/pos-cellular.js +339 -0
  245. package/src/lib/server/pos-cellular.js.map +1 -0
  246. package/src/lib/server/pos-check-in.d.ts +5 -1
  247. package/src/lib/server/pos-check-in.js +296 -28
  248. package/src/lib/server/pos-check-in.js.map +1 -1
  249. package/src/lib/server/pos-day-report.js +29 -3
  250. package/src/lib/server/pos-day-report.js.map +1 -1
  251. package/src/lib/server/pos-display.d.ts +16 -0
  252. package/src/lib/server/pos-display.js +129 -2
  253. package/src/lib/server/pos-display.js.map +1 -1
  254. package/src/lib/server/pos-hardware-admin.d.ts +10 -1
  255. package/src/lib/server/pos-hardware-admin.js +250 -84
  256. package/src/lib/server/pos-hardware-admin.js.map +1 -1
  257. package/src/lib/server/pos-hardware-attach.d.ts +105 -0
  258. package/src/lib/server/pos-hardware-attach.js +443 -0
  259. package/src/lib/server/pos-hardware-attach.js.map +1 -0
  260. package/src/lib/server/pos-hardware-buyer-lookup.d.ts +58 -0
  261. package/src/lib/server/pos-hardware-buyer-lookup.js +180 -0
  262. package/src/lib/server/pos-hardware-buyer-lookup.js.map +1 -0
  263. package/src/lib/server/pos-hardware-buyer-record.d.ts +29 -0
  264. package/src/lib/server/pos-hardware-buyer-record.js +86 -0
  265. package/src/lib/server/pos-hardware-buyer-record.js.map +1 -0
  266. package/src/lib/server/pos-hardware-cancel.d.ts +58 -0
  267. package/src/lib/server/pos-hardware-cancel.js +147 -0
  268. package/src/lib/server/pos-hardware-cancel.js.map +1 -0
  269. package/src/lib/server/pos-hardware-closure-notices.d.ts +27 -0
  270. package/src/lib/server/pos-hardware-closure-notices.js +85 -0
  271. package/src/lib/server/pos-hardware-closure-notices.js.map +1 -0
  272. package/src/lib/server/pos-hardware-closure.d.ts +60 -0
  273. package/src/lib/server/pos-hardware-closure.js +153 -0
  274. package/src/lib/server/pos-hardware-closure.js.map +1 -0
  275. package/src/lib/server/pos-hardware-in-person.d.ts +61 -0
  276. package/src/lib/server/pos-hardware-in-person.js +236 -0
  277. package/src/lib/server/pos-hardware-in-person.js.map +1 -0
  278. package/src/lib/server/pos-hardware-notify.d.ts +40 -2
  279. package/src/lib/server/pos-hardware-notify.js +195 -14
  280. package/src/lib/server/pos-hardware-notify.js.map +1 -1
  281. package/src/lib/server/pos-hardware-readers.d.ts +115 -0
  282. package/src/lib/server/pos-hardware-readers.js +430 -0
  283. package/src/lib/server/pos-hardware-readers.js.map +1 -0
  284. package/src/lib/server/pos-hardware-returns.d.ts +116 -0
  285. package/src/lib/server/pos-hardware-returns.js +502 -0
  286. package/src/lib/server/pos-hardware-returns.js.map +1 -0
  287. package/src/lib/server/pos-hardware-sale-fields.d.ts +28 -0
  288. package/src/lib/server/pos-hardware-sale-fields.js +44 -0
  289. package/src/lib/server/pos-hardware-sale-fields.js.map +1 -0
  290. package/src/lib/server/pos-hardware-sale.d.ts +54 -0
  291. package/src/lib/server/pos-hardware-sale.js +369 -0
  292. package/src/lib/server/pos-hardware-sale.js.map +1 -0
  293. package/src/lib/server/pos-hardware-tax-return-source.d.ts +99 -0
  294. package/src/lib/server/pos-hardware-tax-return-source.js +462 -0
  295. package/src/lib/server/pos-hardware-tax-return-source.js.map +1 -0
  296. package/src/lib/server/pos-hardware-terms.d.ts +64 -0
  297. package/src/lib/server/pos-hardware-terms.js +154 -0
  298. package/src/lib/server/pos-hardware-terms.js.map +1 -0
  299. package/src/lib/server/pos-hardware-user-eraser.d.ts +3 -0
  300. package/src/lib/server/pos-hardware-user-eraser.js +31 -7
  301. package/src/lib/server/pos-hardware-user-eraser.js.map +1 -1
  302. package/src/lib/server/pos-hardware-webhook.d.ts +5 -0
  303. package/src/lib/server/pos-hardware-webhook.js +51 -6
  304. package/src/lib/server/pos-hardware-webhook.js.map +1 -1
  305. package/src/lib/server/pos-hardware.d.ts +74 -1
  306. package/src/lib/server/pos-hardware.js +175 -10
  307. package/src/lib/server/pos-hardware.js.map +1 -1
  308. package/src/lib/server/pos-kiosk.d.ts +2 -0
  309. package/src/lib/server/pos-kiosk.js +17 -12
  310. package/src/lib/server/pos-kiosk.js.map +1 -1
  311. package/src/lib/server/pos-offline-card-order.d.ts +64 -0
  312. package/src/lib/server/pos-offline-card-order.js +102 -0
  313. package/src/lib/server/pos-offline-card-order.js.map +1 -0
  314. package/src/lib/server/pos-offline-card-reconcile.d.ts +67 -1
  315. package/src/lib/server/pos-offline-card-reconcile.js +215 -18
  316. package/src/lib/server/pos-offline-card-reconcile.js.map +1 -1
  317. package/src/lib/server/pos-offline-sync.d.ts +39 -0
  318. package/src/lib/server/pos-offline-sync.js +190 -55
  319. package/src/lib/server/pos-offline-sync.js.map +1 -1
  320. package/src/lib/server/pos-ops-gate.d.ts +15 -4
  321. package/src/lib/server/pos-ops-gate.js +42 -9
  322. package/src/lib/server/pos-ops-gate.js.map +1 -1
  323. package/src/lib/server/pos-ops-routes.js +24 -0
  324. package/src/lib/server/pos-ops-routes.js.map +1 -1
  325. package/src/lib/server/pos-order-refund-ids.d.ts +28 -0
  326. package/src/lib/server/pos-order-refund-ids.js +31 -0
  327. package/src/lib/server/pos-order-refund-ids.js.map +1 -0
  328. package/src/lib/server/pos-order.js +52 -49
  329. package/src/lib/server/pos-order.js.map +1 -1
  330. package/src/lib/server/pos-payment.js +1 -1
  331. package/src/lib/server/pos-payment.js.map +1 -1
  332. package/src/lib/server/pos-reader-splash-admin.js +30 -32
  333. package/src/lib/server/pos-reader-splash-admin.js.map +1 -1
  334. package/src/lib/server/pos-reader-splash-images-route.d.ts +17 -0
  335. package/src/lib/server/pos-reader-splash-images-route.js +113 -0
  336. package/src/lib/server/pos-reader-splash-images-route.js.map +1 -0
  337. package/src/lib/server/pos-reader-splash-images.d.ts +51 -0
  338. package/src/lib/server/pos-reader-splash-images.js +123 -0
  339. package/src/lib/server/pos-reader-splash-images.js.map +1 -0
  340. package/src/lib/server/pos-reader-splash.d.ts +68 -1
  341. package/src/lib/server/pos-reader-splash.js +182 -11
  342. package/src/lib/server/pos-reader-splash.js.map +1 -1
  343. package/src/lib/server/pos-readers.d.ts +29 -0
  344. package/src/lib/server/pos-readers.js +134 -35
  345. package/src/lib/server/pos-readers.js.map +1 -1
  346. package/src/lib/server/pos-return.d.ts +10 -0
  347. package/src/lib/server/pos-return.js +26 -1
  348. package/src/lib/server/pos-return.js.map +1 -1
  349. package/src/lib/server/pos-sale.js +6 -1
  350. package/src/lib/server/pos-sale.js.map +1 -1
  351. package/src/lib/server/pos-shift.js +11 -0
  352. package/src/lib/server/pos-shift.js.map +1 -1
  353. package/src/lib/server/pos-staff-pin.js +25 -20
  354. package/src/lib/server/pos-staff-pin.js.map +1 -1
  355. package/src/lib/server/pos-terminal.d.ts +14 -4
  356. package/src/lib/server/pos-terminal.js +34 -38
  357. package/src/lib/server/pos-terminal.js.map +1 -1
  358. package/src/lib/server/printers.d.ts +7 -3
  359. package/src/lib/server/printers.js +18 -12
  360. package/src/lib/server/printers.js.map +1 -1
  361. package/src/lib/server/product-drafts.d.ts +11 -1
  362. package/src/lib/server/product-drafts.js +12 -8
  363. package/src/lib/server/product-drafts.js.map +1 -1
  364. package/src/lib/server/product.d.ts +15 -1
  365. package/src/lib/server/product.js +16 -3
  366. package/src/lib/server/product.js.map +1 -1
  367. package/src/lib/server/products-write.d.ts +26 -2
  368. package/src/lib/server/products-write.js +19 -7
  369. package/src/lib/server/products-write.js.map +1 -1
  370. package/src/lib/server/refund.js +34 -11
  371. package/src/lib/server/refund.js.map +1 -1
  372. package/src/lib/server/reservation-availability-query.d.ts +8 -0
  373. package/src/lib/server/reservation-availability-query.js +11 -1
  374. package/src/lib/server/reservation-availability-query.js.map +1 -1
  375. package/src/lib/server/reservation-availability.d.ts +1 -1
  376. package/src/lib/server/reservation-availability.js +7 -2
  377. package/src/lib/server/reservation-availability.js.map +1 -1
  378. package/src/lib/server/reservation-guests.d.ts +32 -0
  379. package/src/lib/server/reservation-guests.js +285 -0
  380. package/src/lib/server/reservation-guests.js.map +1 -0
  381. package/src/lib/server/reservation-walk-in.d.ts +11 -1
  382. package/src/lib/server/reservation-walk-in.js +56 -12
  383. package/src/lib/server/reservation-walk-in.js.map +1 -1
  384. package/src/lib/server/reserve.js +18 -5
  385. package/src/lib/server/reserve.js.map +1 -1
  386. package/src/lib/server/returns.js +9 -6
  387. package/src/lib/server/returns.js.map +1 -1
  388. package/src/lib/server/reviews.d.ts +22 -2
  389. package/src/lib/server/reviews.js +88 -20
  390. package/src/lib/server/reviews.js.map +1 -1
  391. package/src/lib/server/shipping-connectors.js +10 -11
  392. package/src/lib/server/shipping-connectors.js.map +1 -1
  393. package/src/lib/server/site-page-resolver.js +20 -3
  394. package/src/lib/server/site-page-resolver.js.map +1 -1
  395. package/src/lib/server/store-day.d.ts +33 -0
  396. package/src/lib/server/store-day.js +46 -0
  397. package/src/lib/server/store-day.js.map +1 -0
  398. package/src/lib/server/store-setup-ai-writer.d.ts +2 -1
  399. package/src/lib/server/store-setup-ai-writer.js +5 -6
  400. package/src/lib/server/store-setup-ai-writer.js.map +1 -1
  401. package/src/lib/server/storefront-tax.d.ts +13 -0
  402. package/src/lib/server/storefront-tax.js +8 -1
  403. package/src/lib/server/storefront-tax.js.map +1 -1
  404. package/src/lib/server/tax-return-source.d.ts +32 -3
  405. package/src/lib/server/tax-return-source.js +99 -20
  406. package/src/lib/server/tax-return-source.js.map +1 -1
  407. package/src/lib/server.js +100 -2
  408. package/src/lib/server.js.map +1 -1
  409. package/src/lib/testing/fake-firestore.js +58 -16
  410. package/src/lib/testing/fake-firestore.js.map +1 -1
  411. package/src/lib/testing/pos-ops-memory-firestore.js +18 -4
  412. package/src/lib/testing/pos-ops-memory-firestore.js.map +1 -1
  413. package/src/lib/testing/site-register-permissions.d.ts +29 -0
  414. package/src/lib/testing/site-register-permissions.js +38 -0
  415. package/src/lib/testing/site-register-permissions.js.map +1 -0
  416. package/src/lib/transfer/tracking.server.js +8 -5
  417. package/src/lib/transfer/tracking.server.js.map +1 -1
  418. package/src/lib/utils/add-to-cart.d.ts +2 -0
  419. package/src/lib/utils/add-to-cart.js +6 -3
  420. package/src/lib/utils/add-to-cart.js.map +1 -1
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { TaxReturnSourceAnswer, TaxReturnSourceRequest } from '@aglyn/aglyn/plugin-manager/plugin-tax-return-sources';
18
+ import { type OwnStore, type OwnStoreOrderInput } from '../model/own-store-tax-summary';
19
+ /** The section's id, unique on the return. */
20
+ export declare const OWN_STORE_TAX_SECTION_ID = "ownStores";
21
+ /** How long before the period an own store's order is still read: a year and a quarter. */
22
+ export declare const OWN_STORE_LOOKBACK_MS: number;
23
+ /** The operator's own stores, as the deployment names them. */
24
+ export interface OwnStores {
25
+ /** The workspace named as the operator's own, or null when none is. */
26
+ orgId: string | null;
27
+ stores: OwnStore[];
28
+ }
29
+ /** Reads the operator's own stores: every site of the named workspace, with its tax origin. */
30
+ export declare function resolveOwnStores(env?: Record<string, string | undefined>): Promise<OwnStores>;
31
+ /** What the own stores' orders read for one period came to. */
32
+ export interface OwnStoreRead {
33
+ orders: OwnStoreOrderInput[];
34
+ truncated: boolean;
35
+ undatedRows: number;
36
+ }
37
+ /** Reads each own store's orders around the period. See the module note. */
38
+ export declare function readOwnStoreOrders(request: TaxReturnSourceRequest, stores: readonly OwnStore[]): Promise<OwnStoreRead>;
39
+ /**
40
+ * The own-stores section for one period, from records already read. Pure,
41
+ * so the section a preparer reads can be proved from fixtures.
42
+ */
43
+ export declare function ownStoreTaxReturnAnswer(input: {
44
+ own: OwnStores;
45
+ read: OwnStoreRead;
46
+ statedBases?: ReadonlyMap<string, number>;
47
+ }, request: TaxReturnSourceRequest): TaxReturnSourceAnswer;
@@ -0,0 +1,312 @@
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
+ * The operator's own stores on its sales tax return (AGL-4038).
19
+ *
20
+ * Everything the operator sells from a store of its own — card readers at an
21
+ * event's register, apparel online, anything it sells later — is its OWN
22
+ * sale, so it folds into the filing figures (Items 1–2 for Texas) through
23
+ * the contract's `operatorSales`, one part per store and channel, with the
24
+ * breakdown beside the figures. The rules are `model/own-store-tax-summary.ts`.
25
+ *
26
+ * Which stores: every site of the workspace `POS_HARDWARE_SELLER_ORG_ID`
27
+ * names. None named, and the card says so and folds in nothing; a merchant's
28
+ * store is never read here.
29
+ *
30
+ * Read per store: the orders placed from {@link OWN_STORE_LOOKBACK_MS}
31
+ * before the period to its end, because an order placed earlier can be paid
32
+ * (a draft) or refunded in the period. A refund or a payment more than that
33
+ * after the order was placed is not read, which the card says. A read that
34
+ * reaches the cap marks the section truncated, and orders with no placed
35
+ * stamp are counted as rows no period can reach; the platform blocks on both.
36
+ */ import { firebaseAdmin, hostDisplayName } from "@aglyn/tenant-data-admin";
37
+ import { PLATFORM_BRAND_NAME } from "@aglyn/aglyn/app-utils/platform-brand";
38
+ import { centsToDollars } from "@aglyn/aglyn/app-utils/tax-jurisdiction-figures";
39
+ import { ownStoreTaxSummary, platformOwnStoreOrgId } from "../model/own-store-tax-summary.js";
40
+ /** The section's id, unique on the return. */ export const OWN_STORE_TAX_SECTION_ID = 'ownStores';
41
+ /** How long before the period an own store's order is still read: a year and a quarter. */ export const OWN_STORE_LOOKBACK_MS = 456 * 24 * 60 * 60 * 1000;
42
+ /** The most sites of the operator's own workspace read. */ const OWN_STORE_MAX_SITES = 50;
43
+ /** Reads the operator's own stores: every site of the named workspace, with its tax origin. */ export async function resolveOwnStores(env = process.env) {
44
+ const orgId = platformOwnStoreOrgId(env);
45
+ if (!orgId) return {
46
+ orgId: null,
47
+ stores: []
48
+ };
49
+ const firestore = firebaseAdmin.app().firestore();
50
+ const hosts = await firestore.collection('hosts').where('orgId', '==', orgId).limit(OWN_STORE_MAX_SITES).get();
51
+ const stores = await Promise.all(hosts.docs.map(async (doc)=>{
52
+ var _settings_get, _settings_get1;
53
+ const settings = await firestore.collection('hosts').doc(doc.id).collection('settings').doc('store').get().catch(()=>null);
54
+ const origin = settings == null ? void 0 : (_settings_get1 = settings.get) == null ? void 0 : (_settings_get = _settings_get1.call(settings, 'tax')) == null ? void 0 : _settings_get.origin;
55
+ const country = typeof (origin == null ? void 0 : origin.country) === 'string' ? origin.country.toUpperCase() : null;
56
+ const state = typeof (origin == null ? void 0 : origin.state) === 'string' ? origin.state.toUpperCase() : null;
57
+ return {
58
+ hostId: doc.id,
59
+ name: hostDisplayName(doc.data(), doc.id),
60
+ origin: country ? {
61
+ country,
62
+ state
63
+ } : null
64
+ };
65
+ }));
66
+ return {
67
+ orgId,
68
+ stores
69
+ };
70
+ }
71
+ /** Reads each own store's orders around the period. See the module note. */ export async function readOwnStoreOrders(request, stores) {
72
+ const firestore = firebaseAdmin.app().firestore();
73
+ const from = request.start.getTime() - OWN_STORE_LOOKBACK_MS;
74
+ const until = request.end.getTime();
75
+ const reads = await Promise.all(stores.map(async (store)=>{
76
+ var _undated_data_count;
77
+ const orders = firestore.collection('hosts').doc(store.hostId).collection('orders');
78
+ const [placed, undated] = await Promise.all([
79
+ orders.where('createdAtMs', '>=', from).where('createdAtMs', '<', until).limit(request.rowCap + 1).get(),
80
+ orders.where('createdAtMs', '==', null).count().get()
81
+ ]);
82
+ return {
83
+ truncated: placed.size > request.rowCap,
84
+ undated: Number((_undated_data_count = undated.data().count) != null ? _undated_data_count : 0),
85
+ orders: placed.docs.slice(0, request.rowCap).map((doc)=>_extends({}, doc.data(), {
86
+ hostId: store.hostId,
87
+ orderId: doc.id
88
+ }))
89
+ };
90
+ }));
91
+ return {
92
+ orders: reads.flatMap((read)=>read.orders),
93
+ truncated: reads.some((read)=>read.truncated),
94
+ undatedRows: reads.reduce((sum, read)=>sum + read.undated, 0)
95
+ };
96
+ }
97
+ const dollars = (cents)=>`$${centsToDollars(cents)}`;
98
+ function ownStoreFindings(summary, filing) {
99
+ const brand = PLATFORM_BRAND_NAME;
100
+ return [
101
+ {
102
+ id: 'ownStoreUntaxed',
103
+ severity: 'review',
104
+ count: summary.attention.untaxedOrders,
105
+ label: `${brand}’s own store sales with no tax charged`,
106
+ detail: `In ${filing.figuresName} as sales, with nothing in taxable sales. If any was taxable where it was ` + `sold, the tax is still owed, out of ${brand}’s receipt.`
107
+ },
108
+ {
109
+ id: 'ownStoreMissingRegion',
110
+ severity: 'review',
111
+ count: summary.attention.ordersMissingRegion,
112
+ label: `${brand}’s own store sales with no region`,
113
+ detail: 'Listed as Not stated, and in no jurisdiction’s figures: a register sale whose store has no tax ' + 'address, or an online one with no shipping or billing address. If it was sold in ' + `${filing.label}, the figures understate it.`
114
+ },
115
+ {
116
+ id: 'ownStoreCanceledWithoutRefund',
117
+ severity: 'review',
118
+ count: summary.attention.canceledWithoutRefund,
119
+ label: `Canceled ${brand} own store orders with no refund recorded`,
120
+ detail: 'Counted as sales: the order is canceled, but no refund was recorded on it. Check the payment.'
121
+ }
122
+ ];
123
+ }
124
+ function ownStoreTables(summary, filing) {
125
+ const rows = summary.parts.flatMap((part)=>Object.entries(part.byJurisdiction).map(([jurisdiction, figures])=>({
126
+ part,
127
+ jurisdiction,
128
+ figures
129
+ })));
130
+ return [
131
+ {
132
+ description: 'Each store’s sales by where they are taxed — at the counter where the store is, online where the ' + 'order shipped — with the refunds made in this period beside them. All of it is folded into the ' + 'filing figures above.',
133
+ columns: [
134
+ {
135
+ label: 'Store and channel'
136
+ },
137
+ {
138
+ label: 'State'
139
+ },
140
+ {
141
+ label: 'Sales',
142
+ numeric: true
143
+ },
144
+ {
145
+ label: 'Total sales',
146
+ numeric: true,
147
+ money: true
148
+ },
149
+ {
150
+ label: 'Taxable sales',
151
+ numeric: true,
152
+ money: true
153
+ },
154
+ {
155
+ label: 'Tax collected',
156
+ numeric: true,
157
+ money: true
158
+ },
159
+ {
160
+ label: 'Refunded in period',
161
+ numeric: true,
162
+ money: true
163
+ }
164
+ ],
165
+ rows: rows.sort((a, b)=>Number(b.jurisdiction === filing.code) - Number(a.jurisdiction === filing.code) || a.part.label.localeCompare(b.part.label) || a.jurisdiction.localeCompare(b.jurisdiction)).map(({ part, jurisdiction, figures })=>({
166
+ key: `${part.id}:${jurisdiction}`,
167
+ cells: [
168
+ _extends({
169
+ text: part.label
170
+ }, figures.refundCount ? {
171
+ caption: `${figures.refundCount} refund${figures.refundCount === 1 ? '' : 's'} in this period`
172
+ } : {}),
173
+ _extends({
174
+ text: jurisdiction === 'unknown' ? 'Not stated' : jurisdiction
175
+ }, jurisdiction === filing.code ? {
176
+ tag: {
177
+ label: 'Registered',
178
+ tone: 'attention'
179
+ }
180
+ } : {}),
181
+ {
182
+ text: String(figures.transactionCount)
183
+ },
184
+ {
185
+ text: dollars(figures.totalSalesCents),
186
+ strong: jurisdiction === filing.code
187
+ },
188
+ {
189
+ text: dollars(figures.taxableSalesCents)
190
+ },
191
+ {
192
+ text: dollars(figures.taxCollectedCents)
193
+ },
194
+ {
195
+ text: dollars(figures.refundedSalesCents)
196
+ }
197
+ ]
198
+ })),
199
+ empty: 'Nothing was sold or refunded at the operator’s own stores in this period.',
200
+ footnote: 'A sale is in the period it was paid and a refund in the period it was made, never netted. Taxable ' + 'sales are the base Stripe stated where it computed the tax, else the whole sale less tax when tax ' + 'was charged. Test-mode sales are in no figure.'
201
+ }
202
+ ];
203
+ }
204
+ function ownStoreFigures(own, summary) {
205
+ const figures = [
206
+ {
207
+ label: 'Stores read',
208
+ value: own.stores.length ? own.stores.map((store)=>store.name).join(', ') : 'None named',
209
+ note: own.orgId ? 'Every site of the workspace named as the operator’s own (POS_HARDWARE_SELLER_ORG_ID).' : 'No workspace is named as the operator’s own (POS_HARDWARE_SELLER_ORG_ID), so no store’s sales are folded in.'
210
+ },
211
+ {
212
+ label: 'Sales paid in this period',
213
+ value: String(summary.orders),
214
+ note: 'Every store, channel and state. Live sales only. Orders placed up to 15 months before the period ' + 'are read for a payment or refund made in it; one later than that is not.'
215
+ }
216
+ ];
217
+ if (summary.excluded.testModeOrders) {
218
+ figures.push({
219
+ label: 'Test-mode sales left out',
220
+ value: String(summary.excluded.testModeOrders),
221
+ note: 'Made with Stripe’s test keys, so not sales: in no figure.'
222
+ });
223
+ }
224
+ if (summary.excluded.marketplaceRemitted) {
225
+ figures.push({
226
+ label: 'Outside marketplace sales left out',
227
+ value: String(summary.excluded.marketplaceRemitted),
228
+ note: 'Sold on an outside marketplace that collects and remits the tax itself.'
229
+ });
230
+ }
231
+ return figures;
232
+ }
233
+ function ownStoreExports(rows) {
234
+ return [
235
+ {
236
+ placement: 'sections',
237
+ rows: [
238
+ [
239
+ `${PLATFORM_BRAND_NAME}’s own store orders in this period — folded into the filing figures above`
240
+ ],
241
+ [
242
+ 'Store',
243
+ 'Order',
244
+ 'Channel',
245
+ 'Paid (UTC)',
246
+ 'Status',
247
+ 'Jurisdiction',
248
+ 'Total sales (USD)',
249
+ 'Taxable sales (USD)',
250
+ 'Taxable base',
251
+ 'Tax collected (USD)',
252
+ 'Refunded (USD)',
253
+ 'Refunded at (UTC)',
254
+ 'In this period as'
255
+ ],
256
+ ...rows.map((row)=>{
257
+ var _row_paidAt, _row_status, _row_refundedAt;
258
+ return [
259
+ row.store,
260
+ row.orderId,
261
+ row.channel === 'in-person' ? 'in person' : 'online',
262
+ (_row_paidAt = row.paidAt) != null ? _row_paidAt : '',
263
+ (_row_status = row.status) != null ? _row_status : '',
264
+ row.jurisdiction,
265
+ centsToDollars(row.totalSalesCents),
266
+ centsToDollars(row.taxableSalesCents),
267
+ row.taxableBase,
268
+ centsToDollars(row.taxCents),
269
+ centsToDollars(row.refundedCents),
270
+ (_row_refundedAt = row.refundedAt) != null ? _row_refundedAt : '',
271
+ row.inPeriodAs
272
+ ];
273
+ })
274
+ ]
275
+ }
276
+ ];
277
+ }
278
+ /**
279
+ * The own-stores section for one period, from records already read. Pure,
280
+ * so the section a preparer reads can be proved from fixtures.
281
+ */ export function ownStoreTaxReturnAnswer(input, request) {
282
+ const brand = PLATFORM_BRAND_NAME;
283
+ const { filing } = request;
284
+ const { summary, rows } = ownStoreTaxSummary({
285
+ stores: input.own.stores,
286
+ orders: input.read.orders,
287
+ period: {
288
+ start: request.start,
289
+ end: request.end
290
+ },
291
+ statedBases: input.statedBases
292
+ });
293
+ return {
294
+ id: OWN_STORE_TAX_SECTION_ID,
295
+ name: 'Own store',
296
+ title: `${brand}’s own stores — its own sales`,
297
+ help: `Everything ${brand} sold from a store of its own, in person and online: card readers, apparel and ` + 'anything else. These are its own sales, folded into the filing figures above.',
298
+ intro: `${brand} sold these itself, from its own stores, so they are its OWN sales and are folded into ` + `${filing.figuresName}, one line per store and channel in the breakdown beside the figures. ` + 'A merchant’s store is never here.',
299
+ truncated: input.read.truncated,
300
+ undatedRows: input.read.undatedRows,
301
+ findings: ownStoreFindings(summary, filing),
302
+ filingLines: [],
303
+ operatorSales: summary.parts,
304
+ tables: ownStoreTables(summary, filing),
305
+ figures: ownStoreFigures(input.own, summary),
306
+ exports: ownStoreExports(rows),
307
+ summary,
308
+ rows
309
+ };
310
+ }
311
+
312
+ //# sourceMappingURL=own-store-tax-return-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/own-store-tax-return-source.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 * The operator's own stores on its sales tax return (AGL-4038).\n *\n * Everything the operator sells from a store of its own — card readers at an\n * event's register, apparel online, anything it sells later — is its OWN\n * sale, so it folds into the filing figures (Items 1–2 for Texas) through\n * the contract's `operatorSales`, one part per store and channel, with the\n * breakdown beside the figures. The rules are `model/own-store-tax-summary.ts`.\n *\n * Which stores: every site of the workspace `POS_HARDWARE_SELLER_ORG_ID`\n * names. None named, and the card says so and folds in nothing; a merchant's\n * store is never read here.\n *\n * Read per store: the orders placed from {@link OWN_STORE_LOOKBACK_MS}\n * before the period to its end, because an order placed earlier can be paid\n * (a draft) or refunded in the period. A refund or a payment more than that\n * after the order was placed is not read, which the card says. A read that\n * reaches the cap marks the section truncated, and orders with no placed\n * stamp are counted as rows no period can reach; the platform blocks on both.\n */\n\nimport { firebaseAdmin, hostDisplayName } from '@aglyn/tenant-data-admin'\nimport { PLATFORM_BRAND_NAME } from '@aglyn/aglyn/app-utils/platform-brand'\nimport { centsToDollars } from '@aglyn/aglyn/app-utils/tax-jurisdiction-figures'\nimport type {\n TaxReturnExportBlock,\n TaxReturnFiling,\n TaxReturnFinding,\n TaxReturnSectionFigure,\n TaxReturnSectionTable,\n TaxReturnSourceAnswer,\n TaxReturnSourceRequest,\n} from '@aglyn/aglyn/plugin-manager/plugin-tax-return-sources'\nimport {\n ownStoreTaxSummary,\n platformOwnStoreOrgId,\n type OwnStore,\n type OwnStoreOrderInput,\n type OwnStoreTaxRow,\n type OwnStoreTaxSummary,\n} from '../model/own-store-tax-summary'\n\n/** The section's id, unique on the return. */\nexport const OWN_STORE_TAX_SECTION_ID = 'ownStores'\n\n/** How long before the period an own store's order is still read: a year and a quarter. */\nexport const OWN_STORE_LOOKBACK_MS = 456 * 24 * 60 * 60 * 1000\n\n/** The most sites of the operator's own workspace read. */\nconst OWN_STORE_MAX_SITES = 50\n\n/** The operator's own stores, as the deployment names them. */\nexport interface OwnStores {\n /** The workspace named as the operator's own, or null when none is. */\n orgId: string | null\n stores: OwnStore[]\n}\n\n/** Reads the operator's own stores: every site of the named workspace, with its tax origin. */\nexport async function resolveOwnStores(\n env: Record<string, string | undefined> = process.env,\n): Promise<OwnStores> {\n const orgId = platformOwnStoreOrgId(env)\n if (!orgId) return { orgId: null, stores: [] }\n const firestore = firebaseAdmin.app().firestore()\n const hosts = await firestore.collection('hosts').where('orgId', '==', orgId).limit(OWN_STORE_MAX_SITES).get()\n const stores = await Promise.all(\n hosts.docs.map(async (doc: { id: string; data: () => Record<string, unknown> }) => {\n const settings = await firestore\n .collection('hosts')\n .doc(doc.id)\n .collection('settings')\n .doc('store')\n .get()\n .catch(() => null)\n const origin = (settings?.get?.('tax') as { origin?: { country?: unknown; state?: unknown } } | undefined)\n ?.origin\n const country = typeof origin?.country === 'string' ? origin.country.toUpperCase() : null\n const state = typeof origin?.state === 'string' ? origin.state.toUpperCase() : null\n return {\n hostId: doc.id,\n name: hostDisplayName(doc.data(), doc.id),\n origin: country ? { country, state } : null,\n } satisfies OwnStore\n }),\n )\n return { orgId, stores }\n}\n\n/** What the own stores' orders read for one period came to. */\nexport interface OwnStoreRead {\n orders: OwnStoreOrderInput[]\n truncated: boolean\n undatedRows: number\n}\n\n/** Reads each own store's orders around the period. See the module note. */\nexport async function readOwnStoreOrders(\n request: TaxReturnSourceRequest,\n stores: readonly OwnStore[],\n): Promise<OwnStoreRead> {\n const firestore = firebaseAdmin.app().firestore()\n const from = request.start.getTime() - OWN_STORE_LOOKBACK_MS\n const until = request.end.getTime()\n const reads = await Promise.all(\n stores.map(async (store) => {\n const orders = firestore.collection('hosts').doc(store.hostId).collection('orders')\n const [placed, undated] = await Promise.all([\n orders.where('createdAtMs', '>=', from).where('createdAtMs', '<', until).limit(request.rowCap + 1).get(),\n orders.where('createdAtMs', '==', null).count().get(),\n ])\n return {\n truncated: placed.size > request.rowCap,\n undated: Number(undated.data().count ?? 0),\n orders: placed.docs.slice(0, request.rowCap).map(\n (doc: { id: string; data: () => Record<string, unknown> }) =>\n ({ ...(doc.data() as Omit<OwnStoreOrderInput, 'hostId' | 'orderId'>), hostId: store.hostId, orderId: doc.id }),\n ),\n }\n }),\n )\n return {\n orders: reads.flatMap((read) => read.orders),\n truncated: reads.some((read) => read.truncated),\n undatedRows: reads.reduce((sum, read) => sum + read.undated, 0),\n }\n}\n\nconst dollars = (cents: number) => `$${centsToDollars(cents)}`\n\nfunction ownStoreFindings(summary: OwnStoreTaxSummary, filing: TaxReturnFiling): TaxReturnFinding[] {\n const brand = PLATFORM_BRAND_NAME\n return [\n {\n id: 'ownStoreUntaxed',\n severity: 'review',\n count: summary.attention.untaxedOrders,\n label: `${brand}’s own store sales with no tax charged`,\n detail:\n `In ${filing.figuresName} as sales, with nothing in taxable sales. If any was taxable where it was ` +\n `sold, the tax is still owed, out of ${brand}’s receipt.`,\n },\n {\n id: 'ownStoreMissingRegion',\n severity: 'review',\n count: summary.attention.ordersMissingRegion,\n label: `${brand}’s own store sales with no region`,\n detail:\n 'Listed as Not stated, and in no jurisdiction’s figures: a register sale whose store has no tax ' +\n 'address, or an online one with no shipping or billing address. If it was sold in ' +\n `${filing.label}, the figures understate it.`,\n },\n {\n id: 'ownStoreCanceledWithoutRefund',\n severity: 'review',\n count: summary.attention.canceledWithoutRefund,\n label: `Canceled ${brand} own store orders with no refund recorded`,\n detail: 'Counted as sales: the order is canceled, but no refund was recorded on it. Check the payment.',\n },\n ]\n}\n\nfunction ownStoreTables(summary: OwnStoreTaxSummary, filing: TaxReturnFiling): TaxReturnSectionTable[] {\n const rows = summary.parts.flatMap((part) =>\n Object.entries(part.byJurisdiction).map(([jurisdiction, figures]) => ({ part, jurisdiction, figures })),\n )\n return [\n {\n description:\n 'Each store’s sales by where they are taxed — at the counter where the store is, online where the ' +\n 'order shipped — with the refunds made in this period beside them. All of it is folded into the ' +\n 'filing figures above.',\n columns: [\n { label: 'Store and channel' },\n { label: 'State' },\n { label: 'Sales', numeric: true },\n { label: 'Total sales', numeric: true, money: true },\n { label: 'Taxable sales', numeric: true, money: true },\n { label: 'Tax collected', numeric: true, money: true },\n { label: 'Refunded in period', numeric: true, money: true },\n ],\n rows: rows\n .sort(\n (a, b) =>\n Number(b.jurisdiction === filing.code) - Number(a.jurisdiction === filing.code) ||\n a.part.label.localeCompare(b.part.label) ||\n a.jurisdiction.localeCompare(b.jurisdiction),\n )\n .map(({ part, jurisdiction, figures }) => ({\n key: `${part.id}:${jurisdiction}`,\n cells: [\n {\n text: part.label,\n ...(figures.refundCount\n ? { caption: `${figures.refundCount} refund${figures.refundCount === 1 ? '' : 's'} in this period` }\n : {}),\n },\n {\n text: jurisdiction === 'unknown' ? 'Not stated' : jurisdiction,\n ...(jurisdiction === filing.code ? { tag: { label: 'Registered', tone: 'attention' as const } } : {}),\n },\n { text: String(figures.transactionCount) },\n { text: dollars(figures.totalSalesCents), strong: jurisdiction === filing.code },\n { text: dollars(figures.taxableSalesCents) },\n { text: dollars(figures.taxCollectedCents) },\n { text: dollars(figures.refundedSalesCents) },\n ],\n })),\n empty: 'Nothing was sold or refunded at the operator’s own stores in this period.',\n footnote:\n 'A sale is in the period it was paid and a refund in the period it was made, never netted. Taxable ' +\n 'sales are the base Stripe stated where it computed the tax, else the whole sale less tax when tax ' +\n 'was charged. Test-mode sales are in no figure.',\n },\n ]\n}\n\nfunction ownStoreFigures(own: OwnStores, summary: OwnStoreTaxSummary): TaxReturnSectionFigure[] {\n const figures: TaxReturnSectionFigure[] = [\n {\n label: 'Stores read',\n value: own.stores.length ? own.stores.map((store) => store.name).join(', ') : 'None named',\n note: own.orgId\n ? 'Every site of the workspace named as the operator’s own (POS_HARDWARE_SELLER_ORG_ID).'\n : 'No workspace is named as the operator’s own (POS_HARDWARE_SELLER_ORG_ID), so no store’s sales are folded in.',\n },\n {\n label: 'Sales paid in this period',\n value: String(summary.orders),\n note:\n 'Every store, channel and state. Live sales only. Orders placed up to 15 months before the period ' +\n 'are read for a payment or refund made in it; one later than that is not.',\n },\n ]\n if (summary.excluded.testModeOrders) {\n figures.push({\n label: 'Test-mode sales left out',\n value: String(summary.excluded.testModeOrders),\n note: 'Made with Stripe’s test keys, so not sales: in no figure.',\n })\n }\n if (summary.excluded.marketplaceRemitted) {\n figures.push({\n label: 'Outside marketplace sales left out',\n value: String(summary.excluded.marketplaceRemitted),\n note: 'Sold on an outside marketplace that collects and remits the tax itself.',\n })\n }\n return figures\n}\n\nfunction ownStoreExports(rows: readonly OwnStoreTaxRow[]): TaxReturnExportBlock[] {\n return [\n {\n placement: 'sections',\n rows: [\n [`${PLATFORM_BRAND_NAME}’s own store orders in this period — folded into the filing figures above`],\n [\n 'Store',\n 'Order',\n 'Channel',\n 'Paid (UTC)',\n 'Status',\n 'Jurisdiction',\n 'Total sales (USD)',\n 'Taxable sales (USD)',\n 'Taxable base',\n 'Tax collected (USD)',\n 'Refunded (USD)',\n 'Refunded at (UTC)',\n 'In this period as',\n ],\n ...rows.map((row) => [\n row.store,\n row.orderId,\n row.channel === 'in-person' ? 'in person' : 'online',\n row.paidAt ?? '',\n row.status ?? '',\n row.jurisdiction,\n centsToDollars(row.totalSalesCents),\n centsToDollars(row.taxableSalesCents),\n row.taxableBase,\n centsToDollars(row.taxCents),\n centsToDollars(row.refundedCents),\n row.refundedAt ?? '',\n row.inPeriodAs,\n ]),\n ],\n },\n ]\n}\n\n/**\n * The own-stores section for one period, from records already read. Pure,\n * so the section a preparer reads can be proved from fixtures.\n */\nexport function ownStoreTaxReturnAnswer(\n input: { own: OwnStores; read: OwnStoreRead; statedBases?: ReadonlyMap<string, number> },\n request: TaxReturnSourceRequest,\n): TaxReturnSourceAnswer {\n const brand = PLATFORM_BRAND_NAME\n const { filing } = request\n const { summary, rows } = ownStoreTaxSummary({\n stores: input.own.stores,\n orders: input.read.orders,\n period: { start: request.start, end: request.end },\n statedBases: input.statedBases,\n })\n return {\n id: OWN_STORE_TAX_SECTION_ID,\n name: 'Own store',\n title: `${brand}’s own stores — its own sales`,\n help:\n `Everything ${brand} sold from a store of its own, in person and online: card readers, apparel and ` +\n 'anything else. These are its own sales, folded into the filing figures above.',\n intro:\n `${brand} sold these itself, from its own stores, so they are its OWN sales and are folded into ` +\n `${filing.figuresName}, one line per store and channel in the breakdown beside the figures. ` +\n 'A merchant’s store is never here.',\n truncated: input.read.truncated,\n undatedRows: input.read.undatedRows,\n findings: ownStoreFindings(summary, filing),\n filingLines: [],\n operatorSales: summary.parts,\n tables: ownStoreTables(summary, filing),\n figures: ownStoreFigures(input.own, summary),\n exports: ownStoreExports(rows),\n summary,\n rows,\n }\n}\n"],"names":["firebaseAdmin","hostDisplayName","PLATFORM_BRAND_NAME","centsToDollars","ownStoreTaxSummary","platformOwnStoreOrgId","OWN_STORE_TAX_SECTION_ID","OWN_STORE_LOOKBACK_MS","OWN_STORE_MAX_SITES","resolveOwnStores","env","process","orgId","stores","firestore","app","hosts","collection","where","limit","get","Promise","all","docs","map","doc","settings","id","catch","origin","country","toUpperCase","state","hostId","name","data","readOwnStoreOrders","request","from","start","getTime","until","end","reads","store","undated","orders","placed","rowCap","count","truncated","size","Number","slice","orderId","flatMap","read","some","undatedRows","reduce","sum","dollars","cents","ownStoreFindings","summary","filing","brand","severity","attention","untaxedOrders","label","detail","figuresName","ordersMissingRegion","canceledWithoutRefund","ownStoreTables","rows","parts","part","Object","entries","byJurisdiction","jurisdiction","figures","description","columns","numeric","money","sort","a","b","code","localeCompare","key","cells","text","refundCount","caption","tag","tone","String","transactionCount","totalSalesCents","strong","taxableSalesCents","taxCollectedCents","refundedSalesCents","empty","footnote","ownStoreFigures","own","value","length","join","note","excluded","testModeOrders","push","marketplaceRemitted","ownStoreExports","placement","row","channel","paidAt","status","taxableBase","taxCents","refundedCents","refundedAt","inPeriodAs","ownStoreTaxReturnAnswer","input","period","statedBases","title","help","intro","findings","filingLines","operatorSales","tables","exports"],"mappings":"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"}
@@ -18,6 +18,8 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
18
18
  import { emailUnverifiedResponse, firebaseAdmin, getOrgForHost, isImpersonationSession, lockdownRefusal } from "@aglyn/tenant-data-admin";
19
19
  import { invalidIdTokenResponse } from "@aglyn/tenant-data-admin/server/id-token-refusal";
20
20
  import { isStorefrontPaymentMethodOn, normalizeStorefrontPaymentMethodSettings, STOREFRONT_PAYMENT_METHODS } from "../model/commerce-payment-methods.js";
21
+ import { commerceSitePermissionRefusal } from "../model/plugin-permissions.js";
22
+ import { holdsCommerceSiteKey } from "./commerce-site-keys.js";
21
23
  import { readSiteDomainRecords } from "./payment-method-domains.js";
22
24
  /** How long the platform's configuration is trusted in memory. */ const PLATFORM_CONFIGURATION_TTL_MS = 10 * 60 * 1000;
23
25
  let platformCache = null;
@@ -159,7 +161,7 @@ export async function paymentMethodsHandler(request) {
159
161
  error: 'Missing hostId'
160
162
  }, 400);
161
163
  try {
162
- var _hostSnapshot_get, _ref1, _ref2, _get;
164
+ var _ref1, _ref2, _get;
163
165
  var _owner_org;
164
166
  const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken);
165
167
  if (!decoded.email_verified && !isImpersonationSession(decoded)) {
@@ -171,17 +173,19 @@ export async function paymentMethodsHandler(request) {
171
173
  if (!hostSnapshot.exists) return json({
172
174
  error: 'Not found'
173
175
  }, 404);
174
- // An allowlist. Reading the card is for whoever manages the store; a
175
- // change asks Stripe for capabilities on the owner's payout account, so it
176
- // is an admin's, like connecting that account is the owner's.
177
- const role = ((_hostSnapshot_get = hostSnapshot.get('memberRoles')) != null ? _hostSnapshot_get : {})[decoded.uid];
178
- const mayRead = role === 'admin' || role === 'editor';
176
+ // An allowlist. Reading the card is for whoever works the store's orders
177
+ // or changes its methods; a change asks Stripe for capabilities on the
178
+ // owner's payout account, so it is "Manage payment methods" (AGL-4047),
179
+ // whose preset is the site Admin who alone made it before, as the
180
+ // reader's is the Admin and Editor.
181
+ const mayEdit = holdsCommerceSiteKey(hostSnapshot, decoded.uid, 'commerce.paymentMethods');
182
+ const mayRead = mayEdit || holdsCommerceSiteKey(hostSnapshot, decoded.uid, 'commerce.orders');
179
183
  if (!mayRead) return json({
180
184
  error: 'Not found'
181
185
  }, 404);
182
- if (method === 'POST' && role !== 'admin') {
186
+ if (method === 'POST' && !mayEdit) {
183
187
  return json({
184
- error: 'Only a site admin can change payment methods'
188
+ error: commerceSitePermissionRefusal('commerce.paymentMethods')
185
189
  }, 403);
186
190
  }
187
191
  const owner = await getOrgForHost(hostId);
@@ -266,7 +270,7 @@ export async function paymentMethodsHandler(request) {
266
270
  methods: buildPaymentMethodRows(settings, platform, capabilities),
267
271
  domains: await readSiteDomainRecords(hostSnapshot.data()),
268
272
  accountConnected: Boolean(accountId),
269
- canEdit: role === 'admin',
273
+ canEdit: mayEdit,
270
274
  canFinish: Boolean(accountId) && decoded.uid === ownerUid,
271
275
  warnings
272
276
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/payment-methods.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 { checkEntitlement, pluginRequestFromWeb } from '@aglyn/aglyn/server'\nimport type { SiteReturnHost } from '@aglyn/aglyn/app-utils/site-return-url'\nimport {\n emailUnverifiedResponse,\n firebaseAdmin,\n getOrgForHost,\n isImpersonationSession,\n lockdownRefusal,\n} from '@aglyn/tenant-data-admin'\nimport { invalidIdTokenResponse } from '@aglyn/tenant-data-admin/server/id-token-refusal'\nimport {\n isStorefrontPaymentMethodOn,\n normalizeStorefrontPaymentMethodSettings,\n STOREFRONT_PAYMENT_METHODS,\n type StorefrontPaymentMethodId,\n type StorefrontPaymentMethodSettings,\n} from '../model/commerce-payment-methods'\nimport {\n type PaymentMethodDomainRecord,\n readSiteDomainRecords,\n} from './payment-method-domains'\n\n/**\n * The merchant's payment methods card (AGL-3629):\n * `GET|POST /api/commerce/payment-methods?hostId=…`, served by the console.\n *\n * GET answers, per method, three facts the card needs and no client can read:\n *\n * - whether the PLATFORM offers it (its default payment method configuration\n * — storefront charges are destination charges with the platform as\n * merchant of record, so that configuration is the ceiling). A method the\n * platform has not turned on, or that Stripe has not made available to it,\n * is reported `unavailable` and the card does not show it at all;\n * - the connected account's capability for it, which Stripe asks platforms to\n * request before an account accepts BNPL, Cash App, Amazon Pay or crypto;\n * - the site's domain registrations, which Apple Pay depends on.\n *\n * POST saves the toggles to `hosts/{hostId}/settings/store.paymentMethods` and\n * requests the capability of each method turned on, in one account update with\n * an idempotency key. Server-side, because the toggle and the capability are\n * one decision: a toggle saved by the browser with no capability behind it\n * would read as on and never appear.\n */\n\nexport type PlatformAvailability = 'on' | 'unavailable' | null\n\nexport type CapabilityStatus = 'active' | 'pending' | 'inactive' | 'unrequested' | null\n\nexport interface PaymentMethodRow {\n id: StorefrontPaymentMethodId\n on: boolean\n platform: PlatformAvailability\n capability: CapabilityStatus\n}\n\nexport interface PaymentMethodsAnswer {\n methods: PaymentMethodRow[]\n domains: PaymentMethodDomainRecord[]\n accountConnected: boolean\n /** The caller may save toggles: a site admin. */\n canEdit: boolean\n /** The caller may open Stripe to finish a method: the organization owner. */\n canFinish: boolean\n warnings: string[]\n}\n\n/** How long the platform's configuration is trusted in memory. */\nconst PLATFORM_CONFIGURATION_TTL_MS = 10 * 60 * 1000\n\nlet platformCache: { at: number; value: Record<string, PlatformAvailability> } | null = null\n\n/** Test seam: forget the cached platform configuration. */\nexport function resetPlatformPaymentMethodCacheForTests(): void {\n platformCache = null\n}\n\nasync function stripe<T>(\n method: 'GET' | 'POST',\n path: string,\n params?: URLSearchParams,\n idempotencyKey?: string,\n): Promise<T> {\n const query = method === 'GET' && params ? `?${params}` : ''\n const response = await fetch(`https://api.stripe.com/v1/${path}${query}`, {\n method,\n headers: {\n Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}`,\n ...(method === 'POST' && { 'Content-Type': 'application/x-www-form-urlencoded' }),\n ...(idempotencyKey && { 'Idempotency-Key': idempotencyKey }),\n },\n ...(method === 'POST' && params && { body: params.toString() }),\n })\n const payload = (await response.json().catch(() => ({}))) as T & {\n error?: { message?: string }\n }\n if (!response.ok) {\n throw new Error(payload?.error?.message ?? `Stripe ${path} failed (${response.status})`)\n }\n return payload\n}\n\ninterface StripeConfiguration {\n is_default?: boolean\n application?: string | null\n active?: boolean\n [key: string]: unknown\n}\n\n/**\n * Which methods the platform's own default configuration offers. The list\n * also returns configurations OTHER Connect applications made for this\n * account (`application` set); those do not govern our sessions and are\n * skipped. `null` per method when Stripe could not be asked — the card then\n * shows the toggle without a verdict rather than hiding a method that may work.\n */\nexport async function platformPaymentMethodAvailability(): Promise<\n Record<string, PlatformAvailability>\n> {\n if (platformCache && Date.now() - platformCache.at < PLATFORM_CONFIGURATION_TTL_MS) {\n return platformCache.value\n }\n const value: Record<string, PlatformAvailability> = {}\n try {\n const list = await stripe<{ data?: StripeConfiguration[] }>(\n 'GET',\n 'payment_method_configurations',\n new URLSearchParams({ limit: '20' }),\n )\n const own =\n list.data?.find((entry) => entry.is_default && !entry.application) ??\n list.data?.find((entry) => !entry.application) ??\n null\n for (const method of STOREFRONT_PAYMENT_METHODS) {\n if (!own) {\n value[method.id] = null\n continue\n }\n const entry = own[method.configurationKey] as\n | { available?: boolean; display_preference?: { value?: string } }\n | undefined\n value[method.id] =\n entry?.available === true && entry?.display_preference?.value === 'on'\n ? 'on'\n : 'unavailable'\n }\n platformCache = { at: Date.now(), value }\n } catch (error) {\n console.warn('[commerce] payment method configuration unreadable', error)\n for (const method of STOREFRONT_PAYMENT_METHODS) value[method.id] = null\n }\n return value\n}\n\nfunction capabilityStatus(\n capabilities: Record<string, string> | undefined,\n key: string | undefined,\n): CapabilityStatus {\n if (!key) return null\n const status = capabilities?.[key]\n if (status === 'active' || status === 'pending' || status === 'inactive') return status\n return 'unrequested'\n}\n\nasync function readAccountCapabilities(\n accountId: string | null,\n): Promise<Record<string, string> | undefined> {\n if (!accountId) return undefined\n try {\n const account = await stripe<{ capabilities?: Record<string, string> }>(\n 'GET',\n `accounts/${encodeURIComponent(accountId)}`,\n )\n return account.capabilities ?? {}\n } catch (error) {\n console.warn('[commerce] connected account unreadable', error)\n return undefined\n }\n}\n\n/** The capabilities a save asks Stripe for: on, offered, not yet requested. */\nexport function capabilitiesToRequest(\n settings: StorefrontPaymentMethodSettings,\n platform: Record<string, PlatformAvailability>,\n capabilities: Record<string, string> | undefined,\n): string[] {\n return STOREFRONT_PAYMENT_METHODS.filter(\n (method) =>\n method.capability &&\n isStorefrontPaymentMethodOn(settings, method.id) &&\n platform[method.id] !== 'unavailable' &&\n capabilityStatus(capabilities, method.capability) === 'unrequested',\n ).map((method) => method.capability as string)\n}\n\nexport function buildPaymentMethodRows(\n settings: StorefrontPaymentMethodSettings,\n platform: Record<string, PlatformAvailability>,\n capabilities: Record<string, string> | undefined,\n): PaymentMethodRow[] {\n return STOREFRONT_PAYMENT_METHODS.map((method) => ({\n id: method.id,\n on: isStorefrontPaymentMethodOn(settings, method.id),\n platform: platform[method.id] ?? null,\n capability: capabilities ? capabilityStatus(capabilities, method.capability) : null,\n }))\n}\n\nconst json = (body: unknown, status = 200) => Response.json(body, { status })\n\n/**\n * Where Stripe sends the owner back: the console page they pressed the button\n * on, judged against the request's own origin so a forged `Referer` cannot\n * turn the link into a redirect to somewhere else.\n */\nexport function consoleReturnUrl(headers: Partial<Record<string, string>>): string {\n const origin = headers.origin || (headers.host ? `https://${headers.host}` : '')\n const referer = headers.referer ?? ''\n try {\n if (origin && referer && new URL(referer).origin === new URL(origin).origin) {\n return referer\n }\n } catch {\n // Unparseable: fall through to the origin.\n }\n return origin || 'https://localhost/'\n}\n\nexport async function paymentMethodsHandler(request: Request): Promise<Response> {\n const { method, headers: rawHeaders, query, body } = await pluginRequestFromWeb(request)\n const headers = rawHeaders as Partial<Record<string, string>>\n if (method !== 'GET' && method !== 'POST') {\n return json({ error: 'Method not allowed' }, 405)\n }\n if (!process.env.STRIPE_SECRET_KEY) {\n return json({ error: 'Payments are not configured (STRIPE_SECRET_KEY).' }, 501)\n }\n const authorization = headers.authorization ?? ''\n const idToken = authorization.startsWith('Bearer ')\n ? authorization.slice('Bearer '.length)\n : undefined\n if (!idToken) return json({ error: 'Unauthenticated' }, 401)\n\n const parsed =\n typeof body === 'string' ? (JSON.parse(body || '{}') as Record<string, unknown>) : (body ?? {})\n const hostId = String(\n (method === 'GET' ? query?.['hostId'] : (parsed as Record<string, unknown>)['hostId']) ?? '',\n )\n if (!hostId) return json({ error: 'Missing hostId' }, 400)\n\n try {\n const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n if (!decoded.email_verified && !isImpersonationSession(decoded)) {\n return emailUnverifiedResponse()\n }\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = firestore.collection('hosts').doc(hostId)\n const hostSnapshot = await hostRef.get()\n if (!hostSnapshot.exists) return json({ error: 'Not found' }, 404)\n\n // An allowlist. Reading the card is for whoever manages the store; a\n // change asks Stripe for capabilities on the owner's payout account, so it\n // is an admin's, like connecting that account is the owner's.\n const role = (hostSnapshot.get('memberRoles') ?? {})[decoded.uid]\n const mayRead = role === 'admin' || role === 'editor'\n if (!mayRead) return json({ error: 'Not found' }, 404)\n if (method === 'POST' && role !== 'admin') {\n return json({ error: 'Only a site admin can change payment methods' }, 403)\n }\n\n const owner = await getOrgForHost(hostId)\n const locked = await lockdownRefusal({\n request,\n staff: decoded['staff'] === true,\n uid: decoded.uid,\n org: owner?.org,\n host: hostSnapshot.data(),\n })\n if (locked) return locked\n if (!checkEntitlement((owner?.org ?? {}) as never, 'commerce')) {\n return json({ error: 'Selling is not included on this plan' }, 402)\n }\n\n const ownerUid = String(owner?.org?.ownerUid ?? '')\n const accountId = ownerUid\n ? (((await firestore.collection('profiles').doc(ownerUid).get()).get(\n 'stripeAccountId',\n ) as string | undefined) ?? null)\n : null\n\n const storeRef = hostRef.collection('settings').doc('store')\n let settings = normalizeStorefrontPaymentMethodSettings(\n (await storeRef.get()).get('paymentMethods'),\n )\n const platform = await platformPaymentMethodAvailability()\n let capabilities = await readAccountCapabilities(accountId)\n const warnings: string[] = []\n\n // FINISH IN STRIPE: a capability Stripe holds `inactive` needs details\n // only the account holder can give, and an Express account has no login of\n // its own, so a link minted here is the only way in. The owner's alone,\n // as connecting the account is (`connect.ts`): the link opens the owner's\n // identity and bank details.\n if (method === 'POST' && (parsed as Record<string, unknown>)['action'] === 'finish') {\n if (!accountId || decoded.uid !== ownerUid) {\n return json({ error: 'Only the organization owner can finish this in Stripe' }, 403)\n }\n const back = consoleReturnUrl(headers)\n const link = await stripe<{ url?: string }>(\n 'POST',\n 'account_links',\n new URLSearchParams({\n account: accountId,\n type: 'account_onboarding',\n 'collection_options[fields]': 'currently_due',\n refresh_url: back,\n return_url: back,\n }),\n )\n return json({ url: link.url ?? null })\n }\n\n if (method === 'POST') {\n const requested = normalizeStorefrontPaymentMethodSettings(\n (parsed as Record<string, unknown>)['methods'],\n )\n if (!Object.keys(requested).length) {\n return json({ error: 'Nothing to save' }, 400)\n }\n settings = { ...settings, ...requested }\n await storeRef.set(\n { paymentMethods: settings, paymentMethodsUpdatedAtMs: Date.now(), paymentMethodsUpdatedBy: decoded.uid },\n { merge: true },\n )\n const wanted = accountId ? capabilitiesToRequest(settings, platform, capabilities) : []\n if (accountId && wanted.length) {\n const params = new URLSearchParams()\n for (const capability of wanted) {\n params.set(`capabilities[${capability}][requested]`, 'true')\n }\n try {\n const account = await stripe<{ capabilities?: Record<string, string> }>(\n 'POST',\n `accounts/${encodeURIComponent(accountId)}`,\n params,\n `aglyn-pm-capabilities:${accountId}:${[...wanted].sort().join(',')}`,\n )\n capabilities = account.capabilities ?? capabilities\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n warnings.push(\n `Stripe did not accept the request to enable ${wanted.join(', ')} on your payout account: ${message}`,\n )\n }\n }\n }\n\n const answer: PaymentMethodsAnswer = {\n methods: buildPaymentMethodRows(settings, platform, capabilities),\n domains: await readSiteDomainRecords(hostSnapshot.data() as SiteReturnHost | undefined),\n accountConnected: Boolean(accountId),\n canEdit: role === 'admin',\n canFinish: Boolean(accountId) && decoded.uid === ownerUid,\n warnings,\n }\n return json(answer)\n } catch (error) {\n const unauthenticated = invalidIdTokenResponse(error)\n if (unauthenticated) return unauthenticated\n console.error(error)\n return json({ error: 'Payment methods could not be loaded' }, 500)\n }\n}\n"],"names":["checkEntitlement","pluginRequestFromWeb","emailUnverifiedResponse","firebaseAdmin","getOrgForHost","isImpersonationSession","lockdownRefusal","invalidIdTokenResponse","isStorefrontPaymentMethodOn","normalizeStorefrontPaymentMethodSettings","STOREFRONT_PAYMENT_METHODS","readSiteDomainRecords","PLATFORM_CONFIGURATION_TTL_MS","platformCache","resetPlatformPaymentMethodCacheForTests","stripe","method","path","params","idempotencyKey","query","response","fetch","headers","Authorization","process","env","STRIPE_SECRET_KEY","body","toString","payload","json","catch","ok","Error","error","message","status","platformPaymentMethodAvailability","Date","now","at","value","list","URLSearchParams","limit","own","data","find","entry","is_default","application","id","configurationKey","available","display_preference","console","warn","capabilityStatus","capabilities","key","readAccountCapabilities","accountId","undefined","account","encodeURIComponent","capabilitiesToRequest","settings","platform","filter","capability","map","buildPaymentMethodRows","on","Response","consoleReturnUrl","origin","host","referer","URL","paymentMethodsHandler","request","rawHeaders","authorization","idToken","startsWith","slice","length","parsed","JSON","parse","hostId","String","hostSnapshot","owner","decoded","app","auth","verifyIdToken","email_verified","firestore","hostRef","collection","doc","get","exists","role","uid","mayRead","locked","staff","org","ownerUid","storeRef","warnings","link","back","type","refresh_url","return_url","url","requested","Object","keys","set","paymentMethods","paymentMethodsUpdatedAtMs","paymentMethodsUpdatedBy","merge","wanted","sort","join","push","answer","methods","domains","accountConnected","Boolean","canEdit","canFinish","unauthenticated"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,gBAAgB,EAAEC,oBAAoB,QAAQ,sBAAqB;AAE5E,SACEC,uBAAuB,EACvBC,aAAa,EACbC,aAAa,EACbC,sBAAsB,EACtBC,eAAe,QACV,2BAA0B;AACjC,SAASC,sBAAsB,QAAQ,mDAAkD;AACzF,SACEC,2BAA2B,EAC3BC,wCAAwC,EACxCC,0BAA0B,QAGrB,uCAAmC;AAC1C,SAEEC,qBAAqB,QAChB,8BAA0B;AA8CjC,gEAAgE,GAChE,MAAMC,gCAAgC,KAAK,KAAK;AAEhD,IAAIC,gBAAoF;AAExF,yDAAyD,GACzD,OAAO,SAASC;IACdD,gBAAgB;AAClB;AAEA,eAAeE,OACbC,MAAsB,EACtBC,IAAY,EACZC,MAAwB,EACxBC,cAAuB;IAEvB,MAAMC,QAAQJ,WAAW,SAASE,SAAS,CAAC,CAAC,EAAEA,QAAQ,GAAG;IAC1D,MAAMG,WAAW,MAAMC,MAAM,CAAC,0BAA0B,EAAEL,OAAOG,OAAO,EAAE;QACxEJ;QACAO,SAAS;YACPC,eAAe,CAAC,OAAO,EAAEC,QAAQC,GAAG,CAACC,iBAAiB,EAAE;WACpDX,WAAW,UAAU;YAAE,gBAAgB;QAAoC,GAC3EG,kBAAkB;YAAE,mBAAmBA;QAAe;OAExDH,WAAW,UAAUE,UAAU;QAAEU,MAAMV,OAAOW,QAAQ;IAAG;IAE/D,MAAMC,UAAW,MAAMT,SAASU,IAAI,GAAGC,KAAK,CAAC,IAAO,CAAA,CAAC,CAAA;IAGrD,IAAI,CAACX,SAASY,EAAE,EAAE;;YACAH;QAAhB,MAAM,IAAII,cAAMJ,4BAAAA,iBAAAA,QAASK,KAAK,qBAAdL,eAAgBM,OAAO,mBAAI,CAAC,OAAO,EAAEnB,KAAK,SAAS,EAAEI,SAASgB,MAAM,CAAC,CAAC,CAAC;IACzF;IACA,OAAOP;AACT;AASA;;;;;;CAMC,GACD,OAAO,eAAeQ;IAGpB,IAAIzB,iBAAiB0B,KAAKC,GAAG,KAAK3B,cAAc4B,EAAE,GAAG7B,+BAA+B;QAClF,OAAOC,cAAc6B,KAAK;IAC5B;IACA,MAAMA,QAA8C,CAAC;IACrD,IAAI;YAOAC;YAAAA,YACAA;QAPF,MAAMA,OAAO,MAAM5B,OACjB,OACA,iCACA,IAAI6B,gBAAgB;YAAEC,OAAO;QAAK;QAEpC,MAAMC,OACJH,iBAAAA,aAAAA,KAAKI,IAAI,qBAATJ,WAAWK,IAAI,CAAC,CAACC,QAAUA,MAAMC,UAAU,IAAI,CAACD,MAAME,WAAW,sBACjER,cAAAA,KAAKI,IAAI,qBAATJ,YAAWK,IAAI,CAAC,CAACC,QAAU,CAACA,MAAME,WAAW,aAD7CR,OAEA;QACF,KAAK,MAAM3B,UAAUN,2BAA4B;gBAShBuC;YAR/B,IAAI,CAACH,KAAK;gBACRJ,KAAK,CAAC1B,OAAOoC,EAAE,CAAC,GAAG;gBACnB;YACF;YACA,MAAMH,QAAQH,GAAG,CAAC9B,OAAOqC,gBAAgB,CAAC;YAG1CX,KAAK,CAAC1B,OAAOoC,EAAE,CAAC,GACdH,CAAAA,yBAAAA,MAAOK,SAAS,MAAK,QAAQL,CAAAA,0BAAAA,4BAAAA,MAAOM,kBAAkB,qBAAzBN,0BAA2BP,KAAK,MAAK,OAC9D,OACA;QACR;QACA7B,gBAAgB;YAAE4B,IAAIF,KAAKC,GAAG;YAAIE;QAAM;IAC1C,EAAE,OAAOP,OAAO;QACdqB,QAAQC,IAAI,CAAC,sDAAsDtB;QACnE,KAAK,MAAMnB,UAAUN,2BAA4BgC,KAAK,CAAC1B,OAAOoC,EAAE,CAAC,GAAG;IACtE;IACA,OAAOV;AACT;AAEA,SAASgB,iBACPC,YAAgD,EAChDC,GAAuB;IAEvB,IAAI,CAACA,KAAK,OAAO;IACjB,MAAMvB,SAASsB,gCAAAA,YAAc,CAACC,IAAI;IAClC,IAAIvB,WAAW,YAAYA,WAAW,aAAaA,WAAW,YAAY,OAAOA;IACjF,OAAO;AACT;AAEA,eAAewB,wBACbC,SAAwB;IAExB,IAAI,CAACA,WAAW,OAAOC;IACvB,IAAI;YAKKC;QAJP,MAAMA,UAAU,MAAMjD,OACpB,OACA,CAAC,SAAS,EAAEkD,mBAAmBH,YAAY;QAE7C,QAAOE,wBAAAA,QAAQL,YAAY,YAApBK,wBAAwB,CAAC;IAClC,EAAE,OAAO7B,OAAO;QACdqB,QAAQC,IAAI,CAAC,2CAA2CtB;QACxD,OAAO4B;IACT;AACF;AAEA,6EAA6E,GAC7E,OAAO,SAASG,sBACdC,QAAyC,EACzCC,QAA8C,EAC9CT,YAAgD;IAEhD,OAAOjD,2BAA2B2D,MAAM,CACtC,CAACrD,SACCA,OAAOsD,UAAU,IACjB9D,4BAA4B2D,UAAUnD,OAAOoC,EAAE,KAC/CgB,QAAQ,CAACpD,OAAOoC,EAAE,CAAC,KAAK,iBACxBM,iBAAiBC,cAAc3C,OAAOsD,UAAU,MAAM,eACxDC,GAAG,CAAC,CAACvD,SAAWA,OAAOsD,UAAU;AACrC;AAEA,OAAO,SAASE,uBACdL,QAAyC,EACzCC,QAA8C,EAC9CT,YAAgD;IAEhD,OAAOjD,2BAA2B6D,GAAG,CAAC,CAACvD;YAG3BoD;eAHuC;YACjDhB,IAAIpC,OAAOoC,EAAE;YACbqB,IAAIjE,4BAA4B2D,UAAUnD,OAAOoC,EAAE;YACnDgB,QAAQ,GAAEA,sBAAAA,QAAQ,CAACpD,OAAOoC,EAAE,CAAC,YAAnBgB,sBAAuB;YACjCE,YAAYX,eAAeD,iBAAiBC,cAAc3C,OAAOsD,UAAU,IAAI;QACjF;;AACF;AAEA,MAAMvC,OAAO,CAACH,MAAeS,SAAS,GAAG,GAAKqC,SAAS3C,IAAI,CAACH,MAAM;QAAES;IAAO;AAE3E;;;;CAIC,GACD,OAAO,SAASsC,iBAAiBpD,OAAwC;QAEvDA;IADhB,MAAMqD,SAASrD,QAAQqD,MAAM,IAAKrD,CAAAA,QAAQsD,IAAI,GAAG,CAAC,QAAQ,EAAEtD,QAAQsD,IAAI,EAAE,GAAG,EAAC;IAC9E,MAAMC,WAAUvD,mBAAAA,QAAQuD,OAAO,YAAfvD,mBAAmB;IACnC,IAAI;QACF,IAAIqD,UAAUE,WAAW,IAAIC,IAAID,SAASF,MAAM,KAAK,IAAIG,IAAIH,QAAQA,MAAM,EAAE;YAC3E,OAAOE;QACT;IACF,EAAE,eAAM;IACN,2CAA2C;IAC7C;IACA,OAAOF,UAAU;AACnB;AAEA,OAAO,eAAeI,sBAAsBC,OAAgB;QASpC1D,wBASnBP;IAjBH,MAAM,EAAEA,MAAM,EAAEO,SAAS2D,UAAU,EAAE9D,KAAK,EAAEQ,IAAI,EAAE,GAAG,MAAM3B,qBAAqBgF;IAChF,MAAM1D,UAAU2D;IAChB,IAAIlE,WAAW,SAASA,WAAW,QAAQ;QACzC,OAAOe,KAAK;YAAEI,OAAO;QAAqB,GAAG;IAC/C;IACA,IAAI,CAACV,QAAQC,GAAG,CAACC,iBAAiB,EAAE;QAClC,OAAOI,KAAK;YAAEI,OAAO;QAAmD,GAAG;IAC7E;IACA,MAAMgD,iBAAgB5D,yBAAAA,QAAQ4D,aAAa,YAArB5D,yBAAyB;IAC/C,MAAM6D,UAAUD,cAAcE,UAAU,CAAC,aACrCF,cAAcG,KAAK,CAAC,UAAUC,MAAM,IACpCxB;IACJ,IAAI,CAACqB,SAAS,OAAOrD,KAAK;QAAEI,OAAO;IAAkB,GAAG;IAExD,MAAMqD,SACJ,OAAO5D,SAAS,WAAY6D,KAAKC,KAAK,CAAC9D,QAAQ,QAAqCA,eAAAA,OAAQ,CAAC;IAC/F,MAAM+D,SAASC,QACZ5E,OAAAA,WAAW,QAAQI,yBAAAA,KAAO,CAAC,SAAS,GAAG,AAACoE,MAAkC,CAAC,SAAS,YAApFxE,OAAyF;IAE5F,IAAI,CAAC2E,QAAQ,OAAO5D,KAAK;QAAEI,OAAO;IAAiB,GAAG;IAEtD,IAAI;YAaY0D,iCAsBR;YAFkBC;QAhCxB,MAAMC,UAAU,MAAM5F,cAAc6F,GAAG,GAAGC,IAAI,GAAGC,aAAa,CAACd;QAC/D,IAAI,CAACW,QAAQI,cAAc,IAAI,CAAC9F,uBAAuB0F,UAAU;YAC/D,OAAO7F;QACT;QACA,MAAMkG,YAAYjG,cAAc6F,GAAG,GAAGI,SAAS;QAC/C,MAAMC,UAAUD,UAAUE,UAAU,CAAC,SAASC,GAAG,CAACZ;QAClD,MAAME,eAAe,MAAMQ,QAAQG,GAAG;QACtC,IAAI,CAACX,aAAaY,MAAM,EAAE,OAAO1E,KAAK;YAAEI,OAAO;QAAY,GAAG;QAE9D,qEAAqE;QACrE,2EAA2E;QAC3E,8DAA8D;QAC9D,MAAMuE,OAAO,EAACb,oBAAAA,aAAaW,GAAG,CAAC,0BAAjBX,oBAAmC,CAAC,EAAE,CAACE,QAAQY,GAAG,CAAC;QACjE,MAAMC,UAAUF,SAAS,WAAWA,SAAS;QAC7C,IAAI,CAACE,SAAS,OAAO7E,KAAK;YAAEI,OAAO;QAAY,GAAG;QAClD,IAAInB,WAAW,UAAU0F,SAAS,SAAS;YACzC,OAAO3E,KAAK;gBAAEI,OAAO;YAA+C,GAAG;QACzE;QAEA,MAAM2D,QAAQ,MAAM1F,cAAcuF;QAClC,MAAMkB,SAAS,MAAMvG,gBAAgB;YACnC2E;YACA6B,OAAOf,OAAO,CAAC,QAAQ,KAAK;YAC5BY,KAAKZ,QAAQY,GAAG;YAChBI,GAAG,EAAEjB,yBAAAA,MAAOiB,GAAG;YACflC,MAAMgB,aAAa9C,IAAI;QACzB;QACA,IAAI8D,QAAQ,OAAOA;QACnB,IAAI,CAAC7G,0BAAkB8F,yBAAAA,MAAOiB,GAAG,oBAAI,CAAC,GAAa,aAAa;YAC9D,OAAOhF,KAAK;gBAAEI,OAAO;YAAuC,GAAG;QACjE;QAEA,MAAM6E,WAAWpB,gBAAOE,0BAAAA,aAAAA,MAAOiB,GAAG,qBAAVjB,WAAYkB,QAAQ,oBAAI;QAChD,MAAMlD,YAAYkD,YACZ,OAAA,AAAC,CAAA,MAAMZ,UAAUE,UAAU,CAAC,YAAYC,GAAG,CAACS,UAAUR,GAAG,EAAC,EAAGA,GAAG,CAChE,8BADA,OAE0B,OAC5B;QAEJ,MAAMS,WAAWZ,QAAQC,UAAU,CAAC,YAAYC,GAAG,CAAC;QACpD,IAAIpC,WAAW1D,yCACb,AAAC,CAAA,MAAMwG,SAAST,GAAG,EAAC,EAAGA,GAAG,CAAC;QAE7B,MAAMpC,WAAW,MAAM9B;QACvB,IAAIqB,eAAe,MAAME,wBAAwBC;QACjD,MAAMoD,WAAqB,EAAE;QAE7B,uEAAuE;QACvE,2EAA2E;QAC3E,wEAAwE;QACxE,0EAA0E;QAC1E,6BAA6B;QAC7B,IAAIlG,WAAW,UAAU,AAACwE,MAAkC,CAAC,SAAS,KAAK,UAAU;gBAgBhE2B;YAfnB,IAAI,CAACrD,aAAaiC,QAAQY,GAAG,KAAKK,UAAU;gBAC1C,OAAOjF,KAAK;oBAAEI,OAAO;gBAAwD,GAAG;YAClF;YACA,MAAMiF,OAAOzC,iBAAiBpD;YAC9B,MAAM4F,OAAO,MAAMpG,OACjB,QACA,iBACA,IAAI6B,gBAAgB;gBAClBoB,SAASF;gBACTuD,MAAM;gBACN,8BAA8B;gBAC9BC,aAAaF;gBACbG,YAAYH;YACd;YAEF,OAAOrF,KAAK;gBAAEyF,GAAG,GAAEL,YAAAA,KAAKK,GAAG,YAARL,YAAY;YAAK;QACtC;QAEA,IAAInG,WAAW,QAAQ;YACrB,MAAMyG,YAAYhH,yCAChB,AAAC+E,MAAkC,CAAC,UAAU;YAEhD,IAAI,CAACkC,OAAOC,IAAI,CAACF,WAAWlC,MAAM,EAAE;gBAClC,OAAOxD,KAAK;oBAAEI,OAAO;gBAAkB,GAAG;YAC5C;YACAgC,WAAW,aAAKA,UAAasD;YAC7B,MAAMR,SAASW,GAAG,CAChB;gBAAEC,gBAAgB1D;gBAAU2D,2BAA2BvF,KAAKC,GAAG;gBAAIuF,yBAAyBhC,QAAQY,GAAG;YAAC,GACxG;gBAAEqB,OAAO;YAAK;YAEhB,MAAMC,SAASnE,YAAYI,sBAAsBC,UAAUC,UAAUT,gBAAgB,EAAE;YACvF,IAAIG,aAAamE,OAAO1C,MAAM,EAAE;gBAC9B,MAAMrE,SAAS,IAAI0B;gBACnB,KAAK,MAAM0B,cAAc2D,OAAQ;oBAC/B/G,OAAO0G,GAAG,CAAC,CAAC,aAAa,EAAEtD,WAAW,YAAY,CAAC,EAAE;gBACvD;gBACA,IAAI;wBAOaN;oBANf,MAAMA,UAAU,MAAMjD,OACpB,QACA,CAAC,SAAS,EAAEkD,mBAAmBH,YAAY,EAC3C5C,QACA,CAAC,sBAAsB,EAAE4C,UAAU,CAAC,EAAE;2BAAImE;qBAAO,CAACC,IAAI,GAAGC,IAAI,CAAC,MAAM;oBAEtExE,gBAAeK,wBAAAA,QAAQL,YAAY,YAApBK,wBAAwBL;gBACzC,EAAE,OAAOxB,OAAO;oBACd,MAAMC,UAAUD,iBAAiBD,QAAQC,MAAMC,OAAO,GAAGwD,OAAOzD;oBAChE+E,SAASkB,IAAI,CACX,CAAC,4CAA4C,EAAEH,OAAOE,IAAI,CAAC,MAAM,yBAAyB,EAAE/F,SAAS;gBAEzG;YACF;QACF;QAEA,MAAMiG,SAA+B;YACnCC,SAAS9D,uBAAuBL,UAAUC,UAAUT;YACpD4E,SAAS,MAAM5H,sBAAsBkF,aAAa9C,IAAI;YACtDyF,kBAAkBC,QAAQ3E;YAC1B4E,SAAShC,SAAS;YAClBiC,WAAWF,QAAQ3E,cAAciC,QAAQY,GAAG,KAAKK;YACjDE;QACF;QACA,OAAOnF,KAAKsG;IACd,EAAE,OAAOlG,OAAO;QACd,MAAMyG,kBAAkBrI,uBAAuB4B;QAC/C,IAAIyG,iBAAiB,OAAOA;QAC5BpF,QAAQrB,KAAK,CAACA;QACd,OAAOJ,KAAK;YAAEI,OAAO;QAAsC,GAAG;IAChE;AACF"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/payment-methods.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 { checkEntitlement, pluginRequestFromWeb } from '@aglyn/aglyn/server'\nimport type { SiteReturnHost } from '@aglyn/aglyn/app-utils/site-return-url'\nimport {\n emailUnverifiedResponse,\n firebaseAdmin,\n getOrgForHost,\n isImpersonationSession,\n lockdownRefusal,\n} from '@aglyn/tenant-data-admin'\nimport { invalidIdTokenResponse } from '@aglyn/tenant-data-admin/server/id-token-refusal'\nimport {\n isStorefrontPaymentMethodOn,\n normalizeStorefrontPaymentMethodSettings,\n STOREFRONT_PAYMENT_METHODS,\n type StorefrontPaymentMethodId,\n type StorefrontPaymentMethodSettings,\n} from '../model/commerce-payment-methods'\nimport { commerceSitePermissionRefusal } from '../model/plugin-permissions'\nimport { holdsCommerceSiteKey } from './commerce-site-keys'\nimport {\n type PaymentMethodDomainRecord,\n readSiteDomainRecords,\n} from './payment-method-domains'\n\n/**\n * The merchant's payment methods card (AGL-3629):\n * `GET|POST /api/commerce/payment-methods?hostId=…`, served by the console.\n *\n * GET answers, per method, three facts the card needs and no client can read:\n *\n * - whether the PLATFORM offers it (its default payment method configuration\n * — storefront charges are destination charges with the platform as\n * merchant of record, so that configuration is the ceiling). A method the\n * platform has not turned on, or that Stripe has not made available to it,\n * is reported `unavailable` and the card does not show it at all;\n * - the connected account's capability for it, which Stripe asks platforms to\n * request before an account accepts BNPL, Cash App, Amazon Pay or crypto;\n * - the site's domain registrations, which Apple Pay depends on.\n *\n * POST saves the toggles to `hosts/{hostId}/settings/store.paymentMethods` and\n * requests the capability of each method turned on, in one account update with\n * an idempotency key. Server-side, because the toggle and the capability are\n * one decision: a toggle saved by the browser with no capability behind it\n * would read as on and never appear.\n */\n\nexport type PlatformAvailability = 'on' | 'unavailable' | null\n\nexport type CapabilityStatus = 'active' | 'pending' | 'inactive' | 'unrequested' | null\n\nexport interface PaymentMethodRow {\n id: StorefrontPaymentMethodId\n on: boolean\n platform: PlatformAvailability\n capability: CapabilityStatus\n}\n\nexport interface PaymentMethodsAnswer {\n methods: PaymentMethodRow[]\n domains: PaymentMethodDomainRecord[]\n accountConnected: boolean\n /** The caller may save toggles: a site admin. */\n canEdit: boolean\n /** The caller may open Stripe to finish a method: the organization owner. */\n canFinish: boolean\n warnings: string[]\n}\n\n/** How long the platform's configuration is trusted in memory. */\nconst PLATFORM_CONFIGURATION_TTL_MS = 10 * 60 * 1000\n\nlet platformCache: { at: number; value: Record<string, PlatformAvailability> } | null = null\n\n/** Test seam: forget the cached platform configuration. */\nexport function resetPlatformPaymentMethodCacheForTests(): void {\n platformCache = null\n}\n\nasync function stripe<T>(\n method: 'GET' | 'POST',\n path: string,\n params?: URLSearchParams,\n idempotencyKey?: string,\n): Promise<T> {\n const query = method === 'GET' && params ? `?${params}` : ''\n const response = await fetch(`https://api.stripe.com/v1/${path}${query}`, {\n method,\n headers: {\n Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}`,\n ...(method === 'POST' && { 'Content-Type': 'application/x-www-form-urlencoded' }),\n ...(idempotencyKey && { 'Idempotency-Key': idempotencyKey }),\n },\n ...(method === 'POST' && params && { body: params.toString() }),\n })\n const payload = (await response.json().catch(() => ({}))) as T & {\n error?: { message?: string }\n }\n if (!response.ok) {\n throw new Error(payload?.error?.message ?? `Stripe ${path} failed (${response.status})`)\n }\n return payload\n}\n\ninterface StripeConfiguration {\n is_default?: boolean\n application?: string | null\n active?: boolean\n [key: string]: unknown\n}\n\n/**\n * Which methods the platform's own default configuration offers. The list\n * also returns configurations OTHER Connect applications made for this\n * account (`application` set); those do not govern our sessions and are\n * skipped. `null` per method when Stripe could not be asked — the card then\n * shows the toggle without a verdict rather than hiding a method that may work.\n */\nexport async function platformPaymentMethodAvailability(): Promise<\n Record<string, PlatformAvailability>\n> {\n if (platformCache && Date.now() - platformCache.at < PLATFORM_CONFIGURATION_TTL_MS) {\n return platformCache.value\n }\n const value: Record<string, PlatformAvailability> = {}\n try {\n const list = await stripe<{ data?: StripeConfiguration[] }>(\n 'GET',\n 'payment_method_configurations',\n new URLSearchParams({ limit: '20' }),\n )\n const own =\n list.data?.find((entry) => entry.is_default && !entry.application) ??\n list.data?.find((entry) => !entry.application) ??\n null\n for (const method of STOREFRONT_PAYMENT_METHODS) {\n if (!own) {\n value[method.id] = null\n continue\n }\n const entry = own[method.configurationKey] as\n | { available?: boolean; display_preference?: { value?: string } }\n | undefined\n value[method.id] =\n entry?.available === true && entry?.display_preference?.value === 'on'\n ? 'on'\n : 'unavailable'\n }\n platformCache = { at: Date.now(), value }\n } catch (error) {\n console.warn('[commerce] payment method configuration unreadable', error)\n for (const method of STOREFRONT_PAYMENT_METHODS) value[method.id] = null\n }\n return value\n}\n\nfunction capabilityStatus(\n capabilities: Record<string, string> | undefined,\n key: string | undefined,\n): CapabilityStatus {\n if (!key) return null\n const status = capabilities?.[key]\n if (status === 'active' || status === 'pending' || status === 'inactive') return status\n return 'unrequested'\n}\n\nasync function readAccountCapabilities(\n accountId: string | null,\n): Promise<Record<string, string> | undefined> {\n if (!accountId) return undefined\n try {\n const account = await stripe<{ capabilities?: Record<string, string> }>(\n 'GET',\n `accounts/${encodeURIComponent(accountId)}`,\n )\n return account.capabilities ?? {}\n } catch (error) {\n console.warn('[commerce] connected account unreadable', error)\n return undefined\n }\n}\n\n/** The capabilities a save asks Stripe for: on, offered, not yet requested. */\nexport function capabilitiesToRequest(\n settings: StorefrontPaymentMethodSettings,\n platform: Record<string, PlatformAvailability>,\n capabilities: Record<string, string> | undefined,\n): string[] {\n return STOREFRONT_PAYMENT_METHODS.filter(\n (method) =>\n method.capability &&\n isStorefrontPaymentMethodOn(settings, method.id) &&\n platform[method.id] !== 'unavailable' &&\n capabilityStatus(capabilities, method.capability) === 'unrequested',\n ).map((method) => method.capability as string)\n}\n\nexport function buildPaymentMethodRows(\n settings: StorefrontPaymentMethodSettings,\n platform: Record<string, PlatformAvailability>,\n capabilities: Record<string, string> | undefined,\n): PaymentMethodRow[] {\n return STOREFRONT_PAYMENT_METHODS.map((method) => ({\n id: method.id,\n on: isStorefrontPaymentMethodOn(settings, method.id),\n platform: platform[method.id] ?? null,\n capability: capabilities ? capabilityStatus(capabilities, method.capability) : null,\n }))\n}\n\nconst json = (body: unknown, status = 200) => Response.json(body, { status })\n\n/**\n * Where Stripe sends the owner back: the console page they pressed the button\n * on, judged against the request's own origin so a forged `Referer` cannot\n * turn the link into a redirect to somewhere else.\n */\nexport function consoleReturnUrl(headers: Partial<Record<string, string>>): string {\n const origin = headers.origin || (headers.host ? `https://${headers.host}` : '')\n const referer = headers.referer ?? ''\n try {\n if (origin && referer && new URL(referer).origin === new URL(origin).origin) {\n return referer\n }\n } catch {\n // Unparseable: fall through to the origin.\n }\n return origin || 'https://localhost/'\n}\n\nexport async function paymentMethodsHandler(request: Request): Promise<Response> {\n const { method, headers: rawHeaders, query, body } = await pluginRequestFromWeb(request)\n const headers = rawHeaders as Partial<Record<string, string>>\n if (method !== 'GET' && method !== 'POST') {\n return json({ error: 'Method not allowed' }, 405)\n }\n if (!process.env.STRIPE_SECRET_KEY) {\n return json({ error: 'Payments are not configured (STRIPE_SECRET_KEY).' }, 501)\n }\n const authorization = headers.authorization ?? ''\n const idToken = authorization.startsWith('Bearer ')\n ? authorization.slice('Bearer '.length)\n : undefined\n if (!idToken) return json({ error: 'Unauthenticated' }, 401)\n\n const parsed =\n typeof body === 'string' ? (JSON.parse(body || '{}') as Record<string, unknown>) : (body ?? {})\n const hostId = String(\n (method === 'GET' ? query?.['hostId'] : (parsed as Record<string, unknown>)['hostId']) ?? '',\n )\n if (!hostId) return json({ error: 'Missing hostId' }, 400)\n\n try {\n const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n if (!decoded.email_verified && !isImpersonationSession(decoded)) {\n return emailUnverifiedResponse()\n }\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = firestore.collection('hosts').doc(hostId)\n const hostSnapshot = await hostRef.get()\n if (!hostSnapshot.exists) return json({ error: 'Not found' }, 404)\n\n // An allowlist. Reading the card is for whoever works the store's orders\n // or changes its methods; a change asks Stripe for capabilities on the\n // owner's payout account, so it is \"Manage payment methods\" (AGL-4047),\n // whose preset is the site Admin who alone made it before, as the\n // reader's is the Admin and Editor.\n const mayEdit = holdsCommerceSiteKey(hostSnapshot, decoded.uid, 'commerce.paymentMethods')\n const mayRead = mayEdit || holdsCommerceSiteKey(hostSnapshot, decoded.uid, 'commerce.orders')\n if (!mayRead) return json({ error: 'Not found' }, 404)\n if (method === 'POST' && !mayEdit) {\n return json({ error: commerceSitePermissionRefusal('commerce.paymentMethods') }, 403)\n }\n\n const owner = await getOrgForHost(hostId)\n const locked = await lockdownRefusal({\n request,\n staff: decoded['staff'] === true,\n uid: decoded.uid,\n org: owner?.org,\n host: hostSnapshot.data(),\n })\n if (locked) return locked\n if (!checkEntitlement((owner?.org ?? {}) as never, 'commerce')) {\n return json({ error: 'Selling is not included on this plan' }, 402)\n }\n\n const ownerUid = String(owner?.org?.ownerUid ?? '')\n const accountId = ownerUid\n ? (((await firestore.collection('profiles').doc(ownerUid).get()).get(\n 'stripeAccountId',\n ) as string | undefined) ?? null)\n : null\n\n const storeRef = hostRef.collection('settings').doc('store')\n let settings = normalizeStorefrontPaymentMethodSettings(\n (await storeRef.get()).get('paymentMethods'),\n )\n const platform = await platformPaymentMethodAvailability()\n let capabilities = await readAccountCapabilities(accountId)\n const warnings: string[] = []\n\n // FINISH IN STRIPE: a capability Stripe holds `inactive` needs details\n // only the account holder can give, and an Express account has no login of\n // its own, so a link minted here is the only way in. The owner's alone,\n // as connecting the account is (`connect.ts`): the link opens the owner's\n // identity and bank details.\n if (method === 'POST' && (parsed as Record<string, unknown>)['action'] === 'finish') {\n if (!accountId || decoded.uid !== ownerUid) {\n return json({ error: 'Only the organization owner can finish this in Stripe' }, 403)\n }\n const back = consoleReturnUrl(headers)\n const link = await stripe<{ url?: string }>(\n 'POST',\n 'account_links',\n new URLSearchParams({\n account: accountId,\n type: 'account_onboarding',\n 'collection_options[fields]': 'currently_due',\n refresh_url: back,\n return_url: back,\n }),\n )\n return json({ url: link.url ?? null })\n }\n\n if (method === 'POST') {\n const requested = normalizeStorefrontPaymentMethodSettings(\n (parsed as Record<string, unknown>)['methods'],\n )\n if (!Object.keys(requested).length) {\n return json({ error: 'Nothing to save' }, 400)\n }\n settings = { ...settings, ...requested }\n await storeRef.set(\n { paymentMethods: settings, paymentMethodsUpdatedAtMs: Date.now(), paymentMethodsUpdatedBy: decoded.uid },\n { merge: true },\n )\n const wanted = accountId ? capabilitiesToRequest(settings, platform, capabilities) : []\n if (accountId && wanted.length) {\n const params = new URLSearchParams()\n for (const capability of wanted) {\n params.set(`capabilities[${capability}][requested]`, 'true')\n }\n try {\n const account = await stripe<{ capabilities?: Record<string, string> }>(\n 'POST',\n `accounts/${encodeURIComponent(accountId)}`,\n params,\n `aglyn-pm-capabilities:${accountId}:${[...wanted].sort().join(',')}`,\n )\n capabilities = account.capabilities ?? capabilities\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n warnings.push(\n `Stripe did not accept the request to enable ${wanted.join(', ')} on your payout account: ${message}`,\n )\n }\n }\n }\n\n const answer: PaymentMethodsAnswer = {\n methods: buildPaymentMethodRows(settings, platform, capabilities),\n domains: await readSiteDomainRecords(hostSnapshot.data() as SiteReturnHost | undefined),\n accountConnected: Boolean(accountId),\n canEdit: mayEdit,\n canFinish: Boolean(accountId) && decoded.uid === ownerUid,\n warnings,\n }\n return json(answer)\n } catch (error) {\n const unauthenticated = invalidIdTokenResponse(error)\n if (unauthenticated) return unauthenticated\n console.error(error)\n return json({ error: 'Payment methods could not be loaded' }, 500)\n }\n}\n"],"names":["checkEntitlement","pluginRequestFromWeb","emailUnverifiedResponse","firebaseAdmin","getOrgForHost","isImpersonationSession","lockdownRefusal","invalidIdTokenResponse","isStorefrontPaymentMethodOn","normalizeStorefrontPaymentMethodSettings","STOREFRONT_PAYMENT_METHODS","commerceSitePermissionRefusal","holdsCommerceSiteKey","readSiteDomainRecords","PLATFORM_CONFIGURATION_TTL_MS","platformCache","resetPlatformPaymentMethodCacheForTests","stripe","method","path","params","idempotencyKey","query","response","fetch","headers","Authorization","process","env","STRIPE_SECRET_KEY","body","toString","payload","json","catch","ok","Error","error","message","status","platformPaymentMethodAvailability","Date","now","at","value","list","URLSearchParams","limit","own","data","find","entry","is_default","application","id","configurationKey","available","display_preference","console","warn","capabilityStatus","capabilities","key","readAccountCapabilities","accountId","undefined","account","encodeURIComponent","capabilitiesToRequest","settings","platform","filter","capability","map","buildPaymentMethodRows","on","Response","consoleReturnUrl","origin","host","referer","URL","paymentMethodsHandler","request","rawHeaders","authorization","idToken","startsWith","slice","length","parsed","JSON","parse","hostId","String","owner","decoded","app","auth","verifyIdToken","email_verified","firestore","hostRef","collection","doc","hostSnapshot","get","exists","mayEdit","uid","mayRead","locked","staff","org","ownerUid","storeRef","warnings","link","back","type","refresh_url","return_url","url","requested","Object","keys","set","paymentMethods","paymentMethodsUpdatedAtMs","paymentMethodsUpdatedBy","merge","wanted","sort","join","push","answer","methods","domains","accountConnected","Boolean","canEdit","canFinish","unauthenticated"],"mappings":"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"}