@mohasinac/appkit 4.13.1 → 4.15.0
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/dist/_internal/client/features/layout/DashboardLayoutClient.js +14 -5
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +3 -0
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +6 -0
- package/dist/_internal/client/features/lottery/LotteryDetailView.d.ts +8 -0
- package/dist/_internal/client/features/lottery/LotteryDetailView.js +4 -1
- package/dist/_internal/client/features/lottery/LotteryListView.d.ts +7 -0
- package/dist/_internal/client/features/lottery/LotteryListView.js +1 -1
- package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.js +4 -1
- package/dist/_internal/client/features/lottery/slot-collage-items.d.ts +15 -0
- package/dist/_internal/client/features/lottery/slot-collage-items.js +13 -0
- package/dist/_internal/server/features/auctions/actions.js +8 -2
- package/dist/_internal/server/features/bundles/data.d.ts +16 -0
- package/dist/_internal/server/features/bundles/data.js +26 -0
- package/dist/_internal/server/features/bundles/index.d.ts +1 -1
- package/dist/_internal/server/features/bundles/index.js +1 -1
- package/dist/_internal/server/features/cart/service.d.ts +3 -3
- package/dist/_internal/server/features/checkout/actions.js +25 -0
- package/dist/_internal/server/features/checkout/locked-lines.d.ts +38 -0
- package/dist/_internal/server/features/checkout/locked-lines.js +171 -0
- package/dist/_internal/server/features/checkout/source-context.d.ts +5 -0
- package/dist/_internal/server/features/checkout/source-context.js +157 -0
- package/dist/_internal/server/features/homepage/index.d.ts +0 -1
- package/dist/_internal/server/features/homepage/index.js +7 -1
- package/dist/_internal/server/features/lottery/adapters.js +4 -0
- package/dist/_internal/server/features/offers/adapters.d.ts +103 -0
- package/dist/_internal/server/features/offers/adapters.js +88 -0
- package/dist/_internal/server/features/offers/index.d.ts +2 -0
- package/dist/_internal/server/features/offers/index.js +1 -0
- package/dist/_internal/server/features/orders/adapters.js +24 -0
- package/dist/_internal/server/features/products/data.js +15 -37
- package/dist/_internal/server/features/products/index.d.ts +1 -1
- package/dist/_internal/server/features/products/index.js +1 -1
- package/dist/_internal/server/features/products/list-public.d.ts +46 -20
- package/dist/_internal/server/features/products/list-public.js +266 -90
- package/dist/_internal/server/features/products/listing-tab-counts.d.ts +44 -0
- package/dist/_internal/server/features/products/listing-tab-counts.js +97 -0
- package/dist/_internal/server/features/site-settings/adapters.d.ts +51 -0
- package/dist/_internal/server/features/site-settings/adapters.js +75 -0
- package/dist/_internal/server/features/site-settings/index.d.ts +1 -0
- package/dist/_internal/server/features/site-settings/index.js +1 -0
- package/dist/_internal/server/features/stores/adapters.d.ts +56 -0
- package/dist/_internal/server/features/stores/adapters.js +91 -0
- package/dist/_internal/server/features/stores/index.d.ts +1 -0
- package/dist/_internal/server/features/stores/index.js +1 -0
- package/dist/_internal/server/jobs/core/auctionSettlement.js +56 -2
- package/dist/_internal/server/jobs/core/offerExpiry.js +55 -19
- package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.d.ts +5 -0
- package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.js +33 -1
- package/dist/_internal/server/jobs/handlers/messages.d.ts +7 -0
- package/dist/_internal/server/jobs/handlers/messages.js +10 -0
- package/dist/_internal/shared/actions/action-registry.js +17 -1
- package/dist/_internal/shared/checkout/lanes.d.ts +25 -0
- package/dist/_internal/shared/checkout/lanes.js +26 -0
- package/dist/_internal/shared/features/auctions/config.d.ts +27 -0
- package/dist/_internal/shared/features/auctions/config.js +27 -0
- package/dist/_internal/shared/features/auctions/schema.d.ts +14 -2
- package/dist/_internal/shared/features/auctions/schema.js +13 -1
- package/dist/_internal/shared/features/blog/schema.d.ts +2 -2
- package/dist/_internal/shared/features/cart/schema.d.ts +20 -15
- package/dist/_internal/shared/features/cart/schema.js +15 -0
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +32 -32
- package/dist/_internal/shared/features/emi/schedule.d.ts +24 -3
- package/dist/_internal/shared/features/emi/schedule.js +20 -5
- package/dist/_internal/shared/features/events/schema.d.ts +2 -2
- package/dist/_internal/shared/features/homepage/section-gate.d.ts +14 -0
- package/dist/_internal/shared/features/homepage/section-gate.js +51 -0
- package/dist/_internal/shared/features/offers/config.d.ts +30 -0
- package/dist/_internal/shared/features/offers/config.js +59 -0
- package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
- package/dist/_internal/shared/features/products/schema.d.ts +30 -30
- package/dist/_internal/shared/features/products/to-product-item.js +6 -0
- package/dist/_internal/shared/features/reviews/schema.d.ts +2 -2
- package/dist/_internal/shared/features/site-settings/fees.d.ts +60 -0
- package/dist/_internal/shared/features/site-settings/fees.js +39 -0
- package/dist/_internal/shared/features/site-settings/types.d.ts +40 -0
- package/dist/_internal/shared/features/site-settings/types.js +1 -0
- package/dist/_internal/shared/history/history.d.ts +88 -0
- package/dist/_internal/shared/history/history.js +198 -0
- package/dist/_internal/shared/history/index.d.ts +4 -0
- package/dist/_internal/shared/history/index.js +2 -0
- package/dist/_internal/shared/history/types.d.ts +61 -0
- package/dist/_internal/shared/history/types.js +6 -0
- package/dist/_internal/shared/listing-types/_registry.d.ts +54 -1
- package/dist/_internal/shared/listing-types/_registry.js +67 -0
- package/dist/_internal/shared/listing-types/art/config.d.ts +3 -0
- package/dist/_internal/shared/listing-types/art/config.js +5 -0
- package/dist/_internal/shared/listing-types/auction/config.d.ts +13 -0
- package/dist/_internal/shared/listing-types/auction/config.js +21 -0
- package/dist/_internal/shared/listing-types/availability.d.ts +79 -0
- package/dist/_internal/shared/listing-types/availability.js +104 -0
- package/dist/_internal/shared/listing-types/capabilities.d.ts +15 -0
- package/dist/_internal/shared/listing-types/capabilities.js +12 -0
- package/dist/_internal/shared/listing-types/classified/config.d.ts +3 -0
- package/dist/_internal/shared/listing-types/classified/config.js +5 -0
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +11 -0
- package/dist/_internal/shared/listing-types/digital-code/config.js +22 -2
- package/dist/_internal/shared/listing-types/live/config.d.ts +3 -0
- package/dist/_internal/shared/listing-types/live/config.js +5 -0
- package/dist/_internal/shared/listing-types/pre-order/config.d.ts +3 -0
- package/dist/_internal/shared/listing-types/pre-order/config.js +19 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +11 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.js +15 -0
- package/dist/_internal/shared/listing-types/standard/config.d.ts +3 -0
- package/dist/_internal/shared/listing-types/standard/config.js +5 -0
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +3 -0
- package/dist/_internal/shared/listing-types/stickers/config.js +5 -0
- package/dist/client.d.ts +20 -7
- package/dist/client.js +22 -4
- package/dist/constants/api-endpoints.d.ts +6 -0
- package/dist/constants/api-endpoints.js +2 -0
- package/dist/constants/field-names.d.ts +57 -8
- package/dist/constants/field-names.js +101 -8
- package/dist/constants/table-keys.d.ts +17 -0
- package/dist/constants/table-keys.js +17 -0
- package/dist/errors/error-codes.d.ts +13 -1
- package/dist/errors/error-codes.js +13 -1
- package/dist/errors/error-display-map.js +12 -3
- package/dist/errors/messages.d.ts +10 -2
- package/dist/errors/messages.js +10 -2
- package/dist/features/about/components/AboutView.d.ts +3 -0
- package/dist/features/about/components/AboutView.js +3 -2
- package/dist/features/about/components/PolicyPageView.d.ts +2 -1
- package/dist/features/about/components/PolicyPageView.js +61 -23
- package/dist/features/about/components/PublicProfileView.js +5 -0
- package/dist/features/about/schemas/firestore.d.ts +3 -0
- package/dist/features/account/components/UserBidsView.js +12 -4
- package/dist/features/account/components/UserOrdersView.js +7 -0
- package/dist/features/account/components/UserReturnsView.d.ts +3 -0
- package/dist/features/account/components/UserReturnsView.js +17 -1
- package/dist/features/account/components/index.d.ts +0 -2
- package/dist/features/account/components/index.js +0 -1
- package/dist/features/account/schemas/index.d.ts +2 -2
- package/dist/features/account/types/index.d.ts +21 -2
- package/dist/features/addresses/schemas/index.d.ts +4 -4
- package/dist/features/admin/components/AdminArtView.js +8 -3
- package/dist/features/admin/components/AdminAuditLogView.js +1 -0
- package/dist/features/admin/components/AdminBidsView.js +15 -2
- package/dist/features/admin/components/AdminBlogEditorView.js +65 -33
- package/dist/features/admin/components/AdminClassifiedView.js +8 -3
- package/dist/features/admin/components/AdminDigitalCodesView.js +8 -3
- package/dist/features/admin/components/AdminFeatureEditorView.js +35 -6
- package/dist/features/admin/components/AdminFeatureFlagsView.js +1 -0
- package/dist/features/admin/components/AdminLiveView.js +8 -3
- package/dist/features/admin/components/AdminNavEditorView.js +15 -5
- package/dist/features/admin/components/AdminNewsletterView.js +18 -2
- package/dist/features/admin/components/AdminOffersView.d.ts +4 -0
- package/dist/features/admin/components/AdminOffersView.js +230 -0
- package/dist/features/admin/components/AdminOrdersView.js +10 -1
- package/dist/features/admin/components/AdminPaymentMethodsView.js +24 -4
- package/dist/features/admin/components/AdminPrizeDrawsView.js +5 -0
- package/dist/features/admin/components/AdminProductsView.js +16 -29
- package/dist/features/admin/components/AdminScammerEditorView.d.ts +2 -1
- package/dist/features/admin/components/AdminScammerEditorView.js +3 -13
- package/dist/features/admin/components/AdminScammersView.js +3 -8
- package/dist/features/admin/components/AdminSectionsView.js +32 -23
- package/dist/features/admin/components/AdminSessionsView.js +17 -2
- package/dist/features/admin/components/AdminSiteSettingsView.js +31 -13
- package/dist/features/admin/components/AdminSiteView.js +6 -2
- package/dist/features/admin/components/AdminStickersView.js +8 -3
- package/dist/features/admin/components/ViewAuditLogEntryModal.js +1 -0
- package/dist/features/admin/components/index.d.ts +2 -0
- package/dist/features/admin/components/index.js +1 -0
- package/dist/features/admin/components/sections/adminSectionsTypes.d.ts +4 -2
- package/dist/features/admin/components/sections/adminSectionsTypes.js +45 -27
- package/dist/features/admin/constants/filter-tabs.d.ts +89 -0
- package/dist/features/admin/constants/filter-tabs.js +56 -0
- package/dist/features/admin/schemas/firestore.d.ts +122 -3
- package/dist/features/admin/schemas/firestore.js +1 -0
- package/dist/features/admin/schemas/homepage-section-form.d.ts +22 -0
- package/dist/features/admin/schemas/homepage-section-form.js +68 -0
- package/dist/features/admin/schemas/nav-item-form.d.ts +74 -0
- package/dist/features/admin/schemas/nav-item-form.js +72 -0
- package/dist/features/auctions/actions/bid-actions.d.ts +20 -5
- package/dist/features/auctions/actions/bid-actions.js +93 -20
- package/dist/features/auctions/components/AuctionBidsTable.d.ts +10 -1
- package/dist/features/auctions/components/AuctionBidsTable.js +22 -4
- package/dist/features/auctions/components/AuctionDetailPageView.js +11 -6
- package/dist/features/auctions/components/AuctionsListView.js +5 -6
- package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +7 -0
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +19 -2
- package/dist/features/auctions/components/PlaceBidFormClient.d.ts +1 -2
- package/dist/features/auctions/components/PlaceBidFormClient.js +8 -4
- package/dist/features/auctions/components/bid-detail-fields.d.ts +29 -0
- package/dist/features/auctions/components/bid-detail-fields.js +103 -0
- package/dist/features/auctions/repository/bid.repository.d.ts +13 -0
- package/dist/features/auctions/repository/bid.repository.js +23 -0
- package/dist/features/auctions/schemas/firestore.d.ts +17 -0
- package/dist/features/auctions/schemas/index.d.ts +12 -12
- package/dist/features/audit-log/schemas/firestore.d.ts +14 -0
- package/dist/features/audit-log/schemas/firestore.js +7 -0
- package/dist/features/auth/permissions/constants.d.ts +1 -1
- package/dist/features/auth/permissions/constants.js +10 -1
- package/dist/features/blog/actions/blog-actions.d.ts +7 -7
- package/dist/features/blog/schemas/blog-form.d.ts +80 -0
- package/dist/features/blog/schemas/blog-form.js +100 -0
- package/dist/features/blog/schemas/index.d.ts +6 -6
- package/dist/features/cart/repository/cart.repository.js +1 -0
- package/dist/features/cart/schemas/firestore.d.ts +15 -0
- package/dist/features/catalogue/schemas/validation.d.ts +4 -4
- package/dist/features/categories/components/BrandDetailPageView.js +23 -40
- package/dist/features/categories/components/BrandDetailTabs.d.ts +7 -7
- package/dist/features/categories/components/BrandDetailTabs.js +8 -12
- package/dist/features/categories/components/BundleCollage.js +1 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +53 -57
- package/dist/features/categories/components/CategoryDetailTabs.d.ts +10 -8
- package/dist/features/categories/components/CategoryDetailTabs.js +11 -16
- package/dist/features/categories/components/CategoryProductsListing.js +11 -1
- package/dist/features/categories/components/ConcernCard.js +7 -1
- package/dist/features/categories/schemas/firestore.d.ts +13 -0
- package/dist/features/categories/schemas/index.d.ts +26 -26
- package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +16 -1
- package/dist/features/classified/components/ClassifiedDetailPageView.js +23 -3
- package/dist/features/events/components/AdminEventEditorView.js +32 -54
- package/dist/features/events/components/AdminEventEntriesView.js +22 -3
- package/dist/features/events/components/AdminEventsView.js +15 -11
- package/dist/features/events/components/EventFilters.d.ts +9 -1
- package/dist/features/events/components/EventFilters.js +45 -21
- package/dist/features/events/components/EventsIndexListing.d.ts +6 -1
- package/dist/features/events/components/EventsIndexListing.js +2 -2
- package/dist/features/events/components/EventsListPageView.js +13 -4
- package/dist/features/events/repository/events.repository.d.ts +17 -0
- package/dist/features/events/repository/events.repository.js +27 -0
- package/dist/features/events/schemas/event-form.d.ts +113 -0
- package/dist/features/events/schemas/event-form.js +82 -0
- package/dist/features/events/schemas/firestore.d.ts +12 -0
- package/dist/features/events/schemas/firestore.js +12 -0
- package/dist/features/events/schemas/index.d.ts +50 -50
- package/dist/features/events/types/index.d.ts +11 -0
- package/dist/features/events/types/index.js +57 -1
- package/dist/features/faq/actions/faq-actions.d.ts +12 -12
- package/dist/features/faq/schemas/index.d.ts +8 -8
- package/dist/features/filters/FilterFacetSection.d.ts +7 -1
- package/dist/features/filters/FilterFacetSection.js +11 -3
- package/dist/features/grouped/schemas/grouped-listing-form.d.ts +101 -0
- package/dist/features/grouped/schemas/grouped-listing-form.js +89 -0
- package/dist/features/grouped/schemas/index.d.ts +4 -4
- package/dist/features/homepage/actions/homepage-section-actions.d.ts +11 -3
- package/dist/features/homepage/actions/homepage-section-actions.js +33 -1
- package/dist/features/homepage/components/AnnouncementBar.d.ts +7 -1
- package/dist/features/homepage/components/AnnouncementBar.js +3 -3
- package/dist/features/homepage/components/MarketplaceHomepageView.js +20 -6
- package/dist/features/homepage/hooks/homepage-query.d.ts +16 -0
- package/dist/features/homepage/hooks/homepage-query.js +45 -0
- package/dist/features/homepage/hooks/useFeaturedAuctions.d.ts +10 -0
- package/dist/features/homepage/hooks/useFeaturedAuctions.js +28 -8
- package/dist/features/homepage/hooks/useFeaturedPreOrders.js +17 -8
- package/dist/features/homepage/hooks/useFeaturedProducts.js +15 -8
- package/dist/features/homepage/schemas/index.d.ts +33 -2
- package/dist/features/homepage/schemas/index.js +24 -0
- package/dist/features/layout/AppLayoutShell.d.ts +11 -1
- package/dist/features/layout/AppLayoutShell.js +15 -14
- package/dist/features/layout/BackToTop.d.ts +9 -0
- package/dist/features/layout/BackToTop.js +10 -1
- package/dist/features/layout/BottomActions.js +28 -25
- package/dist/features/layout/BottomChrome.d.ts +34 -0
- package/dist/features/layout/BottomChrome.js +55 -0
- package/dist/features/layout/BottomNavLayout.d.ts +6 -0
- package/dist/features/layout/BottomNavLayout.js +7 -1
- package/dist/features/layout/BottomNavbar.js +15 -2
- package/dist/features/layout/FooterLayout.js +11 -1
- package/dist/features/layout/NavbarLayout.js +1 -1
- package/dist/features/layout/TitleBarLayout.d.ts +7 -0
- package/dist/features/layout/TitleBarLayout.js +28 -5
- package/dist/features/layout/index.d.ts +2 -0
- package/dist/features/layout/index.js +1 -0
- package/dist/features/lottery/types/index.d.ts +3 -0
- package/dist/features/media/MediaPickerModal.js +5 -1
- package/dist/features/messages/schemas/index.d.ts +2 -2
- package/dist/features/orders/components/OrderScopeTabs.d.ts +20 -0
- package/dist/features/orders/components/OrderScopeTabs.js +31 -0
- package/dist/features/orders/components/OrderStatusTimeline.d.ts +5 -1
- package/dist/features/orders/components/OrderStatusTimeline.js +39 -20
- package/dist/features/orders/constants/order-scope.d.ts +48 -0
- package/dist/features/orders/constants/order-scope.js +111 -0
- package/dist/features/orders/repository/orders.repository.d.ts +54 -7
- package/dist/features/orders/repository/orders.repository.js +121 -22
- package/dist/features/orders/schemas/firestore.d.ts +152 -0
- package/dist/features/orders/schemas/firestore.js +30 -0
- package/dist/features/orders/schemas/index.d.ts +18 -18
- package/dist/features/orders/types/index.d.ts +35 -7
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +14 -9
- package/dist/features/pre-orders/components/PreOrdersListView.js +6 -5
- package/dist/features/pre-orders/schemas/index.d.ts +1 -1
- package/dist/features/products/actions/product-actions.d.ts +14 -0
- package/dist/features/products/actions/product-actions.js +49 -11
- package/dist/features/products/api/route.d.ts +12 -0
- package/dist/features/products/api/route.js +42 -100
- package/dist/features/products/components/ArtStickersListView.js +2 -2
- package/dist/features/products/components/AuctionsIndexListing.js +13 -11
- package/dist/features/products/components/AvailabilityTabs.d.ts +11 -0
- package/dist/features/products/components/AvailabilityTabs.js +47 -0
- package/dist/features/products/components/GroupSettingsPanel.js +5 -1
- package/dist/features/products/components/MakeOfferButton.js +48 -49
- package/dist/features/products/components/PrizeDrawCollage.d.ts +20 -4
- package/dist/features/products/components/PrizeDrawCollage.js +9 -1
- package/dist/features/products/components/PrizeDrawsIndexListing.js +14 -12
- package/dist/features/products/components/PrizeDrawsListingView.js +2 -2
- package/dist/features/products/components/PrizeDrawsSection.d.ts +7 -1
- package/dist/features/products/components/PrizeDrawsSection.js +23 -18
- package/dist/features/products/components/ProductDetailPageView.d.ts +4 -1
- package/dist/features/products/components/ProductDetailPageView.js +18 -4
- package/dist/features/products/components/ProductForm.js +5 -2
- package/dist/features/products/components/ProductGrid.js +6 -1
- package/dist/features/products/components/ProductsIndexListing.js +22 -32
- package/dist/features/products/components/ProductsIndexPageView.js +6 -9
- package/dist/features/products/components/index.d.ts +2 -2
- package/dist/features/products/components/index.js +1 -1
- package/dist/features/products/config/listing-type-listing-config.d.ts +20 -0
- package/dist/features/products/config/listing-type-listing-config.js +22 -10
- package/dist/features/products/constants/action-defs.d.ts +2 -0
- package/dist/features/products/constants/action-defs.js +6 -0
- package/dist/features/products/hooks/useAvailabilityScope.d.ts +13 -0
- package/dist/features/products/hooks/useAvailabilityScope.js +19 -0
- package/dist/features/products/hooks/useProducts.d.ts +5 -0
- package/dist/features/products/hooks/useProducts.js +13 -2
- package/dist/features/products/repository/products.repository.d.ts +31 -2
- package/dist/features/products/repository/products.repository.js +53 -21
- package/dist/features/products/schemas/firestore.d.ts +17 -3
- package/dist/features/products/schemas/firestore.js +7 -2
- package/dist/features/products/schemas/index.d.ts +64 -64
- package/dist/features/products/schemas/product-features.validators.d.ts +79 -6
- package/dist/features/products/schemas/product-features.validators.js +63 -0
- package/dist/features/products/types/index.d.ts +16 -1
- package/dist/features/promotions/schemas/index.d.ts +2 -2
- package/dist/features/reviews/schemas/index.d.ts +16 -16
- package/dist/features/scams/constants/scammer-status-display.d.ts +28 -0
- package/dist/features/scams/constants/scammer-status-display.js +79 -0
- package/dist/features/search/schemas/index.d.ts +4 -4
- package/dist/features/seller/actions/offer-actions.js +57 -4
- package/dist/features/seller/components/OfferPhaseTimeline.d.ts +59 -0
- package/dist/features/seller/components/OfferPhaseTimeline.js +107 -0
- package/dist/features/seller/components/SellerArtView.js +5 -0
- package/dist/features/seller/components/SellerAuctionsView.js +13 -15
- package/dist/features/seller/components/SellerBidsView.js +11 -4
- package/dist/features/seller/components/SellerClassifiedView.js +5 -0
- package/dist/features/seller/components/SellerCouponEditorView.js +17 -17
- package/dist/features/seller/components/SellerDigitalCodesView.js +5 -0
- package/dist/features/seller/components/SellerLiveView.js +5 -0
- package/dist/features/seller/components/SellerOffersView.js +2 -1
- package/dist/features/seller/components/SellerOrdersView.js +31 -9
- package/dist/features/seller/components/SellerPayoutSettingsView.js +56 -31
- package/dist/features/seller/components/SellerPreOrdersView.js +5 -0
- package/dist/features/seller/components/SellerPrizeDrawsView.js +14 -16
- package/dist/features/seller/components/SellerProductShell.js +7 -1
- package/dist/features/seller/components/SellerProductsView.js +11 -8
- package/dist/features/seller/components/SellerStickersView.js +5 -0
- package/dist/features/seller/components/index.d.ts +0 -2
- package/dist/features/seller/components/index.js +0 -1
- package/dist/features/seller/repository/offer.repository.d.ts +142 -24
- package/dist/features/seller/repository/offer.repository.js +165 -26
- package/dist/features/seller/schemas/coupon-form.d.ts +72 -0
- package/dist/features/seller/schemas/coupon-form.js +116 -0
- package/dist/features/seller/schemas/firestore.d.ts +56 -2
- package/dist/features/seller/schemas/firestore.js +27 -0
- package/dist/features/seller/schemas/index.d.ts +2 -2
- package/dist/features/seller/schemas/offer-forms.d.ts +46 -0
- package/dist/features/seller/schemas/offer-forms.js +42 -0
- package/dist/features/seller/server.d.ts +0 -1
- package/dist/features/seller/server.js +0 -1
- package/dist/features/shell/SectionForm.d.ts +99 -0
- package/dist/features/shell/SectionForm.js +128 -0
- package/dist/features/shell/build-sections.d.ts +63 -0
- package/dist/features/shell/build-sections.js +207 -0
- package/dist/features/shell/entity-form.d.ts +109 -0
- package/dist/features/shell/entity-form.js +96 -0
- package/dist/features/shell/field-ui-meta.d.ts +115 -0
- package/dist/features/shell/field-ui-meta.js +324 -0
- package/dist/features/shell/index.d.ts +8 -0
- package/dist/features/shell/index.js +4 -0
- package/dist/features/status-history/components/StatusTimeline.d.ts +74 -0
- package/dist/features/status-history/components/StatusTimeline.js +46 -0
- package/dist/features/status-history/index.d.ts +11 -0
- package/dist/features/status-history/index.js +10 -0
- package/dist/features/store-extensions/components/ReviewDecisionModal.d.ts +27 -0
- package/dist/features/store-extensions/components/ReviewDecisionModal.js +82 -0
- package/dist/features/store-extensions/index.d.ts +12 -0
- package/dist/features/store-extensions/index.js +12 -0
- package/dist/features/store-extensions/schemas/admin-notification-form.d.ts +36 -0
- package/dist/features/store-extensions/schemas/admin-notification-form.js +114 -0
- package/dist/features/store-extensions/schemas/analytics-forms.d.ts +57 -0
- package/dist/features/store-extensions/schemas/analytics-forms.js +158 -0
- package/dist/features/store-extensions/schemas/custom-role-form.d.ts +85 -0
- package/dist/features/store-extensions/schemas/custom-role-form.js +118 -0
- package/dist/features/store-extensions/schemas/firestore.d.ts +21 -1
- package/dist/features/store-extensions/schemas/firestore.js +60 -0
- package/dist/features/store-extensions/schemas/google-config-form.d.ts +53 -0
- package/dist/features/store-extensions/schemas/google-config-form.js +105 -0
- package/dist/features/store-extensions/schemas/item-request-create-form.d.ts +28 -0
- package/dist/features/store-extensions/schemas/item-request-create-form.js +80 -0
- package/dist/features/store-extensions/schemas/listing-template-form.d.ts +78 -0
- package/dist/features/store-extensions/schemas/listing-template-form.js +87 -0
- package/dist/features/store-extensions/schemas/moderation-review-form.d.ts +49 -0
- package/dist/features/store-extensions/schemas/moderation-review-form.js +101 -0
- package/dist/features/store-extensions/schemas/payout-method-form.d.ts +153 -0
- package/dist/features/store-extensions/schemas/payout-method-form.js +155 -0
- package/dist/features/store-extensions/schemas/report-create-form.d.ts +25 -0
- package/dist/features/store-extensions/schemas/report-create-form.js +79 -0
- package/dist/features/store-extensions/schemas/report-review-form.d.ts +47 -0
- package/dist/features/store-extensions/schemas/report-review-form.js +111 -0
- package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +148 -0
- package/dist/features/store-extensions/schemas/shipping-config-form.js +104 -0
- package/dist/features/store-extensions/schemas/store-category-form.d.ts +54 -0
- package/dist/features/store-extensions/schemas/store-category-form.js +73 -0
- package/dist/features/stores/api/[storeSlug]/route.js +2 -25
- package/dist/features/stores/components/StoreAuctionsListing.js +15 -1
- package/dist/features/stores/components/StoreClassifiedsListing.js +12 -2
- package/dist/features/stores/components/StoreDetailLayoutView.js +24 -71
- package/dist/features/stores/components/StoreDigitalCodesListing.js +12 -2
- package/dist/features/stores/components/StoreLiveItemsListing.js +12 -2
- package/dist/features/stores/components/StorePreOrdersListing.js +12 -1
- package/dist/features/stores/components/StoreProductsListing.js +11 -1
- package/dist/features/stores/repository/store.repository.js +6 -0
- package/dist/features/stores/schemas/index.d.ts +6 -6
- package/dist/features/support/schemas/index.d.ts +4 -4
- package/dist/features/tester/actions/checklist-item-actions.d.ts +4 -4
- package/dist/features/tester/seed-data/offers-tester-seed-data.js +119 -3
- package/dist/features/tester/seed-data/products-tester-seed-data.js +131 -1
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +431 -1
- package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
- package/dist/index.d.ts +25 -12
- package/dist/index.js +26 -11
- package/dist/next/routing/route-map.d.ts +23 -3
- package/dist/next/routing/route-map.js +14 -2
- package/dist/providers/db-firebase/base.repository.d.ts +30 -0
- package/dist/providers/db-firebase/base.repository.js +50 -1
- package/dist/providers/db-firebase/index.d.ts +1 -1
- package/dist/providers/db-firebase/index.js +1 -1
- package/dist/providers/db-firebase/sieve.d.ts +25 -0
- package/dist/providers/db-firebase/sieve.js +52 -18
- package/dist/react/hooks/useUrlTable.js +10 -1
- package/dist/schemas/firestore-value.d.ts +8 -0
- package/dist/schemas/firestore-value.js +44 -0
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.js +1 -1
- package/dist/schemas/registry.d.ts +702 -69
- package/dist/schemas/registry.js +64 -1
- package/dist/seed/_helpers/category-forest.d.ts +2 -0
- package/dist/seed/_helpers/category-forest.js +309 -0
- package/dist/seed/_helpers/category-tree.d.ts +27 -0
- package/dist/seed/_helpers/category-tree.js +103 -0
- package/dist/seed/bids-seed-data.js +30 -0
- package/dist/seed/catalogue-seed-data.js +12 -12
- package/dist/seed/categories-seed-data.js +177 -162
- package/dist/seed/events-seed-data.js +61 -10
- package/dist/seed/homepage-sections-seed-data.js +5 -1
- package/dist/seed/offers-seed-data.js +244 -34
- package/dist/seed/orders-seed-data.js +336 -1
- package/dist/seed/products-art-seed-data.js +50 -12
- package/dist/seed/products-auctions-seed-data.js +138 -18
- package/dist/seed/products-classifieds-seed-data.js +80 -16
- package/dist/seed/products-digital-codes-seed-data.js +66 -18
- package/dist/seed/products-live-items-seed-data.js +64 -13
- package/dist/seed/products-preorders-seed-data.d.ts +0 -1
- package/dist/seed/products-preorders-seed-data.js +52 -13
- package/dist/seed/products-prize-draws-seed-data.js +63 -14
- package/dist/seed/products-standard-seed-data.js +99 -26
- package/dist/seed/products-stickers-seed-data.js +47 -12
- package/dist/seed/reviews-seed-data.js +6 -1
- package/dist/seed/site-settings-seed-data.d.ts +1 -38
- package/dist/seed/site-settings-seed-data.js +38 -76
- package/dist/seed/stores-seed-data.js +71 -1
- package/dist/seed/users-seed-data.js +15 -5
- package/dist/server-entry.d.ts +1 -2
- package/dist/server-entry.js +4 -3
- package/dist/server.d.ts +6 -3
- package/dist/server.js +13 -4
- package/dist/styles.css +78 -12
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/Button.style.css +19 -4
- package/dist/ui/components/CollapsibleSection.d.ts +17 -1
- package/dist/ui/components/CollapsibleSection.js +6 -2
- package/dist/ui/components/FilterChipGroup.d.ts +25 -1
- package/dist/ui/components/FilterChipGroup.js +21 -4
- package/dist/ui/components/HandMode.style.css +47 -0
- package/dist/ui/components/Layout.d.ts +9 -2
- package/dist/ui/components/Layout.js +1 -1
- package/dist/ui/components/ListingLayout.js +8 -8
- package/dist/ui/components/ListingLayout.style.css +8 -7
- package/dist/ui/components/RecordDetailModal.d.ts +10 -1
- package/dist/ui/components/RecordDetailModal.js +2 -2
- package/dist/ui/components/StickyToolbar.d.ts +3 -1
- package/dist/ui/components/StickyToolbar.js +62 -20
- package/dist/ui/components/bottom-chrome-slot.d.ts +21 -0
- package/dist/ui/components/bottom-chrome-slot.js +29 -0
- package/dist/ui/components/index.style.css +3 -0
- package/dist/ui/forms/FormShell.d.ts +43 -13
- package/dist/ui/forms/FormShell.js +22 -11
- package/dist/ui/forms/index.d.ts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/package.json +2 -1
- package/scripts/node-esm-loader.mjs +65 -0
- package/scripts/seed-cli-loader.mjs +6 -49
- package/scripts/seed-cli.mjs +1 -1
|
@@ -24,9 +24,15 @@
|
|
|
24
24
|
import { offerRepository } from "../../../../features/seller/repository/offer.repository";
|
|
25
25
|
import { bidRepository } from "../../../../repositories";
|
|
26
26
|
import { OfferStatusValues } from "../../../../features/seller/schemas";
|
|
27
|
+
import { BID_COLLECTION } from "../../../../features/auctions/schemas/firestore";
|
|
28
|
+
import { PRODUCT_COLLECTION } from "../../../../features/products/schemas/firestore";
|
|
27
29
|
import { ValidationError } from "../../../../errors";
|
|
30
|
+
import { BID_ERROR_CODES } from "../../../../errors/error-codes";
|
|
31
|
+
import { ERROR_MESSAGES } from "../../../../errors";
|
|
32
|
+
import { getAdminDb } from "../../../../providers/db-firebase";
|
|
28
33
|
import { serverLogger } from "../../../../monitoring/server-logger";
|
|
29
34
|
import { normalizeError } from "../../../../errors/normalize";
|
|
35
|
+
import { resolveDate } from "../../../../utils/date.formatter";
|
|
30
36
|
import { activeLane, laneOf, laneBlockReason } from "../../../shared/checkout/lanes";
|
|
31
37
|
/**
|
|
32
38
|
* Refuse a checkout that isn't the cart's active lane.
|
|
@@ -49,6 +55,108 @@ export function assertCheckoutLane(allCartItems, selectedItems) {
|
|
|
49
55
|
}
|
|
50
56
|
/** Error code the client maps to a lane-aware message. */
|
|
51
57
|
export const CHECKOUT_LANE_BLOCKED = "CHECKOUT_LANE_BLOCKED";
|
|
58
|
+
const CLAIM_FAILURE_ERRORS = {
|
|
59
|
+
NOT_FOUND: {
|
|
60
|
+
message: ERROR_MESSAGES.BID.AUCTION_NOT_FOUND,
|
|
61
|
+
code: BID_ERROR_CODES.PRODUCT_NOT_FOUND,
|
|
62
|
+
},
|
|
63
|
+
ALREADY_SOLD: {
|
|
64
|
+
message: ERROR_MESSAGES.BID.AUCTION_ALREADY_SOLD,
|
|
65
|
+
code: BID_ERROR_CODES.AUCTION_ALREADY_SOLD,
|
|
66
|
+
},
|
|
67
|
+
AUCTION_ENDED: {
|
|
68
|
+
message: ERROR_MESSAGES.BID.AUCTION_ENDED_BEFORE_CHECKOUT,
|
|
69
|
+
code: BID_ERROR_CODES.AUCTION_ENDED_BEFORE_CHECKOUT,
|
|
70
|
+
},
|
|
71
|
+
LAPSED: {
|
|
72
|
+
message: ERROR_MESSAGES.BID.BUYOUT_LAPSED,
|
|
73
|
+
code: BID_ERROR_CODES.BUYOUT_LAPSED,
|
|
74
|
+
},
|
|
75
|
+
OUTBID: {
|
|
76
|
+
message: ERROR_MESSAGES.BID.BUYOUT_OUTBID,
|
|
77
|
+
code: BID_ERROR_CODES.BUYOUT_OUTBID,
|
|
78
|
+
},
|
|
79
|
+
WRONG_BUYER: {
|
|
80
|
+
message: ERROR_MESSAGES.BID.BUYOUT_LAPSED,
|
|
81
|
+
code: BID_ERROR_CODES.BUYOUT_LAPSED,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Convert a pending Buy Now claim into an actual sale, atomically.
|
|
86
|
+
*
|
|
87
|
+
* This is where a buyout is decided, and it is the ONLY place the auction is
|
|
88
|
+
* closed. `buyNowAuction` deliberately leaves the listing untouched: the auction
|
|
89
|
+
* keeps running, keeps taking bids, and keeps accepting other buyers' buyouts.
|
|
90
|
+
* That means several people can be holding a claim on the same auction at once,
|
|
91
|
+
* which is intentional — whoever reaches this transaction first gets the item,
|
|
92
|
+
* and everyone else is refused HERE, before their order is written and before
|
|
93
|
+
* any payment is captured.
|
|
94
|
+
*
|
|
95
|
+
* Four ways to lose, all of them checked inside the transaction against freshly
|
|
96
|
+
* read documents rather than against the caller's stale cart line:
|
|
97
|
+
* - the auction is already sold (another buyout committed first);
|
|
98
|
+
* - its clock ran out (settlement will award it to a real bidder — the user's
|
|
99
|
+
* explicit rule: an unfinished buyout at auction end fails);
|
|
100
|
+
* - the claim's own bid is no longer `active` (the deadline sweep cancelled it);
|
|
101
|
+
* - bidding passed the buyout price, so buying out is no longer the better deal.
|
|
102
|
+
*
|
|
103
|
+
* Returns a discriminated result rather than throwing out of the transaction
|
|
104
|
+
* body, so each of these precise, buyer-readable refusals survives as itself
|
|
105
|
+
* instead of being reshaped by the transaction wrapper. The caller throws.
|
|
106
|
+
*/
|
|
107
|
+
export async function claimAuctionForCheckout(item, buyerUid) {
|
|
108
|
+
const productId = item.auctionId ?? item.productId;
|
|
109
|
+
const bidId = item.bidId;
|
|
110
|
+
if (!bidId)
|
|
111
|
+
return { ok: false, reason: "NOT_FOUND" };
|
|
112
|
+
const db = getAdminDb();
|
|
113
|
+
return db.runTransaction(async (tx) => {
|
|
114
|
+
const productRef = db.collection(PRODUCT_COLLECTION).doc(productId);
|
|
115
|
+
const bidRef = db.collection(BID_COLLECTION).doc(bidId);
|
|
116
|
+
const [productSnap, bidSnap] = await tx.getAll(productRef, bidRef);
|
|
117
|
+
if (!productSnap.exists || !bidSnap.exists) {
|
|
118
|
+
return { ok: false, reason: "NOT_FOUND" };
|
|
119
|
+
}
|
|
120
|
+
const product = productSnap.data();
|
|
121
|
+
const bid = bidSnap.data();
|
|
122
|
+
if (bid.userId !== buyerUid)
|
|
123
|
+
return { ok: false, reason: "WRONG_BUYER" };
|
|
124
|
+
if (bid.status !== "active")
|
|
125
|
+
return { ok: false, reason: "LAPSED" };
|
|
126
|
+
if (product.isSold === true)
|
|
127
|
+
return { ok: false, reason: "ALREADY_SOLD" };
|
|
128
|
+
const endDate = product.auctionEndDate ? resolveDate(product.auctionEndDate) : null;
|
|
129
|
+
if (endDate && endDate.getTime() <= Date.now()) {
|
|
130
|
+
return { ok: false, reason: "AUCTION_ENDED" };
|
|
131
|
+
}
|
|
132
|
+
const bidAmount = bid.bidAmount;
|
|
133
|
+
const standingBid = typeof product.currentBid === "number" ? product.currentBid : 0;
|
|
134
|
+
// `currentBid` never reflects a pending buyout (see BidDocument.isBuyout),
|
|
135
|
+
// so this compares against real bidding only — exactly the check the buyer
|
|
136
|
+
// passed when they started, re-run against the price as it is right now.
|
|
137
|
+
if (standingBid >= bidAmount) {
|
|
138
|
+
return { ok: false, reason: "OUTBID" };
|
|
139
|
+
}
|
|
140
|
+
tx.update(productRef, {
|
|
141
|
+
isSold: true,
|
|
142
|
+
availableQuantity: 0,
|
|
143
|
+
// Ends the auction NOW. Everything above has already established that
|
|
144
|
+
// nobody outbid the buyout price, so no bidder loses anything they would
|
|
145
|
+
// otherwise have won.
|
|
146
|
+
auctionEndDate: new Date(),
|
|
147
|
+
currentBid: bidAmount,
|
|
148
|
+
leadingBidderId: bid.userId,
|
|
149
|
+
bidsHaveStarted: true,
|
|
150
|
+
updatedAt: new Date(),
|
|
151
|
+
});
|
|
152
|
+
tx.update(bidRef, {
|
|
153
|
+
status: "won",
|
|
154
|
+
isWinning: true,
|
|
155
|
+
updatedAt: new Date(),
|
|
156
|
+
});
|
|
157
|
+
return { ok: true, bidAmount };
|
|
158
|
+
});
|
|
159
|
+
}
|
|
52
160
|
/**
|
|
53
161
|
* Re-validate every locked line immediately before the order is written.
|
|
54
162
|
*
|
|
@@ -56,10 +164,37 @@ export const CHECKOUT_LANE_BLOCKED = "CHECKOUT_LANE_BLOCKED";
|
|
|
56
164
|
* to the cart, but nothing re-checked at order time — so a buyer could add an
|
|
57
165
|
* accepted offer, wait out the 48h window, and still be charged the locked
|
|
58
166
|
* price. Throws on the first invalid line; the caller's transaction aborts.
|
|
167
|
+
*
|
|
168
|
+
* Auction lines were skipped entirely until 2026-08-24 (`if (!item.offerId)
|
|
169
|
+
* continue`), so a won auction's own `checkoutDeadline` had never been checked
|
|
170
|
+
* at order time at all — and a buyout claim, which is decided here, had nowhere
|
|
171
|
+
* to be decided.
|
|
59
172
|
*/
|
|
60
173
|
export async function assertLockedLinesStillValid(items, buyerUid) {
|
|
61
174
|
const now = new Date();
|
|
62
175
|
for (const item of items) {
|
|
176
|
+
// --- Auction lines: deadline for every one, plus the claim for a buyout ---
|
|
177
|
+
if (item.bidId || item.isAuctionWin) {
|
|
178
|
+
if (item.checkoutDeadline && now > resolveDate(item.checkoutDeadline)) {
|
|
179
|
+
throw new ValidationError(item.isBuyout
|
|
180
|
+
? ERROR_MESSAGES.BID.BUYOUT_LAPSED
|
|
181
|
+
: "The payment window for this auction win has expired.", { code: item.isBuyout ? BID_ERROR_CODES.BUYOUT_LAPSED : undefined });
|
|
182
|
+
}
|
|
183
|
+
if (item.isBuyout) {
|
|
184
|
+
const claim = await claimAuctionForCheckout(item, buyerUid);
|
|
185
|
+
if (!claim.ok) {
|
|
186
|
+
const { message, code } = CLAIM_FAILURE_ERRORS[claim.reason];
|
|
187
|
+
serverLogger.info("claimAuctionForCheckout refused", {
|
|
188
|
+
productId: item.auctionId ?? item.productId,
|
|
189
|
+
bidId: item.bidId,
|
|
190
|
+
buyerUid,
|
|
191
|
+
reason: claim.reason,
|
|
192
|
+
});
|
|
193
|
+
throw new ValidationError(message, { code });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
63
198
|
if (!item.offerId)
|
|
64
199
|
continue;
|
|
65
200
|
const offer = await offerRepository.findById(item.offerId);
|
|
@@ -112,5 +247,41 @@ export async function finalizeLockedLines(items, orderId) {
|
|
|
112
247
|
});
|
|
113
248
|
}
|
|
114
249
|
}
|
|
250
|
+
if (item.isBuyout && item.bidId) {
|
|
251
|
+
await closeOutBuyoutLosers(item.auctionId ?? item.productId, item.bidId);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* A buyout ended the auction, so everyone still bidding on it lost.
|
|
257
|
+
*
|
|
258
|
+
* Deliberately AFTER the claim transaction rather than inside it: the number of
|
|
259
|
+
* active bids on a hot auction is unbounded, and a transaction that touches all
|
|
260
|
+
* of them would either blow the 500-write limit or contend with every incoming
|
|
261
|
+
* bid. The claim only has to be atomic about who gets the ITEM; tidying up the
|
|
262
|
+
* losers is bookkeeping, so it is bounded, best-effort and logged.
|
|
263
|
+
*
|
|
264
|
+
* Their bids are `lost`, not `outbid` — the auction is over, which is the same
|
|
265
|
+
* distinction `auctionSettlement` draws.
|
|
266
|
+
*/
|
|
267
|
+
async function closeOutBuyoutLosers(productId, winningBidId) {
|
|
268
|
+
try {
|
|
269
|
+
const active = await bidRepository.getActiveByProduct(productId);
|
|
270
|
+
const losers = active.filter((e) => e.id !== winningBidId);
|
|
271
|
+
if (losers.length === 0)
|
|
272
|
+
return;
|
|
273
|
+
await bidRepository.markManyLost(losers.map((e) => e.ref));
|
|
274
|
+
serverLogger.info("finalizeLockedLines: buyout closed out losing bids", {
|
|
275
|
+
productId,
|
|
276
|
+
winningBidId,
|
|
277
|
+
losers: losers.length,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
catch (err) {
|
|
281
|
+
void normalizeError(err);
|
|
282
|
+
serverLogger.error("finalizeLockedLines: buyout loser close-out failed", {
|
|
283
|
+
productId,
|
|
284
|
+
winningBidId,
|
|
285
|
+
});
|
|
115
286
|
}
|
|
116
287
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CartItemDocument } from "../../../../features/cart/schemas/firestore";
|
|
2
|
+
import type { ProductDocument } from "../../../../features/products/schemas/firestore";
|
|
3
|
+
import type { OrderSourceContext } from "../../../../features/orders/schemas/firestore";
|
|
4
|
+
import type { OrderType } from "../../../../features/orders/utils/order-splitter";
|
|
5
|
+
export declare function buildOrderSourceContext(item: CartItemDocument, product: ProductDocument, orderType: OrderType): Promise<OrderSourceContext | undefined>;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: An order records WHAT was bought and WHAT it cost, and nothing about how
|
|
3
|
+
* the buyer earned the right to buy it at that price. `orderType` has five
|
|
4
|
+
* values and cannot even separate "won at ₹4,200 against 11 bids" from
|
|
5
|
+
* "bought out at ₹6,000 while the standing bid was ₹3,800" — both land as
|
|
6
|
+
* `orderType: "auction"`. Everything else was recoverable only by reading
|
|
7
|
+
* the auction or offer document, which is mutable and eventually archived.
|
|
8
|
+
* WHAT: `buildOrderSourceContext()` — the ONE builder for `OrderSourceContext`,
|
|
9
|
+
* called by both order-creation paths (manual/COD and Razorpay).
|
|
10
|
+
*
|
|
11
|
+
* ## Why one shared function and not two inline blocks
|
|
12
|
+
*
|
|
13
|
+
* `createOrderForGroup` and `createRazorpayGroupOrder` are near-identical
|
|
14
|
+
* ~200-line twins that already drifted once on add-on fees (Root Cause #65).
|
|
15
|
+
* Two hand-written copies of this would be the create-vs-create axis of Root
|
|
16
|
+
* Cause #39: one lane records provenance, the other silently doesn't, and the
|
|
17
|
+
* difference is invisible until someone compares two orders months later.
|
|
18
|
+
*
|
|
19
|
+
* ## Written once, never recomputed
|
|
20
|
+
*
|
|
21
|
+
* These numbers describe a moment. `product.price` moves, `currentBid` is a
|
|
22
|
+
* mirror that a pending buyout deliberately never writes to, and a settled
|
|
23
|
+
* auction is eventually archived. Recomputing later would silently rewrite
|
|
24
|
+
* history, so nothing outside order creation may write this field.
|
|
25
|
+
*
|
|
26
|
+
* ## Read cost
|
|
27
|
+
*
|
|
28
|
+
* Standard, pre-order and prize-draw cost **zero** extra reads — everything
|
|
29
|
+
* comes from the product already in hand. Only the auction and offer lanes pay:
|
|
30
|
+
* one `findByProductSorted` for auctions (bid count, winner, runner-up, the
|
|
31
|
+
* standing bid — all four from one query) and one `findById` for offers. Since
|
|
32
|
+
* a checkout is single-lane by construction, a standard cart never pays either.
|
|
33
|
+
*
|
|
34
|
+
* ## Failure is non-fatal, deliberately
|
|
35
|
+
*
|
|
36
|
+
* A missing bid or offer document returns `undefined` rather than throwing. The
|
|
37
|
+
* money path must not fail because a provenance record could not be assembled —
|
|
38
|
+
* an order with no `sourceContext` is a thinner record; a checkout that 500s
|
|
39
|
+
* after payment authorisation is a support ticket.
|
|
40
|
+
*
|
|
41
|
+
* EXPORTS:
|
|
42
|
+
* buildOrderSourceContext
|
|
43
|
+
*
|
|
44
|
+
* @tag domain:checkout,orders
|
|
45
|
+
* @tag layer:server-feature
|
|
46
|
+
* @tag pattern:none
|
|
47
|
+
* @tag access:server
|
|
48
|
+
* @tag consumers:checkout/actions.ts
|
|
49
|
+
* @tag sideEffects:firestore-read
|
|
50
|
+
*/
|
|
51
|
+
import { bidRepository } from "../../../../features/auctions/repository/bid.repository";
|
|
52
|
+
import { offerRepository } from "../../../../features/seller/repository/offer.repository";
|
|
53
|
+
import { normalizeError } from "../../../../errors/normalize";
|
|
54
|
+
import { serverLogger } from "../../../../monitoring";
|
|
55
|
+
/** Bids that count toward "against N bidders" — a buyout is excluded. */
|
|
56
|
+
function competitiveBids(bids) {
|
|
57
|
+
return bids.filter((b) => !b.isBuyout).sort((a, b) => b.bidAmount - a.bidAmount);
|
|
58
|
+
}
|
|
59
|
+
export async function buildOrderSourceContext(item, product, orderType) {
|
|
60
|
+
try {
|
|
61
|
+
// The offer lane is checked BEFORE orderType, because an accepted offer on
|
|
62
|
+
// a standard listing arrives as orderType "offer" but an accepted offer on
|
|
63
|
+
// a classified does not — the cart line's own `offerId` is the reliable
|
|
64
|
+
// discriminator, exactly as `laneOf()` treats it.
|
|
65
|
+
if (item.offerId) {
|
|
66
|
+
const offer = await offerRepository.findById(item.offerId);
|
|
67
|
+
if (!offer)
|
|
68
|
+
return undefined;
|
|
69
|
+
return {
|
|
70
|
+
path: "offer-accepted",
|
|
71
|
+
offerId: offer.id,
|
|
72
|
+
offeredAmount: offer.offerAmount,
|
|
73
|
+
listPriceAtOffer: offer.listedPrice,
|
|
74
|
+
counterAmount: offer.counterAmount,
|
|
75
|
+
// Persisted since W2. Before the chain fields existed this number was
|
|
76
|
+
// genuinely unknowable — each counter created an unlinked document.
|
|
77
|
+
counterRounds: offer.counterRound ?? 1,
|
|
78
|
+
acceptedBy: offer.storeId,
|
|
79
|
+
acceptedAt: offer.acceptedAt ?? offer.respondedAt ?? new Date(),
|
|
80
|
+
checkoutDeadline: offer.checkoutDeadline,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (item.bidId) {
|
|
84
|
+
const bids = await bidRepository.findByProductSorted(item.productId);
|
|
85
|
+
const rivals = competitiveBids(bids);
|
|
86
|
+
const auctionId = item.auctionId ?? item.productId;
|
|
87
|
+
if (item.isBuyout) {
|
|
88
|
+
return {
|
|
89
|
+
path: "auction-buy-now",
|
|
90
|
+
auctionId,
|
|
91
|
+
bidId: item.bidId,
|
|
92
|
+
buyNowPrice: item.lockedPrice ?? product.buyNowPrice ?? item.price,
|
|
93
|
+
listPrice: product.price,
|
|
94
|
+
// From the bids, not `product.currentBid` — a pending buyout never
|
|
95
|
+
// writes that mirror, so reading it would understate the auction.
|
|
96
|
+
standingBidAtBuyout: rivals[0]?.bidAmount ?? 0,
|
|
97
|
+
bidCount: rivals.length,
|
|
98
|
+
boughtAt: new Date(),
|
|
99
|
+
checkoutDeadline: item.checkoutDeadline ?? new Date(),
|
|
100
|
+
auctionEndDate: product.auctionEndDate,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const winning = bids.find((b) => b.id === item.bidId);
|
|
104
|
+
const winningAmount = winning?.bidAmount ?? item.lockedPrice ?? item.price;
|
|
105
|
+
const reserve = product.reservePrice;
|
|
106
|
+
return {
|
|
107
|
+
path: "auction-won",
|
|
108
|
+
auctionId,
|
|
109
|
+
bidId: item.bidId,
|
|
110
|
+
winningBidAmount: winningAmount,
|
|
111
|
+
bidCount: rivals.length,
|
|
112
|
+
startingBid: product.startingBid ?? 0,
|
|
113
|
+
reservePrice: reserve,
|
|
114
|
+
// No reserve set means the reserve cannot fail, so it is met.
|
|
115
|
+
reserveMet: reserve == null ? true : winningAmount >= reserve,
|
|
116
|
+
auctionEndedAt: product.auctionEndDate ?? new Date(),
|
|
117
|
+
runnerUpAmount: rivals.find((b) => b.id !== item.bidId)?.bidAmount,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
if (orderType === "preorder") {
|
|
121
|
+
const deposit = product.preOrderDepositAmount ??
|
|
122
|
+
(product.preOrderDepositPercent != null
|
|
123
|
+
? (product.price * product.preOrderDepositPercent) / 100
|
|
124
|
+
: 0);
|
|
125
|
+
return {
|
|
126
|
+
path: "pre-order",
|
|
127
|
+
depositAmount: deposit,
|
|
128
|
+
balanceDue: Math.max(0, product.price - deposit),
|
|
129
|
+
expectedDeliveryDate: product.preOrderDeliveryDate,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (orderType === "prize-draw") {
|
|
133
|
+
return {
|
|
134
|
+
path: "prize-draw",
|
|
135
|
+
prizeDrawProductId: item.productId,
|
|
136
|
+
pricePerEntry: product.pricePerEntry ?? product.price,
|
|
137
|
+
entryCount: item.quantity,
|
|
138
|
+
// `prizeDrawMode` is reveal-vs-lottery, a different axis. The reveal
|
|
139
|
+
// TIMING is what this records: a draw with a reveal window is
|
|
140
|
+
// scheduled, one without reveals as soon as it sells out.
|
|
141
|
+
revealMode: product.prizeRevealWindowEnd ? "scheduled" : "instant",
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return { path: "standard", listPrice: product.price };
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
const normalized = normalizeError(err);
|
|
148
|
+
// Non-fatal by design — see the header. Logged loudly so a systematic
|
|
149
|
+
// failure shows up as a pattern rather than as quietly thinner orders.
|
|
150
|
+
serverLogger.warn("[checkout] could not build sourceContext", {
|
|
151
|
+
productId: item.productId,
|
|
152
|
+
orderType,
|
|
153
|
+
error: normalized.message,
|
|
154
|
+
});
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
// `getHomepageInitial` / `getHomepageSections` / `getHeroCarouselSlides` lived
|
|
2
|
+
// in ./data and were deleted 2026-08-24. All three had ZERO call sites — the
|
|
3
|
+
// live homepage is `MarketplaceHomepageView`, which reads its repositories
|
|
4
|
+
// directly — and the only part worth keeping, the feature-flag gate, moved to
|
|
5
|
+
// `_internal/shared/features/homepage/section-gate.ts` and is now actually
|
|
6
|
+
// applied. The rest was a Rule #6 liability: `findActiveAuctions()` /
|
|
7
|
+
// `findActivePreOrders()` were unbounded `.get()` collection scans.
|
|
2
8
|
export { HOMEPAGE_FEATURED_REVIEWS_LIMIT, HOMEPAGE_RECENT_BLOG_POSTS_LIMIT, HOMEPAGE_MAX_SECTIONS, } from "../../../shared/features/homepage/config";
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/** Strip price and weight from a single slot for client consumption. */
|
|
2
2
|
export function toClientLotterySlot(slot) {
|
|
3
|
+
// Allow-list, not a spread: every field named here is a deliberate public
|
|
4
|
+
// exposure with a known reader (§ Public Data Projections). `image` is read
|
|
5
|
+
// by the prize collage on the lottery detail page.
|
|
3
6
|
return {
|
|
4
7
|
slotNumber: slot.slotNumber,
|
|
5
8
|
name: slot.name,
|
|
9
|
+
image: slot.image,
|
|
6
10
|
isBooked: slot.isBooked,
|
|
7
11
|
bookedByUserLotteryNumber: slot.bookedByUserLotteryNumber,
|
|
8
12
|
bookedByDisplayName: slot.bookedByDisplayName,
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offer document → API shape.
|
|
3
|
+
*
|
|
4
|
+
* Offers had **no adapter at all** before this: all three routes
|
|
5
|
+
* (`/api/user/offers`, `/api/store/offers`, `/api/admin/offers`) returned raw
|
|
6
|
+
* `OfferDocument`s straight from the repository, carrying live `Date`
|
|
7
|
+
* objects. `UserOffersPanel.relativeTime` still has a defensive
|
|
8
|
+
* `date instanceof Date ? … : new Date(…)` branch precisely because the shape
|
|
9
|
+
* it receives depends on whether the value survived JSON serialisation.
|
|
10
|
+
*
|
|
11
|
+
* Mirrors `orders/adapters.ts`, including its `toIsoOrUndefined` helper.
|
|
12
|
+
*/
|
|
13
|
+
import type { OfferDocument } from "../../../../features/seller/schemas";
|
|
14
|
+
import type { FieldChange } from "../../../shared/history/index";
|
|
15
|
+
/** One entry on an offer's timeline — dates as ISO, ready for JSON. */
|
|
16
|
+
export interface OfferTimelineEntry {
|
|
17
|
+
at: string;
|
|
18
|
+
actorUid?: string;
|
|
19
|
+
actorRole: "buyer" | "seller" | "admin" | "system";
|
|
20
|
+
changes: Record<string, FieldChange>;
|
|
21
|
+
reason?: string;
|
|
22
|
+
note?: string;
|
|
23
|
+
trigger: string;
|
|
24
|
+
}
|
|
25
|
+
/** One round of a negotiation, as rendered in the chain rail. */
|
|
26
|
+
export interface OfferChainRound {
|
|
27
|
+
id: string;
|
|
28
|
+
counterRound: number;
|
|
29
|
+
status: OfferDocument["status"];
|
|
30
|
+
offerAmount: number;
|
|
31
|
+
counterAmount?: number;
|
|
32
|
+
/**
|
|
33
|
+
* `withdrawn` + a `supersededByOfferId` is NOT a walk-away — the buyer
|
|
34
|
+
* countered. The timeline renders it neutral ("Superseded") rather than
|
|
35
|
+
* negative ("Withdrawn"), which is why this flag is carried explicitly
|
|
36
|
+
* instead of being re-derived in the component.
|
|
37
|
+
*/
|
|
38
|
+
superseded: boolean;
|
|
39
|
+
createdAt: string;
|
|
40
|
+
respondedAt?: string;
|
|
41
|
+
sellerNote?: string;
|
|
42
|
+
buyerNote?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface Offer {
|
|
45
|
+
id: string;
|
|
46
|
+
productId: string;
|
|
47
|
+
productTitle: string;
|
|
48
|
+
productSlug?: string;
|
|
49
|
+
productImageUrl?: string;
|
|
50
|
+
storeId: string;
|
|
51
|
+
storeName: string;
|
|
52
|
+
offerAmount: number;
|
|
53
|
+
listedPrice: number;
|
|
54
|
+
counterAmount?: number;
|
|
55
|
+
lockedPrice?: number;
|
|
56
|
+
currency: string;
|
|
57
|
+
status: OfferDocument["status"];
|
|
58
|
+
buyerNote?: string;
|
|
59
|
+
sellerNote?: string;
|
|
60
|
+
expiresAt: string;
|
|
61
|
+
acceptedAt?: string;
|
|
62
|
+
checkoutDeadline?: string;
|
|
63
|
+
respondedAt?: string;
|
|
64
|
+
paidOrderId?: string;
|
|
65
|
+
paidAt?: string;
|
|
66
|
+
createdAt: string;
|
|
67
|
+
updatedAt: string;
|
|
68
|
+
timeline?: OfferTimelineEntry[];
|
|
69
|
+
timelineTruncated?: number;
|
|
70
|
+
previousOfferId?: string;
|
|
71
|
+
supersededByOfferId?: string;
|
|
72
|
+
chainRootOfferId?: string;
|
|
73
|
+
counterRound?: number;
|
|
74
|
+
/** True when this round was superseded by the buyer's own counter. */
|
|
75
|
+
superseded: boolean;
|
|
76
|
+
cancelledByAdminUid?: string;
|
|
77
|
+
cancelReason?: string;
|
|
78
|
+
buyerUid?: string;
|
|
79
|
+
buyerName?: string;
|
|
80
|
+
buyerEmail?: string;
|
|
81
|
+
}
|
|
82
|
+
export interface OfferAdapterOptions {
|
|
83
|
+
/**
|
|
84
|
+
* Include `buyerUid`/`buyerName`/`buyerEmail`.
|
|
85
|
+
*
|
|
86
|
+
* Default **false**, deliberately. The seller-facing route masks buyer
|
|
87
|
+
* identity, and a route that forgot to call `maskOfferForSeller` would
|
|
88
|
+
* previously have shipped it verbatim — there was no adapter to stop it.
|
|
89
|
+
* Making the omission the default means forgetting the flag under-shares
|
|
90
|
+
* rather than leaks.
|
|
91
|
+
*/
|
|
92
|
+
includeBuyerIdentity?: boolean;
|
|
93
|
+
}
|
|
94
|
+
export declare function offerDocumentToOffer(doc: OfferDocument, opts?: OfferAdapterOptions): Offer;
|
|
95
|
+
/**
|
|
96
|
+
* A chain round — the compact shape the timeline needs, without re-sending
|
|
97
|
+
* the whole document for every round.
|
|
98
|
+
*
|
|
99
|
+
* Buyer identity is never included: the chain is rendered on all three
|
|
100
|
+
* portals from one component, and the seller's view must not gain identity
|
|
101
|
+
* it is masked from elsewhere.
|
|
102
|
+
*/
|
|
103
|
+
export declare function offerToChainRound(doc: OfferDocument): OfferChainRound;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offer document → API shape.
|
|
3
|
+
*
|
|
4
|
+
* Offers had **no adapter at all** before this: all three routes
|
|
5
|
+
* (`/api/user/offers`, `/api/store/offers`, `/api/admin/offers`) returned raw
|
|
6
|
+
* `OfferDocument`s straight from the repository, carrying live `Date`
|
|
7
|
+
* objects. `UserOffersPanel.relativeTime` still has a defensive
|
|
8
|
+
* `date instanceof Date ? … : new Date(…)` branch precisely because the shape
|
|
9
|
+
* it receives depends on whether the value survived JSON serialisation.
|
|
10
|
+
*
|
|
11
|
+
* Mirrors `orders/adapters.ts`, including its `toIsoOrUndefined` helper.
|
|
12
|
+
*/
|
|
13
|
+
function toIsoOrUndefined(value) {
|
|
14
|
+
return value instanceof Date ? value.toISOString() : undefined;
|
|
15
|
+
}
|
|
16
|
+
function toIso(value) {
|
|
17
|
+
return value instanceof Date ? value.toISOString() : String(value);
|
|
18
|
+
}
|
|
19
|
+
export function offerDocumentToOffer(doc, opts = {}) {
|
|
20
|
+
const superseded = doc.status === "withdrawn" && Boolean(doc.supersededByOfferId);
|
|
21
|
+
return {
|
|
22
|
+
id: doc.id,
|
|
23
|
+
productId: doc.productId,
|
|
24
|
+
productTitle: doc.productTitle,
|
|
25
|
+
productSlug: doc.productSlug,
|
|
26
|
+
productImageUrl: doc.productImageUrl,
|
|
27
|
+
storeId: doc.storeId,
|
|
28
|
+
storeName: doc.storeName,
|
|
29
|
+
offerAmount: doc.offerAmount,
|
|
30
|
+
listedPrice: doc.listedPrice,
|
|
31
|
+
counterAmount: doc.counterAmount,
|
|
32
|
+
lockedPrice: doc.lockedPrice,
|
|
33
|
+
currency: doc.currency,
|
|
34
|
+
status: doc.status,
|
|
35
|
+
buyerNote: doc.buyerNote,
|
|
36
|
+
sellerNote: doc.sellerNote,
|
|
37
|
+
expiresAt: toIso(doc.expiresAt),
|
|
38
|
+
acceptedAt: toIsoOrUndefined(doc.acceptedAt),
|
|
39
|
+
checkoutDeadline: toIsoOrUndefined(doc.checkoutDeadline),
|
|
40
|
+
respondedAt: toIsoOrUndefined(doc.respondedAt),
|
|
41
|
+
paidOrderId: doc.paidOrderId,
|
|
42
|
+
paidAt: toIsoOrUndefined(doc.paidAt),
|
|
43
|
+
createdAt: toIso(doc.createdAt),
|
|
44
|
+
updatedAt: toIso(doc.updatedAt),
|
|
45
|
+
timeline: doc.statusHistory?.map((entry) => ({
|
|
46
|
+
at: entry.at instanceof Date ? entry.at.toISOString() : String(entry.at),
|
|
47
|
+
actorUid: entry.actorUid,
|
|
48
|
+
actorRole: entry.actorRole,
|
|
49
|
+
changes: entry.changes,
|
|
50
|
+
reason: entry.reason,
|
|
51
|
+
note: entry.note,
|
|
52
|
+
trigger: entry.trigger,
|
|
53
|
+
})),
|
|
54
|
+
timelineTruncated: doc.statusHistoryTruncated,
|
|
55
|
+
previousOfferId: doc.previousOfferId,
|
|
56
|
+
supersededByOfferId: doc.supersededByOfferId,
|
|
57
|
+
chainRootOfferId: doc.chainRootOfferId,
|
|
58
|
+
counterRound: doc.counterRound,
|
|
59
|
+
superseded,
|
|
60
|
+
cancelledByAdminUid: doc.cancelledByAdminUid,
|
|
61
|
+
cancelReason: doc.cancelReason,
|
|
62
|
+
...(opts.includeBuyerIdentity
|
|
63
|
+
? { buyerUid: doc.buyerUid, buyerName: doc.buyerName, buyerEmail: doc.buyerEmail }
|
|
64
|
+
: {}),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A chain round — the compact shape the timeline needs, without re-sending
|
|
69
|
+
* the whole document for every round.
|
|
70
|
+
*
|
|
71
|
+
* Buyer identity is never included: the chain is rendered on all three
|
|
72
|
+
* portals from one component, and the seller's view must not gain identity
|
|
73
|
+
* it is masked from elsewhere.
|
|
74
|
+
*/
|
|
75
|
+
export function offerToChainRound(doc) {
|
|
76
|
+
return {
|
|
77
|
+
id: doc.id,
|
|
78
|
+
counterRound: doc.counterRound ?? 1,
|
|
79
|
+
status: doc.status,
|
|
80
|
+
offerAmount: doc.offerAmount,
|
|
81
|
+
counterAmount: doc.counterAmount,
|
|
82
|
+
superseded: doc.status === "withdrawn" && Boolean(doc.supersededByOfferId),
|
|
83
|
+
createdAt: toIso(doc.createdAt),
|
|
84
|
+
respondedAt: toIsoOrUndefined(doc.respondedAt),
|
|
85
|
+
sellerNote: doc.sellerNote,
|
|
86
|
+
buyerNote: doc.buyerNote,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { offerDocumentToOffer, offerToChainRound, } from "./adapters";
|
|
@@ -104,6 +104,30 @@ export function orderDocumentToOrder(doc) {
|
|
|
104
104
|
paymentReviewOutcome: doc.paymentReviewOutcome,
|
|
105
105
|
paymentReviewNote: doc.paymentReviewNote,
|
|
106
106
|
cancellationReason: doc.cancellationReason,
|
|
107
|
+
// ── W2: history + provenance ──────────────────────────────────────────
|
|
108
|
+
//
|
|
109
|
+
// `Order.timeline` has existed, been exported, and had ZERO writers since
|
|
110
|
+
// it was declared — `OrderStatusTimeline` synthesised its steps from four
|
|
111
|
+
// scalar dates instead, so a status change with no dedicated date field
|
|
112
|
+
// (payment reviewed, refund posted) was simply invisible.
|
|
113
|
+
//
|
|
114
|
+
// `statusHistory` is that field's real source. Dates are serialised to
|
|
115
|
+
// ISO here for the same reason every other date on this shape is: the
|
|
116
|
+
// client receives JSON, and a raw `Date` arrives as a string that no
|
|
117
|
+
// longer satisfies the type.
|
|
118
|
+
timeline: doc.statusHistory?.map((entry) => ({
|
|
119
|
+
at: entry.at instanceof Date ? entry.at.toISOString() : String(entry.at),
|
|
120
|
+
actorUid: entry.actorUid,
|
|
121
|
+
actorRole: entry.actorRole,
|
|
122
|
+
changes: entry.changes,
|
|
123
|
+
reason: entry.reason,
|
|
124
|
+
note: entry.note,
|
|
125
|
+
trigger: entry.trigger,
|
|
126
|
+
})),
|
|
127
|
+
/** Entries trimmed off the front — so the UI never implies "this is all of it". */
|
|
128
|
+
timelineTruncated: doc.statusHistoryTruncated,
|
|
129
|
+
/** How the buyer acquired the right to buy. Written once, at creation. */
|
|
130
|
+
sourceContext: doc.sourceContext,
|
|
107
131
|
createdAt: doc.createdAt instanceof Date
|
|
108
132
|
? doc.createdAt.toISOString()
|
|
109
133
|
: String(doc.createdAt),
|