@aglyn/plugins-commerce 1.0.0-beta.229 → 1.0.0-beta.231
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +13 -13
- package/src/index.d.ts +0 -1
- package/src/index.js +0 -1
- package/src/index.js.map +1 -1
- package/src/lib/barcode/barcode-decode.d.ts +71 -0
- package/src/lib/barcode/barcode-decode.js +498 -0
- package/src/lib/barcode/barcode-decode.js.map +1 -0
- package/src/lib/barcode/barcode-encode.d.ts +44 -0
- package/src/lib/barcode/barcode-encode.js +138 -0
- package/src/lib/barcode/barcode-encode.js.map +1 -0
- package/src/lib/barcode/barcode-scanner.component.d.ts +23 -0
- package/src/lib/barcode/barcode-scanner.component.js +260 -0
- package/src/lib/barcode/barcode-scanner.component.js.map +1 -0
- package/src/lib/barcode/scan-button.component.d.ts +10 -0
- package/src/lib/barcode/scan-button.component.js +62 -0
- package/src/lib/barcode/scan-button.component.js.map +1 -0
- package/src/lib/barcode/scanner-wedge.d.ts +35 -0
- package/src/lib/barcode/scanner-wedge.js +108 -0
- package/src/lib/barcode/scanner-wedge.js.map +1 -0
- package/src/lib/components/account.js +10 -1
- package/src/lib/components/account.js.map +1 -1
- package/src/lib/components/cart-extras.d.ts +45 -0
- package/src/lib/components/cart-extras.js +127 -0
- package/src/lib/components/cart-extras.js.map +1 -0
- package/src/lib/components/cart.js +82 -15
- package/src/lib/components/cart.js.map +1 -1
- package/src/lib/components/checkout-return-notice.d.ts +26 -0
- package/src/lib/components/checkout-return-notice.js +48 -0
- package/src/lib/components/checkout-return-notice.js.map +1 -0
- package/src/lib/components/commerce-console-page.js +124 -0
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/commerce-console-sections.d.ts +1 -1
- package/src/lib/components/commerce-console-sections.js +4 -0
- package/src/lib/components/commerce-console-sections.js.map +1 -1
- package/src/lib/components/console/bulk-fulfill.d.ts +44 -0
- package/src/lib/components/console/bulk-fulfill.js +84 -0
- package/src/lib/components/console/bulk-fulfill.js.map +1 -0
- package/src/lib/components/console/customer-notifications-card.component.d.ts +19 -0
- package/src/lib/components/console/customer-notifications-card.component.js +149 -0
- package/src/lib/components/console/customer-notifications-card.component.js.map +1 -0
- package/src/lib/components/console/host-orders-card.component.js +84 -5
- package/src/lib/components/console/host-orders-card.component.js.map +1 -1
- package/src/lib/components/console/locations-card.component.js +164 -57
- package/src/lib/components/console/locations-card.component.js.map +1 -1
- package/src/lib/components/console/order-detail-dialog.component.js +209 -61
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
- package/src/lib/components/console/order-fulfillment-panel.component.d.ts +48 -0
- package/src/lib/components/console/order-fulfillment-panel.component.js +542 -0
- package/src/lib/components/console/order-fulfillment-panel.component.js.map +1 -0
- package/src/lib/components/console/order-invoice.component.d.ts +33 -0
- package/src/lib/components/console/order-invoice.component.js +81 -0
- package/src/lib/components/console/order-invoice.component.js.map +1 -0
- package/src/lib/components/console/order-receipt-resend.component.d.ts +21 -0
- package/src/lib/components/console/order-receipt-resend.component.js +203 -0
- package/src/lib/components/console/order-receipt-resend.component.js.map +1 -0
- package/src/lib/components/console/order-returns.component.d.ts +36 -0
- package/src/lib/components/console/order-returns.component.js +142 -0
- package/src/lib/components/console/order-returns.component.js.map +1 -0
- package/src/lib/components/console/order-shipping-actions.component.d.ts +54 -0
- package/src/lib/components/console/order-shipping-actions.component.js +149 -0
- package/src/lib/components/console/order-shipping-actions.component.js.map +1 -0
- package/src/lib/components/console/order-webhooks-card.component.d.ts +50 -0
- package/src/lib/components/console/order-webhooks-card.component.js +623 -0
- package/src/lib/components/console/order-webhooks-card.component.js.map +1 -0
- package/src/lib/components/console/order-zones.d.ts +155 -0
- package/src/lib/components/console/order-zones.js +40 -0
- package/src/lib/components/console/order-zones.js.map +1 -0
- package/src/lib/components/console/payment-methods-card.component.d.ts +67 -0
- package/src/lib/components/console/payment-methods-card.component.js +395 -0
- package/src/lib/components/console/payment-methods-card.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-api.d.ts +124 -0
- package/src/lib/components/console/pos/pos-api.js +101 -0
- package/src/lib/components/console/pos/pos-api.js.map +1 -0
- package/src/lib/components/console/pos/pos-cart-panel.component.d.ts +36 -0
- package/src/lib/components/console/pos/pos-cart-panel.component.js +160 -0
- package/src/lib/components/console/pos/pos-cart-panel.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-item-dialog.component.d.ts +39 -0
- package/src/lib/components/console/pos/pos-item-dialog.component.js +352 -0
- package/src/lib/components/console/pos/pos-item-dialog.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-product-grid.component.d.ts +47 -0
- package/src/lib/components/console/pos/pos-product-grid.component.js +272 -0
- package/src/lib/components/console/pos/pos-product-grid.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-receipt-panel.component.d.ts +27 -0
- package/src/lib/components/console/pos/pos-receipt-panel.component.js +282 -0
- package/src/lib/components/console/pos/pos-receipt-panel.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-tender-dialogs.component.d.ts +53 -0
- package/src/lib/components/console/pos/pos-tender-dialogs.component.js +445 -0
- package/src/lib/components/console/pos/pos-tender-dialogs.component.js.map +1 -0
- package/src/lib/components/console/pos/pos-tender-panel.component.d.ts +31 -0
- package/src/lib/components/console/pos/pos-tender-panel.component.js +640 -0
- package/src/lib/components/console/pos/pos-tender-panel.component.js.map +1 -0
- package/src/lib/components/console/pos/use-pos-display.d.ts +43 -0
- package/src/lib/components/console/pos/use-pos-display.js +161 -0
- package/src/lib/components/console/pos/use-pos-display.js.map +1 -0
- package/src/lib/components/console/pos-devices-card.component.d.ts +14 -0
- package/src/lib/components/console/pos-devices-card.component.js +546 -0
- package/src/lib/components/console/pos-devices-card.component.js.map +1 -0
- package/src/lib/components/console/pos-display/brand-screen.d.ts +33 -0
- package/src/lib/components/console/pos-display/brand-screen.js +85 -0
- package/src/lib/components/console/pos-display/brand-screen.js.map +1 -0
- package/src/lib/components/console/pos-display/cart-screen.d.ts +29 -0
- package/src/lib/components/console/pos-display/cart-screen.js +166 -0
- package/src/lib/components/console/pos-display/cart-screen.js.map +1 -0
- package/src/lib/components/console/pos-display/pairing-screen.d.ts +24 -0
- package/src/lib/components/console/pos-display/pairing-screen.js +127 -0
- package/src/lib/components/console/pos-display/pairing-screen.js.map +1 -0
- package/src/lib/components/console/pos-display/pos-display-api.d.ts +90 -0
- package/src/lib/components/console/pos-display/pos-display-api.js +140 -0
- package/src/lib/components/console/pos-display/pos-display-api.js.map +1 -0
- package/src/lib/components/console/pos-display/receipt-screen.d.ts +35 -0
- package/src/lib/components/console/pos-display/receipt-screen.js +200 -0
- package/src/lib/components/console/pos-display/receipt-screen.js.map +1 -0
- package/src/lib/components/console/pos-display/tip-screen.d.ts +36 -0
- package/src/lib/components/console/pos-display/tip-screen.js +211 -0
- package/src/lib/components/console/pos-display/tip-screen.js.map +1 -0
- package/src/lib/components/console/pos-display-page.component.d.ts +16 -0
- package/src/lib/components/console/pos-display-page.component.js +407 -0
- package/src/lib/components/console/pos-display-page.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-customer-lookup.component.d.ts +40 -0
- package/src/lib/components/console/pos-ops/pos-customer-lookup.component.js +289 -0
- package/src/lib/components/console/pos-ops/pos-customer-lookup.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-last-receipt.component.d.ts +34 -0
- package/src/lib/components/console/pos-ops/pos-last-receipt.component.js +61 -0
- package/src/lib/components/console/pos-ops/pos-last-receipt.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.d.ts +38 -0
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js +129 -0
- package/src/lib/components/console/pos-ops/pos-operations-bar.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-ops-api.d.ts +37 -0
- package/src/lib/components/console/pos-ops/pos-ops-api.js +60 -0
- package/src/lib/components/console/pos-ops/pos-ops-api.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-pin-pad.component.d.ts +48 -0
- package/src/lib/components/console/pos-ops/pos-pin-pad.component.js +220 -0
- package/src/lib/components/console/pos-ops/pos-pin-pad.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-receipt-actions.component.d.ts +63 -0
- package/src/lib/components/console/pos-ops/pos-receipt-actions.component.js +186 -0
- package/src/lib/components/console/pos-ops/pos-receipt-actions.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-receipt.d.ts +39 -0
- package/src/lib/components/console/pos-ops/pos-receipt.js +182 -0
- package/src/lib/components/console/pos-ops/pos-receipt.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-return-dialog.component.d.ts +40 -0
- package/src/lib/components/console/pos-ops/pos-return-dialog.component.js +465 -0
- package/src/lib/components/console/pos-ops/pos-return-dialog.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-shift-history-card.component.d.ts +29 -0
- package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js +253 -0
- package/src/lib/components/console/pos-ops/pos-shift-history-card.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.d.ts +34 -0
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.js +494 -0
- package/src/lib/components/console/pos-ops/pos-shift-panel.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-shift-report.component.d.ts +37 -0
- package/src/lib/components/console/pos-ops/pos-shift-report.component.js +102 -0
- package/src/lib/components/console/pos-ops/pos-shift-report.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-staff-pins-card.component.d.ts +30 -0
- package/src/lib/components/console/pos-ops/pos-staff-pins-card.component.js +277 -0
- package/src/lib/components/console/pos-ops/pos-staff-pins-card.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/register-ops.d.ts +28 -0
- package/src/lib/components/console/pos-ops/register-ops.js +28 -0
- package/src/lib/components/console/pos-ops/register-ops.js.map +1 -0
- package/src/lib/components/console/pos-ops/use-pos-cashier.d.ts +46 -0
- package/src/lib/components/console/pos-ops/use-pos-cashier.js +128 -0
- package/src/lib/components/console/pos-ops/use-pos-cashier.js.map +1 -0
- package/src/lib/components/console/pos-ops/use-pos-sale-receipt.d.ts +36 -0
- package/src/lib/components/console/pos-ops/use-pos-sale-receipt.js +64 -0
- package/src/lib/components/console/pos-ops/use-pos-sale-receipt.js.map +1 -0
- package/src/lib/components/console/pos-page.component.d.ts +13 -5
- package/src/lib/components/console/pos-page.component.js +729 -657
- package/src/lib/components/console/pos-page.component.js.map +1 -1
- package/src/lib/components/console/product-editor-dialog.component.js +51 -7
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/product-labels-dialog.component.d.ts +13 -0
- package/src/lib/components/console/product-labels-dialog.component.js +197 -0
- package/src/lib/components/console/product-labels-dialog.component.js.map +1 -0
- package/src/lib/components/console/product-register-fields.component.d.ts +19 -0
- package/src/lib/components/console/product-register-fields.component.js +241 -0
- package/src/lib/components/console/product-register-fields.component.js.map +1 -0
- package/src/lib/components/console/product-zones.d.ts +58 -2
- package/src/lib/components/console/product-zones.js +10 -2
- package/src/lib/components/console/product-zones.js.map +1 -1
- package/src/lib/components/console/products-hub-card.component.js +51 -11
- package/src/lib/components/console/products-hub-card.component.js.map +1 -1
- package/src/lib/components/console/register-hardware-card.component.d.ts +33 -0
- package/src/lib/components/console/register-hardware-card.component.js +826 -0
- package/src/lib/components/console/register-hardware-card.component.js.map +1 -0
- package/src/lib/components/console/registers-card.component.js +24 -5
- package/src/lib/components/console/registers-card.component.js.map +1 -1
- package/src/lib/components/console/return-actions.d.ts +38 -0
- package/src/lib/components/console/return-actions.js +76 -0
- package/src/lib/components/console/return-actions.js.map +1 -0
- package/src/lib/components/console/return-detail-dialog.component.d.ts +34 -0
- package/src/lib/components/console/return-detail-dialog.component.js +718 -0
- package/src/lib/components/console/return-detail-dialog.component.js.map +1 -0
- package/src/lib/components/console/return-settings-card.component.d.ts +34 -0
- package/src/lib/components/console/return-settings-card.component.js +195 -0
- package/src/lib/components/console/return-settings-card.component.js.map +1 -0
- package/src/lib/components/console/return-zones.d.ts +87 -0
- package/src/lib/components/console/return-zones.js +31 -0
- package/src/lib/components/console/return-zones.js.map +1 -0
- package/src/lib/components/console/returns-card.component.d.ts +45 -0
- package/src/lib/components/console/returns-card.component.js +159 -0
- package/src/lib/components/console/returns-card.component.js.map +1 -0
- package/src/lib/components/console/shipping-settings-card.component.js +161 -5
- package/src/lib/components/console/shipping-settings-card.component.js.map +1 -1
- package/src/lib/components/console/shippingeasy-card.component.d.ts +59 -0
- package/src/lib/components/console/shippingeasy-card.component.js +378 -0
- package/src/lib/components/console/shippingeasy-card.component.js.map +1 -0
- package/src/lib/components/console/shipstation-card.component.d.ts +35 -0
- package/src/lib/components/console/shipstation-card.component.js +345 -0
- package/src/lib/components/console/shipstation-card.component.js.map +1 -0
- package/src/lib/components/console/start-return-dialog.component.d.ts +40 -0
- package/src/lib/components/console/start-return-dialog.component.js +243 -0
- package/src/lib/components/console/start-return-dialog.component.js.map +1 -0
- package/src/lib/components/console/stock-movements-card.component.js +2 -1
- package/src/lib/components/console/stock-movements-card.component.js.map +1 -1
- package/src/lib/components/console/store-settings-card.component.js +2 -66
- package/src/lib/components/console/store-settings-card.component.js.map +1 -1
- package/src/lib/components/console/store-zones.d.ts +42 -0
- package/src/lib/components/console/store-zones.js +39 -0
- package/src/lib/components/console/store-zones.js.map +1 -0
- package/src/lib/components/order-status.d.ts +36 -0
- package/src/lib/components/order-status.js +502 -0
- package/src/lib/components/order-status.js.map +1 -0
- package/src/lib/components/product-detail.js +44 -2
- package/src/lib/components/product-detail.js.map +1 -1
- package/src/lib/components/return-request.d.ts +32 -0
- package/src/lib/components/return-request.js +576 -0
- package/src/lib/components/return-request.js.map +1 -0
- package/src/lib/components/storefront-payment-appearance.d.ts +32 -0
- package/src/lib/components/storefront-payment-appearance.js +114 -0
- package/src/lib/components/storefront-payment-appearance.js.map +1 -0
- package/src/lib/components/storefront-payment-element.d.ts +57 -1
- package/src/lib/components/storefront-payment-element.js +332 -33
- package/src/lib/components/storefront-payment-element.js.map +1 -1
- package/src/lib/constants/order-status.d.ts +22 -0
- package/src/lib/constants/order-status.js +22 -0
- package/src/lib/constants/order-status.js.map +1 -0
- package/src/lib/constants/return-request.d.ts +27 -0
- package/src/lib/constants/return-request.js +32 -0
- package/src/lib/constants/return-request.js.map +1 -0
- package/src/lib/constants/stock-movement-query.js +2 -1
- package/src/lib/constants/stock-movement-query.js.map +1 -1
- package/src/lib/declarations.console-server.js +9 -0
- package/src/lib/declarations.console-server.js.map +1 -1
- package/src/lib/declarations.server.d.ts +2 -1
- package/src/lib/declarations.server.js +47 -1
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/model/buyer-notifications.d.ts +59 -0
- package/src/lib/model/buyer-notifications.js +97 -0
- package/src/lib/model/buyer-notifications.js.map +1 -0
- package/src/lib/model/commerce-orders.d.ts +127 -1
- package/src/lib/model/commerce-orders.js +24 -15
- package/src/lib/model/commerce-orders.js.map +1 -1
- package/src/lib/model/commerce-payment-methods.d.ts +146 -0
- package/src/lib/model/commerce-payment-methods.js +247 -0
- package/src/lib/model/commerce-payment-methods.js.map +1 -0
- package/src/lib/model/commerce-pos-ops.d.ts +437 -0
- package/src/lib/model/commerce-pos-ops.js +721 -0
- package/src/lib/model/commerce-pos-ops.js.map +1 -0
- package/src/lib/model/commerce-pos.d.ts +263 -0
- package/src/lib/model/commerce-pos.js +375 -0
- package/src/lib/model/commerce-pos.js.map +1 -0
- package/src/lib/model/commerce-printers.d.ts +211 -0
- package/src/lib/model/commerce-printers.js +181 -0
- package/src/lib/model/commerce-printers.js.map +1 -0
- package/src/lib/model/commerce-receipt.d.ts +97 -0
- package/src/lib/model/commerce-receipt.js +180 -0
- package/src/lib/model/commerce-receipt.js.map +1 -0
- package/src/lib/model/commerce-returns.d.ts +207 -0
- package/src/lib/model/commerce-returns.js +300 -0
- package/src/lib/model/commerce-returns.js.map +1 -0
- package/src/lib/model/commerce-shipping.d.ts +44 -1
- package/src/lib/model/commerce-shipping.js +53 -9
- package/src/lib/model/commerce-shipping.js.map +1 -1
- package/src/lib/model/commerce-tax-engine.d.ts +90 -0
- package/src/lib/model/commerce-tax-engine.js +129 -0
- package/src/lib/model/commerce-tax-engine.js.map +1 -0
- package/src/lib/model/commerce.d.ts +88 -2
- package/src/lib/model/commerce.js +89 -1
- package/src/lib/model/commerce.js.map +1 -1
- package/src/lib/model/index.d.ts +15 -0
- package/src/lib/model/index.js +15 -0
- package/src/lib/model/index.js.map +1 -1
- package/src/lib/model/order-events.d.ts +154 -0
- package/src/lib/model/order-events.js +153 -0
- package/src/lib/model/order-events.js.map +1 -0
- package/src/lib/model/order-fulfillment.d.ts +117 -0
- package/src/lib/model/order-fulfillment.js +217 -0
- package/src/lib/model/order-fulfillment.js.map +1 -0
- package/src/lib/model/order-history.d.ts +58 -0
- package/src/lib/model/order-history.js +22 -0
- package/src/lib/model/order-history.js.map +1 -0
- package/src/lib/model/order-list-fields.d.ts +9 -1
- package/src/lib/model/order-list-fields.js +7 -1
- package/src/lib/model/order-list-fields.js.map +1 -1
- package/src/lib/model/order-shipping-export.d.ts +91 -0
- package/src/lib/model/order-shipping-export.js +192 -0
- package/src/lib/model/order-shipping-export.js.map +1 -0
- package/src/lib/model/order-status-view.d.ts +103 -0
- package/src/lib/model/order-status-view.js +156 -0
- package/src/lib/model/order-status-view.js.map +1 -0
- package/src/lib/model/order-webhooks.d.ts +142 -0
- package/src/lib/model/order-webhooks.js +91 -0
- package/src/lib/model/order-webhooks.js.map +1 -0
- package/src/lib/model/product-channel.d.ts +56 -0
- package/src/lib/model/product-channel.js +86 -0
- package/src/lib/model/product-channel.js.map +1 -0
- package/src/lib/model/product-modifiers.d.ts +80 -0
- package/src/lib/model/product-modifiers.js +140 -0
- package/src/lib/model/product-modifiers.js.map +1 -0
- package/src/lib/model/shippingeasy.d.ts +94 -0
- package/src/lib/model/shippingeasy.js +267 -0
- package/src/lib/model/shippingeasy.js.map +1 -0
- package/src/lib/model/shipstation.d.ts +125 -0
- package/src/lib/model/shipstation.js +399 -0
- package/src/lib/model/shipstation.js.map +1 -0
- package/src/lib/model/smart-collection-reads.d.ts +32 -0
- package/src/lib/model/smart-collection-reads.js +63 -0
- package/src/lib/model/smart-collection-reads.js.map +1 -0
- package/src/lib/model/tracking-url.d.ts +74 -0
- package/src/lib/model/tracking-url.js +159 -0
- package/src/lib/model/tracking-url.js.map +1 -0
- package/src/lib/plugin-config.d.ts +13 -0
- package/src/lib/plugin-config.js +77 -5
- package/src/lib/plugin-config.js.map +1 -1
- package/src/lib/plugin.js +23 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/pos-ops-config.d.ts +39 -0
- package/src/lib/pos-ops-config.js +88 -0
- package/src/lib/pos-ops-config.js.map +1 -0
- package/src/lib/printing/print-document.d.ts +106 -0
- package/src/lib/printing/print-document.js +464 -0
- package/src/lib/printing/print-document.js.map +1 -0
- package/src/lib/printing/product-labels.d.ts +58 -0
- package/src/lib/printing/product-labels.js +116 -0
- package/src/lib/printing/product-labels.js.map +1 -0
- package/src/lib/printing/render-epson.d.ts +57 -0
- package/src/lib/printing/render-epson.js +135 -0
- package/src/lib/printing/render-epson.js.map +1 -0
- package/src/lib/printing/render-star.d.ts +45 -0
- package/src/lib/printing/render-star.js +100 -0
- package/src/lib/printing/render-star.js.map +1 -0
- package/src/lib/printing/render-text.d.ts +25 -0
- package/src/lib/printing/render-text.js +53 -0
- package/src/lib/printing/render-text.js.map +1 -0
- package/src/lib/server/api-v1/openapi.js +27 -4
- package/src/lib/server/api-v1/openapi.js.map +1 -1
- package/src/lib/server/api-v1/order-view.d.ts +67 -0
- package/src/lib/server/api-v1/order-view.js +120 -0
- package/src/lib/server/api-v1/order-view.js.map +1 -0
- package/src/lib/server/api-v1/orders-and-products.js +58 -65
- package/src/lib/server/api-v1/orders-and-products.js.map +1 -1
- package/src/lib/server/billing-webhook.js +135 -28
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/cancel-order.js +29 -0
- package/src/lib/server/cancel-order.js.map +1 -1
- package/src/lib/server/carrier-rates-availability.d.ts +26 -0
- package/src/lib/server/carrier-rates-availability.js +76 -0
- package/src/lib/server/carrier-rates-availability.js.map +1 -0
- package/src/lib/server/carrier-shipping.d.ts +84 -0
- package/src/lib/server/carrier-shipping.js +135 -0
- package/src/lib/server/carrier-shipping.js.map +1 -0
- package/src/lib/server/cart-checkout.d.ts +2 -0
- package/src/lib/server/cart-checkout.js +226 -22
- package/src/lib/server/cart-checkout.js.map +1 -1
- package/src/lib/server/checkout-extras.d.ts +64 -0
- package/src/lib/server/checkout-extras.js +157 -0
- package/src/lib/server/checkout-extras.js.map +1 -0
- package/src/lib/server/{feed.d.ts → checkout-status.d.ts} +2 -7
- package/src/lib/server/checkout-status.js +111 -0
- package/src/lib/server/checkout-status.js.map +1 -0
- package/src/lib/server/checkout.js +86 -9
- package/src/lib/server/checkout.js.map +1 -1
- package/src/lib/server/draft-order.js +34 -5
- package/src/lib/server/draft-order.js.map +1 -1
- package/src/lib/server/fulfill-order.d.ts +127 -10
- package/src/lib/server/fulfill-order.js +451 -49
- package/src/lib/server/fulfill-order.js.map +1 -1
- package/src/lib/server/legacy-feed.d.ts +28 -0
- package/src/lib/server/legacy-feed.js +52 -0
- package/src/lib/server/legacy-feed.js.map +1 -0
- package/src/lib/server/native-checkout.d.ts +34 -15
- package/src/lib/server/native-checkout.js +32 -17
- package/src/lib/server/native-checkout.js.map +1 -1
- package/src/lib/server/order-event-host-emit.d.ts +23 -0
- package/src/lib/server/order-event-host-emit.js +30 -0
- package/src/lib/server/order-event-host-emit.js.map +1 -0
- package/src/lib/server/order-event-triggers.d.ts +37 -0
- package/src/lib/server/order-event-triggers.js +119 -0
- package/src/lib/server/order-event-triggers.js.map +1 -0
- package/src/lib/server/order-events.d.ts +62 -0
- package/src/lib/server/order-events.js +109 -0
- package/src/lib/server/order-events.js.map +1 -0
- package/src/lib/server/order-history.d.ts +23 -0
- package/src/lib/server/order-history.js +65 -0
- package/src/lib/server/order-history.js.map +1 -0
- package/src/lib/server/order-notifications.d.ts +185 -0
- package/src/lib/server/order-notifications.js +567 -0
- package/src/lib/server/order-notifications.js.map +1 -0
- package/src/lib/server/order-receipt-send.d.ts +39 -0
- package/src/lib/server/order-receipt-send.js +151 -0
- package/src/lib/server/order-receipt-send.js.map +1 -0
- package/src/lib/server/order-status-token.d.ts +31 -0
- package/src/lib/server/order-status-token.js +75 -0
- package/src/lib/server/order-status-token.js.map +1 -0
- package/src/lib/server/order-status.d.ts +58 -0
- package/src/lib/server/order-status.js +141 -0
- package/src/lib/server/order-status.js.map +1 -0
- package/src/lib/server/order-webhooks.d.ts +108 -0
- package/src/lib/server/order-webhooks.js +622 -0
- package/src/lib/server/order-webhooks.js.map +1 -0
- package/src/lib/server/orders-shipping-prepare.d.ts +26 -0
- package/src/lib/server/orders-shipping-prepare.js +121 -0
- package/src/lib/server/orders-shipping-prepare.js.map +1 -0
- package/src/lib/server/payment-method-domains.d.ts +209 -0
- package/src/lib/server/payment-method-domains.js +444 -0
- package/src/lib/server/payment-method-domains.js.map +1 -0
- package/src/lib/server/payment-methods.d.ts +77 -0
- package/src/lib/server/payment-methods.js +284 -0
- package/src/lib/server/payment-methods.js.map +1 -0
- package/src/lib/server/pos-auth.d.ts +50 -0
- package/src/lib/server/pos-auth.js +121 -0
- package/src/lib/server/pos-auth.js.map +1 -0
- package/src/lib/server/pos-customer.d.ts +49 -0
- package/src/lib/server/pos-customer.js +257 -0
- package/src/lib/server/pos-customer.js.map +1 -0
- package/src/lib/server/pos-display.d.ts +57 -0
- package/src/lib/server/pos-display.js +419 -0
- package/src/lib/server/pos-display.js.map +1 -0
- package/src/lib/server/pos-fee-month.d.ts +34 -0
- package/src/lib/server/pos-fee-month.js +36 -0
- package/src/lib/server/pos-fee-month.js.map +1 -0
- package/src/lib/server/pos-ops-gate.d.ts +161 -0
- package/src/lib/server/pos-ops-gate.js +295 -0
- package/src/lib/server/pos-ops-gate.js.map +1 -0
- package/src/lib/server/pos-ops-routes.d.ts +22 -0
- package/src/lib/server/pos-ops-routes.js +36 -0
- package/src/lib/server/pos-ops-routes.js.map +1 -0
- package/src/lib/server/pos-order.d.ts +1 -18
- package/src/lib/server/pos-order.js +222 -42
- package/src/lib/server/pos-order.js.map +1 -1
- package/src/lib/server/pos-payment.d.ts +39 -0
- package/src/lib/server/pos-payment.js +922 -0
- package/src/lib/server/pos-payment.js.map +1 -0
- package/src/lib/server/pos-print.d.ts +82 -0
- package/src/lib/server/pos-print.js +193 -0
- package/src/lib/server/pos-print.js.map +1 -0
- package/src/lib/server/pos-readers.d.ts +27 -0
- package/src/lib/server/pos-readers.js +276 -0
- package/src/lib/server/pos-readers.js.map +1 -0
- package/src/lib/server/pos-refund-authority.d.ts +60 -0
- package/src/lib/server/pos-refund-authority.js +72 -0
- package/src/lib/server/pos-refund-authority.js.map +1 -0
- package/src/lib/server/pos-return.d.ts +58 -0
- package/src/lib/server/pos-return.js +891 -0
- package/src/lib/server/pos-return.js.map +1 -0
- package/src/lib/server/pos-sale-stamp.d.ts +66 -0
- package/src/lib/server/pos-sale-stamp.js +84 -0
- package/src/lib/server/pos-sale-stamp.js.map +1 -0
- package/src/lib/server/pos-sale.d.ts +170 -0
- package/src/lib/server/pos-sale.js +461 -0
- package/src/lib/server/pos-sale.js.map +1 -0
- package/src/lib/server/pos-shift.d.ts +45 -0
- package/src/lib/server/pos-shift.js +484 -0
- package/src/lib/server/pos-shift.js.map +1 -0
- package/src/lib/server/pos-staff-pin.d.ts +26 -0
- package/src/lib/server/pos-staff-pin.js +339 -0
- package/src/lib/server/pos-staff-pin.js.map +1 -0
- package/src/lib/server/pos-stripe.d.ts +91 -0
- package/src/lib/server/pos-stripe.js +129 -0
- package/src/lib/server/pos-stripe.js.map +1 -0
- package/src/lib/server/pos-terminal-connection-token.d.ts +48 -0
- package/src/lib/server/pos-terminal-connection-token.js +166 -0
- package/src/lib/server/pos-terminal-connection-token.js.map +1 -0
- package/src/lib/server/pos-terminal.d.ts +218 -0
- package/src/lib/server/pos-terminal.js +1014 -0
- package/src/lib/server/pos-terminal.js.map +1 -0
- package/src/lib/server/print-queue.d.ts +124 -0
- package/src/lib/server/print-queue.js +301 -0
- package/src/lib/server/print-queue.js.map +1 -0
- package/src/lib/server/printer-poll.d.ts +75 -0
- package/src/lib/server/printer-poll.js +325 -0
- package/src/lib/server/printer-poll.js.map +1 -0
- package/src/lib/server/printer-secret.d.ts +39 -0
- package/src/lib/server/printer-secret.js +56 -0
- package/src/lib/server/printer-secret.js.map +1 -0
- package/src/lib/server/printers.d.ts +114 -0
- package/src/lib/server/printers.js +546 -0
- package/src/lib/server/printers.js.map +1 -0
- package/src/lib/server/product-ai-capability.d.ts +42 -0
- package/src/lib/server/product-ai-capability.js +159 -0
- package/src/lib/server/product-ai-capability.js.map +1 -0
- package/src/lib/server/product-catalog.d.ts +42 -0
- package/src/lib/server/product-catalog.js +305 -0
- package/src/lib/server/product-catalog.js.map +1 -0
- package/src/lib/server/product-drafts.d.ts +119 -0
- package/src/lib/server/product-drafts.js +384 -0
- package/src/lib/server/product-drafts.js.map +1 -0
- package/src/lib/server/refund.js +110 -45
- package/src/lib/server/refund.js.map +1 -1
- package/src/lib/server/reserve.js +2 -0
- package/src/lib/server/reserve.js.map +1 -1
- package/src/lib/server/return-status-action.d.ts +37 -0
- package/src/lib/server/return-status-action.js +57 -0
- package/src/lib/server/return-status-action.js.map +1 -0
- package/src/lib/server/returns.d.ts +119 -0
- package/src/lib/server/returns.js +938 -0
- package/src/lib/server/returns.js.map +1 -0
- package/src/lib/server/shipment-records.d.ts +36 -0
- package/src/lib/server/shipment-records.js +289 -0
- package/src/lib/server/shipment-records.js.map +1 -0
- package/src/lib/server/shipping-connector-gates.d.ts +40 -0
- package/src/lib/server/shipping-connector-gates.js +97 -0
- package/src/lib/server/shipping-connector-gates.js.map +1 -0
- package/src/lib/server/shipping-connectors.d.ts +29 -0
- package/src/lib/server/shipping-connectors.js +236 -0
- package/src/lib/server/shipping-connectors.js.map +1 -0
- package/src/lib/server/shippingeasy.d.ts +238 -0
- package/src/lib/server/shippingeasy.js +787 -0
- package/src/lib/server/shippingeasy.js.map +1 -0
- package/src/lib/server/shipstation.d.ts +129 -0
- package/src/lib/server/shipstation.js +483 -0
- package/src/lib/server/shipstation.js.map +1 -0
- package/src/lib/server/site-page-resolver.d.ts +5 -0
- package/src/lib/server/site-page-resolver.js +156 -1
- package/src/lib/server/site-page-resolver.js.map +1 -1
- package/src/lib/server/stock-levels.d.ts +21 -0
- package/src/lib/server/stock-levels.js +263 -0
- package/src/lib/server/stock-levels.js.map +1 -0
- package/src/lib/server/stripe-refund.d.ts +47 -0
- package/src/lib/server/stripe-refund.js +87 -0
- package/src/lib/server/stripe-refund.js.map +1 -0
- package/src/lib/server/supplier-update.js +46 -5
- package/src/lib/server/supplier-update.js.map +1 -1
- package/src/lib/server/tax-engine-quote.d.ts +47 -0
- package/src/lib/server/tax-engine-quote.js +105 -0
- package/src/lib/server/tax-engine-quote.js.map +1 -0
- package/src/lib/server.js +146 -2
- package/src/lib/server.js.map +1 -1
- package/src/lib/site.js +12 -0
- package/src/lib/site.js.map +1 -1
- package/src/lib/subprocessors.d.ts +26 -0
- package/src/lib/subprocessors.js +50 -0
- package/src/lib/subprocessors.js.map +1 -0
- package/src/lib/tenant-emails.js +461 -3
- package/src/lib/tenant-emails.js.map +1 -1
- package/src/lib/testing/fake-firestore.d.ts +45 -0
- package/src/lib/testing/fake-firestore.js +189 -0
- package/src/lib/testing/fake-firestore.js.map +1 -0
- package/src/lib/testing/memory-firestore.d.ts +123 -0
- package/src/lib/testing/memory-firestore.js +274 -0
- package/src/lib/testing/memory-firestore.js.map +1 -0
- package/src/lib/testing/pos-ops-harness.d.ts +50 -0
- package/src/lib/testing/pos-ops-harness.js +184 -0
- package/src/lib/testing/pos-ops-harness.js.map +1 -0
- package/src/lib/testing/pos-ops-memory-firestore.d.ts +55 -0
- package/src/lib/testing/pos-ops-memory-firestore.js +376 -0
- package/src/lib/testing/pos-ops-memory-firestore.js.map +1 -0
- package/src/lib/transfer/records-transfer.d.ts +11 -1
- package/src/lib/transfer/records-transfer.js +127 -5
- package/src/lib/transfer/records-transfer.js.map +1 -1
- package/src/lib/transfer/records.server.d.ts +9 -2
- package/src/lib/transfer/records.server.js +58 -7
- package/src/lib/transfer/records.server.js.map +1 -1
- package/src/lib/transfer/register-transfer-resources.js +40 -1
- package/src/lib/transfer/register-transfer-resources.js.map +1 -1
- package/src/lib/transfer/register-transfer-ui.js +4 -1
- package/src/lib/transfer/register-transfer-ui.js.map +1 -1
- package/src/lib/transfer/shipping-presets.d.ts +23 -0
- package/src/lib/transfer/shipping-presets.js +156 -0
- package/src/lib/transfer/shipping-presets.js.map +1 -0
- package/src/lib/transfer/tracking-transfer.d.ts +101 -0
- package/src/lib/transfer/tracking-transfer.js +546 -0
- package/src/lib/transfer/tracking-transfer.js.map +1 -0
- package/src/lib/transfer/tracking.server.d.ts +37 -0
- package/src/lib/transfer/tracking.server.js +393 -0
- package/src/lib/transfer/tracking.server.js.map +1 -0
- package/src/lib/transfer/transfer-keys.d.ts +2 -1
- package/src/lib/transfer/transfer-keys.js +6 -2
- package/src/lib/transfer/transfer-keys.js.map +1 -1
- package/src/lib/utils/code128.d.ts +37 -0
- package/src/lib/utils/code128.js +199 -0
- package/src/lib/utils/code128.js.map +1 -0
- package/src/lib/utils/order-invoice.d.ts +55 -0
- package/src/lib/utils/order-invoice.js +127 -0
- package/src/lib/utils/order-invoice.js.map +1 -0
- package/src/lib/utils/use-checkout-return-notice.d.ts +34 -0
- package/src/lib/utils/use-checkout-return-notice.js +78 -0
- package/src/lib/utils/use-checkout-return-notice.js.map +1 -0
- package/src/lib/utils/use-storefront-purchase-event.js +4 -0
- package/src/lib/utils/use-storefront-purchase-event.js.map +1 -1
- package/src/lib/server/feed.js +0 -69
- package/src/lib/server/feed.js.map +0 -1
|
@@ -0,0 +1,787 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2026 Aglyn LLC
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/ import { createHmac, timingSafeEqual } from "crypto";
|
|
18
|
+
import { PLATFORM_BRAND_NAME } from "@aglyn/aglyn/app-utils/platform-brand";
|
|
19
|
+
import { readClientIp } from "@aglyn/aglyn/app-utils/request-ip";
|
|
20
|
+
import { needsReseal, openSecret, sealSecret } from "@aglyn/shared-util-tools/secret-box";
|
|
21
|
+
import { consumeRateLimit, firebaseAdmin, notifyHostManagers } from "@aglyn/tenant-data-admin";
|
|
22
|
+
import { PLUGIN_EVENT_MAX_ATTEMPTS } from "@aglyn/tenant-data-admin/server/plugin-event-outbox";
|
|
23
|
+
import { readShippingEasyCallback, SHIPPINGEASY_DEFAULT_BASE_URL, SHIPPINGEASY_SHIPPED_STATES, SHIPPINGEASY_TIMESTAMP_TOLERANCE_MS, shippingEasyCanonicalQuery, shippingEasyExternalId, shippingEasyIntent, shippingEasyOrderPayload, shippingEasySignaturePlaintext } from "../model/shippingeasy.js";
|
|
24
|
+
import { readCommerceSecretKeyring } from "./order-webhooks.js";
|
|
25
|
+
import { connectorHostIdOf, connectorSiteRefusal, connectorText as text, digestSecret, requestIsSecure } from "./shipping-connector-gates.js";
|
|
26
|
+
import { recordShipNotice, shipStationProductsFor } from "./shipstation.js";
|
|
27
|
+
// lockdown-423: handled — the callback route and every push ask `connectorSiteRefusal`, which asks `lockdownRefusal`, before any write.
|
|
28
|
+
/*
|
|
29
|
+
* THE SHIPPINGEASY CONNECTOR (AGL-3633). The order and the callback as data
|
|
30
|
+
* are in `model/shippingeasy.ts`; this is the HTTP, the keys and the state.
|
|
31
|
+
*
|
|
32
|
+
* ## The merchant's own keys, so nothing to sign up for on our side
|
|
33
|
+
*
|
|
34
|
+
* ShippingEasy's order API is a CUSTOMER API: a merchant pushes orders into
|
|
35
|
+
* their own account with the API key and secret on their Settings → API
|
|
36
|
+
* Credentials page and the store API key of an "API" store. There is no
|
|
37
|
+
* partner account between us and them, so the connector is offered wherever
|
|
38
|
+
* commerce's secret keyring exists (`readCommerceSecretKeyring`), exactly as
|
|
39
|
+
* the ShipStation card is, and nowhere else. The secret is sealed with the
|
|
40
|
+
* shared secret box, bound to its site by the seal context; it never leaves
|
|
41
|
+
* the server again, not even to the admin who typed it.
|
|
42
|
+
*
|
|
43
|
+
* ## Orders go out on commerce's own events
|
|
44
|
+
*
|
|
45
|
+
* Commerce subscribes to its `order.paid`, `order.cancelled` and
|
|
46
|
+
* `order.refunded` events under the name `shippingeasy`
|
|
47
|
+
* (`order-event-triggers.ts`). The subscriber pushes the order as it stands
|
|
48
|
+
* NOW, read fresh, so a retried event never sends a stale copy: a paid order
|
|
49
|
+
* with something to ship is created, and a canceled or refunded one that was
|
|
50
|
+
* sent is canceled there. A failure that may pass (a 5xx, a 429, a timeout)
|
|
51
|
+
* throws, and the outbox retries with its backoff; on the last attempt the
|
|
52
|
+
* site's managers are told. A refusal that will not pass (bad keys, an order
|
|
53
|
+
* ShippingEasy rejects) is recorded on the card instead of retried forever.
|
|
54
|
+
* "Send open orders" on the card pushes what is open now, for the orders
|
|
55
|
+
* paid before the connection or while it was failing.
|
|
56
|
+
*
|
|
57
|
+
* ## Each order once
|
|
58
|
+
*
|
|
59
|
+
* A record per order under the connection
|
|
60
|
+
* (`commerceShippingEasyConnections/{hostId}/orders/{orderId}`) is claimed in
|
|
61
|
+
* a transaction before the call: a second push of the same order while the
|
|
62
|
+
* first is in flight is retried later, and one already sent answers
|
|
63
|
+
* `already`. When ShippingEasy refuses a create, the order is looked up by
|
|
64
|
+
* its identifier first, so an order that did arrive (a response lost on the
|
|
65
|
+
* way back) is recorded as sent rather than as a failure.
|
|
66
|
+
*
|
|
67
|
+
* ## The callback is a shipment, recorded once
|
|
68
|
+
*
|
|
69
|
+
* `/api/commerce/shippingeasy/{hostId}` takes ShippingEasy's shipment
|
|
70
|
+
* notification, signed with the merchant's API secret over the callback's
|
|
71
|
+
* own path, query and body, and records each order of the shipment through
|
|
72
|
+
* `recordShipNotice` — the same door ShipStation's notices go through — keyed
|
|
73
|
+
* by the tracking number, so a redelivery or a number typed into Aglyn first
|
|
74
|
+
* is one parcel and the buyer gets one shipped email.
|
|
75
|
+
*/ /** Where each site's connection is kept: server-only, every client denied. */ export const SHIPPINGEASY_CONNECTIONS = 'commerceShippingEasyConnections';
|
|
76
|
+
/** The per-order records under a connection. */ export const SHIPPINGEASY_ORDER_RECORDS = 'orders';
|
|
77
|
+
/** Callback requests per minute, per site and per calling address. */ export const SHIPPINGEASY_RATE_LIMIT = 120;
|
|
78
|
+
/** The largest callback body read. A shipment of a few orders is tens of kilobytes. */ export const SHIPPINGEASY_CALLBACK_MAX_BYTES = 1024 * 1024;
|
|
79
|
+
/** How long a claimed push holds its order before another may try. */ export const SHIPPINGEASY_CLAIM_MS = 2 * 60000;
|
|
80
|
+
/** How long one call to ShippingEasy may take. */ export const SHIPPINGEASY_REQUEST_TIMEOUT_MS = 15000;
|
|
81
|
+
/** Orders "Send open orders" pushes per click. */ export const SHIPPINGEASY_SYNC_LIMIT = 100;
|
|
82
|
+
/** How far back "Send open orders" looks: older open orders are the merchant's to handle by hand. */ export const SHIPPINGEASY_SYNC_WINDOW_MS = 90 * 24 * 60 * 60 * 1000;
|
|
83
|
+
/** The env var that points the connector at another ShippingEasy address. */ export const SHIPPINGEASY_BASE_URL_ENV = 'SHIPPINGEASY_API_BASE_URL';
|
|
84
|
+
/** A failure that may pass: the outbox retries it. */ export class ShippingEasyUnavailableError extends Error {
|
|
85
|
+
constructor(message){
|
|
86
|
+
super(message);
|
|
87
|
+
this.name = 'ShippingEasyUnavailableError';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/*==========================================
|
|
91
|
+
* KEYS
|
|
92
|
+
*=========================================*/ /** What a key from ShippingEasy's pages looks like: their keys are hex, allowed some slack. */ export const SHIPPINGEASY_KEY = /^[A-Za-z0-9_-]{8,128}$/;
|
|
93
|
+
/** What binds a sealed secret to its site: a copy opens for no other. */ export const shippingEasySealContext = (hostId)=>`${SHIPPINGEASY_CONNECTIONS}/${hostId}#apiSecret`;
|
|
94
|
+
/** The API secret sealed for a site, with the id of the key that sealed it. */ export function sealShippingEasySecret(hostId, apiSecret, keyring) {
|
|
95
|
+
return {
|
|
96
|
+
sealedApiSecret: sealSecret(apiSecret, keyring.current, {
|
|
97
|
+
context: shippingEasySealContext(hostId)
|
|
98
|
+
}),
|
|
99
|
+
secretKeyId: keyring.current.id
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** A site's API secret in the clear and whether to seal it again, or `null` when it cannot be opened. */ export function openShippingEasySecret(connection, keyring) {
|
|
103
|
+
if (!(connection == null ? void 0 : connection.sealedApiSecret) || !keyring) return null;
|
|
104
|
+
try {
|
|
105
|
+
const opened = openSecret(connection.sealedApiSecret, keyring, {
|
|
106
|
+
context: shippingEasySealContext(connection.hostId)
|
|
107
|
+
});
|
|
108
|
+
return {
|
|
109
|
+
apiSecret: opened.plaintext,
|
|
110
|
+
reseal: needsReseal(opened, keyring)
|
|
111
|
+
};
|
|
112
|
+
} catch (unused) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/** The connection's keys in the clear, or `null` when the secret cannot be opened. */ export function shippingEasyCredentialsOf(connection, keyring) {
|
|
117
|
+
const opened = openShippingEasySecret(connection, keyring);
|
|
118
|
+
return opened ? {
|
|
119
|
+
apiKey: connection.apiKey,
|
|
120
|
+
apiSecret: opened.apiSecret,
|
|
121
|
+
storeApiKey: connection.storeApiKey
|
|
122
|
+
} : null;
|
|
123
|
+
}
|
|
124
|
+
/** The hex HMAC-SHA256 ShippingEasy signs with. */ export function signShippingEasy(apiSecret, plaintext) {
|
|
125
|
+
return createHmac('sha256', apiSecret).update(plaintext, 'utf8').digest('hex');
|
|
126
|
+
}
|
|
127
|
+
/** ShippingEasy's API address: the env's when it is an https URL, else theirs. */ export function shippingEasyBaseUrl(env = process.env) {
|
|
128
|
+
var _env_SHIPPINGEASY_BASE_URL_ENV;
|
|
129
|
+
const configured = String((_env_SHIPPINGEASY_BASE_URL_ENV = env[SHIPPINGEASY_BASE_URL_ENV]) != null ? _env_SHIPPINGEASY_BASE_URL_ENV : '').trim();
|
|
130
|
+
if (configured) {
|
|
131
|
+
try {
|
|
132
|
+
const url = new URL(configured);
|
|
133
|
+
if (url.protocol === 'https:') return url.origin;
|
|
134
|
+
} catch (unused) {
|
|
135
|
+
// An unreadable override falls back to ShippingEasy's own address.
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return SHIPPINGEASY_DEFAULT_BASE_URL;
|
|
139
|
+
}
|
|
140
|
+
/*==========================================
|
|
141
|
+
* CALLS
|
|
142
|
+
*=========================================*/ /** One signed call to ShippingEasy. `path` is the full path, `/api/…`. Network failures become `ShippingEasyUnavailableError`. */ export async function shippingEasyRequest(credentials, input, deps = {}) {
|
|
143
|
+
var _deps_now, _input_query, _deps_fetchImpl;
|
|
144
|
+
const now = (_deps_now = deps.now) != null ? _deps_now : Date.now;
|
|
145
|
+
const body = input.body === undefined ? '' : JSON.stringify(input.body);
|
|
146
|
+
const params = _extends({}, (_input_query = input.query) != null ? _input_query : {}, {
|
|
147
|
+
api_key: credentials.apiKey,
|
|
148
|
+
api_timestamp: String(Math.floor(now() / 1000))
|
|
149
|
+
});
|
|
150
|
+
const signature = signShippingEasy(credentials.apiSecret, shippingEasySignaturePlaintext({
|
|
151
|
+
method: input.method,
|
|
152
|
+
path: input.path,
|
|
153
|
+
params,
|
|
154
|
+
body
|
|
155
|
+
}));
|
|
156
|
+
const url = `${shippingEasyBaseUrl(deps.env)}${input.path}?${shippingEasyCanonicalQuery(params)}&api_signature=${signature}`;
|
|
157
|
+
const fetchImpl = (_deps_fetchImpl = deps.fetchImpl) != null ? _deps_fetchImpl : fetch;
|
|
158
|
+
try {
|
|
159
|
+
const response = await fetchImpl(url, _extends({
|
|
160
|
+
method: input.method,
|
|
161
|
+
headers: _extends({
|
|
162
|
+
accept: 'application/json'
|
|
163
|
+
}, body ? {
|
|
164
|
+
'content-type': 'application/json'
|
|
165
|
+
} : {})
|
|
166
|
+
}, body ? {
|
|
167
|
+
body
|
|
168
|
+
} : {}, {
|
|
169
|
+
redirect: 'manual',
|
|
170
|
+
signal: AbortSignal.timeout(SHIPPINGEASY_REQUEST_TIMEOUT_MS)
|
|
171
|
+
}));
|
|
172
|
+
return {
|
|
173
|
+
status: response.status,
|
|
174
|
+
text: (await response.text().catch(()=>'')).slice(0, 4000)
|
|
175
|
+
};
|
|
176
|
+
} catch (error) {
|
|
177
|
+
var _ref;
|
|
178
|
+
throw new ShippingEasyUnavailableError(`ShippingEasy could not be reached (${(_ref = error == null ? void 0 : error.name) != null ? _ref : 'error'})`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/** A refusal's words for the card: ShippingEasy's own message when it sent one, else its status. */ export function shippingEasyRefusalMessage(response) {
|
|
182
|
+
var _ref, _ref1;
|
|
183
|
+
const fallback = `ShippingEasy answered ${response.status}`;
|
|
184
|
+
let parsed;
|
|
185
|
+
try {
|
|
186
|
+
parsed = JSON.parse(response.text);
|
|
187
|
+
} catch (unused) {
|
|
188
|
+
return fallback;
|
|
189
|
+
}
|
|
190
|
+
const errors = (_ref = (_ref1 = parsed == null ? void 0 : parsed['errors']) != null ? _ref1 : parsed == null ? void 0 : parsed['error']) != null ? _ref : parsed == null ? void 0 : parsed['message'];
|
|
191
|
+
const message = Array.isArray(errors) ? errors.map((entry)=>typeof entry === 'string' ? entry : JSON.stringify(entry)).join('; ') : typeof errors === 'string' ? errors : errors ? JSON.stringify(errors) : '';
|
|
192
|
+
return (message || fallback).slice(0, 300);
|
|
193
|
+
}
|
|
194
|
+
const storePath = (credentials)=>`/api/stores/${encodeURIComponent(credentials.storeApiKey)}/orders`;
|
|
195
|
+
/** Whether a status may pass on its own: worth the outbox's retry. */ const transient = (status)=>status >= 500 || status === 429 || status === 408;
|
|
196
|
+
/**
|
|
197
|
+
* Whether the keys work: one read of the store's orders. `refused` means
|
|
198
|
+
* ShippingEasy said no to these keys or this store; `unavailable` means it
|
|
199
|
+
* could not be asked.
|
|
200
|
+
*/ export async function checkShippingEasyCredentials(credentials, deps = {}) {
|
|
201
|
+
try {
|
|
202
|
+
const response = await shippingEasyRequest(credentials, {
|
|
203
|
+
method: 'GET',
|
|
204
|
+
path: storePath(credentials),
|
|
205
|
+
query: {
|
|
206
|
+
per_page: '1'
|
|
207
|
+
}
|
|
208
|
+
}, deps);
|
|
209
|
+
if (response.status >= 200 && response.status < 300) return {
|
|
210
|
+
ok: true
|
|
211
|
+
};
|
|
212
|
+
if (transient(response.status)) return {
|
|
213
|
+
ok: false,
|
|
214
|
+
reason: 'unavailable',
|
|
215
|
+
message: shippingEasyRefusalMessage(response)
|
|
216
|
+
};
|
|
217
|
+
return {
|
|
218
|
+
ok: false,
|
|
219
|
+
reason: 'refused',
|
|
220
|
+
message: shippingEasyRefusalMessage(response)
|
|
221
|
+
};
|
|
222
|
+
} catch (error) {
|
|
223
|
+
return {
|
|
224
|
+
ok: false,
|
|
225
|
+
reason: 'unavailable',
|
|
226
|
+
message: error.message
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function connectionRef(hostId) {
|
|
231
|
+
return firebaseAdmin.app().firestore().collection(SHIPPINGEASY_CONNECTIONS).doc(hostId);
|
|
232
|
+
}
|
|
233
|
+
/** Records the last error, or clears it after a success, on the connection. Never throws. */ async function noteOnConnection(hostId, patch) {
|
|
234
|
+
await connectionRef(hostId).set(patch, {
|
|
235
|
+
merge: true
|
|
236
|
+
}).catch((error)=>console.warn('shippingeasy: connection not stamped', hostId, error));
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Sends one order to ShippingEasy as it stands now, or cancels it there.
|
|
240
|
+
* Safe to call any number of times for the same order: see the block header.
|
|
241
|
+
*/ export async function pushShippingEasyOrder(hostId, orderId, deps = {}) {
|
|
242
|
+
var _deps_now, _orderSnapshot_data, _ref;
|
|
243
|
+
var _claim_record, _claim_record1;
|
|
244
|
+
const now = (_deps_now = deps.now) != null ? _deps_now : Date.now;
|
|
245
|
+
const firestore = firebaseAdmin.app().firestore();
|
|
246
|
+
const stored = await connectionRef(hostId).get();
|
|
247
|
+
if (!stored.exists) return {
|
|
248
|
+
result: 'not_connected'
|
|
249
|
+
};
|
|
250
|
+
const connection = stored.data();
|
|
251
|
+
const orderSnapshot = await firestore.collection('hosts').doc(hostId).collection('orders').doc(orderId).get();
|
|
252
|
+
if (!orderSnapshot.exists) return {
|
|
253
|
+
result: 'skipped'
|
|
254
|
+
};
|
|
255
|
+
const order = (_orderSnapshot_data = orderSnapshot.data()) != null ? _orderSnapshot_data : {};
|
|
256
|
+
const intent = shippingEasyIntent(order, orderId);
|
|
257
|
+
if (!intent) return {
|
|
258
|
+
result: 'skipped'
|
|
259
|
+
};
|
|
260
|
+
const refused = await connectorSiteRefusal({
|
|
261
|
+
method: 'POST'
|
|
262
|
+
}, hostId);
|
|
263
|
+
if (refused) return {
|
|
264
|
+
result: 'refused',
|
|
265
|
+
message: (await refused.text()).slice(0, 300)
|
|
266
|
+
};
|
|
267
|
+
const credentials = shippingEasyCredentialsOf(connection, readCommerceSecretKeyring());
|
|
268
|
+
const externalId = shippingEasyExternalId(order, orderId);
|
|
269
|
+
if (!credentials) {
|
|
270
|
+
const message = 'The ShippingEasy API secret cannot be opened. Enter your keys again.';
|
|
271
|
+
await noteOnConnection(hostId, {
|
|
272
|
+
lastError: {
|
|
273
|
+
message,
|
|
274
|
+
atMs: now(),
|
|
275
|
+
orderNumber: externalId
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
return {
|
|
279
|
+
result: 'failed',
|
|
280
|
+
message
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
const recordRef = connectionRef(hostId).collection(SHIPPINGEASY_ORDER_RECORDS).doc(orderId);
|
|
284
|
+
const claim = await firestore.runTransaction(async (transaction)=>{
|
|
285
|
+
var _record_claimedAtMs;
|
|
286
|
+
const snapshot = await transaction.get(recordRef);
|
|
287
|
+
const record = snapshot.exists ? snapshot.data() : null;
|
|
288
|
+
const atMs = now();
|
|
289
|
+
const inFlight = ((record == null ? void 0 : record.state) === 'sending' || (record == null ? void 0 : record.state) === 'canceling') && atMs - Number((_record_claimedAtMs = record.claimedAtMs) != null ? _record_claimedAtMs : 0) < SHIPPINGEASY_CLAIM_MS;
|
|
290
|
+
if (inFlight) throw new ShippingEasyUnavailableError('This order is being sent to ShippingEasy already');
|
|
291
|
+
if (intent === 'create') {
|
|
292
|
+
var _ref;
|
|
293
|
+
if (record && record.state !== 'sending' && record.state !== 'failed') {
|
|
294
|
+
return {
|
|
295
|
+
go: false,
|
|
296
|
+
outcome: {
|
|
297
|
+
result: 'already'
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
transaction.set(recordRef, {
|
|
302
|
+
orderId,
|
|
303
|
+
externalId: (_ref = record == null ? void 0 : record.externalId) != null ? _ref : externalId,
|
|
304
|
+
state: 'sending',
|
|
305
|
+
claimedAtMs: atMs,
|
|
306
|
+
updatedAtMs: atMs
|
|
307
|
+
});
|
|
308
|
+
return {
|
|
309
|
+
go: true,
|
|
310
|
+
record
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
// Cancel: only what was sent there. An order that never arrived has
|
|
314
|
+
// nothing to cancel, and one canceled already is answered as such.
|
|
315
|
+
if (!record || record.state === 'failed' || record.state === 'sending') return {
|
|
316
|
+
go: false,
|
|
317
|
+
outcome: {
|
|
318
|
+
result: 'skipped'
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
if (record.state === 'canceled') return {
|
|
322
|
+
go: false,
|
|
323
|
+
outcome: {
|
|
324
|
+
result: 'already'
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
transaction.set(recordRef, _extends({}, record, {
|
|
328
|
+
state: 'canceling',
|
|
329
|
+
claimedAtMs: atMs,
|
|
330
|
+
updatedAtMs: atMs
|
|
331
|
+
}));
|
|
332
|
+
return {
|
|
333
|
+
go: true,
|
|
334
|
+
record
|
|
335
|
+
};
|
|
336
|
+
});
|
|
337
|
+
if ('outcome' in claim) return claim.outcome;
|
|
338
|
+
const sentId = (_ref = (_claim_record = claim.record) == null ? void 0 : _claim_record.externalId) != null ? _ref : externalId;
|
|
339
|
+
const settle = async (state, extra = {})=>{
|
|
340
|
+
await recordRef.set(_extends({
|
|
341
|
+
state,
|
|
342
|
+
updatedAtMs: now()
|
|
343
|
+
}, extra), {
|
|
344
|
+
merge: true
|
|
345
|
+
});
|
|
346
|
+
};
|
|
347
|
+
if (intent === 'cancel') {
|
|
348
|
+
let response;
|
|
349
|
+
try {
|
|
350
|
+
response = await shippingEasyRequest(credentials, {
|
|
351
|
+
method: 'POST',
|
|
352
|
+
path: `${storePath(credentials)}/${encodeURIComponent(sentId)}/cancellations`
|
|
353
|
+
}, deps);
|
|
354
|
+
} catch (error) {
|
|
355
|
+
await settle('sent');
|
|
356
|
+
throw error;
|
|
357
|
+
}
|
|
358
|
+
if (transient(response.status)) {
|
|
359
|
+
await settle('sent');
|
|
360
|
+
throw new ShippingEasyUnavailableError(shippingEasyRefusalMessage(response));
|
|
361
|
+
}
|
|
362
|
+
if (response.status >= 200 && response.status < 300) {
|
|
363
|
+
await settle('canceled', {
|
|
364
|
+
canceledAtMs: now(),
|
|
365
|
+
error: null
|
|
366
|
+
});
|
|
367
|
+
await noteOnConnection(hostId, {
|
|
368
|
+
lastPushAtMs: now(),
|
|
369
|
+
lastError: null
|
|
370
|
+
});
|
|
371
|
+
return {
|
|
372
|
+
result: 'canceled'
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
const message = `Order ${sentId} could not be canceled in ShippingEasy: ${shippingEasyRefusalMessage(response)}`;
|
|
376
|
+
await settle('cancel_failed', {
|
|
377
|
+
error: message
|
|
378
|
+
});
|
|
379
|
+
await noteOnConnection(hostId, {
|
|
380
|
+
lastError: {
|
|
381
|
+
message,
|
|
382
|
+
atMs: now(),
|
|
383
|
+
orderNumber: sentId
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
return {
|
|
387
|
+
result: 'failed',
|
|
388
|
+
message
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
const lookUp = async ()=>{
|
|
392
|
+
const found = await shippingEasyRequest(credentials, {
|
|
393
|
+
method: 'GET',
|
|
394
|
+
path: `${storePath(credentials)}/${encodeURIComponent(sentId)}`
|
|
395
|
+
}, deps).catch(()=>null);
|
|
396
|
+
return Boolean(found && found.status >= 200 && found.status < 300);
|
|
397
|
+
};
|
|
398
|
+
const markSent = async ()=>{
|
|
399
|
+
await settle('sent', {
|
|
400
|
+
sentAtMs: now(),
|
|
401
|
+
error: null
|
|
402
|
+
});
|
|
403
|
+
await noteOnConnection(hostId, {
|
|
404
|
+
lastPushAtMs: now(),
|
|
405
|
+
lastError: null
|
|
406
|
+
});
|
|
407
|
+
return {
|
|
408
|
+
result: 'sent'
|
|
409
|
+
};
|
|
410
|
+
};
|
|
411
|
+
// A claim that lapsed mid-call may have landed: look before creating
|
|
412
|
+
// again, so ShippingEasy never holds the order twice.
|
|
413
|
+
if (((_claim_record1 = claim.record) == null ? void 0 : _claim_record1.state) === 'sending' && await lookUp()) return markSent();
|
|
414
|
+
const hostRef = firestore.collection('hosts').doc(hostId);
|
|
415
|
+
const products = await shipStationProductsFor(hostRef, [
|
|
416
|
+
order
|
|
417
|
+
]);
|
|
418
|
+
const payload = shippingEasyOrderPayload({
|
|
419
|
+
docId: orderId,
|
|
420
|
+
order
|
|
421
|
+
}, products);
|
|
422
|
+
// A network failure throws past here with the claim left to lapse rather
|
|
423
|
+
// than released: the call may have landed, and the retry's refused create
|
|
424
|
+
// looks the order up before calling it failed.
|
|
425
|
+
const response = await shippingEasyRequest(credentials, {
|
|
426
|
+
method: 'POST',
|
|
427
|
+
path: storePath(credentials),
|
|
428
|
+
body: payload
|
|
429
|
+
}, deps);
|
|
430
|
+
if (transient(response.status)) {
|
|
431
|
+
await settle('failed', {
|
|
432
|
+
error: shippingEasyRefusalMessage(response)
|
|
433
|
+
});
|
|
434
|
+
throw new ShippingEasyUnavailableError(shippingEasyRefusalMessage(response));
|
|
435
|
+
}
|
|
436
|
+
if (response.status >= 200 && response.status < 300) return markSent();
|
|
437
|
+
// A refused create may be an order that arrived on an earlier try whose
|
|
438
|
+
// answer was lost: ask for it by its identifier before calling it failed.
|
|
439
|
+
if (response.status !== 401 && response.status !== 403 && await lookUp()) return markSent();
|
|
440
|
+
const message = response.status === 401 || response.status === 403 ? 'ShippingEasy refused the API key, secret or store API key. Enter them again.' : `Order ${sentId} was refused by ShippingEasy: ${shippingEasyRefusalMessage(response)}`;
|
|
441
|
+
await settle('failed', {
|
|
442
|
+
error: message
|
|
443
|
+
});
|
|
444
|
+
await noteOnConnection(hostId, {
|
|
445
|
+
lastError: {
|
|
446
|
+
message,
|
|
447
|
+
atMs: now(),
|
|
448
|
+
orderNumber: sentId
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
return {
|
|
452
|
+
result: 'failed',
|
|
453
|
+
message
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* The `shippingeasy` subscriber to commerce's order events. Throws on a
|
|
458
|
+
* failure that may pass, so the outbox retries; on its last attempt the
|
|
459
|
+
* site's managers are told and the card shows why.
|
|
460
|
+
*/ export async function deliverOrderEventToShippingEasy(envelope, deps = {}) {
|
|
461
|
+
var _ref, _envelope_payload;
|
|
462
|
+
var _order;
|
|
463
|
+
const orderId = String((_ref = (_order = ((_envelope_payload = envelope.payload) != null ? _envelope_payload : {}).order) == null ? void 0 : _order.id) != null ? _ref : '');
|
|
464
|
+
if (!orderId || orderId.includes('/')) return null;
|
|
465
|
+
try {
|
|
466
|
+
return await pushShippingEasyOrder(envelope.hostId, orderId, deps);
|
|
467
|
+
} catch (error) {
|
|
468
|
+
var _deps_now;
|
|
469
|
+
if (!(error instanceof ShippingEasyUnavailableError) || envelope.attempt < PLUGIN_EVENT_MAX_ATTEMPTS) throw error;
|
|
470
|
+
const message = `${error.message}. Select Send open orders on the ShippingEasy card to try again.`;
|
|
471
|
+
await noteOnConnection(envelope.hostId, {
|
|
472
|
+
lastError: {
|
|
473
|
+
message,
|
|
474
|
+
atMs: ((_deps_now = deps.now) != null ? _deps_now : Date.now)()
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
await notifyHostManagers(envelope.hostId, {
|
|
478
|
+
type: 'content.order',
|
|
479
|
+
title: 'An order could not be sent to ShippingEasy',
|
|
480
|
+
body: `An order on {site} never reached ShippingEasy after ${envelope.attempt} attempts (${error.message}).`,
|
|
481
|
+
link: `/${envelope.hostId}/products/settings`
|
|
482
|
+
}).catch(()=>undefined);
|
|
483
|
+
return {
|
|
484
|
+
result: 'failed',
|
|
485
|
+
message
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Pushes the site's open orders from the last 90 days, a pass at a time: the
|
|
491
|
+
* orders paid before the connection, or while it was failing. One indexed
|
|
492
|
+
* query (`requiresShipping ==`, `updatedAtMs` range) — the same index the
|
|
493
|
+
* ShipStation feed reads.
|
|
494
|
+
*/ export async function syncShippingEasyOrders(hostId, deps = {}) {
|
|
495
|
+
var _deps_now;
|
|
496
|
+
const now = (_deps_now = deps.now) != null ? _deps_now : Date.now;
|
|
497
|
+
const orders = await firebaseAdmin.app().firestore().collection('hosts').doc(hostId).collection('orders').where('requiresShipping', '==', true).where('updatedAtMs', '>=', now() - SHIPPINGEASY_SYNC_WINDOW_MS).orderBy('updatedAtMs', 'asc').limit(500).get();
|
|
498
|
+
const open = orders.docs.filter((doc)=>{
|
|
499
|
+
var _doc_data;
|
|
500
|
+
return shippingEasyIntent((_doc_data = doc.data()) != null ? _doc_data : {}, doc.id) === 'create';
|
|
501
|
+
});
|
|
502
|
+
const result = {
|
|
503
|
+
sent: 0,
|
|
504
|
+
already: 0,
|
|
505
|
+
failed: 0,
|
|
506
|
+
more: open.length > SHIPPINGEASY_SYNC_LIMIT
|
|
507
|
+
};
|
|
508
|
+
for (const doc of open.slice(0, SHIPPINGEASY_SYNC_LIMIT)){
|
|
509
|
+
try {
|
|
510
|
+
const outcome = await pushShippingEasyOrder(hostId, doc.id, deps);
|
|
511
|
+
if (outcome.result === 'sent') result.sent += 1;
|
|
512
|
+
else if (outcome.result === 'already') result.already += 1;
|
|
513
|
+
else if (outcome.result === 'failed' || outcome.result === 'refused') {
|
|
514
|
+
result.failed += 1;
|
|
515
|
+
// Bad keys or a refused site fail every order alike: stop asking.
|
|
516
|
+
if (outcome.result === 'refused' || /refused the API key/.test(outcome.message)) break;
|
|
517
|
+
}
|
|
518
|
+
} catch (error) {
|
|
519
|
+
result.failed += 1;
|
|
520
|
+
if (error instanceof ShippingEasyUnavailableError) continue;
|
|
521
|
+
throw error;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return result;
|
|
525
|
+
}
|
|
526
|
+
/*==========================================
|
|
527
|
+
* THE CALLBACK
|
|
528
|
+
*=========================================*/ /**
|
|
529
|
+
* Whether a callback was signed with this secret: the HMAC of its method,
|
|
530
|
+
* path, query (without `api_signature`) and raw body, compared in constant
|
|
531
|
+
* time; and, when it carries `api_timestamp`, sent within the hour.
|
|
532
|
+
*/ export function verifyShippingEasyCallback(input) {
|
|
533
|
+
var _input_query_get;
|
|
534
|
+
const presented = String((_input_query_get = input.query.get('api_signature')) != null ? _input_query_get : '').trim().toLowerCase();
|
|
535
|
+
if (!/^[0-9a-f]{64}$/.test(presented)) return 'unsigned';
|
|
536
|
+
const params = {};
|
|
537
|
+
for (const [name, value] of input.query.entries())if (name !== 'api_signature') params[name] = value;
|
|
538
|
+
const expected = signShippingEasy(input.apiSecret, shippingEasySignaturePlaintext({
|
|
539
|
+
method: input.method,
|
|
540
|
+
path: input.path,
|
|
541
|
+
params,
|
|
542
|
+
body: input.body
|
|
543
|
+
}));
|
|
544
|
+
if (!timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(presented, 'hex'))) return 'bad_signature';
|
|
545
|
+
if (params['api_timestamp'] !== undefined) {
|
|
546
|
+
const seconds = Number(params['api_timestamp']);
|
|
547
|
+
if (!Number.isFinite(seconds) || Math.abs(input.nowMs - seconds * 1000) > SHIPPINGEASY_TIMESTAMP_TOLERANCE_MS) return 'expired';
|
|
548
|
+
}
|
|
549
|
+
return 'ok';
|
|
550
|
+
}
|
|
551
|
+
/** `POST /api/commerce/shippingeasy/{hostId}` — ShippingEasy's shipment notification. See the block header. */ export async function shippingEasyRoute(request, context, deps = {}) {
|
|
552
|
+
var _deps_now, _readClientIp, _request_headers_get;
|
|
553
|
+
const now = (_deps_now = deps.now) != null ? _deps_now : Date.now;
|
|
554
|
+
const hostId = connectorHostIdOf(context.params);
|
|
555
|
+
if (!hostId) return text(404, 'Not found');
|
|
556
|
+
if (request.method !== 'POST') return text(405, 'ShippingEasy posts shipments here.', {
|
|
557
|
+
allow: 'POST'
|
|
558
|
+
});
|
|
559
|
+
if (!requestIsSecure(request, deps.env)) return text(403, `Use the https:// address ${PLATFORM_BRAND_NAME} gave you.`);
|
|
560
|
+
const ip = (_readClientIp = readClientIp(request.headers)) != null ? _readClientIp : 'unknown';
|
|
561
|
+
const rate = await consumeRateLimit(`shippingeasy:${hostId}:${ip}`, {
|
|
562
|
+
limit: SHIPPINGEASY_RATE_LIMIT,
|
|
563
|
+
windowMs: 60000
|
|
564
|
+
});
|
|
565
|
+
if (!rate.allowed) {
|
|
566
|
+
return text(429, 'Too many requests; ShippingEasy will retry.', {
|
|
567
|
+
'retry-after': String(Math.max(1, Math.ceil((rate.resetMs - now()) / 1000)))
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
const declared = Number((_request_headers_get = request.headers.get('content-length')) != null ? _request_headers_get : 0);
|
|
571
|
+
if (declared > SHIPPINGEASY_CALLBACK_MAX_BYTES) return text(413, 'The callback is too large.');
|
|
572
|
+
const body = await request.text();
|
|
573
|
+
if (Buffer.byteLength(body, 'utf8') > SHIPPINGEASY_CALLBACK_MAX_BYTES) return text(413, 'The callback is too large.');
|
|
574
|
+
const ref = connectionRef(hostId);
|
|
575
|
+
const stored = await ref.get();
|
|
576
|
+
const connection = stored.exists ? stored.data() : null;
|
|
577
|
+
const keyring = readCommerceSecretKeyring();
|
|
578
|
+
const opened = openShippingEasySecret(connection, keyring);
|
|
579
|
+
if (connection && !opened) console.error('shippingeasy: the stored API secret could not be opened', hostId);
|
|
580
|
+
const url = new URL(request.url);
|
|
581
|
+
// An unknown site is answered exactly like a wrong signature: an unproven
|
|
582
|
+
// caller learns nothing about which sites are connected.
|
|
583
|
+
const verdict = opened ? verifyShippingEasyCallback({
|
|
584
|
+
apiSecret: opened.apiSecret,
|
|
585
|
+
method: request.method,
|
|
586
|
+
path: url.pathname,
|
|
587
|
+
query: url.searchParams,
|
|
588
|
+
body,
|
|
589
|
+
nowMs: now()
|
|
590
|
+
}) : 'bad_signature';
|
|
591
|
+
if (verdict !== 'ok') {
|
|
592
|
+
return text(401, verdict === 'expired' ? 'The callback is too old.' : `The signature does not match the API secret saved in ${PLATFORM_BRAND_NAME}.`);
|
|
593
|
+
}
|
|
594
|
+
if ((opened == null ? void 0 : opened.reseal) && keyring) {
|
|
595
|
+
await ref.set(sealShippingEasySecret(hostId, opened.apiSecret, keyring), {
|
|
596
|
+
merge: true
|
|
597
|
+
}).catch((error)=>console.warn('shippingeasy: secret not resealed', hostId, error));
|
|
598
|
+
}
|
|
599
|
+
const refused = await connectorSiteRefusal(request, hostId);
|
|
600
|
+
if (refused) return refused;
|
|
601
|
+
const callback = readShippingEasyCallback(body);
|
|
602
|
+
if ('problem' in callback) return text(400, callback.problem);
|
|
603
|
+
await noteOnConnection(hostId, {
|
|
604
|
+
lastCallbackAtMs: now()
|
|
605
|
+
});
|
|
606
|
+
if (!SHIPPINGEASY_SHIPPED_STATES.has(callback.workflowState)) {
|
|
607
|
+
return text(200, `Nothing recorded for a ${callback.workflowState || 'shipment'} label.`);
|
|
608
|
+
}
|
|
609
|
+
const digest = digestSecret(body).slice(0, 32);
|
|
610
|
+
const problems = [];
|
|
611
|
+
try {
|
|
612
|
+
for (const notice of callback.notices){
|
|
613
|
+
const outcome = await recordShipNotice(hostId, notice, digest, {
|
|
614
|
+
source: 'shippingeasy'
|
|
615
|
+
});
|
|
616
|
+
if (outcome.status !== 200) problems.push(outcome.body);
|
|
617
|
+
}
|
|
618
|
+
} catch (error) {
|
|
619
|
+
console.error('shippingeasy: callback failed', hostId, error);
|
|
620
|
+
return text(500, `${PLATFORM_BRAND_NAME} could not record the shipment. ShippingEasy will retry.`);
|
|
621
|
+
}
|
|
622
|
+
// A notice for an order this site does not have, or one already canceled,
|
|
623
|
+
// will not record on a retry either: it is answered 200 so ShippingEasy
|
|
624
|
+
// stops sending it, and the card says what happened.
|
|
625
|
+
if (problems.length) {
|
|
626
|
+
await noteOnConnection(hostId, {
|
|
627
|
+
lastError: {
|
|
628
|
+
message: problems.join(' ').slice(0, 300),
|
|
629
|
+
atMs: now()
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
return text(200, problems.length ? problems.join(' ') : 'Recorded.');
|
|
634
|
+
}
|
|
635
|
+
const ending = (key)=>key.slice(-4);
|
|
636
|
+
export function shippingEasyStatusOf(connection, available) {
|
|
637
|
+
if (!connection) return {
|
|
638
|
+
available,
|
|
639
|
+
connected: false
|
|
640
|
+
};
|
|
641
|
+
return _extends({
|
|
642
|
+
available,
|
|
643
|
+
connected: true,
|
|
644
|
+
apiKeyEnding: ending(connection.apiKey),
|
|
645
|
+
storeApiKeyEnding: ending(connection.storeApiKey),
|
|
646
|
+
createdAtMs: connection.createdAtMs
|
|
647
|
+
}, connection.updatedAtMs ? {
|
|
648
|
+
updatedAtMs: connection.updatedAtMs
|
|
649
|
+
} : {}, connection.lastPushAtMs ? {
|
|
650
|
+
lastPushAtMs: connection.lastPushAtMs
|
|
651
|
+
} : {}, connection.lastCallbackAtMs ? {
|
|
652
|
+
lastCallbackAtMs: connection.lastCallbackAtMs
|
|
653
|
+
} : {}, connection.lastError ? {
|
|
654
|
+
lastError: connection.lastError
|
|
655
|
+
} : {});
|
|
656
|
+
}
|
|
657
|
+
/** The card's actions. `status` is the GET. */ export const SHIPPINGEASY_ACTIONS = [
|
|
658
|
+
'status',
|
|
659
|
+
'connect',
|
|
660
|
+
'sync',
|
|
661
|
+
'disconnect'
|
|
662
|
+
];
|
|
663
|
+
const ACTIVITY = {
|
|
664
|
+
type: 'commerce:shippingEasy',
|
|
665
|
+
id: 'shippingeasy',
|
|
666
|
+
name: 'ShippingEasy'
|
|
667
|
+
};
|
|
668
|
+
/**
|
|
669
|
+
* One action of the ShippingEasy card, for a caller the connectors route has
|
|
670
|
+
* already proven a site admin (or, for `status`, an editor) on a site with
|
|
671
|
+
* commerce. Answers the status and body the route sends.
|
|
672
|
+
*
|
|
673
|
+
* - `connect` saves the three keys after one read proves them, sealing the
|
|
674
|
+
* secret; on a site already connected it replaces them (a merchant who
|
|
675
|
+
* made a new secret in ShippingEasy enters it here).
|
|
676
|
+
* - `sync` pushes the open orders, a pass at a time.
|
|
677
|
+
* - `disconnect` deletes the connection; the per-order records go with it,
|
|
678
|
+
* so a later connect sends the open orders afresh.
|
|
679
|
+
*/ export async function shippingEasyConnectorAction(input, deps = {}) {
|
|
680
|
+
var _deps_now, _body_apiKey, _body_apiSecret, _body_storeApiKey;
|
|
681
|
+
const { hostId, action, body } = input;
|
|
682
|
+
const now = (_deps_now = deps.now) != null ? _deps_now : Date.now;
|
|
683
|
+
const keyring = readCommerceSecretKeyring();
|
|
684
|
+
const available = keyring !== null;
|
|
685
|
+
const ref = connectionRef(hostId);
|
|
686
|
+
const read = async ()=>{
|
|
687
|
+
const doc = await ref.get();
|
|
688
|
+
return doc.exists ? doc.data() : null;
|
|
689
|
+
};
|
|
690
|
+
if (action === 'status') return {
|
|
691
|
+
status: 200,
|
|
692
|
+
body: _extends({}, shippingEasyStatusOf(await read(), available))
|
|
693
|
+
};
|
|
694
|
+
if (action === 'disconnect') {
|
|
695
|
+
if (!await read()) return {
|
|
696
|
+
status: 200,
|
|
697
|
+
body: {
|
|
698
|
+
available,
|
|
699
|
+
connected: false
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
await firebaseAdmin.app().firestore().recursiveDelete(ref);
|
|
703
|
+
await input.log('Disconnected ShippingEasy', ACTIVITY);
|
|
704
|
+
return {
|
|
705
|
+
status: 200,
|
|
706
|
+
body: {
|
|
707
|
+
available,
|
|
708
|
+
connected: false
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
if (!keyring) return {
|
|
713
|
+
status: 503,
|
|
714
|
+
body: {
|
|
715
|
+
error: 'ShippingEasy cannot be connected on this deployment yet'
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
if (action === 'sync') {
|
|
719
|
+
const connection = await read();
|
|
720
|
+
if (!connection) return {
|
|
721
|
+
status: 409,
|
|
722
|
+
body: {
|
|
723
|
+
error: 'ShippingEasy is not connected.'
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
const result = await syncShippingEasyOrders(hostId, deps);
|
|
727
|
+
await input.log('Sent open orders to ShippingEasy', ACTIVITY);
|
|
728
|
+
return {
|
|
729
|
+
status: 200,
|
|
730
|
+
body: _extends({}, shippingEasyStatusOf(await read(), available), {
|
|
731
|
+
sync: _extends({}, result)
|
|
732
|
+
})
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
const keys = {
|
|
736
|
+
apiKey: String((_body_apiKey = body['apiKey']) != null ? _body_apiKey : '').trim(),
|
|
737
|
+
apiSecret: String((_body_apiSecret = body['apiSecret']) != null ? _body_apiSecret : '').trim(),
|
|
738
|
+
storeApiKey: String((_body_storeApiKey = body['storeApiKey']) != null ? _body_storeApiKey : '').trim()
|
|
739
|
+
};
|
|
740
|
+
if (!SHIPPINGEASY_KEY.test(keys.apiKey) || !SHIPPINGEASY_KEY.test(keys.apiSecret) || !SHIPPINGEASY_KEY.test(keys.storeApiKey)) {
|
|
741
|
+
return {
|
|
742
|
+
status: 400,
|
|
743
|
+
body: {
|
|
744
|
+
error: 'Paste the API key, API secret and store API key exactly as ShippingEasy shows them.'
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
const check = await checkShippingEasyCredentials(keys, deps);
|
|
749
|
+
if ('reason' in check) {
|
|
750
|
+
return check.reason === 'refused' ? {
|
|
751
|
+
status: 422,
|
|
752
|
+
body: {
|
|
753
|
+
error: `ShippingEasy did not accept these keys (${check.message}). Check all three and try again.`
|
|
754
|
+
}
|
|
755
|
+
} : {
|
|
756
|
+
status: 502,
|
|
757
|
+
body: {
|
|
758
|
+
error: 'ShippingEasy could not be reached. Try again in a minute.'
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
const atMs = now();
|
|
763
|
+
const existing = await read();
|
|
764
|
+
const connection = _extends({}, existing != null ? existing : {
|
|
765
|
+
createdAtMs: atMs,
|
|
766
|
+
createdBy: input.actor.uid
|
|
767
|
+
}, {
|
|
768
|
+
hostId,
|
|
769
|
+
apiKey: keys.apiKey,
|
|
770
|
+
storeApiKey: keys.storeApiKey
|
|
771
|
+
}, sealShippingEasySecret(hostId, keys.apiSecret, keyring), existing ? {
|
|
772
|
+
updatedAtMs: atMs
|
|
773
|
+
} : {}, {
|
|
774
|
+
lastError: null
|
|
775
|
+
});
|
|
776
|
+
await ref.set(connection);
|
|
777
|
+
if (!existing && input.prepareOpenOrders) {
|
|
778
|
+
await input.prepareOpenOrders(hostId).catch((error)=>console.warn('shippingeasy: open orders not stamped', hostId, error));
|
|
779
|
+
}
|
|
780
|
+
await input.log(existing ? 'Replaced the ShippingEasy keys' : 'Connected ShippingEasy', ACTIVITY);
|
|
781
|
+
return {
|
|
782
|
+
status: 200,
|
|
783
|
+
body: _extends({}, shippingEasyStatusOf(connection, available))
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
//# sourceMappingURL=shippingeasy.js.map
|