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

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 (430) 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/order-webhooks-card.component.js +1 -1
  10. package/src/lib/components/console/order-webhooks-card.component.js.map +1 -1
  11. package/src/lib/components/console/payment-methods-card.component.js +1 -1
  12. package/src/lib/components/console/payment-methods-card.component.js.map +1 -1
  13. package/src/lib/components/console/pos/pos-cart-panel.component.d.ts +5 -0
  14. package/src/lib/components/console/pos/pos-cart-panel.component.js +18 -12
  15. package/src/lib/components/console/pos/pos-cart-panel.component.js.map +1 -1
  16. package/src/lib/components/console/pos/pos-hardware-api.d.ts +76 -5
  17. package/src/lib/components/console/pos/pos-hardware-api.js +53 -11
  18. package/src/lib/components/console/pos/pos-hardware-api.js.map +1 -1
  19. package/src/lib/components/console/pos/pos-hardware-buyer.component.d.ts +18 -0
  20. package/src/lib/components/console/pos/pos-hardware-buyer.component.js +629 -0
  21. package/src/lib/components/console/pos/pos-hardware-buyer.component.js.map +1 -0
  22. package/src/lib/components/console/pos/pos-hardware-sale-api.d.ts +162 -0
  23. package/src/lib/components/console/pos/pos-hardware-sale-api.js +122 -0
  24. package/src/lib/components/console/pos/pos-hardware-sale-api.js.map +1 -0
  25. package/src/lib/components/console/pos/pos-hardware-sale-terms.component.d.ts +39 -0
  26. package/src/lib/components/console/pos/pos-hardware-sale-terms.component.js +251 -0
  27. package/src/lib/components/console/pos/pos-hardware-sale-terms.component.js.map +1 -0
  28. package/src/lib/components/console/pos/use-pos-display.js +50 -0
  29. package/src/lib/components/console/pos/use-pos-display.js.map +1 -1
  30. package/src/lib/components/console/pos-cellular-control.component.d.ts +41 -0
  31. package/src/lib/components/console/pos-cellular-control.component.js +211 -0
  32. package/src/lib/components/console/pos-cellular-control.component.js.map +1 -0
  33. package/src/lib/components/console/pos-devices-card.component.d.ts +9 -1
  34. package/src/lib/components/console/pos-devices-card.component.js +47 -15
  35. package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
  36. package/src/lib/components/console/pos-display/pos-display-api.d.ts +6 -0
  37. package/src/lib/components/console/pos-display/pos-display-api.js +8 -1
  38. package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -1
  39. package/src/lib/components/console/pos-display-page.component.d.ts +13 -0
  40. package/src/lib/components/console/pos-display-page.component.js +44 -2
  41. package/src/lib/components/console/pos-display-page.component.js.map +1 -1
  42. package/src/lib/components/console/pos-hardware-card.component.d.ts +12 -4
  43. package/src/lib/components/console/pos-hardware-card.component.js +157 -36
  44. package/src/lib/components/console/pos-hardware-card.component.js.map +1 -1
  45. package/src/lib/components/console/pos-hardware-orders-staff-page.component.js +360 -80
  46. package/src/lib/components/console/pos-hardware-orders-staff-page.component.js.map +1 -1
  47. package/src/lib/components/console/pos-hardware-terms-page.component.d.ts +34 -0
  48. package/src/lib/components/console/pos-hardware-terms-page.component.js +257 -0
  49. package/src/lib/components/console/pos-hardware-terms-page.component.js.map +1 -0
  50. package/src/lib/components/console/pos-hardware-terms-sign-page.component.d.ts +27 -0
  51. package/src/lib/components/console/pos-hardware-terms-sign-page.component.js +104 -0
  52. package/src/lib/components/console/pos-hardware-terms-sign-page.component.js.map +1 -0
  53. package/src/lib/components/console/pos-hardware-waiting-card.component.d.ts +24 -0
  54. package/src/lib/components/console/pos-hardware-waiting-card.component.js +205 -0
  55. package/src/lib/components/console/pos-hardware-waiting-card.component.js.map +1 -0
  56. package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js +297 -201
  57. package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js.map +1 -1
  58. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.d.ts +3 -0
  59. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js +260 -92
  60. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js.map +1 -1
  61. package/src/lib/components/console/pos-ops/pos-operations-bar.component.d.ts +9 -0
  62. package/src/lib/components/console/pos-ops/pos-operations-bar.component.js +15 -6
  63. package/src/lib/components/console/pos-ops/pos-operations-bar.component.js.map +1 -1
  64. package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.d.ts +25 -0
  65. package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.js +136 -0
  66. package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.js.map +1 -0
  67. package/src/lib/components/console/pos-ops/pos-shift-panel.component.d.ts +6 -0
  68. package/src/lib/components/console/pos-ops/pos-shift-panel.component.js +48 -31
  69. package/src/lib/components/console/pos-ops/pos-shift-panel.component.js.map +1 -1
  70. package/src/lib/components/console/pos-page.component.d.ts +1 -1
  71. package/src/lib/components/console/pos-page.component.js +63 -12
  72. package/src/lib/components/console/pos-page.component.js.map +1 -1
  73. package/src/lib/components/console/pos-reader-splash-setting.component.js +1 -1
  74. package/src/lib/components/console/pos-reader-splash-setting.component.js.map +1 -1
  75. package/src/lib/components/console/product-check-in-fields.component.d.ts +4 -2
  76. package/src/lib/components/console/product-check-in-fields.component.js +60 -14
  77. package/src/lib/components/console/product-check-in-fields.component.js.map +1 -1
  78. package/src/lib/components/console/product-editor-dialog.component.js +44 -1
  79. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
  80. package/src/lib/components/console/product-hardware-sku-field.component.d.ts +19 -0
  81. package/src/lib/components/console/product-hardware-sku-field.component.js +92 -0
  82. package/src/lib/components/console/product-hardware-sku-field.component.js.map +1 -0
  83. package/src/lib/components/console/product-kiosk-offer-field.component.d.ts +22 -0
  84. package/src/lib/components/console/product-kiosk-offer-field.component.js +94 -0
  85. package/src/lib/components/console/product-kiosk-offer-field.component.js.map +1 -0
  86. package/src/lib/components/console/product-register-fields.component.d.ts +4 -0
  87. package/src/lib/components/console/product-register-fields.component.js +31 -2
  88. package/src/lib/components/console/product-register-fields.component.js.map +1 -1
  89. package/src/lib/components/console/products-hub-card.component.js +11 -2
  90. package/src/lib/components/console/products-hub-card.component.js.map +1 -1
  91. package/src/lib/components/console/register-hardware-card.component.d.ts +11 -0
  92. package/src/lib/components/console/register-hardware-card.component.js +56 -27
  93. package/src/lib/components/console/register-hardware-card.component.js.map +1 -1
  94. package/src/lib/components/console/reservation-guests-dialog.component.d.ts +28 -0
  95. package/src/lib/components/console/reservation-guests-dialog.component.js +189 -0
  96. package/src/lib/components/console/reservation-guests-dialog.component.js.map +1 -0
  97. package/src/lib/components/console/reservations-card.component.d.ts +9 -0
  98. package/src/lib/components/console/reservations-card.component.js +158 -23
  99. package/src/lib/components/console/reservations-card.component.js.map +1 -1
  100. package/src/lib/components/console/shippingeasy-card.component.js +1 -1
  101. package/src/lib/components/console/shippingeasy-card.component.js.map +1 -1
  102. package/src/lib/components/console/shipstation-card.component.d.ts +1 -1
  103. package/src/lib/components/console/shipstation-card.component.js +3 -3
  104. package/src/lib/components/console/shipstation-card.component.js.map +1 -1
  105. package/src/lib/components/product-detail.d.ts +4 -0
  106. package/src/lib/components/product-detail.js +40 -5
  107. package/src/lib/components/product-detail.js.map +1 -1
  108. package/src/lib/components/product-reviews.js +28 -11
  109. package/src/lib/components/product-reviews.js.map +1 -1
  110. package/src/lib/components/reservation-widget.js +28 -5
  111. package/src/lib/components/reservation-widget.js.map +1 -1
  112. package/src/lib/components/use-day-picker.d.ts +25 -0
  113. package/src/lib/components/use-day-picker.js +57 -0
  114. package/src/lib/components/use-day-picker.js.map +1 -0
  115. package/src/lib/constants/operator-alerts.d.ts +55 -0
  116. package/src/lib/constants/operator-alerts.js +156 -1
  117. package/src/lib/constants/operator-alerts.js.map +1 -1
  118. package/src/lib/declarations.console-server.js +54 -1
  119. package/src/lib/declarations.console-server.js.map +1 -1
  120. package/src/lib/declarations.d.ts +4 -2
  121. package/src/lib/declarations.js +15 -4
  122. package/src/lib/declarations.js.map +1 -1
  123. package/src/lib/declarations.server.js +9 -0
  124. package/src/lib/declarations.server.js.map +1 -1
  125. package/src/lib/model/commerce-cart.d.ts +9 -1
  126. package/src/lib/model/commerce-cart.js +4 -3
  127. package/src/lib/model/commerce-cart.js.map +1 -1
  128. package/src/lib/model/commerce-check-in-product.d.ts +26 -0
  129. package/src/lib/model/commerce-check-in-product.js +64 -2
  130. package/src/lib/model/commerce-check-in-product.js.map +1 -1
  131. package/src/lib/model/commerce-check-in-record.d.ts +127 -0
  132. package/src/lib/model/commerce-check-in-record.js +36 -0
  133. package/src/lib/model/commerce-check-in-record.js.map +1 -0
  134. package/src/lib/model/commerce-check-in.d.ts +91 -87
  135. package/src/lib/model/commerce-check-in.js +186 -62
  136. package/src/lib/model/commerce-check-in.js.map +1 -1
  137. package/src/lib/model/commerce-kiosk-offer.d.ts +31 -0
  138. package/src/lib/model/commerce-kiosk-offer.js +35 -0
  139. package/src/lib/model/commerce-kiosk-offer.js.map +1 -0
  140. package/src/lib/model/commerce-orders.d.ts +76 -0
  141. package/src/lib/model/commerce-orders.js +6 -0
  142. package/src/lib/model/commerce-orders.js.map +1 -1
  143. package/src/lib/model/commerce-pos-day-report.d.ts +54 -1
  144. package/src/lib/model/commerce-pos-day-report.js +39 -2
  145. package/src/lib/model/commerce-pos-day-report.js.map +1 -1
  146. package/src/lib/model/commerce-pos-offline.d.ts +1 -1
  147. package/src/lib/model/commerce-pos-offline.js +6 -1
  148. package/src/lib/model/commerce-pos-offline.js.map +1 -1
  149. package/src/lib/model/commerce-pos-ops.js +3 -2
  150. package/src/lib/model/commerce-pos-ops.js.map +1 -1
  151. package/src/lib/model/commerce-pos.d.ts +36 -3
  152. package/src/lib/model/commerce-pos.js +14 -6
  153. package/src/lib/model/commerce-pos.js.map +1 -1
  154. package/src/lib/model/commerce-receipt.js +3 -2
  155. package/src/lib/model/commerce-receipt.js.map +1 -1
  156. package/src/lib/model/commerce-reservations.d.ts +69 -4
  157. package/src/lib/model/commerce-reservations.js +57 -5
  158. package/src/lib/model/commerce-reservations.js.map +1 -1
  159. package/src/lib/model/commerce.d.ts +66 -0
  160. package/src/lib/model/commerce.js +15 -0
  161. package/src/lib/model/commerce.js.map +1 -1
  162. package/src/lib/model/order-list-fields.d.ts +11 -0
  163. package/src/lib/model/order-list-fields.js +17 -1
  164. package/src/lib/model/order-list-fields.js.map +1 -1
  165. package/src/lib/model/own-store-tax-summary.d.ts +152 -0
  166. package/src/lib/model/own-store-tax-summary.js +288 -0
  167. package/src/lib/model/own-store-tax-summary.js.map +1 -0
  168. package/src/lib/model/plugin-permissions.d.ts +74 -0
  169. package/src/lib/model/plugin-permissions.js +224 -7
  170. package/src/lib/model/plugin-permissions.js.map +1 -1
  171. package/src/lib/model/pos-cellular.d.ts +223 -0
  172. package/src/lib/model/pos-cellular.js +293 -0
  173. package/src/lib/model/pos-cellular.js.map +1 -0
  174. package/src/lib/model/pos-hardware-in-person.d.ts +98 -0
  175. package/src/lib/model/pos-hardware-in-person.js +224 -0
  176. package/src/lib/model/pos-hardware-in-person.js.map +1 -0
  177. package/src/lib/model/pos-hardware-tax-summary.d.ts +166 -0
  178. package/src/lib/model/pos-hardware-tax-summary.js +225 -0
  179. package/src/lib/model/pos-hardware-tax-summary.js.map +1 -0
  180. package/src/lib/model/pos-hardware-terms.d.ts +74 -0
  181. package/src/lib/model/pos-hardware-terms.js +115 -0
  182. package/src/lib/model/pos-hardware-terms.js.map +1 -0
  183. package/src/lib/model/pos-hardware.d.ts +349 -7
  184. package/src/lib/model/pos-hardware.js +291 -20
  185. package/src/lib/model/pos-hardware.js.map +1 -1
  186. package/src/lib/model/product-write.d.ts +10 -0
  187. package/src/lib/model/product-write.js +4 -2
  188. package/src/lib/model/product-write.js.map +1 -1
  189. package/src/lib/model/workspace-site-permissions.d.ts +26 -0
  190. package/src/lib/model/workspace-site-permissions.js +81 -0
  191. package/src/lib/model/workspace-site-permissions.js.map +1 -0
  192. package/src/lib/plugin.js +16 -0
  193. package/src/lib/plugin.js.map +1 -1
  194. package/src/lib/server/billing-webhook.js +25 -1
  195. package/src/lib/server/billing-webhook.js.map +1 -1
  196. package/src/lib/server/cancel-order.js +7 -5
  197. package/src/lib/server/cancel-order.js.map +1 -1
  198. package/src/lib/server/cart-checkout.js +20 -8
  199. package/src/lib/server/cart-checkout.js.map +1 -1
  200. package/src/lib/server/cart.js +29 -0
  201. package/src/lib/server/cart.js.map +1 -1
  202. package/src/lib/server/checkout.js +42 -13
  203. package/src/lib/server/checkout.js.map +1 -1
  204. package/src/lib/server/collection-membership.d.ts +4 -0
  205. package/src/lib/server/collection-membership.js +5 -10
  206. package/src/lib/server/collection-membership.js.map +1 -1
  207. package/src/lib/server/commerce-site-keys.d.ts +48 -0
  208. package/src/lib/server/commerce-site-keys.js +61 -0
  209. package/src/lib/server/commerce-site-keys.js.map +1 -0
  210. package/src/lib/server/draft-order.js +8 -5
  211. package/src/lib/server/draft-order.js.map +1 -1
  212. package/src/lib/server/fulfill-order.js +7 -5
  213. package/src/lib/server/fulfill-order.js.map +1 -1
  214. package/src/lib/server/gift-cards.js +8 -5
  215. package/src/lib/server/gift-cards.js.map +1 -1
  216. package/src/lib/server/local-fulfillment-status.js +9 -6
  217. package/src/lib/server/local-fulfillment-status.js.map +1 -1
  218. package/src/lib/server/member-post.js +6 -5
  219. package/src/lib/server/member-post.js.map +1 -1
  220. package/src/lib/server/membership-admin-password.d.ts +4 -2
  221. package/src/lib/server/membership-admin-password.js +10 -8
  222. package/src/lib/server/membership-admin-password.js.map +1 -1
  223. package/src/lib/server/membership-admin-remove.d.ts +7 -5
  224. package/src/lib/server/membership-admin-remove.js +9 -9
  225. package/src/lib/server/membership-admin-remove.js.map +1 -1
  226. package/src/lib/server/order-notifications.js +5 -2
  227. package/src/lib/server/order-notifications.js.map +1 -1
  228. package/src/lib/server/order-print.js +7 -5
  229. package/src/lib/server/order-print.js.map +1 -1
  230. package/src/lib/server/order-receipt-send.js +8 -5
  231. package/src/lib/server/order-receipt-send.js.map +1 -1
  232. package/src/lib/server/order-webhooks.js +8 -8
  233. package/src/lib/server/order-webhooks.js.map +1 -1
  234. package/src/lib/server/orders-shipping-prepare.js +9 -6
  235. package/src/lib/server/orders-shipping-prepare.js.map +1 -1
  236. package/src/lib/server/own-store-tax-return-source.d.ts +47 -0
  237. package/src/lib/server/own-store-tax-return-source.js +312 -0
  238. package/src/lib/server/own-store-tax-return-source.js.map +1 -0
  239. package/src/lib/server/payment-methods.js +13 -9
  240. package/src/lib/server/payment-methods.js.map +1 -1
  241. package/src/lib/server/pos-auth.d.ts +37 -6
  242. package/src/lib/server/pos-auth.js +40 -15
  243. package/src/lib/server/pos-auth.js.map +1 -1
  244. package/src/lib/server/pos-cellular-billing.d.ts +81 -0
  245. package/src/lib/server/pos-cellular-billing.js +711 -0
  246. package/src/lib/server/pos-cellular-billing.js.map +1 -0
  247. package/src/lib/server/pos-cellular-notify.d.ts +47 -0
  248. package/src/lib/server/pos-cellular-notify.js +150 -0
  249. package/src/lib/server/pos-cellular-notify.js.map +1 -0
  250. package/src/lib/server/pos-cellular.d.ts +88 -0
  251. package/src/lib/server/pos-cellular.js +339 -0
  252. package/src/lib/server/pos-cellular.js.map +1 -0
  253. package/src/lib/server/pos-check-in.d.ts +5 -1
  254. package/src/lib/server/pos-check-in.js +296 -28
  255. package/src/lib/server/pos-check-in.js.map +1 -1
  256. package/src/lib/server/pos-day-report.js +29 -3
  257. package/src/lib/server/pos-day-report.js.map +1 -1
  258. package/src/lib/server/pos-display.d.ts +16 -0
  259. package/src/lib/server/pos-display.js +129 -2
  260. package/src/lib/server/pos-display.js.map +1 -1
  261. package/src/lib/server/pos-hardware-admin.d.ts +10 -1
  262. package/src/lib/server/pos-hardware-admin.js +250 -84
  263. package/src/lib/server/pos-hardware-admin.js.map +1 -1
  264. package/src/lib/server/pos-hardware-attach.d.ts +105 -0
  265. package/src/lib/server/pos-hardware-attach.js +443 -0
  266. package/src/lib/server/pos-hardware-attach.js.map +1 -0
  267. package/src/lib/server/pos-hardware-buyer-lookup.d.ts +58 -0
  268. package/src/lib/server/pos-hardware-buyer-lookup.js +180 -0
  269. package/src/lib/server/pos-hardware-buyer-lookup.js.map +1 -0
  270. package/src/lib/server/pos-hardware-buyer-record.d.ts +29 -0
  271. package/src/lib/server/pos-hardware-buyer-record.js +86 -0
  272. package/src/lib/server/pos-hardware-buyer-record.js.map +1 -0
  273. package/src/lib/server/pos-hardware-cancel.d.ts +58 -0
  274. package/src/lib/server/pos-hardware-cancel.js +147 -0
  275. package/src/lib/server/pos-hardware-cancel.js.map +1 -0
  276. package/src/lib/server/pos-hardware-closure-notices.d.ts +27 -0
  277. package/src/lib/server/pos-hardware-closure-notices.js +85 -0
  278. package/src/lib/server/pos-hardware-closure-notices.js.map +1 -0
  279. package/src/lib/server/pos-hardware-closure.d.ts +60 -0
  280. package/src/lib/server/pos-hardware-closure.js +153 -0
  281. package/src/lib/server/pos-hardware-closure.js.map +1 -0
  282. package/src/lib/server/pos-hardware-in-person.d.ts +61 -0
  283. package/src/lib/server/pos-hardware-in-person.js +236 -0
  284. package/src/lib/server/pos-hardware-in-person.js.map +1 -0
  285. package/src/lib/server/pos-hardware-notify.d.ts +40 -2
  286. package/src/lib/server/pos-hardware-notify.js +195 -14
  287. package/src/lib/server/pos-hardware-notify.js.map +1 -1
  288. package/src/lib/server/pos-hardware-readers.d.ts +115 -0
  289. package/src/lib/server/pos-hardware-readers.js +430 -0
  290. package/src/lib/server/pos-hardware-readers.js.map +1 -0
  291. package/src/lib/server/pos-hardware-returns.d.ts +116 -0
  292. package/src/lib/server/pos-hardware-returns.js +502 -0
  293. package/src/lib/server/pos-hardware-returns.js.map +1 -0
  294. package/src/lib/server/pos-hardware-sale-fields.d.ts +28 -0
  295. package/src/lib/server/pos-hardware-sale-fields.js +44 -0
  296. package/src/lib/server/pos-hardware-sale-fields.js.map +1 -0
  297. package/src/lib/server/pos-hardware-sale.d.ts +54 -0
  298. package/src/lib/server/pos-hardware-sale.js +369 -0
  299. package/src/lib/server/pos-hardware-sale.js.map +1 -0
  300. package/src/lib/server/pos-hardware-tax-return-source.d.ts +99 -0
  301. package/src/lib/server/pos-hardware-tax-return-source.js +462 -0
  302. package/src/lib/server/pos-hardware-tax-return-source.js.map +1 -0
  303. package/src/lib/server/pos-hardware-terms.d.ts +64 -0
  304. package/src/lib/server/pos-hardware-terms.js +154 -0
  305. package/src/lib/server/pos-hardware-terms.js.map +1 -0
  306. package/src/lib/server/pos-hardware-user-eraser.d.ts +3 -0
  307. package/src/lib/server/pos-hardware-user-eraser.js +31 -7
  308. package/src/lib/server/pos-hardware-user-eraser.js.map +1 -1
  309. package/src/lib/server/pos-hardware-webhook.d.ts +5 -0
  310. package/src/lib/server/pos-hardware-webhook.js +51 -6
  311. package/src/lib/server/pos-hardware-webhook.js.map +1 -1
  312. package/src/lib/server/pos-hardware.d.ts +74 -1
  313. package/src/lib/server/pos-hardware.js +175 -10
  314. package/src/lib/server/pos-hardware.js.map +1 -1
  315. package/src/lib/server/pos-kiosk.d.ts +2 -0
  316. package/src/lib/server/pos-kiosk.js +17 -12
  317. package/src/lib/server/pos-kiosk.js.map +1 -1
  318. package/src/lib/server/pos-offline-card-order.d.ts +64 -0
  319. package/src/lib/server/pos-offline-card-order.js +102 -0
  320. package/src/lib/server/pos-offline-card-order.js.map +1 -0
  321. package/src/lib/server/pos-offline-card-reconcile.d.ts +67 -1
  322. package/src/lib/server/pos-offline-card-reconcile.js +215 -18
  323. package/src/lib/server/pos-offline-card-reconcile.js.map +1 -1
  324. package/src/lib/server/pos-offline-sync.d.ts +39 -0
  325. package/src/lib/server/pos-offline-sync.js +190 -55
  326. package/src/lib/server/pos-offline-sync.js.map +1 -1
  327. package/src/lib/server/pos-ops-gate.d.ts +28 -9
  328. package/src/lib/server/pos-ops-gate.js +50 -19
  329. package/src/lib/server/pos-ops-gate.js.map +1 -1
  330. package/src/lib/server/pos-ops-routes.js +24 -0
  331. package/src/lib/server/pos-ops-routes.js.map +1 -1
  332. package/src/lib/server/pos-order-refund-ids.d.ts +28 -0
  333. package/src/lib/server/pos-order-refund-ids.js +31 -0
  334. package/src/lib/server/pos-order-refund-ids.js.map +1 -0
  335. package/src/lib/server/pos-order.js +52 -49
  336. package/src/lib/server/pos-order.js.map +1 -1
  337. package/src/lib/server/pos-payment.js +1 -1
  338. package/src/lib/server/pos-payment.js.map +1 -1
  339. package/src/lib/server/pos-reader-splash-admin.js +30 -32
  340. package/src/lib/server/pos-reader-splash-admin.js.map +1 -1
  341. package/src/lib/server/pos-reader-splash-images-route.d.ts +17 -0
  342. package/src/lib/server/pos-reader-splash-images-route.js +113 -0
  343. package/src/lib/server/pos-reader-splash-images-route.js.map +1 -0
  344. package/src/lib/server/pos-reader-splash-images.d.ts +51 -0
  345. package/src/lib/server/pos-reader-splash-images.js +123 -0
  346. package/src/lib/server/pos-reader-splash-images.js.map +1 -0
  347. package/src/lib/server/pos-reader-splash.d.ts +68 -1
  348. package/src/lib/server/pos-reader-splash.js +182 -11
  349. package/src/lib/server/pos-reader-splash.js.map +1 -1
  350. package/src/lib/server/pos-readers.d.ts +29 -0
  351. package/src/lib/server/pos-readers.js +134 -35
  352. package/src/lib/server/pos-readers.js.map +1 -1
  353. package/src/lib/server/pos-refund-authority.d.ts +3 -1
  354. package/src/lib/server/pos-refund-authority.js +3 -2
  355. package/src/lib/server/pos-refund-authority.js.map +1 -1
  356. package/src/lib/server/pos-return.d.ts +10 -0
  357. package/src/lib/server/pos-return.js +29 -7
  358. package/src/lib/server/pos-return.js.map +1 -1
  359. package/src/lib/server/pos-sale.js +6 -1
  360. package/src/lib/server/pos-sale.js.map +1 -1
  361. package/src/lib/server/pos-shift.js +11 -0
  362. package/src/lib/server/pos-shift.js.map +1 -1
  363. package/src/lib/server/pos-staff-pin.js +29 -24
  364. package/src/lib/server/pos-staff-pin.js.map +1 -1
  365. package/src/lib/server/pos-terminal.d.ts +14 -4
  366. package/src/lib/server/pos-terminal.js +34 -38
  367. package/src/lib/server/pos-terminal.js.map +1 -1
  368. package/src/lib/server/printers.d.ts +7 -3
  369. package/src/lib/server/printers.js +18 -12
  370. package/src/lib/server/printers.js.map +1 -1
  371. package/src/lib/server/product-drafts.d.ts +11 -1
  372. package/src/lib/server/product-drafts.js +12 -8
  373. package/src/lib/server/product-drafts.js.map +1 -1
  374. package/src/lib/server/product.d.ts +15 -1
  375. package/src/lib/server/product.js +16 -3
  376. package/src/lib/server/product.js.map +1 -1
  377. package/src/lib/server/products-write.d.ts +26 -2
  378. package/src/lib/server/products-write.js +19 -7
  379. package/src/lib/server/products-write.js.map +1 -1
  380. package/src/lib/server/refund.js +55 -42
  381. package/src/lib/server/refund.js.map +1 -1
  382. package/src/lib/server/reservation-availability-query.d.ts +8 -0
  383. package/src/lib/server/reservation-availability-query.js +11 -1
  384. package/src/lib/server/reservation-availability-query.js.map +1 -1
  385. package/src/lib/server/reservation-availability.d.ts +1 -1
  386. package/src/lib/server/reservation-availability.js +7 -2
  387. package/src/lib/server/reservation-availability.js.map +1 -1
  388. package/src/lib/server/reservation-guests.d.ts +32 -0
  389. package/src/lib/server/reservation-guests.js +285 -0
  390. package/src/lib/server/reservation-guests.js.map +1 -0
  391. package/src/lib/server/reservation-walk-in.d.ts +11 -1
  392. package/src/lib/server/reservation-walk-in.js +56 -12
  393. package/src/lib/server/reservation-walk-in.js.map +1 -1
  394. package/src/lib/server/reserve.js +18 -5
  395. package/src/lib/server/reserve.js.map +1 -1
  396. package/src/lib/server/returns.js +9 -6
  397. package/src/lib/server/returns.js.map +1 -1
  398. package/src/lib/server/reviews.d.ts +22 -2
  399. package/src/lib/server/reviews.js +88 -20
  400. package/src/lib/server/reviews.js.map +1 -1
  401. package/src/lib/server/shipping-connectors.js +10 -11
  402. package/src/lib/server/shipping-connectors.js.map +1 -1
  403. package/src/lib/server/site-page-resolver.js +20 -3
  404. package/src/lib/server/site-page-resolver.js.map +1 -1
  405. package/src/lib/server/store-day.d.ts +33 -0
  406. package/src/lib/server/store-day.js +46 -0
  407. package/src/lib/server/store-day.js.map +1 -0
  408. package/src/lib/server/store-setup-ai-writer.d.ts +2 -1
  409. package/src/lib/server/store-setup-ai-writer.js +5 -6
  410. package/src/lib/server/store-setup-ai-writer.js.map +1 -1
  411. package/src/lib/server/storefront-tax.d.ts +13 -0
  412. package/src/lib/server/storefront-tax.js +8 -1
  413. package/src/lib/server/storefront-tax.js.map +1 -1
  414. package/src/lib/server/tax-return-source.d.ts +32 -3
  415. package/src/lib/server/tax-return-source.js +99 -20
  416. package/src/lib/server/tax-return-source.js.map +1 -1
  417. package/src/lib/server.js +100 -2
  418. package/src/lib/server.js.map +1 -1
  419. package/src/lib/testing/fake-firestore.js +58 -16
  420. package/src/lib/testing/fake-firestore.js.map +1 -1
  421. package/src/lib/testing/pos-ops-memory-firestore.js +18 -4
  422. package/src/lib/testing/pos-ops-memory-firestore.js.map +1 -1
  423. package/src/lib/testing/site-register-permissions.d.ts +29 -0
  424. package/src/lib/testing/site-register-permissions.js +38 -0
  425. package/src/lib/testing/site-register-permissions.js.map +1 -0
  426. package/src/lib/transfer/tracking.server.js +8 -5
  427. package/src/lib/transfer/tracking.server.js.map +1 -1
  428. package/src/lib/utils/add-to-cart.d.ts +2 -0
  429. package/src/lib/utils/add-to-cart.js +6 -3
  430. package/src/lib/utils/add-to-cart.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/pos-payment.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 {\n consumeRateLimit,\n firebaseAdmin,\n getPluginConfig,\n} from '@aglyn/tenant-data-admin'\nimport { buildRoute, Route, type PluginApiHandler } from '@aglyn/aglyn/server'\nimport recordCapturedContact from '@aglyn/aglyn/plugin-manager/record-captured-contact'\nimport { pluginSmsAvailable } from '@aglyn/aglyn/plugin-manager/plugin-sms-messaging'\nimport {\n checkoutCreditProvider,\n checkoutCreditProviderForCode,\n normalizeCheckoutCreditAccount,\n normalizeCheckoutCreditCode,\n offeredCheckoutCredits,\n type CheckoutCreditStage,\n} from '@aglyn/aglyn/plugin-manager/plugin-checkout-credits'\nimport { finishPosDisplayReceipt } from './pos-display'\nimport * as CommerceModel from '../model'\nimport { posRegisterSettings } from '../plugin-config'\nimport { posOpsSettings } from '../pos-ops-config'\nimport {\n authorizePosStaff,\n posIdempotencyKey,\n posQueryBody,\n posRequestBody,\n type PosStaff,\n} from './pos-auth'\nimport {\n applyPosPayment,\n deliverChosenPosReceipt,\n posPaymentId,\n posSaleSummary,\n readPosSale,\n releasePosSaleDiscount,\n type PosLiftedOrder,\n type PosPaymentOutcome,\n} from './pos-sale'\nimport { posPaymentCashierId } from './pos-sale-stamp'\nimport { printPosSaleReceipt } from './pos-print'\nimport {\n POS_CURRENCY,\n posStripe,\n posStripeErrorMessage,\n posStripeTestMode,\n posTerminalAvailable,\n} from './pos-stripe'\nimport {\n cancelPosCardPayment,\n createCardPresentIntent,\n refreshPosCardPayment,\n retryCardPresentPayment,\n simulatePosReaderTap,\n startCardKeyedPayment,\n startCardLinkPayment,\n startCardPresentPayment,\n} from './pos-terminal'\n\n/**\n * `POST /api/commerce/pos-payment` (AGL-3607): every tender against an OPEN\n * register sale, one `action` per request.\n *\n * The sale was priced by `pos-order.ts` (`payment: 'open'`); nothing here\n * re-prices it or lets the register name a total. Each payment-starting action\n * needs the register's `Idempotency-Key`, from which the payment's id is\n * derived: pressing a tender twice, or retrying after a lost response, finds\n * the payment the first press started instead of taking the money twice.\n */\nexport const posPaymentHandler: PluginApiHandler = async (req, res) => {\n // `sale` is a read and may be a GET, so a register re-reading its sale does\n // not spend the console's write budget; everything else moves money.\n const body = req.method === 'GET' ? posQueryBody(req) : posRequestBody(req)\n if (\n !(\n req.method === 'POST' ||\n (req.method === 'GET' && (body['action'] === 'sale' || body['action'] === 'context'))\n )\n ) {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const hostId = String(body['hostId'] ?? '')\n const gate = await authorizePosStaff(req, hostId)\n if ('error' in gate) return res.status(gate.status).json({ error: gate.error })\n let staff = gate.staff\n const action = String(body['action'] ?? '')\n const orderId = String(body['orderId'] ?? '')\n try {\n if (action === 'gift-card-balance') {\n return await giftCardBalance(staff, body, res)\n }\n if (action === 'credit-lookup') {\n return await creditLookup(staff, body, res)\n }\n if (action === 'context') {\n // What the register needs to draw its tenders: the site's tip and\n // receipt settings, whether card readers are offered at all, and the\n // key the typed-card form loads Stripe with.\n const readers = posTerminalAvailable()\n ? (\n await firebaseAdmin\n .app()\n .firestore()\n .collection('hosts')\n .doc(hostId)\n .collection('terminalReaders')\n .limit(50)\n .get()\n ).docs.map((doc: any) => ({\n id: doc.id as string,\n label: String(doc.get('label') ?? 'Card reader'),\n registerId: (doc.get('registerId') as string | undefined) ?? null,\n status: String(doc.get('status') ?? 'offline'),\n livemode: Boolean(doc.get('livemode')),\n }))\n : []\n const config = await getPluginConfig(staff.orgId || undefined, 'commerce', { hostId })\n return res.status(200).json({\n settings: posRegisterSettings(config),\n // The register's own rules (AGL-3609): the shift it requires, the\n // idle lock and the refund limit. The console reads the same config\n // client-side; the native apps read it here.\n ops: posOpsSettings(config),\n terminal: { available: posTerminalAvailable(), testMode: posStripeTestMode() },\n readers,\n publishableKey: String(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY ?? ''),\n // A text receipt is offered only when an SMS provider is on (AGL-3610).\n smsReceipts: pluginSmsAvailable(),\n // Store credit other plugins keep — rewards (AGL-3640) — offered here.\n credits: await offeredCheckoutCredits({ hostId, channel: 'pos' }),\n })\n }\n if (!orderId) return res.status(400).json({ error: 'Missing orderId' })\n const startsPayment = [\n 'card-present-sdk',\n 'cash',\n 'gift-card',\n 'credit',\n 'folio',\n 'card-present',\n 'card-keyed',\n 'card-link',\n ].includes(action)\n const attemptKey = posIdempotencyKey(req)\n if (startsPayment && !attemptKey) {\n return res.status(400).json({ error: 'Missing Idempotency-Key' })\n }\n const paymentId = startsPayment\n ? posPaymentId(orderId, attemptKey)\n : String(body['paymentId'] ?? '')\n // The cashier a PIN switched in takes the payment (AGL-3609).\n if (startsPayment && body['cashierAssertion']) {\n staff = {\n ...staff,\n uid: await posPaymentCashierId({\n hostId,\n orderId,\n signedInUid: staff.uid,\n assertion: body['cashierAssertion'],\n }),\n }\n }\n const amountCents = Math.round(Number(body['amountCents'] ?? 0))\n const tipCents = Math.round(Number(body['tipCents'] ?? 0)) || 0\n const settings = posRegisterSettings(\n await getPluginConfig(staff.orgId || undefined, 'commerce', { hostId }),\n )\n let outcome: (PosPaymentOutcome & { clientSecret?: string; paymentIntentId?: string }) | null = null\n switch (action) {\n case 'sale': {\n const order = await readPosSale(hostId, orderId)\n if (!order) return res.status(404).json({ error: 'Unknown sale' })\n outcome = { ok: true, order, payment: null, completed: false, changed: false }\n break\n }\n case 'cash':\n outcome = await takeCash(staff, orderId, paymentId, body, tipCents)\n break\n case 'gift-card':\n outcome = await takeGiftCard(staff, orderId, paymentId, body)\n break\n case 'credit':\n outcome = await takeCredit(staff, orderId, paymentId, body)\n break\n case 'folio':\n outcome = await takeFolio(staff, orderId, paymentId, body)\n break\n case 'card-present':\n outcome = await startCardPresentPayment({\n hostId,\n orderId,\n paymentId,\n amountCents,\n tipCents,\n cashierId: staff.uid,\n org: staff.org,\n readerId: String(body['readerId'] ?? ''),\n settings,\n })\n break\n case 'card-present-sdk':\n // Collected by a native app's Stripe Terminal SDK (Tap to Pay or a\n // Bluetooth reader, AGL-3618) against this server-made intent; it\n // settles exactly like a smart-reader payment.\n outcome = await createCardPresentIntent({\n hostId,\n orderId,\n paymentId,\n amountCents,\n tipCents,\n cashierId: staff.uid,\n org: staff.org,\n })\n break\n case 'card-keyed':\n outcome = await startCardKeyedPayment({\n hostId,\n orderId,\n paymentId,\n amountCents,\n tipCents,\n cashierId: staff.uid,\n org: staff.org,\n // The register's own card fields send the PaymentMethod Stripe\n // made from the card, never the card; the server confirms with it.\n ...(body['paymentMethodId'] ? { paymentMethodId: String(body['paymentMethodId']) } : {}),\n })\n break\n case 'card-link':\n outcome = await startCardLinkPayment({\n hostId,\n orderId,\n paymentId,\n amountCents,\n tipCents,\n cashierId: staff.uid,\n org: staff.org,\n returnUrl: await registerReturnUrl(req.headers.host, hostId, staff),\n })\n break\n case 'status':\n outcome = await refreshPosCardPayment({ hostId, orderId, paymentId })\n break\n case 'cancel':\n outcome = await cancelPosCardPayment({ hostId, orderId, paymentId })\n break\n case 'retry':\n outcome = await retryCardPresentPayment({ hostId, orderId, paymentId, settings })\n break\n case 'simulate':\n outcome = await simulatePosReaderTap({\n hostId,\n orderId,\n paymentId,\n cardNumber: String(body['cardNumber'] ?? ''),\n })\n break\n case 'void':\n outcome = await voidPosSale(staff, orderId)\n break\n case 'receipt':\n outcome = await recordReceiptChoice(staff, orderId, body)\n break\n default:\n return res.status(400).json({ error: 'Unknown action' })\n }\n if ('error' in outcome) return res.status(outcome.status).json({ error: outcome.error })\n return res.status(200).json({\n sale: posSaleSummary(outcome.order),\n ...(outcome.payment ? { paymentId: outcome.payment.id } : {}),\n completed: outcome.order.status === 'paid',\n ...(outcome.clientSecret ? { clientSecret: outcome.clientSecret } : {}),\n ...(outcome.paymentIntentId ? { paymentIntentId: outcome.paymentIntentId } : {}),\n // The key the typed-card form loads Stripe with, beside the secret it\n // confirms, so a register whose context read failed can still take it.\n ...(action === 'card-keyed' && outcome.clientSecret\n ? { publishableKey: String(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY ?? '') }\n : {}),\n })\n } catch (error) {\n console.error('[pos-payment]', action, error)\n return res.status(500).json({ error: 'Payment failed — check the sale before trying again' })\n }\n}\n\n/** Where a QR payment page sends the customer back to: the register. */\nasync function registerReturnUrl(\n requestHost: string | string[] | undefined,\n hostId: string,\n staff: PosStaff,\n): Promise<string> {\n const origin = `https://${String(requestHost ?? '')}`\n const subdomain = (\n await firebaseAdmin.app().firestore().collection('hostIndex').doc(hostId).get()\n ).get('subdomain') as string | undefined\n const orgSlug = staff.org?.['slug'] as string | undefined\n return orgSlug && subdomain\n ? `${origin}${buildRoute(Route.HOST_PLUGIN, { orgSlug, host: subdomain, pluginSlug: 'pos' })}`\n : origin\n}\n\n/** The balance a new tender may take, or a refusal. */\nfunction tenderable(\n order: PosLiftedOrder,\n payments: CommerceModel.OrderPayment[],\n): number {\n return CommerceModel.posTenderableCents(Number(order.totals?.totalCents ?? 0), payments)\n}\n\nconst NOT_OPEN = { kind: 'refuse' as const, status: 409, error: 'This sale is no longer open' }\n\n/**\n * Cash: the amount defaults to whatever is left, the change is what the\n * customer handed over beyond it (and beyond any tip they chose).\n */\nasync function takeCash(\n staff: PosStaff,\n orderId: string,\n paymentId: string,\n body: Record<string, any>,\n tipCents: number,\n): Promise<PosPaymentOutcome> {\n const tenderedCents = Math.round(Number(body['tenderedCents'] ?? 0))\n const askedCents = Math.round(Number(body['amountCents'] ?? 0))\n return await applyPosPayment({\n hostId: staff.hostId,\n orderId,\n paymentId,\n decide: ({ order, payments, existing }) => {\n if (existing) return { kind: 'keep' }\n if (order.status !== 'pending') return NOT_OPEN\n if (!Number.isFinite(tenderedCents) || tenderedCents <= 0) {\n return { kind: 'refuse', status: 400, error: 'Enter the cash received.' }\n }\n const open = tenderable(order, payments)\n if (open <= 0) return { kind: 'refuse', status: 409, error: 'Nothing is left to pay on this sale.' }\n const amountCents =\n askedCents > 0 ? Math.min(askedCents, open) : Math.min(open, Math.max(0, tenderedCents - tipCents))\n if (!(amountCents > 0)) {\n return { kind: 'refuse', status: 400, error: 'The cash received does not cover the tip.' }\n }\n const tipProblem = CommerceModel.posTipProblem(tipCents, amountCents)\n if (tipProblem) return { kind: 'refuse', status: 400, error: tipProblem }\n if (tenderedCents < amountCents + tipCents) {\n return { kind: 'refuse', status: 400, error: 'Cash received is short' }\n }\n const total = Number(order.totals?.totalCents ?? 0)\n const now = Date.now()\n return {\n kind: 'put',\n payment: {\n id: paymentId,\n method: 'cash',\n amountCents,\n ...(tipCents > 0 ? { tipCents } : {}),\n status: 'succeeded',\n atMs: now,\n settledAtMs: now,\n cashTenderedCents: tenderedCents,\n changeCents: tenderedCents - amountCents - tipCents,\n takeFeeCents: CommerceModel.posPaymentTakeShareCents({\n method: 'cash',\n takeFeeCents: Number(order.posTakeFeeCents ?? 0),\n totalCents: total,\n amountCents,\n }),\n feeCents: 0,\n cashierId: staff.uid,\n },\n }\n },\n })\n}\n\nfunction giftCardRef(hostId: string, code: string) {\n return firebaseAdmin\n .app()\n .firestore()\n .collection('hosts')\n .doc(hostId)\n .collection('giftCards')\n .doc(code)\n}\n\n/** A gift card's spendable balance, for the cashier to read to the customer. */\nasync function giftCardBalance(\n staff: PosStaff,\n body: Record<string, any>,\n res: Parameters<PluginApiHandler>[1],\n): Promise<void> {\n const code = CommerceModel.giftCardCodeOf(body['code'])\n const rate = await consumeRateLimit(`pos-gift-balance:${staff.uid}`, {\n limit: 30,\n windowMs: 60_000,\n })\n if (!rate.allowed) {\n return res.status(429).json({ error: 'Too many balance checks. Wait a minute and try again.' })\n }\n if (CommerceModel.giftCardCodeProblem(code)) {\n return res.status(404).json({ error: 'No gift card has that code.' })\n }\n const snapshot = await giftCardRef(staff.hostId, code).get()\n if (!snapshot.exists) return res.status(404).json({ error: 'No gift card has that code.' })\n const card = snapshot.data() as CommerceModel.HostGiftCard\n return res.status(200).json({\n availableCents: CommerceModel.giftCardAvailableCents(card, Date.now()),\n frozen: CommerceModel.isGiftCardFrozen(card),\n voided: Number(card.voidedAtMs) > 0,\n last4: code.slice(-4),\n })\n}\n\n/**\n * A gift card: takes the smaller of what the card can give and what is left\n * to pay, in ONE transaction with the sale. The card's spendable balance\n * honours every live hold an online checkout placed on it (AGL-2449), and a\n * frozen card gives nothing (AGL-3363), so the till and the website can\n * never spend the same dollars.\n */\nasync function takeGiftCard(\n staff: PosStaff,\n orderId: string,\n paymentId: string,\n body: Record<string, any>,\n): Promise<PosPaymentOutcome> {\n const code = CommerceModel.giftCardCodeOf(body['code'])\n if (CommerceModel.giftCardCodeProblem(code)) {\n return { ok: false, status: 404, error: 'No gift card has that code.' }\n }\n const askedCents = Math.round(Number(body['amountCents'] ?? 0))\n const cardRef = giftCardRef(staff.hostId, code)\n return await applyPosPayment({\n hostId: staff.hostId,\n orderId,\n paymentId,\n prepare: async (transaction) => {\n const snapshot = await transaction.get(cardRef)\n return snapshot.exists ? (snapshot.data() as CommerceModel.HostGiftCard) : null\n },\n decide: ({ order, payments, existing, context: card }) => {\n if (existing) return { kind: 'keep' }\n if (order.status !== 'pending') return NOT_OPEN\n if (!card) return { kind: 'refuse', status: 404, error: 'No gift card has that code.' }\n const available = CommerceModel.giftCardAvailableCents(card, Date.now())\n if (available <= 0) {\n return {\n kind: 'refuse',\n status: 409,\n error: CommerceModel.isGiftCardFrozen(card)\n ? 'This gift card is on hold and cannot be used right now.'\n : 'This gift card has no balance left.',\n }\n }\n const open = tenderable(order, payments)\n const amountCents = Math.min(available, open, askedCents > 0 ? askedCents : open)\n if (!(amountCents > 0)) {\n return { kind: 'refuse', status: 409, error: 'Nothing is left to pay on this sale.' }\n }\n const now = Date.now()\n return {\n kind: 'put',\n payment: {\n id: paymentId,\n method: 'gift_card',\n amountCents,\n status: 'succeeded',\n atMs: now,\n settledAtMs: now,\n giftCardId: code,\n last4: code.slice(-4),\n takeFeeCents: CommerceModel.posPaymentTakeShareCents({\n method: 'gift_card',\n takeFeeCents: Number(order.posTakeFeeCents ?? 0),\n totalCents: Number(order.totals?.totalCents ?? 0),\n amountCents,\n }),\n feeCents: 0,\n cashierId: staff.uid,\n },\n }\n },\n write: (transaction, card, payment) => {\n transaction.set(\n cardRef,\n {\n balanceCents: Math.max(0, Number(card?.balanceCents ?? 0) - payment.amountCents),\n lastUsedAtMs: Date.now(),\n },\n { merge: true },\n )\n },\n })\n}\n\n/**\n * Staff search for a store-credit account at the register (AGL-3640): a\n * customer's email or code, answered by the plugin that keeps the account.\n * Only staff reach it — `authorizePosStaff` above — so a provider may look\n * accounts up by email here, which it never does for a shopper.\n */\nasync function creditLookup(staff: PosStaff, body: Record<string, any>, res: any) {\n const entry = checkoutCreditProvider(String(body['providerId'] ?? ''))\n if (!entry?.provider.lookup) return res.status(404).json({ error: 'That kind of credit is not taken here.' })\n const rate = await consumeRateLimit(`pos-credit-lookup:${staff.uid}`, {\n limit: 60,\n windowMs: 60_000,\n })\n if (!rate.allowed) return res.status(429).json({ error: 'Too many lookups. Wait a moment.' })\n if (!(await entry.provider.offered({ hostId: staff.hostId, channel: 'pos' }).catch(() => false))) {\n return res.status(404).json({ error: 'That kind of credit is not taken here.' })\n }\n const found = await entry.provider\n .lookup({ hostId: staff.hostId, query: String(body['query'] ?? '').slice(0, 120) })\n .catch((error: unknown) => {\n console.error('[pos-payment] credit lookup failed', entry.providerId, error)\n return []\n })\n const accounts = found\n .slice(0, 10)\n .map((account) => normalizeCheckoutCreditAccount(account))\n .filter((account) => !('error' in account))\n return res.status(200).json({ providerId: entry.providerId, accounts })\n}\n\n/**\n * Store credit another plugin keeps (AGL-3640) — a rewards balance, a friend's\n * referral credit — by the customer's code, or by the account a staff lookup\n * found. The provider's stage reads the account INSIDE the sale's transaction\n * and its debit writes there, so the credit is taken with the payment or not\n * at all; a retried press finds its own payment and takes nothing more.\n */\nasync function takeCredit(\n staff: PosStaff,\n orderId: string,\n paymentId: string,\n body: Record<string, any>,\n): Promise<PosPaymentOutcome> {\n const code = normalizeCheckoutCreditCode(body['code'])\n const entry = code\n ? checkoutCreditProviderForCode(code)\n : checkoutCreditProvider(String(body['providerId'] ?? ''))\n if (!entry) return { ok: false, status: 404, error: 'That code is not one this store takes.' }\n if (!(await entry.provider.offered({ hostId: staff.hostId, channel: 'pos' }).catch(() => false))) {\n return { ok: false, status: 404, error: 'That kind of credit is not taken here.' }\n }\n const sale = await readPosSale(staff.hostId, orderId)\n if (!sale) return { ok: false, status: 404, error: 'Unknown sale' }\n const account = normalizeCheckoutCreditAccount(\n await entry.provider\n .resolve({\n hostId: staff.hostId,\n ...(code ? { code } : { reference: String(body['reference'] ?? '') }),\n channel: 'pos',\n customerEmail: (sale as { customerEmail?: string | null }).customerEmail ?? null,\n staff: true,\n })\n .catch((error: unknown) => {\n console.error('[pos-payment] credit resolve failed', entry.providerId, error)\n return null\n }),\n )\n if ('error' in account) return { ok: false, status: account.status, error: account.error }\n const askedCents = Math.round(Number(body['amountCents'] ?? 0))\n return await applyPosPayment<CheckoutCreditStage | null>({\n hostId: staff.hostId,\n orderId,\n paymentId,\n prepare: async (transaction) =>\n entry.provider.stage({\n transaction,\n hostId: staff.hostId,\n reference: account.reference,\n orderId,\n nowMs: Date.now(),\n }),\n decide: ({ order, payments, existing, context: stage }) => {\n if (existing) return { kind: 'keep' }\n if (order.status !== 'pending') return NOT_OPEN\n if (!stage) return { kind: 'refuse', status: 404, error: `That ${account.label.toLowerCase()} account no longer exists.` }\n const open = tenderable(order, payments)\n if (open <= 0) return { kind: 'refuse', status: 409, error: 'Nothing is left to pay on this sale.' }\n const amountCents = Math.min(stage.availableCents, open, askedCents > 0 ? askedCents : open)\n if (!(amountCents > 0)) {\n return { kind: 'refuse', status: 409, error: `This ${account.label.toLowerCase()} account has nothing to spend.` }\n }\n const now = Date.now()\n return {\n kind: 'put',\n payment: {\n id: paymentId,\n method: 'credit',\n amountCents,\n status: 'succeeded',\n atMs: now,\n settledAtMs: now,\n creditProviderId: entry.providerId,\n creditReference: account.reference,\n creditLabel: account.label,\n ...(account.last4 ? { last4: account.last4 } : {}),\n takeFeeCents: CommerceModel.posPaymentTakeShareCents({\n method: 'credit',\n takeFeeCents: Number(order.posTakeFeeCents ?? 0),\n totalCents: Number(order.totals?.totalCents ?? 0),\n amountCents,\n }),\n feeCents: 0,\n cashierId: staff.uid,\n },\n }\n },\n write: (_transaction, stage, payment) => {\n // The stage writes through the sale's own transaction. Taking less than\n // the payment records would leave the sale paid by money that did not\n // move, so a short debit aborts the whole commit instead.\n const taken = stage ? stage.debit({ cents: payment.amountCents, key: payment.id, orderId, channel: 'pos' }) : 0\n if (taken !== payment.amountCents) {\n throw new Error(`credit debit ${taken} short of payment ${payment.amountCents}`)\n }\n },\n })\n}\n\nfunction reservationRef(hostId: string, reservationId: string) {\n return firebaseAdmin\n .app()\n .firestore()\n .collection('hosts')\n .doc(hostId)\n .collection('reservations')\n .doc(reservationId)\n}\n\n/** Charged to a checked-in stay's folio, in the same commit as the payment. */\nasync function takeFolio(\n staff: PosStaff,\n orderId: string,\n paymentId: string,\n body: Record<string, any>,\n): Promise<PosPaymentOutcome> {\n const reservationId = String(body['reservationId'] ?? '')\n if (!/^[A-Za-z0-9_-]{1,128}$/.test(reservationId)) {\n return { ok: false, status: 400, error: 'Pick a reservation' }\n }\n const askedCents = Math.round(Number(body['amountCents'] ?? 0))\n const stayRef = reservationRef(staff.hostId, reservationId)\n return await applyPosPayment({\n hostId: staff.hostId,\n orderId,\n paymentId,\n prepare: async (transaction) => (await transaction.get(stayRef)).exists as boolean,\n decide: ({ order, payments, existing, context: stayExists }) => {\n if (existing) return { kind: 'keep' }\n if (order.status !== 'pending') return NOT_OPEN\n if (!stayExists) return { kind: 'refuse', status: 404, error: 'Unknown reservation' }\n const open = tenderable(order, payments)\n const amountCents = Math.min(open, askedCents > 0 ? askedCents : open)\n if (!(amountCents > 0)) {\n return { kind: 'refuse', status: 409, error: 'Nothing is left to pay on this sale.' }\n }\n const now = Date.now()\n return {\n kind: 'put',\n payment: {\n id: paymentId,\n method: 'folio',\n amountCents,\n status: 'succeeded',\n atMs: now,\n settledAtMs: now,\n reservationId,\n folioAtMs: now,\n takeFeeCents: CommerceModel.posPaymentTakeShareCents({\n method: 'folio',\n takeFeeCents: Number(order.posTakeFeeCents ?? 0),\n totalCents: Number(order.totals?.totalCents ?? 0),\n amountCents,\n }),\n feeCents: 0,\n cashierId: staff.uid,\n },\n event: { event: 'folio', detail: `Charged to reservation ${reservationId}` },\n }\n },\n write: (transaction, _stay, payment) => {\n // `update`, never a merge-set: a missing stay must not be minted as a\n // stub holding one folio line (AGL-1760). It exists — read above.\n transaction.update(stayRef, {\n folio: firebaseAdmin.firestore.FieldValue.arrayUnion({\n orderId,\n paymentId: payment.id,\n amountCents: payment.amountCents,\n note: 'Register sale',\n atMs: payment.folioAtMs ?? Date.now(),\n }),\n })\n },\n })\n}\n\n/**\n * Abandons an open sale: everything it took is handed back first — cards\n * refunded in full (tip included, fee and transfer reversed), gift cards\n * re-credited, the room charge taken off the folio, cash marked as returned —\n * and only then is the order cancelled. A refund Stripe refuses stops the void\n * with the sale still open and its payment still recorded, never cancelled\n * over money that did not come back.\n */\nexport async function voidPosSale(\n staff: PosStaff,\n orderId: string,\n): Promise<PosPaymentOutcome> {\n const hostId = staff.hostId\n const order = await readPosSale(hostId, orderId)\n if (!order) return { ok: false, status: 404, error: 'Unknown sale' }\n if (order.status === 'cancelled') return { ok: true, order, payment: null, completed: false, changed: false }\n if (order.status !== 'pending' || !Array.isArray(order.payments)) {\n return {\n ok: false,\n status: 409,\n error: 'This sale is already paid. Refund it from the order instead.',\n }\n }\n for (const payment of CommerceModel.orderPayments(order)) {\n if (payment.status === 'pending' && CommerceModel.isCardPaymentMethod(payment.method)) {\n const cancelled = await cancelPosCardPayment({ hostId, orderId, paymentId: payment.id })\n if (!cancelled.ok) return cancelled\n }\n }\n // Re-read after the cancels: one may have completed the sale in the gap.\n const current = await readPosSale(hostId, orderId)\n if (!current) return { ok: false, status: 404, error: 'Unknown sale' }\n if (current.status !== 'pending') {\n return {\n ok: false,\n status: 409,\n error: 'The last card payment went through and the sale is paid. Refund it from the order instead.',\n }\n }\n for (const payment of CommerceModel.orderPayments(current)) {\n if (payment.status !== 'succeeded') continue\n const reversed = await reversePayment(staff, current, payment)\n if (!reversed.ok) return reversed\n }\n const firestore = firebaseAdmin.app().firestore()\n const orderRef = firestore.collection('hosts').doc(hostId).collection('orders').doc(orderId)\n const cancelled = await firestore.runTransaction(async (transaction: any) => {\n const fresh = {\n ...(CommerceModel.liftLegacyOrder(((await transaction.get(orderRef)).data() ?? {}) as any) as any),\n $id: orderId,\n } as PosLiftedOrder\n if (fresh.status !== 'pending') return null\n const open = CommerceModel.orderPayments(fresh).some(\n (payment) => payment.status === 'pending' || payment.status === 'succeeded',\n )\n if (open) return null\n const next = {\n ...fresh,\n status: 'cancelled' as const,\n timeline: CommerceModel.appendOrderEvent(fresh, 'pos-sale-voided', 'Voided at the register'),\n }\n transaction.set(\n orderRef,\n {\n status: 'cancelled',\n cancelledAtMs: Date.now(),\n timeline: next.timeline,\n ...CommerceModel.orderListFields(next, orderId),\n },\n { merge: true },\n )\n return next\n })\n if (!cancelled) {\n return { ok: false, status: 409, error: 'A payment on this sale changed. Check it and try again.' }\n }\n await releasePosSaleDiscount(hostId, current)\n return { ok: true, order: cancelled, payment: null, completed: false, changed: true }\n}\n\n/** Hands one settled payment back, recording `reversed` in the same commit. */\nasync function reversePayment(\n staff: PosStaff,\n order: PosLiftedOrder,\n payment: CommerceModel.OrderPayment,\n): Promise<PosPaymentOutcome> {\n const hostId = staff.hostId\n if (CommerceModel.isCardPaymentMethod(payment.method)) {\n if (!payment.paymentIntentId) {\n return { ok: false, status: 409, error: 'A card payment on this sale has no charge to refund.' }\n }\n const refund = await posStripe('POST', 'refunds', {\n idempotencyKey: `pos-void:${payment.id}`,\n params: {\n payment_intent: payment.paymentIntentId,\n reverse_transfer: true,\n refund_application_fee: true,\n 'metadata[kind]': 'pos-void',\n 'metadata[orderId]': order.$id,\n },\n })\n if (!refund.ok) {\n return {\n ok: false,\n status: 502,\n error: posStripeErrorMessage(refund.body, 'The card refund failed. The sale is still open.'),\n }\n }\n }\n const cardRef = payment.giftCardId ? giftCardRef(hostId, payment.giftCardId) : null\n const stayRef = payment.reservationId ? reservationRef(hostId, payment.reservationId) : null\n // Store credit goes back to the plugin that keeps it (AGL-3640), in the\n // same commit as the reversal. A provider that is gone cannot take it\n // back, so the void stops with the sale still open rather than cancelling\n // over credit that did not come back.\n const creditEntry =\n payment.method === 'credit' && payment.creditProviderId ? checkoutCreditProvider(payment.creditProviderId) : null\n if (payment.method === 'credit' && (!creditEntry || !payment.creditReference)) {\n return {\n ok: false,\n status: 409,\n error: 'The store credit on this sale cannot be handed back right now. The sale is still open.',\n }\n }\n return await applyPosPayment({\n hostId,\n orderId: order.$id,\n paymentId: payment.id,\n prepare: async (transaction) => {\n if (payment.method === 'gift_card' && cardRef) {\n const snapshot = await transaction.get(cardRef)\n return { card: snapshot.exists ? (snapshot.data() as CommerceModel.HostGiftCard) : null, folio: null, credit: null }\n }\n if (payment.method === 'folio' && stayRef) {\n const snapshot = await transaction.get(stayRef)\n return { card: null, folio: snapshot.exists ? ((snapshot.get('folio') ?? []) as any[]) : null, credit: null }\n }\n if (payment.method === 'credit' && creditEntry && payment.creditReference) {\n const credit = await creditEntry.provider.stage({\n transaction,\n hostId,\n reference: payment.creditReference,\n orderId: order.$id,\n nowMs: Date.now(),\n })\n return { card: null, folio: null, credit }\n }\n return { card: null, folio: null, credit: null }\n },\n decide: ({ existing }) => {\n if (!existing) return { kind: 'refuse', status: 404, error: 'Unknown payment' }\n if (existing.status !== 'succeeded') return { kind: 'keep' }\n return {\n kind: 'put',\n payment: { ...existing, status: 'reversed' },\n event: {\n event: 'pos-payment-reversed',\n detail:\n existing.method === 'cash'\n ? `${CommerceModel.describeOrderPayment(existing)} handed back in cash`\n : `${CommerceModel.describeOrderPayment(existing)} returned`,\n },\n }\n },\n write: (transaction, context, reversed) => {\n if (reversed.method === 'gift_card' && cardRef && context.card) {\n transaction.set(\n cardRef,\n { balanceCents: Number(context.card.balanceCents ?? 0) + reversed.amountCents },\n { merge: true },\n )\n }\n if (reversed.method === 'folio' && stayRef && context.folio) {\n transaction.update(stayRef, {\n folio: context.folio.filter((entry) => entry?.paymentId !== reversed.id),\n })\n }\n if (reversed.method === 'credit' && context.credit) {\n context.credit.reverse({ key: reversed.id, orderId: order.$id })\n }\n },\n })\n}\n\n/** A repeat of the same receipt choice inside this window sends nothing more. */\nconst RECEIPT_REPEAT_WINDOW_MS = 2 * 60 * 1000\n\n/**\n * How the customer wants their receipt, from the cashier or the customer\n * display. Kept on the order; an email chosen after the sale is paid is sent\n * at once, and one chosen before is sent when it completes.\n */\nexport async function recordReceiptChoice(\n staff: PosStaff,\n orderId: string,\n body: Record<string, any>,\n): Promise<PosPaymentOutcome> {\n const channel = String(body['channel'] ?? '') as CommerceModel.PosReceiptChannel\n if (!['email', 'sms', 'print', 'none'].includes(channel)) {\n return { ok: false, status: 400, error: 'Choose email, text, print or no receipt.' }\n }\n const to =\n channel === 'email'\n ? CommerceModel.posDisplayEmail(body['to'])\n : channel === 'sms'\n ? CommerceModel.posDisplayPhone(body['to'])\n : ''\n if ((channel === 'email' || channel === 'sms') && !to) {\n return {\n ok: false,\n status: 400,\n error: channel === 'email' ? 'Enter a valid email address.' : 'Enter a valid phone number.',\n }\n }\n if (channel === 'sms' && !pluginSmsAvailable()) {\n return { ok: false, status: 409, error: 'Text receipts are not set up for this store.' }\n }\n const marketingOptIn = channel === 'email' && body['marketingOptIn'] === true\n const firestore = firebaseAdmin.app().firestore()\n const orderRef = firestore.collection('hosts').doc(staff.hostId).collection('orders').doc(orderId)\n const order = await firestore.runTransaction(async (transaction: any) => {\n const snapshot = await transaction.get(orderRef)\n if (!snapshot.exists) return null\n const fresh = {\n ...(CommerceModel.liftLegacyOrder((snapshot.data() ?? {}) as any) as any),\n $id: orderId,\n } as PosLiftedOrder\n if (fresh.channel !== 'pos') return null\n // The same choice twice in a row (a double tap, or the display and the\n // cashier answering together) is one receipt, not two.\n const previous = fresh.receiptRequest\n if (\n fresh.status === 'paid' &&\n previous &&\n previous.channel === channel &&\n String(previous.to ?? '') === to &&\n Date.now() - Number(previous.atMs ?? 0) < RECEIPT_REPEAT_WINDOW_MS\n ) {\n return { ...fresh, repeated: true } as PosLiftedOrder & { repeated?: boolean }\n }\n const receiptRequest = {\n channel,\n ...(to ? { to } : {}),\n ...(marketingOptIn ? { marketingOptIn: true } : {}),\n atMs: Date.now(),\n }\n transaction.set(\n orderRef,\n {\n receiptRequest,\n ...(channel === 'email' && !fresh.customerEmail\n ? {\n customerEmail: to,\n ...CommerceModel.orderListFields({ ...fresh, customerEmail: to }, orderId),\n }\n : {}),\n // The receipt door texts `customerPhone` (AGL-3610).\n ...(channel === 'sms' ? { customerPhone: to } : {}),\n },\n { merge: true },\n )\n return { ...fresh, receiptRequest } as PosLiftedOrder & { repeated?: boolean }\n })\n if (!order) return { ok: false, status: 404, error: 'Unknown sale' }\n if (order.repeated) return { ok: true, order, payment: null, completed: false, changed: false }\n if (order.status === 'paid' && channel === 'print') {\n // Chosen after the sale completed: printed now on the register's receipt\n // printer, under the sale's own key so it never prints twice (AGL-3609).\n await printPosSaleReceipt(staff.hostId, orderId)\n }\n // A kiosk's own receipt screen (AGL-3623) is not the register's display:\n // the display may be asking the cashier's customer right now.\n if (order.status === 'paid' && order.registerId && order.posSource !== 'kiosk') {\n // The customer has answered (or the cashier for them): the display says\n // thank you and drops the address they typed (AGL-3608).\n await finishPosDisplayReceipt(staff.hostId, order.registerId).catch((error: unknown) =>\n console.error('[pos-payment] display finish failed', error),\n )\n }\n if (order.status === 'paid' && (channel === 'email' || channel === 'sms')) {\n // Chosen after the sale completed: sent now, to where they said.\n const sent = await deliverChosenPosReceipt(\n { hostId: staff.hostId, orderId },\n { channel, to, orderEmail: String(order.customerEmail ?? '') },\n )\n if (channel === 'email') {\n await recordCapturedContact({\n orgId: '',\n hostId: staff.hostId,\n identity: { email: to },\n surface: 'relationship',\n lifecycleFloor: 'customer',\n ...(marketingOptIn ? { marketingConsent: true } : {}),\n interaction: {\n source: 'order',\n refId: orderId,\n summary: `In-store purchase (${CommerceModel.formatReceiptMoney(\n Number(order.totals?.totalCents ?? 0),\n POS_CURRENCY,\n )})`,\n },\n }).catch((error: unknown) => console.error('[pos-payment] contact capture failed', error))\n }\n if (sent !== 'sent') {\n // A failed send is not a repeat: the cashier's retry goes out.\n await orderRef\n .set({ receiptRequest: { atMs: 0 } }, { merge: true })\n .catch((error: unknown) => console.error('[pos-payment] receipt retry reset failed', error))\n }\n if (sent === 'not_configured') {\n return {\n ok: false,\n status: 409,\n error: channel === 'sms' ? 'Text receipts are not set up for this store.' : 'Email is not set up.',\n }\n }\n if (sent !== 'sent') return { ok: false, status: 502, error: 'The receipt could not be sent.' }\n }\n return { ok: true, order, payment: null, completed: false, changed: true }\n}\n"],"names":["consumeRateLimit","firebaseAdmin","getPluginConfig","buildRoute","Route","recordCapturedContact","pluginSmsAvailable","checkoutCreditProvider","checkoutCreditProviderForCode","normalizeCheckoutCreditAccount","normalizeCheckoutCreditCode","offeredCheckoutCredits","finishPosDisplayReceipt","CommerceModel","posRegisterSettings","posOpsSettings","authorizePosStaff","posIdempotencyKey","posQueryBody","posRequestBody","applyPosPayment","deliverChosenPosReceipt","posPaymentId","posSaleSummary","readPosSale","releasePosSaleDiscount","posPaymentCashierId","printPosSaleReceipt","POS_CURRENCY","posStripe","posStripeErrorMessage","posStripeTestMode","posTerminalAvailable","cancelPosCardPayment","createCardPresentIntent","refreshPosCardPayment","retryCardPresentPayment","simulatePosReaderTap","startCardKeyedPayment","startCardLinkPayment","startCardPresentPayment","posPaymentHandler","req","res","body","method","status","json","error","hostId","String","gate","staff","action","orderId","process","giftCardBalance","creditLookup","readers","app","firestore","collection","doc","limit","get","docs","map","id","label","registerId","livemode","Boolean","config","orgId","undefined","settings","ops","terminal","available","testMode","publishableKey","env","NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY","smsReceipts","credits","channel","startsPayment","includes","attemptKey","paymentId","uid","signedInUid","assertion","amountCents","Math","round","Number","tipCents","outcome","order","ok","payment","completed","changed","takeCash","takeGiftCard","takeCredit","takeFolio","cashierId","org","readerId","paymentMethodId","returnUrl","registerReturnUrl","headers","host","cardNumber","voidPosSale","recordReceiptChoice","sale","clientSecret","paymentIntentId","console","requestHost","origin","subdomain","orgSlug","HOST_PLUGIN","pluginSlug","tenderable","payments","posTenderableCents","totals","totalCents","NOT_OPEN","kind","tenderedCents","askedCents","decide","existing","isFinite","open","min","max","tipProblem","posTipProblem","total","now","Date","atMs","settledAtMs","cashTenderedCents","changeCents","takeFeeCents","posPaymentTakeShareCents","posTakeFeeCents","feeCents","giftCardRef","code","giftCardCodeOf","rate","windowMs","allowed","giftCardCodeProblem","snapshot","exists","card","data","availableCents","giftCardAvailableCents","frozen","isGiftCardFrozen","voided","voidedAtMs","last4","slice","cardRef","prepare","transaction","context","giftCardId","write","set","balanceCents","lastUsedAtMs","merge","entry","provider","lookup","offered","catch","found","query","providerId","accounts","account","filter","resolve","reference","customerEmail","stage","nowMs","toLowerCase","creditProviderId","creditReference","creditLabel","_transaction","taken","debit","cents","key","Error","reservationRef","reservationId","test","stayRef","stayExists","folioAtMs","event","detail","_stay","update","folio","FieldValue","arrayUnion","note","Array","isArray","orderPayments","isCardPaymentMethod","cancelled","current","reversed","reversePayment","orderRef","runTransaction","fresh","liftLegacyOrder","$id","some","next","timeline","appendOrderEvent","cancelledAtMs","orderListFields","refund","idempotencyKey","params","payment_intent","reverse_transfer","refund_application_fee","creditEntry","credit","describeOrderPayment","reverse","RECEIPT_REPEAT_WINDOW_MS","to","posDisplayEmail","posDisplayPhone","marketingOptIn","previous","receiptRequest","repeated","customerPhone","posSource","sent","orderEmail","identity","email","surface","lifecycleFloor","marketingConsent","interaction","source","refId","summary","formatReceiptMoney"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/pos-payment.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 {\n consumeRateLimit,\n firebaseAdmin,\n getPluginConfig,\n} from '@aglyn/tenant-data-admin'\nimport { buildRoute, Route, type PluginApiHandler } from '@aglyn/aglyn/server'\nimport recordCapturedContact from '@aglyn/aglyn/plugin-manager/record-captured-contact'\nimport { pluginSmsAvailable } from '@aglyn/aglyn/plugin-manager/plugin-sms-messaging'\nimport {\n checkoutCreditProvider,\n checkoutCreditProviderForCode,\n normalizeCheckoutCreditAccount,\n normalizeCheckoutCreditCode,\n offeredCheckoutCredits,\n type CheckoutCreditStage,\n} from '@aglyn/aglyn/plugin-manager/plugin-checkout-credits'\nimport { finishPosDisplayReceipt } from './pos-display'\nimport * as CommerceModel from '../model'\nimport { posRegisterSettings } from '../plugin-config'\nimport { posOpsSettings } from '../pos-ops-config'\nimport {\n authorizePosStaff,\n posIdempotencyKey,\n posQueryBody,\n posRequestBody,\n type PosStaff,\n} from './pos-auth'\nimport {\n applyPosPayment,\n deliverChosenPosReceipt,\n posPaymentId,\n posSaleSummary,\n readPosSale,\n releasePosSaleDiscount,\n type PosLiftedOrder,\n type PosPaymentOutcome,\n} from './pos-sale'\nimport { posPaymentCashierId } from './pos-sale-stamp'\nimport { printPosSaleReceipt } from './pos-print'\nimport {\n POS_CURRENCY,\n posStripe,\n posStripeErrorMessage,\n posStripeTestMode,\n posTerminalAvailable,\n} from './pos-stripe'\nimport {\n cancelPosCardPayment,\n createCardPresentIntent,\n refreshPosCardPayment,\n retryCardPresentPayment,\n simulatePosReaderTap,\n startCardKeyedPayment,\n startCardLinkPayment,\n startCardPresentPayment,\n} from './pos-terminal'\n\n/**\n * `POST /api/commerce/pos-payment` (AGL-3607): every tender against an OPEN\n * register sale, one `action` per request.\n *\n * The sale was priced by `pos-order.ts` (`payment: 'open'`); nothing here\n * re-prices it or lets the register name a total. Each payment-starting action\n * needs the register's `Idempotency-Key`, from which the payment's id is\n * derived: pressing a tender twice, or retrying after a lost response, finds\n * the payment the first press started instead of taking the money twice.\n */\nexport const posPaymentHandler: PluginApiHandler = async (req, res) => {\n // `sale` is a read and may be a GET, so a register re-reading its sale does\n // not spend the console's write budget; everything else moves money.\n const body = req.method === 'GET' ? posQueryBody(req) : posRequestBody(req)\n if (\n !(\n req.method === 'POST' ||\n (req.method === 'GET' && (body['action'] === 'sale' || body['action'] === 'context'))\n )\n ) {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const hostId = String(body['hostId'] ?? '')\n const gate = await authorizePosStaff(req, hostId, 'posSell')\n if ('error' in gate) return res.status(gate.status).json({ error: gate.error })\n let staff = gate.staff\n const action = String(body['action'] ?? '')\n const orderId = String(body['orderId'] ?? '')\n try {\n if (action === 'gift-card-balance') {\n return await giftCardBalance(staff, body, res)\n }\n if (action === 'credit-lookup') {\n return await creditLookup(staff, body, res)\n }\n if (action === 'context') {\n // What the register needs to draw its tenders: the site's tip and\n // receipt settings, whether card readers are offered at all, and the\n // key the typed-card form loads Stripe with.\n const readers = posTerminalAvailable()\n ? (\n await firebaseAdmin\n .app()\n .firestore()\n .collection('hosts')\n .doc(hostId)\n .collection('terminalReaders')\n .limit(50)\n .get()\n ).docs.map((doc: any) => ({\n id: doc.id as string,\n label: String(doc.get('label') ?? 'Card reader'),\n registerId: (doc.get('registerId') as string | undefined) ?? null,\n status: String(doc.get('status') ?? 'offline'),\n livemode: Boolean(doc.get('livemode')),\n }))\n : []\n const config = await getPluginConfig(staff.orgId || undefined, 'commerce', { hostId })\n return res.status(200).json({\n settings: posRegisterSettings(config),\n // The register's own rules (AGL-3609): the shift it requires, the\n // idle lock and the refund limit. The console reads the same config\n // client-side; the native apps read it here.\n ops: posOpsSettings(config),\n terminal: { available: posTerminalAvailable(), testMode: posStripeTestMode() },\n readers,\n publishableKey: String(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY ?? ''),\n // A text receipt is offered only when an SMS provider is on (AGL-3610).\n smsReceipts: pluginSmsAvailable(),\n // Store credit other plugins keep — rewards (AGL-3640) — offered here.\n credits: await offeredCheckoutCredits({ hostId, channel: 'pos' }),\n })\n }\n if (!orderId) return res.status(400).json({ error: 'Missing orderId' })\n const startsPayment = [\n 'card-present-sdk',\n 'cash',\n 'gift-card',\n 'credit',\n 'folio',\n 'card-present',\n 'card-keyed',\n 'card-link',\n ].includes(action)\n const attemptKey = posIdempotencyKey(req)\n if (startsPayment && !attemptKey) {\n return res.status(400).json({ error: 'Missing Idempotency-Key' })\n }\n const paymentId = startsPayment\n ? posPaymentId(orderId, attemptKey)\n : String(body['paymentId'] ?? '')\n // The cashier a PIN switched in takes the payment (AGL-3609).\n if (startsPayment && body['cashierAssertion']) {\n staff = {\n ...staff,\n uid: await posPaymentCashierId({\n hostId,\n orderId,\n signedInUid: staff.uid,\n assertion: body['cashierAssertion'],\n }),\n }\n }\n const amountCents = Math.round(Number(body['amountCents'] ?? 0))\n const tipCents = Math.round(Number(body['tipCents'] ?? 0)) || 0\n const settings = posRegisterSettings(\n await getPluginConfig(staff.orgId || undefined, 'commerce', { hostId }),\n )\n let outcome: (PosPaymentOutcome & { clientSecret?: string; paymentIntentId?: string }) | null = null\n switch (action) {\n case 'sale': {\n const order = await readPosSale(hostId, orderId)\n if (!order) return res.status(404).json({ error: 'Unknown sale' })\n outcome = { ok: true, order, payment: null, completed: false, changed: false }\n break\n }\n case 'cash':\n outcome = await takeCash(staff, orderId, paymentId, body, tipCents)\n break\n case 'gift-card':\n outcome = await takeGiftCard(staff, orderId, paymentId, body)\n break\n case 'credit':\n outcome = await takeCredit(staff, orderId, paymentId, body)\n break\n case 'folio':\n outcome = await takeFolio(staff, orderId, paymentId, body)\n break\n case 'card-present':\n outcome = await startCardPresentPayment({\n hostId,\n orderId,\n paymentId,\n amountCents,\n tipCents,\n cashierId: staff.uid,\n org: staff.org,\n readerId: String(body['readerId'] ?? ''),\n settings,\n })\n break\n case 'card-present-sdk':\n // Collected by a native app's Stripe Terminal SDK (Tap to Pay or a\n // Bluetooth reader, AGL-3618) against this server-made intent; it\n // settles exactly like a smart-reader payment.\n outcome = await createCardPresentIntent({\n hostId,\n orderId,\n paymentId,\n amountCents,\n tipCents,\n cashierId: staff.uid,\n org: staff.org,\n })\n break\n case 'card-keyed':\n outcome = await startCardKeyedPayment({\n hostId,\n orderId,\n paymentId,\n amountCents,\n tipCents,\n cashierId: staff.uid,\n org: staff.org,\n // The register's own card fields send the PaymentMethod Stripe\n // made from the card, never the card; the server confirms with it.\n ...(body['paymentMethodId'] ? { paymentMethodId: String(body['paymentMethodId']) } : {}),\n })\n break\n case 'card-link':\n outcome = await startCardLinkPayment({\n hostId,\n orderId,\n paymentId,\n amountCents,\n tipCents,\n cashierId: staff.uid,\n org: staff.org,\n returnUrl: await registerReturnUrl(req.headers.host, hostId, staff),\n })\n break\n case 'status':\n outcome = await refreshPosCardPayment({ hostId, orderId, paymentId })\n break\n case 'cancel':\n outcome = await cancelPosCardPayment({ hostId, orderId, paymentId })\n break\n case 'retry':\n outcome = await retryCardPresentPayment({ hostId, orderId, paymentId, settings })\n break\n case 'simulate':\n outcome = await simulatePosReaderTap({\n hostId,\n orderId,\n paymentId,\n cardNumber: String(body['cardNumber'] ?? ''),\n })\n break\n case 'void':\n outcome = await voidPosSale(staff, orderId)\n break\n case 'receipt':\n outcome = await recordReceiptChoice(staff, orderId, body)\n break\n default:\n return res.status(400).json({ error: 'Unknown action' })\n }\n if ('error' in outcome) return res.status(outcome.status).json({ error: outcome.error })\n return res.status(200).json({\n sale: posSaleSummary(outcome.order),\n ...(outcome.payment ? { paymentId: outcome.payment.id } : {}),\n completed: outcome.order.status === 'paid',\n ...(outcome.clientSecret ? { clientSecret: outcome.clientSecret } : {}),\n ...(outcome.paymentIntentId ? { paymentIntentId: outcome.paymentIntentId } : {}),\n // The key the typed-card form loads Stripe with, beside the secret it\n // confirms, so a register whose context read failed can still take it.\n ...(action === 'card-keyed' && outcome.clientSecret\n ? { publishableKey: String(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY ?? '') }\n : {}),\n })\n } catch (error) {\n console.error('[pos-payment]', action, error)\n return res.status(500).json({ error: 'Payment failed — check the sale before trying again' })\n }\n}\n\n/** Where a QR payment page sends the customer back to: the register. */\nasync function registerReturnUrl(\n requestHost: string | string[] | undefined,\n hostId: string,\n staff: PosStaff,\n): Promise<string> {\n const origin = `https://${String(requestHost ?? '')}`\n const subdomain = (\n await firebaseAdmin.app().firestore().collection('hostIndex').doc(hostId).get()\n ).get('subdomain') as string | undefined\n const orgSlug = staff.org?.['slug'] as string | undefined\n return orgSlug && subdomain\n ? `${origin}${buildRoute(Route.HOST_PLUGIN, { orgSlug, host: subdomain, pluginSlug: 'pos' })}`\n : origin\n}\n\n/** The balance a new tender may take, or a refusal. */\nfunction tenderable(\n order: PosLiftedOrder,\n payments: CommerceModel.OrderPayment[],\n): number {\n return CommerceModel.posTenderableCents(Number(order.totals?.totalCents ?? 0), payments)\n}\n\nconst NOT_OPEN = { kind: 'refuse' as const, status: 409, error: 'This sale is no longer open' }\n\n/**\n * Cash: the amount defaults to whatever is left, the change is what the\n * customer handed over beyond it (and beyond any tip they chose).\n */\nasync function takeCash(\n staff: PosStaff,\n orderId: string,\n paymentId: string,\n body: Record<string, any>,\n tipCents: number,\n): Promise<PosPaymentOutcome> {\n const tenderedCents = Math.round(Number(body['tenderedCents'] ?? 0))\n const askedCents = Math.round(Number(body['amountCents'] ?? 0))\n return await applyPosPayment({\n hostId: staff.hostId,\n orderId,\n paymentId,\n decide: ({ order, payments, existing }) => {\n if (existing) return { kind: 'keep' }\n if (order.status !== 'pending') return NOT_OPEN\n if (!Number.isFinite(tenderedCents) || tenderedCents <= 0) {\n return { kind: 'refuse', status: 400, error: 'Enter the cash received.' }\n }\n const open = tenderable(order, payments)\n if (open <= 0) return { kind: 'refuse', status: 409, error: 'Nothing is left to pay on this sale.' }\n const amountCents =\n askedCents > 0 ? Math.min(askedCents, open) : Math.min(open, Math.max(0, tenderedCents - tipCents))\n if (!(amountCents > 0)) {\n return { kind: 'refuse', status: 400, error: 'The cash received does not cover the tip.' }\n }\n const tipProblem = CommerceModel.posTipProblem(tipCents, amountCents)\n if (tipProblem) return { kind: 'refuse', status: 400, error: tipProblem }\n if (tenderedCents < amountCents + tipCents) {\n return { kind: 'refuse', status: 400, error: 'Cash received is short' }\n }\n const total = Number(order.totals?.totalCents ?? 0)\n const now = Date.now()\n return {\n kind: 'put',\n payment: {\n id: paymentId,\n method: 'cash',\n amountCents,\n ...(tipCents > 0 ? { tipCents } : {}),\n status: 'succeeded',\n atMs: now,\n settledAtMs: now,\n cashTenderedCents: tenderedCents,\n changeCents: tenderedCents - amountCents - tipCents,\n takeFeeCents: CommerceModel.posPaymentTakeShareCents({\n method: 'cash',\n takeFeeCents: Number(order.posTakeFeeCents ?? 0),\n totalCents: total,\n amountCents,\n }),\n feeCents: 0,\n cashierId: staff.uid,\n },\n }\n },\n })\n}\n\nfunction giftCardRef(hostId: string, code: string) {\n return firebaseAdmin\n .app()\n .firestore()\n .collection('hosts')\n .doc(hostId)\n .collection('giftCards')\n .doc(code)\n}\n\n/** A gift card's spendable balance, for the cashier to read to the customer. */\nasync function giftCardBalance(\n staff: PosStaff,\n body: Record<string, any>,\n res: Parameters<PluginApiHandler>[1],\n): Promise<void> {\n const code = CommerceModel.giftCardCodeOf(body['code'])\n const rate = await consumeRateLimit(`pos-gift-balance:${staff.uid}`, {\n limit: 30,\n windowMs: 60_000,\n })\n if (!rate.allowed) {\n return res.status(429).json({ error: 'Too many balance checks. Wait a minute and try again.' })\n }\n if (CommerceModel.giftCardCodeProblem(code)) {\n return res.status(404).json({ error: 'No gift card has that code.' })\n }\n const snapshot = await giftCardRef(staff.hostId, code).get()\n if (!snapshot.exists) return res.status(404).json({ error: 'No gift card has that code.' })\n const card = snapshot.data() as CommerceModel.HostGiftCard\n return res.status(200).json({\n availableCents: CommerceModel.giftCardAvailableCents(card, Date.now()),\n frozen: CommerceModel.isGiftCardFrozen(card),\n voided: Number(card.voidedAtMs) > 0,\n last4: code.slice(-4),\n })\n}\n\n/**\n * A gift card: takes the smaller of what the card can give and what is left\n * to pay, in ONE transaction with the sale. The card's spendable balance\n * honours every live hold an online checkout placed on it (AGL-2449), and a\n * frozen card gives nothing (AGL-3363), so the till and the website can\n * never spend the same dollars.\n */\nasync function takeGiftCard(\n staff: PosStaff,\n orderId: string,\n paymentId: string,\n body: Record<string, any>,\n): Promise<PosPaymentOutcome> {\n const code = CommerceModel.giftCardCodeOf(body['code'])\n if (CommerceModel.giftCardCodeProblem(code)) {\n return { ok: false, status: 404, error: 'No gift card has that code.' }\n }\n const askedCents = Math.round(Number(body['amountCents'] ?? 0))\n const cardRef = giftCardRef(staff.hostId, code)\n return await applyPosPayment({\n hostId: staff.hostId,\n orderId,\n paymentId,\n prepare: async (transaction) => {\n const snapshot = await transaction.get(cardRef)\n return snapshot.exists ? (snapshot.data() as CommerceModel.HostGiftCard) : null\n },\n decide: ({ order, payments, existing, context: card }) => {\n if (existing) return { kind: 'keep' }\n if (order.status !== 'pending') return NOT_OPEN\n if (!card) return { kind: 'refuse', status: 404, error: 'No gift card has that code.' }\n const available = CommerceModel.giftCardAvailableCents(card, Date.now())\n if (available <= 0) {\n return {\n kind: 'refuse',\n status: 409,\n error: CommerceModel.isGiftCardFrozen(card)\n ? 'This gift card is on hold and cannot be used right now.'\n : 'This gift card has no balance left.',\n }\n }\n const open = tenderable(order, payments)\n const amountCents = Math.min(available, open, askedCents > 0 ? askedCents : open)\n if (!(amountCents > 0)) {\n return { kind: 'refuse', status: 409, error: 'Nothing is left to pay on this sale.' }\n }\n const now = Date.now()\n return {\n kind: 'put',\n payment: {\n id: paymentId,\n method: 'gift_card',\n amountCents,\n status: 'succeeded',\n atMs: now,\n settledAtMs: now,\n giftCardId: code,\n last4: code.slice(-4),\n takeFeeCents: CommerceModel.posPaymentTakeShareCents({\n method: 'gift_card',\n takeFeeCents: Number(order.posTakeFeeCents ?? 0),\n totalCents: Number(order.totals?.totalCents ?? 0),\n amountCents,\n }),\n feeCents: 0,\n cashierId: staff.uid,\n },\n }\n },\n write: (transaction, card, payment) => {\n transaction.set(\n cardRef,\n {\n balanceCents: Math.max(0, Number(card?.balanceCents ?? 0) - payment.amountCents),\n lastUsedAtMs: Date.now(),\n },\n { merge: true },\n )\n },\n })\n}\n\n/**\n * Staff search for a store-credit account at the register (AGL-3640): a\n * customer's email or code, answered by the plugin that keeps the account.\n * Only staff reach it — `authorizePosStaff` above — so a provider may look\n * accounts up by email here, which it never does for a shopper.\n */\nasync function creditLookup(staff: PosStaff, body: Record<string, any>, res: any) {\n const entry = checkoutCreditProvider(String(body['providerId'] ?? ''))\n if (!entry?.provider.lookup) return res.status(404).json({ error: 'That kind of credit is not taken here.' })\n const rate = await consumeRateLimit(`pos-credit-lookup:${staff.uid}`, {\n limit: 60,\n windowMs: 60_000,\n })\n if (!rate.allowed) return res.status(429).json({ error: 'Too many lookups. Wait a moment.' })\n if (!(await entry.provider.offered({ hostId: staff.hostId, channel: 'pos' }).catch(() => false))) {\n return res.status(404).json({ error: 'That kind of credit is not taken here.' })\n }\n const found = await entry.provider\n .lookup({ hostId: staff.hostId, query: String(body['query'] ?? '').slice(0, 120) })\n .catch((error: unknown) => {\n console.error('[pos-payment] credit lookup failed', entry.providerId, error)\n return []\n })\n const accounts = found\n .slice(0, 10)\n .map((account) => normalizeCheckoutCreditAccount(account))\n .filter((account) => !('error' in account))\n return res.status(200).json({ providerId: entry.providerId, accounts })\n}\n\n/**\n * Store credit another plugin keeps (AGL-3640) — a rewards balance, a friend's\n * referral credit — by the customer's code, or by the account a staff lookup\n * found. The provider's stage reads the account INSIDE the sale's transaction\n * and its debit writes there, so the credit is taken with the payment or not\n * at all; a retried press finds its own payment and takes nothing more.\n */\nasync function takeCredit(\n staff: PosStaff,\n orderId: string,\n paymentId: string,\n body: Record<string, any>,\n): Promise<PosPaymentOutcome> {\n const code = normalizeCheckoutCreditCode(body['code'])\n const entry = code\n ? checkoutCreditProviderForCode(code)\n : checkoutCreditProvider(String(body['providerId'] ?? ''))\n if (!entry) return { ok: false, status: 404, error: 'That code is not one this store takes.' }\n if (!(await entry.provider.offered({ hostId: staff.hostId, channel: 'pos' }).catch(() => false))) {\n return { ok: false, status: 404, error: 'That kind of credit is not taken here.' }\n }\n const sale = await readPosSale(staff.hostId, orderId)\n if (!sale) return { ok: false, status: 404, error: 'Unknown sale' }\n const account = normalizeCheckoutCreditAccount(\n await entry.provider\n .resolve({\n hostId: staff.hostId,\n ...(code ? { code } : { reference: String(body['reference'] ?? '') }),\n channel: 'pos',\n customerEmail: (sale as { customerEmail?: string | null }).customerEmail ?? null,\n staff: true,\n })\n .catch((error: unknown) => {\n console.error('[pos-payment] credit resolve failed', entry.providerId, error)\n return null\n }),\n )\n if ('error' in account) return { ok: false, status: account.status, error: account.error }\n const askedCents = Math.round(Number(body['amountCents'] ?? 0))\n return await applyPosPayment<CheckoutCreditStage | null>({\n hostId: staff.hostId,\n orderId,\n paymentId,\n prepare: async (transaction) =>\n entry.provider.stage({\n transaction,\n hostId: staff.hostId,\n reference: account.reference,\n orderId,\n nowMs: Date.now(),\n }),\n decide: ({ order, payments, existing, context: stage }) => {\n if (existing) return { kind: 'keep' }\n if (order.status !== 'pending') return NOT_OPEN\n if (!stage) return { kind: 'refuse', status: 404, error: `That ${account.label.toLowerCase()} account no longer exists.` }\n const open = tenderable(order, payments)\n if (open <= 0) return { kind: 'refuse', status: 409, error: 'Nothing is left to pay on this sale.' }\n const amountCents = Math.min(stage.availableCents, open, askedCents > 0 ? askedCents : open)\n if (!(amountCents > 0)) {\n return { kind: 'refuse', status: 409, error: `This ${account.label.toLowerCase()} account has nothing to spend.` }\n }\n const now = Date.now()\n return {\n kind: 'put',\n payment: {\n id: paymentId,\n method: 'credit',\n amountCents,\n status: 'succeeded',\n atMs: now,\n settledAtMs: now,\n creditProviderId: entry.providerId,\n creditReference: account.reference,\n creditLabel: account.label,\n ...(account.last4 ? { last4: account.last4 } : {}),\n takeFeeCents: CommerceModel.posPaymentTakeShareCents({\n method: 'credit',\n takeFeeCents: Number(order.posTakeFeeCents ?? 0),\n totalCents: Number(order.totals?.totalCents ?? 0),\n amountCents,\n }),\n feeCents: 0,\n cashierId: staff.uid,\n },\n }\n },\n write: (_transaction, stage, payment) => {\n // The stage writes through the sale's own transaction. Taking less than\n // the payment records would leave the sale paid by money that did not\n // move, so a short debit aborts the whole commit instead.\n const taken = stage ? stage.debit({ cents: payment.amountCents, key: payment.id, orderId, channel: 'pos' }) : 0\n if (taken !== payment.amountCents) {\n throw new Error(`credit debit ${taken} short of payment ${payment.amountCents}`)\n }\n },\n })\n}\n\nfunction reservationRef(hostId: string, reservationId: string) {\n return firebaseAdmin\n .app()\n .firestore()\n .collection('hosts')\n .doc(hostId)\n .collection('reservations')\n .doc(reservationId)\n}\n\n/** Charged to a checked-in stay's folio, in the same commit as the payment. */\nasync function takeFolio(\n staff: PosStaff,\n orderId: string,\n paymentId: string,\n body: Record<string, any>,\n): Promise<PosPaymentOutcome> {\n const reservationId = String(body['reservationId'] ?? '')\n if (!/^[A-Za-z0-9_-]{1,128}$/.test(reservationId)) {\n return { ok: false, status: 400, error: 'Pick a reservation' }\n }\n const askedCents = Math.round(Number(body['amountCents'] ?? 0))\n const stayRef = reservationRef(staff.hostId, reservationId)\n return await applyPosPayment({\n hostId: staff.hostId,\n orderId,\n paymentId,\n prepare: async (transaction) => (await transaction.get(stayRef)).exists as boolean,\n decide: ({ order, payments, existing, context: stayExists }) => {\n if (existing) return { kind: 'keep' }\n if (order.status !== 'pending') return NOT_OPEN\n if (!stayExists) return { kind: 'refuse', status: 404, error: 'Unknown reservation' }\n const open = tenderable(order, payments)\n const amountCents = Math.min(open, askedCents > 0 ? askedCents : open)\n if (!(amountCents > 0)) {\n return { kind: 'refuse', status: 409, error: 'Nothing is left to pay on this sale.' }\n }\n const now = Date.now()\n return {\n kind: 'put',\n payment: {\n id: paymentId,\n method: 'folio',\n amountCents,\n status: 'succeeded',\n atMs: now,\n settledAtMs: now,\n reservationId,\n folioAtMs: now,\n takeFeeCents: CommerceModel.posPaymentTakeShareCents({\n method: 'folio',\n takeFeeCents: Number(order.posTakeFeeCents ?? 0),\n totalCents: Number(order.totals?.totalCents ?? 0),\n amountCents,\n }),\n feeCents: 0,\n cashierId: staff.uid,\n },\n event: { event: 'folio', detail: `Charged to reservation ${reservationId}` },\n }\n },\n write: (transaction, _stay, payment) => {\n // `update`, never a merge-set: a missing stay must not be minted as a\n // stub holding one folio line (AGL-1760). It exists — read above.\n transaction.update(stayRef, {\n folio: firebaseAdmin.firestore.FieldValue.arrayUnion({\n orderId,\n paymentId: payment.id,\n amountCents: payment.amountCents,\n note: 'Register sale',\n atMs: payment.folioAtMs ?? Date.now(),\n }),\n })\n },\n })\n}\n\n/**\n * Abandons an open sale: everything it took is handed back first — cards\n * refunded in full (tip included, fee and transfer reversed), gift cards\n * re-credited, the room charge taken off the folio, cash marked as returned —\n * and only then is the order cancelled. A refund Stripe refuses stops the void\n * with the sale still open and its payment still recorded, never cancelled\n * over money that did not come back.\n */\nexport async function voidPosSale(\n staff: PosStaff,\n orderId: string,\n): Promise<PosPaymentOutcome> {\n const hostId = staff.hostId\n const order = await readPosSale(hostId, orderId)\n if (!order) return { ok: false, status: 404, error: 'Unknown sale' }\n if (order.status === 'cancelled') return { ok: true, order, payment: null, completed: false, changed: false }\n if (order.status !== 'pending' || !Array.isArray(order.payments)) {\n return {\n ok: false,\n status: 409,\n error: 'This sale is already paid. Refund it from the order instead.',\n }\n }\n for (const payment of CommerceModel.orderPayments(order)) {\n if (payment.status === 'pending' && CommerceModel.isCardPaymentMethod(payment.method)) {\n const cancelled = await cancelPosCardPayment({ hostId, orderId, paymentId: payment.id })\n if (!cancelled.ok) return cancelled\n }\n }\n // Re-read after the cancels: one may have completed the sale in the gap.\n const current = await readPosSale(hostId, orderId)\n if (!current) return { ok: false, status: 404, error: 'Unknown sale' }\n if (current.status !== 'pending') {\n return {\n ok: false,\n status: 409,\n error: 'The last card payment went through and the sale is paid. Refund it from the order instead.',\n }\n }\n for (const payment of CommerceModel.orderPayments(current)) {\n if (payment.status !== 'succeeded') continue\n const reversed = await reversePayment(staff, current, payment)\n if (!reversed.ok) return reversed\n }\n const firestore = firebaseAdmin.app().firestore()\n const orderRef = firestore.collection('hosts').doc(hostId).collection('orders').doc(orderId)\n const cancelled = await firestore.runTransaction(async (transaction: any) => {\n const fresh = {\n ...(CommerceModel.liftLegacyOrder(((await transaction.get(orderRef)).data() ?? {}) as any) as any),\n $id: orderId,\n } as PosLiftedOrder\n if (fresh.status !== 'pending') return null\n const open = CommerceModel.orderPayments(fresh).some(\n (payment) => payment.status === 'pending' || payment.status === 'succeeded',\n )\n if (open) return null\n const next = {\n ...fresh,\n status: 'cancelled' as const,\n timeline: CommerceModel.appendOrderEvent(fresh, 'pos-sale-voided', 'Voided at the register'),\n }\n transaction.set(\n orderRef,\n {\n status: 'cancelled',\n cancelledAtMs: Date.now(),\n timeline: next.timeline,\n ...CommerceModel.orderListFields(next, orderId),\n },\n { merge: true },\n )\n return next\n })\n if (!cancelled) {\n return { ok: false, status: 409, error: 'A payment on this sale changed. Check it and try again.' }\n }\n await releasePosSaleDiscount(hostId, current)\n return { ok: true, order: cancelled, payment: null, completed: false, changed: true }\n}\n\n/** Hands one settled payment back, recording `reversed` in the same commit. */\nasync function reversePayment(\n staff: PosStaff,\n order: PosLiftedOrder,\n payment: CommerceModel.OrderPayment,\n): Promise<PosPaymentOutcome> {\n const hostId = staff.hostId\n if (CommerceModel.isCardPaymentMethod(payment.method)) {\n if (!payment.paymentIntentId) {\n return { ok: false, status: 409, error: 'A card payment on this sale has no charge to refund.' }\n }\n const refund = await posStripe('POST', 'refunds', {\n idempotencyKey: `pos-void:${payment.id}`,\n params: {\n payment_intent: payment.paymentIntentId,\n reverse_transfer: true,\n refund_application_fee: true,\n 'metadata[kind]': 'pos-void',\n 'metadata[orderId]': order.$id,\n },\n })\n if (!refund.ok) {\n return {\n ok: false,\n status: 502,\n error: posStripeErrorMessage(refund.body, 'The card refund failed. The sale is still open.'),\n }\n }\n }\n const cardRef = payment.giftCardId ? giftCardRef(hostId, payment.giftCardId) : null\n const stayRef = payment.reservationId ? reservationRef(hostId, payment.reservationId) : null\n // Store credit goes back to the plugin that keeps it (AGL-3640), in the\n // same commit as the reversal. A provider that is gone cannot take it\n // back, so the void stops with the sale still open rather than cancelling\n // over credit that did not come back.\n const creditEntry =\n payment.method === 'credit' && payment.creditProviderId ? checkoutCreditProvider(payment.creditProviderId) : null\n if (payment.method === 'credit' && (!creditEntry || !payment.creditReference)) {\n return {\n ok: false,\n status: 409,\n error: 'The store credit on this sale cannot be handed back right now. The sale is still open.',\n }\n }\n return await applyPosPayment({\n hostId,\n orderId: order.$id,\n paymentId: payment.id,\n prepare: async (transaction) => {\n if (payment.method === 'gift_card' && cardRef) {\n const snapshot = await transaction.get(cardRef)\n return { card: snapshot.exists ? (snapshot.data() as CommerceModel.HostGiftCard) : null, folio: null, credit: null }\n }\n if (payment.method === 'folio' && stayRef) {\n const snapshot = await transaction.get(stayRef)\n return { card: null, folio: snapshot.exists ? ((snapshot.get('folio') ?? []) as any[]) : null, credit: null }\n }\n if (payment.method === 'credit' && creditEntry && payment.creditReference) {\n const credit = await creditEntry.provider.stage({\n transaction,\n hostId,\n reference: payment.creditReference,\n orderId: order.$id,\n nowMs: Date.now(),\n })\n return { card: null, folio: null, credit }\n }\n return { card: null, folio: null, credit: null }\n },\n decide: ({ existing }) => {\n if (!existing) return { kind: 'refuse', status: 404, error: 'Unknown payment' }\n if (existing.status !== 'succeeded') return { kind: 'keep' }\n return {\n kind: 'put',\n payment: { ...existing, status: 'reversed' },\n event: {\n event: 'pos-payment-reversed',\n detail:\n existing.method === 'cash'\n ? `${CommerceModel.describeOrderPayment(existing)} handed back in cash`\n : `${CommerceModel.describeOrderPayment(existing)} returned`,\n },\n }\n },\n write: (transaction, context, reversed) => {\n if (reversed.method === 'gift_card' && cardRef && context.card) {\n transaction.set(\n cardRef,\n { balanceCents: Number(context.card.balanceCents ?? 0) + reversed.amountCents },\n { merge: true },\n )\n }\n if (reversed.method === 'folio' && stayRef && context.folio) {\n transaction.update(stayRef, {\n folio: context.folio.filter((entry) => entry?.paymentId !== reversed.id),\n })\n }\n if (reversed.method === 'credit' && context.credit) {\n context.credit.reverse({ key: reversed.id, orderId: order.$id })\n }\n },\n })\n}\n\n/** A repeat of the same receipt choice inside this window sends nothing more. */\nconst RECEIPT_REPEAT_WINDOW_MS = 2 * 60 * 1000\n\n/**\n * How the customer wants their receipt, from the cashier or the customer\n * display. Kept on the order; an email chosen after the sale is paid is sent\n * at once, and one chosen before is sent when it completes.\n */\nexport async function recordReceiptChoice(\n staff: PosStaff,\n orderId: string,\n body: Record<string, any>,\n): Promise<PosPaymentOutcome> {\n const channel = String(body['channel'] ?? '') as CommerceModel.PosReceiptChannel\n if (!['email', 'sms', 'print', 'none'].includes(channel)) {\n return { ok: false, status: 400, error: 'Choose email, text, print or no receipt.' }\n }\n const to =\n channel === 'email'\n ? CommerceModel.posDisplayEmail(body['to'])\n : channel === 'sms'\n ? CommerceModel.posDisplayPhone(body['to'])\n : ''\n if ((channel === 'email' || channel === 'sms') && !to) {\n return {\n ok: false,\n status: 400,\n error: channel === 'email' ? 'Enter a valid email address.' : 'Enter a valid phone number.',\n }\n }\n if (channel === 'sms' && !pluginSmsAvailable()) {\n return { ok: false, status: 409, error: 'Text receipts are not set up for this store.' }\n }\n const marketingOptIn = channel === 'email' && body['marketingOptIn'] === true\n const firestore = firebaseAdmin.app().firestore()\n const orderRef = firestore.collection('hosts').doc(staff.hostId).collection('orders').doc(orderId)\n const order = await firestore.runTransaction(async (transaction: any) => {\n const snapshot = await transaction.get(orderRef)\n if (!snapshot.exists) return null\n const fresh = {\n ...(CommerceModel.liftLegacyOrder((snapshot.data() ?? {}) as any) as any),\n $id: orderId,\n } as PosLiftedOrder\n if (fresh.channel !== 'pos') return null\n // The same choice twice in a row (a double tap, or the display and the\n // cashier answering together) is one receipt, not two.\n const previous = fresh.receiptRequest\n if (\n fresh.status === 'paid' &&\n previous &&\n previous.channel === channel &&\n String(previous.to ?? '') === to &&\n Date.now() - Number(previous.atMs ?? 0) < RECEIPT_REPEAT_WINDOW_MS\n ) {\n return { ...fresh, repeated: true } as PosLiftedOrder & { repeated?: boolean }\n }\n const receiptRequest = {\n channel,\n ...(to ? { to } : {}),\n ...(marketingOptIn ? { marketingOptIn: true } : {}),\n atMs: Date.now(),\n }\n transaction.set(\n orderRef,\n {\n receiptRequest,\n ...(channel === 'email' && !fresh.customerEmail\n ? {\n customerEmail: to,\n ...CommerceModel.orderListFields({ ...fresh, customerEmail: to }, orderId),\n }\n : {}),\n // The receipt door texts `customerPhone` (AGL-3610).\n ...(channel === 'sms' ? { customerPhone: to } : {}),\n },\n { merge: true },\n )\n return { ...fresh, receiptRequest } as PosLiftedOrder & { repeated?: boolean }\n })\n if (!order) return { ok: false, status: 404, error: 'Unknown sale' }\n if (order.repeated) return { ok: true, order, payment: null, completed: false, changed: false }\n if (order.status === 'paid' && channel === 'print') {\n // Chosen after the sale completed: printed now on the register's receipt\n // printer, under the sale's own key so it never prints twice (AGL-3609).\n await printPosSaleReceipt(staff.hostId, orderId)\n }\n // A kiosk's own receipt screen (AGL-3623) is not the register's display:\n // the display may be asking the cashier's customer right now.\n if (order.status === 'paid' && order.registerId && order.posSource !== 'kiosk') {\n // The customer has answered (or the cashier for them): the display says\n // thank you and drops the address they typed (AGL-3608).\n await finishPosDisplayReceipt(staff.hostId, order.registerId).catch((error: unknown) =>\n console.error('[pos-payment] display finish failed', error),\n )\n }\n if (order.status === 'paid' && (channel === 'email' || channel === 'sms')) {\n // Chosen after the sale completed: sent now, to where they said.\n const sent = await deliverChosenPosReceipt(\n { hostId: staff.hostId, orderId },\n { channel, to, orderEmail: String(order.customerEmail ?? '') },\n )\n if (channel === 'email') {\n await recordCapturedContact({\n orgId: '',\n hostId: staff.hostId,\n identity: { email: to },\n surface: 'relationship',\n lifecycleFloor: 'customer',\n ...(marketingOptIn ? { marketingConsent: true } : {}),\n interaction: {\n source: 'order',\n refId: orderId,\n summary: `In-store purchase (${CommerceModel.formatReceiptMoney(\n Number(order.totals?.totalCents ?? 0),\n POS_CURRENCY,\n )})`,\n },\n }).catch((error: unknown) => console.error('[pos-payment] contact capture failed', error))\n }\n if (sent !== 'sent') {\n // A failed send is not a repeat: the cashier's retry goes out.\n await orderRef\n .set({ receiptRequest: { atMs: 0 } }, { merge: true })\n .catch((error: unknown) => console.error('[pos-payment] receipt retry reset failed', error))\n }\n if (sent === 'not_configured') {\n return {\n ok: false,\n status: 409,\n error: channel === 'sms' ? 'Text receipts are not set up for this store.' : 'Email is not set up.',\n }\n }\n if (sent !== 'sent') return { ok: false, status: 502, error: 'The receipt could not be sent.' }\n }\n return { ok: true, order, payment: null, completed: false, changed: true }\n}\n"],"names":["consumeRateLimit","firebaseAdmin","getPluginConfig","buildRoute","Route","recordCapturedContact","pluginSmsAvailable","checkoutCreditProvider","checkoutCreditProviderForCode","normalizeCheckoutCreditAccount","normalizeCheckoutCreditCode","offeredCheckoutCredits","finishPosDisplayReceipt","CommerceModel","posRegisterSettings","posOpsSettings","authorizePosStaff","posIdempotencyKey","posQueryBody","posRequestBody","applyPosPayment","deliverChosenPosReceipt","posPaymentId","posSaleSummary","readPosSale","releasePosSaleDiscount","posPaymentCashierId","printPosSaleReceipt","POS_CURRENCY","posStripe","posStripeErrorMessage","posStripeTestMode","posTerminalAvailable","cancelPosCardPayment","createCardPresentIntent","refreshPosCardPayment","retryCardPresentPayment","simulatePosReaderTap","startCardKeyedPayment","startCardLinkPayment","startCardPresentPayment","posPaymentHandler","req","res","body","method","status","json","error","hostId","String","gate","staff","action","orderId","process","giftCardBalance","creditLookup","readers","app","firestore","collection","doc","limit","get","docs","map","id","label","registerId","livemode","Boolean","config","orgId","undefined","settings","ops","terminal","available","testMode","publishableKey","env","NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY","smsReceipts","credits","channel","startsPayment","includes","attemptKey","paymentId","uid","signedInUid","assertion","amountCents","Math","round","Number","tipCents","outcome","order","ok","payment","completed","changed","takeCash","takeGiftCard","takeCredit","takeFolio","cashierId","org","readerId","paymentMethodId","returnUrl","registerReturnUrl","headers","host","cardNumber","voidPosSale","recordReceiptChoice","sale","clientSecret","paymentIntentId","console","requestHost","origin","subdomain","orgSlug","HOST_PLUGIN","pluginSlug","tenderable","payments","posTenderableCents","totals","totalCents","NOT_OPEN","kind","tenderedCents","askedCents","decide","existing","isFinite","open","min","max","tipProblem","posTipProblem","total","now","Date","atMs","settledAtMs","cashTenderedCents","changeCents","takeFeeCents","posPaymentTakeShareCents","posTakeFeeCents","feeCents","giftCardRef","code","giftCardCodeOf","rate","windowMs","allowed","giftCardCodeProblem","snapshot","exists","card","data","availableCents","giftCardAvailableCents","frozen","isGiftCardFrozen","voided","voidedAtMs","last4","slice","cardRef","prepare","transaction","context","giftCardId","write","set","balanceCents","lastUsedAtMs","merge","entry","provider","lookup","offered","catch","found","query","providerId","accounts","account","filter","resolve","reference","customerEmail","stage","nowMs","toLowerCase","creditProviderId","creditReference","creditLabel","_transaction","taken","debit","cents","key","Error","reservationRef","reservationId","test","stayRef","stayExists","folioAtMs","event","detail","_stay","update","folio","FieldValue","arrayUnion","note","Array","isArray","orderPayments","isCardPaymentMethod","cancelled","current","reversed","reversePayment","orderRef","runTransaction","fresh","liftLegacyOrder","$id","some","next","timeline","appendOrderEvent","cancelledAtMs","orderListFields","refund","idempotencyKey","params","payment_intent","reverse_transfer","refund_application_fee","creditEntry","credit","describeOrderPayment","reverse","RECEIPT_REPEAT_WINDOW_MS","to","posDisplayEmail","posDisplayPhone","marketingOptIn","previous","receiptRequest","repeated","customerPhone","posSource","sent","orderEmail","identity","email","surface","lifecycleFloor","marketingConsent","interaction","source","refId","summary","formatReceiptMoney"],"mappings":"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"}
@@ -20,7 +20,7 @@ import { emailUnverifiedResponse, firebaseAdmin, isImpersonationSession } from "
20
20
  import { addAdminAudit } from "@aglyn/tenant-data-admin/server/admin-audit-write";
21
21
  import { invalidIdTokenResponse } from "@aglyn/tenant-data-admin/server/id-token-refusal";
22
22
  import { POS_READER_SPLASH_FAMILIES, POS_READER_SPLASH_MAX_BYTES, posReaderSplashFamily, posReaderSplashImageProblem } from "../model/pos-reader-splash.js";
23
- import { applyPosReaderSplash, ownerOrgOf, platformSplashReady, platformSplashRef, posReaderSplashBucket, readPlatformSplash } from "./pos-reader-splash.js";
23
+ import { applyPosReaderSplashToStores, platformSplashReady, platformSplashRef, posReaderSplashBucket, readPlatformSplash } from "./pos-reader-splash.js";
24
24
  import { posReaderSplashImageFacts } from "./pos-reader-splash-render.js";
25
25
  /*==========================================
26
26
  * `/api/commerce/admin/reader-splash` (AGL-4048): the platform's default
@@ -46,8 +46,6 @@ import { posReaderSplashImageFacts } from "./pos-reader-splash-render.js";
46
46
  *=========================================*/ const WRITE_ROLES = [
47
47
  'super'
48
48
  ];
49
- /** How many stores one `apply` reaches; staff press it again for the rest. */ const APPLY_WINDOW = 400;
50
- const APPLY_CONCURRENCY = 4;
51
49
  const json = (body, status = 200)=>Response.json(body, {
52
50
  status,
53
51
  headers: {
@@ -77,6 +75,27 @@ function view(doc) {
77
75
  updatedAtMs: (_doc_updatedAtMs = doc.updatedAtMs) != null ? _doc_updatedAtMs : null
78
76
  };
79
77
  }
78
+ /**
79
+ * An uploaded screen's format and size, read here where this process can
80
+ * draw, else by the images function (AGL-4048), which ships `sharp`.
81
+ */ async function uploadedImageFacts(body) {
82
+ const images = await import("./pos-reader-splash-images.js");
83
+ const origin = images.posReaderSplashImagesOrigin();
84
+ if (!origin) {
85
+ const { loadSharp } = await import("./pos-reader-splash-server.js");
86
+ return posReaderSplashImageFacts(await loadSharp(), body);
87
+ }
88
+ try {
89
+ const answer = await images.requestPosReaderSplashImages(origin, {
90
+ op: 'facts',
91
+ dataBase64: body.toString('base64')
92
+ });
93
+ return answer.facts;
94
+ } catch (error) {
95
+ if (error instanceof images.PosReaderSplashImagesRefusal) return null;
96
+ throw error;
97
+ }
98
+ }
80
99
  async function upload(doc, input, uid) {
81
100
  var _input_dataBase64;
82
101
  var _doc_families;
@@ -94,8 +113,7 @@ async function upload(doc, input, uid) {
94
113
  };
95
114
  }
96
115
  const body = Buffer.from(raw, 'base64');
97
- const { loadSharp } = await import("./pos-reader-splash-server.js");
98
- const facts = await posReaderSplashImageFacts(await loadSharp(), body);
116
+ const facts = await uploadedImageFacts(body);
99
117
  if (!facts) return {
100
118
  error: 'That image could not be read.',
101
119
  status: 400
@@ -131,33 +149,13 @@ async function upload(doc, input, uid) {
131
149
  }
132
150
  };
133
151
  }
134
- /** Every store with a Location, its screen brought up to the current default. */ async function applyToEveryStore() {
135
- const firestore = firebaseAdmin.app().firestore();
136
- const platform = await readPlatformSplash();
137
- const snapshot = await firestore.collectionGroup('terminal').limit(APPLY_WINDOW + 1).get();
138
- const hostIds = snapshot.docs.filter((doc)=>doc.id === 'config' && doc.get('stripeLocationId')).map((doc)=>doc.ref.path.split('/')[1]).filter(Boolean);
139
- const counts = {
140
- applied: 0,
141
- unchanged: 0,
142
- failed: 0
143
- };
144
- const queue = hostIds.slice(0, APPLY_WINDOW);
145
- await Promise.all(Array.from({
146
- length: APPLY_CONCURRENCY
147
- }, async ()=>{
148
- for(let hostId = queue.shift(); hostId; hostId = queue.shift()){
149
- const org = await ownerOrgOf(hostId);
150
- const result = await applyPosReaderSplash(hostId, {
151
- org,
152
- platform
153
- });
154
- if (result.outcome === 'applied' || result.outcome === 'cleared') counts.applied += 1;
155
- else if (result.outcome === 'failed') counts.failed += 1;
156
- else counts.unchanged += 1;
157
- }
158
- }));
159
- return _extends({}, counts, {
160
- more: snapshot.docs.length > APPLY_WINDOW
152
+ /**
153
+ * Every store with a Location, its screen brought up to the current default.
154
+ * One `apply` reaches `POS_READER_SPLASH_SWEEP_WINDOW` stores; staff
155
+ * press it again for the rest.
156
+ */ async function applyToEveryStore() {
157
+ return applyPosReaderSplashToStores({
158
+ platform: await readPlatformSplash()
161
159
  });
162
160
  }
163
161
  async function handler(request) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/pos-reader-splash-admin.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 { createHash } from 'node:crypto'\nimport { pluginRequestFromWeb } from '@aglyn/aglyn/server'\nimport { emailUnverifiedResponse, firebaseAdmin, isImpersonationSession } from '@aglyn/tenant-data-admin'\nimport { addAdminAudit } from '@aglyn/tenant-data-admin/server/admin-audit-write'\nimport { invalidIdTokenResponse } from '@aglyn/tenant-data-admin/server/id-token-refusal'\nimport {\n POS_READER_SPLASH_FAMILIES,\n POS_READER_SPLASH_MAX_BYTES,\n posReaderSplashFamily,\n posReaderSplashImageProblem,\n} from '../model/pos-reader-splash'\nimport {\n applyPosReaderSplash,\n ownerOrgOf,\n platformSplashReady,\n platformSplashRef,\n posReaderSplashBucket,\n readPlatformSplash,\n type PlatformSplashDoc,\n type PlatformSplashImage,\n} from './pos-reader-splash'\nimport { posReaderSplashImageFacts } from './pos-reader-splash-render'\n\n/*==========================================\n * `/api/commerce/admin/reader-splash` (AGL-4048): the platform's default\n * card reader start-up screen, for Staff → Reader start-up screen.\n *\n * GET each family's screen, as metadata\n * GET ?preview={family} that family's image itself\n * POST upload { family, contentType, dataBase64 }\n * POST remove { family }\n * POST apply put the current default on every store that\n * uses it (the page calls it after a change)\n *\n * The artwork is designed separately and uploaded here; none is kept in\n * the repository. Each image is checked against Stripe's rules for its\n * family before it is stored: PNG or JPEG, under 2 MB, exactly the reader's\n * screen. The S700/S710 screen is the one that turns the default on; the\n * WisePOS E screen is drawn from it when staff upload none.\n *\n * Staff only. Reading is open to every staff role; every write is `super`,\n * because it changes what every non-white-label store's readers show. Every\n * write is an `adminAudit` row. The images live in storage under\n * `platform/commerce/pos-reader-splash/`, which no client rule opens.\n *=========================================*/\n\nconst WRITE_ROLES = ['super']\n\n/** How many stores one `apply` reaches; staff press it again for the rest. */\nconst APPLY_WINDOW = 400\nconst APPLY_CONCURRENCY = 4\n\nconst json = (body: unknown, status = 200) =>\n Response.json(body, { status, headers: { 'Cache-Control': 'no-store' } })\n\nfunction view(doc: PlatformSplashDoc) {\n return {\n ready: platformSplashReady(doc),\n families: POS_READER_SPLASH_FAMILIES.map((family) => {\n const image = doc.families?.[family.id]\n return {\n id: family.id,\n label: family.label,\n width: family.width,\n height: family.height,\n image: image\n ? {\n contentType: image.contentType,\n bytes: image.bytes,\n sha256: image.sha256,\n uploadedAtMs: image.uploadedAtMs,\n }\n : null,\n }\n }),\n updatedAtMs: doc.updatedAtMs ?? null,\n }\n}\n\nexport type StaffReaderSplashView = ReturnType<typeof view>\n\nasync function upload(\n doc: PlatformSplashDoc,\n input: Record<string, unknown>,\n uid: string,\n): Promise<{ error: string; status: number } | { image: PlatformSplashImage; familyId: string }> {\n const family = posReaderSplashFamily(input['family'])\n if (!family) return { error: 'Unknown reader family', status: 400 }\n const raw = String(input['dataBase64'] ?? '')\n // A base64 body is 4/3 of the file; anything longer cannot be under 2 MB.\n if (!raw || raw.length > Math.ceil((POS_READER_SPLASH_MAX_BYTES * 4) / 3) + 4) {\n return { error: 'Use an image under 2 MB.', status: 400 }\n }\n const body = Buffer.from(raw, 'base64')\n const { loadSharp } = await import('./pos-reader-splash-server')\n const facts = await posReaderSplashImageFacts((await loadSharp()) as any, body)\n if (!facts) return { error: 'That image could not be read.', status: 400 }\n // The bytes decide the type, never the name or the browser's claim.\n const problem = posReaderSplashImageProblem({ ...facts, bytes: body.length }, family)\n if (problem) return { error: problem, status: 400 }\n const sha256 = createHash('sha256').update(body).digest('hex')\n const extension = facts.contentType === 'image/png' ? 'png' : 'jpg'\n const storagePath = `platform/commerce/pos-reader-splash/${family.id}-${sha256.slice(0, 16)}.${extension}`\n await posReaderSplashBucket()\n .file(storagePath)\n .save(body, { contentType: facts.contentType, resumable: false })\n const previous = doc.families?.[family.id]\n if (previous?.storagePath && previous.storagePath !== storagePath) {\n await posReaderSplashBucket().file(previous.storagePath).delete().catch(() => undefined)\n }\n return {\n familyId: family.id,\n image: {\n storagePath,\n sha256,\n contentType: facts.contentType as PlatformSplashImage['contentType'],\n bytes: body.length,\n uploadedAtMs: Date.now(),\n uploadedBy: uid,\n },\n }\n}\n\n/** Every store with a Location, its screen brought up to the current default. */\nasync function applyToEveryStore() {\n const firestore = firebaseAdmin.app().firestore()\n const platform = await readPlatformSplash()\n const snapshot = await firestore.collectionGroup('terminal').limit(APPLY_WINDOW + 1).get()\n const hostIds = (snapshot.docs as Array<{ id: string; ref: { path: string }; get: (field: string) => unknown }>)\n .filter((doc) => doc.id === 'config' && doc.get('stripeLocationId'))\n .map((doc) => doc.ref.path.split('/')[1])\n .filter(Boolean)\n const counts = { applied: 0, unchanged: 0, failed: 0 }\n const queue = hostIds.slice(0, APPLY_WINDOW)\n await Promise.all(\n Array.from({ length: APPLY_CONCURRENCY }, async () => {\n for (let hostId = queue.shift(); hostId; hostId = queue.shift()) {\n const org = await ownerOrgOf(hostId)\n const result = await applyPosReaderSplash(hostId, { org, platform })\n if (result.outcome === 'applied' || result.outcome === 'cleared') counts.applied += 1\n else if (result.outcome === 'failed') counts.failed += 1\n else counts.unchanged += 1\n }\n }),\n )\n return { ...counts, more: snapshot.docs.length > APPLY_WINDOW }\n}\n\nasync function handler(request: Request): Promise<Response> {\n const { method, query, body, headers: rawHeaders } = await pluginRequestFromWeb(request)\n const headers = rawHeaders as Partial<Record<string, string>>\n const authorization = headers.authorization ?? ''\n const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : undefined\n if (!idToken) return json({ error: 'Unauthenticated' }, 401)\n\n try {\n const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n if (!decoded.email_verified && !isImpersonationSession(decoded)) return emailUnverifiedResponse()\n if (!decoded['staff']) return json({ error: 'Staff only' }, 403)\n // A missing role claim reads as the least one, never as super.\n const role = String(decoded['staffRole'] ?? 'support')\n const firestore = firebaseAdmin.app().firestore()\n const doc = await readPlatformSplash()\n\n if (method === 'GET') {\n const preview = String(query?.['preview'] ?? '')\n if (preview) {\n const family = posReaderSplashFamily(preview)\n const image = family ? doc.families?.[family.id] : undefined\n if (!image) return json({ error: 'No image' }, 404)\n const [bytes] = (await posReaderSplashBucket().file(image.storagePath).download()) as [Buffer]\n return new Response(new Uint8Array(bytes), {\n status: 200,\n headers: { 'Content-Type': image.contentType, 'Cache-Control': 'no-store' },\n })\n }\n return json({ ...view(doc), canWrite: WRITE_ROLES.includes(role) })\n }\n\n if (method !== 'POST') return json({ error: 'Method not allowed' }, 405)\n if (!WRITE_ROLES.includes(role)) {\n return json({ error: 'Changing the reader start-up screen requires the super staff role.' }, 403)\n }\n const input = (body ?? {}) as Record<string, unknown>\n const action = String(input['action'] ?? '')\n const actor = { actorUid: decoded.uid, actorEmail: decoded.email ? String(decoded.email) : null }\n\n if (action === 'apply') return json({ ok: true, ...(await applyToEveryStore()) })\n\n if (action === 'upload' || action === 'remove') {\n let next: PlatformSplashDoc\n let familyId: string\n if (action === 'upload') {\n const outcome = await upload(doc, input, decoded.uid)\n if ('error' in outcome) return json({ error: outcome.error }, outcome.status)\n familyId = outcome.familyId\n next = { families: { ...(doc.families ?? {}), [familyId]: outcome.image }, updatedAtMs: Date.now() }\n } else {\n const family = posReaderSplashFamily(input['family'])\n if (!family) return json({ error: 'Unknown reader family' }, 400)\n familyId = family.id\n const families = { ...(doc.families ?? {}) }\n const previous = families[family.id]\n delete families[family.id]\n if (previous?.storagePath) {\n await posReaderSplashBucket().file(previous.storagePath).delete().catch(() => undefined)\n }\n next = { families, updatedAtMs: Date.now() }\n }\n await platformSplashRef().set(next)\n await addAdminAudit(firestore, {\n action: `pos-reader-splash-${action}`,\n ...actor,\n scope: 'posReaderSplash',\n target: `platformSettings/posReaderSplash`,\n before: { family: familyId, sha256: doc.families?.[familyId as keyof typeof doc.families]?.sha256 ?? null },\n after: { family: familyId, sha256: next.families?.[familyId as keyof typeof next.families]?.sha256 ?? null },\n at: firebaseAdmin.firestore.FieldValue.serverTimestamp(),\n })\n return json({ ok: true, ...view(next), canWrite: true })\n }\n return json({ error: 'Unknown action' }, 400)\n } catch (error) {\n const unauthenticated = invalidIdTokenResponse(error)\n if (unauthenticated) return unauthenticated\n console.error('[pos-reader-splash-admin]', error)\n return json({ error: 'The reader start-up screen could not be updated' }, 500)\n }\n}\n\nexport { handler as posReaderSplashAdmin }\n"],"names":["createHash","pluginRequestFromWeb","emailUnverifiedResponse","firebaseAdmin","isImpersonationSession","addAdminAudit","invalidIdTokenResponse","POS_READER_SPLASH_FAMILIES","POS_READER_SPLASH_MAX_BYTES","posReaderSplashFamily","posReaderSplashImageProblem","applyPosReaderSplash","ownerOrgOf","platformSplashReady","platformSplashRef","posReaderSplashBucket","readPlatformSplash","posReaderSplashImageFacts","WRITE_ROLES","APPLY_WINDOW","APPLY_CONCURRENCY","json","body","status","Response","headers","view","doc","ready","families","map","family","image","id","label","width","height","contentType","bytes","sha256","uploadedAtMs","updatedAtMs","upload","input","uid","error","raw","String","length","Math","ceil","Buffer","from","loadSharp","facts","problem","update","digest","extension","storagePath","slice","file","save","resumable","previous","delete","catch","undefined","familyId","Date","now","uploadedBy","applyToEveryStore","firestore","app","platform","snapshot","collectionGroup","limit","get","hostIds","docs","filter","ref","path","split","Boolean","counts","applied","unchanged","failed","queue","Promise","all","Array","hostId","shift","org","result","outcome","more","handler","request","method","query","rawHeaders","authorization","idToken","startsWith","decoded","auth","verifyIdToken","email_verified","role","preview","download","Uint8Array","canWrite","includes","action","actor","actorUid","actorEmail","email","ok","next","set","scope","target","before","after","at","FieldValue","serverTimestamp","unauthenticated","console","posReaderSplashAdmin"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/pos-reader-splash-admin.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 { createHash } from 'node:crypto'\nimport { pluginRequestFromWeb } from '@aglyn/aglyn/server'\nimport { emailUnverifiedResponse, firebaseAdmin, isImpersonationSession } from '@aglyn/tenant-data-admin'\nimport { addAdminAudit } from '@aglyn/tenant-data-admin/server/admin-audit-write'\nimport { invalidIdTokenResponse } from '@aglyn/tenant-data-admin/server/id-token-refusal'\nimport {\n POS_READER_SPLASH_FAMILIES,\n POS_READER_SPLASH_MAX_BYTES,\n posReaderSplashFamily,\n posReaderSplashImageProblem,\n} from '../model/pos-reader-splash'\nimport {\n applyPosReaderSplashToStores,\n platformSplashReady,\n platformSplashRef,\n posReaderSplashBucket,\n readPlatformSplash,\n type PlatformSplashDoc,\n type PlatformSplashImage,\n} from './pos-reader-splash'\nimport { posReaderSplashImageFacts } from './pos-reader-splash-render'\n\n/*==========================================\n * `/api/commerce/admin/reader-splash` (AGL-4048): the platform's default\n * card reader start-up screen, for Staff → Reader start-up screen.\n *\n * GET each family's screen, as metadata\n * GET ?preview={family} that family's image itself\n * POST upload { family, contentType, dataBase64 }\n * POST remove { family }\n * POST apply put the current default on every store that\n * uses it (the page calls it after a change)\n *\n * The artwork is designed separately and uploaded here; none is kept in\n * the repository. Each image is checked against Stripe's rules for its\n * family before it is stored: PNG or JPEG, under 2 MB, exactly the reader's\n * screen. The S700/S710 screen is the one that turns the default on; the\n * WisePOS E screen is drawn from it when staff upload none.\n *\n * Staff only. Reading is open to every staff role; every write is `super`,\n * because it changes what every non-white-label store's readers show. Every\n * write is an `adminAudit` row. The images live in storage under\n * `platform/commerce/pos-reader-splash/`, which no client rule opens.\n *=========================================*/\n\nconst WRITE_ROLES = ['super']\n\nconst json = (body: unknown, status = 200) =>\n Response.json(body, { status, headers: { 'Cache-Control': 'no-store' } })\n\nfunction view(doc: PlatformSplashDoc) {\n return {\n ready: platformSplashReady(doc),\n families: POS_READER_SPLASH_FAMILIES.map((family) => {\n const image = doc.families?.[family.id]\n return {\n id: family.id,\n label: family.label,\n width: family.width,\n height: family.height,\n image: image\n ? {\n contentType: image.contentType,\n bytes: image.bytes,\n sha256: image.sha256,\n uploadedAtMs: image.uploadedAtMs,\n }\n : null,\n }\n }),\n updatedAtMs: doc.updatedAtMs ?? null,\n }\n}\n\nexport type StaffReaderSplashView = ReturnType<typeof view>\n\n/**\n * An uploaded screen's format and size, read here where this process can\n * draw, else by the images function (AGL-4048), which ships `sharp`.\n */\nasync function uploadedImageFacts(body: Buffer): Promise<{ contentType: string; width: number; height: number } | null> {\n const images = await import('./pos-reader-splash-images')\n const origin = images.posReaderSplashImagesOrigin()\n if (!origin) {\n const { loadSharp } = await import('./pos-reader-splash-server')\n return posReaderSplashImageFacts((await loadSharp()) as any, body)\n }\n try {\n const answer = await images.requestPosReaderSplashImages<{\n facts: { contentType: string; width: number; height: number } | null\n }>(origin, { op: 'facts', dataBase64: body.toString('base64') })\n return answer.facts\n } catch (error) {\n if (error instanceof images.PosReaderSplashImagesRefusal) return null\n throw error\n }\n}\n\nasync function upload(\n doc: PlatformSplashDoc,\n input: Record<string, unknown>,\n uid: string,\n): Promise<{ error: string; status: number } | { image: PlatformSplashImage; familyId: string }> {\n const family = posReaderSplashFamily(input['family'])\n if (!family) return { error: 'Unknown reader family', status: 400 }\n const raw = String(input['dataBase64'] ?? '')\n // A base64 body is 4/3 of the file; anything longer cannot be under 2 MB.\n if (!raw || raw.length > Math.ceil((POS_READER_SPLASH_MAX_BYTES * 4) / 3) + 4) {\n return { error: 'Use an image under 2 MB.', status: 400 }\n }\n const body = Buffer.from(raw, 'base64')\n const facts = await uploadedImageFacts(body)\n if (!facts) return { error: 'That image could not be read.', status: 400 }\n // The bytes decide the type, never the name or the browser's claim.\n const problem = posReaderSplashImageProblem({ ...facts, bytes: body.length }, family)\n if (problem) return { error: problem, status: 400 }\n const sha256 = createHash('sha256').update(body).digest('hex')\n const extension = facts.contentType === 'image/png' ? 'png' : 'jpg'\n const storagePath = `platform/commerce/pos-reader-splash/${family.id}-${sha256.slice(0, 16)}.${extension}`\n await posReaderSplashBucket()\n .file(storagePath)\n .save(body, { contentType: facts.contentType, resumable: false })\n const previous = doc.families?.[family.id]\n if (previous?.storagePath && previous.storagePath !== storagePath) {\n await posReaderSplashBucket().file(previous.storagePath).delete().catch(() => undefined)\n }\n return {\n familyId: family.id,\n image: {\n storagePath,\n sha256,\n contentType: facts.contentType as PlatformSplashImage['contentType'],\n bytes: body.length,\n uploadedAtMs: Date.now(),\n uploadedBy: uid,\n },\n }\n}\n\n/**\n * Every store with a Location, its screen brought up to the current default.\n * One `apply` reaches `POS_READER_SPLASH_SWEEP_WINDOW` stores; staff\n * press it again for the rest.\n */\nasync function applyToEveryStore() {\n return applyPosReaderSplashToStores({ platform: await readPlatformSplash() })\n}\n\nasync function handler(request: Request): Promise<Response> {\n const { method, query, body, headers: rawHeaders } = await pluginRequestFromWeb(request)\n const headers = rawHeaders as Partial<Record<string, string>>\n const authorization = headers.authorization ?? ''\n const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : undefined\n if (!idToken) return json({ error: 'Unauthenticated' }, 401)\n\n try {\n const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n if (!decoded.email_verified && !isImpersonationSession(decoded)) return emailUnverifiedResponse()\n if (!decoded['staff']) return json({ error: 'Staff only' }, 403)\n // A missing role claim reads as the least one, never as super.\n const role = String(decoded['staffRole'] ?? 'support')\n const firestore = firebaseAdmin.app().firestore()\n const doc = await readPlatformSplash()\n\n if (method === 'GET') {\n const preview = String(query?.['preview'] ?? '')\n if (preview) {\n const family = posReaderSplashFamily(preview)\n const image = family ? doc.families?.[family.id] : undefined\n if (!image) return json({ error: 'No image' }, 404)\n const [bytes] = (await posReaderSplashBucket().file(image.storagePath).download()) as [Buffer]\n return new Response(new Uint8Array(bytes), {\n status: 200,\n headers: { 'Content-Type': image.contentType, 'Cache-Control': 'no-store' },\n })\n }\n return json({ ...view(doc), canWrite: WRITE_ROLES.includes(role) })\n }\n\n if (method !== 'POST') return json({ error: 'Method not allowed' }, 405)\n if (!WRITE_ROLES.includes(role)) {\n return json({ error: 'Changing the reader start-up screen requires the super staff role.' }, 403)\n }\n const input = (body ?? {}) as Record<string, unknown>\n const action = String(input['action'] ?? '')\n const actor = { actorUid: decoded.uid, actorEmail: decoded.email ? String(decoded.email) : null }\n\n if (action === 'apply') return json({ ok: true, ...(await applyToEveryStore()) })\n\n if (action === 'upload' || action === 'remove') {\n let next: PlatformSplashDoc\n let familyId: string\n if (action === 'upload') {\n const outcome = await upload(doc, input, decoded.uid)\n if ('error' in outcome) return json({ error: outcome.error }, outcome.status)\n familyId = outcome.familyId\n next = { families: { ...(doc.families ?? {}), [familyId]: outcome.image }, updatedAtMs: Date.now() }\n } else {\n const family = posReaderSplashFamily(input['family'])\n if (!family) return json({ error: 'Unknown reader family' }, 400)\n familyId = family.id\n const families = { ...(doc.families ?? {}) }\n const previous = families[family.id]\n delete families[family.id]\n if (previous?.storagePath) {\n await posReaderSplashBucket().file(previous.storagePath).delete().catch(() => undefined)\n }\n next = { families, updatedAtMs: Date.now() }\n }\n await platformSplashRef().set(next)\n await addAdminAudit(firestore, {\n action: `pos-reader-splash-${action}`,\n ...actor,\n scope: 'posReaderSplash',\n target: `platformSettings/posReaderSplash`,\n before: { family: familyId, sha256: doc.families?.[familyId as keyof typeof doc.families]?.sha256 ?? null },\n after: { family: familyId, sha256: next.families?.[familyId as keyof typeof next.families]?.sha256 ?? null },\n at: firebaseAdmin.firestore.FieldValue.serverTimestamp(),\n })\n return json({ ok: true, ...view(next), canWrite: true })\n }\n return json({ error: 'Unknown action' }, 400)\n } catch (error) {\n const unauthenticated = invalidIdTokenResponse(error)\n if (unauthenticated) return unauthenticated\n console.error('[pos-reader-splash-admin]', error)\n return json({ error: 'The reader start-up screen could not be updated' }, 500)\n }\n}\n\nexport { handler as posReaderSplashAdmin }\n"],"names":["createHash","pluginRequestFromWeb","emailUnverifiedResponse","firebaseAdmin","isImpersonationSession","addAdminAudit","invalidIdTokenResponse","POS_READER_SPLASH_FAMILIES","POS_READER_SPLASH_MAX_BYTES","posReaderSplashFamily","posReaderSplashImageProblem","applyPosReaderSplashToStores","platformSplashReady","platformSplashRef","posReaderSplashBucket","readPlatformSplash","posReaderSplashImageFacts","WRITE_ROLES","json","body","status","Response","headers","view","doc","ready","families","map","family","image","id","label","width","height","contentType","bytes","sha256","uploadedAtMs","updatedAtMs","uploadedImageFacts","images","origin","posReaderSplashImagesOrigin","loadSharp","answer","requestPosReaderSplashImages","op","dataBase64","toString","facts","error","PosReaderSplashImagesRefusal","upload","input","uid","raw","String","length","Math","ceil","Buffer","from","problem","update","digest","extension","storagePath","slice","file","save","resumable","previous","delete","catch","undefined","familyId","Date","now","uploadedBy","applyToEveryStore","platform","handler","request","method","query","rawHeaders","authorization","idToken","startsWith","decoded","app","auth","verifyIdToken","email_verified","role","firestore","preview","download","Uint8Array","canWrite","includes","action","actor","actorUid","actorEmail","email","ok","next","outcome","set","scope","target","before","after","at","FieldValue","serverTimestamp","unauthenticated","console","posReaderSplashAdmin"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,UAAU,QAAQ,cAAa;AACxC,SAASC,oBAAoB,QAAQ,sBAAqB;AAC1D,SAASC,uBAAuB,EAAEC,aAAa,EAAEC,sBAAsB,QAAQ,2BAA0B;AACzG,SAASC,aAAa,QAAQ,oDAAmD;AACjF,SAASC,sBAAsB,QAAQ,mDAAkD;AACzF,SACEC,0BAA0B,EAC1BC,2BAA2B,EAC3BC,qBAAqB,EACrBC,2BAA2B,QACtB,gCAA4B;AACnC,SACEC,4BAA4B,EAC5BC,mBAAmB,EACnBC,iBAAiB,EACjBC,qBAAqB,EACrBC,kBAAkB,QAGb,yBAAqB;AAC5B,SAASC,yBAAyB,QAAQ,gCAA4B;AAEtE;;;;;;;;;;;;;;;;;;;;;2CAqB2C,GAE3C,MAAMC,cAAc;IAAC;CAAQ;AAE7B,MAAMC,OAAO,CAACC,MAAeC,SAAS,GAAG,GACvCC,SAASH,IAAI,CAACC,MAAM;QAAEC;QAAQE,SAAS;YAAE,iBAAiB;QAAW;IAAE;AAEzE,SAASC,KAAKC,GAAsB;QAoBnBA;IAnBf,OAAO;QACLC,OAAOb,oBAAoBY;QAC3BE,UAAUnB,2BAA2BoB,GAAG,CAAC,CAACC;gBAC1BJ;YAAd,MAAMK,SAAQL,gBAAAA,IAAIE,QAAQ,qBAAZF,aAAc,CAACI,OAAOE,EAAE,CAAC;YACvC,OAAO;gBACLA,IAAIF,OAAOE,EAAE;gBACbC,OAAOH,OAAOG,KAAK;gBACnBC,OAAOJ,OAAOI,KAAK;gBACnBC,QAAQL,OAAOK,MAAM;gBACrBJ,OAAOA,QACH;oBACEK,aAAaL,MAAMK,WAAW;oBAC9BC,OAAON,MAAMM,KAAK;oBAClBC,QAAQP,MAAMO,MAAM;oBACpBC,cAAcR,MAAMQ,YAAY;gBAClC,IACA;YACN;QACF;QACAC,WAAW,GAAEd,mBAAAA,IAAIc,WAAW,YAAfd,mBAAmB;IAClC;AACF;AAIA;;;CAGC,GACD,eAAee,mBAAmBpB,IAAY;IAC5C,MAAMqB,SAAS,MAAM,MAAM,CAAC;IAC5B,MAAMC,SAASD,OAAOE,2BAA2B;IACjD,IAAI,CAACD,QAAQ;QACX,MAAM,EAAEE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC;QACnC,OAAO3B,0BAA2B,MAAM2B,aAAqBxB;IAC/D;IACA,IAAI;QACF,MAAMyB,SAAS,MAAMJ,OAAOK,4BAA4B,CAErDJ,QAAQ;YAAEK,IAAI;YAASC,YAAY5B,KAAK6B,QAAQ,CAAC;QAAU;QAC9D,OAAOJ,OAAOK,KAAK;IACrB,EAAE,OAAOC,OAAO;QACd,IAAIA,iBAAiBV,OAAOW,4BAA4B,EAAE,OAAO;QACjE,MAAMD;IACR;AACF;AAEA,eAAeE,OACb5B,GAAsB,EACtB6B,KAA8B,EAC9BC,GAAW;QAIQD;QAiBF7B;IAnBjB,MAAMI,SAASnB,sBAAsB4C,KAAK,CAAC,SAAS;IACpD,IAAI,CAACzB,QAAQ,OAAO;QAAEsB,OAAO;QAAyB9B,QAAQ;IAAI;IAClE,MAAMmC,MAAMC,QAAOH,oBAAAA,KAAK,CAAC,aAAa,YAAnBA,oBAAuB;IAC1C,0EAA0E;IAC1E,IAAI,CAACE,OAAOA,IAAIE,MAAM,GAAGC,KAAKC,IAAI,CAAC,AAACnD,8BAA8B,IAAK,KAAK,GAAG;QAC7E,OAAO;YAAE0C,OAAO;YAA4B9B,QAAQ;QAAI;IAC1D;IACA,MAAMD,OAAOyC,OAAOC,IAAI,CAACN,KAAK;IAC9B,MAAMN,QAAQ,MAAMV,mBAAmBpB;IACvC,IAAI,CAAC8B,OAAO,OAAO;QAAEC,OAAO;QAAiC9B,QAAQ;IAAI;IACzE,oEAAoE;IACpE,MAAM0C,UAAUpD,4BAA4B,aAAKuC;QAAOd,OAAOhB,KAAKsC,MAAM;QAAI7B;IAC9E,IAAIkC,SAAS,OAAO;QAAEZ,OAAOY;QAAS1C,QAAQ;IAAI;IAClD,MAAMgB,SAASpC,WAAW,UAAU+D,MAAM,CAAC5C,MAAM6C,MAAM,CAAC;IACxD,MAAMC,YAAYhB,MAAMf,WAAW,KAAK,cAAc,QAAQ;IAC9D,MAAMgC,cAAc,CAAC,oCAAoC,EAAEtC,OAAOE,EAAE,CAAC,CAAC,EAAEM,OAAO+B,KAAK,CAAC,GAAG,IAAI,CAAC,EAAEF,WAAW;IAC1G,MAAMnD,wBACHsD,IAAI,CAACF,aACLG,IAAI,CAAClD,MAAM;QAAEe,aAAae,MAAMf,WAAW;QAAEoC,WAAW;IAAM;IACjE,MAAMC,YAAW/C,gBAAAA,IAAIE,QAAQ,qBAAZF,aAAc,CAACI,OAAOE,EAAE,CAAC;IAC1C,IAAIyC,CAAAA,4BAAAA,SAAUL,WAAW,KAAIK,SAASL,WAAW,KAAKA,aAAa;QACjE,MAAMpD,wBAAwBsD,IAAI,CAACG,SAASL,WAAW,EAAEM,MAAM,GAAGC,KAAK,CAAC,IAAMC;IAChF;IACA,OAAO;QACLC,UAAU/C,OAAOE,EAAE;QACnBD,OAAO;YACLqC;YACA9B;YACAF,aAAae,MAAMf,WAAW;YAC9BC,OAAOhB,KAAKsC,MAAM;YAClBpB,cAAcuC,KAAKC,GAAG;YACtBC,YAAYxB;QACd;IACF;AACF;AAEA;;;;CAIC,GACD,eAAeyB;IACb,OAAOpE,6BAA6B;QAAEqE,UAAU,MAAMjE;IAAqB;AAC7E;AAEA,eAAekE,QAAQC,OAAgB;QAGf5D;IAFtB,MAAM,EAAE6D,MAAM,EAAEC,KAAK,EAAEjE,IAAI,EAAEG,SAAS+D,UAAU,EAAE,GAAG,MAAMpF,qBAAqBiF;IAChF,MAAM5D,UAAU+D;IAChB,MAAMC,iBAAgBhE,yBAAAA,QAAQgE,aAAa,YAArBhE,yBAAyB;IAC/C,MAAMiE,UAAUD,cAAcE,UAAU,CAAC,aAAaF,cAAcnB,KAAK,CAAC,UAAUV,MAAM,IAAIiB;IAC9F,IAAI,CAACa,SAAS,OAAOrE,KAAK;QAAEgC,OAAO;IAAkB,GAAG;IAExD,IAAI;YAKkBuC,oBAwBEpC;QA5BtB,MAAMoC,UAAU,MAAMtF,cAAcuF,GAAG,GAAGC,IAAI,GAAGC,aAAa,CAACL;QAC/D,IAAI,CAACE,QAAQI,cAAc,IAAI,CAACzF,uBAAuBqF,UAAU,OAAOvF;QACxE,IAAI,CAACuF,OAAO,CAAC,QAAQ,EAAE,OAAOvE,KAAK;YAAEgC,OAAO;QAAa,GAAG;QAC5D,+DAA+D;QAC/D,MAAM4C,OAAOtC,QAAOiC,qBAAAA,OAAO,CAAC,YAAY,YAApBA,qBAAwB;QAC5C,MAAMM,YAAY5F,cAAcuF,GAAG,GAAGK,SAAS;QAC/C,MAAMvE,MAAM,MAAMT;QAElB,IAAIoE,WAAW,OAAO;;YACpB,MAAMa,UAAUxC,eAAO4B,yBAAAA,KAAO,CAAC,UAAU,mBAAI;YAC7C,IAAIY,SAAS;oBAEYxE;gBADvB,MAAMI,SAASnB,sBAAsBuF;gBACrC,MAAMnE,QAAQD,UAASJ,gBAAAA,IAAIE,QAAQ,qBAAZF,aAAc,CAACI,OAAOE,EAAE,CAAC,GAAG4C;gBACnD,IAAI,CAAC7C,OAAO,OAAOX,KAAK;oBAAEgC,OAAO;gBAAW,GAAG;gBAC/C,MAAM,CAACf,MAAM,GAAI,MAAMrB,wBAAwBsD,IAAI,CAACvC,MAAMqC,WAAW,EAAE+B,QAAQ;gBAC/E,OAAO,IAAI5E,SAAS,IAAI6E,WAAW/D,QAAQ;oBACzCf,QAAQ;oBACRE,SAAS;wBAAE,gBAAgBO,MAAMK,WAAW;wBAAE,iBAAiB;oBAAW;gBAC5E;YACF;YACA,OAAOhB,KAAK,aAAKK,KAAKC;gBAAM2E,UAAUlF,YAAYmF,QAAQ,CAACN;;QAC7D;QAEA,IAAIX,WAAW,QAAQ,OAAOjE,KAAK;YAAEgC,OAAO;QAAqB,GAAG;QACpE,IAAI,CAACjC,YAAYmF,QAAQ,CAACN,OAAO;YAC/B,OAAO5E,KAAK;gBAAEgC,OAAO;YAAqE,GAAG;QAC/F;QACA,MAAMG,QAASlC,eAAAA,OAAQ,CAAC;QACxB,MAAMkF,SAAS7C,QAAOH,gBAAAA,KAAK,CAAC,SAAS,YAAfA,gBAAmB;QACzC,MAAMiD,QAAQ;YAAEC,UAAUd,QAAQnC,GAAG;YAAEkD,YAAYf,QAAQgB,KAAK,GAAGjD,OAAOiC,QAAQgB,KAAK,IAAI;QAAK;QAEhG,IAAIJ,WAAW,SAAS,OAAOnF,KAAK;YAAEwF,IAAI;WAAU,MAAM3B;QAE1D,IAAIsB,WAAW,YAAYA,WAAW,UAAU;;gBA0BR7E,wBAAAA,gBACDmF,yBAAAA;YA1BrC,IAAIA;YACJ,IAAIhC;YACJ,IAAI0B,WAAW,UAAU;oBAIE7E;gBAHzB,MAAMoF,UAAU,MAAMxD,OAAO5B,KAAK6B,OAAOoC,QAAQnC,GAAG;gBACpD,IAAI,WAAWsD,SAAS,OAAO1F,KAAK;oBAAEgC,OAAO0D,QAAQ1D,KAAK;gBAAC,GAAG0D,QAAQxF,MAAM;gBAC5EuD,WAAWiC,QAAQjC,QAAQ;gBAC3BgC,OAAO;oBAAEjF,UAAU,cAAMF,iBAAAA,IAAIE,QAAQ,YAAZF,iBAAgB,CAAC;wBAAI,CAACmD,SAAS,EAAEiC,QAAQ/E,KAAK;;oBAAIS,aAAasC,KAAKC,GAAG;gBAAG;YACrG,OAAO;oBAIkBrD;gBAHvB,MAAMI,SAASnB,sBAAsB4C,KAAK,CAAC,SAAS;gBACpD,IAAI,CAACzB,QAAQ,OAAOV,KAAK;oBAAEgC,OAAO;gBAAwB,GAAG;gBAC7DyB,WAAW/C,OAAOE,EAAE;gBACpB,MAAMJ,WAAW,cAAMF,iBAAAA,IAAIE,QAAQ,YAAZF,iBAAgB,CAAC;gBACxC,MAAM+C,WAAW7C,QAAQ,CAACE,OAAOE,EAAE,CAAC;gBACpC,OAAOJ,QAAQ,CAACE,OAAOE,EAAE,CAAC;gBAC1B,IAAIyC,4BAAAA,SAAUL,WAAW,EAAE;oBACzB,MAAMpD,wBAAwBsD,IAAI,CAACG,SAASL,WAAW,EAAEM,MAAM,GAAGC,KAAK,CAAC,IAAMC;gBAChF;gBACAiC,OAAO;oBAAEjF;oBAAUY,aAAasC,KAAKC,GAAG;gBAAG;YAC7C;YACA,MAAMhE,oBAAoBgG,GAAG,CAACF;YAC9B,MAAMtG,cAAc0F,WAAW;gBAC7BM,QAAQ,CAAC,kBAAkB,EAAEA,QAAQ;eAClCC;gBACHQ,OAAO;gBACPC,QAAQ,CAAC,gCAAgC,CAAC;gBAC1CC,QAAQ;oBAAEpF,QAAQ+C;oBAAUvC,MAAM,YAAEZ,iBAAAA,IAAIE,QAAQ,sBAAZF,yBAAAA,cAAc,CAACmD,SAAsC,qBAArDnD,uBAAuDY,MAAM,oBAAI;gBAAK;gBAC1G6E,OAAO;oBAAErF,QAAQ+C;oBAAUvC,MAAM,YAAEuE,iBAAAA,KAAKjF,QAAQ,sBAAbiF,0BAAAA,cAAe,CAAChC,SAAuC,qBAAvDgC,wBAAyDvE,MAAM,oBAAI;gBAAK;gBAC3G8E,IAAI/G,cAAc4F,SAAS,CAACoB,UAAU,CAACC,eAAe;;YAExD,OAAOlG,KAAK;gBAAEwF,IAAI;eAASnF,KAAKoF;gBAAOR,UAAU;;QACnD;QACA,OAAOjF,KAAK;YAAEgC,OAAO;QAAiB,GAAG;IAC3C,EAAE,OAAOA,OAAO;QACd,MAAMmE,kBAAkB/G,uBAAuB4C;QAC/C,IAAImE,iBAAiB,OAAOA;QAC5BC,QAAQpE,KAAK,CAAC,6BAA6BA;QAC3C,OAAOhC,KAAK;YAAEgC,OAAO;QAAkD,GAAG;IAC5E;AACF;AAEA,SAAS+B,WAAWsC,oBAAoB,GAAE"}
@@ -0,0 +1,17 @@
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
+ export declare function posReaderSplashImagesRoute(request: Request): Promise<Response>;