@mohasinac/appkit 4.53.0 โ 4.53.1
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/.build-stamp.json +3 -3
- package/dist/_internal/client/scaffolds/AppShell.js +1 -1
- package/dist/_internal/server/features/auctions/og.d.ts +3 -1
- package/dist/_internal/server/features/auctions/og.js +3 -1
- package/dist/_internal/server/features/bundles/actions.js +1 -1
- package/dist/_internal/server/features/business-documents/download.d.ts +41 -0
- package/dist/_internal/server/features/business-documents/download.js +91 -0
- package/dist/_internal/server/features/categories/adapters.d.ts +1 -1
- package/dist/_internal/server/features/categories/adapters.js +10 -0
- package/dist/_internal/server/features/checkout/actions.d.ts +14 -0
- package/dist/_internal/server/features/checkout/actions.js +106 -12
- package/dist/_internal/server/features/checkout/bundle-expansion.js +17 -0
- package/dist/_internal/server/features/checkout/data.d.ts +22 -0
- package/dist/_internal/server/features/checkout/group-rule-revalidation.d.ts +34 -0
- package/dist/_internal/server/features/checkout/group-rule-revalidation.js +124 -0
- package/dist/_internal/server/features/checkout/supplier-identity.d.ts +55 -0
- package/dist/_internal/server/features/checkout/supplier-identity.js +81 -0
- package/dist/_internal/server/features/classified/metadata.js +1 -1
- package/dist/_internal/server/features/classified/og.d.ts +3 -1
- package/dist/_internal/server/features/classified/og.js +3 -1
- package/dist/_internal/server/features/digital-code/metadata.js +1 -1
- package/dist/_internal/server/features/digital-code/og.d.ts +3 -1
- package/dist/_internal/server/features/digital-code/og.js +3 -1
- package/dist/_internal/server/features/digital-code/pool.d.ts +19 -4
- package/dist/_internal/server/features/digital-code/pool.js +19 -4
- package/dist/_internal/server/features/live/metadata.js +1 -1
- package/dist/_internal/server/features/live/og.d.ts +3 -1
- package/dist/_internal/server/features/live/og.js +3 -1
- package/dist/_internal/server/features/messages/actions.js +1 -1
- package/dist/_internal/server/features/parts/og.js +1 -1
- package/dist/_internal/server/features/pre-orders/og.d.ts +3 -1
- package/dist/_internal/server/features/pre-orders/og.js +3 -1
- package/dist/_internal/server/features/price-index/search.d.ts +18 -0
- package/dist/_internal/server/features/price-index/search.js +47 -7
- package/dist/_internal/server/features/prize-draws/og.d.ts +3 -1
- package/dist/_internal/server/features/prize-draws/og.js +3 -1
- package/dist/_internal/server/features/products/group-members.d.ts +26 -0
- package/dist/_internal/server/features/products/group-members.js +7 -1
- package/dist/_internal/server/features/products/og.d.ts +3 -1
- package/dist/_internal/server/features/products/og.js +3 -1
- package/dist/_internal/server/features/search/scoped-sources.d.ts +26 -0
- package/dist/_internal/server/features/search/scoped-sources.js +252 -0
- package/dist/_internal/server/features/search/search-everything.d.ts +57 -0
- package/dist/_internal/server/features/search/search-everything.js +70 -20
- package/dist/_internal/server/features/seo/sitemap.js +6 -0
- package/dist/_internal/server/features/shared/listing-adapters.js +4 -2
- package/dist/_internal/server/features/sticker-trace/adapters.d.ts +11 -0
- package/dist/_internal/server/features/sticker-trace/adapters.js +1 -0
- package/dist/_internal/server/features/sticker-trace/promote-to-listings.d.ts +26 -0
- package/dist/_internal/server/features/sticker-trace/promote-to-listings.js +264 -0
- package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +3 -1
- package/dist/_internal/server/features/sticker-trace/sheet-actions.js +32 -0
- package/dist/_internal/server/features/sticker-trace/storage.d.ts +20 -1
- package/dist/_internal/server/features/sticker-trace/storage.js +20 -1
- package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
- package/dist/_internal/server/features/stores/adapters.js +16 -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/features/stores/tabs.d.ts +25 -0
- package/dist/_internal/server/features/stores/tabs.js +122 -0
- package/dist/_internal/shared/checkout/rules/_defaults.js +0 -2
- package/dist/_internal/shared/checkout/rules/_limits.d.ts +14 -1
- package/dist/_internal/shared/checkout/rules/_limits.js +14 -1
- package/dist/_internal/shared/checkout/rules/_registry.js +2 -0
- package/dist/_internal/shared/checkout/rules/auction.rule.js +9 -1
- package/dist/_internal/shared/checkout/rules/bundle.rule.js +13 -0
- package/dist/_internal/shared/checkout/rules/index.d.ts +2 -0
- package/dist/_internal/shared/checkout/rules/index.js +9 -0
- package/dist/_internal/shared/checkout/rules/offer.rule.js +0 -1
- package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +26 -0
- package/dist/_internal/shared/checkout/rules/payment-gate.js +133 -0
- package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +29 -8
- package/dist/_internal/shared/checkout/rules/spares.rule.d.ts +16 -0
- package/dist/_internal/shared/checkout/rules/spares.rule.js +5 -0
- package/dist/_internal/shared/checkout/rules/types.d.ts +26 -2
- package/dist/_internal/shared/config/schema.d.ts +122 -0
- package/dist/_internal/shared/features/cart/schema.js +3 -2
- package/dist/_internal/shared/features/products/group-rules.d.ts +75 -0
- package/dist/_internal/shared/features/products/group-rules.js +142 -0
- package/dist/_internal/shared/listing-types/_registry.d.ts +24 -0
- package/dist/_internal/shared/listing-types/_registry.js +39 -1
- package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/art/config.js +2 -0
- package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/auction/config.js +2 -0
- package/dist/_internal/shared/listing-types/availability.js +48 -0
- package/dist/_internal/shared/listing-types/capabilities.js +19 -0
- package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/classified/config.js +2 -0
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/digital-code/config.js +2 -0
- package/dist/_internal/shared/listing-types/feature-flags.js +1 -0
- package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/live/config.js +2 -0
- package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/pre-order/config.js +2 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.js +2 -0
- package/dist/_internal/shared/listing-types/spares/config.d.ts +74 -0
- package/dist/_internal/shared/listing-types/spares/config.js +60 -0
- package/dist/_internal/shared/listing-types/spares/ctas.d.ts +1 -0
- package/dist/_internal/shared/listing-types/spares/ctas.js +4 -0
- package/dist/_internal/shared/listing-types/spares/og.js +1 -0
- package/dist/_internal/shared/listing-types/spares/schema.d.ts +2 -0
- package/dist/_internal/shared/listing-types/spares/schema.js +3 -0
- package/dist/_internal/shared/listing-types/spares/seed-factory.d.ts +1 -0
- package/dist/_internal/shared/listing-types/spares/seed-factory.js +1 -0
- package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/standard/config.js +2 -0
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/stickers/config.js +2 -0
- package/dist/_internal/shared/search/match.d.ts +11 -0
- package/dist/_internal/shared/search/match.js +2 -1
- package/dist/_internal/shared/search/to-groups.d.ts +52 -0
- package/dist/_internal/shared/search/to-groups.js +141 -0
- package/dist/client.d.ts +8 -2
- package/dist/client.js +4 -1
- package/dist/constants/api-endpoints.d.ts +39 -15
- package/dist/constants/api-endpoints.js +28 -5
- package/dist/constants/cache-invalidation.js +3 -1
- package/dist/constants/field-names.d.ts +6 -0
- package/dist/constants/field-names.js +6 -0
- package/dist/features/about/components/PolicyPageView.d.ts +22 -2
- package/dist/features/about/components/PolicyPageView.js +14 -2
- package/dist/features/about/components/PublicProfileView.js +2 -1
- package/dist/features/about/components/ShippingPolicyView.js +42 -2
- package/dist/features/account/components/NotificationBell.js +1 -1
- package/dist/features/account/hooks/useProfileStats.js +5 -1
- package/dist/features/addresses/repository/addresses.repository.d.ts +16 -0
- package/dist/features/addresses/repository/addresses.repository.js +21 -0
- package/dist/features/admin/actions/admin-actions.js +16 -1
- package/dist/features/admin/components/AdminCategoryEditorView.js +19 -2
- package/dist/features/admin/components/AdminNavigationView.js +1 -1
- package/dist/features/admin/components/AdminPageHeader.js +1 -1
- package/dist/features/admin/components/AdminProductEditorView.js +17 -2
- package/dist/features/admin/components/AdminSidebar.js +1 -1
- package/dist/features/admin/components/AdminSiteSettingsView.js +39 -8
- package/dist/features/admin/components/AdminSparesView.d.ts +12 -0
- package/dist/features/admin/components/AdminSparesView.js +30 -0
- package/dist/features/admin/components/AdminUsersView.js +9 -7
- 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.js +7 -0
- package/dist/features/admin/constants/filter-tabs.d.ts +3 -0
- package/dist/features/admin/constants/filter-tabs.js +1 -0
- package/dist/features/admin/schemas/firestore.d.ts +26 -2
- package/dist/features/auctions/components/AuctionDetailPageView.js +4 -11
- package/dist/features/auth/repository/user.repository.d.ts +13 -0
- package/dist/features/auth/repository/user.repository.js +28 -0
- package/dist/features/auth/schemas/firestore.d.ts +2 -0
- package/dist/features/auth/schemas/firestore.js +2 -0
- package/dist/features/business-documents/repository/business-documents.repository.d.ts +58 -0
- package/dist/features/business-documents/repository/business-documents.repository.js +54 -0
- package/dist/features/business-documents/schemas/firestore.d.ts +105 -0
- package/dist/features/business-documents/schemas/firestore.js +75 -0
- package/dist/features/cart/actions/cart-actions.js +83 -6
- package/dist/features/cart/repository/cart.repository.js +32 -4
- package/dist/features/cart/schemas/firestore.d.ts +20 -0
- package/dist/features/cart/schemas/index.d.ts +2 -2
- package/dist/features/catalogue/components/PublicCatalogueItemDetailView.js +1 -1
- package/dist/features/categories/api/[id]/price-guidance/route.d.ts +42 -0
- package/dist/features/categories/api/[id]/price-guidance/route.js +113 -0
- package/dist/features/categories/components/BrandDetailPageView.js +19 -3
- package/dist/features/categories/components/BrandDetailTabs.js +10 -0
- package/dist/features/categories/components/CategoriesIndexListing.js +23 -8
- package/dist/features/categories/components/CategoryDetailPageView.js +141 -14
- package/dist/features/categories/components/CategoryDetailTabs.js +12 -0
- package/dist/features/categories/components/CategoryGrid.js +10 -1
- package/dist/features/categories/components/PriceGuidanceHint.d.ts +29 -0
- package/dist/features/categories/components/PriceGuidanceHint.js +61 -0
- package/dist/features/categories/components/SubcategoryCardRow.d.ts +27 -0
- package/dist/features/categories/components/SubcategoryCardRow.js +98 -0
- package/dist/features/categories/constants/category-tabs.d.ts +20 -25
- package/dist/features/categories/constants/category-tabs.js +22 -39
- package/dist/features/categories/repository/categories.repository.d.ts +12 -0
- package/dist/features/categories/repository/categories.repository.js +20 -0
- package/dist/features/categories/schemas/firestore.d.ts +22 -1
- package/dist/features/categories/schemas/firestore.js +10 -0
- package/dist/features/categories/schemas/index.d.ts +6 -0
- package/dist/features/categories/schemas/index.js +2 -0
- package/dist/features/categories/types/index.d.ts +8 -0
- package/dist/features/categories/utils/taxonomy-visual.d.ts +16 -3
- package/dist/features/categories/utils/taxonomy-visual.js +26 -10
- package/dist/features/classified/components/ClassifiedDetailPageView.js +4 -9
- package/dist/features/contact/components/ContactPageView.d.ts +33 -1
- package/dist/features/contact/components/ContactPageView.js +58 -28
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +4 -9
- package/dist/features/grouped/components/GroupedListingDetailView.js +9 -1
- package/dist/features/grouped/schemas/firestore.d.ts +5 -0
- package/dist/features/homepage/actions/homepage-section-actions.d.ts +3 -3
- package/dist/features/homepage/components/CollectionCardsSection.d.ts +28 -6
- package/dist/features/homepage/components/CollectionCardsSection.js +43 -8
- package/dist/features/homepage/components/HowItWorksSection.d.ts +23 -6
- package/dist/features/homepage/components/HowItWorksSection.js +4 -4
- package/dist/features/homepage/components/PromoGrid.d.ts +31 -2
- package/dist/features/homepage/components/PromoGrid.js +12 -3
- package/dist/features/homepage/components/TestimonialsCarousel.d.ts +34 -2
- package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
- package/dist/features/homepage/components/index.d.ts +0 -20
- package/dist/features/homepage/components/index.js +0 -11
- package/dist/features/homepage/index.d.ts +0 -2
- package/dist/features/homepage/index.js +0 -2
- package/dist/features/homepage/lib/section-renderer.d.ts +9 -0
- package/dist/features/homepage/lib/section-renderer.js +202 -58
- package/dist/features/homepage/repository/homepage-sections.repository.d.ts +35 -3
- package/dist/features/homepage/repository/homepage-sections.repository.js +58 -8
- package/dist/features/homepage/schemas/firestore.d.ts +106 -3
- package/dist/features/homepage/schemas/firestore.js +32 -2
- package/dist/features/homepage/schemas/index.d.ts +36 -7
- package/dist/features/homepage/schemas/index.js +39 -27
- package/dist/features/homepage/server.d.ts +0 -3
- package/dist/features/homepage/server.js +0 -3
- package/dist/features/homepage/types/index.d.ts +0 -47
- package/dist/features/homepage/types/index.js +49 -0
- package/dist/features/layout/AppLayoutShell.js +1 -1
- package/dist/features/layout/BottomNavItem.js +1 -1
- package/dist/features/layout/BottomSheet.js +1 -1
- package/dist/features/layout/TitleBarLayout.js +1 -1
- package/dist/features/live/components/LiveItemDetailPageView.js +4 -9
- package/dist/features/media/hooks/useMedia.js +17 -0
- package/dist/features/media/repository/media-assets.repository.d.ts +46 -0
- package/dist/features/media/repository/media-assets.repository.js +31 -0
- package/dist/features/media/trust-signals.d.ts +85 -0
- package/dist/features/media/trust-signals.js +126 -0
- package/dist/features/parts/components/PartDetailPageView.d.ts +14 -1
- package/dist/features/parts/components/PartDetailPageView.js +2 -2
- package/dist/features/parts/components/PartsIndexPageView.d.ts +11 -2
- package/dist/features/parts/components/PartsIndexPageView.js +2 -2
- package/dist/features/parts/components/PartsSearchBox.d.ts +9 -0
- package/dist/features/parts/components/PartsSearchBox.js +57 -0
- package/dist/features/parts/schemas/firestore.d.ts +149 -3
- package/dist/features/parts/schemas/firestore.js +184 -0
- package/dist/features/payments/repository/payout.repository.d.ts +15 -0
- package/dist/features/payments/repository/payout.repository.js +21 -0
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +4 -11
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +1 -1
- package/dist/features/price-index/components/PriceIndexToolView.d.ts +3 -1
- package/dist/features/price-index/components/PriceIndexToolView.js +92 -13
- package/dist/features/products/components/CompareOverlay.d.ts +18 -1
- package/dist/features/products/components/CompareOverlay.js +21 -2
- package/dist/features/products/components/CustomSectionTabContent.d.ts +31 -0
- package/dist/features/products/components/CustomSectionTabContent.js +29 -3
- package/dist/features/products/components/GroupMemberPicker.d.ts +19 -1
- package/dist/features/products/components/GroupMemberPicker.js +46 -8
- package/dist/features/products/components/GroupSettingsPanel.d.ts +11 -1
- package/dist/features/products/components/GroupSettingsPanel.js +91 -3
- package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
- package/dist/features/products/components/PrizeDrawEntryActions.d.ts +15 -1
- package/dist/features/products/components/PrizeDrawEntryActions.js +70 -8
- package/dist/features/products/components/ProductDetailPageView.js +74 -15
- package/dist/features/products/components/ProductForm.d.ts +13 -1
- package/dist/features/products/components/ProductForm.js +16 -2
- package/dist/features/products/components/ProductsIndexListing.d.ts +16 -1
- package/dist/features/products/components/ProductsIndexListing.js +3 -3
- package/dist/features/products/components/ShowGroupSection.js +15 -2
- package/dist/features/products/components/SparesListView.d.ts +7 -0
- package/dist/features/products/components/SparesListView.js +39 -0
- package/dist/features/products/constants/action-defs.d.ts +1 -0
- package/dist/features/products/constants/action-defs.js +1 -0
- package/dist/features/products/repository/products.repository.d.ts +98 -0
- package/dist/features/products/repository/products.repository.js +235 -17
- package/dist/features/products/schemas/firestore.d.ts +97 -4
- package/dist/features/products/schemas/firestore.js +104 -0
- package/dist/features/products/schemas/index.d.ts +10 -19
- package/dist/features/products/schemas/index.js +23 -6
- package/dist/features/products/types/index.d.ts +45 -1
- package/dist/features/products/utils/group-member-image.d.ts +39 -0
- package/dist/features/products/utils/group-member-image.js +3 -0
- package/dist/features/products/utils/listing-badge-variant.js +4 -0
- package/dist/features/reviews/components/ReviewsList.js +1 -1
- package/dist/features/scams/components/ScamProfileView.js +1 -1
- package/dist/features/search/components/EntityTypeahead.d.ts +44 -0
- package/dist/features/search/components/EntityTypeahead.js +92 -0
- package/dist/features/search/components/Search.d.ts +12 -1
- package/dist/features/search/components/Search.js +47 -3
- package/dist/features/search/components/SearchFacetRail.d.ts +11 -0
- package/dist/features/search/components/SearchFacetRail.js +92 -0
- package/dist/features/search/components/SearchResultsClient.d.ts +33 -0
- package/dist/features/search/components/SearchResultsClient.js +103 -0
- package/dist/features/search/components/SearchResultsPageView.d.ts +15 -1
- package/dist/features/search/components/SearchResultsPageView.js +2 -2
- package/dist/features/search/components/index.d.ts +0 -6
- package/dist/features/search/components/index.js +0 -3
- package/dist/features/search/hooks/useNavSuggestions.d.ts +13 -0
- package/dist/features/search/hooks/useScopedSearch.d.ts +34 -0
- package/dist/features/search/hooks/useScopedSearch.js +114 -0
- package/dist/features/search/hooks/useSiteSearch.d.ts +26 -0
- package/dist/features/search/hooks/useSiteSearch.js +149 -0
- package/dist/features/search/index.d.ts +0 -4
- package/dist/features/search/index.js +0 -4
- package/dist/features/search/manifest.d.ts +12 -0
- package/dist/features/search/manifest.js +17 -2
- package/dist/features/search/server.d.ts +0 -3
- package/dist/features/search/server.js +0 -3
- package/dist/features/seller/components/SellerListingTypeView.d.ts +1 -1
- package/dist/features/seller/components/SellerListingTypeView.js +20 -0
- package/dist/features/seller/components/SellerPayoutSettingsView.js +35 -14
- package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
- package/dist/features/seller/components/SellerProductShell.js +2 -1
- package/dist/features/seller/components/SellerSidebar.js +1 -1
- package/dist/features/seller/components/SellerSparesView.d.ts +17 -0
- package/dist/features/seller/components/SellerSparesView.js +6 -0
- package/dist/features/seller/components/index.d.ts +2 -0
- package/dist/features/seller/components/index.js +1 -0
- package/dist/features/shell/CommandPalette.js +1 -1
- package/dist/features/sticker-trace/schemas/firestore.d.ts +19 -0
- package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
- package/dist/features/stores/components/StoreDetailLayoutView.js +7 -82
- package/dist/features/stores/components/StoreHeader.js +1 -2
- package/dist/features/stores/components/StoreSparesPageView.d.ts +27 -0
- package/dist/features/stores/components/StoreSparesPageView.js +48 -0
- package/dist/features/stores/schemas/firestore.d.ts +19 -0
- package/dist/features/tester/seed-data/authored/buying__spares-and-groups.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/buying__spares-and-groups.js +96 -0
- package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +280 -45
- package/dist/features/tester/seed-data/authored/content-discovery__category-tabs-franchise-bundles.js +54 -32
- package/dist/features/tester/seed-data/authored/content-discovery__parts-database.js +3 -2
- package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.js +73 -0
- package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.js +340 -0
- package/dist/features/tester/seed-data/authored/index.js +16 -0
- package/dist/features/tester/seed-data/authored/search-and-nav__header-search.d.ts +1 -0
- package/dist/features/tester/seed-data/authored/search-and-nav__header-search.js +57 -0
- package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.js +77 -0
- package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.js +58 -0
- package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +5 -4
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +372 -18
- package/dist/index.d.ts +17 -57
- package/dist/index.js +35 -96
- package/dist/next/routing/route-map.d.ts +42 -1
- package/dist/next/routing/route-map.js +45 -0
- package/dist/providers/db-firebase/base.repository.d.ts +22 -0
- package/dist/providers/db-firebase/base.repository.js +36 -0
- package/dist/schemas/registry.d.ts +15 -6
- package/dist/security/blind-index-tokens.d.ts +54 -0
- package/dist/security/blind-index-tokens.js +152 -0
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/settings-encryption.d.ts +35 -0
- package/dist/security/settings-encryption.js +91 -0
- package/dist/seed/_helpers/brand-rows.js +38 -14
- package/dist/seed/_helpers/category-forest.js +73 -7
- package/dist/seed/_helpers/category-images-generated.d.ts +25 -6
- package/dist/seed/_helpers/category-images-generated.js +81 -6
- package/dist/seed/_helpers/category-models.d.ts +1 -1
- package/dist/seed/_helpers/category-models.js +7 -1
- package/dist/seed/_helpers/category-parts-glossary-map.js +8 -0
- package/dist/seed/_helpers/category-parts.d.ts +1 -1
- package/dist/seed/_helpers/category-parts.js +50 -2
- package/dist/seed/_helpers/character-features.d.ts +1 -1
- package/dist/seed/_helpers/character-features.js +2 -1
- package/dist/seed/_helpers/franchise-rows.js +10 -2
- package/dist/seed/_helpers/media.d.ts +47 -0
- package/dist/seed/_helpers/media.js +34 -0
- package/dist/seed/authenticity-knowledge-seed-data.d.ts +49 -5
- package/dist/seed/authenticity-knowledge-seed-data.js +10001 -549
- package/dist/seed/categories-seed-data.js +124 -20
- package/dist/seed/grouped-listings-seed-data.js +16 -0
- package/dist/seed/homepage-sections-seed-data.js +94 -5
- package/dist/seed/index.d.ts +2 -3
- package/dist/seed/index.js +2 -2
- package/dist/seed/manifest.js +3 -0
- package/dist/seed/media-assets-seed-data.d.ts +1 -1
- package/dist/seed/media-assets-seed-data.js +746 -196
- package/dist/seed/model-composition-seed-data.js +122 -6
- package/dist/seed/part-glossary-seed-data.d.ts +1 -1
- package/dist/seed/part-glossary-seed-data.js +37219 -463
- package/dist/seed/products-art-seed-data.js +7 -18
- package/dist/seed/products-auctions-seed-data.js +56 -47
- package/dist/seed/products-beyblade-x-seed-data.d.ts +2 -0
- package/dist/seed/products-beyblade-x-seed-data.js +441 -0
- package/dist/seed/products-catalogue-seed-data.d.ts +5 -5
- package/dist/seed/products-catalogue-seed-data.js +1500 -1240
- package/dist/seed/products-classifieds-seed-data.js +9 -27
- package/dist/seed/products-digital-codes-seed-data.js +9 -18
- package/dist/seed/products-live-items-seed-data.js +5 -13
- package/dist/seed/products-preorders-seed-data.js +67 -33
- package/dist/seed/products-prize-draws-seed-data.js +8 -17
- package/dist/seed/products-spares-seed-data.d.ts +2 -0
- package/dist/seed/products-spares-seed-data.js +368 -0
- package/dist/seed/products-standard-seed-data.js +39 -126
- package/dist/seed/products-stickers-seed-data.js +59 -15
- package/dist/seed/site-settings-seed-data.js +8 -0
- package/dist/seo/json-ld.d.ts +25 -0
- package/dist/seo/json-ld.js +28 -0
- package/dist/server-entry.d.ts +3 -1
- package/dist/server-entry.js +2 -2
- package/dist/server.d.ts +9 -9
- package/dist/server.js +27 -25
- package/dist/styles.css +202 -1
- package/dist/tailwind-input.css +31 -17
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/Accordion.js +1 -1
- package/dist/ui/components/Breadcrumb.js +1 -1
- package/dist/ui/components/DetailPageGallery.js +0 -2
- package/dist/ui/components/DetailPageHero.js +0 -1
- package/dist/ui/components/DetailPageTabs.js +1 -1
- package/dist/ui/components/Divider.js +3 -3
- package/dist/ui/components/GatedPrice.js +5 -1
- package/dist/ui/components/HorizontalScroller.js +1 -1
- package/dist/ui/components/ListingLayout.js +3 -3
- package/dist/ui/components/MediaTabs.style.css +81 -0
- package/dist/ui/components/Pagination.js +1 -1
- package/dist/ui/components/PendingValue.d.ts +45 -0
- package/dist/ui/components/PendingValue.js +7 -0
- package/dist/ui/components/Radio.style.css +119 -0
- package/dist/ui/components/RatingDisplay.js +2 -2
- package/dist/ui/components/SettingsSection.js +0 -2
- package/dist/ui/components/SiteLogo.js +3 -0
- package/dist/ui/components/SiteMark.js +3 -0
- package/dist/ui/components/SortDropdown.js +1 -1
- package/dist/ui/components/SpecTable.d.ts +58 -0
- package/dist/ui/components/SpecTable.js +8 -0
- package/dist/ui/components/StarRating.js +1 -3
- package/dist/ui/components/SummaryCard.js +1 -1
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/icons/icon-registry.d.ts +1 -0
- package/dist/ui/icons/icon-registry.js +9 -1
- package/dist/ui/index.d.ts +4 -0
- package/dist/ui/index.js +2 -0
- package/dist/utils/search-txt-query.d.ts +12 -0
- package/dist/utils/search-txt-query.js +12 -0
- package/package.json +1 -1
- package/scripts/dedupe-peer-deps.mjs +18 -0
- package/scripts/seed-cli.mjs +135 -26
- package/scripts/verify-css-build.mjs +118 -37
- package/dist/_internal/server/features/search/actions.d.ts +0 -7
- package/dist/_internal/server/features/search/actions.js +0 -21
- package/dist/_internal/server/features/search/data.d.ts +0 -15
- package/dist/_internal/server/features/search/data.js +0 -18
- package/dist/_internal/server/features/search/index.d.ts +0 -3
- package/dist/_internal/server/features/search/index.js +0 -2
- package/dist/features/homepage/api/[id]/route.d.ts +0 -23
- package/dist/features/homepage/api/[id]/route.js +0 -103
- package/dist/features/homepage/api/route.d.ts +0 -14
- package/dist/features/homepage/api/route.js +0 -140
- package/dist/features/homepage/api/sections/[id]/route.d.ts +0 -26
- package/dist/features/homepage/api/sections/[id]/route.js +0 -95
- package/dist/features/homepage/api/sections/route.d.ts +0 -13
- package/dist/features/homepage/api/sections/route.js +0 -82
- package/dist/features/homepage/components/AdvertisementBanner.d.ts +0 -14
- package/dist/features/homepage/components/AdvertisementBanner.js +0 -35
- package/dist/features/homepage/components/BeforeAfterCard.d.ts +0 -9
- package/dist/features/homepage/components/BeforeAfterCard.js +0 -73
- package/dist/features/homepage/components/FeaturedResultsSection.d.ts +0 -17
- package/dist/features/homepage/components/FeaturedResultsSection.js +0 -17
- package/dist/features/homepage/components/HeroBanner.d.ts +0 -7
- package/dist/features/homepage/components/HeroBanner.js +0 -43
- package/dist/features/homepage/components/HeroSection.d.ts +0 -7
- package/dist/features/homepage/components/HeroSection.js +0 -6
- package/dist/features/homepage/components/HomepageSkeleton.d.ts +0 -2
- package/dist/features/homepage/components/HomepageSkeleton.js +0 -21
- package/dist/features/homepage/components/HomepageView.d.ts +0 -25
- package/dist/features/homepage/components/HomepageView.js +0 -5
- package/dist/features/homepage/components/NewsletterBanner.d.ts +0 -23
- package/dist/features/homepage/components/NewsletterBanner.js +0 -37
- package/dist/features/homepage/components/SiteFeaturesSection.d.ts +0 -14
- package/dist/features/homepage/components/SiteFeaturesSection.js +0 -11
- package/dist/features/homepage/components/TrustBadges.d.ts +0 -6
- package/dist/features/homepage/components/TrustBadges.js +0 -46
- package/dist/features/homepage/components/TrustIndicatorsSection.d.ts +0 -12
- package/dist/features/homepage/components/TrustIndicatorsSection.js +0 -11
- package/dist/features/homepage/hooks/useHomepage.d.ts +0 -11
- package/dist/features/homepage/hooks/useHomepage.js +0 -17
- package/dist/features/homepage/hooks/useHomepageSections.d.ts +0 -2
- package/dist/features/homepage/hooks/useHomepageSections.js +0 -10
- package/dist/features/homepage/repository/homepage.repository.d.ts +0 -11
- package/dist/features/homepage/repository/homepage.repository.js +0 -25
- package/dist/features/search/actions/index.d.ts +0 -1
- package/dist/features/search/actions/index.js +0 -1
- package/dist/features/search/actions/search-actions.d.ts +0 -18
- package/dist/features/search/actions/search-actions.js +0 -43
- package/dist/features/search/api/route.d.ts +0 -22
- package/dist/features/search/api/route.js +0 -128
- package/dist/features/search/columns/index.d.ts +0 -17
- package/dist/features/search/columns/index.js +0 -49
- package/dist/features/search/components/SearchFiltersRow.d.ts +0 -22
- package/dist/features/search/components/SearchFiltersRow.js +0 -21
- package/dist/features/search/components/SearchResultsSection.d.ts +0 -53
- package/dist/features/search/components/SearchResultsSection.js +0 -35
- package/dist/features/search/components/SearchView.d.ts +0 -27
- package/dist/features/search/components/SearchView.js +0 -8
- package/dist/features/search/hooks/useSearch.d.ts +0 -21
- package/dist/features/search/hooks/useSearch.js +0 -33
- package/dist/features/search/repository/search.repository.d.ts +0 -14
- package/dist/features/search/repository/search.repository.js +0 -59
- package/dist/features/search/schemas/index.d.ts +0 -70
- package/dist/features/search/schemas/index.js +0 -36
- package/dist/features/search/types/index.d.ts +0 -48
- package/dist/features/stores/components/StoreScopedSearch.d.ts +0 -17
- package/dist/features/stores/components/StoreScopedSearch.js +0 -27
- package/dist/seed/defaults/homepage-sections.d.ts +0 -2
- package/dist/seed/defaults/homepage-sections.js +0 -60
- package/dist/seed/factories/homepage-section.factory.d.ts +0 -10
- package/dist/seed/factories/homepage-section.factory.js +0 -13
- /package/dist/{features/search/types/index.js โ _internal/shared/listing-types/spares/og.d.ts} +0 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who is the supplier of record on this order's invoice.
|
|
3
|
+
*
|
|
4
|
+
* โโ The rule โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
5
|
+
*
|
|
6
|
+
* A seller WITH their own GSTIN invoices under it. A seller WITHOUT one
|
|
7
|
+
* invoices under LetItRip's. The official store carries its own, so it is the
|
|
8
|
+
* first case rather than a special case.
|
|
9
|
+
*
|
|
10
|
+
* โโ Why this is one function โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
11
|
+
*
|
|
12
|
+
* ๐ It would be two lines to write `store?.gstin ?? settings.gst?.gstin` at
|
|
13
|
+
* the call site, and that is exactly how Root Cause #75 happened: a money rule
|
|
14
|
+
* described as "the single source of truth" that was reachable by copy-paste,
|
|
15
|
+
* got copied four times, and two copies never learned about a branch added
|
|
16
|
+
* later โ so Razorpay captured the list price for an accepted offer. Grepping
|
|
17
|
+
* for a FUNCTION name finds every caller; grepping for the SHAPE of an
|
|
18
|
+
* expression does not.
|
|
19
|
+
*
|
|
20
|
+
* The three fields also have to move TOGETHER. A GSTIN printed under the wrong
|
|
21
|
+
* legal name is a worse invoice than no GSTIN at all, so this never mixes a
|
|
22
|
+
* seller's GSTIN with the platform's name โ see `resolve` below.
|
|
23
|
+
*
|
|
24
|
+
* โโ Why it is snapshot, not looked up โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
25
|
+
*
|
|
26
|
+
* The caller writes the result onto `OrderDocument.supplierGstin` /
|
|
27
|
+
* `supplierLegalName` / `supplierAddress` at creation and never recomputes it.
|
|
28
|
+
* `OrderDocument`'s own comment is explicit that these are "OUR GST
|
|
29
|
+
* registration as it stood at the moment of supply" โ an admin correcting a
|
|
30
|
+
* typo in the GSTIN must not silently reissue every invoice ever produced.
|
|
31
|
+
*/
|
|
32
|
+
import type { StoreDocument } from "../../../../features/stores/schemas/firestore";
|
|
33
|
+
import type { SiteSettingsDocument } from "../../../../features/admin/schemas/firestore";
|
|
34
|
+
export interface SupplierIdentity {
|
|
35
|
+
gstin?: string;
|
|
36
|
+
legalName?: string;
|
|
37
|
+
address?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Which party the invoice is issued by.
|
|
40
|
+
*
|
|
41
|
+
* Not decoration: the invoice renderers use it to decide whether to say
|
|
42
|
+
* "Tax Invoice", and an operator reading an order needs to know which
|
|
43
|
+
* registration was applied without re-deriving the rule.
|
|
44
|
+
*/
|
|
45
|
+
source: "seller" | "platform" | "none";
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolve the supplier identity for an order from `store`.
|
|
49
|
+
*
|
|
50
|
+
* Returns `source: "none"` when GST is disabled or the platform has no GSTIN
|
|
51
|
+
* configured and the seller has none either. A caller must treat that as "this
|
|
52
|
+
* is not a tax invoice" rather than as an error โ GST is genuinely optional
|
|
53
|
+
* and `siteSettings.gst.enabled` defaults to false.
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveSupplierIdentity(store: Pick<StoreDocument, "gstin" | "legalName" | "registeredAddress"> | null | undefined, settings: Pick<SiteSettingsDocument, "gst"> | null | undefined): SupplierIdentity;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who is the supplier of record on this order's invoice.
|
|
3
|
+
*
|
|
4
|
+
* โโ The rule โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
5
|
+
*
|
|
6
|
+
* A seller WITH their own GSTIN invoices under it. A seller WITHOUT one
|
|
7
|
+
* invoices under LetItRip's. The official store carries its own, so it is the
|
|
8
|
+
* first case rather than a special case.
|
|
9
|
+
*
|
|
10
|
+
* โโ Why this is one function โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
11
|
+
*
|
|
12
|
+
* ๐ It would be two lines to write `store?.gstin ?? settings.gst?.gstin` at
|
|
13
|
+
* the call site, and that is exactly how Root Cause #75 happened: a money rule
|
|
14
|
+
* described as "the single source of truth" that was reachable by copy-paste,
|
|
15
|
+
* got copied four times, and two copies never learned about a branch added
|
|
16
|
+
* later โ so Razorpay captured the list price for an accepted offer. Grepping
|
|
17
|
+
* for a FUNCTION name finds every caller; grepping for the SHAPE of an
|
|
18
|
+
* expression does not.
|
|
19
|
+
*
|
|
20
|
+
* The three fields also have to move TOGETHER. A GSTIN printed under the wrong
|
|
21
|
+
* legal name is a worse invoice than no GSTIN at all, so this never mixes a
|
|
22
|
+
* seller's GSTIN with the platform's name โ see `resolve` below.
|
|
23
|
+
*
|
|
24
|
+
* โโ Why it is snapshot, not looked up โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
25
|
+
*
|
|
26
|
+
* The caller writes the result onto `OrderDocument.supplierGstin` /
|
|
27
|
+
* `supplierLegalName` / `supplierAddress` at creation and never recomputes it.
|
|
28
|
+
* `OrderDocument`'s own comment is explicit that these are "OUR GST
|
|
29
|
+
* registration as it stood at the moment of supply" โ an admin correcting a
|
|
30
|
+
* typo in the GSTIN must not silently reissue every invoice ever produced.
|
|
31
|
+
*/
|
|
32
|
+
const trimmed = (v) => {
|
|
33
|
+
const s = (v ?? "").trim();
|
|
34
|
+
return s.length > 0 ? s : undefined;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the supplier identity for an order from `store`.
|
|
38
|
+
*
|
|
39
|
+
* Returns `source: "none"` when GST is disabled or the platform has no GSTIN
|
|
40
|
+
* configured and the seller has none either. A caller must treat that as "this
|
|
41
|
+
* is not a tax invoice" rather than as an error โ GST is genuinely optional
|
|
42
|
+
* and `siteSettings.gst.enabled` defaults to false.
|
|
43
|
+
*/
|
|
44
|
+
export function resolveSupplierIdentity(store, settings) {
|
|
45
|
+
const sellerGstin = trimmed(store?.gstin);
|
|
46
|
+
/*
|
|
47
|
+
* Seller branch. Taken on the GSTIN alone, and the legal name and address
|
|
48
|
+
* come from the SELLER too โ falling back to the platform's for a missing
|
|
49
|
+
* name would print LetItRip's legal entity beside the seller's registration,
|
|
50
|
+
* which identifies neither party correctly.
|
|
51
|
+
*
|
|
52
|
+
* A seller with a GSTIN and no legal name is a data gap worth seeing as a
|
|
53
|
+
* blank on the invoice, not one worth papering over with the wrong name.
|
|
54
|
+
*/
|
|
55
|
+
if (sellerGstin) {
|
|
56
|
+
return {
|
|
57
|
+
gstin: sellerGstin,
|
|
58
|
+
legalName: trimmed(store?.legalName),
|
|
59
|
+
address: trimmed(store?.registeredAddress),
|
|
60
|
+
source: "seller",
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/*
|
|
64
|
+
* Platform branch. Gated on `gst.enabled`, matching what the checkout
|
|
65
|
+
* already did before sellers could have a GSTIN at all โ disabling GST must
|
|
66
|
+
* continue to produce plain invoices rather than tax invoices.
|
|
67
|
+
*/
|
|
68
|
+
const gst = settings?.gst;
|
|
69
|
+
if (gst?.enabled) {
|
|
70
|
+
const platformGstin = trimmed(gst.gstin);
|
|
71
|
+
if (platformGstin) {
|
|
72
|
+
return {
|
|
73
|
+
gstin: platformGstin,
|
|
74
|
+
legalName: trimmed(gst.legalName),
|
|
75
|
+
address: trimmed(gst.address),
|
|
76
|
+
source: "platform",
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return { source: "none" };
|
|
81
|
+
}
|
|
@@ -33,7 +33,7 @@ export function buildClassifiedMetadata(product, opts) {
|
|
|
33
33
|
description,
|
|
34
34
|
url: canonical,
|
|
35
35
|
type: "website",
|
|
36
|
-
images: image ? [{ url: image }] : undefined,
|
|
36
|
+
images: image ? [{ url: typeof image === "string" ? image : image.url }] : undefined,
|
|
37
37
|
},
|
|
38
38
|
twitter: {
|
|
39
39
|
card: image ? "summary_large_image" : "summary",
|
|
@@ -10,7 +10,9 @@ interface ClassifiedDocLike {
|
|
|
10
10
|
price?: number | null;
|
|
11
11
|
currency?: string | null;
|
|
12
12
|
mainImage?: string | null;
|
|
13
|
-
images?: (
|
|
13
|
+
images?: ({
|
|
14
|
+
url: string;
|
|
15
|
+
} | string | null | undefined)[] | null;
|
|
14
16
|
classified?: {
|
|
15
17
|
meetupArea?: {
|
|
16
18
|
city?: string;
|
|
@@ -8,7 +8,9 @@ export function renderClassifiedOg(doc, opts) {
|
|
|
8
8
|
return renderClassifiedOgImage({
|
|
9
9
|
title: doc?.title ?? "Classified Listing",
|
|
10
10
|
location,
|
|
11
|
-
imageUrl: resolveOgImageUrl(doc?.mainImage ||
|
|
11
|
+
imageUrl: resolveOgImageUrl(doc?.mainImage ||
|
|
12
|
+
(typeof doc?.images?.[0] === "string" ? doc.images[0] : doc?.images?.[0]?.url) ||
|
|
13
|
+
null, opts.baseUrl),
|
|
12
14
|
}, opts.siteName);
|
|
13
15
|
}
|
|
14
16
|
export function renderClassifiedOgImage(data, siteName) {
|
|
@@ -26,7 +26,7 @@ export function buildDigitalCodeMetadata(product, opts) {
|
|
|
26
26
|
description,
|
|
27
27
|
url: canonical,
|
|
28
28
|
type: "website",
|
|
29
|
-
images: image ? [{ url: image }] : undefined,
|
|
29
|
+
images: image ? [{ url: typeof image === "string" ? image : image.url }] : undefined,
|
|
30
30
|
},
|
|
31
31
|
twitter: {
|
|
32
32
|
card: image ? "summary_large_image" : "summary",
|
|
@@ -10,7 +10,9 @@ interface DigitalCodeDocLike {
|
|
|
10
10
|
price?: number | null;
|
|
11
11
|
currency?: string | null;
|
|
12
12
|
mainImage?: string | null;
|
|
13
|
-
images?: (
|
|
13
|
+
images?: ({
|
|
14
|
+
url: string;
|
|
15
|
+
} | string | null | undefined)[] | null;
|
|
14
16
|
digitalCode?: {
|
|
15
17
|
codeDeliveryMethod?: string;
|
|
16
18
|
} | null;
|
|
@@ -9,7 +9,9 @@ export function renderDigitalCodeOg(doc, opts) {
|
|
|
9
9
|
return renderDigitalCodeOgImage({
|
|
10
10
|
title: doc?.title ?? "Digital Code",
|
|
11
11
|
deliveryMethod,
|
|
12
|
-
imageUrl: resolveOgImageUrl(doc?.mainImage ||
|
|
12
|
+
imageUrl: resolveOgImageUrl(doc?.mainImage ||
|
|
13
|
+
(typeof doc?.images?.[0] === "string" ? doc.images[0] : doc?.images?.[0]?.url) ||
|
|
14
|
+
null, opts.baseUrl),
|
|
13
15
|
}, opts.siteName);
|
|
14
16
|
}
|
|
15
17
|
export function renderDigitalCodeOgImage(data, siteName) {
|
|
@@ -20,10 +20,25 @@ import { type ProductCodeContentKind } from "../../../../features/products/schem
|
|
|
20
20
|
/**
|
|
21
21
|
* Where a delivered asset's bytes live.
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* No `mediaAssets` row is ever created for one โ a row is what mints a
|
|
24
|
+
* `/media/{shortId}` slug, and that slug is served without authentication. No
|
|
25
|
+
* row, no slug, no public URL. That half was, and remains, true.
|
|
26
|
+
*
|
|
27
|
+
* ๐ CORRECTED 2026-10-19. This block used to open with "deliberately OUTSIDE
|
|
28
|
+
* every prefix the public media proxy knows how to resolve", and that was
|
|
29
|
+
* FALSE from the day the proxy's raw-path fallback shipped: `/media/[...slug]`
|
|
30
|
+
* treats any multi-segment slug it cannot resolve through `mediaAssets` as a
|
|
31
|
+
* literal storage path, so `/media/private/digital-content/...` resolved and
|
|
32
|
+
* served. It did watermark, so no pristine original leaked โ but a paid asset
|
|
33
|
+
* was reachable by anyone who guessed the object name, and the only thing
|
|
34
|
+
* standing in the way was `randomUUID()`.
|
|
35
|
+
*
|
|
36
|
+
* The proxy now refuses a raw path under `private/` outright
|
|
37
|
+
* (`PRIVATE_PREFIX` in `src/app/api/media/[...slug]/route.ts`), so the
|
|
38
|
+
* statement is true again โ but it is true because of a check, not because of
|
|
39
|
+
* the prefix, and that distinction is the whole reason this comment was wrong
|
|
40
|
+
* for so long. An unenforced invariant written as a fact is worse than no
|
|
41
|
+
* comment: it is the reason nobody looked.
|
|
27
42
|
*/
|
|
28
43
|
export declare const DIGITAL_CONTENT_PREFIX = "private/digital-content";
|
|
29
44
|
/**
|
|
@@ -26,10 +26,25 @@ import { PRODUCT_COLLECTION, PRODUCT_CODES_SUBCOLLECTION, } from "../../../../fe
|
|
|
26
26
|
/**
|
|
27
27
|
* Where a delivered asset's bytes live.
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
29
|
+
* No `mediaAssets` row is ever created for one โ a row is what mints a
|
|
30
|
+
* `/media/{shortId}` slug, and that slug is served without authentication. No
|
|
31
|
+
* row, no slug, no public URL. That half was, and remains, true.
|
|
32
|
+
*
|
|
33
|
+
* ๐ CORRECTED 2026-10-19. This block used to open with "deliberately OUTSIDE
|
|
34
|
+
* every prefix the public media proxy knows how to resolve", and that was
|
|
35
|
+
* FALSE from the day the proxy's raw-path fallback shipped: `/media/[...slug]`
|
|
36
|
+
* treats any multi-segment slug it cannot resolve through `mediaAssets` as a
|
|
37
|
+
* literal storage path, so `/media/private/digital-content/...` resolved and
|
|
38
|
+
* served. It did watermark, so no pristine original leaked โ but a paid asset
|
|
39
|
+
* was reachable by anyone who guessed the object name, and the only thing
|
|
40
|
+
* standing in the way was `randomUUID()`.
|
|
41
|
+
*
|
|
42
|
+
* The proxy now refuses a raw path under `private/` outright
|
|
43
|
+
* (`PRIVATE_PREFIX` in `src/app/api/media/[...slug]/route.ts`), so the
|
|
44
|
+
* statement is true again โ but it is true because of a check, not because of
|
|
45
|
+
* the prefix, and that distinction is the whole reason this comment was wrong
|
|
46
|
+
* for so long. An unenforced invariant written as a fact is worse than no
|
|
47
|
+
* comment: it is the reason nobody looked.
|
|
33
48
|
*/
|
|
34
49
|
export const DIGITAL_CONTENT_PREFIX = "private/digital-content";
|
|
35
50
|
/**
|
|
@@ -29,7 +29,7 @@ export function buildLiveItemMetadata(product, opts) {
|
|
|
29
29
|
description,
|
|
30
30
|
url: canonical,
|
|
31
31
|
type: "website",
|
|
32
|
-
images: image ? [{ url: image }] : undefined,
|
|
32
|
+
images: image ? [{ url: typeof image === "string" ? image : image.url }] : undefined,
|
|
33
33
|
},
|
|
34
34
|
twitter: {
|
|
35
35
|
card: image ? "summary_large_image" : "summary",
|
|
@@ -10,7 +10,9 @@ interface LiveItemDocLike {
|
|
|
10
10
|
price?: number | null;
|
|
11
11
|
currency?: string | null;
|
|
12
12
|
mainImage?: string | null;
|
|
13
|
-
images?: (
|
|
13
|
+
images?: ({
|
|
14
|
+
url: string;
|
|
15
|
+
} | string | null | undefined)[] | null;
|
|
14
16
|
liveItem?: {
|
|
15
17
|
species?: string;
|
|
16
18
|
} | null;
|
|
@@ -4,7 +4,9 @@ export function renderLiveItemOg(doc, opts) {
|
|
|
4
4
|
return renderLiveItemOgImage({
|
|
5
5
|
title: doc?.title ?? "Live Listing",
|
|
6
6
|
species: doc?.liveItem?.species ?? null,
|
|
7
|
-
imageUrl: resolveOgImageUrl(doc?.mainImage ||
|
|
7
|
+
imageUrl: resolveOgImageUrl(doc?.mainImage ||
|
|
8
|
+
(typeof doc?.images?.[0] === "string" ? doc.images[0] : doc?.images?.[0]?.url) ||
|
|
9
|
+
null, opts.baseUrl),
|
|
8
10
|
}, opts.siteName);
|
|
9
11
|
}
|
|
10
12
|
export function renderLiveItemOgImage(data, siteName) {
|
|
@@ -160,7 +160,7 @@ export async function sendMessage(input) {
|
|
|
160
160
|
productRef = {
|
|
161
161
|
productId: product.id,
|
|
162
162
|
title: product.title,
|
|
163
|
-
image: product.images?.[0],
|
|
163
|
+
image: product.images?.[0]?.url,
|
|
164
164
|
price: product.price,
|
|
165
165
|
// Without this the card cannot pick the right detail route โ see the
|
|
166
166
|
// field's own comment on `MessageProductRef`.
|
|
@@ -58,7 +58,7 @@ export function renderPartOg(part, usedByCount, opts) {
|
|
|
58
58
|
/** One classification's card. */
|
|
59
59
|
export function renderPartClassificationOg(slot, count, opts) {
|
|
60
60
|
const label = PART_SLOT_LABEL[slot] ?? slot;
|
|
61
|
-
return shell("
|
|
61
|
+
return shell("Beyblade parts gallery", label,
|
|
62
62
|
// `count` comes from the same bounded read the page renders, so the number
|
|
63
63
|
// on the card is the number on the page. A separate count query would be a
|
|
64
64
|
// second source that could disagree.
|
|
@@ -8,7 +8,9 @@ interface PreOrderDocLike {
|
|
|
8
8
|
title?: string | null;
|
|
9
9
|
preOrderReleaseDate?: Date | string | null;
|
|
10
10
|
mainImage?: string | null;
|
|
11
|
-
images?: (
|
|
11
|
+
images?: ({
|
|
12
|
+
url: string;
|
|
13
|
+
} | string | null | undefined)[] | null;
|
|
12
14
|
}
|
|
13
15
|
/** High-level OG renderer โ accepts the raw pre-order document from `getPreOrderForDetail`. */
|
|
14
16
|
export declare function renderPreOrderOg(doc: PreOrderDocLike | null | undefined, opts: {
|
|
@@ -12,7 +12,9 @@ export function renderPreOrderOg(doc, opts) {
|
|
|
12
12
|
return renderPreOrderOgImage({
|
|
13
13
|
title: doc?.title ?? "Pre-Order",
|
|
14
14
|
releaseDateLabel,
|
|
15
|
-
imageUrl: resolveOgImageUrl(doc?.mainImage ||
|
|
15
|
+
imageUrl: resolveOgImageUrl(doc?.mainImage ||
|
|
16
|
+
(typeof doc?.images?.[0] === "string" ? doc.images[0] : doc?.images?.[0]?.url) ||
|
|
17
|
+
null, opts.baseUrl),
|
|
16
18
|
}, opts.siteName);
|
|
17
19
|
}
|
|
18
20
|
export function renderPreOrderOgImage(data, siteName) {
|
|
@@ -117,3 +117,21 @@ export interface PriceIndexSearchResponse {
|
|
|
117
117
|
* Cost: one `searchTxt` push-down query plus ONE multi-get. Both bounded.
|
|
118
118
|
*/
|
|
119
119
|
export declare function searchPriceIndex(rawQuery: string): Promise<PriceIndexSearchResponse>;
|
|
120
|
+
/**
|
|
121
|
+
* Tier 1 adoption โ the client already resolved candidate leaves LOCALLY via
|
|
122
|
+
* the public search artifact (`useSiteSearch({ types: ["model", "category"] })`),
|
|
123
|
+
* at zero Firestore reads. This is the ONLY query this path still needs: one
|
|
124
|
+
* multi-get, bounded by however many ids the client resolved (capped the
|
|
125
|
+
* same as the search path, so a crafted request cannot demand an unbounded
|
|
126
|
+
* `getAll`).
|
|
127
|
+
*
|
|
128
|
+
* ๐ Deliberately NOT filtering brand/bundle categoryType here โ the CALLER
|
|
129
|
+
* already did that at index-build time (`PUBLIC_INDEX_SOURCES`'s category
|
|
130
|
+
* source only emits real listing leaves under the "model"/"category" type
|
|
131
|
+
* keys), so re-deriving the same filter from a bare id list would be a
|
|
132
|
+
* second, independently-maintained copy of a rule that already lives in one
|
|
133
|
+
* place. If that assumption is ever wrong, the cost is a band shown for a
|
|
134
|
+
* brand/bundle row โ cosmetic, not a leak, since no money figure is ever
|
|
135
|
+
* attached to a document that does not already have sales recorded.
|
|
136
|
+
*/
|
|
137
|
+
export declare function getPriceIndexBandsForIds(rawIds: readonly string[]): Promise<PriceIndexSearchResult[]>;
|
|
@@ -154,8 +154,22 @@ export async function searchPriceIndex(rawQuery) {
|
|
|
154
154
|
return !t || t === "category" || t === "sublisting";
|
|
155
155
|
});
|
|
156
156
|
const page = listingRows.slice(0, PRICE_INDEX_SEARCH_LIMIT);
|
|
157
|
-
const
|
|
158
|
-
|
|
157
|
+
const results = await buildBandsForLeaves(page);
|
|
158
|
+
return {
|
|
159
|
+
...base,
|
|
160
|
+
results,
|
|
161
|
+
truncated: listingRows.length > PRICE_INDEX_SEARCH_LIMIT,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The ONE multi-get, shared by the search path above and the ids-only path
|
|
166
|
+
* below โ the actual band-shaping logic (sort by sample size, omit an empty
|
|
167
|
+
* `bands` array, the "no sales recorded" vs "zero sales" distinction) must
|
|
168
|
+
* answer identically regardless of how the category list was resolved.
|
|
169
|
+
*/
|
|
170
|
+
async function buildBandsForLeaves(leaves) {
|
|
171
|
+
const bandsByLeaf = await priceIndexRepository.getManyForLeaves(leaves.map((c) => c.id));
|
|
172
|
+
return leaves.map((c) => {
|
|
159
173
|
const doc = bandsByLeaf.get(c.id);
|
|
160
174
|
const bands = doc
|
|
161
175
|
? Object.entries(doc.byListingType ?? {})
|
|
@@ -180,9 +194,35 @@ export async function searchPriceIndex(rawQuery) {
|
|
|
180
194
|
...(doc ? { windowDays: doc.windowDays, computedAt: toIso(doc.computedAt) } : {}),
|
|
181
195
|
};
|
|
182
196
|
});
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Tier 1 adoption โ the client already resolved candidate leaves LOCALLY via
|
|
200
|
+
* the public search artifact (`useSiteSearch({ types: ["model", "category"] })`),
|
|
201
|
+
* at zero Firestore reads. This is the ONLY query this path still needs: one
|
|
202
|
+
* multi-get, bounded by however many ids the client resolved (capped the
|
|
203
|
+
* same as the search path, so a crafted request cannot demand an unbounded
|
|
204
|
+
* `getAll`).
|
|
205
|
+
*
|
|
206
|
+
* ๐ Deliberately NOT filtering brand/bundle categoryType here โ the CALLER
|
|
207
|
+
* already did that at index-build time (`PUBLIC_INDEX_SOURCES`'s category
|
|
208
|
+
* source only emits real listing leaves under the "model"/"category" type
|
|
209
|
+
* keys), so re-deriving the same filter from a bare id list would be a
|
|
210
|
+
* second, independently-maintained copy of a rule that already lives in one
|
|
211
|
+
* place. If that assumption is ever wrong, the cost is a band shown for a
|
|
212
|
+
* brand/bundle row โ cosmetic, not a leak, since no money figure is ever
|
|
213
|
+
* attached to a document that does not already have sales recorded.
|
|
214
|
+
*/
|
|
215
|
+
export async function getPriceIndexBandsForIds(rawIds) {
|
|
216
|
+
const ids = [...new Set(rawIds.filter((id) => typeof id === "string" && id.length > 0))].slice(0, PRICE_INDEX_SEARCH_LIMIT);
|
|
217
|
+
if (ids.length === 0)
|
|
218
|
+
return [];
|
|
219
|
+
const docs = await categoriesRepository.getManyByIds(ids);
|
|
220
|
+
const leaves = docs.map((c) => ({
|
|
221
|
+
id: c.id,
|
|
222
|
+
name: c.name,
|
|
223
|
+
slug: c.slug,
|
|
224
|
+
path: c.path,
|
|
225
|
+
display: c.display,
|
|
226
|
+
}));
|
|
227
|
+
return buildBandsForLeaves(leaves);
|
|
188
228
|
}
|
|
@@ -17,7 +17,9 @@ interface PrizeDrawDocLike {
|
|
|
17
17
|
price?: number | null;
|
|
18
18
|
currency?: string | null;
|
|
19
19
|
mainImage?: string | null;
|
|
20
|
-
images?: (
|
|
20
|
+
images?: ({
|
|
21
|
+
url: string;
|
|
22
|
+
} | string | null | undefined)[] | null;
|
|
21
23
|
prizeRevealStatus?: "pending" | "open" | "closed" | null;
|
|
22
24
|
prizeMaxEntries?: number | null;
|
|
23
25
|
prizeCurrentEntries?: number | null;
|
|
@@ -19,7 +19,9 @@ export function renderPrizeDrawOg(doc, opts) {
|
|
|
19
19
|
return renderPrizeDrawOgImage({
|
|
20
20
|
title: doc?.title ?? doc?.name ?? "Prize Draw",
|
|
21
21
|
pricePerEntryLabel,
|
|
22
|
-
imageUrl: resolveOgImageUrl(doc?.mainImage ||
|
|
22
|
+
imageUrl: resolveOgImageUrl(doc?.mainImage ||
|
|
23
|
+
(typeof doc?.images?.[0] === "string" ? doc.images[0] : doc?.images?.[0]?.url) ||
|
|
24
|
+
null, opts.baseUrl),
|
|
23
25
|
revealStatus: doc?.prizeRevealStatus ?? null,
|
|
24
26
|
entriesLabel,
|
|
25
27
|
}, opts.siteName);
|
|
@@ -42,6 +42,16 @@ export interface PublicGroupMember {
|
|
|
42
42
|
groupTitle?: string;
|
|
43
43
|
/** Drives the stepper's `max`. */
|
|
44
44
|
availableQuantity: number;
|
|
45
|
+
/**
|
|
46
|
+
* Made to order โ the stepper is UNCAPPED for this member.
|
|
47
|
+
*
|
|
48
|
+
* ๐ This is an ALLOW-LIST projection: a field absent from this interface and
|
|
49
|
+
* from `toPublicGroupMember` below simply does not reach the picker, with no
|
|
50
|
+
* error anywhere. Without it the picker reads `availableQuantity: 0` on a
|
|
51
|
+
* print-on-demand member and caps the stepper at zero โ the member renders,
|
|
52
|
+
* looks selectable, and cannot be chosen.
|
|
53
|
+
*/
|
|
54
|
+
madeToOrder?: boolean;
|
|
45
55
|
storeId: string;
|
|
46
56
|
storeName?: string;
|
|
47
57
|
status: string;
|
|
@@ -50,6 +60,22 @@ export interface PublicGroupMember {
|
|
|
50
60
|
* snapshot it for per-member GST proration at checkout. */
|
|
51
61
|
gstRate?: 0 | 5 | 12 | 18 | 28;
|
|
52
62
|
hsnCode?: string;
|
|
63
|
+
/**
|
|
64
|
+
* The group's OWN selection rules โ present only on the PARENT row, since
|
|
65
|
+
* that is the only document that carries them.
|
|
66
|
+
*
|
|
67
|
+
* ๐ Projected so `readGroupRules` has something real to read client-side.
|
|
68
|
+
* Without these the picker would silently see no rules on every page that
|
|
69
|
+
* derives them from this endpoint's own response (`ShowGroupSection`),
|
|
70
|
+
* which is a client-only regression of the exact kind E3 exists to close โ
|
|
71
|
+
* a server-only rule reads as a broken button, and here it would be the
|
|
72
|
+
* reverse: a client that never finds out a rule exists at all.
|
|
73
|
+
*/
|
|
74
|
+
groupMinMembers?: number;
|
|
75
|
+
groupMaxMembers?: number;
|
|
76
|
+
groupMaxUnitsPerMember?: number;
|
|
77
|
+
groupRequiredMemberIds?: string[];
|
|
78
|
+
groupDiscountPercent?: number;
|
|
53
79
|
}
|
|
54
80
|
export declare function toPublicGroupMember(doc: ProductDocument): PublicGroupMember;
|
|
55
81
|
export declare function toPublicGroupMembers(docs: readonly ProductDocument[]): PublicGroupMember[];
|
|
@@ -22,18 +22,24 @@ export function toPublicGroupMember(doc) {
|
|
|
22
22
|
title: doc.title,
|
|
23
23
|
price: doc.price,
|
|
24
24
|
currency: doc.currency,
|
|
25
|
-
image: doc.images?.[0] ?? doc.mainImage,
|
|
25
|
+
image: doc.images?.[0]?.url ?? doc.mainImage,
|
|
26
26
|
condition: doc.condition,
|
|
27
27
|
listingType: normalizeListingType(doc),
|
|
28
28
|
isGroupParent: doc.isGroupParent,
|
|
29
29
|
groupTitle: doc.groupTitle,
|
|
30
30
|
availableQuantity: doc.availableQuantity ?? 0,
|
|
31
|
+
madeToOrder: doc.madeToOrder,
|
|
31
32
|
storeId: doc.storeId,
|
|
32
33
|
storeName: doc.storeName,
|
|
33
34
|
status: doc.status,
|
|
34
35
|
isSold: doc.isSold,
|
|
35
36
|
gstRate: doc.gstRate,
|
|
36
37
|
hsnCode: doc.hsnCode,
|
|
38
|
+
groupMinMembers: doc.groupMinMembers,
|
|
39
|
+
groupMaxMembers: doc.groupMaxMembers,
|
|
40
|
+
groupMaxUnitsPerMember: doc.groupMaxUnitsPerMember,
|
|
41
|
+
groupRequiredMemberIds: doc.groupRequiredMemberIds,
|
|
42
|
+
groupDiscountPercent: doc.groupDiscountPercent,
|
|
37
43
|
};
|
|
38
44
|
}
|
|
39
45
|
export function toPublicGroupMembers(docs) {
|
|
@@ -11,7 +11,9 @@ interface ProductDocLike {
|
|
|
11
11
|
title?: string | null;
|
|
12
12
|
price?: number | null;
|
|
13
13
|
mainImage?: string | null;
|
|
14
|
-
images?: (
|
|
14
|
+
images?: ({
|
|
15
|
+
url: string;
|
|
16
|
+
} | string | null | undefined)[] | null;
|
|
15
17
|
}
|
|
16
18
|
/** High-level OG renderer โ accepts the raw product document from `getProductForDetail`. */
|
|
17
19
|
export declare function renderProductOg(doc: ProductDocLike | null | undefined, opts: OgOptions & {
|
|
@@ -6,7 +6,9 @@ export function renderProductOg(doc, opts) {
|
|
|
6
6
|
return renderProductOgImage({
|
|
7
7
|
title: doc?.title ?? "Product",
|
|
8
8
|
price: doc?.price ?? null,
|
|
9
|
-
imageUrl: resolveOgImageUrl(doc?.mainImage ||
|
|
9
|
+
imageUrl: resolveOgImageUrl(doc?.mainImage ||
|
|
10
|
+
(typeof doc?.images?.[0] === "string" ? doc.images[0] : doc?.images?.[0]?.url) ||
|
|
11
|
+
null, opts.baseUrl),
|
|
10
12
|
}, opts.siteName);
|
|
11
13
|
}
|
|
12
14
|
export function renderProductOgImage(data, siteName) {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type SearchSource } from "./search-everything";
|
|
2
|
+
/** The viewer this search is scoped TO. Null means signed out. */
|
|
3
|
+
export interface SearchViewer {
|
|
4
|
+
readonly uid: string;
|
|
5
|
+
readonly role: string;
|
|
6
|
+
/** The store slug this viewer owns, if any. See ยง Store Identity. */
|
|
7
|
+
readonly storeId: string | null;
|
|
8
|
+
readonly isAdmin: boolean;
|
|
9
|
+
readonly isSeller: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Build the viewer's sources.
|
|
13
|
+
*
|
|
14
|
+
* ๐ Returns `[]` for a guest, which is what makes "zero authenticated
|
|
15
|
+
* requests when signed out" structural rather than a caller's discipline.
|
|
16
|
+
*/
|
|
17
|
+
export declare function scopedSourcesFor(viewer: SearchViewer | null): SearchSource[];
|
|
18
|
+
/**
|
|
19
|
+
* ฮฃ `scanLimit`, for the budget check.
|
|
20
|
+
*
|
|
21
|
+
* Exported so `audit-scoped-search-ownership` R4 can print the arithmetic
|
|
22
|
+
* rather than just a verdict: "over budget" without the per-source figures
|
|
23
|
+
* tells you nothing about which source to shrink.
|
|
24
|
+
*/
|
|
25
|
+
export declare function scopedScanTotal(sources: readonly SearchSource[]): number;
|
|
26
|
+
export declare function assertWithinScopedBudget(sources: readonly SearchSource[]): void;
|