@mohasinac/appkit 4.30.18 → 4.31.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/digital-code/CodeRevealPanel.js +5 -2
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +3 -3
- package/dist/_internal/client/features/layout/useSidebarSearch.d.ts +21 -5
- package/dist/_internal/client/features/layout/useSidebarSearch.js +27 -6
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +23 -3
- package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +106 -86
- package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +16 -5
- package/dist/_internal/client/features/lottery/LotteryPullForm.js +65 -40
- package/dist/_internal/client/features/maintenance/views/AnalysisRunnerView.js +5 -2
- package/dist/_internal/client/features/maintenance/views/CloudLogsListView.js +11 -3
- package/dist/_internal/client/hand-mode/HandModeProvider.js +2 -0
- package/dist/_internal/server/features/auctions/actions.js +14 -3
- package/dist/_internal/server/features/auctions/service.js +1 -1
- package/dist/_internal/server/features/auth/permissions.d.ts +2 -0
- package/dist/_internal/server/features/auth/permissions.js +3 -2
- package/dist/_internal/server/features/blog/data.js +2 -2
- package/dist/_internal/server/features/blog/service.js +3 -3
- package/dist/_internal/server/features/brands/data.js +1 -1
- package/dist/_internal/server/features/brands/service.js +3 -3
- package/dist/_internal/server/features/bundles/actions.js +6 -1
- package/dist/_internal/server/features/bundles/data.js +21 -4
- package/dist/_internal/server/features/cart/data.js +3 -1
- package/dist/_internal/server/features/cart/service.js +13 -2
- package/dist/_internal/server/features/categories/data.js +26 -6
- package/dist/_internal/server/features/classified/index.d.ts +0 -1
- package/dist/_internal/server/features/classified/index.js +0 -1
- package/dist/_internal/server/features/digital-code/index.d.ts +0 -1
- package/dist/_internal/server/features/digital-code/index.js +0 -1
- package/dist/_internal/server/features/events/actions.js +17 -4
- package/dist/_internal/server/features/events/data.js +1 -1
- package/dist/_internal/server/features/events/service.js +1 -1
- package/dist/_internal/server/features/grouped/data.js +7 -2
- package/dist/_internal/server/features/item-requests/data.js +1 -1
- package/dist/_internal/server/features/live/index.d.ts +0 -1
- package/dist/_internal/server/features/live/index.js +0 -1
- package/dist/_internal/server/features/lottery/actions.js +2 -2
- package/dist/_internal/server/features/lottery/data.js +1 -1
- package/dist/_internal/server/features/orders/actions.js +7 -7
- package/dist/_internal/server/features/orders/data.d.ts +1 -1
- package/dist/_internal/server/features/orders/data.js +14 -2
- package/dist/_internal/server/features/orders/service.js +1 -1
- package/dist/_internal/server/features/pre-orders/service.js +1 -1
- package/dist/_internal/server/features/prize-draws/actions.js +1 -1
- package/dist/_internal/server/features/products/data.js +21 -6
- package/dist/_internal/server/features/products/list-public.d.ts +9 -0
- package/dist/_internal/server/features/products/list-public.js +95 -7
- package/dist/_internal/server/features/products/service.js +1 -1
- package/dist/_internal/server/features/promotions/actions.js +1 -1
- package/dist/_internal/server/features/promotions/data.js +1 -1
- package/dist/_internal/server/features/promotions/service.js +1 -1
- package/dist/_internal/server/features/reviews/data.d.ts +1 -1
- package/dist/_internal/server/features/reviews/data.js +6 -1
- package/dist/_internal/server/features/reviews/og-data.js +1 -1
- package/dist/_internal/server/features/shared/listing-data-factory.js +7 -2
- package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
- package/dist/_internal/server/features/site-settings/adapters.js +8 -5
- package/dist/_internal/server/features/stores/data.js +1 -1
- package/dist/_internal/server/features/sublisting-categories/data.js +1 -1
- package/dist/_internal/server/features/tester/visibility.d.ts +2 -1
- package/dist/_internal/server/features/tester/visibility.js +2 -2
- package/dist/_internal/server/functions/scheduled.d.ts +3 -1
- package/dist/_internal/server/functions/scheduled.js +27 -1
- package/dist/_internal/server/jobs/core/auctionSettlement.js +6 -1
- package/dist/_internal/server/jobs/core/hardBanCascade.js +4 -0
- package/dist/_internal/server/jobs/core/index.d.ts +2 -0
- package/dist/_internal/server/jobs/core/index.js +2 -0
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +7 -15
- package/dist/_internal/server/jobs/core/pageViewPrune.d.ts +10 -0
- package/dist/_internal/server/jobs/core/pageViewPrune.js +44 -0
- package/dist/_internal/server/jobs/core/pageViewRollup.d.ts +2 -0
- package/dist/_internal/server/jobs/core/pageViewRollup.js +87 -0
- package/dist/_internal/server/jobs/core/revenueRollup.js +7 -1
- package/dist/_internal/server/jobs/handlers/index.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/index.js +2 -0
- package/dist/_internal/server/jobs/handlers/pageViewPrune.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/pageViewPrune.js +2 -0
- package/dist/_internal/server/jobs/handlers/pageViewRollup.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/pageViewRollup.js +2 -0
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +69 -22
- package/dist/_internal/shared/checkout/rules/classified.rule.d.ts +9 -4
- package/dist/_internal/shared/checkout/rules/classified.rule.js +7 -2
- package/dist/_internal/shared/features/layout/matchesNavQuery.d.ts +14 -0
- package/dist/_internal/shared/features/layout/matchesNavQuery.js +72 -0
- package/dist/_internal/shared/features/layout/types.d.ts +37 -1
- package/dist/_internal/shared/features/layout/types.js +19 -1
- package/dist/_internal/shared/features/notifications/action-url.d.ts +9 -1
- package/dist/_internal/shared/features/notifications/action-url.js +47 -0
- package/dist/_internal/shared/features/offers/config.d.ts +65 -0
- package/dist/_internal/shared/features/offers/config.js +73 -2
- package/dist/_internal/shared/features/orders/schema.d.ts +19 -1
- package/dist/_internal/shared/features/orders/schema.js +22 -2
- package/dist/_internal/shared/features/site-settings/types.d.ts +12 -3
- package/dist/_internal/shared/listing-types/capabilities.d.ts +8 -2
- package/dist/_internal/shared/listing-types/capabilities.js +6 -1
- package/dist/_internal/shared/listing-types/classified/ctas.js +6 -1
- package/dist/_internal/shared/listing-types/feature-flags.d.ts +10 -5
- package/dist/_internal/shared/listing-types/feature-flags.js +11 -6
- package/dist/client/api/useApiQuery.js +17 -6
- package/dist/client.d.ts +38 -20
- package/dist/client.js +39 -14
- package/dist/configs/next.js +10 -2
- package/dist/constants/api-endpoints.d.ts +18 -54
- package/dist/constants/api-endpoints.js +6 -26
- package/dist/constants/field-names.d.ts +6 -24
- package/dist/constants/field-names.js +10 -27
- package/dist/constants/geo/countries.d.ts +50 -0
- package/dist/constants/geo/countries.js +129 -0
- package/dist/constants/geo/subdivisions.d.ts +13 -0
- package/dist/constants/geo/subdivisions.js +104 -0
- package/dist/constants/index.d.ts +2 -2
- package/dist/constants/index.js +2 -2
- package/dist/constants/table-keys.d.ts +24 -0
- package/dist/constants/table-keys.js +28 -0
- package/dist/contracts/client-realtime.d.ts +6 -0
- package/dist/contracts/extend.d.ts +0 -9
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/realtime-session.d.ts +12 -12
- package/dist/contracts/realtime-session.js +79 -77
- package/dist/core/browser.d.ts +1 -1
- package/dist/core/browser.js +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/site-config.d.ts +0 -3
- package/dist/core/site-config.js +0 -3
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/errors/messages.d.ts +0 -8
- package/dist/errors/messages.js +0 -9
- package/dist/features/about/components/DeveloperView.js +7 -2
- package/dist/features/about/components/PolicyPageView.js +9 -1
- package/dist/features/about/components/PublicProfileView.js +23 -5
- package/dist/features/about/schemas/index.d.ts +8 -8
- package/dist/features/account/components/AddressFilters.js +32 -11
- package/dist/features/account/components/AddressForm.d.ts +26 -25
- package/dist/features/account/components/AddressForm.js +81 -103
- package/dist/features/account/components/AddressesIndexListing.js +8 -4
- package/dist/features/account/components/NotificationBell.js +4 -3
- package/dist/features/account/components/NotificationPreferencesPanel.js +1 -1
- package/dist/features/account/components/UserOffersPanel.js +1 -1
- package/dist/features/account/components/UserSidebar.d.ts +3 -4
- package/dist/features/account/components/UserSupportView.js +89 -58
- package/dist/features/account/components/index.d.ts +1 -7
- package/dist/features/account/components/index.js +0 -3
- package/dist/features/account/hooks/useAddresses.d.ts +4 -3
- package/dist/features/account/hooks/useAddresses.js +4 -6
- package/dist/features/account/hooks/useCollapsedSections.d.ts +51 -10
- package/dist/features/account/hooks/useCollapsedSections.js +211 -38
- package/dist/features/account/hooks/useProfile.d.ts +8 -0
- package/dist/features/account/index.d.ts +0 -3
- package/dist/features/account/index.js +0 -3
- package/dist/features/account/schemas/index.d.ts +0 -92
- package/dist/features/account/schemas/index.js +42 -20
- package/dist/features/addresses/components/AddressLocationFields.d.ts +13 -0
- package/dist/features/addresses/components/AddressLocationFields.js +41 -0
- package/dist/features/addresses/hooks/usePostalLookup.d.ts +17 -0
- package/dist/features/addresses/hooks/usePostalLookup.js +133 -0
- package/dist/features/addresses/schemas/address-form.d.ts +423 -0
- package/dist/features/addresses/schemas/address-form.js +212 -0
- package/dist/features/addresses/schemas/index.d.ts +1 -0
- package/dist/features/addresses/schemas/index.js +8 -0
- package/dist/features/admin/actions/admin-read-actions.d.ts +1 -1
- package/dist/features/admin/actions/index.d.ts +0 -1
- package/dist/features/admin/actions/index.js +0 -1
- package/dist/features/admin/actions/notification-actions.js +1 -41
- package/dist/features/admin/components/AdminActionIndexView.d.ts +32 -0
- package/dist/features/admin/components/AdminActionIndexView.js +128 -0
- package/dist/features/admin/components/AdminAdEditorView.js +159 -163
- package/dist/features/admin/components/AdminAddressEditorView.js +97 -55
- package/dist/features/admin/components/AdminBrandEditorView.d.ts +15 -0
- package/dist/features/admin/components/AdminBrandEditorView.js +113 -77
- package/dist/features/admin/components/AdminBundleEditorView.d.ts +19 -9
- package/dist/features/admin/components/AdminBundleEditorView.js +136 -168
- package/dist/features/admin/components/AdminCategoryEditorView.js +120 -43
- package/dist/features/admin/components/AdminCouponEditorView.js +145 -109
- package/dist/features/admin/components/AdminEmployeeEditorView.js +125 -56
- package/dist/features/admin/components/AdminFaqEditorView.js +112 -58
- package/dist/features/admin/components/AdminFeatureEditorView.js +108 -68
- package/dist/features/admin/components/AdminFulfillmentView.js +5 -2
- package/dist/features/admin/components/AdminMediaView.js +3 -3
- package/dist/features/admin/components/AdminNavEditorView.js +69 -44
- package/dist/features/admin/components/AdminOrderEditorView.js +47 -10
- package/dist/features/admin/components/AdminPrizeDrawsView.js +16 -2
- package/dist/features/admin/components/AdminSidebar.d.ts +11 -7
- package/dist/features/admin/components/AdminSiteSettingsView.js +37 -37
- package/dist/features/admin/components/AdminStoreEditorView.js +75 -52
- package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +71 -30
- package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +95 -65
- package/dist/features/admin/components/BrandQuickCreateForm.d.ts +10 -0
- package/dist/features/admin/components/BrandQuickCreateForm.js +49 -26
- package/dist/features/admin/components/CategoryQuickCreateForm.d.ts +11 -0
- package/dist/features/admin/components/CategoryQuickCreateForm.js +48 -26
- package/dist/features/admin/components/index.d.ts +2 -2
- package/dist/features/admin/components/index.js +1 -1
- package/dist/features/admin/constants/site-settings-tabs.d.ts +120 -0
- package/dist/features/admin/constants/site-settings-tabs.js +152 -0
- package/dist/features/admin/index.d.ts +0 -3
- package/dist/features/admin/index.js +0 -2
- package/dist/features/admin/repository/analytics-rollup.repository.d.ts +35 -0
- package/dist/features/admin/repository/analytics-rollup.repository.js +30 -0
- package/dist/features/admin/schemas/admin-editor-forms.d.ts +56 -57
- package/dist/features/admin/schemas/admin-editor-forms.js +97 -54
- package/dist/features/admin/schemas/admin-ops-forms.d.ts +57 -5
- package/dist/features/admin/schemas/admin-ops-forms.js +104 -20
- package/dist/features/admin/schemas/admin-user-form.js +7 -0
- package/dist/features/admin/schemas/firestore.d.ts +48 -95
- package/dist/features/admin/schemas/firestore.js +15 -151
- package/dist/features/admin/schemas/nav-item-form.js +9 -2
- package/dist/features/admin/server.d.ts +0 -4
- package/dist/features/admin/server.js +0 -2
- package/dist/features/admin/types/index.d.ts +0 -7
- package/dist/features/analytics/repository/page-views.repository.d.ts +14 -0
- package/dist/features/analytics/repository/page-views.repository.js +24 -0
- package/dist/features/analytics/types.d.ts +1 -1
- package/dist/features/analytics/types.js +13 -0
- package/dist/features/auctions/components/AuctionDetailPageView.js +6 -2
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +3 -1
- package/dist/features/auth/actions/index.d.ts +0 -1
- package/dist/features/auth/actions/index.js +0 -1
- package/dist/features/auth/actions/profile-actions.js +4 -3
- package/dist/features/auth/actions/realtime-token-actions.js +1 -12
- package/dist/features/auth/auth-helpers.js +5 -7
- package/dist/features/auth/components/ForgotPasswordView.js +1 -1
- package/dist/features/auth/components/Guards.js +2 -1
- package/dist/features/auth/components/LoginForm.d.ts +0 -2
- package/dist/features/auth/components/LoginForm.js +2 -4
- package/dist/features/auth/components/RegisterForm.js +62 -19
- package/dist/features/auth/components/ResetPasswordView.js +1 -1
- package/dist/features/auth/hooks/useAuth.js +3 -0
- package/dist/features/auth/permissions/constants.d.ts +27 -1
- package/dist/features/auth/role-predicates.d.ts +75 -7
- package/dist/features/auth/role-predicates.js +28 -2
- package/dist/features/auth/schemas/firestore.d.ts +22 -0
- package/dist/features/auth/schemas/index.d.ts +1 -1
- package/dist/features/auth/schemas/index.js +44 -8
- package/dist/features/auth/types/index.d.ts +14 -1
- package/dist/features/blog/api/route.js +10 -2
- package/dist/features/blog/components/BlogIndexListing.js +1 -1
- package/dist/features/blog/hooks/useBlog.js +2 -2
- package/dist/features/blog/repository/blog.repository.js +3 -1
- package/dist/features/blog/schemas/index.d.ts +4 -0
- package/dist/features/blog/schemas/index.js +2 -0
- package/dist/features/blog/types/index.d.ts +1 -1
- package/dist/features/cart/actions/cart-actions.js +13 -4
- package/dist/features/cart/utils/pending-ops.js +1 -1
- package/dist/features/catalogue/components/CatalogueItemEditorView.d.ts +22 -0
- package/dist/features/catalogue/components/CatalogueItemEditorView.js +112 -52
- package/dist/features/catalogue/schemas/validation.d.ts +4 -4
- package/dist/features/catalogue/schemas/validation.js +47 -10
- package/dist/features/categories/components/BrandDetailPageView.js +28 -12
- package/dist/features/categories/components/CategoryDetailPageView.js +37 -20
- package/dist/features/categories/repository/categories.repository.js +3 -1
- package/dist/features/categories/schemas/bundle-form.d.ts +142 -0
- package/dist/features/categories/schemas/bundle-form.js +149 -0
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +10 -1
- package/dist/features/classified/components/ClassifiedContactSellerPanel.js +1 -1
- package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +5 -4
- package/dist/features/classified/components/ClassifiedDetailPageView.js +47 -18
- package/dist/features/consultation/components/ConsultationForm.js +1 -1
- package/dist/features/consultation/schemas/index.js +34 -10
- package/dist/features/corporate/schemas/index.js +36 -15
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +4 -1
- package/dist/features/events/components/EventBanner.js +5 -2
- package/dist/features/events/components/EventOfferCard.js +3 -1
- package/dist/features/events/components/EventPollWidget.js +1 -1
- package/dist/features/events/components/SpinWheelView.js +3 -2
- package/dist/features/filters/FilterPanel.js +3 -3
- package/dist/features/filters/RangeFilter.d.ts +10 -0
- package/dist/features/filters/RangeFilter.js +41 -4
- package/dist/features/grouped/components/GroupedListingEditorView.js +2 -1
- package/dist/features/history/hooks/useHistory.js +29 -27
- package/dist/features/homepage/components/AdSlot.js +3 -1
- package/dist/features/homepage/components/GoogleReviewsSection.js +8 -2
- package/dist/features/homepage/components/MarketplaceHomepageView.js +58 -15
- package/dist/features/homepage/components/SocialFeedSection.js +4 -1
- package/dist/features/homepage/hooks/useBlogArticles.js +1 -1
- package/dist/features/homepage/lib/live-stats.js +8 -1
- package/dist/features/homepage/repository/carousel.repository.js +2 -1
- package/dist/features/layout/BottomActions.js +84 -11
- package/dist/features/layout/BottomActionsContext.d.ts +1 -6
- package/dist/features/layout/BottomActionsContext.js +1 -1
- package/dist/features/layout/hooks/useBottomActions.js +2 -2
- package/dist/features/layout/hooks/useFormBottomActions.d.ts +12 -1
- package/dist/features/layout/hooks/useFormBottomActions.js +12 -6
- package/dist/features/live/components/LiveItemDetailPageView.js +4 -1
- package/dist/features/lottery/schemas/config-write.d.ts +9 -5
- package/dist/features/lottery/schemas/config-write.js +69 -9
- package/dist/features/media/finalize.js +3 -1
- package/dist/features/media/modals/ImageEditor.js +1 -1
- package/dist/features/media/modals/VideoThumbnailSelector.js +5 -2
- package/dist/features/media/modals/VideoTrimModal.js +5 -2
- package/dist/features/media/upload/MediaUploadField.js +2 -2
- package/dist/features/messages/hooks/useConversation.js +18 -4
- package/dist/features/messages/hooks/useConversations.js +25 -8
- package/dist/features/orders/components/RefundRequestView.js +5 -2
- package/dist/features/orders/schemas/buyer-forms.d.ts +6 -3
- package/dist/features/orders/schemas/buyer-forms.js +31 -3
- package/dist/features/orders/schemas/index.d.ts +2 -2
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +3 -1
- package/dist/features/pre-orders/components/PreOrderActionsClient.js +1 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +4 -1
- package/dist/features/products/components/GroupSettingsPanel.js +3 -1
- package/dist/features/products/components/MakeOfferButton.d.ts +13 -2
- package/dist/features/products/components/MakeOfferButton.js +33 -11
- package/dist/features/products/components/PrizeDrawDetailPageView.js +4 -1
- package/dist/features/products/components/ProductDetailActions.js +0 -1
- package/dist/features/products/components/ProductDetailPageView.d.ts +7 -3
- package/dist/features/products/components/ProductDetailPageView.js +16 -7
- package/dist/features/products/components/ShareButton.js +3 -1
- package/dist/features/products/constants/action-defs.d.ts +1 -2
- package/dist/features/products/constants/action-defs.js +40 -43
- package/dist/features/products/repository/loadProductFeatures.js +10 -2
- package/dist/features/products/repository/products.repository.d.ts +5 -1
- package/dist/features/products/repository/products.repository.js +25 -2
- package/dist/features/products/schemas/firestore.d.ts +7 -3
- package/dist/features/products/schemas/product-features.validators.js +3 -0
- package/dist/features/promotions/components/CouponCard.js +11 -8
- package/dist/features/reviews/actions/review-actions.js +8 -1
- package/dist/features/reviews/components/ReviewDetailPageView.js +13 -3
- package/dist/features/reviews/components/ReviewDetailShell.js +3 -1
- package/dist/features/scams/actions/scam-actions.d.ts +9 -1
- package/dist/features/scams/actions/scam-actions.js +52 -12
- package/dist/features/scams/components/SellerTrustBadge.d.ts +1 -1
- package/dist/features/scams/components/SellerTrustBadge.js +13 -0
- package/dist/features/scams/repository/scammer.repository.js +2 -1
- package/dist/features/scams/schemas/firestore.d.ts +15 -1
- package/dist/features/scams/schemas/report-form.d.ts +5 -5
- package/dist/features/scams/schemas/report-form.js +18 -3
- package/dist/features/search/action-index/derive.d.ts +49 -0
- package/dist/features/search/action-index/derive.js +121 -0
- package/dist/features/search/action-index/repository.d.ts +42 -0
- package/dist/features/search/action-index/repository.js +100 -0
- package/dist/features/search/action-index/settings-entries.d.ts +41 -0
- package/dist/features/search/action-index/settings-entries.js +268 -0
- package/dist/features/search/action-index/types.d.ts +81 -0
- package/dist/features/search/action-index/types.js +102 -0
- package/dist/features/search/action-index/validate-entry.d.ts +34 -0
- package/dist/features/search/action-index/validate-entry.js +114 -0
- package/dist/features/search/hooks/useNavSuggestions.d.ts +5 -1
- package/dist/features/search/hooks/useNavSuggestions.js +23 -3
- package/dist/features/search/repository/search.repository.js +3 -1
- package/dist/features/seller/actions/offer-actions.js +43 -19
- package/dist/features/seller/actions/seller-actions.js +29 -5
- package/dist/features/seller/components/CategoryChipPicker.d.ts +9 -0
- package/dist/features/seller/components/CategoryChipPicker.js +12 -0
- package/dist/features/seller/components/FulfillmentView.js +5 -2
- package/dist/features/seller/components/PhysicalLocationModal.js +1 -1
- package/dist/features/seller/components/PrintCenterView.js +3 -1
- package/dist/features/seller/components/SellerAddressesView.js +5 -1
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +83 -43
- package/dist/features/seller/components/SellerArtView.d.ts +14 -7
- package/dist/features/seller/components/SellerArtView.js +4 -119
- package/dist/features/seller/components/SellerBidsView.js +1 -1
- package/dist/features/seller/components/SellerClassifiedView.d.ts +14 -7
- package/dist/features/seller/components/SellerClassifiedView.js +4 -124
- package/dist/features/seller/components/SellerCouponEditorView.d.ts +22 -1
- package/dist/features/seller/components/SellerCouponEditorView.js +91 -45
- package/dist/features/seller/components/SellerCouponsView.js +1 -1
- package/dist/features/seller/components/SellerDigitalCodesView.d.ts +14 -7
- package/dist/features/seller/components/SellerDigitalCodesView.js +4 -126
- package/dist/features/seller/components/SellerGoogleReviewsView.js +2 -2
- package/dist/features/seller/components/SellerListingTypeView.d.ts +66 -0
- package/dist/features/seller/components/SellerListingTypeView.js +277 -0
- package/dist/features/seller/components/SellerLiveView.d.ts +14 -7
- package/dist/features/seller/components/SellerLiveView.js +4 -126
- package/dist/features/seller/components/SellerOrdersView.js +3 -3
- package/dist/features/seller/components/SellerPayoutMethodsView.js +2 -2
- package/dist/features/seller/components/SellerProductShell.d.ts +5 -0
- package/dist/features/seller/components/SellerProductShell.js +15 -5
- package/dist/features/seller/components/SellerProductsView.js +24 -10
- package/dist/features/seller/components/SellerReviewsView.js +47 -16
- package/dist/features/seller/components/SellerShippingConfigsView.js +5 -4
- package/dist/features/seller/components/SellerSidebar.d.ts +3 -6
- package/dist/features/seller/components/SellerStickersView.d.ts +14 -7
- package/dist/features/seller/components/SellerStickersView.js +4 -119
- package/dist/features/seller/components/SellerStoreCategoriesView.js +3 -2
- package/dist/features/seller/components/SellerSupportView.d.ts +31 -0
- package/dist/features/seller/components/SellerSupportView.js +100 -0
- package/dist/features/seller/components/index.d.ts +4 -8
- package/dist/features/seller/components/index.js +2 -4
- package/dist/features/seller/index.d.ts +0 -1
- package/dist/features/seller/index.js +0 -1
- package/dist/features/seller/schemas/coupon-form.d.ts +214 -0
- package/dist/features/seller/schemas/coupon-form.js +155 -23
- package/dist/features/seller/schemas/offer-forms.d.ts +16 -7
- package/dist/features/seller/schemas/offer-forms.js +28 -12
- package/dist/features/shell/FormShell.js +2 -2
- package/dist/features/shell/QuickFormDrawer.js +2 -2
- package/dist/features/shell/SectionForm.d.ts +19 -1
- package/dist/features/shell/SectionForm.js +104 -17
- package/dist/features/shell/build-sections.d.ts +23 -0
- package/dist/features/shell/build-sections.js +106 -8
- package/dist/features/shell/field-ui-meta.d.ts +44 -0
- package/dist/features/shell/field-ui-meta.js +14 -7
- package/dist/features/shell/form-sections.d.ts +46 -0
- package/dist/features/shell/form-sections.js +114 -0
- package/dist/features/shipments/components/AdminShipmentEditorView.js +87 -64
- package/dist/features/shipments/schemas/validation.d.ts +2 -2
- package/dist/features/shipments/schemas/validation.js +44 -13
- package/dist/features/store-extensions/schemas/custom-role-form.js +6 -2
- package/dist/features/store-extensions/schemas/listing-template-form.d.ts +7 -7
- package/dist/features/store-extensions/schemas/payout-method-form.js +14 -0
- package/dist/features/stores/actions/store-query-actions.js +3 -2
- package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -1
- package/dist/features/stores/api/[storeSlug]/products/route.js +3 -1
- package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
- package/dist/features/stores/components/StoreDetailLayoutView.js +12 -3
- package/dist/features/support/repository/support.repository.d.ts +21 -0
- package/dist/features/support/repository/support.repository.js +63 -0
- package/dist/features/support/schemas/firestore.d.ts +27 -2
- package/dist/features/support/schemas/firestore.js +2 -0
- package/dist/features/support/schemas/ticket-create-form.js +7 -0
- package/dist/features/tester/schemas/checklist-item-form.d.ts +43 -0
- package/dist/features/tester/schemas/checklist-item-form.js +109 -0
- package/dist/features/tester/seed-data/blog-tester-seed-data.js +2 -2
- package/dist/features/tester/seed-data/categories-tester-seed-data.js +2 -2
- package/dist/features/tester/seed-data/events-tester-seed-data.js +5 -5
- package/dist/features/tester/seed-data/orders-tester-seed-data.js +2 -2
- package/dist/features/tester/seed-data/products-tester-seed-data.js +48 -49
- package/dist/features/tester/seed-data/stores-tester-seed-data.js +3 -3
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +291 -30
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +51 -14
- package/dist/features/wishlist/hooks/useWishlistToggle.js +8 -1
- package/dist/http/api-handler.js +2 -1
- package/dist/index.d.ts +25 -104
- package/dist/index.js +38 -143
- package/dist/jobs.d.ts +1 -1
- package/dist/jobs.js +1 -1
- package/dist/monitoring/browser.d.ts +0 -2
- package/dist/monitoring/browser.js +12 -1
- package/dist/monitoring/index.d.ts +0 -2
- package/dist/monitoring/index.js +0 -1
- package/dist/next/api/routeHandler.js +9 -4
- package/dist/next/index.d.ts +1 -2
- package/dist/next/index.js +0 -1
- package/dist/next/middleware/index.d.ts +0 -2
- package/dist/next/middleware/index.js +0 -1
- package/dist/next/routing/route-map.d.ts +8 -7
- package/dist/next/routing/route-map.js +10 -3
- package/dist/providers/auth-firebase/session.js +3 -1
- package/dist/providers/db-firebase/admin-app-lite.js +8 -8
- package/dist/providers/db-firebase/admin.js +27 -13
- package/dist/providers/db-firebase/browser-stub.d.ts +1 -11
- package/dist/providers/db-firebase/browser-stub.js +6 -11
- package/dist/providers/db-firebase/index.d.ts +0 -1
- package/dist/providers/db-firebase/index.js +0 -1
- package/dist/providers/db-firebase/rtdb-paths.d.ts +15 -6
- package/dist/providers/db-firebase/rtdb-paths.js +15 -6
- package/dist/providers/db-firebase/rtdb-url.d.ts +27 -0
- package/dist/providers/db-firebase/rtdb-url.js +50 -0
- package/dist/providers/db-firebase/sieve.d.ts +22 -0
- package/dist/providers/firebase-client/realtime.d.ts +20 -0
- package/dist/providers/firebase-client/realtime.js +34 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +1 -1
- package/dist/react/hooks/use-action-dispatch.js +8 -2
- package/dist/react/hooks/useFormStatePreservation.js +3 -1
- package/dist/react/hooks/useListingTypeFlags.d.ts +1 -1
- package/dist/react/hooks/useListingTypeFlags.js +1 -1
- package/dist/react/hooks/usePendingFilters.js +5 -3
- package/dist/react/hooks/usePendingTable.js +15 -3
- package/dist/react/hooks/useRealtimeEvent.js +20 -9
- package/dist/repositories/index.d.ts +0 -1
- package/dist/repositories/index.js +0 -1
- package/dist/schemas/registry.d.ts +197 -232
- package/dist/schemas/registry.js +5 -6
- package/dist/schemas/webhooks/razorpay.d.ts +50 -50
- package/dist/security/authorization.d.ts +9 -0
- package/dist/security/authorization.js +16 -2
- package/dist/security/browser.d.ts +1 -3
- package/dist/security/browser.js +5 -2
- package/dist/security/index.d.ts +1 -3
- package/dist/security/index.js +19 -2
- package/dist/security/pii-encrypt.js +16 -0
- package/dist/security/pii-schemas.d.ts +0 -14
- package/dist/security/pii-schemas.js +7 -15
- package/dist/seed/_helpers/category-forest.js +2 -2
- package/dist/seed/_helpers/media.d.ts +19 -0
- package/dist/seed/_helpers/media.js +75 -0
- package/dist/seed/blog-posts-seed-data.js +17 -17
- package/dist/seed/carousel-slides-seed-data.js +7 -7
- package/dist/seed/cart-seed-data.js +13 -13
- package/dist/seed/categories-seed-data.js +10 -10
- package/dist/seed/events-seed-data.js +24 -24
- package/dist/seed/factories/product.factory.js +4 -4
- package/dist/seed/factories/store.factory.js +3 -3
- package/dist/seed/factories/user.factory.js +2 -2
- package/dist/seed/grouped-listings-seed-data.js +11 -11
- package/dist/seed/homepage-sections-seed-data.js +2 -2
- package/dist/seed/index.d.ts +0 -1
- package/dist/seed/index.js +0 -1
- package/dist/seed/manifest.d.ts +1 -1
- package/dist/seed/manifest.js +0 -5
- package/dist/seed/notifications-seed-data.js +20 -1
- package/dist/seed/orders-seed-data.js +2 -2
- package/dist/seed/products-art-seed-data.js +16 -16
- package/dist/seed/products-auctions-seed-data.js +34 -34
- package/dist/seed/products-classifieds-seed-data.js +35 -37
- package/dist/seed/products-digital-codes-seed-data.js +20 -20
- package/dist/seed/products-live-items-seed-data.js +11 -11
- package/dist/seed/products-preorders-seed-data.js +13 -13
- package/dist/seed/products-prize-draws-seed-data.js +43 -43
- package/dist/seed/products-standard-seed-data.js +54 -54
- package/dist/seed/products-stickers-seed-data.js +15 -15
- package/dist/seed/reviews-seed-data.js +4 -4
- package/dist/seed/scammers-seed-data.js +3 -3
- package/dist/seed/site-settings-seed-data.js +11 -24
- package/dist/seed/store-extensions-seed-data.js +10 -10
- package/dist/seed/stores-seed-data.js +11 -11
- package/dist/seed/support-tickets-seed-data.d.ts +14 -0
- package/dist/seed/support-tickets-seed-data.js +20 -1
- package/dist/seed/users-seed-data.js +20 -20
- package/dist/server-entry.d.ts +0 -1
- package/dist/server-entry.js +0 -1
- package/dist/server.d.ts +9 -6
- package/dist/server.js +7 -13
- package/dist/styles.css +248 -68
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/default-dark.js +2 -2
- package/dist/tokens/themes/default-light.js +2 -2
- package/dist/tokens/tokens.css +24 -4
- package/dist/ui/components/ActionRow.d.ts +50 -0
- package/dist/ui/components/ActionRow.js +53 -0
- package/dist/ui/components/ActionRow.style.css +145 -0
- package/dist/ui/components/Drawer.d.ts +10 -0
- package/dist/ui/components/Drawer.js +2 -1
- package/dist/ui/components/FilterDrawer.js +4 -1
- package/dist/ui/components/FilterDrawer.style.css +6 -12
- package/dist/ui/components/FormActionBar.js +14 -1
- package/dist/ui/components/FormActionBar.style.css +12 -11
- package/dist/ui/components/ListingLayout.js +8 -1
- package/dist/ui/components/ListingLayout.style.css +6 -13
- package/dist/ui/components/Modal.d.ts +15 -1
- package/dist/ui/components/Modal.js +17 -3
- package/dist/ui/components/QuickCreateModal.js +2 -2
- package/dist/ui/components/QuickCreateModal.style.css +78 -84
- package/dist/ui/components/RecordDetailModal.js +2 -2
- package/dist/ui/components/SideDrawer.d.ts +8 -0
- package/dist/ui/components/SideDrawer.js +2 -1
- package/dist/ui/components/SideDrawer.style.css +6 -3
- package/dist/ui/components/SideModal.d.ts +11 -1
- package/dist/ui/components/SideModal.js +3 -2
- package/dist/ui/components/SideModal.style.css +14 -0
- package/dist/ui/components/Typography.style.css +33 -24
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/components/toolbar-collapse.js +1 -2
- package/dist/ui/forms/FormShell.style.css +260 -311
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +1 -0
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.js +1 -1
- package/dist/validation/schemas.d.ts +0 -19
- package/dist/validation/schemas.js +8 -19
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +3 -6
|
@@ -54,6 +54,8 @@ export function HandModeProvider({ initialHand, children }) {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
catch (_err) {
|
|
57
|
+
// localStorage unavailable (private-browse) — fall through to the value
|
|
58
|
+
// readHandPreference() already resolved; there is no preference to honour.
|
|
57
59
|
void normalizeError(_err);
|
|
58
60
|
}
|
|
59
61
|
return stored;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { wrapAction } from "@mohasinac/appkit/server";
|
|
3
|
+
import { safeRead } from "../../../../errors/safe-read";
|
|
3
4
|
import { bidRepository, productRepository, userRepository, siteSettingsRepository } from "../../../../repositories";
|
|
4
5
|
import { requireRoleUser } from "../../../../providers/auth-firebase/helpers";
|
|
5
6
|
import { placeBidActionSchema } from "../../../shared/features/auctions/schema";
|
|
@@ -16,10 +17,20 @@ export async function placeBidAction(input) {
|
|
|
16
17
|
assertNotAuctionOwner(product, user.uid);
|
|
17
18
|
const settings = await siteSettingsRepository.getSingleton();
|
|
18
19
|
assertBidAmount(product, amount, settings.auctionConfig?.bidIncrementTiers ?? []);
|
|
19
|
-
const profile = await userRepository.findById(user.uid)
|
|
20
|
+
const profile = await safeRead(() => userRepository.findById(user.uid), {
|
|
21
|
+
route: "auction:placeBid",
|
|
22
|
+
key: "auctions.placeBid.bidderProfile",
|
|
23
|
+
fallback: null,
|
|
24
|
+
});
|
|
20
25
|
const userName = profile?.displayName ?? user.name ?? "Anonymous";
|
|
21
|
-
//
|
|
22
|
-
|
|
26
|
+
// (Removed: a `setWinningBid("__placeholder__", auctionId)` call whose
|
|
27
|
+
// rejection was swallowed. It accomplished NOTHING. setWinningBid builds a
|
|
28
|
+
// single batch — mark every bid for the product `outbid`, then update the
|
|
29
|
+
// winning bid's own doc — and `__placeholder__` is not a real bid id, so
|
|
30
|
+
// `batch.commit()` always threw and DISCARDED the whole batch, outbid
|
|
31
|
+
// marking included. It cost a full-collection query and an exception per
|
|
32
|
+
// bid placed, and the real `setWinningBid(bid.id, …)` below already marks
|
|
33
|
+
// every other bid for this product as outbid.)
|
|
23
34
|
const bid = await bidRepository.create({
|
|
24
35
|
productId: auctionId,
|
|
25
36
|
productTitle: product.title ?? auctionId,
|
|
@@ -4,7 +4,7 @@ import { AuctionNotFoundError, AuctionEndedError, BidTooLowError, BidOnOwnAuctio
|
|
|
4
4
|
import { AUCTION_SNIPING_WINDOW_SECONDS, AUCTION_DEFAULT_EXTENSION_MINUTES, resolveMinBid, } from "../../../shared/features/auctions/config";
|
|
5
5
|
/** Assert an auction exists, is published, and is still active. Returns the product. */
|
|
6
6
|
export async function assertAuctionActive(auctionId) {
|
|
7
|
-
const product = await productRepository.findByIdOrSlug(auctionId)
|
|
7
|
+
const product = await productRepository.findByIdOrSlug(auctionId);
|
|
8
8
|
if (!product || !isAuctionListing(product))
|
|
9
9
|
throw new AuctionNotFoundError(auctionId);
|
|
10
10
|
const endDate = product.auctionEndDate instanceof Date
|
|
@@ -26,6 +26,8 @@ export declare function checkAnyPermission(resolved: ResolvedPermissions, requir
|
|
|
26
26
|
type GetUser = () => Promise<{
|
|
27
27
|
uid: string;
|
|
28
28
|
role: string;
|
|
29
|
+
permissions?: readonly string[] | null;
|
|
30
|
+
/** @deprecated Legacy tester flags; still read during the migration window. */
|
|
29
31
|
isTester?: boolean;
|
|
30
32
|
canTestAdmin?: boolean;
|
|
31
33
|
} | null>;
|
|
@@ -60,8 +60,9 @@ export function makeAdminSectionLayout(permission, opts) {
|
|
|
60
60
|
redirect(opts.loginPath ?? String(ROUTES.AUTH.LOGIN));
|
|
61
61
|
return null;
|
|
62
62
|
}
|
|
63
|
-
//
|
|
64
|
-
//
|
|
63
|
+
// Admin role, or a tester cleared for admin surfaces (the `tester` role
|
|
64
|
+
// plus `tester:admin-surfaces`, or the legacy isTester/canTestAdmin pair),
|
|
65
|
+
// passes without a permission check.
|
|
65
66
|
if (isEffectiveAdminUser(user))
|
|
66
67
|
return children;
|
|
67
68
|
// non-employee non-admin roles have no business in /admin
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { cache } from "react";
|
|
2
2
|
import { blogRepository } from "../../../../repositories";
|
|
3
3
|
export const getBlogPostForDetail = cache(async (slug) => {
|
|
4
|
-
return (await blogRepository.findBySlug(slug)
|
|
4
|
+
return (await blogRepository.findBySlug(slug)) ?? null;
|
|
5
5
|
});
|
|
6
6
|
export const getBlogPostById = cache(async (id) => {
|
|
7
|
-
return (await blogRepository.findById(id)
|
|
7
|
+
return (await blogRepository.findById(id)) ?? null;
|
|
8
8
|
});
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { blogRepository } from "../../../../repositories";
|
|
2
2
|
import { BlogPostNotFoundError, BlogSlugConflictError } from "../../../shared/features/blog/errors";
|
|
3
3
|
export async function assertBlogPostExists(slugOrId) {
|
|
4
|
-
const post = await blogRepository.findBySlug(slugOrId)
|
|
5
|
-
?? await blogRepository.findById(slugOrId)
|
|
4
|
+
const post = await blogRepository.findBySlug(slugOrId)
|
|
5
|
+
?? await blogRepository.findById(slugOrId);
|
|
6
6
|
if (!post)
|
|
7
7
|
throw new BlogPostNotFoundError(slugOrId);
|
|
8
8
|
return post;
|
|
9
9
|
}
|
|
10
10
|
export async function assertBlogSlugUnique(slug) {
|
|
11
|
-
const existing = await blogRepository.findBySlug(slug)
|
|
11
|
+
const existing = await blogRepository.findBySlug(slug);
|
|
12
12
|
if (existing)
|
|
13
13
|
throw new BlogSlugConflictError(slug);
|
|
14
14
|
}
|
|
@@ -6,7 +6,7 @@ import { categoriesRepository } from "../../../../repositories";
|
|
|
6
6
|
* `BrandDetailPageView` consume the same `CategoryDocument` shape.
|
|
7
7
|
*/
|
|
8
8
|
export const getBrandForDetail = cache(async (slug) => {
|
|
9
|
-
return categoriesRepository.findBySlugAndType(slug, "brand")
|
|
9
|
+
return categoriesRepository.findBySlugAndType(slug, "brand");
|
|
10
10
|
});
|
|
11
11
|
/**
|
|
12
12
|
* @deprecated Identical to getBrandForDetail after SB-UNI-C. Kept as an
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { categoriesRepository } from "../../../../repositories";
|
|
2
2
|
import { BrandNotFoundError, BrandSlugConflictError } from "../../../shared/features/brands/errors";
|
|
3
3
|
export async function assertBrandExists(slugOrId) {
|
|
4
|
-
const brand = (await categoriesRepository.findBySlugAndType(slugOrId, "brand")
|
|
5
|
-
(await categoriesRepository.findById(slugOrId)
|
|
4
|
+
const brand = (await categoriesRepository.findBySlugAndType(slugOrId, "brand")) ??
|
|
5
|
+
(await categoriesRepository.findById(slugOrId));
|
|
6
6
|
if (!brand || brand.categoryType !== "brand")
|
|
7
7
|
throw new BrandNotFoundError(slugOrId);
|
|
8
8
|
return brand;
|
|
9
9
|
}
|
|
10
10
|
export async function assertBrandSlugUnique(slug) {
|
|
11
|
-
const existing = await categoriesRepository.findBySlugAndType(slug, "brand")
|
|
11
|
+
const existing = await categoriesRepository.findBySlugAndType(slug, "brand");
|
|
12
12
|
if (existing)
|
|
13
13
|
throw new BrandSlugConflictError(slug);
|
|
14
14
|
}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* helpers can fan out stock decrements to member products.
|
|
14
14
|
*/
|
|
15
15
|
import { NotFoundError, ValidationError } from "../../../../errors";
|
|
16
|
+
import { safeRead } from "../../../../errors/safe-read";
|
|
16
17
|
import { categoriesRepository } from "../../../../repositories";
|
|
17
18
|
import { cartRepository } from "../../../../features/cart/repository/cart.repository";
|
|
18
19
|
import { assertCanAddNewItems } from "../../../../features/cart/actions/cart-actions";
|
|
@@ -55,7 +56,11 @@ quantity = 1) {
|
|
|
55
56
|
// treating that as a stock quantity would silently change how much a
|
|
56
57
|
// prize-draw member decrements, which the stock fan-out has never done.
|
|
57
58
|
const memberIds = bundle.bundleProductIds ?? [];
|
|
58
|
-
const memberDocs = await Promise.all(memberIds.map((id) => productRepository.findById(id)
|
|
59
|
+
const memberDocs = await Promise.all(memberIds.map((id) => safeRead(() => productRepository.findById(id), {
|
|
60
|
+
route: "/bundles",
|
|
61
|
+
key: "bundles.addBundleToCart.member",
|
|
62
|
+
fallback: null,
|
|
63
|
+
})));
|
|
59
64
|
const groupMembers = memberDocs
|
|
60
65
|
.filter((p) => p !== null)
|
|
61
66
|
.map((p) => ({
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { cache } from "react";
|
|
9
9
|
import { categoriesRepository } from "../../../../repositories";
|
|
10
10
|
import { productRepository } from "../../../../repositories";
|
|
11
|
+
import { safeRead } from "../../../../errors/safe-read";
|
|
11
12
|
/**
|
|
12
13
|
* Fetch a single bundle by slug for the public detail page. Returns null
|
|
13
14
|
* when the slug is empty or no matching `categoryType:"bundle"` row exists.
|
|
@@ -43,7 +44,11 @@ export const listBundleMembers = cache(async (bundle, _opts) => {
|
|
|
43
44
|
const ids = resolveBundleMemberIds(bundle);
|
|
44
45
|
if (ids.length === 0)
|
|
45
46
|
return [];
|
|
46
|
-
const results = await Promise.all(ids.map((id) => productRepository.findById(id)
|
|
47
|
+
const results = await Promise.all(ids.map((id) => safeRead(() => productRepository.findById(id), {
|
|
48
|
+
route: "/bundles",
|
|
49
|
+
key: "bundles.listBundleMembers.member",
|
|
50
|
+
fallback: null,
|
|
51
|
+
})));
|
|
47
52
|
return results.filter((p) => p !== null);
|
|
48
53
|
});
|
|
49
54
|
/**
|
|
@@ -58,7 +63,11 @@ export const listBundleMembers = cache(async (bundle, _opts) => {
|
|
|
58
63
|
export async function resolveBundleOriginalTotal(productIds) {
|
|
59
64
|
if (productIds.length === 0)
|
|
60
65
|
return undefined;
|
|
61
|
-
const results = await Promise.all(productIds.map((id) => productRepository.findById(id)
|
|
66
|
+
const results = await Promise.all(productIds.map((id) => safeRead(() => productRepository.findById(id), {
|
|
67
|
+
route: "/bundles",
|
|
68
|
+
key: "bundles.resolveBundleOriginalTotal.member",
|
|
69
|
+
fallback: null,
|
|
70
|
+
})));
|
|
62
71
|
const prices = [];
|
|
63
72
|
for (const p of results) {
|
|
64
73
|
if (!p || typeof p.price !== "number")
|
|
@@ -89,7 +98,11 @@ export async function resolveBundleOriginalTotal(productIds) {
|
|
|
89
98
|
export async function findBundleMemberStores(productIds) {
|
|
90
99
|
if (productIds.length === 0)
|
|
91
100
|
return [];
|
|
92
|
-
const results = await Promise.all(productIds.map((id) => productRepository.findById(id)
|
|
101
|
+
const results = await Promise.all(productIds.map((id) => safeRead(() => productRepository.findById(id), {
|
|
102
|
+
route: "/bundles",
|
|
103
|
+
key: "bundles.findBundleMemberStores.member",
|
|
104
|
+
fallback: null,
|
|
105
|
+
})));
|
|
93
106
|
const stores = new Set();
|
|
94
107
|
for (const p of results) {
|
|
95
108
|
// An unresolvable member says nothing about seller spread — the price
|
|
@@ -118,7 +131,11 @@ export async function findBundleMemberStores(productIds) {
|
|
|
118
131
|
export async function resolveBundleCategorySlugs(productIds) {
|
|
119
132
|
if (productIds.length === 0)
|
|
120
133
|
return [];
|
|
121
|
-
const results = await Promise.all(productIds.map((id) => productRepository.findById(id)
|
|
134
|
+
const results = await Promise.all(productIds.map((id) => safeRead(() => productRepository.findById(id), {
|
|
135
|
+
route: "/bundles",
|
|
136
|
+
key: "bundles.resolveBundleCategorySlugs.member",
|
|
137
|
+
fallback: null,
|
|
138
|
+
})));
|
|
122
139
|
const slugs = new Set();
|
|
123
140
|
for (const p of results) {
|
|
124
141
|
for (const slug of p?.categorySlugs ?? [])
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { cache } from "react";
|
|
2
2
|
import { cartRepository } from "../../../../repositories";
|
|
3
3
|
export const getCartForUser = cache(async (userId) => {
|
|
4
|
-
|
|
4
|
+
// No catch: this cart IS the page. Degrading a Firestore failure to null
|
|
5
|
+
// renders an EMPTY CART to someone whose cart is full — money path.
|
|
6
|
+
return (await cartRepository.findByUserId(userId)) ?? null;
|
|
5
7
|
});
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { cartRepository } from "../../../../repositories";
|
|
2
2
|
import { CART_MAX_ITEMS } from "../../../shared/features/cart/config";
|
|
3
3
|
import { CartFullError, CartQuantityError } from "../../../shared/features/cart/errors";
|
|
4
|
+
import { normalizeError } from "../../../../errors/normalize";
|
|
5
|
+
import { serverLogger } from "../../../../monitoring/server-logger";
|
|
4
6
|
export async function assertCartCapacity(userId, addingQty) {
|
|
5
|
-
|
|
7
|
+
// No catch. Swallowing to null made `currentItemCount` 0, so a Firestore
|
|
8
|
+
// failure silently DISABLED the cart cap and let the add through — a guard
|
|
9
|
+
// that fails open. A throw is caught by the action envelope and recorded.
|
|
10
|
+
const cart = await cartRepository.findByUserId(userId);
|
|
6
11
|
const currentItemCount = cart ? (cart.items ?? []).length : 0;
|
|
7
12
|
if (currentItemCount + addingQty > CART_MAX_ITEMS) {
|
|
8
13
|
throw new CartFullError(CART_MAX_ITEMS);
|
|
@@ -20,6 +25,12 @@ export async function upsertCartItem(userId, item) {
|
|
|
20
25
|
}
|
|
21
26
|
export async function mergeGuestItems(userId, guestItems) {
|
|
22
27
|
for (const item of guestItems) {
|
|
23
|
-
|
|
28
|
+
// A WRITE, not a read — safeRead does not apply. Guest-merge is
|
|
29
|
+
// best-effort per item so one bad line cannot lose the whole cart, but a
|
|
30
|
+
// dropped item must be visible rather than silent.
|
|
31
|
+
await cartRepository.addItem(userId, item).catch((err) => {
|
|
32
|
+
void normalizeError(err);
|
|
33
|
+
serverLogger.warn("cart.mergeGuestCart: item dropped", { userId, err });
|
|
34
|
+
});
|
|
24
35
|
}
|
|
25
36
|
}
|
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { cache } from "react";
|
|
3
3
|
import { categoriesRepository } from "../../../../repositories";
|
|
4
|
+
import { safeRead } from "../../../../errors/safe-read";
|
|
4
5
|
import { CATEGORIES_FEATURED_LIMIT, CATEGORIES_MENU_LIMIT, CATEGORIES_SITEMAP_LIMIT } from "../../../shared/features/categories/config";
|
|
5
6
|
/** Full category document by slug — deduped per request via React.cache(). */
|
|
6
7
|
export const getCategoryForDetail = cache(async (slug) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
/*
|
|
9
|
+
* 🛑 No view-count write here — deleted 2026-08-31.
|
|
10
|
+
*
|
|
11
|
+
* This fired `incrementViewCount` on every render, which was two defects at
|
|
12
|
+
* once. It is a Firestore WRITE on the render path (Rule #6), and product
|
|
13
|
+
* and category detail were being counted TWICE by two systems that key
|
|
14
|
+
* differently: this one on the document by id, and the client
|
|
15
|
+
* `PageViewTracker` into `pageViews` by slug. They can never reconcile —
|
|
16
|
+
* they disagree on bots, on prefetch, and on JS-disabled clients — so the
|
|
17
|
+
* two numbers were guaranteed to drift and neither could be trusted.
|
|
18
|
+
*
|
|
19
|
+
* `pageViews` is the single counter now. `viewCount` on the document stays
|
|
20
|
+
* for historical rows; nothing increments it.
|
|
21
|
+
*/
|
|
22
|
+
return (await categoriesRepository.getCategoryBySlug(slug)) ?? null;
|
|
11
23
|
});
|
|
12
24
|
/** Flat list of all categories at tier 1 (roots) — for nav/sitemap. */
|
|
13
25
|
export const listRootCategories = cache(async () => {
|
|
14
|
-
return categoriesRepository.getCategoriesByTier(1)
|
|
26
|
+
return safeRead(() => categoriesRepository.getCategoriesByTier(1), {
|
|
27
|
+
route: "/categories",
|
|
28
|
+
key: "categories.listRootCategories",
|
|
29
|
+
fallback: [],
|
|
30
|
+
});
|
|
15
31
|
});
|
|
16
32
|
/** Featured categories for homepage display (showOnHomepage: true). */
|
|
17
33
|
export const listFeaturedCategories = cache(async () => {
|
|
@@ -29,7 +45,11 @@ export const listMenuCategories = cache(async () => {
|
|
|
29
45
|
});
|
|
30
46
|
/** Full category tree rooted at a given rootId — for sidebar navigation. */
|
|
31
47
|
export const getCategoryTree = cache(async (rootId) => {
|
|
32
|
-
return categoriesRepository.buildTree(rootId)
|
|
48
|
+
return safeRead(() => categoriesRepository.buildTree(rootId), {
|
|
49
|
+
route: "/categories",
|
|
50
|
+
key: "categories.getCategoryTree",
|
|
51
|
+
fallback: [],
|
|
52
|
+
});
|
|
33
53
|
});
|
|
34
54
|
/** Flat category list for sitemap generation. */
|
|
35
55
|
export const listSitemapCategories = cache(async () => {
|
|
@@ -6,6 +6,8 @@ import { eventInputSchema, eventUpdateSchema, registerForEventSchema } from "../
|
|
|
6
6
|
import { assertEventActive } from "./service";
|
|
7
7
|
import { AlreadyRegisteredError, EventNotFoundError } from "../../../shared/features/events/errors";
|
|
8
8
|
import { ValidationError } from "../../../shared/errors/index";
|
|
9
|
+
import { normalizeError } from "../../../../errors/normalize";
|
|
10
|
+
import { serverLogger } from "../../../../monitoring/server-logger";
|
|
9
11
|
export async function createEventAction(input) {
|
|
10
12
|
return wrapAction(async () => {
|
|
11
13
|
const user = await requireRoleUser(["admin", "moderator"]);
|
|
@@ -23,7 +25,7 @@ export async function createEventAction(input) {
|
|
|
23
25
|
export async function updateEventAction(eventId, input) {
|
|
24
26
|
return wrapAction(async () => {
|
|
25
27
|
await requireRoleUser(["admin", "moderator"]);
|
|
26
|
-
const event = await eventRepository.findById(eventId)
|
|
28
|
+
const event = await eventRepository.findById(eventId);
|
|
27
29
|
if (!event)
|
|
28
30
|
throw new EventNotFoundError(eventId);
|
|
29
31
|
const parsed = eventUpdateSchema.safeParse(input);
|
|
@@ -52,15 +54,26 @@ export async function registerForEventAction(input) {
|
|
|
52
54
|
reviewStatus: "pending",
|
|
53
55
|
submittedAt: new Date(),
|
|
54
56
|
});
|
|
55
|
-
// Increment entry count
|
|
56
|
-
|
|
57
|
+
// Increment entry count. The entry document is already written and is the
|
|
58
|
+
// authoritative record, so a failed counter bump must not fail the
|
|
59
|
+
// registration — but it leaves `stats.totalEntries` under-reporting, and
|
|
60
|
+
// the capacity check in assertEventActive reads that mirror, so it has to
|
|
61
|
+
// be visible to an operator rather than dropped (Root Cause #42).
|
|
62
|
+
await eventRepository.incrementTotalEntries(eventId).catch((err) => {
|
|
63
|
+
void normalizeError(err);
|
|
64
|
+
serverLogger.warn("events: incrementTotalEntries failed — stats.totalEntries is now stale", {
|
|
65
|
+
eventId,
|
|
66
|
+
error: err instanceof Error ? err.message : String(err),
|
|
67
|
+
});
|
|
68
|
+
return null;
|
|
69
|
+
});
|
|
57
70
|
return entry;
|
|
58
71
|
});
|
|
59
72
|
}
|
|
60
73
|
export async function cancelEventRegistrationAction(entryId) {
|
|
61
74
|
return wrapAction(async () => {
|
|
62
75
|
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
63
|
-
const entry = await eventEntryRepository.findById(entryId)
|
|
76
|
+
const entry = await eventEntryRepository.findById(entryId);
|
|
64
77
|
if (!entry || entry.userId !== user.uid) {
|
|
65
78
|
throw new ValidationError("Registration not found or does not belong to you");
|
|
66
79
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { eventRepository } from "../../../../repositories";
|
|
2
2
|
import { EventNotFoundError, EventNotActiveError, EventEndedError, EventFullError, } from "../../../shared/features/events/errors";
|
|
3
3
|
export async function assertEventActive(eventId) {
|
|
4
|
-
const event = await eventRepository.findById(eventId)
|
|
4
|
+
const event = await eventRepository.findById(eventId);
|
|
5
5
|
if (!event)
|
|
6
6
|
throw new EventNotFoundError(eventId);
|
|
7
7
|
const status = event.status;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cache } from "react";
|
|
2
2
|
import { getAdminDb } from "../../../../providers/db-firebase";
|
|
3
3
|
import { normalizeError } from "../../../../errors/normalize";
|
|
4
|
+
import { safeRead } from "../../../../errors/safe-read";
|
|
4
5
|
import { serverLogger } from "../../../../monitoring/server-logger";
|
|
5
6
|
import { GROUPED_LISTINGS_COLLECTION, } from "../../../../features/grouped/schemas/firestore";
|
|
6
7
|
import { productRepository, groupedListingsRepository } from "../../../../repositories";
|
|
@@ -70,7 +71,7 @@ export const getGroupedListingWithItems = cache(async (slug) => {
|
|
|
70
71
|
return null;
|
|
71
72
|
const items = [];
|
|
72
73
|
for (const productId of doc.productIds) {
|
|
73
|
-
const product = await productRepository.findByIdOrSlug(productId).
|
|
74
|
+
const product = await safeRead(() => productRepository.findByIdOrSlug(productId), { route: "/groups", key: "grouped.getGroupedListingWithItems.member", fallback: null });
|
|
74
75
|
if (product)
|
|
75
76
|
items.push(product);
|
|
76
77
|
}
|
|
@@ -128,7 +129,11 @@ export const getGroupsWithItemsForProduct = cache(async (productId) => {
|
|
|
128
129
|
const groups = await getGroupsForProduct(productId);
|
|
129
130
|
return Promise.all(groups.map(async (group) => {
|
|
130
131
|
const otherIds = group.productIds.filter((id) => id !== productId);
|
|
131
|
-
const items = await Promise.all(otherIds.map((id) => productRepository.findByIdOrSlug(id)
|
|
132
|
+
const items = await Promise.all(otherIds.map((id) => safeRead(() => productRepository.findByIdOrSlug(id), {
|
|
133
|
+
route: "/products",
|
|
134
|
+
key: "grouped.getGroupsWithItemsForProduct.member",
|
|
135
|
+
fallback: null,
|
|
136
|
+
})));
|
|
132
137
|
return { ...group, items: items.filter((p) => p !== null) };
|
|
133
138
|
}));
|
|
134
139
|
});
|
|
@@ -39,7 +39,7 @@ export async function submitLotteryPullAction(input) {
|
|
|
39
39
|
// Load the event/product to get the lotteryConfig
|
|
40
40
|
let lotteryConfig;
|
|
41
41
|
if (data.sourceType === "event") {
|
|
42
|
-
const event = await eventRepository.findById(sourceId)
|
|
42
|
+
const event = await eventRepository.findById(sourceId);
|
|
43
43
|
if (!event || event.type !== "lottery") {
|
|
44
44
|
throw new LotteryError("LOTTERY_WINDOW_CLOSED", "Lottery event not found or not of type lottery.");
|
|
45
45
|
}
|
|
@@ -52,7 +52,7 @@ export async function submitLotteryPullAction(input) {
|
|
|
52
52
|
lotteryConfig = event.lotteryConfig;
|
|
53
53
|
}
|
|
54
54
|
else {
|
|
55
|
-
const product = await productRepository.findById(sourceId)
|
|
55
|
+
const product = await productRepository.findById(sourceId);
|
|
56
56
|
if (!product || product.listingType !== "prize-draw") {
|
|
57
57
|
throw new LotteryError("LOTTERY_WINDOW_CLOSED", "Prize-draw product not found.");
|
|
58
58
|
}
|
|
@@ -4,7 +4,7 @@ import { lotteryEntryRepository } from "../../../../features/lottery/repository/
|
|
|
4
4
|
import { toClientLotteryConfig } from "./adapters";
|
|
5
5
|
/** Fetch a lottery-type event with price/weight stripped for client use. */
|
|
6
6
|
export const getLotteryEventCached = cache(async (id) => {
|
|
7
|
-
const event = await eventRepository.findById(id)
|
|
7
|
+
const event = await eventRepository.findById(id);
|
|
8
8
|
if (!event || event.type !== "lottery")
|
|
9
9
|
return null;
|
|
10
10
|
return {
|
|
@@ -53,7 +53,7 @@ export async function updateOrderStatusAction(input) {
|
|
|
53
53
|
const parsed = updateOrderStatusSchema.safeParse(input);
|
|
54
54
|
if (!parsed.success)
|
|
55
55
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid input");
|
|
56
|
-
const order = await orderRepository.findById(parsed.data.orderId)
|
|
56
|
+
const order = await orderRepository.findById(parsed.data.orderId);
|
|
57
57
|
if (!order)
|
|
58
58
|
throw new OrderNotFoundError(parsed.data.orderId);
|
|
59
59
|
if (!isAdminUser(user) && order.storeId !== user.uid) {
|
|
@@ -126,7 +126,7 @@ function notifyAdminsOfPaymentProof(order) {
|
|
|
126
126
|
export async function attachPaymentProofAction(orderId, proof) {
|
|
127
127
|
return wrapAction(async () => {
|
|
128
128
|
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
129
|
-
const order = await orderRepository.findById(orderId)
|
|
129
|
+
const order = await orderRepository.findById(orderId);
|
|
130
130
|
if (!order)
|
|
131
131
|
throw new OrderNotFoundError(orderId);
|
|
132
132
|
if (!isAdminUser(user) && order.userId !== user.uid)
|
|
@@ -187,7 +187,7 @@ export async function adminVerifyPaymentAction(orderId) {
|
|
|
187
187
|
if (!isAdminUser(user) && !isModeratorUser(user)) {
|
|
188
188
|
throw new ValidationError("Only admin or moderator can verify payments");
|
|
189
189
|
}
|
|
190
|
-
const order = await orderRepository.findById(orderId)
|
|
190
|
+
const order = await orderRepository.findById(orderId);
|
|
191
191
|
if (!order)
|
|
192
192
|
throw new OrderNotFoundError(orderId);
|
|
193
193
|
if (order.paymentStatus === "paid")
|
|
@@ -226,7 +226,7 @@ export async function adminRequestProofReuploadAction(orderId, note) {
|
|
|
226
226
|
}
|
|
227
227
|
if (!note.trim())
|
|
228
228
|
throw new ValidationError(REASON_REQUIRED_MSG);
|
|
229
|
-
const order = await orderRepository.findById(orderId)
|
|
229
|
+
const order = await orderRepository.findById(orderId);
|
|
230
230
|
if (!order)
|
|
231
231
|
throw new OrderNotFoundError(orderId);
|
|
232
232
|
if (order.paymentStatus === "paid") {
|
|
@@ -275,7 +275,7 @@ export async function adminRejectPaymentAsFraudAction(orderId, note) {
|
|
|
275
275
|
}
|
|
276
276
|
if (!note.trim())
|
|
277
277
|
throw new ValidationError(REASON_REQUIRED_MSG);
|
|
278
|
-
const order = await orderRepository.findById(orderId)
|
|
278
|
+
const order = await orderRepository.findById(orderId);
|
|
279
279
|
if (!order)
|
|
280
280
|
throw new OrderNotFoundError(orderId);
|
|
281
281
|
if (order.paymentStatus === "paid") {
|
|
@@ -317,13 +317,13 @@ export async function raiseOrderDisputeAction(orderId, reason) {
|
|
|
317
317
|
const user = await requireRoleUser(["buyer", "seller", "admin"]);
|
|
318
318
|
if (!reason.trim())
|
|
319
319
|
throw new ValidationError(REASON_REQUIRED_MSG);
|
|
320
|
-
const order = await orderRepository.findById(orderId)
|
|
320
|
+
const order = await orderRepository.findById(orderId);
|
|
321
321
|
if (!order)
|
|
322
322
|
throw new OrderNotFoundError(orderId);
|
|
323
323
|
const isBuyer = order.userId === user.uid;
|
|
324
324
|
let isSeller = false;
|
|
325
325
|
if (!isBuyer && !isAdminUser(user) && !isModeratorUser(user) && order.storeId) {
|
|
326
|
-
const store = await storeRepository.findById(order.storeId)
|
|
326
|
+
const store = await storeRepository.findById(order.storeId);
|
|
327
327
|
isSeller = store?.ownerId === user.uid;
|
|
328
328
|
}
|
|
329
329
|
if (!isBuyer && !isSeller && !isAdminUser(user) && !isModeratorUser(user)) {
|
|
@@ -7,4 +7,4 @@ export declare const getOrdersForBuyer: (userId: string, page?: number, pageSize
|
|
|
7
7
|
totalPages: number;
|
|
8
8
|
hasMore: boolean;
|
|
9
9
|
}>;
|
|
10
|
-
export declare const getRecentOrdersForBuyer: (userId: string) => Promise<
|
|
10
|
+
export declare const getRecentOrdersForBuyer: (userId: string) => Promise<import("../../../..").OrderDocument[]>;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { cache } from "react";
|
|
2
2
|
import { orderRepository } from "../../../../repositories";
|
|
3
|
+
import { safeRead } from "../../../../errors/safe-read";
|
|
3
4
|
export const getOrderForDetail = cache(async (orderId) => {
|
|
4
|
-
|
|
5
|
+
// No catch: this order IS the page. Swallowing a Firestore failure to null
|
|
6
|
+
// renders "order not found" for a datastore outage — the caller cannot tell
|
|
7
|
+
// the two apart, which is Root Cause #59 on the money path. A throw reaches
|
|
8
|
+
// the route/error boundary and is now recorded.
|
|
9
|
+
return (await orderRepository.findById(orderId)) ?? null;
|
|
5
10
|
});
|
|
6
11
|
export const getOrdersForBuyer = cache(async (userId, page = 1, pageSize = 20) => {
|
|
7
12
|
return orderRepository.listForUser(userId, { page, pageSize }).catch(() => ({
|
|
@@ -14,5 +19,12 @@ export const getOrdersForBuyer = cache(async (userId, page = 1, pageSize = 20) =
|
|
|
14
19
|
}));
|
|
15
20
|
});
|
|
16
21
|
export const getRecentOrdersForBuyer = cache(async (userId) => {
|
|
17
|
-
|
|
22
|
+
// Optional: a recent-orders rail. Degrading to empty is right, but it must
|
|
23
|
+
// be VISIBLE — safeRead records a DEGRADED_READ row instead of returning a
|
|
24
|
+
// value indistinguishable from "no recent orders".
|
|
25
|
+
return safeRead(() => orderRepository.findRecentByUser(userId), {
|
|
26
|
+
route: "/user/orders",
|
|
27
|
+
key: "orders.findRecentByUser",
|
|
28
|
+
fallback: [],
|
|
29
|
+
});
|
|
18
30
|
});
|
|
@@ -2,7 +2,7 @@ import { orderRepository } from "../../../../repositories";
|
|
|
2
2
|
import { OrderNotFoundError, OrderCancelError, OrderOwnershipError, OrderReturnWindowError, } from "../../../shared/features/orders/errors";
|
|
3
3
|
import { ORDER_CANCELLABLE_STATUSES, ORDER_RETURN_WINDOW_MS, } from "../../../shared/features/orders/config";
|
|
4
4
|
export async function assertOrderOwnership(orderId, userId) {
|
|
5
|
-
const order = await orderRepository.findById(orderId)
|
|
5
|
+
const order = await orderRepository.findById(orderId);
|
|
6
6
|
if (!order)
|
|
7
7
|
throw new OrderNotFoundError(orderId);
|
|
8
8
|
if (order.userId !== userId)
|
|
@@ -4,7 +4,7 @@ import { roundRupees } from "../../../../utils/number.formatter";
|
|
|
4
4
|
import { PreOrderNotFoundError, PreOrderSoldOutError, PreOrderNotOpenError, } from "../../../shared/features/pre-orders/errors";
|
|
5
5
|
/** Assert a pre-order exists, is published, and has remaining capacity. */
|
|
6
6
|
export async function assertPreOrderAvailable(preOrderId, requestedQty = 1) {
|
|
7
|
-
const product = await productRepository.findByIdOrSlug(preOrderId)
|
|
7
|
+
const product = await productRepository.findByIdOrSlug(preOrderId);
|
|
8
8
|
if (!product || !isPreOrderListing(product))
|
|
9
9
|
throw new PreOrderNotFoundError(preOrderId);
|
|
10
10
|
if (product.status !== "published")
|
|
@@ -9,7 +9,7 @@ export async function enterPrizeDrawAction(input) {
|
|
|
9
9
|
const { prizeDrawId } = input;
|
|
10
10
|
if (!prizeDrawId)
|
|
11
11
|
throw new Error("prizeDrawId is required.");
|
|
12
|
-
const product = await productRepository.findByIdOrSlug(prizeDrawId)
|
|
12
|
+
const product = await productRepository.findByIdOrSlug(prizeDrawId);
|
|
13
13
|
if (!product)
|
|
14
14
|
throw new Error("Prize draw not found.");
|
|
15
15
|
assertPrizeDrawOpen(product);
|