@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
@@ -17,8 +17,11 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
17
17
  */ import { createHash, randomBytes, randomInt } from "crypto";
18
18
  import { consumeRateLimit, firebaseAdmin, getPluginConfig, getOrgForHost } from "@aglyn/tenant-data-admin";
19
19
  import { resolveMediaSrc } from "@aglyn/aglyn/app-utils/media-ref";
20
+ import { sanitizeCustomerDisplayScreen } from "@aglyn/aglyn/plugin-manager/plugin-customer-display";
20
21
  import { pluginSmsAvailable } from "@aglyn/aglyn/plugin-manager/plugin-sms-messaging";
21
22
  import * as CommerceModel from "../model/index.js";
23
+ import { BUNDLE_ID } from "../constants/bundle-common.js";
24
+ import { parsePosHardwareInPersonConfig } from "../model/pos-hardware.js";
22
25
  import { posRegisterSettings } from "../plugin-config.js";
23
26
  import { authorizePosStaff, posQueryBody, posRequestBody } from "./pos-auth.js";
24
27
  import { POS_CURRENCY } from "./pos-stripe.js";
@@ -188,6 +191,31 @@ async function registerExists(hostId, registerId) {
188
191
  data: (_snapshot_data = snapshot.data()) != null ? _snapshot_data : {}
189
192
  };
190
193
  }
194
+ /**
195
+ * Core's customer display verifier (AGL-4042, `plugin-customer-display-verifier`):
196
+ * who a paired display is, for another plugin's server acting for the screen
197
+ * it put there. The display's own token is the credential, so the pairing is
198
+ * the authorization: a live CUSTOMER DISPLAY token (never a kiosk's) answers
199
+ * the store it is paired to, the workspace that owns it, the plugin screen it
200
+ * is showing now, and who put it there. Anything else answers `null`.
201
+ */ export async function verifyPosCustomerDisplay(credential) {
202
+ var _ref, _ref1;
203
+ var _owner_org;
204
+ const display = await resolveDisplayToken(credential);
205
+ if (!display || display.mode !== 'display') return null;
206
+ const owner = await getOrgForHost(display.hostId).catch(()=>null);
207
+ const orgId = String((_ref = (_ref1 = owner == null ? void 0 : (_owner_org = owner.org) == null ? void 0 : _owner_org.id) != null ? _ref1 : owner == null ? void 0 : owner.orgId) != null ? _ref : '');
208
+ if (!orgId) return null;
209
+ const snapshot = await stateRef(display.hostId, display.registerId).get();
210
+ const state = snapshot.exists ? snapshot.data() : null;
211
+ const screen = (state == null ? void 0 : state.mode) === 'screen' && state.screen ? state.screen : null;
212
+ return {
213
+ hostId: display.hostId,
214
+ orgId,
215
+ screen,
216
+ shownBy: screen && typeof (state == null ? void 0 : state.screenShownBy) === 'string' ? state.screenShownBy : null
217
+ };
218
+ }
191
219
  /** A token row's mode, `display` for one that predates kiosks. */ function tokenMode(doc) {
192
220
  return doc.get('mode') === 'kiosk' ? 'kiosk' : 'display';
193
221
  }
@@ -264,6 +292,24 @@ async function registerExists(hostId, registerId) {
264
292
  ok: true
265
293
  });
266
294
  }
295
+ case 'hardware-terms':
296
+ case 'accept-hardware-terms':
297
+ {
298
+ // The terms of sale for a card reader sold here (AGL-4038), on the
299
+ // screen the register put on this display: the display's own token,
300
+ // never a staff session.
301
+ if (req.method !== 'POST') return res.status(405).json({
302
+ error: 'Method not allowed'
303
+ });
304
+ const display = await resolveDisplayToken(displayToken(req, body));
305
+ if (!display) return res.status(401).json({
306
+ error: 'This display is not paired.'
307
+ });
308
+ if (display.mode === 'kiosk') return res.status(403).json({
309
+ error: 'This device is a self-service kiosk.'
310
+ });
311
+ return await hardwareTermsOnDisplay(req, display, body, action, res);
312
+ }
267
313
  default:
268
314
  return await staffAction(req, body, action, res);
269
315
  }
@@ -348,7 +394,9 @@ async function pair(req, body, res) {
348
394
  async function staffAction(req, body, action, res) {
349
395
  var _body_hostId, _body_registerId;
350
396
  const hostId = String((_body_hostId = body['hostId']) != null ? _body_hostId : '');
351
- const gate = await authorizePosStaff(req, hostId);
397
+ // Pairing a customer display and revoking one is setting the register up
398
+ // (AGL-4047); showing a sale on a paired display is part of the sale.
399
+ const gate = await authorizePosStaff(req, hostId, action === 'pairing-code' || action === 'revoke' ? 'posDevices' : undefined);
352
400
  if ('error' in gate) return res.status(gate.status).json({
353
401
  error: gate.error
354
402
  });
@@ -393,7 +441,14 @@ async function staffAction(req, body, action, res) {
393
441
  case 'push':
394
442
  {
395
443
  var _state_promptId;
396
- const state = CommerceModel.sanitizePosDisplayState(body['state'], Date.now());
444
+ // Another plugin's screen (AGL-4042) is checked by core's seam: a
445
+ // declared plugin page and a few short parameters, nothing else.
446
+ const state = CommerceModel.sanitizePosDisplayState(body['state'], Date.now(), {
447
+ screen: sanitizeCustomerDisplayScreen
448
+ });
449
+ // Who put a plugin's screen there (AGL-4042), from the session, so the
450
+ // screen's plugin can name them through core's display verifier.
451
+ if (state.mode === 'screen') state.screenShownBy = gate.staff.uid;
397
452
  // "Text" is never offered on a screen when the store cannot send one.
398
453
  if (state.receipt && !pluginSmsAvailable()) {
399
454
  const channels = state.receipt.channels.filter((channel)=>channel !== 'sms');
@@ -408,6 +463,26 @@ async function staffAction(req, body, action, res) {
408
463
  promptId: (_state_promptId = state.promptId) != null ? _state_promptId : null
409
464
  });
410
465
  }
466
+ case 'close-screen':
467
+ {
468
+ var _body_pluginId;
469
+ var _current_screen;
470
+ // A plugin takes its own screen off the display (AGL-4042, core's
471
+ // `CustomerDisplayHost.close`): only while that plugin's screen is
472
+ // the one showing, so it never clears a sale the register moved on to.
473
+ const pluginId = String((_body_pluginId = body['pluginId']) != null ? _body_pluginId : '');
474
+ const snapshot = await stateRef(hostId, registerId).get();
475
+ const current = snapshot.exists ? snapshot.data() : null;
476
+ const showing = (current == null ? void 0 : current.mode) === 'screen' && ((_current_screen = current.screen) == null ? void 0 : _current_screen.pluginId) === pluginId;
477
+ if (showing) await writePosDisplayState(hostId, registerId, {
478
+ mode: 'idle',
479
+ updatedAtMs: Date.now()
480
+ });
481
+ return res.status(200).json({
482
+ ok: true,
483
+ closed: showing
484
+ });
485
+ }
411
486
  case 'state':
412
487
  {
413
488
  const snapshot = await stateRef(hostId, registerId).get();
@@ -456,5 +531,57 @@ async function staffAction(req, body, action, res) {
456
531
  });
457
532
  }
458
533
  }
534
+ /** The page the terms of sale open at on a display, beneath `/kiosk/commerce`. */ export const POS_HARDWARE_TERMS_PAGE_PATH = '/hardware-terms';
535
+ /**
536
+ * The terms of sale on a customer display (AGL-4038): read them, or accept
537
+ * them, for the sale the register put on THIS display — the screen must be
538
+ * showing, for this register, with this sale's id, so a display can neither
539
+ * read nor accept for another sale. Accepting records it and takes the
540
+ * screen off, so the display shows the register again.
541
+ */ async function hardwareTermsOnDisplay(req, display, body, action, res) {
542
+ var _body_order;
543
+ var _state_screen, _state_screen1, _state_screen_params, _state_screen2;
544
+ const config = parsePosHardwareInPersonConfig(process.env);
545
+ if (!config || display.hostId !== config.sellerHostId) {
546
+ return res.status(404).json({
547
+ error: 'Card reader sales are not available here.'
548
+ });
549
+ }
550
+ const order = String((_body_order = body['order']) != null ? _body_order : '');
551
+ const snapshot = await stateRef(display.hostId, display.registerId).get();
552
+ const state = snapshot.exists ? snapshot.data() : null;
553
+ const showing = (state == null ? void 0 : state.mode) === 'screen' && ((_state_screen = state.screen) == null ? void 0 : _state_screen.pluginId) === BUNDLE_ID && ((_state_screen1 = state.screen) == null ? void 0 : _state_screen1.path) === POS_HARDWARE_TERMS_PAGE_PATH && ((_state_screen2 = state.screen) == null ? void 0 : (_state_screen_params = _state_screen2.params) == null ? void 0 : _state_screen_params['order']) === order;
554
+ if (!showing) return res.status(409).json({
555
+ error: 'That screen has moved on. Check the display.'
556
+ });
557
+ const terms = await import("./pos-hardware-terms.js");
558
+ try {
559
+ if (action === 'hardware-terms') {
560
+ return res.status(200).json(_extends({}, terms.posHardwareTermsView(), await terms.posHardwareTermsSale(config, order)));
561
+ }
562
+ if (body['accept'] !== true) return res.status(400).json({
563
+ error: 'Tick the box to accept the terms of sale.'
564
+ });
565
+ const acceptance = await terms.recordPosHardwareTermsAcceptance(_extends({
566
+ config,
567
+ registerOrderId: order,
568
+ method: 'display',
569
+ staffUid: null
570
+ }, terms.posHardwareTermsDevice(req.headers)));
571
+ await writePosDisplayState(display.hostId, display.registerId, {
572
+ mode: 'idle',
573
+ updatedAtMs: Date.now()
574
+ });
575
+ return res.status(200).json({
576
+ ok: true,
577
+ acceptance
578
+ });
579
+ } catch (error) {
580
+ if (error instanceof terms.PosHardwareTermsRefusal) return res.status(error.status).json({
581
+ error: error.message
582
+ });
583
+ throw error;
584
+ }
585
+ }
459
586
 
460
587
  //# sourceMappingURL=pos-display.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/pos-display.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, randomBytes, randomInt } from 'crypto'\nimport { consumeRateLimit, firebaseAdmin, getPluginConfig, getOrgForHost } from '@aglyn/tenant-data-admin'\nimport type { PluginApiHandler, PluginApiRequest } from '@aglyn/aglyn/server'\nimport { resolveMediaSrc } from '@aglyn/aglyn/app-utils/media-ref'\nimport { pluginSmsAvailable } from '@aglyn/aglyn/plugin-manager/plugin-sms-messaging'\nimport * as CommerceModel from '../model'\nimport { posRegisterSettings } from '../plugin-config'\nimport { authorizePosStaff, posQueryBody, posRequestBody } from './pos-auth'\nimport { POS_CURRENCY } from './pos-stripe'\n\n/*==========================================\n * THE CUSTOMER DISPLAY (AGL-3608).\n *\n * A second screen — a tablet on a stand facing the customer — that shows the\n * basket, takes the tip and the receipt choice, and hands both back to the\n * cashier. It must work with NO staff sign-in on the customer's device, so it\n * holds nothing but a display token.\n *\n * ## Pairing\n *\n * The register asks for a six-digit code (`pairing-code`), good for ten\n * minutes and usable once. The display sends it (`pair`) and receives a\n * random 256-bit token. Only hashes are stored: `posDisplayPairings/{sha256}`\n * for the code and `posDisplayTokens/{sha256}` for the token, each naming the\n * one site and register it opens. Revoking a display, or removing its\n * register, kills the token. A six-digit space is small, so `pair` is rate\n * limited per address and a code dies at its first use.\n *\n * ## Why polling through this route, not a Firestore listener\n *\n * A Firestore listener needs a Firebase identity the rules can test, which on\n * the customer's device means minting a custom auth session — a credential\n * that would sit on an unattended tablet with the console's own SDK. Polling\n * this route once a second with the display token is the simplest thing that\n * is secure: the token opens exactly one register's display state and\n * nothing else, the state lives in a server-only collection\n * (`posDisplayStates`, denied to every client by the rules) so not even a\n * signed-in site member can read a customer's typed address out of it, and a\n * revoked token stops working on the next poll.\n *=========================================*/\n\nconst PAIRINGS = 'posDisplayPairings'\nconst TOKENS = 'posDisplayTokens'\nconst STATES = 'posDisplayStates'\n\nexport function sha256(value: string): string {\n return createHash('sha256').update(value).digest('hex')\n}\n\n/** The one state document a register's display reads. */\nexport function posDisplayStateId(hostId: string, registerId: string): string {\n return `${hostId}__${registerId}`\n}\n\nfunction stateRef(hostId: string, registerId: string) {\n return firebaseAdmin\n .app()\n .firestore()\n .collection(STATES)\n .doc(posDisplayStateId(hostId, registerId))\n}\n\n/**\n * The store's currency (`hosts/{hostId}/settings/store.currency`, lower\n * case), which every figure on the customer's screen is formatted in. A\n * store that never chose one is in the currency the register charges.\n */\nexport async function posDisplayCurrency(hostId: string): Promise<string> {\n const snapshot = await firebaseAdmin\n .app()\n .firestore()\n .collection('hosts')\n .doc(hostId)\n .collection('settings')\n .doc('store')\n .get()\n .catch(() => null)\n const chosen = String(snapshot?.exists ? (snapshot.get('currency') ?? '') : '')\n .trim()\n .toLowerCase()\n return /^[a-z]{3}$/.test(chosen) ? chosen : POS_CURRENCY\n}\n\n/**\n * Writes the display state whole, so nothing from the last prompt lingers —\n * a customer's typed address included. The currency is the store's, stamped\n * here so the screen never formats a figure in one the register made up.\n */\nexport async function writePosDisplayState(\n hostId: string,\n registerId: string,\n state: CommerceModel.PosDisplayState,\n): Promise<void> {\n await stateRef(hostId, registerId).set({\n ...state,\n currency: await posDisplayCurrency(hostId),\n hostId,\n registerId,\n })\n}\n\n/** The register's display returns to the thank-you screen with no customer data. */\nexport async function resetPosDisplay(hostId: string, registerId: string): Promise<void> {\n await writePosDisplayState(hostId, registerId, { mode: 'thanks', updatedAtMs: Date.now() })\n}\n\n/**\n * Ends the customer's turn once the register has acted on their receipt\n * choice (AGL-3608): a display still on the receipt prompt says thank you,\n * and an answer holding a typed email address or phone number is dropped\n * from the state either way, so no contact detail outlives the sale on the\n * server doc a public screen reads.\n *\n * Conditional, in a transaction, because the receipt can be sent after the\n * cashier has started the next sale: a display already showing the next\n * customer's basket is left alone.\n */\nexport async function finishPosDisplayReceipt(hostId: string, registerId: string): Promise<void> {\n const firestore = firebaseAdmin.app().firestore()\n const ref = stateRef(hostId, registerId)\n const currency = await posDisplayCurrency(hostId)\n await firestore.runTransaction(async (transaction: any) => {\n const snapshot = await transaction.get(ref)\n if (!snapshot.exists) return\n const state = snapshot.data() as CommerceModel.PosDisplayState\n if (state.mode === 'receipt') {\n transaction.set(ref, {\n mode: 'thanks',\n updatedAtMs: Date.now(),\n currency,\n hostId,\n registerId,\n })\n return\n }\n if (state.response && (state.response.email || state.response.phone)) {\n const rest = { ...state }\n delete rest.response\n transaction.set(ref, rest)\n }\n })\n}\n\n/** Signs every display of a register out, and forgets its state. */\nexport async function revokePosDisplays(hostId: string, registerId: string): Promise<void> {\n const firestore = firebaseAdmin.app().firestore()\n const tokens = await firestore\n .collection(TOKENS)\n .where('hostId', '==', hostId)\n .where('registerId', '==', registerId)\n .limit(50)\n .get()\n await Promise.all(tokens.docs.map((doc: any) => doc.ref.delete()))\n await stateRef(hostId, registerId).delete().catch(() => undefined)\n}\n\nasync function registerExists(hostId: string, registerId: string): Promise<boolean> {\n if (!/^[A-Za-z0-9_-]{1,128}$/.test(registerId)) return false\n return (\n await firebaseAdmin\n .app()\n .firestore()\n .collection('hosts')\n .doc(hostId)\n .collection('registers')\n .doc(registerId)\n .get()\n ).exists\n}\n\n/** The store's name, logo and welcome line, for the idle and thank-you screens. */\nexport async function displayBranding(hostId: string) {\n const firestore = firebaseAdmin.app().firestore()\n const host = await firestore.collection('hosts').doc(hostId).get()\n const ownerOrg = await getOrgForHost(hostId).catch(() => null)\n const settings = posRegisterSettings(\n await getPluginConfig(ownerOrg?.orgId, 'commerce', { hostId }).catch(() => ({})),\n )\n return {\n name: String(host.get('displayName') ?? host.get('name') ?? '').slice(0, 80) || 'Welcome',\n logoUrl: resolveMediaSrc(host.get('logoUrl'), { hostId }) ?? null,\n logoDarkUrl: resolveMediaSrc(host.get('logoDarkUrl'), { hostId }) ?? null,\n message: settings.displayMessage || 'Welcome',\n }\n}\n\n/** The display token on a request, or ''. */\nexport function displayToken(req: PluginApiRequest, body: Record<string, any>): string {\n const header = String(req.headers['x-pos-display-token'] ?? '')\n return (header || String(body['token'] ?? '')).trim().slice(0, 128)\n}\n\n/** What a paired device's token opens. */\nexport interface PosDeviceToken {\n hostId: string\n registerId: string\n ref: any\n /**\n * A customer display, or a self-service kiosk (AGL-3623). A token minted\n * before kiosks existed has no mode and is a display.\n */\n mode: CommerceModel.PosDeviceMode\n /** The staff member whose pairing code opened this device. */\n createdBy: string\n /** The token document, for the caller that keeps device settings on it. */\n data: Record<string, any>\n}\n\n/** The register a live display token opens, or null. */\nexport async function resolveDisplayToken(token: string): Promise<PosDeviceToken | null> {\n if (!/^[A-Za-z0-9_-]{40,128}$/.test(token)) return null\n const ref = firebaseAdmin.app().firestore().collection(TOKENS).doc(sha256(token))\n const snapshot = await ref.get()\n if (!snapshot.exists) return null\n const hostId = String(snapshot.get('hostId') ?? '')\n const registerId = String(snapshot.get('registerId') ?? '')\n if (!hostId || !registerId) return null\n // A display whose register was removed is dead, even if its token row\n // somehow outlived the removal.\n if (!(await registerExists(hostId, registerId))) return null\n const lastSeen = Number(snapshot.get('lastSeenAtMs') ?? 0)\n if (Date.now() - lastSeen > 60_000) {\n await ref.set({ lastSeenAtMs: Date.now() }, { merge: true }).catch(() => undefined)\n }\n return {\n hostId,\n registerId,\n ref,\n mode: snapshot.get('mode') === 'kiosk' ? 'kiosk' : 'display',\n createdBy: String(snapshot.get('createdBy') ?? ''),\n data: (snapshot.data() ?? {}) as Record<string, any>,\n }\n}\n\n/** A token row's mode, `display` for one that predates kiosks. */\nfunction tokenMode(doc: any): CommerceModel.PosDeviceMode {\n return doc.get('mode') === 'kiosk' ? 'kiosk' : 'display'\n}\n\n/**\n * `POST /api/commerce/pos-display`.\n *\n * Staff (Firebase token + the register's gate): `pairing-code`, `push`,\n * `state`, `displays`, `revoke`.\n * Display (display token only): `pair`, `poll`, `respond`, `forget`.\n */\nexport const posDisplayHandler: PluginApiHandler = async (req, res) => {\n // The two polls are GETs: a read is not a console write, so a display and a\n // register asking once a second do not spend the console's write budget.\n const body = req.method === 'GET' ? posQueryBody(req) : posRequestBody(req)\n const action = String(body['action'] ?? '')\n if (\n !(req.method === 'POST' || (req.method === 'GET' && (action === 'poll' || action === 'state')))\n ) {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n res.setHeader('Cache-Control', 'no-store')\n try {\n switch (action) {\n case 'pair':\n return await pair(req, body, res)\n case 'poll':\n case 'respond':\n case 'forget': {\n const display = await resolveDisplayToken(displayToken(req, body))\n if (!display) return res.status(401).json({ error: 'This display is not paired.' })\n if (action === 'forget') {\n // A kiosk leaves kiosk mode behind a staff PIN (AGL-3623), through\n // `commerce/pos-kiosk`, never by a customer's tap here.\n if (display.mode === 'kiosk') {\n return res.status(403).json({ error: 'Ask a staff member to unlock this kiosk.' })\n }\n await display.ref.delete()\n return res.status(200).json({ ok: true })\n }\n // A kiosk is not the register's customer display (AGL-3623): the\n // basket the cashier is ringing up belongs to another customer.\n if (display.mode === 'kiosk') {\n return res.status(403).json({ error: 'This device is a self-service kiosk.' })\n }\n const snapshot = await stateRef(display.hostId, display.registerId).get()\n const state = snapshot.exists ? (snapshot.data() as CommerceModel.PosDisplayState) : null\n if (action === 'poll') {\n return res.status(200).json({\n state: CommerceModel.posDisplayPublicState(state, Date.now()),\n branding:\n body['branding'] === true || body['branding'] === 'true'\n ? await displayBranding(display.hostId)\n : undefined,\n })\n }\n const response = CommerceModel.sanitizePosDisplayResponse(state, body['response'], Date.now())\n if (!response) {\n return res.status(409).json({ error: 'That screen has moved on. Check the display.' })\n }\n await stateRef(display.hostId, display.registerId).set({ response }, { merge: true })\n return res.status(200).json({ ok: true })\n }\n default:\n return await staffAction(req, body, action, res)\n }\n } catch (error) {\n console.error('[pos-display]', action, error)\n return res.status(500).json({ error: 'The customer display could not be updated' })\n }\n}\n\nasync function pair(\n req: PluginApiRequest,\n body: Record<string, any>,\n res: Parameters<PluginApiHandler>[1],\n) {\n const address = String(req.socket?.remoteAddress ?? '') || 'no-address'\n const rate = await consumeRateLimit(`pos-display-pair:${address}`, {\n limit: 10,\n windowMs: 10 * 60 * 1000,\n })\n if (!rate.allowed) {\n return res.status(429).json({ error: 'Too many tries. Wait a few minutes and try again.' })\n }\n const code = String(body['code'] ?? '').replace(/\\D/g, '')\n // The device asks for the kind of screen it is; the code decides. A kiosk\n // code opens a kiosk, and a display code never does (AGL-3623).\n const wanted: CommerceModel.PosDeviceMode = body['mode'] === 'kiosk' ? 'kiosk' : 'display'\n if (code.length !== 6) return res.status(400).json({ error: 'Enter the 6-digit code from the register.' })\n const firestore = firebaseAdmin.app().firestore()\n const pairingRef = firestore.collection(PAIRINGS).doc(sha256(code))\n const token = randomBytes(32).toString('base64url')\n // Spent in the same transaction that mints the token: a code opens one\n // display, once, and a second display racing the first gets nothing.\n const paired = await firestore.runTransaction(async (transaction: any) => {\n const snapshot = await transaction.get(pairingRef)\n if (!snapshot.exists) return null\n const expiresAtMs = Number(snapshot.get('expiresAtMs') ?? 0)\n transaction.delete(pairingRef)\n if (!(expiresAtMs > Date.now())) return null\n const hostId = String(snapshot.get('hostId') ?? '')\n const registerId = String(snapshot.get('registerId') ?? '')\n const mode: CommerceModel.PosDeviceMode = snapshot.get('mode') === 'kiosk' ? 'kiosk' : 'display'\n // The wrong kind of screen leaves the code spent: the register shows a\n // new one for the device it meant.\n if (mode !== wanted) return { mismatch: mode }\n transaction.set(firestore.collection(TOKENS).doc(sha256(token)), {\n hostId,\n registerId,\n mode,\n createdAtMs: Date.now(),\n createdBy: String(snapshot.get('createdBy') ?? ''),\n lastSeenAtMs: Date.now(),\n label:\n String(body['label'] ?? '').slice(0, 60) ||\n (mode === 'kiosk' ? 'Self-service kiosk' : 'Customer display'),\n })\n return { hostId, registerId, mode }\n })\n if (!paired) {\n return res.status(404).json({ error: 'That code is not valid. Show a new code on the register.' })\n }\n if ('mismatch' in paired) {\n return res.status(409).json({\n error:\n paired.mismatch === 'kiosk'\n ? 'That code is for a self-service kiosk. Open the kiosk address, or show a display code on the register.'\n : 'That code is for a customer display. Choose Self-service kiosk on the register and show a new code.',\n })\n }\n return res\n .status(200)\n .json({ token, mode: paired.mode, branding: await displayBranding(paired.hostId) })\n}\n\nasync function staffAction(\n req: PluginApiRequest,\n body: Record<string, any>,\n action: string,\n res: Parameters<PluginApiHandler>[1],\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 const registerId = String(body['registerId'] ?? '')\n if (!(await registerExists(hostId, registerId))) {\n return res.status(404).json({ error: 'Unknown register' })\n }\n const firestore = firebaseAdmin.app().firestore()\n switch (action) {\n case 'pairing-code': {\n for (let attempt = 0; attempt < 8; attempt++) {\n const code = String(randomInt(0, 1_000_000)).padStart(6, '0')\n const ref = firestore.collection(PAIRINGS).doc(sha256(code))\n const expiresAtMs = Date.now() + CommerceModel.POS_DISPLAY_PAIRING_TTL_MS\n const claimed = await firestore.runTransaction(async (transaction: any) => {\n const existing = await transaction.get(ref)\n // A live code another register is showing is never overwritten.\n if (existing.exists && Number(existing.get('expiresAtMs') ?? 0) > Date.now()) return false\n transaction.set(ref, {\n hostId,\n registerId,\n expiresAtMs,\n createdBy: gate.staff.uid,\n // A kiosk code (AGL-3623) opens a self-service kiosk instead.\n mode: body['mode'] === 'kiosk' ? 'kiosk' : 'display',\n })\n return true\n })\n if (claimed) return res.status(200).json({ code, expiresAtMs })\n }\n return res.status(503).json({ error: 'Could not make a code. Try again.' })\n }\n case 'push': {\n const state = CommerceModel.sanitizePosDisplayState(body['state'], Date.now())\n // \"Text\" is never offered on a screen when the store cannot send one.\n if (state.receipt && !pluginSmsAvailable()) {\n const channels = state.receipt.channels.filter((channel) => channel !== 'sms')\n state.receipt.channels = channels.length ? channels : ['print', 'none']\n }\n await writePosDisplayState(hostId, registerId, state)\n return res.status(200).json({ ok: true, promptId: state.promptId ?? null })\n }\n case 'state': {\n const snapshot = await stateRef(hostId, registerId).get()\n const state = snapshot.exists ? (snapshot.data() as CommerceModel.PosDisplayState) : null\n const displays = await firestore\n .collection(TOKENS)\n .where('hostId', '==', hostId)\n .where('registerId', '==', registerId)\n .limit(10)\n .get()\n return res.status(200).json({\n state,\n // A display that polled within the last two minutes is \"connected\".\n // A kiosk is not the register's display (AGL-3623).\n connected: displays.docs.some(\n (doc: any) =>\n tokenMode(doc) === 'display' && Date.now() - Number(doc.get('lastSeenAtMs') ?? 0) < 120_000,\n ),\n })\n }\n case 'displays': {\n const displays = await firestore\n .collection(TOKENS)\n .where('hostId', '==', hostId)\n .where('registerId', '==', registerId)\n .limit(10)\n .get()\n return res.status(200).json({\n displays: displays.docs.map((doc: any) => ({\n id: doc.id.slice(0, 16),\n label: String(doc.get('label') ?? 'Customer display'),\n mode: tokenMode(doc),\n createdAtMs: Number(doc.get('createdAtMs') ?? 0),\n lastSeenAtMs: Number(doc.get('lastSeenAtMs') ?? 0),\n })),\n })\n }\n case 'revoke': {\n const prefix = String(body['displayId'] ?? '')\n const displays = await firestore\n .collection(TOKENS)\n .where('hostId', '==', hostId)\n .where('registerId', '==', registerId)\n .limit(10)\n .get()\n const doomed = displays.docs.filter(\n (doc: any) => prefix === '*' || (prefix.length === 16 && doc.id.startsWith(prefix)),\n )\n await Promise.all(doomed.map((doc: any) => doc.ref.delete()))\n return res.status(200).json({ revoked: doomed.length })\n }\n default:\n return res.status(400).json({ error: 'Unknown action' })\n }\n}\n"],"names":["createHash","randomBytes","randomInt","consumeRateLimit","firebaseAdmin","getPluginConfig","getOrgForHost","resolveMediaSrc","pluginSmsAvailable","CommerceModel","posRegisterSettings","authorizePosStaff","posQueryBody","posRequestBody","POS_CURRENCY","PAIRINGS","TOKENS","STATES","sha256","value","update","digest","posDisplayStateId","hostId","registerId","stateRef","app","firestore","collection","doc","posDisplayCurrency","snapshot","get","catch","chosen","String","exists","trim","toLowerCase","test","writePosDisplayState","state","set","currency","resetPosDisplay","mode","updatedAtMs","Date","now","finishPosDisplayReceipt","ref","runTransaction","transaction","data","response","email","phone","rest","revokePosDisplays","tokens","where","limit","Promise","all","docs","map","delete","undefined","registerExists","displayBranding","host","ownerOrg","settings","orgId","name","slice","logoUrl","logoDarkUrl","message","displayMessage","displayToken","req","body","header","headers","resolveDisplayToken","token","lastSeen","Number","lastSeenAtMs","merge","createdBy","tokenMode","posDisplayHandler","res","method","action","status","json","error","setHeader","pair","display","ok","posDisplayPublicState","branding","sanitizePosDisplayResponse","staffAction","console","address","socket","remoteAddress","rate","windowMs","allowed","code","replace","wanted","length","pairingRef","toString","paired","expiresAtMs","mismatch","createdAtMs","label","gate","attempt","padStart","POS_DISPLAY_PAIRING_TTL_MS","claimed","existing","staff","uid","sanitizePosDisplayState","receipt","channels","filter","channel","promptId","displays","connected","some","id","prefix","doomed","startsWith","revoked"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/pos-display.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, randomBytes, randomInt } from 'crypto'\nimport { consumeRateLimit, firebaseAdmin, getPluginConfig, getOrgForHost } from '@aglyn/tenant-data-admin'\nimport type { PluginApiHandler, PluginApiRequest } from '@aglyn/aglyn/server'\nimport { resolveMediaSrc } from '@aglyn/aglyn/app-utils/media-ref'\nimport { sanitizeCustomerDisplayScreen } from '@aglyn/aglyn/plugin-manager/plugin-customer-display'\nimport { pluginSmsAvailable } from '@aglyn/aglyn/plugin-manager/plugin-sms-messaging'\nimport * as CommerceModel from '../model'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { parsePosHardwareInPersonConfig } from '../model/pos-hardware'\nimport { posRegisterSettings } from '../plugin-config'\nimport { authorizePosStaff, posQueryBody, posRequestBody } from './pos-auth'\nimport { POS_CURRENCY } from './pos-stripe'\n\n/*==========================================\n * THE CUSTOMER DISPLAY (AGL-3608).\n *\n * A second screen — a tablet on a stand facing the customer — that shows the\n * basket, takes the tip and the receipt choice, and hands both back to the\n * cashier. It must work with NO staff sign-in on the customer's device, so it\n * holds nothing but a display token.\n *\n * ## Pairing\n *\n * The register asks for a six-digit code (`pairing-code`), good for ten\n * minutes and usable once. The display sends it (`pair`) and receives a\n * random 256-bit token. Only hashes are stored: `posDisplayPairings/{sha256}`\n * for the code and `posDisplayTokens/{sha256}` for the token, each naming the\n * one site and register it opens. Revoking a display, or removing its\n * register, kills the token. A six-digit space is small, so `pair` is rate\n * limited per address and a code dies at its first use.\n *\n * ## Why polling through this route, not a Firestore listener\n *\n * A Firestore listener needs a Firebase identity the rules can test, which on\n * the customer's device means minting a custom auth session — a credential\n * that would sit on an unattended tablet with the console's own SDK. Polling\n * this route once a second with the display token is the simplest thing that\n * is secure: the token opens exactly one register's display state and\n * nothing else, the state lives in a server-only collection\n * (`posDisplayStates`, denied to every client by the rules) so not even a\n * signed-in site member can read a customer's typed address out of it, and a\n * revoked token stops working on the next poll.\n *=========================================*/\n\nconst PAIRINGS = 'posDisplayPairings'\nconst TOKENS = 'posDisplayTokens'\nconst STATES = 'posDisplayStates'\n\nexport function sha256(value: string): string {\n return createHash('sha256').update(value).digest('hex')\n}\n\n/** The one state document a register's display reads. */\nexport function posDisplayStateId(hostId: string, registerId: string): string {\n return `${hostId}__${registerId}`\n}\n\nfunction stateRef(hostId: string, registerId: string) {\n return firebaseAdmin\n .app()\n .firestore()\n .collection(STATES)\n .doc(posDisplayStateId(hostId, registerId))\n}\n\n/**\n * The store's currency (`hosts/{hostId}/settings/store.currency`, lower\n * case), which every figure on the customer's screen is formatted in. A\n * store that never chose one is in the currency the register charges.\n */\nexport async function posDisplayCurrency(hostId: string): Promise<string> {\n const snapshot = await firebaseAdmin\n .app()\n .firestore()\n .collection('hosts')\n .doc(hostId)\n .collection('settings')\n .doc('store')\n .get()\n .catch(() => null)\n const chosen = String(snapshot?.exists ? (snapshot.get('currency') ?? '') : '')\n .trim()\n .toLowerCase()\n return /^[a-z]{3}$/.test(chosen) ? chosen : POS_CURRENCY\n}\n\n/**\n * Writes the display state whole, so nothing from the last prompt lingers —\n * a customer's typed address included. The currency is the store's, stamped\n * here so the screen never formats a figure in one the register made up.\n */\nexport async function writePosDisplayState(\n hostId: string,\n registerId: string,\n state: CommerceModel.PosDisplayState,\n): Promise<void> {\n await stateRef(hostId, registerId).set({\n ...state,\n currency: await posDisplayCurrency(hostId),\n hostId,\n registerId,\n })\n}\n\n/** The register's display returns to the thank-you screen with no customer data. */\nexport async function resetPosDisplay(hostId: string, registerId: string): Promise<void> {\n await writePosDisplayState(hostId, registerId, { mode: 'thanks', updatedAtMs: Date.now() })\n}\n\n/**\n * Ends the customer's turn once the register has acted on their receipt\n * choice (AGL-3608): a display still on the receipt prompt says thank you,\n * and an answer holding a typed email address or phone number is dropped\n * from the state either way, so no contact detail outlives the sale on the\n * server doc a public screen reads.\n *\n * Conditional, in a transaction, because the receipt can be sent after the\n * cashier has started the next sale: a display already showing the next\n * customer's basket is left alone.\n */\nexport async function finishPosDisplayReceipt(hostId: string, registerId: string): Promise<void> {\n const firestore = firebaseAdmin.app().firestore()\n const ref = stateRef(hostId, registerId)\n const currency = await posDisplayCurrency(hostId)\n await firestore.runTransaction(async (transaction: any) => {\n const snapshot = await transaction.get(ref)\n if (!snapshot.exists) return\n const state = snapshot.data() as CommerceModel.PosDisplayState\n if (state.mode === 'receipt') {\n transaction.set(ref, {\n mode: 'thanks',\n updatedAtMs: Date.now(),\n currency,\n hostId,\n registerId,\n })\n return\n }\n if (state.response && (state.response.email || state.response.phone)) {\n const rest = { ...state }\n delete rest.response\n transaction.set(ref, rest)\n }\n })\n}\n\n/** Signs every display of a register out, and forgets its state. */\nexport async function revokePosDisplays(hostId: string, registerId: string): Promise<void> {\n const firestore = firebaseAdmin.app().firestore()\n const tokens = await firestore\n .collection(TOKENS)\n .where('hostId', '==', hostId)\n .where('registerId', '==', registerId)\n .limit(50)\n .get()\n await Promise.all(tokens.docs.map((doc: any) => doc.ref.delete()))\n await stateRef(hostId, registerId).delete().catch(() => undefined)\n}\n\nasync function registerExists(hostId: string, registerId: string): Promise<boolean> {\n if (!/^[A-Za-z0-9_-]{1,128}$/.test(registerId)) return false\n return (\n await firebaseAdmin\n .app()\n .firestore()\n .collection('hosts')\n .doc(hostId)\n .collection('registers')\n .doc(registerId)\n .get()\n ).exists\n}\n\n/** The store's name, logo and welcome line, for the idle and thank-you screens. */\nexport async function displayBranding(hostId: string) {\n const firestore = firebaseAdmin.app().firestore()\n const host = await firestore.collection('hosts').doc(hostId).get()\n const ownerOrg = await getOrgForHost(hostId).catch(() => null)\n const settings = posRegisterSettings(\n await getPluginConfig(ownerOrg?.orgId, 'commerce', { hostId }).catch(() => ({})),\n )\n return {\n name: String(host.get('displayName') ?? host.get('name') ?? '').slice(0, 80) || 'Welcome',\n logoUrl: resolveMediaSrc(host.get('logoUrl'), { hostId }) ?? null,\n logoDarkUrl: resolveMediaSrc(host.get('logoDarkUrl'), { hostId }) ?? null,\n message: settings.displayMessage || 'Welcome',\n }\n}\n\n/** The display token on a request, or ''. */\nexport function displayToken(req: PluginApiRequest, body: Record<string, any>): string {\n const header = String(req.headers['x-pos-display-token'] ?? '')\n return (header || String(body['token'] ?? '')).trim().slice(0, 128)\n}\n\n/** What a paired device's token opens. */\nexport interface PosDeviceToken {\n hostId: string\n registerId: string\n ref: any\n /**\n * A customer display, or a self-service kiosk (AGL-3623). A token minted\n * before kiosks existed has no mode and is a display.\n */\n mode: CommerceModel.PosDeviceMode\n /** The staff member whose pairing code opened this device. */\n createdBy: string\n /** The token document, for the caller that keeps device settings on it. */\n data: Record<string, any>\n}\n\n/** The register a live display token opens, or null. */\nexport async function resolveDisplayToken(token: string): Promise<PosDeviceToken | null> {\n if (!/^[A-Za-z0-9_-]{40,128}$/.test(token)) return null\n const ref = firebaseAdmin.app().firestore().collection(TOKENS).doc(sha256(token))\n const snapshot = await ref.get()\n if (!snapshot.exists) return null\n const hostId = String(snapshot.get('hostId') ?? '')\n const registerId = String(snapshot.get('registerId') ?? '')\n if (!hostId || !registerId) return null\n // A display whose register was removed is dead, even if its token row\n // somehow outlived the removal.\n if (!(await registerExists(hostId, registerId))) return null\n const lastSeen = Number(snapshot.get('lastSeenAtMs') ?? 0)\n if (Date.now() - lastSeen > 60_000) {\n await ref.set({ lastSeenAtMs: Date.now() }, { merge: true }).catch(() => undefined)\n }\n return {\n hostId,\n registerId,\n ref,\n mode: snapshot.get('mode') === 'kiosk' ? 'kiosk' : 'display',\n createdBy: String(snapshot.get('createdBy') ?? ''),\n data: (snapshot.data() ?? {}) as Record<string, any>,\n }\n}\n\n/**\n * Core's customer display verifier (AGL-4042, `plugin-customer-display-verifier`):\n * who a paired display is, for another plugin's server acting for the screen\n * it put there. The display's own token is the credential, so the pairing is\n * the authorization: a live CUSTOMER DISPLAY token (never a kiosk's) answers\n * the store it is paired to, the workspace that owns it, the plugin screen it\n * is showing now, and who put it there. Anything else answers `null`.\n */\nexport async function verifyPosCustomerDisplay(credential: string): Promise<{\n hostId: string\n orgId: string\n screen: CommerceModel.PosDisplayScreen | null\n shownBy: string | null\n} | null> {\n const display = await resolveDisplayToken(credential)\n if (!display || display.mode !== 'display') return null\n const owner = await getOrgForHost(display.hostId).catch(() => null)\n const orgId = String(owner?.org?.id ?? owner?.orgId ?? '')\n if (!orgId) return null\n const snapshot = await stateRef(display.hostId, display.registerId).get()\n const state = snapshot.exists ? (snapshot.data() as CommerceModel.PosDisplayState) : null\n const screen = state?.mode === 'screen' && state.screen ? state.screen : null\n return {\n hostId: display.hostId,\n orgId,\n screen,\n shownBy: screen && typeof state?.screenShownBy === 'string' ? state.screenShownBy : null,\n }\n}\n\n/** A token row's mode, `display` for one that predates kiosks. */\nfunction tokenMode(doc: any): CommerceModel.PosDeviceMode {\n return doc.get('mode') === 'kiosk' ? 'kiosk' : 'display'\n}\n\n/**\n * `POST /api/commerce/pos-display`.\n *\n * Staff (Firebase token + the register's gate): `pairing-code`, `push`,\n * `state`, `displays`, `revoke`.\n * Display (display token only): `pair`, `poll`, `respond`, `forget`.\n */\nexport const posDisplayHandler: PluginApiHandler = async (req, res) => {\n // The two polls are GETs: a read is not a console write, so a display and a\n // register asking once a second do not spend the console's write budget.\n const body = req.method === 'GET' ? posQueryBody(req) : posRequestBody(req)\n const action = String(body['action'] ?? '')\n if (\n !(req.method === 'POST' || (req.method === 'GET' && (action === 'poll' || action === 'state')))\n ) {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n res.setHeader('Cache-Control', 'no-store')\n try {\n switch (action) {\n case 'pair':\n return await pair(req, body, res)\n case 'poll':\n case 'respond':\n case 'forget': {\n const display = await resolveDisplayToken(displayToken(req, body))\n if (!display) return res.status(401).json({ error: 'This display is not paired.' })\n if (action === 'forget') {\n // A kiosk leaves kiosk mode behind a staff PIN (AGL-3623), through\n // `commerce/pos-kiosk`, never by a customer's tap here.\n if (display.mode === 'kiosk') {\n return res.status(403).json({ error: 'Ask a staff member to unlock this kiosk.' })\n }\n await display.ref.delete()\n return res.status(200).json({ ok: true })\n }\n // A kiosk is not the register's customer display (AGL-3623): the\n // basket the cashier is ringing up belongs to another customer.\n if (display.mode === 'kiosk') {\n return res.status(403).json({ error: 'This device is a self-service kiosk.' })\n }\n const snapshot = await stateRef(display.hostId, display.registerId).get()\n const state = snapshot.exists ? (snapshot.data() as CommerceModel.PosDisplayState) : null\n if (action === 'poll') {\n return res.status(200).json({\n state: CommerceModel.posDisplayPublicState(state, Date.now()),\n branding:\n body['branding'] === true || body['branding'] === 'true'\n ? await displayBranding(display.hostId)\n : undefined,\n })\n }\n const response = CommerceModel.sanitizePosDisplayResponse(state, body['response'], Date.now())\n if (!response) {\n return res.status(409).json({ error: 'That screen has moved on. Check the display.' })\n }\n await stateRef(display.hostId, display.registerId).set({ response }, { merge: true })\n return res.status(200).json({ ok: true })\n }\n case 'hardware-terms':\n case 'accept-hardware-terms': {\n // The terms of sale for a card reader sold here (AGL-4038), on the\n // screen the register put on this display: the display's own token,\n // never a staff session.\n if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })\n const display = await resolveDisplayToken(displayToken(req, body))\n if (!display) return res.status(401).json({ error: 'This display is not paired.' })\n if (display.mode === 'kiosk') return res.status(403).json({ error: 'This device is a self-service kiosk.' })\n return await hardwareTermsOnDisplay(req, display, body, action, res)\n }\n default:\n return await staffAction(req, body, action, res)\n }\n } catch (error) {\n console.error('[pos-display]', action, error)\n return res.status(500).json({ error: 'The customer display could not be updated' })\n }\n}\n\nasync function pair(\n req: PluginApiRequest,\n body: Record<string, any>,\n res: Parameters<PluginApiHandler>[1],\n) {\n const address = String(req.socket?.remoteAddress ?? '') || 'no-address'\n const rate = await consumeRateLimit(`pos-display-pair:${address}`, {\n limit: 10,\n windowMs: 10 * 60 * 1000,\n })\n if (!rate.allowed) {\n return res.status(429).json({ error: 'Too many tries. Wait a few minutes and try again.' })\n }\n const code = String(body['code'] ?? '').replace(/\\D/g, '')\n // The device asks for the kind of screen it is; the code decides. A kiosk\n // code opens a kiosk, and a display code never does (AGL-3623).\n const wanted: CommerceModel.PosDeviceMode = body['mode'] === 'kiosk' ? 'kiosk' : 'display'\n if (code.length !== 6) return res.status(400).json({ error: 'Enter the 6-digit code from the register.' })\n const firestore = firebaseAdmin.app().firestore()\n const pairingRef = firestore.collection(PAIRINGS).doc(sha256(code))\n const token = randomBytes(32).toString('base64url')\n // Spent in the same transaction that mints the token: a code opens one\n // display, once, and a second display racing the first gets nothing.\n const paired = await firestore.runTransaction(async (transaction: any) => {\n const snapshot = await transaction.get(pairingRef)\n if (!snapshot.exists) return null\n const expiresAtMs = Number(snapshot.get('expiresAtMs') ?? 0)\n transaction.delete(pairingRef)\n if (!(expiresAtMs > Date.now())) return null\n const hostId = String(snapshot.get('hostId') ?? '')\n const registerId = String(snapshot.get('registerId') ?? '')\n const mode: CommerceModel.PosDeviceMode = snapshot.get('mode') === 'kiosk' ? 'kiosk' : 'display'\n // The wrong kind of screen leaves the code spent: the register shows a\n // new one for the device it meant.\n if (mode !== wanted) return { mismatch: mode }\n transaction.set(firestore.collection(TOKENS).doc(sha256(token)), {\n hostId,\n registerId,\n mode,\n createdAtMs: Date.now(),\n createdBy: String(snapshot.get('createdBy') ?? ''),\n lastSeenAtMs: Date.now(),\n label:\n String(body['label'] ?? '').slice(0, 60) ||\n (mode === 'kiosk' ? 'Self-service kiosk' : 'Customer display'),\n })\n return { hostId, registerId, mode }\n })\n if (!paired) {\n return res.status(404).json({ error: 'That code is not valid. Show a new code on the register.' })\n }\n if ('mismatch' in paired) {\n return res.status(409).json({\n error:\n paired.mismatch === 'kiosk'\n ? 'That code is for a self-service kiosk. Open the kiosk address, or show a display code on the register.'\n : 'That code is for a customer display. Choose Self-service kiosk on the register and show a new code.',\n })\n }\n return res\n .status(200)\n .json({ token, mode: paired.mode, branding: await displayBranding(paired.hostId) })\n}\n\nasync function staffAction(\n req: PluginApiRequest,\n body: Record<string, any>,\n action: string,\n res: Parameters<PluginApiHandler>[1],\n) {\n const hostId = String(body['hostId'] ?? '')\n // Pairing a customer display and revoking one is setting the register up\n // (AGL-4047); showing a sale on a paired display is part of the sale.\n const gate = await authorizePosStaff(\n req,\n hostId,\n action === 'pairing-code' || action === 'revoke' ? 'posDevices' : undefined,\n )\n if ('error' in gate) return res.status(gate.status).json({ error: gate.error })\n const registerId = String(body['registerId'] ?? '')\n if (!(await registerExists(hostId, registerId))) {\n return res.status(404).json({ error: 'Unknown register' })\n }\n const firestore = firebaseAdmin.app().firestore()\n switch (action) {\n case 'pairing-code': {\n for (let attempt = 0; attempt < 8; attempt++) {\n const code = String(randomInt(0, 1_000_000)).padStart(6, '0')\n const ref = firestore.collection(PAIRINGS).doc(sha256(code))\n const expiresAtMs = Date.now() + CommerceModel.POS_DISPLAY_PAIRING_TTL_MS\n const claimed = await firestore.runTransaction(async (transaction: any) => {\n const existing = await transaction.get(ref)\n // A live code another register is showing is never overwritten.\n if (existing.exists && Number(existing.get('expiresAtMs') ?? 0) > Date.now()) return false\n transaction.set(ref, {\n hostId,\n registerId,\n expiresAtMs,\n createdBy: gate.staff.uid,\n // A kiosk code (AGL-3623) opens a self-service kiosk instead.\n mode: body['mode'] === 'kiosk' ? 'kiosk' : 'display',\n })\n return true\n })\n if (claimed) return res.status(200).json({ code, expiresAtMs })\n }\n return res.status(503).json({ error: 'Could not make a code. Try again.' })\n }\n case 'push': {\n // Another plugin's screen (AGL-4042) is checked by core's seam: a\n // declared plugin page and a few short parameters, nothing else.\n const state = CommerceModel.sanitizePosDisplayState(body['state'], Date.now(), {\n screen: sanitizeCustomerDisplayScreen,\n })\n // Who put a plugin's screen there (AGL-4042), from the session, so the\n // screen's plugin can name them through core's display verifier.\n if (state.mode === 'screen') state.screenShownBy = gate.staff.uid\n // \"Text\" is never offered on a screen when the store cannot send one.\n if (state.receipt && !pluginSmsAvailable()) {\n const channels = state.receipt.channels.filter((channel) => channel !== 'sms')\n state.receipt.channels = channels.length ? channels : ['print', 'none']\n }\n await writePosDisplayState(hostId, registerId, state)\n return res.status(200).json({ ok: true, promptId: state.promptId ?? null })\n }\n case 'close-screen': {\n // A plugin takes its own screen off the display (AGL-4042, core's\n // `CustomerDisplayHost.close`): only while that plugin's screen is\n // the one showing, so it never clears a sale the register moved on to.\n const pluginId = String(body['pluginId'] ?? '')\n const snapshot = await stateRef(hostId, registerId).get()\n const current = snapshot.exists ? (snapshot.data() as CommerceModel.PosDisplayState) : null\n const showing = current?.mode === 'screen' && current.screen?.pluginId === pluginId\n if (showing) await writePosDisplayState(hostId, registerId, { mode: 'idle', updatedAtMs: Date.now() })\n return res.status(200).json({ ok: true, closed: showing })\n }\n case 'state': {\n const snapshot = await stateRef(hostId, registerId).get()\n const state = snapshot.exists ? (snapshot.data() as CommerceModel.PosDisplayState) : null\n const displays = await firestore\n .collection(TOKENS)\n .where('hostId', '==', hostId)\n .where('registerId', '==', registerId)\n .limit(10)\n .get()\n return res.status(200).json({\n state,\n // A display that polled within the last two minutes is \"connected\".\n // A kiosk is not the register's display (AGL-3623).\n connected: displays.docs.some(\n (doc: any) =>\n tokenMode(doc) === 'display' && Date.now() - Number(doc.get('lastSeenAtMs') ?? 0) < 120_000,\n ),\n })\n }\n case 'displays': {\n const displays = await firestore\n .collection(TOKENS)\n .where('hostId', '==', hostId)\n .where('registerId', '==', registerId)\n .limit(10)\n .get()\n return res.status(200).json({\n displays: displays.docs.map((doc: any) => ({\n id: doc.id.slice(0, 16),\n label: String(doc.get('label') ?? 'Customer display'),\n mode: tokenMode(doc),\n createdAtMs: Number(doc.get('createdAtMs') ?? 0),\n lastSeenAtMs: Number(doc.get('lastSeenAtMs') ?? 0),\n })),\n })\n }\n case 'revoke': {\n const prefix = String(body['displayId'] ?? '')\n const displays = await firestore\n .collection(TOKENS)\n .where('hostId', '==', hostId)\n .where('registerId', '==', registerId)\n .limit(10)\n .get()\n const doomed = displays.docs.filter(\n (doc: any) => prefix === '*' || (prefix.length === 16 && doc.id.startsWith(prefix)),\n )\n await Promise.all(doomed.map((doc: any) => doc.ref.delete()))\n return res.status(200).json({ revoked: doomed.length })\n }\n default:\n return res.status(400).json({ error: 'Unknown action' })\n }\n}\n\n/** The page the terms of sale open at on a display, beneath `/kiosk/commerce`. */\nexport const POS_HARDWARE_TERMS_PAGE_PATH = '/hardware-terms'\n\n/**\n * The terms of sale on a customer display (AGL-4038): read them, or accept\n * them, for the sale the register put on THIS display — the screen must be\n * showing, for this register, with this sale's id, so a display can neither\n * read nor accept for another sale. Accepting records it and takes the\n * screen off, so the display shows the register again.\n */\nasync function hardwareTermsOnDisplay(\n req: PluginApiRequest,\n display: PosDeviceToken,\n body: Record<string, any>,\n action: 'hardware-terms' | 'accept-hardware-terms',\n res: Parameters<PluginApiHandler>[1],\n) {\n const config = parsePosHardwareInPersonConfig(process.env)\n if (!config || display.hostId !== config.sellerHostId) {\n return res.status(404).json({ error: 'Card reader sales are not available here.' })\n }\n const order = String(body['order'] ?? '')\n const snapshot = await stateRef(display.hostId, display.registerId).get()\n const state = snapshot.exists ? (snapshot.data() as CommerceModel.PosDisplayState) : null\n const showing =\n state?.mode === 'screen' &&\n state.screen?.pluginId === BUNDLE_ID &&\n state.screen?.path === POS_HARDWARE_TERMS_PAGE_PATH &&\n state.screen?.params?.['order'] === order\n if (!showing) return res.status(409).json({ error: 'That screen has moved on. Check the display.' })\n const terms = await import('./pos-hardware-terms')\n try {\n if (action === 'hardware-terms') {\n return res.status(200).json({ ...terms.posHardwareTermsView(), ...(await terms.posHardwareTermsSale(config, order)) })\n }\n if (body['accept'] !== true) return res.status(400).json({ error: 'Tick the box to accept the terms of sale.' })\n const acceptance = await terms.recordPosHardwareTermsAcceptance({\n config,\n registerOrderId: order,\n method: 'display',\n staffUid: null,\n ...terms.posHardwareTermsDevice(req.headers as Record<string, unknown>),\n })\n await writePosDisplayState(display.hostId, display.registerId, { mode: 'idle', updatedAtMs: Date.now() })\n return res.status(200).json({ ok: true, acceptance })\n } catch (error) {\n if (error instanceof terms.PosHardwareTermsRefusal) return res.status(error.status).json({ error: error.message })\n throw error\n }\n}\n\n"],"names":["createHash","randomBytes","randomInt","consumeRateLimit","firebaseAdmin","getPluginConfig","getOrgForHost","resolveMediaSrc","sanitizeCustomerDisplayScreen","pluginSmsAvailable","CommerceModel","BUNDLE_ID","parsePosHardwareInPersonConfig","posRegisterSettings","authorizePosStaff","posQueryBody","posRequestBody","POS_CURRENCY","PAIRINGS","TOKENS","STATES","sha256","value","update","digest","posDisplayStateId","hostId","registerId","stateRef","app","firestore","collection","doc","posDisplayCurrency","snapshot","get","catch","chosen","String","exists","trim","toLowerCase","test","writePosDisplayState","state","set","currency","resetPosDisplay","mode","updatedAtMs","Date","now","finishPosDisplayReceipt","ref","runTransaction","transaction","data","response","email","phone","rest","revokePosDisplays","tokens","where","limit","Promise","all","docs","map","delete","undefined","registerExists","displayBranding","host","ownerOrg","settings","orgId","name","slice","logoUrl","logoDarkUrl","message","displayMessage","displayToken","req","body","header","headers","resolveDisplayToken","token","lastSeen","Number","lastSeenAtMs","merge","createdBy","verifyPosCustomerDisplay","credential","owner","display","org","id","screen","shownBy","screenShownBy","tokenMode","posDisplayHandler","res","method","action","status","json","error","setHeader","pair","ok","posDisplayPublicState","branding","sanitizePosDisplayResponse","hardwareTermsOnDisplay","staffAction","console","address","socket","remoteAddress","rate","windowMs","allowed","code","replace","wanted","length","pairingRef","toString","paired","expiresAtMs","mismatch","createdAtMs","label","gate","attempt","padStart","POS_DISPLAY_PAIRING_TTL_MS","claimed","existing","staff","uid","sanitizePosDisplayState","receipt","channels","filter","channel","promptId","current","pluginId","showing","closed","displays","connected","some","prefix","doomed","startsWith","revoked","POS_HARDWARE_TERMS_PAGE_PATH","config","process","env","sellerHostId","order","path","params","terms","posHardwareTermsView","posHardwareTermsSale","acceptance","recordPosHardwareTermsAcceptance","registerOrderId","staffUid","posHardwareTermsDevice","PosHardwareTermsRefusal"],"mappings":"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"}
@@ -26,7 +26,7 @@ declare function staffView(id: string, order: PosHardwareOrder): {
26
26
  lines: import("../model/pos-hardware").PosHardwareLine[];
27
27
  subtotalCents: number;
28
28
  shipping: {
29
- method: import("../model/pos-hardware").PosHardwareShippingMethod;
29
+ method: import("../model/pos-hardware").PosHardwareOrderShippingMethod;
30
30
  label: string;
31
31
  cents: number;
32
32
  name: string | null;
@@ -44,6 +44,15 @@ declare function staffView(id: string, order: PosHardwareOrder): {
44
44
  refundPending: boolean;
45
45
  createdAtMs: number;
46
46
  updatedAtMs: number;
47
+ source: import("../model/pos-hardware").PosHardwareOrderSource;
48
+ discountCents: number;
49
+ posSale: import("../model/pos-hardware").PosHardwareRegisterSale;
50
+ paidTo: import("../model/pos-hardware").PosHardwarePaidTo;
51
+ attachment: import("../model/pos-hardware").PosHardwareAttachment;
52
+ units: import("../model/pos-hardware").PosHardwareUnit[];
53
+ refundedCents: number;
54
+ refunds: import("../model/pos-hardware").PosHardwareRefund[];
55
+ returnRequest: import("../model/pos-hardware").PosHardwareReturnRequest;
47
56
  };
48
57
  export type StaffHardwareOrderView = ReturnType<typeof staffView>;
49
58
  declare function handler(request: Request): Promise<Response>;