@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.
- package/README.md +1 -1
- package/package.json +13 -13
- package/src/lib/components/cart.js +25 -12
- package/src/lib/components/cart.js.map +1 -1
- package/src/lib/components/commerce-console-page.js +70 -13
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/console/order-detail-dialog.component.js +2 -1
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
- package/src/lib/components/console/order-webhooks-card.component.js +1 -1
- package/src/lib/components/console/order-webhooks-card.component.js.map +1 -1
- package/src/lib/components/console/payment-methods-card.component.js +1 -1
- package/src/lib/components/console/payment-methods-card.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-cart-panel.component.d.ts +5 -0
- package/src/lib/components/console/pos/pos-cart-panel.component.js +18 -12
- package/src/lib/components/console/pos/pos-cart-panel.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-hardware-api.d.ts +76 -5
- package/src/lib/components/console/pos/pos-hardware-api.js +53 -11
- package/src/lib/components/console/pos/pos-hardware-api.js.map +1 -1
- package/src/lib/components/console/pos/pos-hardware-buyer.component.d.ts +18 -0
- package/src/lib/components/console/pos/pos-hardware-buyer.component.js +629 -0
- package/src/lib/components/console/pos/pos-hardware-buyer.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-hardware-sale-api.d.ts +162 -0
- package/src/lib/components/console/pos/pos-hardware-sale-api.js +122 -0
- package/src/lib/components/console/pos/pos-hardware-sale-api.js.map +1 -0
- package/src/lib/components/console/pos/pos-hardware-sale-terms.component.d.ts +39 -0
- package/src/lib/components/console/pos/pos-hardware-sale-terms.component.js +251 -0
- package/src/lib/components/console/pos/pos-hardware-sale-terms.component.js.map +1 -0
- package/src/lib/components/console/pos/use-pos-display.js +50 -0
- package/src/lib/components/console/pos/use-pos-display.js.map +1 -1
- package/src/lib/components/console/pos-cellular-control.component.d.ts +41 -0
- package/src/lib/components/console/pos-cellular-control.component.js +211 -0
- package/src/lib/components/console/pos-cellular-control.component.js.map +1 -0
- package/src/lib/components/console/pos-devices-card.component.d.ts +9 -1
- package/src/lib/components/console/pos-devices-card.component.js +47 -15
- package/src/lib/components/console/pos-devices-card.component.js.map +1 -1
- package/src/lib/components/console/pos-display/pos-display-api.d.ts +6 -0
- package/src/lib/components/console/pos-display/pos-display-api.js +8 -1
- package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -1
- package/src/lib/components/console/pos-display-page.component.d.ts +13 -0
- package/src/lib/components/console/pos-display-page.component.js +44 -2
- package/src/lib/components/console/pos-display-page.component.js.map +1 -1
- package/src/lib/components/console/pos-hardware-card.component.d.ts +12 -4
- package/src/lib/components/console/pos-hardware-card.component.js +157 -36
- package/src/lib/components/console/pos-hardware-card.component.js.map +1 -1
- package/src/lib/components/console/pos-hardware-orders-staff-page.component.js +360 -80
- package/src/lib/components/console/pos-hardware-orders-staff-page.component.js.map +1 -1
- package/src/lib/components/console/pos-hardware-terms-page.component.d.ts +34 -0
- package/src/lib/components/console/pos-hardware-terms-page.component.js +257 -0
- package/src/lib/components/console/pos-hardware-terms-page.component.js.map +1 -0
- package/src/lib/components/console/pos-hardware-terms-sign-page.component.d.ts +27 -0
- package/src/lib/components/console/pos-hardware-terms-sign-page.component.js +104 -0
- package/src/lib/components/console/pos-hardware-terms-sign-page.component.js.map +1 -0
- package/src/lib/components/console/pos-hardware-waiting-card.component.d.ts +24 -0
- package/src/lib/components/console/pos-hardware-waiting-card.component.js +205 -0
- package/src/lib/components/console/pos-hardware-waiting-card.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js +297 -201
- package/src/lib/components/console/pos-ops/pos-check-in-dialog.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.d.ts +3 -0
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js +260 -92
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.d.ts +9 -0
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js +15 -6
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js.map +1 -1
- package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.d.ts +25 -0
- package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.js +136 -0
- package/src/lib/components/console/pos-ops/pos-rain-check-dialog.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.d.ts +6 -0
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.js +48 -31
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.js.map +1 -1
- package/src/lib/components/console/pos-page.component.d.ts +1 -1
- package/src/lib/components/console/pos-page.component.js +63 -12
- package/src/lib/components/console/pos-page.component.js.map +1 -1
- package/src/lib/components/console/pos-reader-splash-setting.component.js +1 -1
- package/src/lib/components/console/pos-reader-splash-setting.component.js.map +1 -1
- package/src/lib/components/console/product-check-in-fields.component.d.ts +4 -2
- package/src/lib/components/console/product-check-in-fields.component.js +60 -14
- package/src/lib/components/console/product-check-in-fields.component.js.map +1 -1
- package/src/lib/components/console/product-editor-dialog.component.js +44 -1
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/product-hardware-sku-field.component.d.ts +19 -0
- package/src/lib/components/console/product-hardware-sku-field.component.js +92 -0
- package/src/lib/components/console/product-hardware-sku-field.component.js.map +1 -0
- package/src/lib/components/console/product-kiosk-offer-field.component.d.ts +22 -0
- package/src/lib/components/console/product-kiosk-offer-field.component.js +94 -0
- package/src/lib/components/console/product-kiosk-offer-field.component.js.map +1 -0
- package/src/lib/components/console/product-register-fields.component.d.ts +4 -0
- package/src/lib/components/console/product-register-fields.component.js +31 -2
- package/src/lib/components/console/product-register-fields.component.js.map +1 -1
- package/src/lib/components/console/products-hub-card.component.js +11 -2
- package/src/lib/components/console/products-hub-card.component.js.map +1 -1
- package/src/lib/components/console/register-hardware-card.component.d.ts +11 -0
- package/src/lib/components/console/register-hardware-card.component.js +56 -27
- package/src/lib/components/console/register-hardware-card.component.js.map +1 -1
- package/src/lib/components/console/reservation-guests-dialog.component.d.ts +28 -0
- package/src/lib/components/console/reservation-guests-dialog.component.js +189 -0
- package/src/lib/components/console/reservation-guests-dialog.component.js.map +1 -0
- package/src/lib/components/console/reservations-card.component.d.ts +9 -0
- package/src/lib/components/console/reservations-card.component.js +158 -23
- package/src/lib/components/console/reservations-card.component.js.map +1 -1
- package/src/lib/components/console/shippingeasy-card.component.js +1 -1
- package/src/lib/components/console/shippingeasy-card.component.js.map +1 -1
- package/src/lib/components/console/shipstation-card.component.d.ts +1 -1
- package/src/lib/components/console/shipstation-card.component.js +3 -3
- package/src/lib/components/console/shipstation-card.component.js.map +1 -1
- package/src/lib/components/product-detail.d.ts +4 -0
- package/src/lib/components/product-detail.js +40 -5
- package/src/lib/components/product-detail.js.map +1 -1
- package/src/lib/components/product-reviews.js +28 -11
- package/src/lib/components/product-reviews.js.map +1 -1
- package/src/lib/components/reservation-widget.js +28 -5
- package/src/lib/components/reservation-widget.js.map +1 -1
- package/src/lib/components/use-day-picker.d.ts +25 -0
- package/src/lib/components/use-day-picker.js +57 -0
- package/src/lib/components/use-day-picker.js.map +1 -0
- package/src/lib/constants/operator-alerts.d.ts +55 -0
- package/src/lib/constants/operator-alerts.js +156 -1
- package/src/lib/constants/operator-alerts.js.map +1 -1
- package/src/lib/declarations.console-server.js +54 -1
- package/src/lib/declarations.console-server.js.map +1 -1
- package/src/lib/declarations.d.ts +4 -2
- package/src/lib/declarations.js +15 -4
- package/src/lib/declarations.js.map +1 -1
- package/src/lib/declarations.server.js +9 -0
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/model/commerce-cart.d.ts +9 -1
- package/src/lib/model/commerce-cart.js +4 -3
- package/src/lib/model/commerce-cart.js.map +1 -1
- package/src/lib/model/commerce-check-in-product.d.ts +26 -0
- package/src/lib/model/commerce-check-in-product.js +64 -2
- package/src/lib/model/commerce-check-in-product.js.map +1 -1
- package/src/lib/model/commerce-check-in-record.d.ts +127 -0
- package/src/lib/model/commerce-check-in-record.js +36 -0
- package/src/lib/model/commerce-check-in-record.js.map +1 -0
- package/src/lib/model/commerce-check-in.d.ts +91 -87
- package/src/lib/model/commerce-check-in.js +186 -62
- package/src/lib/model/commerce-check-in.js.map +1 -1
- package/src/lib/model/commerce-kiosk-offer.d.ts +31 -0
- package/src/lib/model/commerce-kiosk-offer.js +35 -0
- package/src/lib/model/commerce-kiosk-offer.js.map +1 -0
- package/src/lib/model/commerce-orders.d.ts +76 -0
- package/src/lib/model/commerce-orders.js +6 -0
- package/src/lib/model/commerce-orders.js.map +1 -1
- package/src/lib/model/commerce-pos-day-report.d.ts +54 -1
- package/src/lib/model/commerce-pos-day-report.js +39 -2
- package/src/lib/model/commerce-pos-day-report.js.map +1 -1
- package/src/lib/model/commerce-pos-offline.d.ts +1 -1
- package/src/lib/model/commerce-pos-offline.js +6 -1
- package/src/lib/model/commerce-pos-offline.js.map +1 -1
- package/src/lib/model/commerce-pos-ops.js +3 -2
- package/src/lib/model/commerce-pos-ops.js.map +1 -1
- package/src/lib/model/commerce-pos.d.ts +36 -3
- package/src/lib/model/commerce-pos.js +14 -6
- package/src/lib/model/commerce-pos.js.map +1 -1
- package/src/lib/model/commerce-receipt.js +3 -2
- package/src/lib/model/commerce-receipt.js.map +1 -1
- package/src/lib/model/commerce-reservations.d.ts +69 -4
- package/src/lib/model/commerce-reservations.js +57 -5
- package/src/lib/model/commerce-reservations.js.map +1 -1
- package/src/lib/model/commerce.d.ts +66 -0
- package/src/lib/model/commerce.js +15 -0
- package/src/lib/model/commerce.js.map +1 -1
- package/src/lib/model/order-list-fields.d.ts +11 -0
- package/src/lib/model/order-list-fields.js +17 -1
- package/src/lib/model/order-list-fields.js.map +1 -1
- package/src/lib/model/own-store-tax-summary.d.ts +152 -0
- package/src/lib/model/own-store-tax-summary.js +288 -0
- package/src/lib/model/own-store-tax-summary.js.map +1 -0
- package/src/lib/model/plugin-permissions.d.ts +74 -0
- package/src/lib/model/plugin-permissions.js +224 -7
- package/src/lib/model/plugin-permissions.js.map +1 -1
- package/src/lib/model/pos-cellular.d.ts +223 -0
- package/src/lib/model/pos-cellular.js +293 -0
- package/src/lib/model/pos-cellular.js.map +1 -0
- package/src/lib/model/pos-hardware-in-person.d.ts +98 -0
- package/src/lib/model/pos-hardware-in-person.js +224 -0
- package/src/lib/model/pos-hardware-in-person.js.map +1 -0
- package/src/lib/model/pos-hardware-tax-summary.d.ts +166 -0
- package/src/lib/model/pos-hardware-tax-summary.js +225 -0
- package/src/lib/model/pos-hardware-tax-summary.js.map +1 -0
- package/src/lib/model/pos-hardware-terms.d.ts +74 -0
- package/src/lib/model/pos-hardware-terms.js +115 -0
- package/src/lib/model/pos-hardware-terms.js.map +1 -0
- package/src/lib/model/pos-hardware.d.ts +349 -7
- package/src/lib/model/pos-hardware.js +291 -20
- package/src/lib/model/pos-hardware.js.map +1 -1
- package/src/lib/model/product-write.d.ts +10 -0
- package/src/lib/model/product-write.js +4 -2
- package/src/lib/model/product-write.js.map +1 -1
- package/src/lib/model/workspace-site-permissions.d.ts +26 -0
- package/src/lib/model/workspace-site-permissions.js +81 -0
- package/src/lib/model/workspace-site-permissions.js.map +1 -0
- package/src/lib/plugin.js +16 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/server/billing-webhook.js +25 -1
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/cancel-order.js +7 -5
- package/src/lib/server/cancel-order.js.map +1 -1
- package/src/lib/server/cart-checkout.js +20 -8
- package/src/lib/server/cart-checkout.js.map +1 -1
- package/src/lib/server/cart.js +29 -0
- package/src/lib/server/cart.js.map +1 -1
- package/src/lib/server/checkout.js +42 -13
- package/src/lib/server/checkout.js.map +1 -1
- package/src/lib/server/collection-membership.d.ts +4 -0
- package/src/lib/server/collection-membership.js +5 -10
- package/src/lib/server/collection-membership.js.map +1 -1
- package/src/lib/server/commerce-site-keys.d.ts +48 -0
- package/src/lib/server/commerce-site-keys.js +61 -0
- package/src/lib/server/commerce-site-keys.js.map +1 -0
- package/src/lib/server/draft-order.js +8 -5
- package/src/lib/server/draft-order.js.map +1 -1
- package/src/lib/server/fulfill-order.js +7 -5
- package/src/lib/server/fulfill-order.js.map +1 -1
- package/src/lib/server/gift-cards.js +8 -5
- package/src/lib/server/gift-cards.js.map +1 -1
- package/src/lib/server/local-fulfillment-status.js +9 -6
- package/src/lib/server/local-fulfillment-status.js.map +1 -1
- package/src/lib/server/member-post.js +6 -5
- package/src/lib/server/member-post.js.map +1 -1
- package/src/lib/server/membership-admin-password.d.ts +4 -2
- package/src/lib/server/membership-admin-password.js +10 -8
- package/src/lib/server/membership-admin-password.js.map +1 -1
- package/src/lib/server/membership-admin-remove.d.ts +7 -5
- package/src/lib/server/membership-admin-remove.js +9 -9
- package/src/lib/server/membership-admin-remove.js.map +1 -1
- package/src/lib/server/order-notifications.js +5 -2
- package/src/lib/server/order-notifications.js.map +1 -1
- package/src/lib/server/order-print.js +7 -5
- package/src/lib/server/order-print.js.map +1 -1
- package/src/lib/server/order-receipt-send.js +8 -5
- package/src/lib/server/order-receipt-send.js.map +1 -1
- package/src/lib/server/order-webhooks.js +8 -8
- package/src/lib/server/order-webhooks.js.map +1 -1
- package/src/lib/server/orders-shipping-prepare.js +9 -6
- package/src/lib/server/orders-shipping-prepare.js.map +1 -1
- package/src/lib/server/own-store-tax-return-source.d.ts +47 -0
- package/src/lib/server/own-store-tax-return-source.js +312 -0
- package/src/lib/server/own-store-tax-return-source.js.map +1 -0
- package/src/lib/server/payment-methods.js +13 -9
- package/src/lib/server/payment-methods.js.map +1 -1
- package/src/lib/server/pos-auth.d.ts +37 -6
- package/src/lib/server/pos-auth.js +40 -15
- package/src/lib/server/pos-auth.js.map +1 -1
- package/src/lib/server/pos-cellular-billing.d.ts +81 -0
- package/src/lib/server/pos-cellular-billing.js +711 -0
- package/src/lib/server/pos-cellular-billing.js.map +1 -0
- package/src/lib/server/pos-cellular-notify.d.ts +47 -0
- package/src/lib/server/pos-cellular-notify.js +150 -0
- package/src/lib/server/pos-cellular-notify.js.map +1 -0
- package/src/lib/server/pos-cellular.d.ts +88 -0
- package/src/lib/server/pos-cellular.js +339 -0
- package/src/lib/server/pos-cellular.js.map +1 -0
- package/src/lib/server/pos-check-in.d.ts +5 -1
- package/src/lib/server/pos-check-in.js +296 -28
- package/src/lib/server/pos-check-in.js.map +1 -1
- package/src/lib/server/pos-day-report.js +29 -3
- package/src/lib/server/pos-day-report.js.map +1 -1
- package/src/lib/server/pos-display.d.ts +16 -0
- package/src/lib/server/pos-display.js +129 -2
- package/src/lib/server/pos-display.js.map +1 -1
- package/src/lib/server/pos-hardware-admin.d.ts +10 -1
- package/src/lib/server/pos-hardware-admin.js +250 -84
- package/src/lib/server/pos-hardware-admin.js.map +1 -1
- package/src/lib/server/pos-hardware-attach.d.ts +105 -0
- package/src/lib/server/pos-hardware-attach.js +443 -0
- package/src/lib/server/pos-hardware-attach.js.map +1 -0
- package/src/lib/server/pos-hardware-buyer-lookup.d.ts +58 -0
- package/src/lib/server/pos-hardware-buyer-lookup.js +180 -0
- package/src/lib/server/pos-hardware-buyer-lookup.js.map +1 -0
- package/src/lib/server/pos-hardware-buyer-record.d.ts +29 -0
- package/src/lib/server/pos-hardware-buyer-record.js +86 -0
- package/src/lib/server/pos-hardware-buyer-record.js.map +1 -0
- package/src/lib/server/pos-hardware-cancel.d.ts +58 -0
- package/src/lib/server/pos-hardware-cancel.js +147 -0
- package/src/lib/server/pos-hardware-cancel.js.map +1 -0
- package/src/lib/server/pos-hardware-closure-notices.d.ts +27 -0
- package/src/lib/server/pos-hardware-closure-notices.js +85 -0
- package/src/lib/server/pos-hardware-closure-notices.js.map +1 -0
- package/src/lib/server/pos-hardware-closure.d.ts +60 -0
- package/src/lib/server/pos-hardware-closure.js +153 -0
- package/src/lib/server/pos-hardware-closure.js.map +1 -0
- package/src/lib/server/pos-hardware-in-person.d.ts +61 -0
- package/src/lib/server/pos-hardware-in-person.js +236 -0
- package/src/lib/server/pos-hardware-in-person.js.map +1 -0
- package/src/lib/server/pos-hardware-notify.d.ts +40 -2
- package/src/lib/server/pos-hardware-notify.js +195 -14
- package/src/lib/server/pos-hardware-notify.js.map +1 -1
- package/src/lib/server/pos-hardware-readers.d.ts +115 -0
- package/src/lib/server/pos-hardware-readers.js +430 -0
- package/src/lib/server/pos-hardware-readers.js.map +1 -0
- package/src/lib/server/pos-hardware-returns.d.ts +116 -0
- package/src/lib/server/pos-hardware-returns.js +502 -0
- package/src/lib/server/pos-hardware-returns.js.map +1 -0
- package/src/lib/server/pos-hardware-sale-fields.d.ts +28 -0
- package/src/lib/server/pos-hardware-sale-fields.js +44 -0
- package/src/lib/server/pos-hardware-sale-fields.js.map +1 -0
- package/src/lib/server/pos-hardware-sale.d.ts +54 -0
- package/src/lib/server/pos-hardware-sale.js +369 -0
- package/src/lib/server/pos-hardware-sale.js.map +1 -0
- package/src/lib/server/pos-hardware-tax-return-source.d.ts +99 -0
- package/src/lib/server/pos-hardware-tax-return-source.js +462 -0
- package/src/lib/server/pos-hardware-tax-return-source.js.map +1 -0
- package/src/lib/server/pos-hardware-terms.d.ts +64 -0
- package/src/lib/server/pos-hardware-terms.js +154 -0
- package/src/lib/server/pos-hardware-terms.js.map +1 -0
- package/src/lib/server/pos-hardware-user-eraser.d.ts +3 -0
- package/src/lib/server/pos-hardware-user-eraser.js +31 -7
- package/src/lib/server/pos-hardware-user-eraser.js.map +1 -1
- package/src/lib/server/pos-hardware-webhook.d.ts +5 -0
- package/src/lib/server/pos-hardware-webhook.js +51 -6
- package/src/lib/server/pos-hardware-webhook.js.map +1 -1
- package/src/lib/server/pos-hardware.d.ts +74 -1
- package/src/lib/server/pos-hardware.js +175 -10
- package/src/lib/server/pos-hardware.js.map +1 -1
- package/src/lib/server/pos-kiosk.d.ts +2 -0
- package/src/lib/server/pos-kiosk.js +17 -12
- package/src/lib/server/pos-kiosk.js.map +1 -1
- package/src/lib/server/pos-offline-card-order.d.ts +64 -0
- package/src/lib/server/pos-offline-card-order.js +102 -0
- package/src/lib/server/pos-offline-card-order.js.map +1 -0
- package/src/lib/server/pos-offline-card-reconcile.d.ts +67 -1
- package/src/lib/server/pos-offline-card-reconcile.js +215 -18
- package/src/lib/server/pos-offline-card-reconcile.js.map +1 -1
- package/src/lib/server/pos-offline-sync.d.ts +39 -0
- package/src/lib/server/pos-offline-sync.js +190 -55
- package/src/lib/server/pos-offline-sync.js.map +1 -1
- package/src/lib/server/pos-ops-gate.d.ts +28 -9
- package/src/lib/server/pos-ops-gate.js +50 -19
- package/src/lib/server/pos-ops-gate.js.map +1 -1
- package/src/lib/server/pos-ops-routes.js +24 -0
- package/src/lib/server/pos-ops-routes.js.map +1 -1
- package/src/lib/server/pos-order-refund-ids.d.ts +28 -0
- package/src/lib/server/pos-order-refund-ids.js +31 -0
- package/src/lib/server/pos-order-refund-ids.js.map +1 -0
- package/src/lib/server/pos-order.js +52 -49
- package/src/lib/server/pos-order.js.map +1 -1
- package/src/lib/server/pos-payment.js +1 -1
- package/src/lib/server/pos-payment.js.map +1 -1
- package/src/lib/server/pos-reader-splash-admin.js +30 -32
- package/src/lib/server/pos-reader-splash-admin.js.map +1 -1
- package/src/lib/server/pos-reader-splash-images-route.d.ts +17 -0
- package/src/lib/server/pos-reader-splash-images-route.js +113 -0
- package/src/lib/server/pos-reader-splash-images-route.js.map +1 -0
- package/src/lib/server/pos-reader-splash-images.d.ts +51 -0
- package/src/lib/server/pos-reader-splash-images.js +123 -0
- package/src/lib/server/pos-reader-splash-images.js.map +1 -0
- package/src/lib/server/pos-reader-splash.d.ts +68 -1
- package/src/lib/server/pos-reader-splash.js +182 -11
- package/src/lib/server/pos-reader-splash.js.map +1 -1
- package/src/lib/server/pos-readers.d.ts +29 -0
- package/src/lib/server/pos-readers.js +134 -35
- package/src/lib/server/pos-readers.js.map +1 -1
- package/src/lib/server/pos-refund-authority.d.ts +3 -1
- package/src/lib/server/pos-refund-authority.js +3 -2
- package/src/lib/server/pos-refund-authority.js.map +1 -1
- package/src/lib/server/pos-return.d.ts +10 -0
- package/src/lib/server/pos-return.js +29 -7
- package/src/lib/server/pos-return.js.map +1 -1
- package/src/lib/server/pos-sale.js +6 -1
- package/src/lib/server/pos-sale.js.map +1 -1
- package/src/lib/server/pos-shift.js +11 -0
- package/src/lib/server/pos-shift.js.map +1 -1
- package/src/lib/server/pos-staff-pin.js +29 -24
- package/src/lib/server/pos-staff-pin.js.map +1 -1
- package/src/lib/server/pos-terminal.d.ts +14 -4
- package/src/lib/server/pos-terminal.js +34 -38
- package/src/lib/server/pos-terminal.js.map +1 -1
- package/src/lib/server/printers.d.ts +7 -3
- package/src/lib/server/printers.js +18 -12
- package/src/lib/server/printers.js.map +1 -1
- package/src/lib/server/product-drafts.d.ts +11 -1
- package/src/lib/server/product-drafts.js +12 -8
- package/src/lib/server/product-drafts.js.map +1 -1
- package/src/lib/server/product.d.ts +15 -1
- package/src/lib/server/product.js +16 -3
- package/src/lib/server/product.js.map +1 -1
- package/src/lib/server/products-write.d.ts +26 -2
- package/src/lib/server/products-write.js +19 -7
- package/src/lib/server/products-write.js.map +1 -1
- package/src/lib/server/refund.js +55 -42
- package/src/lib/server/refund.js.map +1 -1
- package/src/lib/server/reservation-availability-query.d.ts +8 -0
- package/src/lib/server/reservation-availability-query.js +11 -1
- package/src/lib/server/reservation-availability-query.js.map +1 -1
- package/src/lib/server/reservation-availability.d.ts +1 -1
- package/src/lib/server/reservation-availability.js +7 -2
- package/src/lib/server/reservation-availability.js.map +1 -1
- package/src/lib/server/reservation-guests.d.ts +32 -0
- package/src/lib/server/reservation-guests.js +285 -0
- package/src/lib/server/reservation-guests.js.map +1 -0
- package/src/lib/server/reservation-walk-in.d.ts +11 -1
- package/src/lib/server/reservation-walk-in.js +56 -12
- package/src/lib/server/reservation-walk-in.js.map +1 -1
- package/src/lib/server/reserve.js +18 -5
- package/src/lib/server/reserve.js.map +1 -1
- package/src/lib/server/returns.js +9 -6
- package/src/lib/server/returns.js.map +1 -1
- package/src/lib/server/reviews.d.ts +22 -2
- package/src/lib/server/reviews.js +88 -20
- package/src/lib/server/reviews.js.map +1 -1
- package/src/lib/server/shipping-connectors.js +10 -11
- package/src/lib/server/shipping-connectors.js.map +1 -1
- package/src/lib/server/site-page-resolver.js +20 -3
- package/src/lib/server/site-page-resolver.js.map +1 -1
- package/src/lib/server/store-day.d.ts +33 -0
- package/src/lib/server/store-day.js +46 -0
- package/src/lib/server/store-day.js.map +1 -0
- package/src/lib/server/store-setup-ai-writer.d.ts +2 -1
- package/src/lib/server/store-setup-ai-writer.js +5 -6
- package/src/lib/server/store-setup-ai-writer.js.map +1 -1
- package/src/lib/server/storefront-tax.d.ts +13 -0
- package/src/lib/server/storefront-tax.js +8 -1
- package/src/lib/server/storefront-tax.js.map +1 -1
- package/src/lib/server/tax-return-source.d.ts +32 -3
- package/src/lib/server/tax-return-source.js +99 -20
- package/src/lib/server/tax-return-source.js.map +1 -1
- package/src/lib/server.js +100 -2
- package/src/lib/server.js.map +1 -1
- package/src/lib/testing/fake-firestore.js +58 -16
- package/src/lib/testing/fake-firestore.js.map +1 -1
- package/src/lib/testing/pos-ops-memory-firestore.js +18 -4
- package/src/lib/testing/pos-ops-memory-firestore.js.map +1 -1
- package/src/lib/testing/site-register-permissions.d.ts +29 -0
- package/src/lib/testing/site-register-permissions.js +38 -0
- package/src/lib/testing/site-register-permissions.js.map +1 -0
- package/src/lib/transfer/tracking.server.js +8 -5
- package/src/lib/transfer/tracking.server.js.map +1 -1
- package/src/lib/utils/add-to-cart.d.ts +2 -0
- package/src/lib/utils/add-to-cart.js +6 -3
- package/src/lib/utils/add-to-cart.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/order-webhooks.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 { createResourceUid } from '@aglyn/aglyn/app-utils/create-resource-uid'\nimport { PLATFORM_BRAND_NAME } from '@aglyn/aglyn/app-utils/platform-brand'\nimport type { PluginApiHandler } from '@aglyn/aglyn/server'\nimport type { PluginDomainEventEnvelope } from '@aglyn/aglyn/plugin-manager/plugin-domain-events'\nimport {\n describeConfiguredUrlRefusal,\n configuredUrlRefusal,\n fetchConfiguredPublicUrl,\n firebaseAdmin,\n notifyHostManagers,\n} from '@aglyn/tenant-data-admin'\nimport { PLUGIN_EVENT_MAX_ATTEMPTS } from '@aglyn/tenant-data-admin/server/plugin-event-outbox'\nimport { resolveOrgPermissions } from '@aglyn/tenant-runtime/org-permissions'\nimport {\n createSecretBoxKey,\n openSecret,\n parseSecretBoxKeyring,\n sealSecret,\n SECRET_BOX_KEY_BYTES,\n type SecretBoxKey,\n type SecretBoxKeyring,\n} from '@aglyn/shared-util-tools/secret-box'\nimport { createHmac, hkdfSync, randomBytes } from 'node:crypto'\nimport { COMMERCE_EVENT_DECLARATIONS } from '../model/order-events'\nimport * as Webhooks from '../model/order-webhooks'\n\n/**\n * Merchant order webhooks (AGL-3611): the console's door and the delivery\n * behind it. The model (`model/order-webhooks.ts`) says what is stored where.\n *\n * DELIVERY RIDES THE PLUGIN EVENT OUTBOX. Commerce subscribes to its own\n * order and return events under the name `webhooks`; the subscriber posts the\n * event to every endpoint that takes it and records each attempt in the\n * delivery log. An endpoint that already took an event is not posted it\n * again, so when one of three endpoints fails, the subscriber throws, the\n * outbox retries it with its backoff (30s, 2m, 10m, 30m, 1h, 6h, 12h), and\n * only the failing endpoint is called again. On the last attempt the delivery\n * is marked failed and the site's managers are told.\n *\n * EVERY CALL GOES THROUGH `fetchConfiguredPublicUrl`: https on the default\n * port, a public address pinned at connect time, no redirect followed. A\n * merchant's endpoint is a stranger's server to us.\n *\n * THE SECRET IS SEALED with the shared secret box, under the keyring\n * `readCommerceSecretKeyring` answers, bound to its endpoint by the seal's\n * context. The plaintext leaves the server once, in the answer to the request\n * that made or rolled it.\n */\n\nexport const COMMERCE_SECRET_KEY_ENV = 'COMMERCE_SECRET_KEY'\n\nconst SECRETS = 'orderWebhookSecrets'\n\n/** Delivery rows live this long, then Firestore's TTL removes them. */\nexport const ORDER_WEBHOOK_LOG_RETENTION_MS = 30 * 86_400_000\n\ntype Firestore = FirebaseFirestore.Firestore\n\n/** The id of the key derived from `TOKEN_SIGNING_SECRET`. */\nexport const DERIVED_COMMERCE_KEY_ID = 'tss1'\n\n/**\n * A secret-box key derived from `TOKEN_SIGNING_SECRET` with HKDF, under its\n * own label, so the commerce tokens and the sealed secrets never share key\n * material. `null` when that secret is unset.\n */\nfunction derivedCommerceKey(): SecretBoxKey | null {\n const base = String(process.env['TOKEN_SIGNING_SECRET'] ?? '')\n if (!base) return null\n const material = new Uint8Array(hkdfSync('sha256', base, 'aglyn-commerce', 'secret-box:v1', SECRET_BOX_KEY_BYTES))\n return createSecretBoxKey(material, DERIVED_COMMERCE_KEY_ID)\n}\n\n/**\n * The keyring commerce seals its stored secrets with. `COMMERCE_SECRET_KEY`\n * (a secret-box keyring) when it is set, its first key sealing; otherwise the\n * key derived from `TOKEN_SIGNING_SECRET`, which every deployment that sells\n * already has. The derived key stays in the ring after a dedicated key is\n * configured, so what it sealed still opens. `null` when neither is usable.\n * Never throws.\n */\nexport function readCommerceSecretKeyring(): SecretBoxKeyring | null {\n let derived: SecretBoxKey | null = null\n try {\n derived = derivedCommerceKey()\n } catch {\n derived = null\n }\n const raw = String(process.env[COMMERCE_SECRET_KEY_ENV] ?? '').trim()\n if (raw) {\n try {\n const ring = parseSecretBoxKeyring(raw)\n const keys = derived && !ring.keys.some((key) => key.id === derived!.id) ? [...ring.keys, derived] : ring.keys\n return { current: ring.current, keys }\n } catch {\n // An unusable dedicated key falls back to the derived one rather than\n // sealing nothing.\n }\n }\n return derived ? { current: derived, keys: [derived] } : null\n}\n\n/** Whether this deployment can sign webhooks at all. */\nexport function orderWebhooksConfigured(): boolean {\n return readCommerceSecretKeyring() !== null\n}\n\nconst sealContext = (hostId: string, endpointId: string) => `hosts/${hostId}/${SECRETS}/${endpointId}#secret`\n\n/** A fresh signing secret: `whsec_` and 32 random bytes. */\nexport function mintOrderWebhookSecret(): string {\n return `whsec_${randomBytes(32).toString('base64url')}`\n}\n\n/** The HMAC-SHA256 of `{t}.{body}` under the secret, as hex. */\nexport function signOrderWebhook(secret: string, timestampSeconds: number, body: string): string {\n return createHmac('sha256', secret).update(Webhooks.orderWebhookSignedPayload(timestampSeconds, body)).digest('hex')\n}\n\nconst hostRefFor = (firestore: Firestore, hostId: string) => firestore.collection('hosts').doc(hostId)\n\nasync function readSecret(\n firestore: Firestore,\n hostId: string,\n endpointId: string,\n keyring: SecretBoxKeyring,\n): Promise<string> {\n const hostRef = hostRefFor(firestore, hostId)\n const snapshot = await hostRef.collection('orderWebhookSecrets').doc(endpointId).get()\n const sealed = String(snapshot.get('sealedSecret') ?? '')\n if (!sealed) throw new Error('This endpoint has no signing secret')\n return openSecret(sealed, keyring, { context: sealContext(hostId, endpointId) }).plaintext\n}\n\nfunction sealedSecretRecord(\n hostId: string,\n endpointId: string,\n secret: string,\n keyring: SecretBoxKeyring,\n now: number,\n): Webhooks.OrderWebhookSecretRecord {\n return {\n sealedSecret: sealSecret(secret, keyring.current, { context: sealContext(hostId, endpointId) }),\n secretKeyId: keyring.current.id,\n updatedAtMs: now,\n }\n}\n\n/** What one POST came to. */\nexport interface OrderWebhookPostResult {\n attempt: Webhooks.OrderWebhookAttempt\n delivered: boolean\n}\n\n/**\n * Posts one body to one endpoint, signed. Never throws: a refusal, a timeout\n * or a reset is an attempt that failed, with the reason in words.\n */\nexport async function postOrderWebhook(input: {\n url: string\n secret: string\n event: string\n eventId: string\n body: string\n now?: () => number\n fetchImpl?: typeof fetchConfiguredPublicUrl\n}): Promise<OrderWebhookPostResult> {\n const clock = input.now ?? Date.now\n const startedAt = clock()\n const timestamp = Math.floor(startedAt / 1000)\n const signature = Webhooks.formatOrderWebhookSignature(timestamp, signOrderWebhook(input.secret, timestamp, input.body))\n let httpStatus: number | null = null\n let error: string | undefined\n try {\n const result = await (input.fetchImpl ?? fetchConfiguredPublicUrl)(input.url, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'user-agent': 'Aglyn-Webhooks/1.0',\n [Webhooks.ORDER_WEBHOOK_SIGNATURE_HEADER]: signature,\n [Webhooks.ORDER_WEBHOOK_EVENT_HEADER]: input.event,\n [Webhooks.ORDER_WEBHOOK_EVENT_ID_HEADER]: input.eventId,\n },\n body: input.body,\n signal: AbortSignal.timeout(Webhooks.ORDER_WEBHOOK_TIMEOUT_MS),\n })\n if ('refusal' in result) {\n error = `Not sent: ${describeConfiguredUrlRefusal(result.refusal)}`\n } else {\n httpStatus = result.status\n if (!Webhooks.orderWebhookAccepted(httpStatus)) {\n error =\n httpStatus >= 300 && httpStatus < 400\n ? `The endpoint answered ${httpStatus}, a redirect; redirects are not followed`\n : `The endpoint answered ${httpStatus}`\n }\n }\n } catch (caught) {\n const name = (caught as Error)?.name\n error =\n name === 'TimeoutError' || name === 'AbortError'\n ? `No answer within ${Webhooks.ORDER_WEBHOOK_TIMEOUT_MS / 1000} seconds`\n : `The connection failed: ${String((caught as Error)?.message ?? caught).slice(0, 200)}`\n }\n const attempt: Webhooks.OrderWebhookAttempt = {\n atMs: startedAt,\n httpStatus,\n ...(error ? { error } : {}),\n durationMs: Math.max(0, clock() - startedAt),\n }\n return { attempt, delivered: !error }\n}\n\nfunction expiresAt(now: number) {\n return firebaseAdmin.firestore.Timestamp.fromMillis(now + ORDER_WEBHOOK_LOG_RETENTION_MS)\n}\n\n/** Records an attempt on the delivery row and on the endpoint's summary. */\nasync function recordAttempt(\n firestore: Firestore,\n hostId: string,\n endpointId: string,\n delivery: {\n id: string\n eventId: string\n event: string\n orderId: string | null\n body: string\n test?: boolean\n prior: Webhooks.OrderWebhookDelivery | null\n },\n result: OrderWebhookPostResult,\n status: Webhooks.OrderWebhookDeliveryStatus,\n now: number,\n): Promise<void> {\n const hostRef = hostRefFor(firestore, hostId)\n const row: Webhooks.OrderWebhookDelivery & { expiresAt: unknown } = {\n endpointId,\n eventId: delivery.eventId,\n event: delivery.event,\n orderId: delivery.orderId,\n status,\n attempts: Webhooks.appendOrderWebhookAttempt(delivery.prior?.attempts, result.attempt),\n body: delivery.body.slice(0, Webhooks.ORDER_WEBHOOK_BODY_MAX),\n ...(delivery.test ? { test: true } : {}),\n createdAtMs: delivery.prior?.createdAtMs ?? now,\n updatedAtMs: now,\n expiresAt: expiresAt(now),\n }\n await hostRef.collection('orderWebhookDeliveries').doc(delivery.id).set(row)\n await hostRef\n .collection('orderWebhooks')\n .doc(endpointId)\n .update({\n lastDeliveryAtMs: now,\n lastDeliveryStatus: status,\n consecutiveFailures: result.delivered ? 0 : firebaseAdmin.firestore.FieldValue.increment(1),\n })\n .catch(() => undefined)\n}\n\n/**\n * The subscriber: posts one event to every endpoint of the site that takes\n * it and has not taken it already. Throws when any endpoint still owes it, so\n * the outbox retries; on the outbox's last attempt it records the failure and\n * tells the site's managers instead.\n */\nexport async function deliverOrderEventToWebhooks(\n envelope: PluginDomainEventEnvelope,\n deps: { fetchImpl?: typeof fetchConfiguredPublicUrl; now?: () => number } = {},\n): Promise<{ delivered: number; failed: number }> {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, envelope.hostId)\n const endpoints = await hostRef.collection('orderWebhooks').where('enabled', '==', true).get()\n const taking = endpoints.docs.filter((doc) =>\n Webhooks.orderWebhookTakes(doc.data() as Webhooks.OrderWebhookEndpoint, envelope.event, envelope.occurredAtMs),\n )\n if (taking.length === 0) return { delivered: 0, failed: 0 }\n const keyring = readCommerceSecretKeyring()\n const clock = deps.now ?? Date.now\n const final = envelope.attempt >= PLUGIN_EVENT_MAX_ATTEMPTS\n const body = Webhooks.orderWebhookBody({\n eventId: envelope.id,\n event: envelope.event,\n occurredAtMs: envelope.occurredAtMs,\n hostId: envelope.hostId,\n payload: envelope.payload,\n })\n const orderId = String(((envelope.payload ?? {}) as { order?: { id?: unknown } }).order?.id ?? '') || null\n const outcomes = await Promise.all(\n taking.map(async (doc) => {\n const endpoint = doc.data() as Webhooks.OrderWebhookEndpoint\n const deliveryId = Webhooks.orderWebhookDeliveryId(envelope.id, doc.id)\n const priorSnapshot = await hostRef.collection('orderWebhookDeliveries').doc(deliveryId).get()\n const prior = priorSnapshot.exists ? (priorSnapshot.data() as Webhooks.OrderWebhookDelivery) : null\n // Taken already, on an earlier pass or by a resend from the console.\n if (prior?.status === 'delivered') return 'delivered' as const\n const settled = await attemptEndpoint({\n firestore,\n hostId: envelope.hostId,\n endpointId: doc.id,\n url: endpoint.url,\n keyring,\n event: envelope.event,\n eventId: envelope.id,\n body,\n clock,\n fetchImpl: deps.fetchImpl,\n })\n const status: Webhooks.OrderWebhookDeliveryStatus = settled.delivered ? 'delivered' : final ? 'failed' : 'retrying'\n await recordAttempt(\n firestore,\n envelope.hostId,\n doc.id,\n { id: deliveryId, eventId: envelope.id, event: envelope.event, orderId, body, prior },\n settled,\n status,\n clock(),\n )\n if (status === 'failed') {\n await notifyHostManagers(envelope.hostId, {\n type: 'content.order',\n title: 'An order webhook could not be delivered',\n body:\n `${envelope.event} never reached ${safeHost(endpoint.url)} on {site} after ` +\n `${envelope.attempt} attempts (${settled.attempt.error ?? 'no answer'}). ` +\n 'Resend it from the delivery log once the endpoint is fixed.',\n link: `/${envelope.hostId}/products/notifications`,\n }).catch(() => undefined)\n }\n return status\n }),\n )\n const delivered = outcomes.filter((status) => status === 'delivered').length\n const failed = outcomes.length - delivered\n if (failed > 0 && !final) {\n throw new Error(`${failed} of ${outcomes.length} order webhook endpoints did not take ${envelope.event}`)\n }\n return { delivered, failed }\n}\n\n/** One signed attempt at one endpoint; a missing key or secret is a failed attempt. */\nasync function attemptEndpoint(input: {\n firestore: Firestore\n hostId: string\n endpointId: string\n url: string\n keyring: SecretBoxKeyring | null\n event: string\n eventId: string\n body: string\n clock: () => number\n fetchImpl?: typeof fetchConfiguredPublicUrl\n}): Promise<OrderWebhookPostResult> {\n const failed = (error: string): OrderWebhookPostResult => ({\n delivered: false,\n attempt: { atMs: input.clock(), httpStatus: null, error, durationMs: 0 },\n })\n if (!input.keyring) return failed('Webhook signing is not configured')\n let secret: string\n try {\n secret = await readSecret(input.firestore, input.hostId, input.endpointId, input.keyring)\n } catch (error) {\n return failed(`The signing secret could not be read: ${String((error as Error)?.message ?? error).slice(0, 120)}`)\n }\n return postOrderWebhook({\n url: input.url,\n secret,\n event: input.event,\n eventId: input.eventId,\n body: input.body,\n fetchImpl: input.fetchImpl,\n now: input.clock,\n })\n}\n\nfunction safeHost(url: string): string {\n try {\n return new URL(url).hostname\n } catch {\n return 'the endpoint'\n }\n}\n\n// ---------------------------------------------------------------------------\n// The console's door\n// ---------------------------------------------------------------------------\n\nconst ACTIONS = ['status', 'create', 'update', 'roll-secret', 'delete', 'test', 'resend'] as const\ntype Action = (typeof ACTIONS)[number]\n\nconst isId = (value: string) => Boolean(value) && value.length <= 1500 && !/^__.*__$/.test(value) && !value.includes('/')\n\nfunction cleanUrl(raw: unknown): { url: string } | { error: string } {\n const url = String(raw ?? '').trim()\n if (!url) return { error: 'Enter the endpoint’s address' }\n if (url.length > 2048) return { error: 'That address is too long' }\n const refusal = configuredUrlRefusal(url)\n if (refusal) return { error: `This endpoint cannot be used: ${describeConfiguredUrlRefusal(refusal)}` }\n return { url }\n}\n\nconst cleanDescription = (raw: unknown) => String(raw ?? '').trim().slice(0, 120)\n\n/**\n * `POST /api/commerce/order-webhooks` with `{ hostId, action, … }`. Endpoints\n * post the order book to an outside server, so only an admin of the whole\n * workspace manages them — the bar a refund sets.\n *\n * - `status` → `{ configured, events: [{ event, label, description }] }`\n * - `create` `{ url, events, description? }` → `{ id, secret }` (shown once)\n * - `update` `{ endpointId, url?, events?, enabled?, description? }`\n * - `roll-secret` `{ endpointId }` → `{ secret }`\n * - `delete` `{ endpointId }`; the delivery log stays until it expires\n * - `test` `{ endpointId }` → posts a `webhook.test` event now\n * - `resend` `{ deliveryId }` → posts a logged delivery again now\n */\nexport const orderWebhooksHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })\n const authorization = String(req.headers.authorization ?? '')\n const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : undefined\n if (!idToken) return res.status(401).json({ error: 'Unauthenticated' })\n let body: Record<string, any>\n try {\n body = (typeof req.body === 'string' ? JSON.parse(req.body) : req.body) ?? {}\n } catch {\n return res.status(400).json({ error: 'Invalid JSON' })\n }\n const hostId = String(body.hostId ?? '')\n const action = String(body.action ?? '') as Action\n if (!isId(hostId)) return res.status(400).json({ error: 'Missing hostId' })\n if (!ACTIONS.includes(action)) return res.status(400).json({ error: 'Unknown action' })\n try {\n const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, hostId)\n const hostSnapshot = await hostRef.get()\n if (!hostSnapshot.exists) return res.status(404).json({ error: 'Unknown site' })\n if ((hostSnapshot.get('memberRoles') ?? {})[decoded.uid] !== 'admin') {\n return res.status(403).json({ error: 'Webhooks are managed by a site admin' })\n }\n const membership = await resolveOrgPermissions(decoded.uid, { hostId })\n if (!membership.orgWide || membership.hostRole !== 'admin') {\n return res.status(403).json({ error: 'Webhooks are managed by an admin of the whole workspace' })\n }\n const keyring = readCommerceSecretKeyring()\n if (action === 'status') {\n return res.status(200).json({\n configured: Boolean(keyring),\n maxEndpoints: Webhooks.ORDER_WEBHOOK_MAX_ENDPOINTS,\n events: COMMERCE_EVENT_DECLARATIONS.map((entry) => ({\n event: entry.event.id,\n label: entry.label,\n description: entry.description,\n })),\n })\n }\n if (!keyring) {\n return res.status(503).json({ error: 'Order webhooks are not configured on this deployment' })\n }\n const now = Date.now()\n const endpoints = hostRef.collection('orderWebhooks')\n\n if (action === 'create') {\n const url = cleanUrl(body.url)\n if ('error' in url) return res.status(400).json({ error: url.error })\n const events = Webhooks.normalizeOrderWebhookEvents(body.events)\n if (events.length === 0) return res.status(400).json({ error: 'Choose at least one event' })\n const secret = mintOrderWebhookSecret()\n const ref = endpoints.doc(createResourceUid())\n const created = await firestore.runTransaction(async (transaction) => {\n const existing = await transaction.get(endpoints.limit(Webhooks.ORDER_WEBHOOK_MAX_ENDPOINTS))\n if (existing.size >= Webhooks.ORDER_WEBHOOK_MAX_ENDPOINTS) return false\n const endpoint: Webhooks.OrderWebhookEndpoint = {\n url: url.url,\n events,\n enabled: true,\n ...(cleanDescription(body.description) ? { description: cleanDescription(body.description) } : {}),\n secretHint: secret.slice(-4),\n consecutiveFailures: 0,\n createdAtMs: now,\n updatedAtMs: now,\n createdBy: decoded.uid,\n }\n transaction.create(ref, endpoint)\n transaction.create(hostRef.collection('orderWebhookSecrets').doc(ref.id), sealedSecretRecord(hostId, ref.id, secret, keyring, now))\n return true\n })\n if (!created) {\n return res.status(409).json({ error: `A store can keep ${Webhooks.ORDER_WEBHOOK_MAX_ENDPOINTS} webhook endpoints` })\n }\n return res.status(200).json({ ok: true, id: ref.id, secret })\n }\n\n if (action === 'resend') {\n const deliveryId = String(body.deliveryId ?? '')\n if (!isId(deliveryId)) return res.status(400).json({ error: 'Missing deliveryId' })\n const deliveryRef = hostRef.collection('orderWebhookDeliveries').doc(deliveryId)\n const deliverySnapshot = await deliveryRef.get()\n if (!deliverySnapshot.exists) return res.status(404).json({ error: 'Unknown delivery' })\n const delivery = deliverySnapshot.data() as Webhooks.OrderWebhookDelivery\n const endpointSnapshot = await endpoints.doc(delivery.endpointId).get()\n if (!endpointSnapshot.exists) return res.status(404).json({ error: 'That endpoint was deleted' })\n if (delivery.body.length >= Webhooks.ORDER_WEBHOOK_BODY_MAX) {\n return res.status(409).json({ error: 'This delivery was too large to keep, so it cannot be resent' })\n }\n const endpoint = endpointSnapshot.data() as Webhooks.OrderWebhookEndpoint\n const secret = await readSecret(firestore, hostId, delivery.endpointId, keyring)\n const result = await postOrderWebhook({ url: endpoint.url, secret, event: delivery.event, eventId: delivery.eventId, body: delivery.body })\n const status: Webhooks.OrderWebhookDeliveryStatus = result.delivered\n ? 'delivered'\n : delivery.status === 'delivered'\n ? 'delivered'\n : delivery.status\n await recordAttempt(\n firestore,\n hostId,\n delivery.endpointId,\n { id: deliveryId, eventId: delivery.eventId, event: delivery.event, orderId: delivery.orderId, body: delivery.body, test: delivery.test, prior: delivery },\n result,\n status,\n Date.now(),\n )\n return res.status(200).json({ ok: true, delivered: result.delivered, attempt: result.attempt })\n }\n\n const endpointId = String(body.endpointId ?? '')\n if (!isId(endpointId)) return res.status(400).json({ error: 'Missing endpointId' })\n const endpointRef = endpoints.doc(endpointId)\n const endpointSnapshot = await endpointRef.get()\n if (!endpointSnapshot.exists) return res.status(404).json({ error: 'Unknown endpoint' })\n const endpoint = endpointSnapshot.data() as Webhooks.OrderWebhookEndpoint\n\n if (action === 'update') {\n const patch: Partial<Webhooks.OrderWebhookEndpoint> = { updatedAtMs: now }\n if (body.url !== undefined) {\n const url = cleanUrl(body.url)\n if ('error' in url) return res.status(400).json({ error: url.error })\n patch.url = url.url\n }\n if (body.events !== undefined) {\n const events = Webhooks.normalizeOrderWebhookEvents(body.events)\n if (events.length === 0) return res.status(400).json({ error: 'Choose at least one event' })\n patch.events = events\n }\n if (body.enabled !== undefined) {\n patch.enabled = Boolean(body.enabled)\n if (patch.enabled) patch.consecutiveFailures = 0\n }\n if (body.description !== undefined) patch.description = cleanDescription(body.description)\n await endpointRef.update(patch)\n return res.status(200).json({ ok: true })\n }\n\n if (action === 'roll-secret') {\n const secret = mintOrderWebhookSecret()\n const batch = firestore.batch()\n batch.set(hostRef.collection('orderWebhookSecrets').doc(endpointId), sealedSecretRecord(hostId, endpointId, secret, keyring, now))\n batch.update(endpointRef, { secretHint: secret.slice(-4), updatedAtMs: now })\n await batch.commit()\n return res.status(200).json({ ok: true, secret })\n }\n\n if (action === 'delete') {\n const batch = firestore.batch()\n batch.delete(endpointRef)\n batch.delete(hostRef.collection('orderWebhookSecrets').doc(endpointId))\n await batch.commit()\n return res.status(200).json({ ok: true })\n }\n\n // test\n const eventId = `test_${randomBytes(9).toString('base64url')}`\n const testBody = Webhooks.orderWebhookBody({\n eventId,\n event: Webhooks.ORDER_WEBHOOK_TEST_EVENT,\n occurredAtMs: now,\n hostId,\n payload: { message: `A test event from ${PLATFORM_BRAND_NAME}. Answer with any 2xx status.` },\n })\n const secret = await readSecret(firestore, hostId, endpointId, keyring)\n const result = await postOrderWebhook({ url: endpoint.url, secret, event: Webhooks.ORDER_WEBHOOK_TEST_EVENT, eventId, body: testBody })\n await recordAttempt(\n firestore,\n hostId,\n endpointId,\n { id: Webhooks.orderWebhookDeliveryId(eventId, endpointId), eventId, event: Webhooks.ORDER_WEBHOOK_TEST_EVENT, orderId: null, body: testBody, test: true, prior: null },\n result,\n result.delivered ? 'delivered' : 'failed',\n Date.now(),\n )\n return res.status(200).json({ ok: true, delivered: result.delivered, attempt: result.attempt })\n } catch (error) {\n console.error('order webhooks action failed', action, error)\n return res.status(500).json({ error: 'The webhook could not be updated. Please try again.' })\n }\n}\n"],"names":["createResourceUid","PLATFORM_BRAND_NAME","describeConfiguredUrlRefusal","configuredUrlRefusal","fetchConfiguredPublicUrl","firebaseAdmin","notifyHostManagers","PLUGIN_EVENT_MAX_ATTEMPTS","resolveOrgPermissions","createSecretBoxKey","openSecret","parseSecretBoxKeyring","sealSecret","SECRET_BOX_KEY_BYTES","createHmac","hkdfSync","randomBytes","COMMERCE_EVENT_DECLARATIONS","Webhooks","COMMERCE_SECRET_KEY_ENV","SECRETS","ORDER_WEBHOOK_LOG_RETENTION_MS","DERIVED_COMMERCE_KEY_ID","derivedCommerceKey","process","base","String","env","material","Uint8Array","readCommerceSecretKeyring","derived","raw","trim","ring","keys","some","key","id","current","orderWebhooksConfigured","sealContext","hostId","endpointId","mintOrderWebhookSecret","toString","signOrderWebhook","secret","timestampSeconds","body","update","orderWebhookSignedPayload","digest","hostRefFor","firestore","collection","doc","readSecret","keyring","snapshot","hostRef","get","sealed","Error","context","plaintext","sealedSecretRecord","now","sealedSecret","secretKeyId","updatedAtMs","postOrderWebhook","input","clock","Date","startedAt","timestamp","Math","floor","signature","formatOrderWebhookSignature","httpStatus","error","result","fetchImpl","url","method","headers","ORDER_WEBHOOK_SIGNATURE_HEADER","ORDER_WEBHOOK_EVENT_HEADER","event","ORDER_WEBHOOK_EVENT_ID_HEADER","eventId","signal","AbortSignal","timeout","ORDER_WEBHOOK_TIMEOUT_MS","refusal","status","orderWebhookAccepted","caught","name","message","slice","attempt","atMs","durationMs","max","delivered","expiresAt","Timestamp","fromMillis","recordAttempt","delivery","row","orderId","attempts","appendOrderWebhookAttempt","prior","ORDER_WEBHOOK_BODY_MAX","test","createdAtMs","set","lastDeliveryAtMs","lastDeliveryStatus","consecutiveFailures","FieldValue","increment","catch","undefined","deliverOrderEventToWebhooks","envelope","deps","app","endpoints","where","taking","docs","filter","orderWebhookTakes","data","occurredAtMs","length","failed","final","orderWebhookBody","payload","order","outcomes","Promise","all","map","endpoint","deliveryId","orderWebhookDeliveryId","priorSnapshot","exists","settled","attemptEndpoint","type","title","safeHost","link","URL","hostname","ACTIONS","isId","value","Boolean","includes","cleanUrl","cleanDescription","orderWebhooksHandler","req","res","json","authorization","idToken","startsWith","JSON","parse","action","hostSnapshot","decoded","auth","verifyIdToken","uid","membership","orgWide","hostRole","configured","maxEndpoints","ORDER_WEBHOOK_MAX_ENDPOINTS","events","entry","label","description","normalizeOrderWebhookEvents","ref","created","runTransaction","transaction","existing","limit","size","enabled","secretHint","createdBy","create","ok","deliveryRef","deliverySnapshot","endpointSnapshot","endpointRef","patch","batch","commit","delete","testBody","ORDER_WEBHOOK_TEST_EVENT","console"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/order-webhooks.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 { createResourceUid } from '@aglyn/aglyn/app-utils/create-resource-uid'\nimport { PLATFORM_BRAND_NAME } from '@aglyn/aglyn/app-utils/platform-brand'\nimport type { PluginApiHandler } from '@aglyn/aglyn/server'\nimport type { PluginDomainEventEnvelope } from '@aglyn/aglyn/plugin-manager/plugin-domain-events'\nimport {\n describeConfiguredUrlRefusal,\n configuredUrlRefusal,\n fetchConfiguredPublicUrl,\n firebaseAdmin,\n notifyHostManagers,\n} from '@aglyn/tenant-data-admin'\nimport { PLUGIN_EVENT_MAX_ATTEMPTS } from '@aglyn/tenant-data-admin/server/plugin-event-outbox'\nimport { resolveOrgPermissions } from '@aglyn/tenant-runtime/org-permissions'\nimport {\n createSecretBoxKey,\n openSecret,\n parseSecretBoxKeyring,\n sealSecret,\n SECRET_BOX_KEY_BYTES,\n type SecretBoxKey,\n type SecretBoxKeyring,\n} from '@aglyn/shared-util-tools/secret-box'\nimport { createHmac, hkdfSync, randomBytes } from 'node:crypto'\nimport { COMMERCE_EVENT_DECLARATIONS } from '../model/order-events'\nimport * as Webhooks from '../model/order-webhooks'\nimport { commerceWorkspacePermissionRefusal } from '../model/workspace-site-permissions'\nimport { holdsCommerceWorkspaceSiteKey } from './commerce-site-keys'\n\n/**\n * Merchant order webhooks (AGL-3611): the console's door and the delivery\n * behind it. The model (`model/order-webhooks.ts`) says what is stored where.\n *\n * DELIVERY RIDES THE PLUGIN EVENT OUTBOX. Commerce subscribes to its own\n * order and return events under the name `webhooks`; the subscriber posts the\n * event to every endpoint that takes it and records each attempt in the\n * delivery log. An endpoint that already took an event is not posted it\n * again, so when one of three endpoints fails, the subscriber throws, the\n * outbox retries it with its backoff (30s, 2m, 10m, 30m, 1h, 6h, 12h), and\n * only the failing endpoint is called again. On the last attempt the delivery\n * is marked failed and the site's managers are told.\n *\n * EVERY CALL GOES THROUGH `fetchConfiguredPublicUrl`: https on the default\n * port, a public address pinned at connect time, no redirect followed. A\n * merchant's endpoint is a stranger's server to us.\n *\n * THE SECRET IS SEALED with the shared secret box, under the keyring\n * `readCommerceSecretKeyring` answers, bound to its endpoint by the seal's\n * context. The plaintext leaves the server once, in the answer to the request\n * that made or rolled it.\n */\n\nexport const COMMERCE_SECRET_KEY_ENV = 'COMMERCE_SECRET_KEY'\n\nconst SECRETS = 'orderWebhookSecrets'\n\n/** Delivery rows live this long, then Firestore's TTL removes them. */\nexport const ORDER_WEBHOOK_LOG_RETENTION_MS = 30 * 86_400_000\n\ntype Firestore = FirebaseFirestore.Firestore\n\n/** The id of the key derived from `TOKEN_SIGNING_SECRET`. */\nexport const DERIVED_COMMERCE_KEY_ID = 'tss1'\n\n/**\n * A secret-box key derived from `TOKEN_SIGNING_SECRET` with HKDF, under its\n * own label, so the commerce tokens and the sealed secrets never share key\n * material. `null` when that secret is unset.\n */\nfunction derivedCommerceKey(): SecretBoxKey | null {\n const base = String(process.env['TOKEN_SIGNING_SECRET'] ?? '')\n if (!base) return null\n const material = new Uint8Array(hkdfSync('sha256', base, 'aglyn-commerce', 'secret-box:v1', SECRET_BOX_KEY_BYTES))\n return createSecretBoxKey(material, DERIVED_COMMERCE_KEY_ID)\n}\n\n/**\n * The keyring commerce seals its stored secrets with. `COMMERCE_SECRET_KEY`\n * (a secret-box keyring) when it is set, its first key sealing; otherwise the\n * key derived from `TOKEN_SIGNING_SECRET`, which every deployment that sells\n * already has. The derived key stays in the ring after a dedicated key is\n * configured, so what it sealed still opens. `null` when neither is usable.\n * Never throws.\n */\nexport function readCommerceSecretKeyring(): SecretBoxKeyring | null {\n let derived: SecretBoxKey | null = null\n try {\n derived = derivedCommerceKey()\n } catch {\n derived = null\n }\n const raw = String(process.env[COMMERCE_SECRET_KEY_ENV] ?? '').trim()\n if (raw) {\n try {\n const ring = parseSecretBoxKeyring(raw)\n const keys = derived && !ring.keys.some((key) => key.id === derived!.id) ? [...ring.keys, derived] : ring.keys\n return { current: ring.current, keys }\n } catch {\n // An unusable dedicated key falls back to the derived one rather than\n // sealing nothing.\n }\n }\n return derived ? { current: derived, keys: [derived] } : null\n}\n\n/** Whether this deployment can sign webhooks at all. */\nexport function orderWebhooksConfigured(): boolean {\n return readCommerceSecretKeyring() !== null\n}\n\nconst sealContext = (hostId: string, endpointId: string) => `hosts/${hostId}/${SECRETS}/${endpointId}#secret`\n\n/** A fresh signing secret: `whsec_` and 32 random bytes. */\nexport function mintOrderWebhookSecret(): string {\n return `whsec_${randomBytes(32).toString('base64url')}`\n}\n\n/** The HMAC-SHA256 of `{t}.{body}` under the secret, as hex. */\nexport function signOrderWebhook(secret: string, timestampSeconds: number, body: string): string {\n return createHmac('sha256', secret).update(Webhooks.orderWebhookSignedPayload(timestampSeconds, body)).digest('hex')\n}\n\nconst hostRefFor = (firestore: Firestore, hostId: string) => firestore.collection('hosts').doc(hostId)\n\nasync function readSecret(\n firestore: Firestore,\n hostId: string,\n endpointId: string,\n keyring: SecretBoxKeyring,\n): Promise<string> {\n const hostRef = hostRefFor(firestore, hostId)\n const snapshot = await hostRef.collection('orderWebhookSecrets').doc(endpointId).get()\n const sealed = String(snapshot.get('sealedSecret') ?? '')\n if (!sealed) throw new Error('This endpoint has no signing secret')\n return openSecret(sealed, keyring, { context: sealContext(hostId, endpointId) }).plaintext\n}\n\nfunction sealedSecretRecord(\n hostId: string,\n endpointId: string,\n secret: string,\n keyring: SecretBoxKeyring,\n now: number,\n): Webhooks.OrderWebhookSecretRecord {\n return {\n sealedSecret: sealSecret(secret, keyring.current, { context: sealContext(hostId, endpointId) }),\n secretKeyId: keyring.current.id,\n updatedAtMs: now,\n }\n}\n\n/** What one POST came to. */\nexport interface OrderWebhookPostResult {\n attempt: Webhooks.OrderWebhookAttempt\n delivered: boolean\n}\n\n/**\n * Posts one body to one endpoint, signed. Never throws: a refusal, a timeout\n * or a reset is an attempt that failed, with the reason in words.\n */\nexport async function postOrderWebhook(input: {\n url: string\n secret: string\n event: string\n eventId: string\n body: string\n now?: () => number\n fetchImpl?: typeof fetchConfiguredPublicUrl\n}): Promise<OrderWebhookPostResult> {\n const clock = input.now ?? Date.now\n const startedAt = clock()\n const timestamp = Math.floor(startedAt / 1000)\n const signature = Webhooks.formatOrderWebhookSignature(timestamp, signOrderWebhook(input.secret, timestamp, input.body))\n let httpStatus: number | null = null\n let error: string | undefined\n try {\n const result = await (input.fetchImpl ?? fetchConfiguredPublicUrl)(input.url, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'user-agent': 'Aglyn-Webhooks/1.0',\n [Webhooks.ORDER_WEBHOOK_SIGNATURE_HEADER]: signature,\n [Webhooks.ORDER_WEBHOOK_EVENT_HEADER]: input.event,\n [Webhooks.ORDER_WEBHOOK_EVENT_ID_HEADER]: input.eventId,\n },\n body: input.body,\n signal: AbortSignal.timeout(Webhooks.ORDER_WEBHOOK_TIMEOUT_MS),\n })\n if ('refusal' in result) {\n error = `Not sent: ${describeConfiguredUrlRefusal(result.refusal)}`\n } else {\n httpStatus = result.status\n if (!Webhooks.orderWebhookAccepted(httpStatus)) {\n error =\n httpStatus >= 300 && httpStatus < 400\n ? `The endpoint answered ${httpStatus}, a redirect; redirects are not followed`\n : `The endpoint answered ${httpStatus}`\n }\n }\n } catch (caught) {\n const name = (caught as Error)?.name\n error =\n name === 'TimeoutError' || name === 'AbortError'\n ? `No answer within ${Webhooks.ORDER_WEBHOOK_TIMEOUT_MS / 1000} seconds`\n : `The connection failed: ${String((caught as Error)?.message ?? caught).slice(0, 200)}`\n }\n const attempt: Webhooks.OrderWebhookAttempt = {\n atMs: startedAt,\n httpStatus,\n ...(error ? { error } : {}),\n durationMs: Math.max(0, clock() - startedAt),\n }\n return { attempt, delivered: !error }\n}\n\nfunction expiresAt(now: number) {\n return firebaseAdmin.firestore.Timestamp.fromMillis(now + ORDER_WEBHOOK_LOG_RETENTION_MS)\n}\n\n/** Records an attempt on the delivery row and on the endpoint's summary. */\nasync function recordAttempt(\n firestore: Firestore,\n hostId: string,\n endpointId: string,\n delivery: {\n id: string\n eventId: string\n event: string\n orderId: string | null\n body: string\n test?: boolean\n prior: Webhooks.OrderWebhookDelivery | null\n },\n result: OrderWebhookPostResult,\n status: Webhooks.OrderWebhookDeliveryStatus,\n now: number,\n): Promise<void> {\n const hostRef = hostRefFor(firestore, hostId)\n const row: Webhooks.OrderWebhookDelivery & { expiresAt: unknown } = {\n endpointId,\n eventId: delivery.eventId,\n event: delivery.event,\n orderId: delivery.orderId,\n status,\n attempts: Webhooks.appendOrderWebhookAttempt(delivery.prior?.attempts, result.attempt),\n body: delivery.body.slice(0, Webhooks.ORDER_WEBHOOK_BODY_MAX),\n ...(delivery.test ? { test: true } : {}),\n createdAtMs: delivery.prior?.createdAtMs ?? now,\n updatedAtMs: now,\n expiresAt: expiresAt(now),\n }\n await hostRef.collection('orderWebhookDeliveries').doc(delivery.id).set(row)\n await hostRef\n .collection('orderWebhooks')\n .doc(endpointId)\n .update({\n lastDeliveryAtMs: now,\n lastDeliveryStatus: status,\n consecutiveFailures: result.delivered ? 0 : firebaseAdmin.firestore.FieldValue.increment(1),\n })\n .catch(() => undefined)\n}\n\n/**\n * The subscriber: posts one event to every endpoint of the site that takes\n * it and has not taken it already. Throws when any endpoint still owes it, so\n * the outbox retries; on the outbox's last attempt it records the failure and\n * tells the site's managers instead.\n */\nexport async function deliverOrderEventToWebhooks(\n envelope: PluginDomainEventEnvelope,\n deps: { fetchImpl?: typeof fetchConfiguredPublicUrl; now?: () => number } = {},\n): Promise<{ delivered: number; failed: number }> {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, envelope.hostId)\n const endpoints = await hostRef.collection('orderWebhooks').where('enabled', '==', true).get()\n const taking = endpoints.docs.filter((doc) =>\n Webhooks.orderWebhookTakes(doc.data() as Webhooks.OrderWebhookEndpoint, envelope.event, envelope.occurredAtMs),\n )\n if (taking.length === 0) return { delivered: 0, failed: 0 }\n const keyring = readCommerceSecretKeyring()\n const clock = deps.now ?? Date.now\n const final = envelope.attempt >= PLUGIN_EVENT_MAX_ATTEMPTS\n const body = Webhooks.orderWebhookBody({\n eventId: envelope.id,\n event: envelope.event,\n occurredAtMs: envelope.occurredAtMs,\n hostId: envelope.hostId,\n payload: envelope.payload,\n })\n const orderId = String(((envelope.payload ?? {}) as { order?: { id?: unknown } }).order?.id ?? '') || null\n const outcomes = await Promise.all(\n taking.map(async (doc) => {\n const endpoint = doc.data() as Webhooks.OrderWebhookEndpoint\n const deliveryId = Webhooks.orderWebhookDeliveryId(envelope.id, doc.id)\n const priorSnapshot = await hostRef.collection('orderWebhookDeliveries').doc(deliveryId).get()\n const prior = priorSnapshot.exists ? (priorSnapshot.data() as Webhooks.OrderWebhookDelivery) : null\n // Taken already, on an earlier pass or by a resend from the console.\n if (prior?.status === 'delivered') return 'delivered' as const\n const settled = await attemptEndpoint({\n firestore,\n hostId: envelope.hostId,\n endpointId: doc.id,\n url: endpoint.url,\n keyring,\n event: envelope.event,\n eventId: envelope.id,\n body,\n clock,\n fetchImpl: deps.fetchImpl,\n })\n const status: Webhooks.OrderWebhookDeliveryStatus = settled.delivered ? 'delivered' : final ? 'failed' : 'retrying'\n await recordAttempt(\n firestore,\n envelope.hostId,\n doc.id,\n { id: deliveryId, eventId: envelope.id, event: envelope.event, orderId, body, prior },\n settled,\n status,\n clock(),\n )\n if (status === 'failed') {\n await notifyHostManagers(envelope.hostId, {\n type: 'content.order',\n title: 'An order webhook could not be delivered',\n body:\n `${envelope.event} never reached ${safeHost(endpoint.url)} on {site} after ` +\n `${envelope.attempt} attempts (${settled.attempt.error ?? 'no answer'}). ` +\n 'Resend it from the delivery log once the endpoint is fixed.',\n link: `/${envelope.hostId}/products/notifications`,\n }).catch(() => undefined)\n }\n return status\n }),\n )\n const delivered = outcomes.filter((status) => status === 'delivered').length\n const failed = outcomes.length - delivered\n if (failed > 0 && !final) {\n throw new Error(`${failed} of ${outcomes.length} order webhook endpoints did not take ${envelope.event}`)\n }\n return { delivered, failed }\n}\n\n/** One signed attempt at one endpoint; a missing key or secret is a failed attempt. */\nasync function attemptEndpoint(input: {\n firestore: Firestore\n hostId: string\n endpointId: string\n url: string\n keyring: SecretBoxKeyring | null\n event: string\n eventId: string\n body: string\n clock: () => number\n fetchImpl?: typeof fetchConfiguredPublicUrl\n}): Promise<OrderWebhookPostResult> {\n const failed = (error: string): OrderWebhookPostResult => ({\n delivered: false,\n attempt: { atMs: input.clock(), httpStatus: null, error, durationMs: 0 },\n })\n if (!input.keyring) return failed('Webhook signing is not configured')\n let secret: string\n try {\n secret = await readSecret(input.firestore, input.hostId, input.endpointId, input.keyring)\n } catch (error) {\n return failed(`The signing secret could not be read: ${String((error as Error)?.message ?? error).slice(0, 120)}`)\n }\n return postOrderWebhook({\n url: input.url,\n secret,\n event: input.event,\n eventId: input.eventId,\n body: input.body,\n fetchImpl: input.fetchImpl,\n now: input.clock,\n })\n}\n\nfunction safeHost(url: string): string {\n try {\n return new URL(url).hostname\n } catch {\n return 'the endpoint'\n }\n}\n\n// ---------------------------------------------------------------------------\n// The console's door\n// ---------------------------------------------------------------------------\n\nconst ACTIONS = ['status', 'create', 'update', 'roll-secret', 'delete', 'test', 'resend'] as const\ntype Action = (typeof ACTIONS)[number]\n\nconst isId = (value: string) => Boolean(value) && value.length <= 1500 && !/^__.*__$/.test(value) && !value.includes('/')\n\nfunction cleanUrl(raw: unknown): { url: string } | { error: string } {\n const url = String(raw ?? '').trim()\n if (!url) return { error: 'Enter the endpoint’s address' }\n if (url.length > 2048) return { error: 'That address is too long' }\n const refusal = configuredUrlRefusal(url)\n if (refusal) return { error: `This endpoint cannot be used: ${describeConfiguredUrlRefusal(refusal)}` }\n return { url }\n}\n\nconst cleanDescription = (raw: unknown) => String(raw ?? '').trim().slice(0, 120)\n\n/**\n * `POST /api/commerce/order-webhooks` with `{ hostId, action, … }`. Endpoints\n * post the order book to an outside server, so only an admin of the whole\n * workspace manages them — the bar a refund sets.\n *\n * - `status` → `{ configured, events: [{ event, label, description }] }`\n * - `create` `{ url, events, description? }` → `{ id, secret }` (shown once)\n * - `update` `{ endpointId, url?, events?, enabled?, description? }`\n * - `roll-secret` `{ endpointId }` → `{ secret }`\n * - `delete` `{ endpointId }`; the delivery log stays until it expires\n * - `test` `{ endpointId }` → posts a `webhook.test` event now\n * - `resend` `{ deliveryId }` → posts a logged delivery again now\n */\nexport const orderWebhooksHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })\n const authorization = String(req.headers.authorization ?? '')\n const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : undefined\n if (!idToken) return res.status(401).json({ error: 'Unauthenticated' })\n let body: Record<string, any>\n try {\n body = (typeof req.body === 'string' ? JSON.parse(req.body) : req.body) ?? {}\n } catch {\n return res.status(400).json({ error: 'Invalid JSON' })\n }\n const hostId = String(body.hostId ?? '')\n const action = String(body.action ?? '') as Action\n if (!isId(hostId)) return res.status(400).json({ error: 'Missing hostId' })\n if (!ACTIONS.includes(action)) return res.status(400).json({ error: 'Unknown action' })\n try {\n const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = hostRefFor(firestore, hostId)\n const hostSnapshot = await hostRef.get()\n if (!hostSnapshot.exists) return res.status(404).json({ error: 'Unknown site' })\n // \"Manage order webhooks\" (`commerce.webhooks`, AGL-4047): its preset is\n // the gate this asked before, the site's Admin who is a member of the\n // whole workspace (a webhook's secret signs every order it is sent).\n const membership = await resolveOrgPermissions(decoded.uid, { hostId })\n if (!holdsCommerceWorkspaceSiteKey(hostSnapshot, decoded.uid, 'commerce.webhooks', membership)) {\n return res.status(403).json({ error: commerceWorkspacePermissionRefusal('commerce.webhooks') })\n }\n const keyring = readCommerceSecretKeyring()\n if (action === 'status') {\n return res.status(200).json({\n configured: Boolean(keyring),\n maxEndpoints: Webhooks.ORDER_WEBHOOK_MAX_ENDPOINTS,\n events: COMMERCE_EVENT_DECLARATIONS.map((entry) => ({\n event: entry.event.id,\n label: entry.label,\n description: entry.description,\n })),\n })\n }\n if (!keyring) {\n return res.status(503).json({ error: 'Order webhooks are not configured on this deployment' })\n }\n const now = Date.now()\n const endpoints = hostRef.collection('orderWebhooks')\n\n if (action === 'create') {\n const url = cleanUrl(body.url)\n if ('error' in url) return res.status(400).json({ error: url.error })\n const events = Webhooks.normalizeOrderWebhookEvents(body.events)\n if (events.length === 0) return res.status(400).json({ error: 'Choose at least one event' })\n const secret = mintOrderWebhookSecret()\n const ref = endpoints.doc(createResourceUid())\n const created = await firestore.runTransaction(async (transaction) => {\n const existing = await transaction.get(endpoints.limit(Webhooks.ORDER_WEBHOOK_MAX_ENDPOINTS))\n if (existing.size >= Webhooks.ORDER_WEBHOOK_MAX_ENDPOINTS) return false\n const endpoint: Webhooks.OrderWebhookEndpoint = {\n url: url.url,\n events,\n enabled: true,\n ...(cleanDescription(body.description) ? { description: cleanDescription(body.description) } : {}),\n secretHint: secret.slice(-4),\n consecutiveFailures: 0,\n createdAtMs: now,\n updatedAtMs: now,\n createdBy: decoded.uid,\n }\n transaction.create(ref, endpoint)\n transaction.create(hostRef.collection('orderWebhookSecrets').doc(ref.id), sealedSecretRecord(hostId, ref.id, secret, keyring, now))\n return true\n })\n if (!created) {\n return res.status(409).json({ error: `A store can keep ${Webhooks.ORDER_WEBHOOK_MAX_ENDPOINTS} webhook endpoints` })\n }\n return res.status(200).json({ ok: true, id: ref.id, secret })\n }\n\n if (action === 'resend') {\n const deliveryId = String(body.deliveryId ?? '')\n if (!isId(deliveryId)) return res.status(400).json({ error: 'Missing deliveryId' })\n const deliveryRef = hostRef.collection('orderWebhookDeliveries').doc(deliveryId)\n const deliverySnapshot = await deliveryRef.get()\n if (!deliverySnapshot.exists) return res.status(404).json({ error: 'Unknown delivery' })\n const delivery = deliverySnapshot.data() as Webhooks.OrderWebhookDelivery\n const endpointSnapshot = await endpoints.doc(delivery.endpointId).get()\n if (!endpointSnapshot.exists) return res.status(404).json({ error: 'That endpoint was deleted' })\n if (delivery.body.length >= Webhooks.ORDER_WEBHOOK_BODY_MAX) {\n return res.status(409).json({ error: 'This delivery was too large to keep, so it cannot be resent' })\n }\n const endpoint = endpointSnapshot.data() as Webhooks.OrderWebhookEndpoint\n const secret = await readSecret(firestore, hostId, delivery.endpointId, keyring)\n const result = await postOrderWebhook({ url: endpoint.url, secret, event: delivery.event, eventId: delivery.eventId, body: delivery.body })\n const status: Webhooks.OrderWebhookDeliveryStatus = result.delivered\n ? 'delivered'\n : delivery.status === 'delivered'\n ? 'delivered'\n : delivery.status\n await recordAttempt(\n firestore,\n hostId,\n delivery.endpointId,\n { id: deliveryId, eventId: delivery.eventId, event: delivery.event, orderId: delivery.orderId, body: delivery.body, test: delivery.test, prior: delivery },\n result,\n status,\n Date.now(),\n )\n return res.status(200).json({ ok: true, delivered: result.delivered, attempt: result.attempt })\n }\n\n const endpointId = String(body.endpointId ?? '')\n if (!isId(endpointId)) return res.status(400).json({ error: 'Missing endpointId' })\n const endpointRef = endpoints.doc(endpointId)\n const endpointSnapshot = await endpointRef.get()\n if (!endpointSnapshot.exists) return res.status(404).json({ error: 'Unknown endpoint' })\n const endpoint = endpointSnapshot.data() as Webhooks.OrderWebhookEndpoint\n\n if (action === 'update') {\n const patch: Partial<Webhooks.OrderWebhookEndpoint> = { updatedAtMs: now }\n if (body.url !== undefined) {\n const url = cleanUrl(body.url)\n if ('error' in url) return res.status(400).json({ error: url.error })\n patch.url = url.url\n }\n if (body.events !== undefined) {\n const events = Webhooks.normalizeOrderWebhookEvents(body.events)\n if (events.length === 0) return res.status(400).json({ error: 'Choose at least one event' })\n patch.events = events\n }\n if (body.enabled !== undefined) {\n patch.enabled = Boolean(body.enabled)\n if (patch.enabled) patch.consecutiveFailures = 0\n }\n if (body.description !== undefined) patch.description = cleanDescription(body.description)\n await endpointRef.update(patch)\n return res.status(200).json({ ok: true })\n }\n\n if (action === 'roll-secret') {\n const secret = mintOrderWebhookSecret()\n const batch = firestore.batch()\n batch.set(hostRef.collection('orderWebhookSecrets').doc(endpointId), sealedSecretRecord(hostId, endpointId, secret, keyring, now))\n batch.update(endpointRef, { secretHint: secret.slice(-4), updatedAtMs: now })\n await batch.commit()\n return res.status(200).json({ ok: true, secret })\n }\n\n if (action === 'delete') {\n const batch = firestore.batch()\n batch.delete(endpointRef)\n batch.delete(hostRef.collection('orderWebhookSecrets').doc(endpointId))\n await batch.commit()\n return res.status(200).json({ ok: true })\n }\n\n // test\n const eventId = `test_${randomBytes(9).toString('base64url')}`\n const testBody = Webhooks.orderWebhookBody({\n eventId,\n event: Webhooks.ORDER_WEBHOOK_TEST_EVENT,\n occurredAtMs: now,\n hostId,\n payload: { message: `A test event from ${PLATFORM_BRAND_NAME}. Answer with any 2xx status.` },\n })\n const secret = await readSecret(firestore, hostId, endpointId, keyring)\n const result = await postOrderWebhook({ url: endpoint.url, secret, event: Webhooks.ORDER_WEBHOOK_TEST_EVENT, eventId, body: testBody })\n await recordAttempt(\n firestore,\n hostId,\n endpointId,\n { id: Webhooks.orderWebhookDeliveryId(eventId, endpointId), eventId, event: Webhooks.ORDER_WEBHOOK_TEST_EVENT, orderId: null, body: testBody, test: true, prior: null },\n result,\n result.delivered ? 'delivered' : 'failed',\n Date.now(),\n )\n return res.status(200).json({ ok: true, delivered: result.delivered, attempt: result.attempt })\n } catch (error) {\n console.error('order webhooks action failed', action, error)\n return res.status(500).json({ error: 'The webhook could not be updated. Please try again.' })\n }\n}\n"],"names":["createResourceUid","PLATFORM_BRAND_NAME","describeConfiguredUrlRefusal","configuredUrlRefusal","fetchConfiguredPublicUrl","firebaseAdmin","notifyHostManagers","PLUGIN_EVENT_MAX_ATTEMPTS","resolveOrgPermissions","createSecretBoxKey","openSecret","parseSecretBoxKeyring","sealSecret","SECRET_BOX_KEY_BYTES","createHmac","hkdfSync","randomBytes","COMMERCE_EVENT_DECLARATIONS","Webhooks","commerceWorkspacePermissionRefusal","holdsCommerceWorkspaceSiteKey","COMMERCE_SECRET_KEY_ENV","SECRETS","ORDER_WEBHOOK_LOG_RETENTION_MS","DERIVED_COMMERCE_KEY_ID","derivedCommerceKey","process","base","String","env","material","Uint8Array","readCommerceSecretKeyring","derived","raw","trim","ring","keys","some","key","id","current","orderWebhooksConfigured","sealContext","hostId","endpointId","mintOrderWebhookSecret","toString","signOrderWebhook","secret","timestampSeconds","body","update","orderWebhookSignedPayload","digest","hostRefFor","firestore","collection","doc","readSecret","keyring","snapshot","hostRef","get","sealed","Error","context","plaintext","sealedSecretRecord","now","sealedSecret","secretKeyId","updatedAtMs","postOrderWebhook","input","clock","Date","startedAt","timestamp","Math","floor","signature","formatOrderWebhookSignature","httpStatus","error","result","fetchImpl","url","method","headers","ORDER_WEBHOOK_SIGNATURE_HEADER","ORDER_WEBHOOK_EVENT_HEADER","event","ORDER_WEBHOOK_EVENT_ID_HEADER","eventId","signal","AbortSignal","timeout","ORDER_WEBHOOK_TIMEOUT_MS","refusal","status","orderWebhookAccepted","caught","name","message","slice","attempt","atMs","durationMs","max","delivered","expiresAt","Timestamp","fromMillis","recordAttempt","delivery","row","orderId","attempts","appendOrderWebhookAttempt","prior","ORDER_WEBHOOK_BODY_MAX","test","createdAtMs","set","lastDeliveryAtMs","lastDeliveryStatus","consecutiveFailures","FieldValue","increment","catch","undefined","deliverOrderEventToWebhooks","envelope","deps","app","endpoints","where","taking","docs","filter","orderWebhookTakes","data","occurredAtMs","length","failed","final","orderWebhookBody","payload","order","outcomes","Promise","all","map","endpoint","deliveryId","orderWebhookDeliveryId","priorSnapshot","exists","settled","attemptEndpoint","type","title","safeHost","link","URL","hostname","ACTIONS","isId","value","Boolean","includes","cleanUrl","cleanDescription","orderWebhooksHandler","req","res","json","authorization","idToken","startsWith","JSON","parse","action","decoded","auth","verifyIdToken","hostSnapshot","membership","uid","configured","maxEndpoints","ORDER_WEBHOOK_MAX_ENDPOINTS","events","entry","label","description","normalizeOrderWebhookEvents","ref","created","runTransaction","transaction","existing","limit","size","enabled","secretHint","createdBy","create","ok","deliveryRef","deliverySnapshot","endpointSnapshot","endpointRef","patch","batch","commit","delete","testBody","ORDER_WEBHOOK_TEST_EVENT","console"],"mappings":"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"}
|
|
@@ -14,7 +14,9 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
|
14
14
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
|
-
*/ import
|
|
17
|
+
*/ import { holdsCommerceSiteKey } from "./commerce-site-keys.js";
|
|
18
|
+
import { commerceSitePermissionRefusal } from "../model/plugin-permissions.js";
|
|
19
|
+
import * as Aglyn from "@aglyn/aglyn/server";
|
|
18
20
|
import { firebaseAdmin, getOrgForHost } from "@aglyn/tenant-data-admin";
|
|
19
21
|
import * as CommerceModel from "../model/index.js";
|
|
20
22
|
/*
|
|
@@ -89,16 +91,17 @@ export const ordersShippingPrepareHandler = async (req, res)=>{
|
|
|
89
91
|
error: 'Missing hostId'
|
|
90
92
|
});
|
|
91
93
|
try {
|
|
92
|
-
var _hostSnapshot_get;
|
|
93
94
|
const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken);
|
|
94
95
|
const hostSnapshot = await firebaseAdmin.app().firestore().collection('hosts').doc(hostId).get();
|
|
95
96
|
if (!hostSnapshot.exists) return res.status(404).json({
|
|
96
97
|
error: 'Unknown site'
|
|
97
98
|
});
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
// "Manage orders" (`commerce.orders`, AGL-4047).
|
|
100
|
+
if (!holdsCommerceSiteKey(hostSnapshot, decoded.uid, 'commerce.orders')) {
|
|
101
|
+
return res.status(403).json({
|
|
102
|
+
error: commerceSitePermissionRefusal('commerce.orders')
|
|
103
|
+
});
|
|
104
|
+
}
|
|
102
105
|
const owner = await getOrgForHost(hostId);
|
|
103
106
|
if (!Aglyn.checkEntitlement(owner == null ? void 0 : owner.org, 'commerce')) {
|
|
104
107
|
return res.status(403).json({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/orders-shipping-prepare.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 * as Aglyn from '@aglyn/aglyn/server'\nimport { firebaseAdmin, getOrgForHost } from '@aglyn/tenant-data-admin'\nimport * as CommerceModel from '../model'\n\n/*\n * `commerce/orders-shipping-prepare` (AGL-3613): POST `{ hostId }` stamps the\n * site's open orders written before AGL-3613 with what the shipping export\n * and a shipping tool's feed ask (`requiresShipping`, `updatedAtMs`), so the\n * indexed query finds them. The console calls it before an export for\n * shipping. Bounded to OPEN orders — the ones a shipping tool still has to\n * see — and a no-op for an order already stamped. The site's admins and\n * editors, the order book's roles.\n */\n\n/** Statuses a shipping tool still has to see an order in. */\nconst OPEN_STATUSES: readonly CommerceModel.OrderStatus[] = ['pending', 'paid', 'partially_fulfilled']\n\n/** The most open orders one `prepare` stamps; a store with more is stamped over several calls. */\nexport const PREPARE_MAX_ORDERS = 2000\n\n/**\n * Stamps the site's open orders that predate the stamp. Answers how many it\n * stamped. `updatedAtMs` is the order's creation, not now: stamping is not\n * a change ShipStation needs to hear about.\n */\nexport async function prepareOpenOrders(hostId: string): Promise<number> {\n const firestore = firebaseAdmin.app().firestore()\n const orders = firestore.collection('hosts').doc(hostId).collection('orders')\n const snapshot = await orders.where('status', 'in', [...OPEN_STATUSES]).limit(PREPARE_MAX_ORDERS).get()\n let stamped = 0\n let batch = firestore.batch()\n let inBatch = 0\n for (const doc of snapshot.docs) {\n const data = (doc.data() ?? {}) as Partial<CommerceModel.HostOrder> & { requiresShipping?: unknown; updatedAtMs?: unknown; createdAtMs?: unknown }\n if (typeof data.requiresShipping === 'boolean' && typeof data.updatedAtMs === 'number') continue\n const createdAtMs = Number(data.createdAtMs)\n batch.update(doc.ref, {\n ...(typeof data.requiresShipping === 'boolean' ? {} : { requiresShipping: CommerceModel.orderRequiresShipping(data) }),\n ...(typeof data.updatedAtMs === 'number'\n ? {}\n : { updatedAtMs: Number.isFinite(createdAtMs) && createdAtMs > 0 ? createdAtMs : Date.now() }),\n })\n stamped += 1\n inBatch += 1\n if (inBatch === 400) {\n await batch.commit()\n batch = firestore.batch()\n inBatch = 0\n }\n }\n if (inBatch) await batch.commit()\n return stamped\n}\n\nexport const ordersShippingPrepareHandler: Aglyn.PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })\n const authorization = String(req.headers.authorization ?? '')\n const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : undefined\n if (!idToken) return res.status(401).json({ error: 'Unauthenticated' })\n let body: Record<string, unknown>\n try {\n body = typeof req.body === 'string' ? JSON.parse(req.body) : (req.body ?? {})\n } catch {\n return res.status(400).json({ error: 'The request could not be read' })\n }\n const hostId = String(body['hostId'] ?? '')\n if (!/^[A-Za-z0-9_-]{1,128}$/.test(hostId)) return res.status(400).json({ error: 'Missing hostId' })\n try {\n const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n const hostSnapshot = await firebaseAdmin.app().firestore().collection('hosts').doc(hostId).get()\n if (!hostSnapshot.exists) return res.status(404).json({ error: 'Unknown site' })\n
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/server/orders-shipping-prepare.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 { holdsCommerceSiteKey } from './commerce-site-keys'\nimport { commerceSitePermissionRefusal } from '../model/plugin-permissions'\nimport * as Aglyn from '@aglyn/aglyn/server'\nimport { firebaseAdmin, getOrgForHost } from '@aglyn/tenant-data-admin'\nimport * as CommerceModel from '../model'\n\n/*\n * `commerce/orders-shipping-prepare` (AGL-3613): POST `{ hostId }` stamps the\n * site's open orders written before AGL-3613 with what the shipping export\n * and a shipping tool's feed ask (`requiresShipping`, `updatedAtMs`), so the\n * indexed query finds them. The console calls it before an export for\n * shipping. Bounded to OPEN orders — the ones a shipping tool still has to\n * see — and a no-op for an order already stamped. The site's admins and\n * editors, the order book's roles.\n */\n\n/** Statuses a shipping tool still has to see an order in. */\nconst OPEN_STATUSES: readonly CommerceModel.OrderStatus[] = ['pending', 'paid', 'partially_fulfilled']\n\n/** The most open orders one `prepare` stamps; a store with more is stamped over several calls. */\nexport const PREPARE_MAX_ORDERS = 2000\n\n/**\n * Stamps the site's open orders that predate the stamp. Answers how many it\n * stamped. `updatedAtMs` is the order's creation, not now: stamping is not\n * a change ShipStation needs to hear about.\n */\nexport async function prepareOpenOrders(hostId: string): Promise<number> {\n const firestore = firebaseAdmin.app().firestore()\n const orders = firestore.collection('hosts').doc(hostId).collection('orders')\n const snapshot = await orders.where('status', 'in', [...OPEN_STATUSES]).limit(PREPARE_MAX_ORDERS).get()\n let stamped = 0\n let batch = firestore.batch()\n let inBatch = 0\n for (const doc of snapshot.docs) {\n const data = (doc.data() ?? {}) as Partial<CommerceModel.HostOrder> & { requiresShipping?: unknown; updatedAtMs?: unknown; createdAtMs?: unknown }\n if (typeof data.requiresShipping === 'boolean' && typeof data.updatedAtMs === 'number') continue\n const createdAtMs = Number(data.createdAtMs)\n batch.update(doc.ref, {\n ...(typeof data.requiresShipping === 'boolean' ? {} : { requiresShipping: CommerceModel.orderRequiresShipping(data) }),\n ...(typeof data.updatedAtMs === 'number'\n ? {}\n : { updatedAtMs: Number.isFinite(createdAtMs) && createdAtMs > 0 ? createdAtMs : Date.now() }),\n })\n stamped += 1\n inBatch += 1\n if (inBatch === 400) {\n await batch.commit()\n batch = firestore.batch()\n inBatch = 0\n }\n }\n if (inBatch) await batch.commit()\n return stamped\n}\n\nexport const ordersShippingPrepareHandler: Aglyn.PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') return res.status(405).json({ error: 'Method not allowed' })\n const authorization = String(req.headers.authorization ?? '')\n const idToken = authorization.startsWith('Bearer ') ? authorization.slice('Bearer '.length) : undefined\n if (!idToken) return res.status(401).json({ error: 'Unauthenticated' })\n let body: Record<string, unknown>\n try {\n body = typeof req.body === 'string' ? JSON.parse(req.body) : (req.body ?? {})\n } catch {\n return res.status(400).json({ error: 'The request could not be read' })\n }\n const hostId = String(body['hostId'] ?? '')\n if (!/^[A-Za-z0-9_-]{1,128}$/.test(hostId)) return res.status(400).json({ error: 'Missing hostId' })\n try {\n const decoded = await firebaseAdmin.app().auth().verifyIdToken(idToken)\n const hostSnapshot = await firebaseAdmin.app().firestore().collection('hosts').doc(hostId).get()\n if (!hostSnapshot.exists) return res.status(404).json({ error: 'Unknown site' })\n // \"Manage orders\" (`commerce.orders`, AGL-4047).\n if (!holdsCommerceSiteKey(hostSnapshot, decoded.uid, 'commerce.orders')) {\n return res.status(403).json({ error: commerceSitePermissionRefusal('commerce.orders') })\n }\n const owner = await getOrgForHost(hostId)\n if (!Aglyn.checkEntitlement(owner?.org as never, 'commerce')) {\n return res.status(403).json({ error: 'Selling is not enabled' })\n }\n const stamped = await prepareOpenOrders(hostId)\n return res.status(200).json({ ok: true, stamped })\n } catch (error) {\n console.error('orders-shipping-prepare failed', hostId, error)\n return res.status(500).json({ error: 'That did not work. Try again.' })\n }\n}\n"],"names":["holdsCommerceSiteKey","commerceSitePermissionRefusal","Aglyn","firebaseAdmin","getOrgForHost","CommerceModel","OPEN_STATUSES","PREPARE_MAX_ORDERS","prepareOpenOrders","hostId","firestore","app","orders","collection","doc","snapshot","where","limit","get","stamped","batch","inBatch","docs","data","requiresShipping","updatedAtMs","createdAtMs","Number","update","ref","orderRequiresShipping","isFinite","Date","now","commit","ordersShippingPrepareHandler","req","res","body","method","status","json","error","authorization","String","headers","idToken","startsWith","slice","length","undefined","JSON","parse","test","decoded","auth","verifyIdToken","hostSnapshot","exists","uid","owner","checkEntitlement","org","ok","console"],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import type { TaxReturnSourceAnswer, TaxReturnSourceRequest } from '@aglyn/aglyn/plugin-manager/plugin-tax-return-sources';
|
|
18
|
+
import { type OwnStore, type OwnStoreOrderInput } from '../model/own-store-tax-summary';
|
|
19
|
+
/** The section's id, unique on the return. */
|
|
20
|
+
export declare const OWN_STORE_TAX_SECTION_ID = "ownStores";
|
|
21
|
+
/** How long before the period an own store's order is still read: a year and a quarter. */
|
|
22
|
+
export declare const OWN_STORE_LOOKBACK_MS: number;
|
|
23
|
+
/** The operator's own stores, as the deployment names them. */
|
|
24
|
+
export interface OwnStores {
|
|
25
|
+
/** The workspace named as the operator's own, or null when none is. */
|
|
26
|
+
orgId: string | null;
|
|
27
|
+
stores: OwnStore[];
|
|
28
|
+
}
|
|
29
|
+
/** Reads the operator's own stores: every site of the named workspace, with its tax origin. */
|
|
30
|
+
export declare function resolveOwnStores(env?: Record<string, string | undefined>): Promise<OwnStores>;
|
|
31
|
+
/** What the own stores' orders read for one period came to. */
|
|
32
|
+
export interface OwnStoreRead {
|
|
33
|
+
orders: OwnStoreOrderInput[];
|
|
34
|
+
truncated: boolean;
|
|
35
|
+
undatedRows: number;
|
|
36
|
+
}
|
|
37
|
+
/** Reads each own store's orders around the period. See the module note. */
|
|
38
|
+
export declare function readOwnStoreOrders(request: TaxReturnSourceRequest, stores: readonly OwnStore[]): Promise<OwnStoreRead>;
|
|
39
|
+
/**
|
|
40
|
+
* The own-stores section for one period, from records already read. Pure,
|
|
41
|
+
* so the section a preparer reads can be proved from fixtures.
|
|
42
|
+
*/
|
|
43
|
+
export declare function ownStoreTaxReturnAnswer(input: {
|
|
44
|
+
own: OwnStores;
|
|
45
|
+
read: OwnStoreRead;
|
|
46
|
+
statedBases?: ReadonlyMap<string, number>;
|
|
47
|
+
}, request: TaxReturnSourceRequest): TaxReturnSourceAnswer;
|