@aglyn/plugins-commerce 1.0.0-beta.229 → 1.0.0-beta.231
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.
- package/package.json +13 -13
- package/src/index.d.ts +0 -1
- package/src/index.js +0 -1
- package/src/index.js.map +1 -1
- package/src/lib/barcode/barcode-decode.d.ts +71 -0
- package/src/lib/barcode/barcode-decode.js +498 -0
- package/src/lib/barcode/barcode-decode.js.map +1 -0
- package/src/lib/barcode/barcode-encode.d.ts +44 -0
- package/src/lib/barcode/barcode-encode.js +138 -0
- package/src/lib/barcode/barcode-encode.js.map +1 -0
- package/src/lib/barcode/barcode-scanner.component.d.ts +23 -0
- package/src/lib/barcode/barcode-scanner.component.js +260 -0
- package/src/lib/barcode/barcode-scanner.component.js.map +1 -0
- package/src/lib/barcode/scan-button.component.d.ts +10 -0
- package/src/lib/barcode/scan-button.component.js +62 -0
- package/src/lib/barcode/scan-button.component.js.map +1 -0
- package/src/lib/barcode/scanner-wedge.d.ts +35 -0
- package/src/lib/barcode/scanner-wedge.js +108 -0
- package/src/lib/barcode/scanner-wedge.js.map +1 -0
- package/src/lib/components/account.js +10 -1
- package/src/lib/components/account.js.map +1 -1
- package/src/lib/components/cart-extras.d.ts +45 -0
- package/src/lib/components/cart-extras.js +127 -0
- package/src/lib/components/cart-extras.js.map +1 -0
- package/src/lib/components/cart.js +82 -15
- package/src/lib/components/cart.js.map +1 -1
- package/src/lib/components/checkout-return-notice.d.ts +26 -0
- package/src/lib/components/checkout-return-notice.js +48 -0
- package/src/lib/components/checkout-return-notice.js.map +1 -0
- package/src/lib/components/commerce-console-page.js +124 -0
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/commerce-console-sections.d.ts +1 -1
- package/src/lib/components/commerce-console-sections.js +4 -0
- package/src/lib/components/commerce-console-sections.js.map +1 -1
- package/src/lib/components/console/bulk-fulfill.d.ts +44 -0
- package/src/lib/components/console/bulk-fulfill.js +84 -0
- package/src/lib/components/console/bulk-fulfill.js.map +1 -0
- package/src/lib/components/console/customer-notifications-card.component.d.ts +19 -0
- package/src/lib/components/console/customer-notifications-card.component.js +149 -0
- package/src/lib/components/console/customer-notifications-card.component.js.map +1 -0
- package/src/lib/components/console/host-orders-card.component.js +84 -5
- package/src/lib/components/console/host-orders-card.component.js.map +1 -1
- package/src/lib/components/console/locations-card.component.js +164 -57
- package/src/lib/components/console/locations-card.component.js.map +1 -1
- package/src/lib/components/console/order-detail-dialog.component.js +209 -61
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
- package/src/lib/components/console/order-fulfillment-panel.component.d.ts +48 -0
- package/src/lib/components/console/order-fulfillment-panel.component.js +542 -0
- package/src/lib/components/console/order-fulfillment-panel.component.js.map +1 -0
- package/src/lib/components/console/order-invoice.component.d.ts +33 -0
- package/src/lib/components/console/order-invoice.component.js +81 -0
- package/src/lib/components/console/order-invoice.component.js.map +1 -0
- package/src/lib/components/console/order-receipt-resend.component.d.ts +21 -0
- package/src/lib/components/console/order-receipt-resend.component.js +203 -0
- package/src/lib/components/console/order-receipt-resend.component.js.map +1 -0
- package/src/lib/components/console/order-returns.component.d.ts +36 -0
- package/src/lib/components/console/order-returns.component.js +142 -0
- package/src/lib/components/console/order-returns.component.js.map +1 -0
- package/src/lib/components/console/order-shipping-actions.component.d.ts +54 -0
- package/src/lib/components/console/order-shipping-actions.component.js +149 -0
- package/src/lib/components/console/order-shipping-actions.component.js.map +1 -0
- package/src/lib/components/console/order-webhooks-card.component.d.ts +50 -0
- package/src/lib/components/console/order-webhooks-card.component.js +623 -0
- package/src/lib/components/console/order-webhooks-card.component.js.map +1 -0
- package/src/lib/components/console/order-zones.d.ts +155 -0
- package/src/lib/components/console/order-zones.js +40 -0
- package/src/lib/components/console/order-zones.js.map +1 -0
- package/src/lib/components/console/payment-methods-card.component.d.ts +67 -0
- package/src/lib/components/console/payment-methods-card.component.js +395 -0
- package/src/lib/components/console/payment-methods-card.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-api.d.ts +124 -0
- package/src/lib/components/console/pos/pos-api.js +101 -0
- package/src/lib/components/console/pos/pos-api.js.map +1 -0
- package/src/lib/components/console/pos/pos-cart-panel.component.d.ts +36 -0
- package/src/lib/components/console/pos/pos-cart-panel.component.js +160 -0
- package/src/lib/components/console/pos/pos-cart-panel.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-item-dialog.component.d.ts +39 -0
- package/src/lib/components/console/pos/pos-item-dialog.component.js +352 -0
- package/src/lib/components/console/pos/pos-item-dialog.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-product-grid.component.d.ts +47 -0
- package/src/lib/components/console/pos/pos-product-grid.component.js +272 -0
- package/src/lib/components/console/pos/pos-product-grid.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-receipt-panel.component.d.ts +27 -0
- package/src/lib/components/console/pos/pos-receipt-panel.component.js +282 -0
- package/src/lib/components/console/pos/pos-receipt-panel.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-tender-dialogs.component.d.ts +53 -0
- package/src/lib/components/console/pos/pos-tender-dialogs.component.js +445 -0
- package/src/lib/components/console/pos/pos-tender-dialogs.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-tender-panel.component.d.ts +31 -0
- package/src/lib/components/console/pos/pos-tender-panel.component.js +640 -0
- package/src/lib/components/console/pos/pos-tender-panel.component.js.map +1 -0
- package/src/lib/components/console/pos/use-pos-display.d.ts +43 -0
- package/src/lib/components/console/pos/use-pos-display.js +161 -0
- package/src/lib/components/console/pos/use-pos-display.js.map +1 -0
- package/src/lib/components/console/pos-devices-card.component.d.ts +14 -0
- package/src/lib/components/console/pos-devices-card.component.js +546 -0
- package/src/lib/components/console/pos-devices-card.component.js.map +1 -0
- package/src/lib/components/console/pos-display/brand-screen.d.ts +33 -0
- package/src/lib/components/console/pos-display/brand-screen.js +85 -0
- package/src/lib/components/console/pos-display/brand-screen.js.map +1 -0
- package/src/lib/components/console/pos-display/cart-screen.d.ts +29 -0
- package/src/lib/components/console/pos-display/cart-screen.js +166 -0
- package/src/lib/components/console/pos-display/cart-screen.js.map +1 -0
- package/src/lib/components/console/pos-display/pairing-screen.d.ts +24 -0
- package/src/lib/components/console/pos-display/pairing-screen.js +127 -0
- package/src/lib/components/console/pos-display/pairing-screen.js.map +1 -0
- package/src/lib/components/console/pos-display/pos-display-api.d.ts +90 -0
- package/src/lib/components/console/pos-display/pos-display-api.js +140 -0
- package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -0
- package/src/lib/components/console/pos-display/receipt-screen.d.ts +35 -0
- package/src/lib/components/console/pos-display/receipt-screen.js +200 -0
- package/src/lib/components/console/pos-display/receipt-screen.js.map +1 -0
- package/src/lib/components/console/pos-display/tip-screen.d.ts +36 -0
- package/src/lib/components/console/pos-display/tip-screen.js +211 -0
- package/src/lib/components/console/pos-display/tip-screen.js.map +1 -0
- package/src/lib/components/console/pos-display-page.component.d.ts +16 -0
- package/src/lib/components/console/pos-display-page.component.js +407 -0
- package/src/lib/components/console/pos-display-page.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-customer-lookup.component.d.ts +40 -0
- package/src/lib/components/console/pos-ops/pos-customer-lookup.component.js +289 -0
- package/src/lib/components/console/pos-ops/pos-customer-lookup.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-last-receipt.component.d.ts +34 -0
- package/src/lib/components/console/pos-ops/pos-last-receipt.component.js +61 -0
- package/src/lib/components/console/pos-ops/pos-last-receipt.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.d.ts +38 -0
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js +129 -0
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-ops-api.d.ts +37 -0
- package/src/lib/components/console/pos-ops/pos-ops-api.js +60 -0
- package/src/lib/components/console/pos-ops/pos-ops-api.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-pin-pad.component.d.ts +48 -0
- package/src/lib/components/console/pos-ops/pos-pin-pad.component.js +220 -0
- package/src/lib/components/console/pos-ops/pos-pin-pad.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-receipt-actions.component.d.ts +63 -0
- package/src/lib/components/console/pos-ops/pos-receipt-actions.component.js +186 -0
- package/src/lib/components/console/pos-ops/pos-receipt-actions.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-receipt.d.ts +39 -0
- package/src/lib/components/console/pos-ops/pos-receipt.js +182 -0
- package/src/lib/components/console/pos-ops/pos-receipt.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-return-dialog.component.d.ts +40 -0
- package/src/lib/components/console/pos-ops/pos-return-dialog.component.js +465 -0
- package/src/lib/components/console/pos-ops/pos-return-dialog.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-shift-history-card.component.d.ts +29 -0
- package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js +253 -0
- package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.d.ts +34 -0
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.js +494 -0
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-shift-report.component.d.ts +37 -0
- package/src/lib/components/console/pos-ops/pos-shift-report.component.js +102 -0
- package/src/lib/components/console/pos-ops/pos-shift-report.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-staff-pins-card.component.d.ts +30 -0
- package/src/lib/components/console/pos-ops/pos-staff-pins-card.component.js +277 -0
- package/src/lib/components/console/pos-ops/pos-staff-pins-card.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/register-ops.d.ts +28 -0
- package/src/lib/components/console/pos-ops/register-ops.js +28 -0
- package/src/lib/components/console/pos-ops/register-ops.js.map +1 -0
- package/src/lib/components/console/pos-ops/use-pos-cashier.d.ts +46 -0
- package/src/lib/components/console/pos-ops/use-pos-cashier.js +128 -0
- package/src/lib/components/console/pos-ops/use-pos-cashier.js.map +1 -0
- package/src/lib/components/console/pos-ops/use-pos-sale-receipt.d.ts +36 -0
- package/src/lib/components/console/pos-ops/use-pos-sale-receipt.js +64 -0
- package/src/lib/components/console/pos-ops/use-pos-sale-receipt.js.map +1 -0
- package/src/lib/components/console/pos-page.component.d.ts +13 -5
- package/src/lib/components/console/pos-page.component.js +729 -657
- package/src/lib/components/console/pos-page.component.js.map +1 -1
- package/src/lib/components/console/product-editor-dialog.component.js +51 -7
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/product-labels-dialog.component.d.ts +13 -0
- package/src/lib/components/console/product-labels-dialog.component.js +197 -0
- package/src/lib/components/console/product-labels-dialog.component.js.map +1 -0
- package/src/lib/components/console/product-register-fields.component.d.ts +19 -0
- package/src/lib/components/console/product-register-fields.component.js +241 -0
- package/src/lib/components/console/product-register-fields.component.js.map +1 -0
- package/src/lib/components/console/product-zones.d.ts +58 -2
- package/src/lib/components/console/product-zones.js +10 -2
- package/src/lib/components/console/product-zones.js.map +1 -1
- package/src/lib/components/console/products-hub-card.component.js +51 -11
- package/src/lib/components/console/products-hub-card.component.js.map +1 -1
- package/src/lib/components/console/register-hardware-card.component.d.ts +33 -0
- package/src/lib/components/console/register-hardware-card.component.js +826 -0
- package/src/lib/components/console/register-hardware-card.component.js.map +1 -0
- package/src/lib/components/console/registers-card.component.js +24 -5
- package/src/lib/components/console/registers-card.component.js.map +1 -1
- package/src/lib/components/console/return-actions.d.ts +38 -0
- package/src/lib/components/console/return-actions.js +76 -0
- package/src/lib/components/console/return-actions.js.map +1 -0
- package/src/lib/components/console/return-detail-dialog.component.d.ts +34 -0
- package/src/lib/components/console/return-detail-dialog.component.js +718 -0
- package/src/lib/components/console/return-detail-dialog.component.js.map +1 -0
- package/src/lib/components/console/return-settings-card.component.d.ts +34 -0
- package/src/lib/components/console/return-settings-card.component.js +195 -0
- package/src/lib/components/console/return-settings-card.component.js.map +1 -0
- package/src/lib/components/console/return-zones.d.ts +87 -0
- package/src/lib/components/console/return-zones.js +31 -0
- package/src/lib/components/console/return-zones.js.map +1 -0
- package/src/lib/components/console/returns-card.component.d.ts +45 -0
- package/src/lib/components/console/returns-card.component.js +159 -0
- package/src/lib/components/console/returns-card.component.js.map +1 -0
- package/src/lib/components/console/shipping-settings-card.component.js +161 -5
- package/src/lib/components/console/shipping-settings-card.component.js.map +1 -1
- package/src/lib/components/console/shippingeasy-card.component.d.ts +59 -0
- package/src/lib/components/console/shippingeasy-card.component.js +378 -0
- package/src/lib/components/console/shippingeasy-card.component.js.map +1 -0
- package/src/lib/components/console/shipstation-card.component.d.ts +35 -0
- package/src/lib/components/console/shipstation-card.component.js +345 -0
- package/src/lib/components/console/shipstation-card.component.js.map +1 -0
- package/src/lib/components/console/start-return-dialog.component.d.ts +40 -0
- package/src/lib/components/console/start-return-dialog.component.js +243 -0
- package/src/lib/components/console/start-return-dialog.component.js.map +1 -0
- package/src/lib/components/console/stock-movements-card.component.js +2 -1
- package/src/lib/components/console/stock-movements-card.component.js.map +1 -1
- package/src/lib/components/console/store-settings-card.component.js +2 -66
- package/src/lib/components/console/store-settings-card.component.js.map +1 -1
- package/src/lib/components/console/store-zones.d.ts +42 -0
- package/src/lib/components/console/store-zones.js +39 -0
- package/src/lib/components/console/store-zones.js.map +1 -0
- package/src/lib/components/order-status.d.ts +36 -0
- package/src/lib/components/order-status.js +502 -0
- package/src/lib/components/order-status.js.map +1 -0
- package/src/lib/components/product-detail.js +44 -2
- package/src/lib/components/product-detail.js.map +1 -1
- package/src/lib/components/return-request.d.ts +32 -0
- package/src/lib/components/return-request.js +576 -0
- package/src/lib/components/return-request.js.map +1 -0
- package/src/lib/components/storefront-payment-appearance.d.ts +32 -0
- package/src/lib/components/storefront-payment-appearance.js +114 -0
- package/src/lib/components/storefront-payment-appearance.js.map +1 -0
- package/src/lib/components/storefront-payment-element.d.ts +57 -1
- package/src/lib/components/storefront-payment-element.js +332 -33
- package/src/lib/components/storefront-payment-element.js.map +1 -1
- package/src/lib/constants/order-status.d.ts +22 -0
- package/src/lib/constants/order-status.js +22 -0
- package/src/lib/constants/order-status.js.map +1 -0
- package/src/lib/constants/return-request.d.ts +27 -0
- package/src/lib/constants/return-request.js +32 -0
- package/src/lib/constants/return-request.js.map +1 -0
- package/src/lib/constants/stock-movement-query.js +2 -1
- package/src/lib/constants/stock-movement-query.js.map +1 -1
- package/src/lib/declarations.console-server.js +9 -0
- package/src/lib/declarations.console-server.js.map +1 -1
- package/src/lib/declarations.server.d.ts +2 -1
- package/src/lib/declarations.server.js +47 -1
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/model/buyer-notifications.d.ts +59 -0
- package/src/lib/model/buyer-notifications.js +97 -0
- package/src/lib/model/buyer-notifications.js.map +1 -0
- package/src/lib/model/commerce-orders.d.ts +127 -1
- package/src/lib/model/commerce-orders.js +24 -15
- package/src/lib/model/commerce-orders.js.map +1 -1
- package/src/lib/model/commerce-payment-methods.d.ts +146 -0
- package/src/lib/model/commerce-payment-methods.js +247 -0
- package/src/lib/model/commerce-payment-methods.js.map +1 -0
- package/src/lib/model/commerce-pos-ops.d.ts +437 -0
- package/src/lib/model/commerce-pos-ops.js +721 -0
- package/src/lib/model/commerce-pos-ops.js.map +1 -0
- package/src/lib/model/commerce-pos.d.ts +263 -0
- package/src/lib/model/commerce-pos.js +375 -0
- package/src/lib/model/commerce-pos.js.map +1 -0
- package/src/lib/model/commerce-printers.d.ts +211 -0
- package/src/lib/model/commerce-printers.js +181 -0
- package/src/lib/model/commerce-printers.js.map +1 -0
- package/src/lib/model/commerce-receipt.d.ts +97 -0
- package/src/lib/model/commerce-receipt.js +180 -0
- package/src/lib/model/commerce-receipt.js.map +1 -0
- package/src/lib/model/commerce-returns.d.ts +207 -0
- package/src/lib/model/commerce-returns.js +300 -0
- package/src/lib/model/commerce-returns.js.map +1 -0
- package/src/lib/model/commerce-shipping.d.ts +44 -1
- package/src/lib/model/commerce-shipping.js +53 -9
- package/src/lib/model/commerce-shipping.js.map +1 -1
- package/src/lib/model/commerce-tax-engine.d.ts +90 -0
- package/src/lib/model/commerce-tax-engine.js +129 -0
- package/src/lib/model/commerce-tax-engine.js.map +1 -0
- package/src/lib/model/commerce.d.ts +88 -2
- package/src/lib/model/commerce.js +89 -1
- package/src/lib/model/commerce.js.map +1 -1
- package/src/lib/model/index.d.ts +15 -0
- package/src/lib/model/index.js +15 -0
- package/src/lib/model/index.js.map +1 -1
- package/src/lib/model/order-events.d.ts +154 -0
- package/src/lib/model/order-events.js +153 -0
- package/src/lib/model/order-events.js.map +1 -0
- package/src/lib/model/order-fulfillment.d.ts +117 -0
- package/src/lib/model/order-fulfillment.js +217 -0
- package/src/lib/model/order-fulfillment.js.map +1 -0
- package/src/lib/model/order-history.d.ts +58 -0
- package/src/lib/model/order-history.js +22 -0
- package/src/lib/model/order-history.js.map +1 -0
- package/src/lib/model/order-list-fields.d.ts +9 -1
- package/src/lib/model/order-list-fields.js +7 -1
- package/src/lib/model/order-list-fields.js.map +1 -1
- package/src/lib/model/order-shipping-export.d.ts +91 -0
- package/src/lib/model/order-shipping-export.js +192 -0
- package/src/lib/model/order-shipping-export.js.map +1 -0
- package/src/lib/model/order-status-view.d.ts +103 -0
- package/src/lib/model/order-status-view.js +156 -0
- package/src/lib/model/order-status-view.js.map +1 -0
- package/src/lib/model/order-webhooks.d.ts +142 -0
- package/src/lib/model/order-webhooks.js +91 -0
- package/src/lib/model/order-webhooks.js.map +1 -0
- package/src/lib/model/product-channel.d.ts +56 -0
- package/src/lib/model/product-channel.js +86 -0
- package/src/lib/model/product-channel.js.map +1 -0
- package/src/lib/model/product-modifiers.d.ts +80 -0
- package/src/lib/model/product-modifiers.js +140 -0
- package/src/lib/model/product-modifiers.js.map +1 -0
- package/src/lib/model/shippingeasy.d.ts +94 -0
- package/src/lib/model/shippingeasy.js +267 -0
- package/src/lib/model/shippingeasy.js.map +1 -0
- package/src/lib/model/shipstation.d.ts +125 -0
- package/src/lib/model/shipstation.js +399 -0
- package/src/lib/model/shipstation.js.map +1 -0
- package/src/lib/model/smart-collection-reads.d.ts +32 -0
- package/src/lib/model/smart-collection-reads.js +63 -0
- package/src/lib/model/smart-collection-reads.js.map +1 -0
- package/src/lib/model/tracking-url.d.ts +74 -0
- package/src/lib/model/tracking-url.js +159 -0
- package/src/lib/model/tracking-url.js.map +1 -0
- package/src/lib/plugin-config.d.ts +13 -0
- package/src/lib/plugin-config.js +77 -5
- package/src/lib/plugin-config.js.map +1 -1
- package/src/lib/plugin.js +23 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/pos-ops-config.d.ts +39 -0
- package/src/lib/pos-ops-config.js +88 -0
- package/src/lib/pos-ops-config.js.map +1 -0
- package/src/lib/printing/print-document.d.ts +106 -0
- package/src/lib/printing/print-document.js +464 -0
- package/src/lib/printing/print-document.js.map +1 -0
- package/src/lib/printing/product-labels.d.ts +58 -0
- package/src/lib/printing/product-labels.js +116 -0
- package/src/lib/printing/product-labels.js.map +1 -0
- package/src/lib/printing/render-epson.d.ts +57 -0
- package/src/lib/printing/render-epson.js +135 -0
- package/src/lib/printing/render-epson.js.map +1 -0
- package/src/lib/printing/render-star.d.ts +45 -0
- package/src/lib/printing/render-star.js +100 -0
- package/src/lib/printing/render-star.js.map +1 -0
- package/src/lib/printing/render-text.d.ts +25 -0
- package/src/lib/printing/render-text.js +53 -0
- package/src/lib/printing/render-text.js.map +1 -0
- package/src/lib/server/api-v1/openapi.js +27 -4
- package/src/lib/server/api-v1/openapi.js.map +1 -1
- package/src/lib/server/api-v1/order-view.d.ts +67 -0
- package/src/lib/server/api-v1/order-view.js +120 -0
- package/src/lib/server/api-v1/order-view.js.map +1 -0
- package/src/lib/server/api-v1/orders-and-products.js +58 -65
- package/src/lib/server/api-v1/orders-and-products.js.map +1 -1
- package/src/lib/server/billing-webhook.js +135 -28
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/cancel-order.js +29 -0
- package/src/lib/server/cancel-order.js.map +1 -1
- package/src/lib/server/carrier-rates-availability.d.ts +26 -0
- package/src/lib/server/carrier-rates-availability.js +76 -0
- package/src/lib/server/carrier-rates-availability.js.map +1 -0
- package/src/lib/server/carrier-shipping.d.ts +84 -0
- package/src/lib/server/carrier-shipping.js +135 -0
- package/src/lib/server/carrier-shipping.js.map +1 -0
- package/src/lib/server/cart-checkout.d.ts +2 -0
- package/src/lib/server/cart-checkout.js +226 -22
- package/src/lib/server/cart-checkout.js.map +1 -1
- package/src/lib/server/checkout-extras.d.ts +64 -0
- package/src/lib/server/checkout-extras.js +157 -0
- package/src/lib/server/checkout-extras.js.map +1 -0
- package/src/lib/server/{feed.d.ts → checkout-status.d.ts} +2 -7
- package/src/lib/server/checkout-status.js +111 -0
- package/src/lib/server/checkout-status.js.map +1 -0
- package/src/lib/server/checkout.js +86 -9
- package/src/lib/server/checkout.js.map +1 -1
- package/src/lib/server/draft-order.js +34 -5
- package/src/lib/server/draft-order.js.map +1 -1
- package/src/lib/server/fulfill-order.d.ts +127 -10
- package/src/lib/server/fulfill-order.js +451 -49
- package/src/lib/server/fulfill-order.js.map +1 -1
- package/src/lib/server/legacy-feed.d.ts +28 -0
- package/src/lib/server/legacy-feed.js +52 -0
- package/src/lib/server/legacy-feed.js.map +1 -0
- package/src/lib/server/native-checkout.d.ts +34 -15
- package/src/lib/server/native-checkout.js +32 -17
- package/src/lib/server/native-checkout.js.map +1 -1
- package/src/lib/server/order-event-host-emit.d.ts +23 -0
- package/src/lib/server/order-event-host-emit.js +30 -0
- package/src/lib/server/order-event-host-emit.js.map +1 -0
- package/src/lib/server/order-event-triggers.d.ts +37 -0
- package/src/lib/server/order-event-triggers.js +119 -0
- package/src/lib/server/order-event-triggers.js.map +1 -0
- package/src/lib/server/order-events.d.ts +62 -0
- package/src/lib/server/order-events.js +109 -0
- package/src/lib/server/order-events.js.map +1 -0
- package/src/lib/server/order-history.d.ts +23 -0
- package/src/lib/server/order-history.js +65 -0
- package/src/lib/server/order-history.js.map +1 -0
- package/src/lib/server/order-notifications.d.ts +185 -0
- package/src/lib/server/order-notifications.js +567 -0
- package/src/lib/server/order-notifications.js.map +1 -0
- package/src/lib/server/order-receipt-send.d.ts +39 -0
- package/src/lib/server/order-receipt-send.js +151 -0
- package/src/lib/server/order-receipt-send.js.map +1 -0
- package/src/lib/server/order-status-token.d.ts +31 -0
- package/src/lib/server/order-status-token.js +75 -0
- package/src/lib/server/order-status-token.js.map +1 -0
- package/src/lib/server/order-status.d.ts +58 -0
- package/src/lib/server/order-status.js +141 -0
- package/src/lib/server/order-status.js.map +1 -0
- package/src/lib/server/order-webhooks.d.ts +108 -0
- package/src/lib/server/order-webhooks.js +622 -0
- package/src/lib/server/order-webhooks.js.map +1 -0
- package/src/lib/server/orders-shipping-prepare.d.ts +26 -0
- package/src/lib/server/orders-shipping-prepare.js +121 -0
- package/src/lib/server/orders-shipping-prepare.js.map +1 -0
- package/src/lib/server/payment-method-domains.d.ts +209 -0
- package/src/lib/server/payment-method-domains.js +444 -0
- package/src/lib/server/payment-method-domains.js.map +1 -0
- package/src/lib/server/payment-methods.d.ts +77 -0
- package/src/lib/server/payment-methods.js +284 -0
- package/src/lib/server/payment-methods.js.map +1 -0
- package/src/lib/server/pos-auth.d.ts +50 -0
- package/src/lib/server/pos-auth.js +121 -0
- package/src/lib/server/pos-auth.js.map +1 -0
- package/src/lib/server/pos-customer.d.ts +49 -0
- package/src/lib/server/pos-customer.js +257 -0
- package/src/lib/server/pos-customer.js.map +1 -0
- package/src/lib/server/pos-display.d.ts +57 -0
- package/src/lib/server/pos-display.js +419 -0
- package/src/lib/server/pos-display.js.map +1 -0
- package/src/lib/server/pos-fee-month.d.ts +34 -0
- package/src/lib/server/pos-fee-month.js +36 -0
- package/src/lib/server/pos-fee-month.js.map +1 -0
- package/src/lib/server/pos-ops-gate.d.ts +161 -0
- package/src/lib/server/pos-ops-gate.js +295 -0
- package/src/lib/server/pos-ops-gate.js.map +1 -0
- package/src/lib/server/pos-ops-routes.d.ts +22 -0
- package/src/lib/server/pos-ops-routes.js +36 -0
- package/src/lib/server/pos-ops-routes.js.map +1 -0
- package/src/lib/server/pos-order.d.ts +1 -18
- package/src/lib/server/pos-order.js +222 -42
- package/src/lib/server/pos-order.js.map +1 -1
- package/src/lib/server/pos-payment.d.ts +39 -0
- package/src/lib/server/pos-payment.js +922 -0
- package/src/lib/server/pos-payment.js.map +1 -0
- package/src/lib/server/pos-print.d.ts +82 -0
- package/src/lib/server/pos-print.js +193 -0
- package/src/lib/server/pos-print.js.map +1 -0
- package/src/lib/server/pos-readers.d.ts +27 -0
- package/src/lib/server/pos-readers.js +276 -0
- package/src/lib/server/pos-readers.js.map +1 -0
- package/src/lib/server/pos-refund-authority.d.ts +60 -0
- package/src/lib/server/pos-refund-authority.js +72 -0
- package/src/lib/server/pos-refund-authority.js.map +1 -0
- package/src/lib/server/pos-return.d.ts +58 -0
- package/src/lib/server/pos-return.js +891 -0
- package/src/lib/server/pos-return.js.map +1 -0
- package/src/lib/server/pos-sale-stamp.d.ts +66 -0
- package/src/lib/server/pos-sale-stamp.js +84 -0
- package/src/lib/server/pos-sale-stamp.js.map +1 -0
- package/src/lib/server/pos-sale.d.ts +170 -0
- package/src/lib/server/pos-sale.js +461 -0
- package/src/lib/server/pos-sale.js.map +1 -0
- package/src/lib/server/pos-shift.d.ts +45 -0
- package/src/lib/server/pos-shift.js +484 -0
- package/src/lib/server/pos-shift.js.map +1 -0
- package/src/lib/server/pos-staff-pin.d.ts +26 -0
- package/src/lib/server/pos-staff-pin.js +339 -0
- package/src/lib/server/pos-staff-pin.js.map +1 -0
- package/src/lib/server/pos-stripe.d.ts +91 -0
- package/src/lib/server/pos-stripe.js +129 -0
- package/src/lib/server/pos-stripe.js.map +1 -0
- package/src/lib/server/pos-terminal-connection-token.d.ts +48 -0
- package/src/lib/server/pos-terminal-connection-token.js +166 -0
- package/src/lib/server/pos-terminal-connection-token.js.map +1 -0
- package/src/lib/server/pos-terminal.d.ts +218 -0
- package/src/lib/server/pos-terminal.js +1014 -0
- package/src/lib/server/pos-terminal.js.map +1 -0
- package/src/lib/server/print-queue.d.ts +124 -0
- package/src/lib/server/print-queue.js +301 -0
- package/src/lib/server/print-queue.js.map +1 -0
- package/src/lib/server/printer-poll.d.ts +75 -0
- package/src/lib/server/printer-poll.js +325 -0
- package/src/lib/server/printer-poll.js.map +1 -0
- package/src/lib/server/printer-secret.d.ts +39 -0
- package/src/lib/server/printer-secret.js +56 -0
- package/src/lib/server/printer-secret.js.map +1 -0
- package/src/lib/server/printers.d.ts +114 -0
- package/src/lib/server/printers.js +546 -0
- package/src/lib/server/printers.js.map +1 -0
- package/src/lib/server/product-ai-capability.d.ts +42 -0
- package/src/lib/server/product-ai-capability.js +159 -0
- package/src/lib/server/product-ai-capability.js.map +1 -0
- package/src/lib/server/product-catalog.d.ts +42 -0
- package/src/lib/server/product-catalog.js +305 -0
- package/src/lib/server/product-catalog.js.map +1 -0
- package/src/lib/server/product-drafts.d.ts +119 -0
- package/src/lib/server/product-drafts.js +384 -0
- package/src/lib/server/product-drafts.js.map +1 -0
- package/src/lib/server/refund.js +110 -45
- package/src/lib/server/refund.js.map +1 -1
- package/src/lib/server/reserve.js +2 -0
- package/src/lib/server/reserve.js.map +1 -1
- package/src/lib/server/return-status-action.d.ts +37 -0
- package/src/lib/server/return-status-action.js +57 -0
- package/src/lib/server/return-status-action.js.map +1 -0
- package/src/lib/server/returns.d.ts +119 -0
- package/src/lib/server/returns.js +938 -0
- package/src/lib/server/returns.js.map +1 -0
- package/src/lib/server/shipment-records.d.ts +36 -0
- package/src/lib/server/shipment-records.js +289 -0
- package/src/lib/server/shipment-records.js.map +1 -0
- package/src/lib/server/shipping-connector-gates.d.ts +40 -0
- package/src/lib/server/shipping-connector-gates.js +97 -0
- package/src/lib/server/shipping-connector-gates.js.map +1 -0
- package/src/lib/server/shipping-connectors.d.ts +29 -0
- package/src/lib/server/shipping-connectors.js +236 -0
- package/src/lib/server/shipping-connectors.js.map +1 -0
- package/src/lib/server/shippingeasy.d.ts +238 -0
- package/src/lib/server/shippingeasy.js +787 -0
- package/src/lib/server/shippingeasy.js.map +1 -0
- package/src/lib/server/shipstation.d.ts +129 -0
- package/src/lib/server/shipstation.js +483 -0
- package/src/lib/server/shipstation.js.map +1 -0
- package/src/lib/server/site-page-resolver.d.ts +5 -0
- package/src/lib/server/site-page-resolver.js +156 -1
- package/src/lib/server/site-page-resolver.js.map +1 -1
- package/src/lib/server/stock-levels.d.ts +21 -0
- package/src/lib/server/stock-levels.js +263 -0
- package/src/lib/server/stock-levels.js.map +1 -0
- package/src/lib/server/stripe-refund.d.ts +47 -0
- package/src/lib/server/stripe-refund.js +87 -0
- package/src/lib/server/stripe-refund.js.map +1 -0
- package/src/lib/server/supplier-update.js +46 -5
- package/src/lib/server/supplier-update.js.map +1 -1
- package/src/lib/server/tax-engine-quote.d.ts +47 -0
- package/src/lib/server/tax-engine-quote.js +105 -0
- package/src/lib/server/tax-engine-quote.js.map +1 -0
- package/src/lib/server.js +146 -2
- package/src/lib/server.js.map +1 -1
- package/src/lib/site.js +12 -0
- package/src/lib/site.js.map +1 -1
- package/src/lib/subprocessors.d.ts +26 -0
- package/src/lib/subprocessors.js +50 -0
- package/src/lib/subprocessors.js.map +1 -0
- package/src/lib/tenant-emails.js +461 -3
- package/src/lib/tenant-emails.js.map +1 -1
- package/src/lib/testing/fake-firestore.d.ts +45 -0
- package/src/lib/testing/fake-firestore.js +189 -0
- package/src/lib/testing/fake-firestore.js.map +1 -0
- package/src/lib/testing/memory-firestore.d.ts +123 -0
- package/src/lib/testing/memory-firestore.js +274 -0
- package/src/lib/testing/memory-firestore.js.map +1 -0
- package/src/lib/testing/pos-ops-harness.d.ts +50 -0
- package/src/lib/testing/pos-ops-harness.js +184 -0
- package/src/lib/testing/pos-ops-harness.js.map +1 -0
- package/src/lib/testing/pos-ops-memory-firestore.d.ts +55 -0
- package/src/lib/testing/pos-ops-memory-firestore.js +376 -0
- package/src/lib/testing/pos-ops-memory-firestore.js.map +1 -0
- package/src/lib/transfer/records-transfer.d.ts +11 -1
- package/src/lib/transfer/records-transfer.js +127 -5
- package/src/lib/transfer/records-transfer.js.map +1 -1
- package/src/lib/transfer/records.server.d.ts +9 -2
- package/src/lib/transfer/records.server.js +58 -7
- package/src/lib/transfer/records.server.js.map +1 -1
- package/src/lib/transfer/register-transfer-resources.js +40 -1
- package/src/lib/transfer/register-transfer-resources.js.map +1 -1
- package/src/lib/transfer/register-transfer-ui.js +4 -1
- package/src/lib/transfer/register-transfer-ui.js.map +1 -1
- package/src/lib/transfer/shipping-presets.d.ts +23 -0
- package/src/lib/transfer/shipping-presets.js +156 -0
- package/src/lib/transfer/shipping-presets.js.map +1 -0
- package/src/lib/transfer/tracking-transfer.d.ts +101 -0
- package/src/lib/transfer/tracking-transfer.js +546 -0
- package/src/lib/transfer/tracking-transfer.js.map +1 -0
- package/src/lib/transfer/tracking.server.d.ts +37 -0
- package/src/lib/transfer/tracking.server.js +393 -0
- package/src/lib/transfer/tracking.server.js.map +1 -0
- package/src/lib/transfer/transfer-keys.d.ts +2 -1
- package/src/lib/transfer/transfer-keys.js +6 -2
- package/src/lib/transfer/transfer-keys.js.map +1 -1
- package/src/lib/utils/code128.d.ts +37 -0
- package/src/lib/utils/code128.js +199 -0
- package/src/lib/utils/code128.js.map +1 -0
- package/src/lib/utils/order-invoice.d.ts +55 -0
- package/src/lib/utils/order-invoice.js +127 -0
- package/src/lib/utils/order-invoice.js.map +1 -0
- package/src/lib/utils/use-checkout-return-notice.d.ts +34 -0
- package/src/lib/utils/use-checkout-return-notice.js +78 -0
- package/src/lib/utils/use-checkout-return-notice.js.map +1 -0
- package/src/lib/utils/use-storefront-purchase-event.js +4 -0
- package/src/lib/utils/use-storefront-purchase-event.js.map +1 -1
- package/src/lib/server/feed.js +0 -69
- package/src/lib/server/feed.js.map +0 -1
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2026 Aglyn LLC
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/ import { createHash, randomBytes, randomInt } from "crypto";
|
|
18
|
+
import { consumeRateLimit, firebaseAdmin, getPluginConfig, getOrgForHost } from "@aglyn/tenant-data-admin";
|
|
19
|
+
import { resolveMediaSrc } from "@aglyn/aglyn/app-utils/media-ref";
|
|
20
|
+
import { pluginSmsAvailable } from "@aglyn/aglyn/plugin-manager/plugin-sms-messaging";
|
|
21
|
+
import * as CommerceModel from "../model/index.js";
|
|
22
|
+
import { posRegisterSettings } from "../plugin-config.js";
|
|
23
|
+
import { authorizePosStaff, posQueryBody, posRequestBody } from "./pos-auth.js";
|
|
24
|
+
import { POS_CURRENCY } from "./pos-stripe.js";
|
|
25
|
+
/*==========================================
|
|
26
|
+
* THE CUSTOMER DISPLAY (AGL-3608).
|
|
27
|
+
*
|
|
28
|
+
* A second screen — a tablet on a stand facing the customer — that shows the
|
|
29
|
+
* basket, takes the tip and the receipt choice, and hands both back to the
|
|
30
|
+
* cashier. It must work with NO staff sign-in on the customer's device, so it
|
|
31
|
+
* holds nothing but a display token.
|
|
32
|
+
*
|
|
33
|
+
* ## Pairing
|
|
34
|
+
*
|
|
35
|
+
* The register asks for a six-digit code (`pairing-code`), good for ten
|
|
36
|
+
* minutes and usable once. The display sends it (`pair`) and receives a
|
|
37
|
+
* random 256-bit token. Only hashes are stored: `posDisplayPairings/{sha256}`
|
|
38
|
+
* for the code and `posDisplayTokens/{sha256}` for the token, each naming the
|
|
39
|
+
* one site and register it opens. Revoking a display, or removing its
|
|
40
|
+
* register, kills the token. A six-digit space is small, so `pair` is rate
|
|
41
|
+
* limited per address and a code dies at its first use.
|
|
42
|
+
*
|
|
43
|
+
* ## Why polling through this route, not a Firestore listener
|
|
44
|
+
*
|
|
45
|
+
* A Firestore listener needs a Firebase identity the rules can test, which on
|
|
46
|
+
* the customer's device means minting a custom auth session — a credential
|
|
47
|
+
* that would sit on an unattended tablet with the console's own SDK. Polling
|
|
48
|
+
* this route once a second with the display token is the simplest thing that
|
|
49
|
+
* is secure: the token opens exactly one register's display state and
|
|
50
|
+
* nothing else, the state lives in a server-only collection
|
|
51
|
+
* (`posDisplayStates`, denied to every client by the rules) so not even a
|
|
52
|
+
* signed-in site member can read a customer's typed address out of it, and a
|
|
53
|
+
* revoked token stops working on the next poll.
|
|
54
|
+
*=========================================*/ const PAIRINGS = 'posDisplayPairings';
|
|
55
|
+
const TOKENS = 'posDisplayTokens';
|
|
56
|
+
const STATES = 'posDisplayStates';
|
|
57
|
+
export function sha256(value) {
|
|
58
|
+
return createHash('sha256').update(value).digest('hex');
|
|
59
|
+
}
|
|
60
|
+
/** The one state document a register's display reads. */ export function posDisplayStateId(hostId, registerId) {
|
|
61
|
+
return `${hostId}__${registerId}`;
|
|
62
|
+
}
|
|
63
|
+
function stateRef(hostId, registerId) {
|
|
64
|
+
return firebaseAdmin.app().firestore().collection(STATES).doc(posDisplayStateId(hostId, registerId));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The store's currency (`hosts/{hostId}/settings/store.currency`, lower
|
|
68
|
+
* case), which every figure on the customer's screen is formatted in. A
|
|
69
|
+
* store that never chose one is in the currency the register charges.
|
|
70
|
+
*/ export async function posDisplayCurrency(hostId) {
|
|
71
|
+
var _snapshot_get;
|
|
72
|
+
const snapshot = await firebaseAdmin.app().firestore().collection('hosts').doc(hostId).collection('settings').doc('store').get().catch(()=>null);
|
|
73
|
+
const chosen = String((snapshot == null ? void 0 : snapshot.exists) ? (_snapshot_get = snapshot.get('currency')) != null ? _snapshot_get : '' : '').trim().toLowerCase();
|
|
74
|
+
return /^[a-z]{3}$/.test(chosen) ? chosen : POS_CURRENCY;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Writes the display state whole, so nothing from the last prompt lingers —
|
|
78
|
+
* a customer's typed address included. The currency is the store's, stamped
|
|
79
|
+
* here so the screen never formats a figure in one the register made up.
|
|
80
|
+
*/ export async function writePosDisplayState(hostId, registerId, state) {
|
|
81
|
+
await stateRef(hostId, registerId).set(_extends({}, state, {
|
|
82
|
+
currency: await posDisplayCurrency(hostId),
|
|
83
|
+
hostId,
|
|
84
|
+
registerId
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
/** The register's display returns to the thank-you screen with no customer data. */ export async function resetPosDisplay(hostId, registerId) {
|
|
88
|
+
await writePosDisplayState(hostId, registerId, {
|
|
89
|
+
mode: 'thanks',
|
|
90
|
+
updatedAtMs: Date.now()
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Ends the customer's turn once the register has acted on their receipt
|
|
95
|
+
* choice (AGL-3608): a display still on the receipt prompt says thank you,
|
|
96
|
+
* and an answer holding a typed email address or phone number is dropped
|
|
97
|
+
* from the state either way, so no contact detail outlives the sale on the
|
|
98
|
+
* server doc a public screen reads.
|
|
99
|
+
*
|
|
100
|
+
* Conditional, in a transaction, because the receipt can be sent after the
|
|
101
|
+
* cashier has started the next sale: a display already showing the next
|
|
102
|
+
* customer's basket is left alone.
|
|
103
|
+
*/ export async function finishPosDisplayReceipt(hostId, registerId) {
|
|
104
|
+
const firestore = firebaseAdmin.app().firestore();
|
|
105
|
+
const ref = stateRef(hostId, registerId);
|
|
106
|
+
const currency = await posDisplayCurrency(hostId);
|
|
107
|
+
await firestore.runTransaction(async (transaction)=>{
|
|
108
|
+
const snapshot = await transaction.get(ref);
|
|
109
|
+
if (!snapshot.exists) return;
|
|
110
|
+
const state = snapshot.data();
|
|
111
|
+
if (state.mode === 'receipt') {
|
|
112
|
+
transaction.set(ref, {
|
|
113
|
+
mode: 'thanks',
|
|
114
|
+
updatedAtMs: Date.now(),
|
|
115
|
+
currency,
|
|
116
|
+
hostId,
|
|
117
|
+
registerId
|
|
118
|
+
});
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (state.response && (state.response.email || state.response.phone)) {
|
|
122
|
+
const rest = _extends({}, state);
|
|
123
|
+
delete rest.response;
|
|
124
|
+
transaction.set(ref, rest);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/** Signs every display of a register out, and forgets its state. */ export async function revokePosDisplays(hostId, registerId) {
|
|
129
|
+
const firestore = firebaseAdmin.app().firestore();
|
|
130
|
+
const tokens = await firestore.collection(TOKENS).where('hostId', '==', hostId).where('registerId', '==', registerId).limit(50).get();
|
|
131
|
+
await Promise.all(tokens.docs.map((doc)=>doc.ref.delete()));
|
|
132
|
+
await stateRef(hostId, registerId).delete().catch(()=>undefined);
|
|
133
|
+
}
|
|
134
|
+
async function registerExists(hostId, registerId) {
|
|
135
|
+
if (!/^[A-Za-z0-9_-]{1,128}$/.test(registerId)) return false;
|
|
136
|
+
return (await firebaseAdmin.app().firestore().collection('hosts').doc(hostId).collection('registers').doc(registerId).get()).exists;
|
|
137
|
+
}
|
|
138
|
+
/** The store's name, logo and welcome line, for the idle and thank-you screens. */ async function displayBranding(hostId) {
|
|
139
|
+
var _ref, _host_get, _resolveMediaSrc, _resolveMediaSrc1;
|
|
140
|
+
const firestore = firebaseAdmin.app().firestore();
|
|
141
|
+
const host = await firestore.collection('hosts').doc(hostId).get();
|
|
142
|
+
const ownerOrg = await getOrgForHost(hostId).catch(()=>null);
|
|
143
|
+
const settings = posRegisterSettings(await getPluginConfig(ownerOrg == null ? void 0 : ownerOrg.orgId, 'commerce', {
|
|
144
|
+
hostId
|
|
145
|
+
}).catch(()=>({})));
|
|
146
|
+
return {
|
|
147
|
+
name: String((_ref = (_host_get = host.get('displayName')) != null ? _host_get : host.get('name')) != null ? _ref : '').slice(0, 80) || 'Welcome',
|
|
148
|
+
logoUrl: (_resolveMediaSrc = resolveMediaSrc(host.get('logoUrl'), {
|
|
149
|
+
hostId
|
|
150
|
+
})) != null ? _resolveMediaSrc : null,
|
|
151
|
+
logoDarkUrl: (_resolveMediaSrc1 = resolveMediaSrc(host.get('logoDarkUrl'), {
|
|
152
|
+
hostId
|
|
153
|
+
})) != null ? _resolveMediaSrc1 : null,
|
|
154
|
+
message: settings.displayMessage || 'Welcome'
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/** The display token on a request, or ''. */ function displayToken(req, body) {
|
|
158
|
+
var _req_headers_xposdisplaytoken, _body_token;
|
|
159
|
+
const header = String((_req_headers_xposdisplaytoken = req.headers['x-pos-display-token']) != null ? _req_headers_xposdisplaytoken : '');
|
|
160
|
+
return (header || String((_body_token = body['token']) != null ? _body_token : '')).trim().slice(0, 128);
|
|
161
|
+
}
|
|
162
|
+
/** The register a live display token opens, or null. */ async function resolveDisplayToken(token) {
|
|
163
|
+
var _snapshot_get, _snapshot_get1, _snapshot_get2;
|
|
164
|
+
if (!/^[A-Za-z0-9_-]{40,128}$/.test(token)) return null;
|
|
165
|
+
const ref = firebaseAdmin.app().firestore().collection(TOKENS).doc(sha256(token));
|
|
166
|
+
const snapshot = await ref.get();
|
|
167
|
+
if (!snapshot.exists) return null;
|
|
168
|
+
const hostId = String((_snapshot_get = snapshot.get('hostId')) != null ? _snapshot_get : '');
|
|
169
|
+
const registerId = String((_snapshot_get1 = snapshot.get('registerId')) != null ? _snapshot_get1 : '');
|
|
170
|
+
if (!hostId || !registerId) return null;
|
|
171
|
+
// A display whose register was removed is dead, even if its token row
|
|
172
|
+
// somehow outlived the removal.
|
|
173
|
+
if (!await registerExists(hostId, registerId)) return null;
|
|
174
|
+
const lastSeen = Number((_snapshot_get2 = snapshot.get('lastSeenAtMs')) != null ? _snapshot_get2 : 0);
|
|
175
|
+
if (Date.now() - lastSeen > 60000) {
|
|
176
|
+
await ref.set({
|
|
177
|
+
lastSeenAtMs: Date.now()
|
|
178
|
+
}, {
|
|
179
|
+
merge: true
|
|
180
|
+
}).catch(()=>undefined);
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
hostId,
|
|
184
|
+
registerId,
|
|
185
|
+
ref
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* `POST /api/commerce/pos-display`.
|
|
190
|
+
*
|
|
191
|
+
* Staff (Firebase token + the register's gate): `pairing-code`, `push`,
|
|
192
|
+
* `state`, `displays`, `revoke`.
|
|
193
|
+
* Display (display token only): `pair`, `poll`, `respond`, `forget`.
|
|
194
|
+
*/ export const posDisplayHandler = async (req, res)=>{
|
|
195
|
+
var _body_action;
|
|
196
|
+
// The two polls are GETs: a read is not a console write, so a display and a
|
|
197
|
+
// register asking once a second do not spend the console's write budget.
|
|
198
|
+
const body = req.method === 'GET' ? posQueryBody(req) : posRequestBody(req);
|
|
199
|
+
const action = String((_body_action = body['action']) != null ? _body_action : '');
|
|
200
|
+
if (!(req.method === 'POST' || req.method === 'GET' && (action === 'poll' || action === 'state'))) {
|
|
201
|
+
return res.status(405).json({
|
|
202
|
+
error: 'Method not allowed'
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
206
|
+
try {
|
|
207
|
+
switch(action){
|
|
208
|
+
case 'pair':
|
|
209
|
+
return await pair(req, body, res);
|
|
210
|
+
case 'poll':
|
|
211
|
+
case 'respond':
|
|
212
|
+
case 'forget':
|
|
213
|
+
{
|
|
214
|
+
const display = await resolveDisplayToken(displayToken(req, body));
|
|
215
|
+
if (!display) return res.status(401).json({
|
|
216
|
+
error: 'This display is not paired.'
|
|
217
|
+
});
|
|
218
|
+
if (action === 'forget') {
|
|
219
|
+
await display.ref.delete();
|
|
220
|
+
return res.status(200).json({
|
|
221
|
+
ok: true
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
const snapshot = await stateRef(display.hostId, display.registerId).get();
|
|
225
|
+
const state = snapshot.exists ? snapshot.data() : null;
|
|
226
|
+
if (action === 'poll') {
|
|
227
|
+
return res.status(200).json({
|
|
228
|
+
state: CommerceModel.posDisplayPublicState(state, Date.now()),
|
|
229
|
+
branding: body['branding'] === true || body['branding'] === 'true' ? await displayBranding(display.hostId) : undefined
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
const response = CommerceModel.sanitizePosDisplayResponse(state, body['response'], Date.now());
|
|
233
|
+
if (!response) {
|
|
234
|
+
return res.status(409).json({
|
|
235
|
+
error: 'That screen has moved on. Check the display.'
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
await stateRef(display.hostId, display.registerId).set({
|
|
239
|
+
response
|
|
240
|
+
}, {
|
|
241
|
+
merge: true
|
|
242
|
+
});
|
|
243
|
+
return res.status(200).json({
|
|
244
|
+
ok: true
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
default:
|
|
248
|
+
return await staffAction(req, body, action, res);
|
|
249
|
+
}
|
|
250
|
+
} catch (error) {
|
|
251
|
+
console.error('[pos-display]', action, error);
|
|
252
|
+
return res.status(500).json({
|
|
253
|
+
error: 'The customer display could not be updated'
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
async function pair(req, body, res) {
|
|
258
|
+
var _ref, _body_code;
|
|
259
|
+
var _req_socket;
|
|
260
|
+
const address = String((_ref = (_req_socket = req.socket) == null ? void 0 : _req_socket.remoteAddress) != null ? _ref : '') || 'no-address';
|
|
261
|
+
const rate = await consumeRateLimit(`pos-display-pair:${address}`, {
|
|
262
|
+
limit: 10,
|
|
263
|
+
windowMs: 10 * 60 * 1000
|
|
264
|
+
});
|
|
265
|
+
if (!rate.allowed) {
|
|
266
|
+
return res.status(429).json({
|
|
267
|
+
error: 'Too many tries. Wait a few minutes and try again.'
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
const code = String((_body_code = body['code']) != null ? _body_code : '').replace(/\D/g, '');
|
|
271
|
+
if (code.length !== 6) return res.status(400).json({
|
|
272
|
+
error: 'Enter the 6-digit code from the register.'
|
|
273
|
+
});
|
|
274
|
+
const firestore = firebaseAdmin.app().firestore();
|
|
275
|
+
const pairingRef = firestore.collection(PAIRINGS).doc(sha256(code));
|
|
276
|
+
const token = randomBytes(32).toString('base64url');
|
|
277
|
+
// Spent in the same transaction that mints the token: a code opens one
|
|
278
|
+
// display, once, and a second display racing the first gets nothing.
|
|
279
|
+
const paired = await firestore.runTransaction(async (transaction)=>{
|
|
280
|
+
var _snapshot_get, _snapshot_get1, _snapshot_get2, _snapshot_get3, _body_label;
|
|
281
|
+
const snapshot = await transaction.get(pairingRef);
|
|
282
|
+
if (!snapshot.exists) return null;
|
|
283
|
+
const expiresAtMs = Number((_snapshot_get = snapshot.get('expiresAtMs')) != null ? _snapshot_get : 0);
|
|
284
|
+
transaction.delete(pairingRef);
|
|
285
|
+
if (!(expiresAtMs > Date.now())) return null;
|
|
286
|
+
const hostId = String((_snapshot_get1 = snapshot.get('hostId')) != null ? _snapshot_get1 : '');
|
|
287
|
+
const registerId = String((_snapshot_get2 = snapshot.get('registerId')) != null ? _snapshot_get2 : '');
|
|
288
|
+
transaction.set(firestore.collection(TOKENS).doc(sha256(token)), {
|
|
289
|
+
hostId,
|
|
290
|
+
registerId,
|
|
291
|
+
createdAtMs: Date.now(),
|
|
292
|
+
createdBy: String((_snapshot_get3 = snapshot.get('createdBy')) != null ? _snapshot_get3 : ''),
|
|
293
|
+
lastSeenAtMs: Date.now(),
|
|
294
|
+
label: String((_body_label = body['label']) != null ? _body_label : '').slice(0, 60) || 'Customer display'
|
|
295
|
+
});
|
|
296
|
+
return {
|
|
297
|
+
hostId,
|
|
298
|
+
registerId
|
|
299
|
+
};
|
|
300
|
+
});
|
|
301
|
+
if (!paired) {
|
|
302
|
+
return res.status(404).json({
|
|
303
|
+
error: 'That code is not valid. Show a new code on the register.'
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
return res.status(200).json({
|
|
307
|
+
token,
|
|
308
|
+
branding: await displayBranding(paired.hostId)
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
async function staffAction(req, body, action, res) {
|
|
312
|
+
var _body_hostId, _body_registerId;
|
|
313
|
+
const hostId = String((_body_hostId = body['hostId']) != null ? _body_hostId : '');
|
|
314
|
+
const gate = await authorizePosStaff(req, hostId);
|
|
315
|
+
if ('error' in gate) return res.status(gate.status).json({
|
|
316
|
+
error: gate.error
|
|
317
|
+
});
|
|
318
|
+
const registerId = String((_body_registerId = body['registerId']) != null ? _body_registerId : '');
|
|
319
|
+
if (!await registerExists(hostId, registerId)) {
|
|
320
|
+
return res.status(404).json({
|
|
321
|
+
error: 'Unknown register'
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
const firestore = firebaseAdmin.app().firestore();
|
|
325
|
+
switch(action){
|
|
326
|
+
case 'pairing-code':
|
|
327
|
+
{
|
|
328
|
+
for(let attempt = 0; attempt < 8; attempt++){
|
|
329
|
+
const code = String(randomInt(0, 1000000)).padStart(6, '0');
|
|
330
|
+
const ref = firestore.collection(PAIRINGS).doc(sha256(code));
|
|
331
|
+
const expiresAtMs = Date.now() + CommerceModel.POS_DISPLAY_PAIRING_TTL_MS;
|
|
332
|
+
const claimed = await firestore.runTransaction(async (transaction)=>{
|
|
333
|
+
var _existing_get;
|
|
334
|
+
const existing = await transaction.get(ref);
|
|
335
|
+
// A live code another register is showing is never overwritten.
|
|
336
|
+
if (existing.exists && Number((_existing_get = existing.get('expiresAtMs')) != null ? _existing_get : 0) > Date.now()) return false;
|
|
337
|
+
transaction.set(ref, {
|
|
338
|
+
hostId,
|
|
339
|
+
registerId,
|
|
340
|
+
expiresAtMs,
|
|
341
|
+
createdBy: gate.staff.uid
|
|
342
|
+
});
|
|
343
|
+
return true;
|
|
344
|
+
});
|
|
345
|
+
if (claimed) return res.status(200).json({
|
|
346
|
+
code,
|
|
347
|
+
expiresAtMs
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
return res.status(503).json({
|
|
351
|
+
error: 'Could not make a code. Try again.'
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
case 'push':
|
|
355
|
+
{
|
|
356
|
+
var _state_promptId;
|
|
357
|
+
const state = CommerceModel.sanitizePosDisplayState(body['state'], Date.now());
|
|
358
|
+
// "Text" is never offered on a screen when the store cannot send one.
|
|
359
|
+
if (state.receipt && !pluginSmsAvailable()) {
|
|
360
|
+
const channels = state.receipt.channels.filter((channel)=>channel !== 'sms');
|
|
361
|
+
state.receipt.channels = channels.length ? channels : [
|
|
362
|
+
'print',
|
|
363
|
+
'none'
|
|
364
|
+
];
|
|
365
|
+
}
|
|
366
|
+
await writePosDisplayState(hostId, registerId, state);
|
|
367
|
+
return res.status(200).json({
|
|
368
|
+
ok: true,
|
|
369
|
+
promptId: (_state_promptId = state.promptId) != null ? _state_promptId : null
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
case 'state':
|
|
373
|
+
{
|
|
374
|
+
const snapshot = await stateRef(hostId, registerId).get();
|
|
375
|
+
const state = snapshot.exists ? snapshot.data() : null;
|
|
376
|
+
const displays = await firestore.collection(TOKENS).where('hostId', '==', hostId).where('registerId', '==', registerId).limit(10).get();
|
|
377
|
+
return res.status(200).json({
|
|
378
|
+
state,
|
|
379
|
+
// A display that polled within the last two minutes is "connected".
|
|
380
|
+
connected: displays.docs.some((doc)=>{
|
|
381
|
+
var _doc_get;
|
|
382
|
+
return Date.now() - Number((_doc_get = doc.get('lastSeenAtMs')) != null ? _doc_get : 0) < 120000;
|
|
383
|
+
})
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
case 'displays':
|
|
387
|
+
{
|
|
388
|
+
const displays = await firestore.collection(TOKENS).where('hostId', '==', hostId).where('registerId', '==', registerId).limit(10).get();
|
|
389
|
+
return res.status(200).json({
|
|
390
|
+
displays: displays.docs.map((doc)=>{
|
|
391
|
+
var _doc_get, _doc_get1, _doc_get2;
|
|
392
|
+
return {
|
|
393
|
+
id: doc.id.slice(0, 16),
|
|
394
|
+
label: String((_doc_get = doc.get('label')) != null ? _doc_get : 'Customer display'),
|
|
395
|
+
createdAtMs: Number((_doc_get1 = doc.get('createdAtMs')) != null ? _doc_get1 : 0),
|
|
396
|
+
lastSeenAtMs: Number((_doc_get2 = doc.get('lastSeenAtMs')) != null ? _doc_get2 : 0)
|
|
397
|
+
};
|
|
398
|
+
})
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
case 'revoke':
|
|
402
|
+
{
|
|
403
|
+
var _body_displayId;
|
|
404
|
+
const prefix = String((_body_displayId = body['displayId']) != null ? _body_displayId : '');
|
|
405
|
+
const displays = await firestore.collection(TOKENS).where('hostId', '==', hostId).where('registerId', '==', registerId).limit(10).get();
|
|
406
|
+
const doomed = displays.docs.filter((doc)=>prefix === '*' || prefix.length === 16 && doc.id.startsWith(prefix));
|
|
407
|
+
await Promise.all(doomed.map((doc)=>doc.ref.delete()));
|
|
408
|
+
return res.status(200).json({
|
|
409
|
+
revoked: doomed.length
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
default:
|
|
413
|
+
return res.status(400).json({
|
|
414
|
+
error: 'Unknown action'
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
//# sourceMappingURL=pos-display.js.map
|
|
@@ -0,0 +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. */\nasync 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 ''. */\nfunction 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/** The register a live display token opens, or null. */\nasync function resolveDisplayToken(\n token: string,\n): Promise<{ hostId: string; registerId: string; ref: any } | 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 { hostId, registerId, ref }\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 await display.ref.delete()\n return res.status(200).json({ ok: true })\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 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 transaction.set(firestore.collection(TOKENS).doc(sha256(token)), {\n hostId,\n registerId,\n createdAtMs: Date.now(),\n createdBy: String(snapshot.get('createdBy') ?? ''),\n lastSeenAtMs: Date.now(),\n label: String(body['label'] ?? '').slice(0, 60) || 'Customer display',\n })\n return { hostId, registerId }\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 return res.status(200).json({ token, 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 })\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 connected: displays.docs.some(\n (doc: any) => 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 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","posDisplayHandler","res","method","action","status","json","error","setHeader","pair","display","ok","posDisplayPublicState","branding","sanitizePosDisplayResponse","staffAction","console","address","socket","remoteAddress","rate","windowMs","allowed","code","replace","length","pairingRef","toString","paired","expiresAtMs","createdAtMs","createdBy","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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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The billing month a non-card POS fee accrues into (AGL-2111): `YYYY-MM` in
|
|
19
|
+
* **UTC**, byte-identical to the key `apps/console/utils/billing-month.ts`
|
|
20
|
+
* mints and to the twelve other month counters on the platform
|
|
21
|
+
* (`orgs/{id}/apiUsage/*`, `orgs/{id}/assistUsage/*`, the per-host counters).
|
|
22
|
+
*
|
|
23
|
+
* It has to be UTC and it has to be this exact expression: `report-usage`
|
|
24
|
+
* sweeps `previousMonth()` in UTC and reads the accrual document by that key,
|
|
25
|
+
* so a local-time month would strand every sale rung in the offset window on a
|
|
26
|
+
* document no sweep ever looks at — which is uncollected revenue that leaves
|
|
27
|
+
* no trace. `offline-pos-fee-month-key.spec.ts` pins the two against each
|
|
28
|
+
* other rather than trusting the comment.
|
|
29
|
+
*
|
|
30
|
+
* Local rather than imported because `apps/console` is an app: a plugin
|
|
31
|
+
* library cannot import from it, and the repo's other eleven copies of this
|
|
32
|
+
* one-liner are the established shape.
|
|
33
|
+
*/
|
|
34
|
+
export declare function offlineFeeMonthKey(now?: Date): string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* The billing month a non-card POS fee accrues into (AGL-2111): `YYYY-MM` in
|
|
18
|
+
* **UTC**, byte-identical to the key `apps/console/utils/billing-month.ts`
|
|
19
|
+
* mints and to the twelve other month counters on the platform
|
|
20
|
+
* (`orgs/{id}/apiUsage/*`, `orgs/{id}/assistUsage/*`, the per-host counters).
|
|
21
|
+
*
|
|
22
|
+
* It has to be UTC and it has to be this exact expression: `report-usage`
|
|
23
|
+
* sweeps `previousMonth()` in UTC and reads the accrual document by that key,
|
|
24
|
+
* so a local-time month would strand every sale rung in the offset window on a
|
|
25
|
+
* document no sweep ever looks at — which is uncollected revenue that leaves
|
|
26
|
+
* no trace. `offline-pos-fee-month-key.spec.ts` pins the two against each
|
|
27
|
+
* other rather than trusting the comment.
|
|
28
|
+
*
|
|
29
|
+
* Local rather than imported because `apps/console` is an app: a plugin
|
|
30
|
+
* library cannot import from it, and the repo's other eleven copies of this
|
|
31
|
+
* one-liner are the established shape.
|
|
32
|
+
*/ export function offlineFeeMonthKey(now = new Date()) {
|
|
33
|
+
return now.toISOString().slice(0, 7);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=pos-fee-month.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/pos-fee-month.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The billing month a non-card POS fee accrues into (AGL-2111): `YYYY-MM` in\n * **UTC**, byte-identical to the key `apps/console/utils/billing-month.ts`\n * mints and to the twelve other month counters on the platform\n * (`orgs/{id}/apiUsage/*`, `orgs/{id}/assistUsage/*`, the per-host counters).\n *\n * It has to be UTC and it has to be this exact expression: `report-usage`\n * sweeps `previousMonth()` in UTC and reads the accrual document by that key,\n * so a local-time month would strand every sale rung in the offset window on a\n * document no sweep ever looks at — which is uncollected revenue that leaves\n * no trace. `offline-pos-fee-month-key.spec.ts` pins the two against each\n * other rather than trusting the comment.\n *\n * Local rather than imported because `apps/console` is an app: a plugin\n * library cannot import from it, and the repo's other eleven copies of this\n * one-liner are the established shape.\n */\nexport function offlineFeeMonthKey(now: Date = new Date()): string {\n return now.toISOString().slice(0, 7)\n}\n"],"names":["offlineFeeMonthKey","now","Date","toISOString","slice"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;CAgBC,GACD,OAAO,SAASA,mBAAmBC,MAAY,IAAIC,MAAM;IACvD,OAAOD,IAAIE,WAAW,GAAGC,KAAK,CAAC,GAAG;AACpC"}
|