@aglyn/plugins-commerce 1.0.0-beta.284 → 1.0.0-beta.287
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/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 +11 -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 +67 -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/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 +29 -0
- package/src/lib/server/commerce-site-keys.js +40 -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/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 +15 -4
- package/src/lib/server/pos-ops-gate.js +42 -9
- 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-return.d.ts +10 -0
- package/src/lib/server/pos-return.js +26 -1
- 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 +25 -20
- 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 +34 -11
- 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/testing/pos-ops-memory-firestore.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*==========================================\n * AN IN-MEMORY ADMIN FIRESTORE, for the register operations' specs\n * (AGL-3609) — the CRM's transfer double (AGL-3527), kept beside the\n * commerce specs because one plugin's testing helpers are not another's\n * to import.\n *\n * Documents by path; the operators the CRM's transfer hooks and the job\n * engine issue — `where` (equality, ranges, `in`, the array operators),\n * `orderBy` (a field or the document id), `limit`, `startAfter`, `count`,\n * `getAll`, batches and read-then-write transactions — and the write\n * sentinels (`delete`, `serverTimestamp`, `arrayUnion`, `arrayRemove`,\n * `increment`) applied along dotted paths, as Firestore applies them.\n *\n * A spec mocks `firebase-admin/firestore` with {@link memoryFirestoreModule}\n * so the code under test builds its sentinels from the same table.\n *=========================================*/\n\ntype Data = Record<string, unknown>\n\ninterface Sentinel {\n __sentinel: 'delete' | 'serverTimestamp' | 'arrayUnion' | 'arrayRemove' | 'increment'\n values?: unknown[]\n by?: number\n}\n\nconst DOCUMENT_ID = { __documentId: true }\n\n/** What a spec hands `jest.mock('firebase-admin/firestore', …)`. */\nexport const memoryFirestoreModule = {\n __esModule: true,\n FieldValue: {\n delete: (): Sentinel => ({ __sentinel: 'delete' }),\n serverTimestamp: (): Sentinel => ({ __sentinel: 'serverTimestamp' }),\n arrayUnion: (...values: unknown[]): Sentinel => ({ __sentinel: 'arrayUnion', values }),\n arrayRemove: (...values: unknown[]): Sentinel => ({ __sentinel: 'arrayRemove', values }),\n increment: (by: number): Sentinel => ({ __sentinel: 'increment', by }),\n },\n FieldPath: { documentId: () => DOCUMENT_ID },\n Timestamp: { fromDate: (date: Date) => date.getTime() },\n}\n\nconst isSentinel = (value: unknown): value is Sentinel =>\n Boolean(value && typeof value === 'object' && '__sentinel' in (value as object))\n\nconst copy = <T>(value: T): T => (value === undefined ? value : (JSON.parse(JSON.stringify(value)) as T))\n\nfunction readPath(data: Data | undefined, path: string): unknown {\n return path.split('.').reduce<unknown>((node, key) => (node as Data | undefined)?.[key], data)\n}\n\nexport interface MemoryFirestore {\n /** Every document, by full path. */\n docs: Map<string, Data>\n /** The clock `serverTimestamp` writes. */\n now: () => number\n firestore: FirebaseFirestore.Firestore\n /** Seeds one document at its full path. */\n seed: (path: string, data: Data) => void\n /** A document's data, or `undefined`. */\n read: (path: string) => Data | undefined\n}\n\n/** A fresh in-memory Firestore. */\nexport function memoryFirestore(clock: () => number = () => 1_800_000_000_000): MemoryFirestore {\n const docs = new Map<string, Data>()\n /** A write counter per path, for the transaction's concurrency check. */\n const versions = new Map<string, number>()\n const bump = (path: string) => versions.set(path, (versions.get(path) ?? 0) + 1)\n\n const resolve = (value: unknown, current: unknown): unknown => {\n if (!isSentinel(value)) return Array.isArray(value) || (value && typeof value === 'object') ? copy(value) : value\n switch (value.__sentinel) {\n case 'serverTimestamp':\n return clock()\n case 'arrayUnion':\n return [...new Set([...(Array.isArray(current) ? current : []), ...(value.values ?? [])])]\n case 'arrayRemove':\n return (Array.isArray(current) ? current : []).filter((entry) => !(value.values ?? []).includes(entry))\n case 'increment':\n return Number(current ?? 0) + Number(value.by ?? 0)\n default:\n return undefined\n }\n }\n\n /** Writes `value` at a dotted path, a `delete` sentinel removing the leaf. */\n const writePath = (target: Data, path: string, value: unknown): void => {\n const keys = path.split('.')\n let node = target\n for (const key of keys.slice(0, -1)) {\n if (!node[key] || typeof node[key] !== 'object') node[key] = {}\n node = node[key] as Data\n }\n const leaf = keys[keys.length - 1] as string\n if (isSentinel(value) && value.__sentinel === 'delete') delete node[leaf]\n else node[leaf] = resolve(value, node[leaf])\n }\n\n /** Every top-level key of `data` with sentinels resolved (a `set`). */\n const settle = (data: Data, base: Data = {}): Data => {\n const next = copy(base)\n for (const [key, value] of Object.entries(data)) {\n if (value === undefined) continue\n if (isSentinel(value)) writePath(next, key, value)\n else if (value && typeof value === 'object' && !Array.isArray(value) && base[key] && typeof base[key] === 'object') {\n next[key] = settle(value as Data, base[key] as Data)\n } else next[key] = resolve(value, next[key])\n }\n return next\n }\n\n const snapshot = (path: string): any => {\n const data = docs.get(path)\n return {\n id: path.slice(path.lastIndexOf('/') + 1),\n ref: docRef(path),\n exists: data !== undefined,\n data: () => copy(data),\n get: (field: string) => copy(readPath(data, field)),\n }\n }\n\n const docRef = (path: string): any => ({\n id: path.slice(path.lastIndexOf('/') + 1),\n path,\n get firestore() {\n return firestore\n },\n get parent() {\n return collectionRef(path.slice(0, path.lastIndexOf('/')))\n },\n collection: (name: string) => collectionRef(`${path}/${name}`),\n get: async () => snapshot(path),\n set: async (data: Data, options?: { merge?: boolean }) => {\n docs.set(path, settle(data, options?.merge ? (docs.get(path) ?? {}) : {}))\n bump(path)\n },\n create: async (data: Data) => {\n if (docs.has(path)) throw Object.assign(new Error(`ALREADY_EXISTS: ${path}`), { code: 6 })\n docs.set(path, settle(data))\n bump(path)\n },\n update: async (...args: unknown[]) => {\n const current = docs.get(path)\n if (!current) throw Object.assign(new Error(`NOT_FOUND: ${path}`), { code: 5 })\n const patch: Data =\n typeof args[0] === 'string'\n ? Object.fromEntries(\n Array.from({ length: args.length / 2 }, (_unused, at) => [String(args[at * 2]), args[at * 2 + 1]]),\n )\n : (args[0] as Data)\n const next = copy(current)\n for (const [key, value] of Object.entries(patch)) writePath(next, key, value)\n docs.set(path, next)\n bump(path)\n },\n delete: async () => {\n docs.delete(path)\n bump(path)\n },\n })\n\n interface QueryState {\n path: string\n filters: Array<{ field: string | typeof DOCUMENT_ID; op: string; value: unknown }>\n order: Array<{ field: string | typeof DOCUMENT_ID; direction: 'asc' | 'desc' }>\n limit?: number\n after?: any\n }\n\n const fieldOf = (data: Data | undefined, id: string, field: string | typeof DOCUMENT_ID) =>\n field === DOCUMENT_ID ? id : readPath(data, field as string)\n\n const compare = (a: unknown, b: unknown): number => {\n if (a === b) return 0\n if (a === undefined || a === null) return -1\n if (b === undefined || b === null) return 1\n return (a as number) < (b as number) ? -1 : 1\n }\n\n const matches = (data: Data, id: string, filter: QueryState['filters'][number]): boolean => {\n const value = fieldOf(data, id, filter.field)\n const wanted = filter.value\n switch (filter.op) {\n case '==':\n return JSON.stringify(value) === JSON.stringify(wanted)\n case '!=':\n return value !== undefined && JSON.stringify(value) !== JSON.stringify(wanted)\n case 'in':\n return (wanted as unknown[]).some((entry) => JSON.stringify(entry) === JSON.stringify(value))\n case 'not-in':\n return value !== undefined && !(wanted as unknown[]).some((entry) => JSON.stringify(entry) === JSON.stringify(value))\n case 'array-contains':\n return Array.isArray(value) && value.includes(wanted)\n case 'array-contains-any':\n return Array.isArray(value) && value.some((entry) => (wanted as unknown[]).includes(entry))\n case '<':\n return value !== undefined && compare(value, wanted) < 0\n case '<=':\n return value !== undefined && compare(value, wanted) <= 0\n case '>':\n return value !== undefined && compare(value, wanted) > 0\n case '>=':\n return value !== undefined && compare(value, wanted) >= 0\n default:\n throw new Error(`memory firestore: no operator ${filter.op}`)\n }\n }\n\n const run = (state: QueryState): any[] => {\n const prefix = `${state.path}/`\n let found = [...docs.entries()]\n .filter(([path]) => path.startsWith(prefix) && !path.slice(prefix.length).includes('/'))\n .map(([path, data]) => ({ path, id: path.slice(prefix.length), data }))\n .filter((entry) => state.filters.every((filter) => matches(entry.data, entry.id, filter)))\n const order = state.order.length ? state.order : [{ field: DOCUMENT_ID, direction: 'asc' as const }]\n for (const { field } of order) {\n if (field !== DOCUMENT_ID) found = found.filter((entry) => readPath(entry.data, field as string) !== undefined)\n }\n found.sort((a, b) => {\n for (const { field, direction } of [...order, { field: DOCUMENT_ID, direction: 'asc' as const }]) {\n const result = compare(fieldOf(a.data, a.id, field), fieldOf(b.data, b.id, field))\n if (result) return direction === 'desc' ? -result : result\n }\n return 0\n })\n if (state.after) {\n const at = found.findIndex((entry) => entry.id === state.after.id)\n found = at >= 0 ? found.slice(at + 1) : found\n }\n if (state.limit !== undefined) found = found.slice(0, state.limit)\n return found.map((entry) => snapshot(entry.path))\n }\n\n const query = (state: QueryState): any => ({\n where: (field: string | typeof DOCUMENT_ID, op: string, value: unknown) =>\n query({ ...state, filters: [...state.filters, { field, op, value }] }),\n orderBy: (field: string | typeof DOCUMENT_ID, direction: 'asc' | 'desc' = 'asc') =>\n query({ ...state, order: [...state.order, { field, direction }] }),\n limit: (count: number) => query({ ...state, limit: count }),\n startAfter: (after: any) => query({ ...state, after }),\n get: async () => {\n const found = run(state)\n return { docs: found, empty: !found.length, size: found.length }\n },\n count: () => ({\n get: async () => ({ data: () => ({ count: run({ ...state, limit: undefined }).length }) }),\n }),\n })\n\n const collectionRef = (path: string): any => ({\n id: path.slice(path.lastIndexOf('/') + 1),\n path,\n get parent() {\n const at = path.lastIndexOf('/')\n return at > 0 ? docRef(path.slice(0, at)) : null\n },\n doc: (id?: string) => docRef(`${path}/${id ?? `auto${Math.random().toString(36).slice(2, 12)}`}`),\n ...query({ path, filters: [], order: [] }),\n })\n\n const firestore = {\n collection: (name: string) => collectionRef(name),\n getAll: async (...refs: Array<{ path: string }>) => refs.map((ref) => snapshot(ref.path)),\n batch: () => {\n const staged: Array<() => Promise<void>> = []\n const batch = {\n set: (ref: any, data: Data, options?: { merge?: boolean }) => (staged.push(() => ref.set(data, options)), batch),\n create: (ref: any, data: Data) => (staged.push(() => ref.create(data)), batch),\n update: (ref: any, ...args: unknown[]) => (staged.push(() => ref.update(...args)), batch),\n delete: (ref: any) => (staged.push(() => ref.delete()), batch),\n commit: async () => {\n for (const write of staged) await write()\n },\n }\n return batch\n },\n /**\n * Read-then-write with OPTIMISTIC CONCURRENCY, as the server SDK commits\n * one: every document the body read is versioned, and a commit that finds\n * one of them written since is thrown away and the body run again. Two\n * transactions racing on one document therefore end the way they do in\n * Firestore — the second re-reads the first one's write — which is the\n * property a one-open-shift or a lockout counter rests on.\n */\n runTransaction: async <T>(body: (transaction: any) => Promise<T>): Promise<T> => {\n for (let attempt = 0; attempt < 10; attempt += 1) {\n const staged: Array<() => Promise<void>> = []\n const seen = new Map<string, number>()\n const transaction = {\n get: async (target: any) => {\n const result = await target.get()\n if (typeof target.path === 'string' && !('docs' in result)) {\n seen.set(target.path, versions.get(target.path) ?? 0)\n } else if (result?.docs) {\n for (const doc of result.docs) seen.set(doc.ref.path, versions.get(doc.ref.path) ?? 0)\n }\n return result\n },\n set: (ref: any, data: Data, options?: { merge?: boolean }) => (staged.push(() => ref.set(data, options)), transaction),\n create: (ref: any, data: Data) => (staged.push(() => ref.create(data)), transaction),\n update: (ref: any, ...args: unknown[]) => (staged.push(() => ref.update(...args)), transaction),\n delete: (ref: any) => (staged.push(() => ref.delete()), transaction),\n }\n const result = await body(transaction)\n const stale = [...seen].some(([path, version]) => (versions.get(path) ?? 0) !== version)\n if (stale) continue\n // Every write starts before any is awaited, so the commit is atomic\n // against another transaction checking its own reads.\n await Promise.all(staged.map((write) => write()))\n return result\n }\n throw new Error('memory firestore: transaction contended too many times')\n },\n }\n\n return {\n docs,\n now: clock,\n firestore: firestore as unknown as FirebaseFirestore.Firestore,\n seed: (path, data) => docs.set(path, copy(data)),\n read: (path) => copy(docs.get(path)),\n }\n}\n"],"names":["DOCUMENT_ID","__documentId","memoryFirestoreModule","__esModule","FieldValue","delete","__sentinel","serverTimestamp","arrayUnion","values","arrayRemove","increment","by","FieldPath","documentId","Timestamp","fromDate","date","getTime","isSentinel","value","Boolean","copy","undefined","JSON","parse","stringify","readPath","data","path","split","reduce","node","key","memoryFirestore","clock","docs","Map","versions","bump","set","get","resolve","current","Array","isArray","Set","filter","entry","includes","Number","writePath","target","keys","slice","leaf","length","settle","base","next","Object","entries","snapshot","id","lastIndexOf","ref","docRef","exists","field","firestore","parent","collectionRef","collection","name","options","merge","create","has","assign","Error","code","update","args","patch","fromEntries","from","_unused","at","String","fieldOf","compare","a","b","matches","wanted","op","some","run","state","prefix","found","startsWith","map","filters","every","order","direction","sort","result","after","findIndex","limit","query","where","orderBy","count","startAfter","empty","size","doc","Math","random","toString","getAll","refs","batch","staged","push","commit","write","runTransaction","body","attempt","seen","transaction","stale","version","Promise","all","now","seed","read"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/testing/pos-ops-memory-firestore.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*==========================================\n * AN IN-MEMORY ADMIN FIRESTORE, for the register operations' specs\n * (AGL-3609) — the CRM's transfer double (AGL-3527), kept beside the\n * commerce specs because one plugin's testing helpers are not another's\n * to import.\n *\n * Documents by path; the operators the CRM's transfer hooks and the job\n * engine issue — `collectionGroup` (every collection of that name, at any\n * depth), `where` (equality, ranges, `in`, the array operators),\n * `orderBy` (a field or the document id), `limit`, `startAfter`, `count`,\n * `getAll`, batches and read-then-write transactions — and the write\n * sentinels (`delete`, `serverTimestamp`, `arrayUnion`, `arrayRemove`,\n * `increment`) applied along dotted paths, as Firestore applies them.\n *\n * A spec mocks `firebase-admin/firestore` with {@link memoryFirestoreModule}\n * so the code under test builds its sentinels from the same table.\n *=========================================*/\n\ntype Data = Record<string, unknown>\n\ninterface Sentinel {\n __sentinel: 'delete' | 'serverTimestamp' | 'arrayUnion' | 'arrayRemove' | 'increment'\n values?: unknown[]\n by?: number\n}\n\nconst DOCUMENT_ID = { __documentId: true }\n\n/** What a spec hands `jest.mock('firebase-admin/firestore', …)`. */\nexport const memoryFirestoreModule = {\n __esModule: true,\n FieldValue: {\n delete: (): Sentinel => ({ __sentinel: 'delete' }),\n serverTimestamp: (): Sentinel => ({ __sentinel: 'serverTimestamp' }),\n arrayUnion: (...values: unknown[]): Sentinel => ({ __sentinel: 'arrayUnion', values }),\n arrayRemove: (...values: unknown[]): Sentinel => ({ __sentinel: 'arrayRemove', values }),\n increment: (by: number): Sentinel => ({ __sentinel: 'increment', by }),\n },\n FieldPath: { documentId: () => DOCUMENT_ID },\n Timestamp: { fromDate: (date: Date) => date.getTime() },\n}\n\nconst isSentinel = (value: unknown): value is Sentinel =>\n Boolean(value && typeof value === 'object' && '__sentinel' in (value as object))\n\nconst copy = <T>(value: T): T => (value === undefined ? value : (JSON.parse(JSON.stringify(value)) as T))\n\nfunction readPath(data: Data | undefined, path: string): unknown {\n return path.split('.').reduce<unknown>((node, key) => (node as Data | undefined)?.[key], data)\n}\n\nexport interface MemoryFirestore {\n /** Every document, by full path. */\n docs: Map<string, Data>\n /** The clock `serverTimestamp` writes. */\n now: () => number\n firestore: FirebaseFirestore.Firestore\n /** Seeds one document at its full path. */\n seed: (path: string, data: Data) => void\n /** A document's data, or `undefined`. */\n read: (path: string) => Data | undefined\n}\n\n/** A fresh in-memory Firestore. */\nexport function memoryFirestore(clock: () => number = () => 1_800_000_000_000): MemoryFirestore {\n const docs = new Map<string, Data>()\n /** A write counter per path, for the transaction's concurrency check. */\n const versions = new Map<string, number>()\n const bump = (path: string) => versions.set(path, (versions.get(path) ?? 0) + 1)\n\n const resolve = (value: unknown, current: unknown): unknown => {\n if (!isSentinel(value)) return Array.isArray(value) || (value && typeof value === 'object') ? copy(value) : value\n switch (value.__sentinel) {\n case 'serverTimestamp':\n return clock()\n case 'arrayUnion':\n return [...new Set([...(Array.isArray(current) ? current : []), ...(value.values ?? [])])]\n case 'arrayRemove':\n return (Array.isArray(current) ? current : []).filter((entry) => !(value.values ?? []).includes(entry))\n case 'increment':\n return Number(current ?? 0) + Number(value.by ?? 0)\n default:\n return undefined\n }\n }\n\n /** Writes `value` at a dotted path, a `delete` sentinel removing the leaf. */\n const writePath = (target: Data, path: string, value: unknown): void => {\n const keys = path.split('.')\n let node = target\n for (const key of keys.slice(0, -1)) {\n if (!node[key] || typeof node[key] !== 'object') node[key] = {}\n node = node[key] as Data\n }\n const leaf = keys[keys.length - 1] as string\n if (isSentinel(value) && value.__sentinel === 'delete') delete node[leaf]\n else node[leaf] = resolve(value, node[leaf])\n }\n\n /** Every top-level key of `data` with sentinels resolved (a `set`). */\n const settle = (data: Data, base: Data = {}): Data => {\n const next = copy(base)\n for (const [key, value] of Object.entries(data)) {\n if (value === undefined) continue\n if (isSentinel(value)) writePath(next, key, value)\n else if (value && typeof value === 'object' && !Array.isArray(value) && base[key] && typeof base[key] === 'object') {\n next[key] = settle(value as Data, base[key] as Data)\n } else next[key] = resolve(value, next[key])\n }\n return next\n }\n\n const snapshot = (path: string): any => {\n const data = docs.get(path)\n return {\n id: path.slice(path.lastIndexOf('/') + 1),\n ref: docRef(path),\n exists: data !== undefined,\n data: () => copy(data),\n get: (field: string) => copy(readPath(data, field)),\n }\n }\n\n const docRef = (path: string): any => ({\n id: path.slice(path.lastIndexOf('/') + 1),\n path,\n get firestore() {\n return firestore\n },\n get parent() {\n return collectionRef(path.slice(0, path.lastIndexOf('/')))\n },\n collection: (name: string) => collectionRef(`${path}/${name}`),\n get: async () => snapshot(path),\n set: async (data: Data, options?: { merge?: boolean }) => {\n docs.set(path, settle(data, options?.merge ? (docs.get(path) ?? {}) : {}))\n bump(path)\n },\n create: async (data: Data) => {\n if (docs.has(path)) throw Object.assign(new Error(`ALREADY_EXISTS: ${path}`), { code: 6 })\n docs.set(path, settle(data))\n bump(path)\n },\n update: async (...args: unknown[]) => {\n const current = docs.get(path)\n if (!current) throw Object.assign(new Error(`NOT_FOUND: ${path}`), { code: 5 })\n const patch: Data =\n typeof args[0] === 'string'\n ? Object.fromEntries(\n Array.from({ length: args.length / 2 }, (_unused, at) => [String(args[at * 2]), args[at * 2 + 1]]),\n )\n : (args[0] as Data)\n const next = copy(current)\n for (const [key, value] of Object.entries(patch)) writePath(next, key, value)\n docs.set(path, next)\n bump(path)\n },\n delete: async () => {\n docs.delete(path)\n bump(path)\n },\n })\n\n interface QueryState {\n path: string\n /** A collection-group query: `path` is the collection's NAME, matched at any depth. */\n group?: boolean\n filters: Array<{ field: string | typeof DOCUMENT_ID; op: string; value: unknown }>\n order: Array<{ field: string | typeof DOCUMENT_ID; direction: 'asc' | 'desc' }>\n limit?: number\n after?: any\n }\n\n const fieldOf = (data: Data | undefined, id: string, field: string | typeof DOCUMENT_ID) =>\n field === DOCUMENT_ID ? id : readPath(data, field as string)\n\n const compare = (a: unknown, b: unknown): number => {\n if (a === b) return 0\n if (a === undefined || a === null) return -1\n if (b === undefined || b === null) return 1\n return (a as number) < (b as number) ? -1 : 1\n }\n\n const matches = (data: Data, id: string, filter: QueryState['filters'][number]): boolean => {\n const value = fieldOf(data, id, filter.field)\n const wanted = filter.value\n switch (filter.op) {\n case '==':\n return JSON.stringify(value) === JSON.stringify(wanted)\n case '!=':\n return value !== undefined && JSON.stringify(value) !== JSON.stringify(wanted)\n case 'in':\n return (wanted as unknown[]).some((entry) => JSON.stringify(entry) === JSON.stringify(value))\n case 'not-in':\n return value !== undefined && !(wanted as unknown[]).some((entry) => JSON.stringify(entry) === JSON.stringify(value))\n case 'array-contains':\n return Array.isArray(value) && value.includes(wanted)\n case 'array-contains-any':\n return Array.isArray(value) && value.some((entry) => (wanted as unknown[]).includes(entry))\n case '<':\n return value !== undefined && compare(value, wanted) < 0\n case '<=':\n return value !== undefined && compare(value, wanted) <= 0\n case '>':\n return value !== undefined && compare(value, wanted) > 0\n case '>=':\n return value !== undefined && compare(value, wanted) >= 0\n default:\n throw new Error(`memory firestore: no operator ${filter.op}`)\n }\n }\n\n const inQuery = (state: QueryState, path: string): boolean => {\n if (state.group) {\n const segments = path.split('/')\n return segments.length >= 2 && segments.length % 2 === 0 && segments[segments.length - 2] === state.path\n }\n const prefix = `${state.path}/`\n return path.startsWith(prefix) && !path.slice(prefix.length).includes('/')\n }\n\n const run = (state: QueryState): any[] => {\n let found = [...docs.entries()]\n .filter(([path]) => inQuery(state, path))\n .map(([path, data]) => ({ path, id: path.slice(path.lastIndexOf('/') + 1), data }))\n .filter((entry) => state.filters.every((filter) => matches(entry.data, entry.id, filter)))\n const order = state.order.length ? state.order : [{ field: DOCUMENT_ID, direction: 'asc' as const }]\n for (const { field } of order) {\n if (field !== DOCUMENT_ID) found = found.filter((entry) => readPath(entry.data, field as string) !== undefined)\n }\n found.sort((a, b) => {\n for (const { field, direction } of [...order, { field: DOCUMENT_ID, direction: 'asc' as const }]) {\n const result = compare(fieldOf(a.data, a.id, field), fieldOf(b.data, b.id, field))\n if (result) return direction === 'desc' ? -result : result\n }\n return 0\n })\n if (state.after) {\n const at = found.findIndex((entry) => entry.id === state.after.id)\n found = at >= 0 ? found.slice(at + 1) : found\n }\n if (state.limit !== undefined) found = found.slice(0, state.limit)\n return found.map((entry) => snapshot(entry.path))\n }\n\n const query = (state: QueryState): any => ({\n where: (field: string | typeof DOCUMENT_ID, op: string, value: unknown) =>\n query({ ...state, filters: [...state.filters, { field, op, value }] }),\n orderBy: (field: string | typeof DOCUMENT_ID, direction: 'asc' | 'desc' = 'asc') =>\n query({ ...state, order: [...state.order, { field, direction }] }),\n limit: (count: number) => query({ ...state, limit: count }),\n startAfter: (after: any) => query({ ...state, after }),\n get: async () => {\n const found = run(state)\n return { docs: found, empty: !found.length, size: found.length }\n },\n count: () => ({\n get: async () => ({ data: () => ({ count: run({ ...state, limit: undefined }).length }) }),\n }),\n })\n\n const collectionRef = (path: string): any => ({\n id: path.slice(path.lastIndexOf('/') + 1),\n path,\n get parent() {\n const at = path.lastIndexOf('/')\n return at > 0 ? docRef(path.slice(0, at)) : null\n },\n doc: (id?: string) => docRef(`${path}/${id ?? `auto${Math.random().toString(36).slice(2, 12)}`}`),\n ...query({ path, filters: [], order: [] }),\n })\n\n const firestore = {\n collection: (name: string) => collectionRef(name),\n collectionGroup: (name: string) => query({ path: name, group: true, filters: [], order: [] }),\n getAll: async (...refs: Array<{ path: string }>) => refs.map((ref) => snapshot(ref.path)),\n batch: () => {\n const staged: Array<() => Promise<void>> = []\n const batch = {\n set: (ref: any, data: Data, options?: { merge?: boolean }) => (staged.push(() => ref.set(data, options)), batch),\n create: (ref: any, data: Data) => (staged.push(() => ref.create(data)), batch),\n update: (ref: any, ...args: unknown[]) => (staged.push(() => ref.update(...args)), batch),\n delete: (ref: any) => (staged.push(() => ref.delete()), batch),\n commit: async () => {\n for (const write of staged) await write()\n },\n }\n return batch\n },\n /**\n * Read-then-write with OPTIMISTIC CONCURRENCY, as the server SDK commits\n * one: every document the body read is versioned, and a commit that finds\n * one of them written since is thrown away and the body run again. Two\n * transactions racing on one document therefore end the way they do in\n * Firestore — the second re-reads the first one's write — which is the\n * property a one-open-shift or a lockout counter rests on.\n */\n runTransaction: async <T>(body: (transaction: any) => Promise<T>): Promise<T> => {\n for (let attempt = 0; attempt < 10; attempt += 1) {\n const staged: Array<() => Promise<void>> = []\n const seen = new Map<string, number>()\n const transaction = {\n get: async (target: any) => {\n const result = await target.get()\n if (typeof target.path === 'string' && !('docs' in result)) {\n seen.set(target.path, versions.get(target.path) ?? 0)\n } else if (result?.docs) {\n for (const doc of result.docs) seen.set(doc.ref.path, versions.get(doc.ref.path) ?? 0)\n }\n return result\n },\n set: (ref: any, data: Data, options?: { merge?: boolean }) => (staged.push(() => ref.set(data, options)), transaction),\n create: (ref: any, data: Data) => (staged.push(() => ref.create(data)), transaction),\n update: (ref: any, ...args: unknown[]) => (staged.push(() => ref.update(...args)), transaction),\n delete: (ref: any) => (staged.push(() => ref.delete()), transaction),\n }\n const result = await body(transaction)\n const stale = [...seen].some(([path, version]) => (versions.get(path) ?? 0) !== version)\n if (stale) continue\n // Every write starts before any is awaited, so the commit is atomic\n // against another transaction checking its own reads.\n await Promise.all(staged.map((write) => write()))\n return result\n }\n throw new Error('memory firestore: transaction contended too many times')\n },\n }\n\n return {\n docs,\n now: clock,\n firestore: firestore as unknown as FirebaseFirestore.Firestore,\n seed: (path, data) => docs.set(path, copy(data)),\n read: (path) => copy(docs.get(path)),\n }\n}\n"],"names":["DOCUMENT_ID","__documentId","memoryFirestoreModule","__esModule","FieldValue","delete","__sentinel","serverTimestamp","arrayUnion","values","arrayRemove","increment","by","FieldPath","documentId","Timestamp","fromDate","date","getTime","isSentinel","value","Boolean","copy","undefined","JSON","parse","stringify","readPath","data","path","split","reduce","node","key","memoryFirestore","clock","docs","Map","versions","bump","set","get","resolve","current","Array","isArray","Set","filter","entry","includes","Number","writePath","target","keys","slice","leaf","length","settle","base","next","Object","entries","snapshot","id","lastIndexOf","ref","docRef","exists","field","firestore","parent","collectionRef","collection","name","options","merge","create","has","assign","Error","code","update","args","patch","fromEntries","from","_unused","at","String","fieldOf","compare","a","b","matches","wanted","op","some","inQuery","state","group","segments","prefix","startsWith","run","found","map","filters","every","order","direction","sort","result","after","findIndex","limit","query","where","orderBy","count","startAfter","empty","size","doc","Math","random","toString","collectionGroup","getAll","refs","batch","staged","push","commit","write","runTransaction","body","attempt","seen","transaction","stale","version","Promise","all","now","seed","read"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The register's `managePos` as `resolveOrgPermissions(uid, { hostId })`
|
|
19
|
+
* resolves it for one site (AGL-4047), for the specs that fake that resolver
|
|
20
|
+
* now that the POS routes ask it alone and no longer read the site's
|
|
21
|
+
* `memberRoles` themselves.
|
|
22
|
+
*
|
|
23
|
+
* Someone with no access to the site holds nothing. Otherwise the site
|
|
24
|
+
* role's default decides — on for admin and editor, off for author and
|
|
25
|
+
* viewer, the tier defaults `managePos` is declared with — unless a role or
|
|
26
|
+
* an override `granted` or refused it.
|
|
27
|
+
*/
|
|
28
|
+
export declare const SITE_ROLE_REGISTER_DEFAULTS: Readonly<Record<string, boolean>>;
|
|
29
|
+
export declare function siteRegisterVerdict(memberRoles: Readonly<Record<string, unknown>> | null | undefined, uid: string, granted?: boolean): boolean;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* The register's `managePos` as `resolveOrgPermissions(uid, { hostId })`
|
|
18
|
+
* resolves it for one site (AGL-4047), for the specs that fake that resolver
|
|
19
|
+
* now that the POS routes ask it alone and no longer read the site's
|
|
20
|
+
* `memberRoles` themselves.
|
|
21
|
+
*
|
|
22
|
+
* Someone with no access to the site holds nothing. Otherwise the site
|
|
23
|
+
* role's default decides — on for admin and editor, off for author and
|
|
24
|
+
* viewer, the tier defaults `managePos` is declared with — unless a role or
|
|
25
|
+
* an override `granted` or refused it.
|
|
26
|
+
*/ export const SITE_ROLE_REGISTER_DEFAULTS = {
|
|
27
|
+
admin: true,
|
|
28
|
+
editor: true,
|
|
29
|
+
author: false,
|
|
30
|
+
viewer: false
|
|
31
|
+
};
|
|
32
|
+
export function siteRegisterVerdict(memberRoles, uid, granted) {
|
|
33
|
+
const role = memberRoles == null ? void 0 : memberRoles[uid];
|
|
34
|
+
if (typeof role !== 'string' || !role) return false;
|
|
35
|
+
return typeof granted === 'boolean' ? granted : SITE_ROLE_REGISTER_DEFAULTS[role] === true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=site-register-permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/testing/site-register-permissions.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The register's `managePos` as `resolveOrgPermissions(uid, { hostId })`\n * resolves it for one site (AGL-4047), for the specs that fake that resolver\n * now that the POS routes ask it alone and no longer read the site's\n * `memberRoles` themselves.\n *\n * Someone with no access to the site holds nothing. Otherwise the site\n * role's default decides — on for admin and editor, off for author and\n * viewer, the tier defaults `managePos` is declared with — unless a role or\n * an override `granted` or refused it.\n */\nexport const SITE_ROLE_REGISTER_DEFAULTS: Readonly<Record<string, boolean>> = {\n admin: true,\n editor: true,\n author: false,\n viewer: false,\n}\n\nexport function siteRegisterVerdict(\n memberRoles: Readonly<Record<string, unknown>> | null | undefined,\n uid: string,\n granted?: boolean,\n): boolean {\n const role = memberRoles?.[uid]\n if (typeof role !== 'string' || !role) return false\n return typeof granted === 'boolean' ? granted : SITE_ROLE_REGISTER_DEFAULTS[role] === true\n}\n"],"names":["SITE_ROLE_REGISTER_DEFAULTS","admin","editor","author","viewer","siteRegisterVerdict","memberRoles","uid","granted","role"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;CAUC,GACD,OAAO,MAAMA,8BAAiE;IAC5EC,OAAO;IACPC,QAAQ;IACRC,QAAQ;IACRC,QAAQ;AACV,EAAC;AAED,OAAO,SAASC,oBACdC,WAAiE,EACjEC,GAAW,EACXC,OAAiB;IAEjB,MAAMC,OAAOH,+BAAAA,WAAa,CAACC,IAAI;IAC/B,IAAI,OAAOE,SAAS,YAAY,CAACA,MAAM,OAAO;IAC9C,OAAO,OAAOD,YAAY,YAAYA,UAAUR,2BAA2B,CAACS,KAAK,KAAK;AACxF"}
|
|
@@ -15,11 +15,11 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/ import { buildMatchLookup } from "@aglyn/aglyn/data-transfer";
|
|
18
|
-
import { hostRoleFor } from "@aglyn/aglyn/app-utils/organizations";
|
|
19
18
|
import * as Aglyn from "@aglyn/aglyn/server";
|
|
20
|
-
import { firebaseAdmin, getOrgForHost, resolveOrgMembership } from "@aglyn/tenant-data-admin";
|
|
19
|
+
import { firebaseAdmin, getOrgForHost, memberHasPermissionOnHost, resolveOrgMembership } from "@aglyn/tenant-data-admin";
|
|
21
20
|
import { TransferEngineError } from "@aglyn/tenant-data-admin/server/transfer-jobs";
|
|
22
21
|
import { normalizeTrackingNumber, parseShippingOrderRef } from "../model/order-shipping-export.js";
|
|
22
|
+
import { commerceSitePermissionRefusal } from "../model/plugin-permissions.js";
|
|
23
23
|
import { cancelOrderFulfillment, recordOrderShipment, updateFulfillmentTracking } from "../server/fulfill-order.js";
|
|
24
24
|
import { NOTHING, ROW_BUDGET_MS, firestoreOf, hostRefOf, readerSeesHost } from "./server-common.js";
|
|
25
25
|
import { TRACKING_DEFAULT_POLICY, TRACKING_MATCH_KEYS, matchTrackingRows, planTrackingRows, trackingExportRows, trackingMatchValues, trackingRecord } from "./tracking-transfer.js";
|
|
@@ -50,9 +50,12 @@ import { TRACKING_DEFAULT_POLICY, TRACKING_MATCH_KEYS, matchTrackingRows, planTr
|
|
|
50
50
|
if (!hostId) throw new TransferEngineError('invalid', 400, 'Tracking numbers belong to a site; name the site.');
|
|
51
51
|
const uid = ctx.actorUid;
|
|
52
52
|
const membership = uid ? await resolveOrgMembership(uid, ctx.orgId) : null;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
// "Manage orders" (`commerce.orders`, AGL-4047) on this site, resolved fresh
|
|
54
|
+
// from the membership: its preset is the site's Admin and Editor this
|
|
55
|
+
// asked for, then the member's custom role, own permissions and site toggle.
|
|
56
|
+
const allowed = !!uid && !!(membership == null ? void 0 : membership.member) && await memberHasPermissionOnHost(ctx.orgId, hostId, membership.member, 'commerce.orders');
|
|
57
|
+
if (!allowed) {
|
|
58
|
+
throw new TransferEngineError('forbidden', 403, commerceSitePermissionRefusal('commerce.orders'));
|
|
56
59
|
}
|
|
57
60
|
const owner = await getOrgForHost(hostId).catch(()=>null);
|
|
58
61
|
if (!Aglyn.checkEntitlement(owner == null ? void 0 : owner.org, 'commerce')) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/transfer/tracking.server.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n buildMatchLookup,\n type BuildTransferPlanInput,\n type MatchKeySpec,\n type MatchLookupRequest,\n type PlannedTransferRow,\n type TransferChunk,\n type TransferPlan,\n type TransferRowResult,\n type TransferUndoEntry,\n type TransferUndoSnapshot,\n type TransferUndoStep,\n} from '@aglyn/aglyn/data-transfer'\nimport { hostRoleFor } from '@aglyn/aglyn/app-utils/organizations'\nimport * as Aglyn from '@aglyn/aglyn/server'\nimport type {\n PluginTransferResource,\n TransferApplyResult,\n TransferApplyWriter,\n TransferLookupResult,\n TransferReadOptions,\n TransferReadPage,\n TransferResourceContext,\n TransferRevertDecisions,\n TransferRevertResult,\n} from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources'\nimport { firebaseAdmin, getOrgForHost, resolveOrgMembership } from '@aglyn/tenant-data-admin'\nimport { TransferEngineError } from '@aglyn/tenant-data-admin/server/transfer-jobs'\nimport { normalizeTrackingNumber, parseShippingOrderRef } from '../model/order-shipping-export'\nimport {\n cancelOrderFulfillment,\n recordOrderShipment,\n updateFulfillmentTracking,\n} from '../server/fulfill-order'\nimport { NOTHING, ROW_BUDGET_MS, firestoreOf, hostRefOf, readerSeesHost, type Firestore } from './server-common'\nimport {\n TRACKING_DEFAULT_POLICY,\n TRACKING_MATCH_KEYS,\n matchTrackingRows,\n planTrackingRows,\n trackingExportRows,\n trackingMatchValues,\n trackingRecord,\n type StoredTrackingOrder,\n type TrackingPlannedRow,\n} from './tracking-transfer'\n\n/*\n * THE TRACKING IMPORT'S SERVER HALF (AGL-3613). The plan is\n * `planTrackingRows`; this module reads the orders it plans against, writes\n * each parcel through the order's own shipment paths and undoes them.\n *\n * - WHO: the site's admins and editors — the roles the console's Fulfill\n * button has — on a plan that sells. Asked by the plan, the apply and the\n * undo, each server-side.\n * - HOW: a new parcel through `recordOrderShipment`, keyed by its tracking\n * number, so a retried chunk or a second import of the same file is one\n * parcel; the buyer is emailed as for any shipment. A replaced tracking\n * number through `updateFulfillmentTracking`.\n * - UNDO: a parcel this import recorded is cancelled (its units go back to\n * unfulfilled), and a replaced tracking number is put back — each only\n * while the shipment still holds what the import wrote; otherwise it is a\n * conflict the person decides.\n */\n\nconst IN_MAX = 30\n\n/** Orders a page of the shipments export reads: those that have shipped something. */\nconst SHIPPED_STATUSES = ['partially_fulfilled', 'fulfilled', 'delivered']\n\n/** The member importing, checked for the role and the plan, or the refusal. */\nasync function shipperOf(ctx: TransferResourceContext): Promise<{ hostId: string }> {\n const hostId = ctx.hostId\n if (!hostId) throw new TransferEngineError('invalid', 400, 'Tracking numbers belong to a site; name the site.')\n const uid = ctx.actorUid\n const membership = uid ? await resolveOrgMembership(uid, ctx.orgId) : null\n const role = membership?.member ? hostRoleFor(membership.member, hostId as never) : null\n if (!uid || (role !== 'admin' && role !== 'editor')) {\n throw new TransferEngineError('forbidden', 403, 'Only a site’s admins and editors can record shipments.')\n }\n const owner = await getOrgForHost(hostId).catch(() => null)\n if (!Aglyn.checkEntitlement(owner?.org as never, 'commerce')) {\n throw new TransferEngineError('forbidden', 403, 'This site’s plan does not include selling.')\n }\n return { hostId }\n}\n\nconst ordersOf = (firestore: Firestore, ctx: TransferResourceContext) => hostRefOf(firestore, ctx).collection('orders')\n\n/** Orders by the values a file names them by: numbers through one query per 30, ids directly. */\nasync function findOrders(\n firestore: Firestore,\n ctx: TransferResourceContext,\n requests: readonly MatchLookupRequest[],\n): Promise<Map<string, FirebaseFirestore.DocumentSnapshot>> {\n const collection = ordersOf(firestore, ctx)\n const found = new Map<string, FirebaseFirestore.DocumentSnapshot>()\n const numbers = new Set<number>()\n const ids = new Set<string>()\n for (const request of requests) {\n for (const value of request.values) {\n const ref = request.fieldId === 'id' ? { id: value } : parseShippingOrderRef(value)\n if (!ref) continue\n if (ref.number !== undefined) numbers.add(ref.number)\n if (ref.id && !ref.id.includes('/') && !/^__.*__$/.test(ref.id)) ids.add(ref.id)\n }\n }\n const numberList = [...numbers]\n for (let at = 0; at < numberList.length; at += IN_MAX) {\n const snapshot = await collection.where('number', 'in', numberList.slice(at, at + IN_MAX)).get()\n for (const doc of snapshot.docs) found.set(doc.id, doc)\n }\n const idList = [...ids].filter((id) => !found.has(id))\n for (let at = 0; at < idList.length; at += 100) {\n for (const doc of await firestore.getAll(...idList.slice(at, at + 100).map((id) => collection.doc(id)))) {\n if (doc.exists) found.set(doc.id, doc)\n }\n }\n return found\n}\n\nexport async function lookupTrackingOrders(\n ctx: TransferResourceContext,\n requests: readonly MatchLookupRequest[],\n): Promise<TransferLookupResult> {\n const found = await findOrders(firestoreOf(), ctx, requests)\n const keys: MatchKeySpec[] = requests.map((request) => ({ fieldId: request.fieldId, normalizer: request.normalizer }))\n const records = new Map<string, Readonly<Record<string, unknown>>>()\n const entries: Array<{ id: string; values: Record<string, unknown> }> = []\n for (const doc of found.values()) {\n const data = (doc.data() ?? {}) as StoredTrackingOrder\n records.set(doc.id, trackingRecord(doc.id, data))\n entries.push({ id: doc.id, values: trackingMatchValues(doc.id, data) })\n }\n return { lookup: buildMatchLookup(entries, keys), records }\n}\n\n/**\n * The shipments export: every order that has shipped something, newest\n * first, one row per shipment with a tracking number. The cursor is the last\n * order's `createdAtMs` and id, as the orders export pages.\n */\nexport async function readTrackingPage(\n ctx: TransferResourceContext,\n cursor: string | null,\n fieldIds: readonly string[],\n options?: TransferReadOptions,\n): Promise<TransferReadPage> {\n if (!readerSeesHost(ctx, options)) return NOTHING\n if (options?.filter) throw new Error('Shipments export every shipment, or those of the orders you select.')\n const firestore = firestoreOf()\n const collection = ordersOf(firestore, ctx)\n const pageSize = Math.max(1, Math.min(500, options?.pageSize ?? 200))\n let docs: FirebaseFirestore.DocumentSnapshot[]\n let next: string | null\n if (options?.ids) {\n const offset = cursor ? Number(cursor) : 0\n const ids = options.ids.slice(offset, offset + pageSize)\n docs = ids.length ? (await firestore.getAll(...ids.map((id) => collection.doc(id)))).filter((doc) => doc.exists) : []\n next = offset + ids.length < options.ids.length ? String(offset + ids.length) : null\n } else {\n const query = collection\n .where('status', 'in', SHIPPED_STATUSES)\n .orderBy('createdAtMs', 'desc')\n .orderBy(firebaseAdmin.firestore.FieldPath.documentId(), 'desc')\n const after = cursor ? (JSON.parse(cursor) as unknown[]) : null\n const snapshot = await (after ? query.startAfter(...after) : query).limit(pageSize).get()\n docs = snapshot.docs\n const last = snapshot.docs[snapshot.docs.length - 1]\n next = last && snapshot.docs.length === pageSize ? JSON.stringify([last.get('createdAtMs') ?? null, last.id]) : null\n }\n const rows = docs.flatMap((doc) =>\n trackingExportRows(doc.id, (doc.data() ?? {}) as StoredTrackingOrder).map((record) =>\n Object.fromEntries(fieldIds.map((fieldId) => [fieldId, record[fieldId] ?? null])),\n ),\n )\n return { rows, next }\n}\n\n/** The dry run, against every matched order read once. */\nexport async function planTracking(ctx: TransferResourceContext, input: BuildTransferPlanInput): Promise<TransferPlan> {\n await shipperOf(ctx)\n const firestore = firestoreOf()\n const ids = [\n ...new Set(\n input.matches\n .map((match) => (match.kind === 'matched' ? match.recordId : null))\n .filter((id): id is string => Boolean(id)),\n ),\n ]\n const collection = ordersOf(firestore, ctx)\n const orders = new Map<string, StoredTrackingOrder>()\n for (let at = 0; at < ids.length; at += 100) {\n for (const doc of await firestore.getAll(...ids.slice(at, at + 100).map((id) => collection.doc(id)))) {\n if (doc.exists) orders.set(doc.id, (doc.data() ?? {}) as StoredTrackingOrder)\n }\n }\n return planTrackingRows(input, orders)\n}\n\n/** Records one chunk's parcels, each through the order's own shipment paths. */\nexport async function applyTracking(\n ctx: TransferResourceContext,\n chunk: TransferChunk<PlannedTransferRow>,\n writer: TransferApplyWriter,\n): Promise<TransferApplyResult> {\n const { hostId } = await shipperOf(ctx)\n const results: TransferRowResult[] = []\n const undo: TransferUndoEntry[] = []\n const fail = async (row: number, message: string) => {\n const result: TransferRowResult = { row, outcome: 'failed', reason: 'refusedValue', message }\n results.push(result)\n await writer.markApplied(result)\n }\n for (const row of chunk.rows as TrackingPlannedRow[]) {\n const earlier = await writer.alreadyApplied(row.index)\n if (earlier) {\n results.push(earlier)\n continue\n }\n if (writer.timeLeftMs() < ROW_BUDGET_MS) break\n const decision = row.tracking\n if (row.verdict !== 'update' || !decision) {\n await fail(row.index, 'A tracking file only records parcels for orders it names.')\n continue\n }\n if (decision.action === 'ship') {\n const outcome = await recordOrderShipment({\n hostId,\n orderId: decision.orderId,\n to: 'fulfilled',\n carrier: decision.carrier,\n trackingNumber: decision.trackingNumber,\n ...(decision.trackingUrl ? { trackingUrl: decision.trackingUrl } : {}),\n ...(decision.lineItems ? { lineItems: decision.lineItems } : {}),\n idempotencyKey: `tracking-import:${normalizeTrackingNumber(decision.trackingNumber)}`,\n onceByTracking: true,\n })\n if (outcome.outcome === 'recorded' || (outcome.outcome === 'already' && outcome.fulfillment)) {\n const fulfillment = outcome.fulfillment\n const result: TransferRowResult = {\n row: row.index,\n outcome: outcome.outcome === 'recorded' ? 'updated' : 'unchanged',\n recordId: decision.orderId,\n }\n // Only a parcel THIS import recorded is undone; one found already\n // there was somebody else's.\n const entry: TransferUndoEntry | undefined =\n outcome.outcome === 'recorded' && fulfillment\n ? {\n row: row.index,\n recordId: decision.orderId,\n action: 'updated',\n previous: { fulfillmentId: null },\n written: {\n fulfillmentId: fulfillment.id,\n trackingNumber: fulfillment.trackingNumber ?? null,\n carrier: fulfillment.carrier ?? null,\n },\n }\n : undefined\n results.push(result)\n if (entry) undo.push(entry)\n await writer.markApplied(result, entry)\n continue\n }\n await fail(\n row.index,\n outcome.outcome === 'blocked'\n ? `The order is ${outcome.from.replace(/_/g, ' ')} and cannot be shipped.`\n : outcome.outcome === 'invalid_lines'\n ? outcome.message\n : outcome.outcome === 'no_such_order'\n ? 'The order no longer exists.'\n : 'The order has nothing left to ship.',\n )\n continue\n }\n const outcome = await updateFulfillmentTracking({\n hostId,\n orderId: decision.orderId,\n fulfillmentId: decision.fulfillmentId,\n carrier: decision.carrier,\n trackingNumber: decision.trackingNumber,\n ...(decision.trackingUrl ? { trackingUrl: decision.trackingUrl } : {}),\n })\n if (outcome.outcome === 'updated' || outcome.outcome === 'already') {\n const result: TransferRowResult = {\n row: row.index,\n outcome: outcome.outcome === 'updated' ? 'updated' : 'unchanged',\n recordId: decision.orderId,\n }\n const entry: TransferUndoEntry | undefined =\n outcome.outcome === 'updated'\n ? {\n row: row.index,\n recordId: decision.orderId,\n action: 'updated',\n previous: { fulfillmentId: decision.fulfillmentId, ...decision.previous },\n written: {\n fulfillmentId: decision.fulfillmentId,\n trackingNumber: outcome.fulfillment.trackingNumber ?? null,\n carrier: outcome.fulfillment.carrier ?? null,\n },\n }\n : undefined\n results.push(result)\n if (entry) undo.push(entry)\n await writer.markApplied(result, entry)\n continue\n }\n await fail(\n row.index,\n outcome.outcome === 'locked'\n ? `The order is ${outcome.from.replace(/_/g, ' ')}; its shipments can no longer change.`\n : 'The shipment no longer exists.',\n )\n }\n return { results, undo }\n}\n\n/**\n * Undoes one chunk, newest first: a parcel the import recorded is cancelled\n * and a tracking number it replaced is put back — while the shipment still\n * holds what the import wrote. A shipment edited since is a conflict, done\n * only when the person's decision says `revert`.\n */\nexport async function revertTracking(\n ctx: TransferResourceContext,\n snapshot: TransferUndoSnapshot,\n decisions?: TransferRevertDecisions,\n): Promise<TransferRevertResult> {\n const { hostId } = await shipperOf(ctx)\n const firestore = firestoreOf()\n const collection = ordersOf(firestore, ctx)\n const done: TransferUndoStep[] = []\n const conflicts: TransferUndoStep[] = []\n for (const entry of [...snapshot.entries].reverse()) {\n const fulfillmentId = String(entry.written['fulfillmentId'] ?? '')\n const doc = await collection.doc(entry.recordId).get()\n const order = doc.exists ? ((doc.data() ?? {}) as Record<string, unknown>) : null\n const current = ((order?.['fulfillments'] as Array<Record<string, unknown>> | undefined) ?? []).find(\n (fulfillment) => fulfillment['id'] === fulfillmentId,\n )\n if (!doc.exists || !current || current['status'] === 'cancelled') {\n done.push({ action: 'nothing', recordId: entry.recordId, why: doc.exists ? 'alreadyReverted' : 'gone' })\n continue\n }\n const edited =\n normalizeTrackingNumber(current['trackingNumber']) !== normalizeTrackingNumber(entry.written['trackingNumber'])\n if (edited && decisions?.[entry.recordId] !== 'revert') {\n conflicts.push({\n action: 'conflict',\n recordId: entry.recordId,\n fields: ['trackingNumber'],\n values: { trackingNumber: current['trackingNumber'] ?? null },\n })\n continue\n }\n const recorded = entry.previous?.['fulfillmentId'] === null\n const outcome = recorded\n ? await cancelOrderFulfillment({ hostId, orderId: entry.recordId, fulfillmentId })\n : await updateFulfillmentTracking({\n hostId,\n orderId: entry.recordId,\n fulfillmentId,\n carrier: String(entry.previous?.['carrier'] ?? ''),\n trackingNumber: String(entry.previous?.['trackingNumber'] ?? ''),\n ...(entry.previous?.['trackingUrl'] ? { trackingUrl: String(entry.previous['trackingUrl']) } : {}),\n })\n if (outcome.outcome === 'locked') {\n conflicts.push({\n action: 'conflict',\n recordId: entry.recordId,\n fields: ['status'],\n values: { status: outcome.from },\n })\n continue\n }\n done.push(\n recorded\n ? { action: 'delete', recordId: entry.recordId }\n : {\n action: 'restore',\n recordId: entry.recordId,\n values: { trackingNumber: entry.previous?.['trackingNumber'] ?? null },\n },\n )\n }\n return { done, conflicts }\n}\n\nexport const trackingTransfer: PluginTransferResource = {\n matchKeys: TRACKING_MATCH_KEYS,\n defaultPolicy: TRACKING_DEFAULT_POLICY,\n readPage: (ctx, cursor, fieldIds, options) => readTrackingPage(ctx, cursor, fieldIds, options),\n lookup: (ctx, requests) => lookupTrackingOrders(ctx, requests),\n match: (_ctx, input) => ({ outcomes: matchTrackingRows(input.rows, input.lookup) }),\n plan: (ctx, input) => planTracking(ctx, input),\n apply: (ctx, chunk, writer) => applyTracking(ctx, chunk, writer),\n revert: (ctx, snapshot, decisions) => revertTracking(ctx, snapshot, decisions),\n}\n"],"names":["buildMatchLookup","hostRoleFor","Aglyn","firebaseAdmin","getOrgForHost","resolveOrgMembership","TransferEngineError","normalizeTrackingNumber","parseShippingOrderRef","cancelOrderFulfillment","recordOrderShipment","updateFulfillmentTracking","NOTHING","ROW_BUDGET_MS","firestoreOf","hostRefOf","readerSeesHost","TRACKING_DEFAULT_POLICY","TRACKING_MATCH_KEYS","matchTrackingRows","planTrackingRows","trackingExportRows","trackingMatchValues","trackingRecord","IN_MAX","SHIPPED_STATUSES","shipperOf","ctx","hostId","uid","actorUid","membership","orgId","role","member","owner","catch","checkEntitlement","org","ordersOf","firestore","collection","findOrders","requests","found","Map","numbers","Set","ids","request","value","values","ref","fieldId","id","number","undefined","add","includes","test","numberList","at","length","snapshot","where","slice","get","doc","docs","set","idList","filter","has","getAll","map","exists","lookupTrackingOrders","keys","normalizer","records","entries","data","push","lookup","readTrackingPage","cursor","fieldIds","options","Error","pageSize","Math","max","min","next","offset","Number","String","last","query","orderBy","FieldPath","documentId","after","JSON","parse","startAfter","limit","stringify","rows","flatMap","record","Object","fromEntries","planTracking","input","matches","match","kind","recordId","Boolean","orders","applyTracking","chunk","writer","results","undo","fail","row","message","result","outcome","reason","markApplied","earlier","alreadyApplied","index","timeLeftMs","decision","tracking","verdict","action","orderId","to","carrier","trackingNumber","trackingUrl","lineItems","idempotencyKey","onceByTracking","fulfillment","entry","previous","fulfillmentId","written","from","replace","revertTracking","decisions","done","conflicts","reverse","order","current","find","why","edited","fields","recorded","status","trackingTransfer","matchKeys","defaultPolicy","readPage","_ctx","outcomes","plan","apply","revert"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,gBAAgB,QAWX,6BAA4B;AACnC,SAASC,WAAW,QAAQ,uCAAsC;AAClE,YAAYC,WAAW,sBAAqB;AAY5C,SAASC,aAAa,EAAEC,aAAa,EAAEC,oBAAoB,QAAQ,2BAA0B;AAC7F,SAASC,mBAAmB,QAAQ,gDAA+C;AACnF,SAASC,uBAAuB,EAAEC,qBAAqB,QAAQ,oCAAgC;AAC/F,SACEC,sBAAsB,EACtBC,mBAAmB,EACnBC,yBAAyB,QACpB,6BAAyB;AAChC,SAASC,OAAO,EAAEC,aAAa,EAAEC,WAAW,EAAEC,SAAS,EAAEC,cAAc,QAAwB,qBAAiB;AAChH,SACEC,uBAAuB,EACvBC,mBAAmB,EACnBC,iBAAiB,EACjBC,gBAAgB,EAChBC,kBAAkB,EAClBC,mBAAmB,EACnBC,cAAc,QAGT,yBAAqB;AAE5B;;;;;;;;;;;;;;;;CAgBC,GAED,MAAMC,SAAS;AAEf,oFAAoF,GACpF,MAAMC,mBAAmB;IAAC;IAAuB;IAAa;CAAY;AAE1E,6EAA6E,GAC7E,eAAeC,UAAUC,GAA4B;IACnD,MAAMC,SAASD,IAAIC,MAAM;IACzB,IAAI,CAACA,QAAQ,MAAM,IAAItB,oBAAoB,WAAW,KAAK;IAC3D,MAAMuB,MAAMF,IAAIG,QAAQ;IACxB,MAAMC,aAAaF,MAAM,MAAMxB,qBAAqBwB,KAAKF,IAAIK,KAAK,IAAI;IACtE,MAAMC,OAAOF,CAAAA,8BAAAA,WAAYG,MAAM,IAAGjC,YAAY8B,WAAWG,MAAM,EAAEN,UAAmB;IACpF,IAAI,CAACC,OAAQI,SAAS,WAAWA,SAAS,UAAW;QACnD,MAAM,IAAI3B,oBAAoB,aAAa,KAAK;IAClD;IACA,MAAM6B,QAAQ,MAAM/B,cAAcwB,QAAQQ,KAAK,CAAC,IAAM;IACtD,IAAI,CAAClC,MAAMmC,gBAAgB,CAACF,yBAAAA,MAAOG,GAAG,EAAW,aAAa;QAC5D,MAAM,IAAIhC,oBAAoB,aAAa,KAAK;IAClD;IACA,OAAO;QAAEsB;IAAO;AAClB;AAEA,MAAMW,WAAW,CAACC,WAAsBb,MAAiCZ,UAAUyB,WAAWb,KAAKc,UAAU,CAAC;AAE9G,+FAA+F,GAC/F,eAAeC,WACbF,SAAoB,EACpBb,GAA4B,EAC5BgB,QAAuC;IAEvC,MAAMF,aAAaF,SAASC,WAAWb;IACvC,MAAMiB,QAAQ,IAAIC;IAClB,MAAMC,UAAU,IAAIC;IACpB,MAAMC,MAAM,IAAID;IAChB,KAAK,MAAME,WAAWN,SAAU;QAC9B,KAAK,MAAMO,SAASD,QAAQE,MAAM,CAAE;YAClC,MAAMC,MAAMH,QAAQI,OAAO,KAAK,OAAO;gBAAEC,IAAIJ;YAAM,IAAI1C,sBAAsB0C;YAC7E,IAAI,CAACE,KAAK;YACV,IAAIA,IAAIG,MAAM,KAAKC,WAAWV,QAAQW,GAAG,CAACL,IAAIG,MAAM;YACpD,IAAIH,IAAIE,EAAE,IAAI,CAACF,IAAIE,EAAE,CAACI,QAAQ,CAAC,QAAQ,CAAC,WAAWC,IAAI,CAACP,IAAIE,EAAE,GAAGN,IAAIS,GAAG,CAACL,IAAIE,EAAE;QACjF;IACF;IACA,MAAMM,aAAa;WAAId;KAAQ;IAC/B,IAAK,IAAIe,KAAK,GAAGA,KAAKD,WAAWE,MAAM,EAAED,MAAMrC,OAAQ;QACrD,MAAMuC,WAAW,MAAMtB,WAAWuB,KAAK,CAAC,UAAU,MAAMJ,WAAWK,KAAK,CAACJ,IAAIA,KAAKrC,SAAS0C,GAAG;QAC9F,KAAK,MAAMC,OAAOJ,SAASK,IAAI,CAAExB,MAAMyB,GAAG,CAACF,IAAIb,EAAE,EAAEa;IACrD;IACA,MAAMG,SAAS;WAAItB;KAAI,CAACuB,MAAM,CAAC,CAACjB,KAAO,CAACV,MAAM4B,GAAG,CAAClB;IAClD,IAAK,IAAIO,KAAK,GAAGA,KAAKS,OAAOR,MAAM,EAAED,MAAM,IAAK;QAC9C,KAAK,MAAMM,OAAO,CAAA,MAAM3B,UAAUiC,MAAM,IAAIH,OAAOL,KAAK,CAACJ,IAAIA,KAAK,KAAKa,GAAG,CAAC,CAACpB,KAAOb,WAAW0B,GAAG,CAACb,KAAI,EAAG;YACvG,IAAIa,IAAIQ,MAAM,EAAE/B,MAAMyB,GAAG,CAACF,IAAIb,EAAE,EAAEa;QACpC;IACF;IACA,OAAOvB;AACT;AAEA,OAAO,eAAegC,qBACpBjD,GAA4B,EAC5BgB,QAAuC;IAEvC,MAAMC,QAAQ,MAAMF,WAAW5B,eAAea,KAAKgB;IACnD,MAAMkC,OAAuBlC,SAAS+B,GAAG,CAAC,CAACzB,UAAa,CAAA;YAAEI,SAASJ,QAAQI,OAAO;YAAEyB,YAAY7B,QAAQ6B,UAAU;QAAC,CAAA;IACnH,MAAMC,UAAU,IAAIlC;IACpB,MAAMmC,UAAkE,EAAE;IAC1E,KAAK,MAAMb,OAAOvB,MAAMO,MAAM,GAAI;YAClBgB;QAAd,MAAMc,QAAQd,YAAAA,IAAIc,IAAI,cAARd,YAAc,CAAC;QAC7BY,QAAQV,GAAG,CAACF,IAAIb,EAAE,EAAE/B,eAAe4C,IAAIb,EAAE,EAAE2B;QAC3CD,QAAQE,IAAI,CAAC;YAAE5B,IAAIa,IAAIb,EAAE;YAAEH,QAAQ7B,oBAAoB6C,IAAIb,EAAE,EAAE2B;QAAM;IACvE;IACA,OAAO;QAAEE,QAAQnF,iBAAiBgF,SAASH;QAAOE;IAAQ;AAC5D;AAEA;;;;CAIC,GACD,OAAO,eAAeK,iBACpBzD,GAA4B,EAC5B0D,MAAqB,EACrBC,QAA2B,EAC3BC,OAA6B;;IAE7B,IAAI,CAACvE,eAAeW,KAAK4D,UAAU,OAAO3E;IAC1C,IAAI2E,2BAAAA,QAAShB,MAAM,EAAE,MAAM,IAAIiB,MAAM;IACrC,MAAMhD,YAAY1B;IAClB,MAAM2B,aAAaF,SAASC,WAAWb;IACvC,MAAM8D,WAAWC,KAAKC,GAAG,CAAC,GAAGD,KAAKE,GAAG,CAAC,aAAKL,2BAAAA,QAASE,QAAQ,mBAAI;IAChE,IAAIrB;IACJ,IAAIyB;IACJ,IAAIN,2BAAAA,QAASvC,GAAG,EAAE;QAChB,MAAM8C,SAAST,SAASU,OAAOV,UAAU;QACzC,MAAMrC,MAAMuC,QAAQvC,GAAG,CAACiB,KAAK,CAAC6B,QAAQA,SAASL;QAC/CrB,OAAOpB,IAAIc,MAAM,GAAG,AAAC,CAAA,MAAMtB,UAAUiC,MAAM,IAAIzB,IAAI0B,GAAG,CAAC,CAACpB,KAAOb,WAAW0B,GAAG,CAACb,KAAI,EAAGiB,MAAM,CAAC,CAACJ,MAAQA,IAAIQ,MAAM,IAAI,EAAE;QACrHkB,OAAOC,SAAS9C,IAAIc,MAAM,GAAGyB,QAAQvC,GAAG,CAACc,MAAM,GAAGkC,OAAOF,SAAS9C,IAAIc,MAAM,IAAI;IAClF,OAAO;YAS8DmC;QARnE,MAAMC,QAAQzD,WACXuB,KAAK,CAAC,UAAU,MAAMvC,kBACtB0E,OAAO,CAAC,eAAe,QACvBA,OAAO,CAAChG,cAAcqC,SAAS,CAAC4D,SAAS,CAACC,UAAU,IAAI;QAC3D,MAAMC,QAAQjB,SAAUkB,KAAKC,KAAK,CAACnB,UAAwB;QAC3D,MAAMtB,WAAW,MAAM,AAACuC,CAAAA,QAAQJ,MAAMO,UAAU,IAAIH,SAASJ,KAAI,EAAGQ,KAAK,CAACjB,UAAUvB,GAAG;QACvFE,OAAOL,SAASK,IAAI;QACpB,MAAM6B,OAAOlC,SAASK,IAAI,CAACL,SAASK,IAAI,CAACN,MAAM,GAAG,EAAE;QACpD+B,OAAOI,QAAQlC,SAASK,IAAI,CAACN,MAAM,KAAK2B,WAAWc,KAAKI,SAAS,CAAC;aAACV,YAAAA,KAAK/B,GAAG,CAAC,0BAAT+B,YAA2B;YAAMA,KAAK3C,EAAE;SAAC,IAAI;IAClH;IACA,MAAMsD,OAAOxC,KAAKyC,OAAO,CAAC,CAAC1C;YACGA;eAA5B9C,mBAAmB8C,IAAIb,EAAE,GAAGa,YAAAA,IAAIc,IAAI,cAARd,YAAc,CAAC,GAA2BO,GAAG,CAAC,CAACoC,SACzEC,OAAOC,WAAW,CAAC1B,SAASZ,GAAG,CAAC,CAACrB;oBAAsByD;uBAAV;oBAACzD;qBAASyD,kBAAAA,MAAM,CAACzD,QAAQ,YAAfyD,kBAAmB;iBAAK;;;IAGnF,OAAO;QAAEF;QAAMf;IAAK;AACtB;AAEA,wDAAwD,GACxD,OAAO,eAAeoB,aAAatF,GAA4B,EAAEuF,KAA6B;IAC5F,MAAMxF,UAAUC;IAChB,MAAMa,YAAY1B;IAClB,MAAMkC,MAAM;WACP,IAAID,IACLmE,MAAMC,OAAO,CACVzC,GAAG,CAAC,CAAC0C,QAAWA,MAAMC,IAAI,KAAK,YAAYD,MAAME,QAAQ,GAAG,MAC5D/C,MAAM,CAAC,CAACjB,KAAqBiE,QAAQjE;KAE3C;IACD,MAAMb,aAAaF,SAASC,WAAWb;IACvC,MAAM6F,SAAS,IAAI3E;IACnB,IAAK,IAAIgB,KAAK,GAAGA,KAAKb,IAAIc,MAAM,EAAED,MAAM,IAAK;QAC3C,KAAK,MAAMM,OAAO,CAAA,MAAM3B,UAAUiC,MAAM,IAAIzB,IAAIiB,KAAK,CAACJ,IAAIA,KAAK,KAAKa,GAAG,CAAC,CAACpB,KAAOb,WAAW0B,GAAG,CAACb,KAAI,EAAG;gBAChEa;YAApC,IAAIA,IAAIQ,MAAM,EAAE6C,OAAOnD,GAAG,CAACF,IAAIb,EAAE,GAAGa,YAAAA,IAAIc,IAAI,cAARd,YAAc,CAAC;QACrD;IACF;IACA,OAAO/C,iBAAiB8F,OAAOM;AACjC;AAEA,8EAA8E,GAC9E,OAAO,eAAeC,cACpB9F,GAA4B,EAC5B+F,KAAwC,EACxCC,MAA2B;IAE3B,MAAM,EAAE/F,MAAM,EAAE,GAAG,MAAMF,UAAUC;IACnC,MAAMiG,UAA+B,EAAE;IACvC,MAAMC,OAA4B,EAAE;IACpC,MAAMC,OAAO,OAAOC,KAAaC;QAC/B,MAAMC,SAA4B;YAAEF;YAAKG,SAAS;YAAUC,QAAQ;YAAgBH;QAAQ;QAC5FJ,QAAQ1C,IAAI,CAAC+C;QACb,MAAMN,OAAOS,WAAW,CAACH;IAC3B;IACA,KAAK,MAAMF,OAAOL,MAAMd,IAAI,CAA0B;QACpD,MAAMyB,UAAU,MAAMV,OAAOW,cAAc,CAACP,IAAIQ,KAAK;QACrD,IAAIF,SAAS;YACXT,QAAQ1C,IAAI,CAACmD;YACb;QACF;QACA,IAAIV,OAAOa,UAAU,KAAK3H,eAAe;QACzC,MAAM4H,WAAWV,IAAIW,QAAQ;QAC7B,IAAIX,IAAIY,OAAO,KAAK,YAAY,CAACF,UAAU;YACzC,MAAMX,KAAKC,IAAIQ,KAAK,EAAE;YACtB;QACF;QACA,IAAIE,SAASG,MAAM,KAAK,QAAQ;YAC9B,MAAMV,UAAU,MAAMxH,oBAAoB;gBACxCkB;gBACAiH,SAASJ,SAASI,OAAO;gBACzBC,IAAI;gBACJC,SAASN,SAASM,OAAO;gBACzBC,gBAAgBP,SAASO,cAAc;eACnCP,SAASQ,WAAW,GAAG;gBAAEA,aAAaR,SAASQ,WAAW;YAAC,IAAI,CAAC,GAChER,SAASS,SAAS,GAAG;gBAAEA,WAAWT,SAASS,SAAS;YAAC,IAAI,CAAC;gBAC9DC,gBAAgB,CAAC,gBAAgB,EAAE5I,wBAAwBkI,SAASO,cAAc,GAAG;gBACrFI,gBAAgB;;YAElB,IAAIlB,QAAQA,OAAO,KAAK,cAAeA,QAAQA,OAAO,KAAK,aAAaA,QAAQmB,WAAW,EAAG;oBAkBlEA,6BACPA;gBAlBnB,MAAMA,cAAcnB,QAAQmB,WAAW;gBACvC,MAAMpB,SAA4B;oBAChCF,KAAKA,IAAIQ,KAAK;oBACdL,SAASA,QAAQA,OAAO,KAAK,aAAa,YAAY;oBACtDZ,UAAUmB,SAASI,OAAO;gBAC5B;gBACA,kEAAkE;gBAClE,6BAA6B;gBAC7B,MAAMS,QACJpB,QAAQA,OAAO,KAAK,cAAcmB,cAC9B;oBACEtB,KAAKA,IAAIQ,KAAK;oBACdjB,UAAUmB,SAASI,OAAO;oBAC1BD,QAAQ;oBACRW,UAAU;wBAAEC,eAAe;oBAAK;oBAChCC,SAAS;wBACPD,eAAeH,YAAY/F,EAAE;wBAC7B0F,cAAc,GAAEK,8BAAAA,YAAYL,cAAc,YAA1BK,8BAA8B;wBAC9CN,OAAO,GAAEM,uBAAAA,YAAYN,OAAO,YAAnBM,uBAAuB;oBAClC;gBACF,IACA7F;gBACNoE,QAAQ1C,IAAI,CAAC+C;gBACb,IAAIqB,OAAOzB,KAAK3C,IAAI,CAACoE;gBACrB,MAAM3B,OAAOS,WAAW,CAACH,QAAQqB;gBACjC;YACF;YACA,MAAMxB,KACJC,IAAIQ,KAAK,EACTL,QAAQA,OAAO,KAAK,YAChB,CAAC,aAAa,EAAEA,QAAQwB,IAAI,CAACC,OAAO,CAAC,MAAM,KAAK,uBAAuB,CAAC,GACxEzB,QAAQA,OAAO,KAAK,kBAClBA,QAAQF,OAAO,GACfE,QAAQA,OAAO,KAAK,kBAClB,gCACA;YAEV;QACF;QACA,MAAMA,UAAU,MAAMvH,0BAA0B;YAC9CiB;YACAiH,SAASJ,SAASI,OAAO;YACzBW,eAAef,SAASe,aAAa;YACrCT,SAASN,SAASM,OAAO;YACzBC,gBAAgBP,SAASO,cAAc;WACnCP,SAASQ,WAAW,GAAG;YAAEA,aAAaR,SAASQ,WAAW;QAAC,IAAI,CAAC;QAEtE,IAAIf,QAAQA,OAAO,KAAK,aAAaA,QAAQA,OAAO,KAAK,WAAW;gBAexCA,qCACPA;YAfnB,MAAMD,SAA4B;gBAChCF,KAAKA,IAAIQ,KAAK;gBACdL,SAASA,QAAQA,OAAO,KAAK,YAAY,YAAY;gBACrDZ,UAAUmB,SAASI,OAAO;YAC5B;YACA,MAAMS,QACJpB,QAAQA,OAAO,KAAK,YAChB;gBACEH,KAAKA,IAAIQ,KAAK;gBACdjB,UAAUmB,SAASI,OAAO;gBAC1BD,QAAQ;gBACRW,UAAU;oBAAEC,eAAef,SAASe,aAAa;mBAAKf,SAASc,QAAQ;gBACvEE,SAAS;oBACPD,eAAef,SAASe,aAAa;oBACrCR,cAAc,GAAEd,sCAAAA,QAAQmB,WAAW,CAACL,cAAc,YAAlCd,sCAAsC;oBACtDa,OAAO,GAAEb,+BAAAA,QAAQmB,WAAW,CAACN,OAAO,YAA3Bb,+BAA+B;gBAC1C;YACF,IACA1E;YACNoE,QAAQ1C,IAAI,CAAC+C;YACb,IAAIqB,OAAOzB,KAAK3C,IAAI,CAACoE;YACrB,MAAM3B,OAAOS,WAAW,CAACH,QAAQqB;YACjC;QACF;QACA,MAAMxB,KACJC,IAAIQ,KAAK,EACTL,QAAQA,OAAO,KAAK,WAChB,CAAC,aAAa,EAAEA,QAAQwB,IAAI,CAACC,OAAO,CAAC,MAAM,KAAK,qCAAqC,CAAC,GACtF;IAER;IACA,OAAO;QAAE/B;QAASC;IAAK;AACzB;AAEA;;;;;CAKC,GACD,OAAO,eAAe+B,eACpBjI,GAA4B,EAC5BoC,QAA8B,EAC9B8F,SAAmC;IAEnC,MAAM,EAAEjI,MAAM,EAAE,GAAG,MAAMF,UAAUC;IACnC,MAAMa,YAAY1B;IAClB,MAAM2B,aAAaF,SAASC,WAAWb;IACvC,MAAMmI,OAA2B,EAAE;IACnC,MAAMC,YAAgC,EAAE;IACxC,KAAK,MAAMT,SAAS;WAAIvF,SAASiB,OAAO;KAAC,CAACgF,OAAO,GAAI;YACtBV,8BAEAnF;YAmBZmF,iBAOKA,kBACOA,kBACnBA,kBAiBwBA;QA/ClC,MAAME,gBAAgBxD,QAAOsD,+BAAAA,MAAMG,OAAO,CAAC,gBAAgB,YAA9BH,+BAAkC;QAC/D,MAAMnF,MAAM,MAAM1B,WAAW0B,GAAG,CAACmF,MAAMhC,QAAQ,EAAEpD,GAAG;QACpD,MAAM+F,QAAQ9F,IAAIQ,MAAM,IAAKR,YAAAA,IAAIc,IAAI,cAARd,YAAc,CAAC,IAAiC;QAC7E,MAAM+F,UAAU,SAAED,yBAAAA,KAAO,CAAC,eAAe,mBAAmD,EAAE,EAAEE,IAAI,CAClG,CAACd,cAAgBA,WAAW,CAAC,KAAK,KAAKG;QAEzC,IAAI,CAACrF,IAAIQ,MAAM,IAAI,CAACuF,WAAWA,OAAO,CAAC,SAAS,KAAK,aAAa;YAChEJ,KAAK5E,IAAI,CAAC;gBAAE0D,QAAQ;gBAAWtB,UAAUgC,MAAMhC,QAAQ;gBAAE8C,KAAKjG,IAAIQ,MAAM,GAAG,oBAAoB;YAAO;YACtG;QACF;QACA,MAAM0F,SACJ9J,wBAAwB2J,OAAO,CAAC,iBAAiB,MAAM3J,wBAAwB+I,MAAMG,OAAO,CAAC,iBAAiB;QAChH,IAAIY,UAAUR,CAAAA,6BAAAA,SAAW,CAACP,MAAMhC,QAAQ,CAAC,MAAK,UAAU;gBAK1B4C;YAJ5BH,UAAU7E,IAAI,CAAC;gBACb0D,QAAQ;gBACRtB,UAAUgC,MAAMhC,QAAQ;gBACxBgD,QAAQ;oBAAC;iBAAiB;gBAC1BnH,QAAQ;oBAAE6F,cAAc,GAAEkB,0BAAAA,OAAO,CAAC,iBAAiB,YAAzBA,0BAA6B;gBAAK;YAC9D;YACA;QACF;QACA,MAAMK,WAAWjB,EAAAA,kBAAAA,MAAMC,QAAQ,qBAAdD,eAAgB,CAAC,gBAAgB,MAAK;QACvD,MAAMpB,UAAUqC,WACZ,MAAM9J,uBAAuB;YAAEmB;YAAQiH,SAASS,MAAMhC,QAAQ;YAAEkC;QAAc,KAC9E,MAAM7I,0BAA0B;YAC9BiB;YACAiH,SAASS,MAAMhC,QAAQ;YACvBkC;YACAT,SAAS/C,iBAAOsD,mBAAAA,MAAMC,QAAQ,qBAAdD,gBAAgB,CAAC,UAAU,oBAAI;YAC/CN,gBAAgBhD,iBAAOsD,mBAAAA,MAAMC,QAAQ,qBAAdD,gBAAgB,CAAC,iBAAiB,oBAAI;WACzDA,EAAAA,mBAAAA,MAAMC,QAAQ,qBAAdD,gBAAgB,CAAC,cAAc,IAAG;YAAEL,aAAajD,OAAOsD,MAAMC,QAAQ,CAAC,cAAc;QAAE,IAAI,CAAC;QAEtG,IAAIrB,QAAQA,OAAO,KAAK,UAAU;YAChC6B,UAAU7E,IAAI,CAAC;gBACb0D,QAAQ;gBACRtB,UAAUgC,MAAMhC,QAAQ;gBACxBgD,QAAQ;oBAAC;iBAAS;gBAClBnH,QAAQ;oBAAEqH,QAAQtC,QAAQwB,IAAI;gBAAC;YACjC;YACA;QACF;QACAI,KAAK5E,IAAI,CACPqF,WACI;YAAE3B,QAAQ;YAAUtB,UAAUgC,MAAMhC,QAAQ;QAAC,IAC7C;YACEsB,QAAQ;YACRtB,UAAUgC,MAAMhC,QAAQ;YACxBnE,QAAQ;gBAAE6F,cAAc,YAAEM,mBAAAA,MAAMC,QAAQ,qBAAdD,gBAAgB,CAAC,iBAAiB,oBAAI;YAAK;QACvE;IAER;IACA,OAAO;QAAEQ;QAAMC;IAAU;AAC3B;AAEA,OAAO,MAAMU,mBAA2C;IACtDC,WAAWxJ;IACXyJ,eAAe1J;IACf2J,UAAU,CAACjJ,KAAK0D,QAAQC,UAAUC,UAAYH,iBAAiBzD,KAAK0D,QAAQC,UAAUC;IACtFJ,QAAQ,CAACxD,KAAKgB,WAAaiC,qBAAqBjD,KAAKgB;IACrDyE,OAAO,CAACyD,MAAM3D,QAAW,CAAA;YAAE4D,UAAU3J,kBAAkB+F,MAAMN,IAAI,EAAEM,MAAM/B,MAAM;QAAE,CAAA;IACjF4F,MAAM,CAACpJ,KAAKuF,QAAUD,aAAatF,KAAKuF;IACxC8D,OAAO,CAACrJ,KAAK+F,OAAOC,SAAWF,cAAc9F,KAAK+F,OAAOC;IACzDsD,QAAQ,CAACtJ,KAAKoC,UAAU8F,YAAcD,eAAejI,KAAKoC,UAAU8F;AACtE,EAAC"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/transfer/tracking.server.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n buildMatchLookup,\n type BuildTransferPlanInput,\n type MatchKeySpec,\n type MatchLookupRequest,\n type PlannedTransferRow,\n type TransferChunk,\n type TransferPlan,\n type TransferRowResult,\n type TransferUndoEntry,\n type TransferUndoSnapshot,\n type TransferUndoStep,\n} from '@aglyn/aglyn/data-transfer'\nimport * as Aglyn from '@aglyn/aglyn/server'\nimport type {\n PluginTransferResource,\n TransferApplyResult,\n TransferApplyWriter,\n TransferLookupResult,\n TransferReadOptions,\n TransferReadPage,\n TransferResourceContext,\n TransferRevertDecisions,\n TransferRevertResult,\n} from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources'\nimport { firebaseAdmin, getOrgForHost, memberHasPermissionOnHost, resolveOrgMembership } from '@aglyn/tenant-data-admin'\nimport { TransferEngineError } from '@aglyn/tenant-data-admin/server/transfer-jobs'\nimport { normalizeTrackingNumber, parseShippingOrderRef } from '../model/order-shipping-export'\nimport { commerceSitePermissionRefusal } from '../model/plugin-permissions'\nimport {\n cancelOrderFulfillment,\n recordOrderShipment,\n updateFulfillmentTracking,\n} from '../server/fulfill-order'\nimport { NOTHING, ROW_BUDGET_MS, firestoreOf, hostRefOf, readerSeesHost, type Firestore } from './server-common'\nimport {\n TRACKING_DEFAULT_POLICY,\n TRACKING_MATCH_KEYS,\n matchTrackingRows,\n planTrackingRows,\n trackingExportRows,\n trackingMatchValues,\n trackingRecord,\n type StoredTrackingOrder,\n type TrackingPlannedRow,\n} from './tracking-transfer'\n\n/*\n * THE TRACKING IMPORT'S SERVER HALF (AGL-3613). The plan is\n * `planTrackingRows`; this module reads the orders it plans against, writes\n * each parcel through the order's own shipment paths and undoes them.\n *\n * - WHO: the site's admins and editors — the roles the console's Fulfill\n * button has — on a plan that sells. Asked by the plan, the apply and the\n * undo, each server-side.\n * - HOW: a new parcel through `recordOrderShipment`, keyed by its tracking\n * number, so a retried chunk or a second import of the same file is one\n * parcel; the buyer is emailed as for any shipment. A replaced tracking\n * number through `updateFulfillmentTracking`.\n * - UNDO: a parcel this import recorded is cancelled (its units go back to\n * unfulfilled), and a replaced tracking number is put back — each only\n * while the shipment still holds what the import wrote; otherwise it is a\n * conflict the person decides.\n */\n\nconst IN_MAX = 30\n\n/** Orders a page of the shipments export reads: those that have shipped something. */\nconst SHIPPED_STATUSES = ['partially_fulfilled', 'fulfilled', 'delivered']\n\n/** The member importing, checked for the role and the plan, or the refusal. */\nasync function shipperOf(ctx: TransferResourceContext): Promise<{ hostId: string }> {\n const hostId = ctx.hostId\n if (!hostId) throw new TransferEngineError('invalid', 400, 'Tracking numbers belong to a site; name the site.')\n const uid = ctx.actorUid\n const membership = uid ? await resolveOrgMembership(uid, ctx.orgId) : null\n // \"Manage orders\" (`commerce.orders`, AGL-4047) on this site, resolved fresh\n // from the membership: its preset is the site's Admin and Editor this\n // asked for, then the member's custom role, own permissions and site toggle.\n const allowed =\n !!uid && !!membership?.member &&\n (await memberHasPermissionOnHost(ctx.orgId, hostId, membership.member, 'commerce.orders'))\n if (!allowed) {\n throw new TransferEngineError('forbidden', 403, commerceSitePermissionRefusal('commerce.orders'))\n }\n const owner = await getOrgForHost(hostId).catch(() => null)\n if (!Aglyn.checkEntitlement(owner?.org as never, 'commerce')) {\n throw new TransferEngineError('forbidden', 403, 'This site’s plan does not include selling.')\n }\n return { hostId }\n}\n\nconst ordersOf = (firestore: Firestore, ctx: TransferResourceContext) => hostRefOf(firestore, ctx).collection('orders')\n\n/** Orders by the values a file names them by: numbers through one query per 30, ids directly. */\nasync function findOrders(\n firestore: Firestore,\n ctx: TransferResourceContext,\n requests: readonly MatchLookupRequest[],\n): Promise<Map<string, FirebaseFirestore.DocumentSnapshot>> {\n const collection = ordersOf(firestore, ctx)\n const found = new Map<string, FirebaseFirestore.DocumentSnapshot>()\n const numbers = new Set<number>()\n const ids = new Set<string>()\n for (const request of requests) {\n for (const value of request.values) {\n const ref = request.fieldId === 'id' ? { id: value } : parseShippingOrderRef(value)\n if (!ref) continue\n if (ref.number !== undefined) numbers.add(ref.number)\n if (ref.id && !ref.id.includes('/') && !/^__.*__$/.test(ref.id)) ids.add(ref.id)\n }\n }\n const numberList = [...numbers]\n for (let at = 0; at < numberList.length; at += IN_MAX) {\n const snapshot = await collection.where('number', 'in', numberList.slice(at, at + IN_MAX)).get()\n for (const doc of snapshot.docs) found.set(doc.id, doc)\n }\n const idList = [...ids].filter((id) => !found.has(id))\n for (let at = 0; at < idList.length; at += 100) {\n for (const doc of await firestore.getAll(...idList.slice(at, at + 100).map((id) => collection.doc(id)))) {\n if (doc.exists) found.set(doc.id, doc)\n }\n }\n return found\n}\n\nexport async function lookupTrackingOrders(\n ctx: TransferResourceContext,\n requests: readonly MatchLookupRequest[],\n): Promise<TransferLookupResult> {\n const found = await findOrders(firestoreOf(), ctx, requests)\n const keys: MatchKeySpec[] = requests.map((request) => ({ fieldId: request.fieldId, normalizer: request.normalizer }))\n const records = new Map<string, Readonly<Record<string, unknown>>>()\n const entries: Array<{ id: string; values: Record<string, unknown> }> = []\n for (const doc of found.values()) {\n const data = (doc.data() ?? {}) as StoredTrackingOrder\n records.set(doc.id, trackingRecord(doc.id, data))\n entries.push({ id: doc.id, values: trackingMatchValues(doc.id, data) })\n }\n return { lookup: buildMatchLookup(entries, keys), records }\n}\n\n/**\n * The shipments export: every order that has shipped something, newest\n * first, one row per shipment with a tracking number. The cursor is the last\n * order's `createdAtMs` and id, as the orders export pages.\n */\nexport async function readTrackingPage(\n ctx: TransferResourceContext,\n cursor: string | null,\n fieldIds: readonly string[],\n options?: TransferReadOptions,\n): Promise<TransferReadPage> {\n if (!readerSeesHost(ctx, options)) return NOTHING\n if (options?.filter) throw new Error('Shipments export every shipment, or those of the orders you select.')\n const firestore = firestoreOf()\n const collection = ordersOf(firestore, ctx)\n const pageSize = Math.max(1, Math.min(500, options?.pageSize ?? 200))\n let docs: FirebaseFirestore.DocumentSnapshot[]\n let next: string | null\n if (options?.ids) {\n const offset = cursor ? Number(cursor) : 0\n const ids = options.ids.slice(offset, offset + pageSize)\n docs = ids.length ? (await firestore.getAll(...ids.map((id) => collection.doc(id)))).filter((doc) => doc.exists) : []\n next = offset + ids.length < options.ids.length ? String(offset + ids.length) : null\n } else {\n const query = collection\n .where('status', 'in', SHIPPED_STATUSES)\n .orderBy('createdAtMs', 'desc')\n .orderBy(firebaseAdmin.firestore.FieldPath.documentId(), 'desc')\n const after = cursor ? (JSON.parse(cursor) as unknown[]) : null\n const snapshot = await (after ? query.startAfter(...after) : query).limit(pageSize).get()\n docs = snapshot.docs\n const last = snapshot.docs[snapshot.docs.length - 1]\n next = last && snapshot.docs.length === pageSize ? JSON.stringify([last.get('createdAtMs') ?? null, last.id]) : null\n }\n const rows = docs.flatMap((doc) =>\n trackingExportRows(doc.id, (doc.data() ?? {}) as StoredTrackingOrder).map((record) =>\n Object.fromEntries(fieldIds.map((fieldId) => [fieldId, record[fieldId] ?? null])),\n ),\n )\n return { rows, next }\n}\n\n/** The dry run, against every matched order read once. */\nexport async function planTracking(ctx: TransferResourceContext, input: BuildTransferPlanInput): Promise<TransferPlan> {\n await shipperOf(ctx)\n const firestore = firestoreOf()\n const ids = [\n ...new Set(\n input.matches\n .map((match) => (match.kind === 'matched' ? match.recordId : null))\n .filter((id): id is string => Boolean(id)),\n ),\n ]\n const collection = ordersOf(firestore, ctx)\n const orders = new Map<string, StoredTrackingOrder>()\n for (let at = 0; at < ids.length; at += 100) {\n for (const doc of await firestore.getAll(...ids.slice(at, at + 100).map((id) => collection.doc(id)))) {\n if (doc.exists) orders.set(doc.id, (doc.data() ?? {}) as StoredTrackingOrder)\n }\n }\n return planTrackingRows(input, orders)\n}\n\n/** Records one chunk's parcels, each through the order's own shipment paths. */\nexport async function applyTracking(\n ctx: TransferResourceContext,\n chunk: TransferChunk<PlannedTransferRow>,\n writer: TransferApplyWriter,\n): Promise<TransferApplyResult> {\n const { hostId } = await shipperOf(ctx)\n const results: TransferRowResult[] = []\n const undo: TransferUndoEntry[] = []\n const fail = async (row: number, message: string) => {\n const result: TransferRowResult = { row, outcome: 'failed', reason: 'refusedValue', message }\n results.push(result)\n await writer.markApplied(result)\n }\n for (const row of chunk.rows as TrackingPlannedRow[]) {\n const earlier = await writer.alreadyApplied(row.index)\n if (earlier) {\n results.push(earlier)\n continue\n }\n if (writer.timeLeftMs() < ROW_BUDGET_MS) break\n const decision = row.tracking\n if (row.verdict !== 'update' || !decision) {\n await fail(row.index, 'A tracking file only records parcels for orders it names.')\n continue\n }\n if (decision.action === 'ship') {\n const outcome = await recordOrderShipment({\n hostId,\n orderId: decision.orderId,\n to: 'fulfilled',\n carrier: decision.carrier,\n trackingNumber: decision.trackingNumber,\n ...(decision.trackingUrl ? { trackingUrl: decision.trackingUrl } : {}),\n ...(decision.lineItems ? { lineItems: decision.lineItems } : {}),\n idempotencyKey: `tracking-import:${normalizeTrackingNumber(decision.trackingNumber)}`,\n onceByTracking: true,\n })\n if (outcome.outcome === 'recorded' || (outcome.outcome === 'already' && outcome.fulfillment)) {\n const fulfillment = outcome.fulfillment\n const result: TransferRowResult = {\n row: row.index,\n outcome: outcome.outcome === 'recorded' ? 'updated' : 'unchanged',\n recordId: decision.orderId,\n }\n // Only a parcel THIS import recorded is undone; one found already\n // there was somebody else's.\n const entry: TransferUndoEntry | undefined =\n outcome.outcome === 'recorded' && fulfillment\n ? {\n row: row.index,\n recordId: decision.orderId,\n action: 'updated',\n previous: { fulfillmentId: null },\n written: {\n fulfillmentId: fulfillment.id,\n trackingNumber: fulfillment.trackingNumber ?? null,\n carrier: fulfillment.carrier ?? null,\n },\n }\n : undefined\n results.push(result)\n if (entry) undo.push(entry)\n await writer.markApplied(result, entry)\n continue\n }\n await fail(\n row.index,\n outcome.outcome === 'blocked'\n ? `The order is ${outcome.from.replace(/_/g, ' ')} and cannot be shipped.`\n : outcome.outcome === 'invalid_lines'\n ? outcome.message\n : outcome.outcome === 'no_such_order'\n ? 'The order no longer exists.'\n : 'The order has nothing left to ship.',\n )\n continue\n }\n const outcome = await updateFulfillmentTracking({\n hostId,\n orderId: decision.orderId,\n fulfillmentId: decision.fulfillmentId,\n carrier: decision.carrier,\n trackingNumber: decision.trackingNumber,\n ...(decision.trackingUrl ? { trackingUrl: decision.trackingUrl } : {}),\n })\n if (outcome.outcome === 'updated' || outcome.outcome === 'already') {\n const result: TransferRowResult = {\n row: row.index,\n outcome: outcome.outcome === 'updated' ? 'updated' : 'unchanged',\n recordId: decision.orderId,\n }\n const entry: TransferUndoEntry | undefined =\n outcome.outcome === 'updated'\n ? {\n row: row.index,\n recordId: decision.orderId,\n action: 'updated',\n previous: { fulfillmentId: decision.fulfillmentId, ...decision.previous },\n written: {\n fulfillmentId: decision.fulfillmentId,\n trackingNumber: outcome.fulfillment.trackingNumber ?? null,\n carrier: outcome.fulfillment.carrier ?? null,\n },\n }\n : undefined\n results.push(result)\n if (entry) undo.push(entry)\n await writer.markApplied(result, entry)\n continue\n }\n await fail(\n row.index,\n outcome.outcome === 'locked'\n ? `The order is ${outcome.from.replace(/_/g, ' ')}; its shipments can no longer change.`\n : 'The shipment no longer exists.',\n )\n }\n return { results, undo }\n}\n\n/**\n * Undoes one chunk, newest first: a parcel the import recorded is cancelled\n * and a tracking number it replaced is put back — while the shipment still\n * holds what the import wrote. A shipment edited since is a conflict, done\n * only when the person's decision says `revert`.\n */\nexport async function revertTracking(\n ctx: TransferResourceContext,\n snapshot: TransferUndoSnapshot,\n decisions?: TransferRevertDecisions,\n): Promise<TransferRevertResult> {\n const { hostId } = await shipperOf(ctx)\n const firestore = firestoreOf()\n const collection = ordersOf(firestore, ctx)\n const done: TransferUndoStep[] = []\n const conflicts: TransferUndoStep[] = []\n for (const entry of [...snapshot.entries].reverse()) {\n const fulfillmentId = String(entry.written['fulfillmentId'] ?? '')\n const doc = await collection.doc(entry.recordId).get()\n const order = doc.exists ? ((doc.data() ?? {}) as Record<string, unknown>) : null\n const current = ((order?.['fulfillments'] as Array<Record<string, unknown>> | undefined) ?? []).find(\n (fulfillment) => fulfillment['id'] === fulfillmentId,\n )\n if (!doc.exists || !current || current['status'] === 'cancelled') {\n done.push({ action: 'nothing', recordId: entry.recordId, why: doc.exists ? 'alreadyReverted' : 'gone' })\n continue\n }\n const edited =\n normalizeTrackingNumber(current['trackingNumber']) !== normalizeTrackingNumber(entry.written['trackingNumber'])\n if (edited && decisions?.[entry.recordId] !== 'revert') {\n conflicts.push({\n action: 'conflict',\n recordId: entry.recordId,\n fields: ['trackingNumber'],\n values: { trackingNumber: current['trackingNumber'] ?? null },\n })\n continue\n }\n const recorded = entry.previous?.['fulfillmentId'] === null\n const outcome = recorded\n ? await cancelOrderFulfillment({ hostId, orderId: entry.recordId, fulfillmentId })\n : await updateFulfillmentTracking({\n hostId,\n orderId: entry.recordId,\n fulfillmentId,\n carrier: String(entry.previous?.['carrier'] ?? ''),\n trackingNumber: String(entry.previous?.['trackingNumber'] ?? ''),\n ...(entry.previous?.['trackingUrl'] ? { trackingUrl: String(entry.previous['trackingUrl']) } : {}),\n })\n if (outcome.outcome === 'locked') {\n conflicts.push({\n action: 'conflict',\n recordId: entry.recordId,\n fields: ['status'],\n values: { status: outcome.from },\n })\n continue\n }\n done.push(\n recorded\n ? { action: 'delete', recordId: entry.recordId }\n : {\n action: 'restore',\n recordId: entry.recordId,\n values: { trackingNumber: entry.previous?.['trackingNumber'] ?? null },\n },\n )\n }\n return { done, conflicts }\n}\n\nexport const trackingTransfer: PluginTransferResource = {\n matchKeys: TRACKING_MATCH_KEYS,\n defaultPolicy: TRACKING_DEFAULT_POLICY,\n readPage: (ctx, cursor, fieldIds, options) => readTrackingPage(ctx, cursor, fieldIds, options),\n lookup: (ctx, requests) => lookupTrackingOrders(ctx, requests),\n match: (_ctx, input) => ({ outcomes: matchTrackingRows(input.rows, input.lookup) }),\n plan: (ctx, input) => planTracking(ctx, input),\n apply: (ctx, chunk, writer) => applyTracking(ctx, chunk, writer),\n revert: (ctx, snapshot, decisions) => revertTracking(ctx, snapshot, decisions),\n}\n"],"names":["buildMatchLookup","Aglyn","firebaseAdmin","getOrgForHost","memberHasPermissionOnHost","resolveOrgMembership","TransferEngineError","normalizeTrackingNumber","parseShippingOrderRef","commerceSitePermissionRefusal","cancelOrderFulfillment","recordOrderShipment","updateFulfillmentTracking","NOTHING","ROW_BUDGET_MS","firestoreOf","hostRefOf","readerSeesHost","TRACKING_DEFAULT_POLICY","TRACKING_MATCH_KEYS","matchTrackingRows","planTrackingRows","trackingExportRows","trackingMatchValues","trackingRecord","IN_MAX","SHIPPED_STATUSES","shipperOf","ctx","hostId","uid","actorUid","membership","orgId","allowed","member","owner","catch","checkEntitlement","org","ordersOf","firestore","collection","findOrders","requests","found","Map","numbers","Set","ids","request","value","values","ref","fieldId","id","number","undefined","add","includes","test","numberList","at","length","snapshot","where","slice","get","doc","docs","set","idList","filter","has","getAll","map","exists","lookupTrackingOrders","keys","normalizer","records","entries","data","push","lookup","readTrackingPage","cursor","fieldIds","options","Error","pageSize","Math","max","min","next","offset","Number","String","last","query","orderBy","FieldPath","documentId","after","JSON","parse","startAfter","limit","stringify","rows","flatMap","record","Object","fromEntries","planTracking","input","matches","match","kind","recordId","Boolean","orders","applyTracking","chunk","writer","results","undo","fail","row","message","result","outcome","reason","markApplied","earlier","alreadyApplied","index","timeLeftMs","decision","tracking","verdict","action","orderId","to","carrier","trackingNumber","trackingUrl","lineItems","idempotencyKey","onceByTracking","fulfillment","entry","previous","fulfillmentId","written","from","replace","revertTracking","decisions","done","conflicts","reverse","order","current","find","why","edited","fields","recorded","status","trackingTransfer","matchKeys","defaultPolicy","readPage","_ctx","outcomes","plan","apply","revert"],"mappings":"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"}
|
|
@@ -22,6 +22,8 @@ export interface AddToCartRequest {
|
|
|
22
22
|
productId: string;
|
|
23
23
|
variantId: string;
|
|
24
24
|
quantity: number;
|
|
25
|
+
/** The day the shopper chose to use a check-in item (AGL-4043), `YYYY-MM-DD`. */
|
|
26
|
+
useDayKey?: string;
|
|
25
27
|
/** The GA4 line: product id (never the variant's), name, price, quantity. */
|
|
26
28
|
item: AnalyticsItem;
|
|
27
29
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
1
2
|
/**
|
|
2
3
|
* @license
|
|
3
4
|
* Copyright 2026 Aglyn LLC
|
|
@@ -23,19 +24,21 @@ import { CART_UPDATED_EVENT } from "../constants/cart-events.js";
|
|
|
23
24
|
* (AGL-1591) and refresh every cart badge on the page. Resolves whether the
|
|
24
25
|
* server took the line; the server prices it, never the caller.
|
|
25
26
|
*/ export async function addToCart(request) {
|
|
26
|
-
const { hostId, siteFetch, productId, variantId, quantity, item } = request;
|
|
27
|
+
const { hostId, siteFetch, productId, variantId, quantity, useDayKey, item } = request;
|
|
27
28
|
const response = await siteFetch('/api/commerce/cart', {
|
|
28
29
|
method: 'POST',
|
|
29
30
|
headers: {
|
|
30
31
|
'Content-Type': 'application/json'
|
|
31
32
|
},
|
|
32
|
-
body: JSON.stringify({
|
|
33
|
+
body: JSON.stringify(_extends({
|
|
33
34
|
hostId,
|
|
34
35
|
action: 'add',
|
|
35
36
|
productId,
|
|
36
37
|
variantId,
|
|
37
38
|
quantity
|
|
38
|
-
}
|
|
39
|
+
}, useDayKey ? {
|
|
40
|
+
useDayKey
|
|
41
|
+
} : {}))
|
|
39
42
|
}).catch(()=>null);
|
|
40
43
|
if (!(response == null ? void 0 : response.ok)) return false;
|
|
41
44
|
recordSiteJourneyStep('cart', productId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/utils/add-to-cart.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n buildAddToCartParams,\n trackEvent,\n type AnalyticsItem,\n} from '@aglyn/aglyn/app-utils/analytics-events'\nimport { recordSiteJourneyStep } from '@aglyn/aglyn/app-utils/site-journey'\nimport { CART_UPDATED_EVENT } from '../constants/cart-events'\n\nexport interface AddToCartRequest {\n hostId: string\n /** The site's fetch (`Aglyn.useSiteFetch()`), which carries the cart cookie. */\n siteFetch: typeof fetch\n productId: string\n variantId: string\n quantity: number\n /** The GA4 line: product id (never the variant's), name, price, quantity. */\n item: AnalyticsItem\n}\n\n/**\n * Put one line in the shopper's cart. The product page's Add to cart and the\n * product grid's quick add both go through this one path, so both record the\n * same funnel step (AGL-3605), report the same priced `add_to_cart`\n * (AGL-1591) and refresh every cart badge on the page. Resolves whether the\n * server took the line; the server prices it, never the caller.\n */\nexport async function addToCart(request: AddToCartRequest): Promise<boolean> {\n const { hostId, siteFetch, productId, variantId, quantity, item } = request\n const response = await siteFetch('/api/commerce/cart', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ hostId, action: 'add', productId, variantId, quantity }),\n }).catch(() => null)\n if (!response?.ok) return false\n recordSiteJourneyStep('cart', productId)\n // `value` describes what was JUST ADDED, not the cart's new total — see\n // `buildAddToCartParams`.\n trackEvent('add_to_cart', buildAddToCartParams({ items: [item] }))\n window.dispatchEvent(new Event(CART_UPDATED_EVENT))\n return true\n}\n"],"names":["buildAddToCartParams","trackEvent","recordSiteJourneyStep","CART_UPDATED_EVENT","addToCart","request","hostId","siteFetch","productId","variantId","quantity","item","response","method","headers","body","JSON","stringify","action","catch","ok","items","window","dispatchEvent","Event"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,oBAAoB,EACpBC,UAAU,QAEL,0CAAyC;AAChD,SAASC,qBAAqB,QAAQ,sCAAqC;AAC3E,SAASC,kBAAkB,QAAQ,8BAA0B;
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/utils/add-to-cart.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n buildAddToCartParams,\n trackEvent,\n type AnalyticsItem,\n} from '@aglyn/aglyn/app-utils/analytics-events'\nimport { recordSiteJourneyStep } from '@aglyn/aglyn/app-utils/site-journey'\nimport { CART_UPDATED_EVENT } from '../constants/cart-events'\n\nexport interface AddToCartRequest {\n hostId: string\n /** The site's fetch (`Aglyn.useSiteFetch()`), which carries the cart cookie. */\n siteFetch: typeof fetch\n productId: string\n variantId: string\n quantity: number\n /** The day the shopper chose to use a check-in item (AGL-4043), `YYYY-MM-DD`. */\n useDayKey?: string\n /** The GA4 line: product id (never the variant's), name, price, quantity. */\n item: AnalyticsItem\n}\n\n/**\n * Put one line in the shopper's cart. The product page's Add to cart and the\n * product grid's quick add both go through this one path, so both record the\n * same funnel step (AGL-3605), report the same priced `add_to_cart`\n * (AGL-1591) and refresh every cart badge on the page. Resolves whether the\n * server took the line; the server prices it, never the caller.\n */\nexport async function addToCart(request: AddToCartRequest): Promise<boolean> {\n const { hostId, siteFetch, productId, variantId, quantity, useDayKey, item } = request\n const response = await siteFetch('/api/commerce/cart', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ hostId, action: 'add', productId, variantId, quantity, ...(useDayKey ? { useDayKey } : {}) }),\n }).catch(() => null)\n if (!response?.ok) return false\n recordSiteJourneyStep('cart', productId)\n // `value` describes what was JUST ADDED, not the cart's new total — see\n // `buildAddToCartParams`.\n trackEvent('add_to_cart', buildAddToCartParams({ items: [item] }))\n window.dispatchEvent(new Event(CART_UPDATED_EVENT))\n return true\n}\n"],"names":["buildAddToCartParams","trackEvent","recordSiteJourneyStep","CART_UPDATED_EVENT","addToCart","request","hostId","siteFetch","productId","variantId","quantity","useDayKey","item","response","method","headers","body","JSON","stringify","action","catch","ok","items","window","dispatchEvent","Event"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,oBAAoB,EACpBC,UAAU,QAEL,0CAAyC;AAChD,SAASC,qBAAqB,QAAQ,sCAAqC;AAC3E,SAASC,kBAAkB,QAAQ,8BAA0B;AAe7D;;;;;;CAMC,GACD,OAAO,eAAeC,UAAUC,OAAyB;IACvD,MAAM,EAAEC,MAAM,EAAEC,SAAS,EAAEC,SAAS,EAAEC,SAAS,EAAEC,QAAQ,EAAEC,SAAS,EAAEC,IAAI,EAAE,GAAGP;IAC/E,MAAMQ,WAAW,MAAMN,UAAU,sBAAsB;QACrDO,QAAQ;QACRC,SAAS;YAAE,gBAAgB;QAAmB;QAC9CC,MAAMC,KAAKC,SAAS,CAAC;YAAEZ;YAAQa,QAAQ;YAAOX;YAAWC;YAAWC;WAAcC,YAAY;YAAEA;QAAU,IAAI,CAAC;IACjH,GAAGS,KAAK,CAAC,IAAM;IACf,IAAI,EAACP,4BAAAA,SAAUQ,EAAE,GAAE,OAAO;IAC1BnB,sBAAsB,QAAQM;IAC9B,wEAAwE;IACxE,0BAA0B;IAC1BP,WAAW,eAAeD,qBAAqB;QAAEsB,OAAO;YAACV;SAAK;IAAC;IAC/DW,OAAOC,aAAa,CAAC,IAAIC,MAAMtB;IAC/B,OAAO;AACT"}
|