@mohasinac/appkit 4.52.4 → 4.53.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/.build-stamp.json +4 -4
- package/dist/_internal/client/features/sticker-trace/canvas-codec.d.ts +2 -0
- package/dist/_internal/client/features/sticker-trace/canvas-codec.js +148 -0
- package/dist/_internal/server/features/auctions/actions.js +1 -1
- package/dist/_internal/server/features/categories/data.js +23 -7
- package/dist/_internal/server/features/checkout/actions.js +10 -3
- package/dist/_internal/server/features/checkout/data.d.ts +15 -0
- package/dist/_internal/server/features/checkout/data.js +20 -3
- package/dist/_internal/server/features/lottery/actions.js +9 -1
- package/dist/_internal/server/features/lottery/og.d.ts +40 -0
- package/dist/_internal/server/features/lottery/og.js +79 -0
- package/dist/_internal/server/features/messages/actions.js +4 -0
- package/dist/_internal/server/features/offers/adapters.js +17 -3
- package/dist/_internal/server/features/orders/actions.js +7 -2
- package/dist/_internal/server/features/raffle/actions.d.ts +19 -0
- package/dist/_internal/server/features/raffle/actions.js +25 -0
- package/dist/_internal/server/features/reviews/actions.js +1 -1
- package/dist/_internal/server/features/reviews/data.d.ts +1 -1
- package/dist/_internal/server/features/search/index-build/artifact-store.d.ts +89 -0
- package/dist/_internal/server/features/search/index-build/artifact-store.js +208 -0
- package/dist/_internal/server/features/search/index-build/build.d.ts +57 -0
- package/dist/_internal/server/features/search/index-build/build.js +285 -0
- package/dist/_internal/server/features/search/index-build/sources.d.ts +53 -0
- package/dist/_internal/server/features/search/index-build/sources.js +385 -0
- package/dist/_internal/server/features/search/search-sources.d.ts +0 -15
- package/dist/_internal/server/features/search/search-sources.js +142 -7
- package/dist/_internal/server/features/seo/robots.js +21 -1
- package/dist/_internal/server/features/seo/sitemap.js +1 -1
- package/dist/_internal/server/features/shared/listing-data-factory.js +16 -4
- package/dist/_internal/server/features/site-settings/adapters.d.ts +1 -1
- package/dist/_internal/server/features/site-settings/adapters.js +26 -0
- package/dist/_internal/server/features/sticker-trace/actions.d.ts +109 -0
- package/dist/_internal/server/features/sticker-trace/actions.js +172 -0
- package/dist/_internal/server/features/sticker-trace/adapters.d.ts +80 -0
- package/dist/_internal/server/features/sticker-trace/adapters.js +174 -0
- package/dist/_internal/server/features/sticker-trace/build-cut-file.d.ts +26 -0
- package/dist/_internal/server/features/sticker-trace/build-cut-file.js +127 -0
- package/dist/_internal/server/features/sticker-trace/coordinator.d.ts +27 -0
- package/dist/_internal/server/features/sticker-trace/coordinator.js +169 -0
- package/dist/_internal/server/features/sticker-trace/fanout.d.ts +43 -0
- package/dist/_internal/server/features/sticker-trace/fanout.js +180 -0
- package/dist/_internal/server/features/sticker-trace/finalizer.d.ts +25 -0
- package/dist/_internal/server/features/sticker-trace/finalizer.js +123 -0
- package/dist/_internal/server/features/sticker-trace/mosaic-inputs.d.ts +30 -0
- package/dist/_internal/server/features/sticker-trace/mosaic-inputs.js +112 -0
- package/dist/_internal/server/features/sticker-trace/progress.d.ts +81 -0
- package/dist/_internal/server/features/sticker-trace/progress.js +198 -0
- package/dist/_internal/server/features/sticker-trace/promote.d.ts +23 -0
- package/dist/_internal/server/features/sticker-trace/promote.js +193 -0
- package/dist/_internal/server/features/sticker-trace/shard.d.ts +50 -0
- package/dist/_internal/server/features/sticker-trace/shard.js +174 -0
- package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +141 -0
- package/dist/_internal/server/features/sticker-trace/sheet-actions.js +279 -0
- package/dist/_internal/server/features/sticker-trace/storage.d.ts +135 -0
- package/dist/_internal/server/features/sticker-trace/storage.js +282 -0
- package/dist/_internal/server/functions/scheduled.d.ts +2 -1
- package/dist/_internal/server/functions/scheduled.js +25 -1
- package/dist/_internal/server/jobs/core/_event-ref.d.ts +51 -0
- package/dist/_internal/server/jobs/core/_event-ref.js +63 -0
- package/dist/_internal/server/jobs/core/assignSpinPrize.d.ts +18 -0
- package/dist/_internal/server/jobs/core/assignSpinPrize.js +77 -16
- package/dist/_internal/server/jobs/core/auctionSettlement.js +13 -4
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +44 -15
- package/dist/_internal/server/jobs/core/bundleStockSync.js +3 -4
- package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +44 -0
- package/dist/_internal/server/jobs/core/event-draw-reasons.d.ts +78 -0
- package/dist/_internal/server/jobs/core/event-draw-reasons.js +133 -0
- package/dist/_internal/server/jobs/core/listingProcessor.js +28 -8
- package/dist/_internal/server/jobs/core/onOrderCreate.js +12 -1
- package/dist/_internal/server/jobs/core/onScamReportCreate.js +13 -2
- package/dist/_internal/server/jobs/core/onScamReportRejected.js +8 -2
- package/dist/_internal/server/jobs/core/onScamReportVerified.js +8 -2
- package/dist/_internal/server/jobs/core/onStoreWrite.js +11 -4
- package/dist/_internal/server/jobs/core/prizeDrawAssignWinner.js +5 -4
- package/dist/_internal/server/jobs/core/prizeDrawExpiryReveal.js +1 -4
- package/dist/_internal/server/jobs/core/prizeDrawSoldOutReveal.js +1 -2
- package/dist/_internal/server/jobs/core/promotions.js +7 -4
- package/dist/_internal/server/jobs/core/searchIndexBuild.d.ts +7 -0
- package/dist/_internal/server/jobs/core/searchIndexBuild.js +211 -0
- package/dist/_internal/server/jobs/core/triggerEventRaffle.d.ts +35 -0
- package/dist/_internal/server/jobs/core/triggerEventRaffle.js +213 -31
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +20 -14
- package/dist/_internal/server/jobs/handlers/assignSpinPrize.d.ts +8 -0
- package/dist/_internal/server/jobs/handlers/assignSpinPrize.js +15 -15
- package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
- package/dist/_internal/server/jobs/handlers/index.js +1 -0
- package/dist/_internal/server/jobs/handlers/onCategoryWrite.js +18 -0
- package/dist/_internal/server/jobs/handlers/onProductWrite.js +18 -0
- package/dist/_internal/server/jobs/handlers/onReviewWrite.js +18 -0
- package/dist/_internal/server/jobs/handlers/onScamReportUpdate.js +18 -0
- package/dist/_internal/server/jobs/handlers/onStoreWrite.js +18 -0
- package/dist/_internal/server/jobs/handlers/searchIndexBuild.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/searchIndexBuild.js +2 -0
- package/dist/_internal/server/jobs/handlers/triggerEventRaffle.d.ts +8 -0
- package/dist/_internal/server/jobs/handlers/triggerEventRaffle.js +15 -6
- package/dist/_internal/shared/actions/action-registry.js +29 -0
- package/dist/_internal/shared/cache/revalidate-targets.d.ts +0 -1
- package/dist/_internal/shared/cache/revalidate-targets.js +10 -8
- package/dist/_internal/shared/features/events/config.d.ts +14 -0
- package/dist/_internal/shared/features/events/config.js +14 -0
- package/dist/_internal/shared/features/notifications/action-url.js +8 -0
- package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
- package/dist/_internal/shared/features/sticker-trace/codec.d.ts +81 -0
- package/dist/_internal/shared/features/sticker-trace/codec.js +30 -0
- package/dist/_internal/shared/features/sticker-trace/config.d.ts +81 -0
- package/dist/_internal/shared/features/sticker-trace/config.js +177 -0
- package/dist/_internal/shared/features/sticker-trace/cut-contour.d.ts +20 -0
- package/dist/_internal/shared/features/sticker-trace/cut-contour.js +60 -0
- package/dist/_internal/shared/features/sticker-trace/export/build-export-set.d.ts +65 -0
- package/dist/_internal/shared/features/sticker-trace/export/build-export-set.js +176 -0
- package/dist/_internal/shared/features/sticker-trace/export/cut-svg.d.ts +56 -0
- package/dist/_internal/shared/features/sticker-trace/export/cut-svg.js +120 -0
- package/dist/_internal/shared/features/sticker-trace/export/machine-profiles.d.ts +92 -0
- package/dist/_internal/shared/features/sticker-trace/export/machine-profiles.js +153 -0
- package/dist/_internal/shared/features/sticker-trace/export/nesting.d.ts +51 -0
- package/dist/_internal/shared/features/sticker-trace/export/nesting.js +110 -0
- package/dist/_internal/shared/features/sticker-trace/export/page-sizes.d.ts +68 -0
- package/dist/_internal/shared/features/sticker-trace/export/page-sizes.js +223 -0
- package/dist/_internal/shared/features/sticker-trace/export/part-tiling.d.ts +51 -0
- package/dist/_internal/shared/features/sticker-trace/export/part-tiling.js +178 -0
- package/dist/_internal/shared/features/sticker-trace/export/simplify-budget.d.ts +26 -0
- package/dist/_internal/shared/features/sticker-trace/export/simplify-budget.js +134 -0
- package/dist/_internal/shared/features/sticker-trace/export/vectorise-art.d.ts +40 -0
- package/dist/_internal/shared/features/sticker-trace/export/vectorise-art.js +195 -0
- package/dist/_internal/shared/features/sticker-trace/index.d.ts +2 -0
- package/dist/_internal/shared/features/sticker-trace/index.js +59 -0
- package/dist/_internal/shared/features/sticker-trace/math/catmull-rom.d.ts +11 -0
- package/dist/_internal/shared/features/sticker-trace/math/catmull-rom.js +66 -0
- package/dist/_internal/shared/features/sticker-trace/math/edt.d.ts +27 -0
- package/dist/_internal/shared/features/sticker-trace/math/edt.js +165 -0
- package/dist/_internal/shared/features/sticker-trace/math/label.d.ts +15 -0
- package/dist/_internal/shared/features/sticker-trace/math/label.js +156 -0
- package/dist/_internal/shared/features/sticker-trace/math/marching-squares.d.ts +16 -0
- package/dist/_internal/shared/features/sticker-trace/math/marching-squares.js +242 -0
- package/dist/_internal/shared/features/sticker-trace/math/morphology.d.ts +46 -0
- package/dist/_internal/shared/features/sticker-trace/math/morphology.js +168 -0
- package/dist/_internal/shared/features/sticker-trace/math/rasterize-path.d.ts +88 -0
- package/dist/_internal/shared/features/sticker-trace/math/rasterize-path.js +286 -0
- package/dist/_internal/shared/features/sticker-trace/math/rdp.d.ts +10 -0
- package/dist/_internal/shared/features/sticker-trace/math/rdp.js +74 -0
- package/dist/_internal/shared/features/sticker-trace/resume.d.ts +50 -0
- package/dist/_internal/shared/features/sticker-trace/resume.js +160 -0
- package/dist/_internal/shared/features/sticker-trace/trace/cluster.d.ts +20 -0
- package/dist/_internal/shared/features/sticker-trace/trace/cluster.js +132 -0
- package/dist/_internal/shared/features/sticker-trace/trace/cross-profile.d.ts +28 -0
- package/dist/_internal/shared/features/sticker-trace/trace/cross-profile.js +120 -0
- package/dist/_internal/shared/features/sticker-trace/trace/flood.d.ts +21 -0
- package/dist/_internal/shared/features/sticker-trace/trace/flood.js +104 -0
- package/dist/_internal/shared/features/sticker-trace/trace/geometry.d.ts +3 -0
- package/dist/_internal/shared/features/sticker-trace/trace/geometry.js +140 -0
- package/dist/_internal/shared/features/sticker-trace/trace/line-filter.d.ts +15 -0
- package/dist/_internal/shared/features/sticker-trace/trace/line-filter.js +138 -0
- package/dist/_internal/shared/features/sticker-trace/trace/merge.d.ts +27 -0
- package/dist/_internal/shared/features/sticker-trace/trace/merge.js +187 -0
- package/dist/_internal/shared/features/sticker-trace/trace/paper.d.ts +32 -0
- package/dist/_internal/shared/features/sticker-trace/trace/paper.js +147 -0
- package/dist/_internal/shared/features/sticker-trace/trace/prefilter.d.ts +30 -0
- package/dist/_internal/shared/features/sticker-trace/trace/prefilter.js +125 -0
- package/dist/_internal/shared/features/sticker-trace/trace/quantise.d.ts +10 -0
- package/dist/_internal/shared/features/sticker-trace/trace/quantise.js +153 -0
- package/dist/_internal/shared/features/sticker-trace/trace/ridge.d.ts +88 -0
- package/dist/_internal/shared/features/sticker-trace/trace/ridge.js +344 -0
- package/dist/_internal/shared/features/sticker-trace/trace/segment.d.ts +10 -0
- package/dist/_internal/shared/features/sticker-trace/trace/segment.js +251 -0
- package/dist/_internal/shared/features/sticker-trace/types.d.ts +197 -0
- package/dist/_internal/shared/features/sticker-trace/types.js +49 -0
- package/dist/_internal/shared/listing-types/_registry.d.ts +11 -0
- package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/art/config.js +1 -0
- package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/auction/config.js +1 -0
- package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/classified/config.js +1 -0
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/digital-code/config.js +1 -0
- package/dist/_internal/shared/listing-types/feature-flags.d.ts +7 -0
- package/dist/_internal/shared/listing-types/feature-flags.js +9 -0
- package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/live/config.js +1 -0
- package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/pre-order/config.js +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.js +1 -0
- package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/standard/config.js +1 -0
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/stickers/config.js +1 -0
- package/dist/_internal/shared/media/limits.d.ts +12 -2
- package/dist/_internal/shared/media/limits.js +12 -2
- package/dist/_internal/shared/search/artifact-url.d.ts +35 -0
- package/dist/_internal/shared/search/artifact-url.js +119 -0
- package/dist/_internal/shared/search/index-record.d.ts +68 -0
- package/dist/_internal/shared/search/index-record.js +96 -0
- package/dist/_internal/shared/search/match.d.ts +65 -0
- package/dist/_internal/shared/search/match.js +263 -0
- package/dist/client.d.ts +8 -7
- package/dist/client.js +12 -5
- package/dist/configs/eslint.js +22 -2
- package/dist/constants/api-endpoints.d.ts +68 -0
- package/dist/constants/api-endpoints.js +32 -0
- package/dist/constants/field-names.d.ts +7 -1
- package/dist/constants/field-names.js +36 -1
- package/dist/contracts/repository.d.ts +8 -7
- package/dist/contracts/search.d.ts +2 -2
- package/dist/contracts/table.d.ts +3 -3
- package/dist/contracts/table.js +3 -3
- package/dist/core/contact-submissions.repository.js +2 -2
- package/dist/core/integration-keys.js +7 -1
- package/dist/core/newsletter.repository.js +2 -2
- package/dist/core/site-config.js +1 -1
- package/dist/errors/error-codes.d.ts +30 -0
- package/dist/errors/error-codes.js +30 -0
- package/dist/errors/error-display-map.js +40 -1
- package/dist/features/account/api/[userId]/addresses/route.js +1 -1
- package/dist/features/account/components/UserBidsView.js +1 -1
- package/dist/features/account/components/index.d.ts +0 -8
- package/dist/features/account/components/index.js +0 -4
- package/dist/features/addresses/repository/addresses.repository.d.ts +17 -6
- package/dist/features/addresses/repository/addresses.repository.js +65 -9
- package/dist/features/addresses/schemas/firestore.d.ts +17 -6
- package/dist/features/admin/actions/notification-actions.js +15 -6
- package/dist/features/admin/api/bids/route.js +1 -1
- package/dist/features/admin/api/coupons/route.js +1 -1
- package/dist/features/admin/api/products/route.js +1 -1
- package/dist/features/admin/api/reviews/route.js +1 -1
- package/dist/features/admin/components/AdminAdEditorView.js +19 -5
- package/dist/features/admin/components/AdminAuditLogView.js +1 -1
- package/dist/features/admin/components/AdminBlogEditorView.js +0 -1
- package/dist/features/admin/components/AdminBlogView.js +1 -1
- package/dist/features/admin/components/AdminBrandsView.js +17 -1
- package/dist/features/admin/components/AdminCategoryEditorView.js +0 -1
- package/dist/features/admin/components/AdminContactView.js +1 -1
- package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -3
- package/dist/features/admin/components/AdminNewsletterView.js +1 -1
- package/dist/features/admin/components/AdminOrdersView.js +9 -2
- package/dist/features/admin/components/AdminPayoutsView.js +1 -1
- package/dist/features/admin/components/AdminPrizeDrawsView.js +11 -0
- package/dist/features/admin/components/AdminProductEditorView.d.ts +10 -1
- package/dist/features/admin/components/AdminProductEditorView.js +24 -37
- package/dist/features/admin/components/AdminProductsView.js +10 -3
- package/dist/features/admin/components/AdminScammersView.js +1 -1
- package/dist/features/admin/components/AdminSectionsView.js +21 -5
- package/dist/features/admin/components/AdminSessionsView.js +1 -1
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +22 -1
- package/dist/features/admin/components/AdminTeamView.js +1 -1
- package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +0 -1
- package/dist/features/admin/components/AdminUsersView.js +1 -1
- package/dist/features/admin/components/DataListingView.d.ts +2 -1
- package/dist/features/admin/components/DataListingView.js +9 -4
- package/dist/features/admin/components/analytics/AdminPageViewsReportView.js +0 -2
- package/dist/features/admin/hooks/useAdminListing.d.ts +1 -1
- package/dist/features/admin/repository/site-settings.repository.js +8 -3
- package/dist/features/admin/schemas/firestore.d.ts +62 -1
- package/dist/features/admin/schemas/firestore.js +32 -0
- package/dist/features/admin/types/index.d.ts +1 -1
- package/dist/features/auctions/actions/bid-actions.d.ts +2 -2
- package/dist/features/auctions/actions/bid-actions.js +16 -4
- package/dist/features/auctions/api/route.js +1 -1
- package/dist/features/auctions/components/AuctionBottomActions.js +4 -0
- package/dist/features/auctions/repository/bid.repository.d.ts +46 -4
- package/dist/features/auctions/repository/bid.repository.js +114 -13
- package/dist/features/auctions/schemas/firestore.d.ts +24 -4
- package/dist/features/auctions/schemas/firestore.js +1 -0
- package/dist/features/auth/actions/profile-actions.js +30 -4
- package/dist/features/auth/components/index.d.ts +0 -1
- package/dist/features/auth/components/index.js +0 -1
- package/dist/features/auth/repository/session.repository.d.ts +17 -3
- package/dist/features/auth/repository/session.repository.js +46 -5
- package/dist/features/auth/repository/token.repository.d.ts +27 -4
- package/dist/features/auth/repository/token.repository.js +65 -11
- package/dist/features/auth/repository/user.repository.d.ts +33 -7
- package/dist/features/auth/repository/user.repository.js +100 -15
- package/dist/features/auth/schemas/firestore.d.ts +63 -12
- package/dist/features/auth/schemas/firestore.js +11 -0
- package/dist/features/before-after/api/route.js +1 -1
- package/dist/features/blog/components/BlogListView.js +16 -3
- package/dist/features/blog/components/BlogPostView.js +1 -1
- package/dist/features/blog/schemas/index.d.ts +2 -2
- package/dist/features/cart/api/route.js +1 -1
- package/dist/features/catalogue/repository/catalogue.repository.d.ts +7 -7
- package/dist/features/catalogue/repository/catalogue.repository.js +28 -10
- package/dist/features/catalogue/schemas/firestore.d.ts +11 -0
- package/dist/features/categories/api/route.js +10 -10
- package/dist/features/categories/components/CategoryDetailPageView.js +35 -5
- package/dist/features/categories/components/CategorySelectorCreate.js +0 -1
- package/dist/features/categories/components/index.d.ts +0 -2
- package/dist/features/categories/components/index.js +0 -1
- package/dist/features/categories/repository/categories.repository.d.ts +1 -0
- package/dist/features/categories/repository/categories.repository.js +31 -1
- package/dist/features/categories/schemas/index.d.ts +2 -2
- package/dist/features/categories/utils/taxonomy-visual.d.ts +21 -0
- package/dist/features/categories/utils/taxonomy-visual.js +58 -0
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +8 -1
- package/dist/features/collections/api/[slug]/route.js +3 -3
- package/dist/features/collections/api/route.js +1 -1
- package/dist/features/consultation/api/route.js +1 -1
- package/dist/features/consultation/repository/consultations.repository.js +1 -1
- package/dist/features/consultation/types/index.d.ts +1 -1
- package/dist/features/contact/components/ContactForm.js +1 -3
- package/dist/features/corporate/api/route.js +1 -1
- package/dist/features/corporate/repository/corporate.repository.js +1 -1
- package/dist/features/corporate/types/index.d.ts +1 -1
- package/dist/features/cron/jobs/auction-expiry.job.js +1 -1
- package/dist/features/cron/jobs/preorder-reminder.job.js +1 -1
- package/dist/features/events/actions/event-actions.d.ts +14 -0
- package/dist/features/events/actions/event-actions.js +82 -3
- package/dist/features/events/api/[id]/route.js +2 -2
- package/dist/features/events/components/AdminEventEditorView.js +22 -3
- package/dist/features/events/components/AdminEventsView.js +32 -8
- package/dist/features/events/components/EventRafflesSection.d.ts +34 -1
- package/dist/features/events/components/EventRafflesSection.js +52 -3
- package/dist/features/events/components/SpinWheelView.d.ts +2 -2
- package/dist/features/events/components/SpinWheelView.js +41 -4
- package/dist/features/events/repository/event-entry.repository.d.ts +14 -2
- package/dist/features/events/repository/event-entry.repository.js +41 -7
- package/dist/features/events/schemas/firestore.d.ts +17 -4
- package/dist/features/events/types/index.d.ts +37 -0
- package/dist/features/faq/repository/faqs.repository.js +1 -1
- package/dist/features/faq/schemas/index.d.ts +5 -2
- package/dist/features/faq/schemas/index.js +6 -0
- package/dist/features/faq/types/index.d.ts +0 -1
- package/dist/features/grouped/components/GroupedListingEditorView.js +17 -2
- package/dist/features/homepage/api/carousel/[id]/route.js +1 -1
- package/dist/features/homepage/api/carousel/route.js +4 -4
- package/dist/features/homepage/api/route.js +2 -2
- package/dist/features/homepage/api/sections/route.js +1 -1
- package/dist/features/homepage/components/AnnouncementBar.d.ts +1 -9
- package/dist/features/homepage/components/AnnouncementBar.js +13 -19
- package/dist/features/homepage/components/MarketplaceHomepageView.js +6 -1
- package/dist/features/homepage/components/index.d.ts +0 -2
- package/dist/features/homepage/components/index.js +0 -1
- package/dist/features/homepage/repository/homepage.repository.js +1 -1
- package/dist/features/homepage/schemas/firestore.d.ts +6 -0
- package/dist/features/homepage/schemas/index.d.ts +10 -10
- package/dist/features/layout/AppLayoutShell.d.ts +12 -3
- package/dist/features/layout/AppLayoutShell.js +65 -13
- package/dist/features/layout/BottomActionsContext.d.ts +16 -0
- package/dist/features/layout/BottomActionsContext.js +5 -0
- package/dist/features/layout/BottomChrome.js +48 -9
- package/dist/features/layout/BottomNavbar.d.ts +14 -0
- package/dist/features/layout/BottomNavbar.js +43 -3
- package/dist/features/layout/MainNavbar.d.ts +11 -0
- package/dist/features/layout/NavbarLayout.d.ts +3 -0
- package/dist/features/layout/NavbarLayout.js +88 -11
- package/dist/features/layout/SideActionDock.d.ts +1 -0
- package/dist/features/layout/SideActionDock.js +219 -0
- package/dist/features/layout/TitleBarLayout.d.ts +1 -3
- package/dist/features/layout/TitleBarLayout.js +3 -4
- package/dist/features/layout/cta-anchor.d.ts +31 -0
- package/dist/features/layout/cta-anchor.js +31 -0
- package/dist/features/layout/hooks/useBottomActions.d.ts +7 -0
- package/dist/features/layout/hooks/useBottomActions.js +6 -1
- package/dist/features/layout/index.d.ts +9 -1
- package/dist/features/layout/index.js +9 -1
- package/dist/features/layout/useCtaReveal.d.ts +24 -0
- package/dist/features/layout/useCtaReveal.js +82 -0
- package/dist/features/layout/useHoldToOpen.d.ts +41 -0
- package/dist/features/layout/useHoldToOpen.js +84 -0
- package/dist/features/lottery/repository/lottery-entry.repository.d.ts +18 -3
- package/dist/features/lottery/repository/lottery-entry.repository.js +48 -6
- package/dist/features/lottery/schemas/firestore.d.ts +33 -5
- package/dist/features/loyalty/api/balance/route.js +1 -1
- package/dist/features/loyalty/api/history/route.js +1 -1
- package/dist/features/media/MediaImage.js +0 -1
- package/dist/features/media/MediaPickerModal.js +7 -1
- package/dist/features/media/modals/ImageEditor.js +5 -1
- package/dist/features/media/modals/VideoThumbnailSelector.js +17 -1
- package/dist/features/media/repository/media-assets.repository.d.ts +19 -0
- package/dist/features/media/upload/CameraCapture.js +16 -1
- package/dist/features/media/upload/ImageUpload.js +42 -4
- package/dist/features/media/upload/MediaUploadField.js +69 -13
- package/dist/features/media/upload/downscale-image.d.ts +56 -0
- package/dist/features/media/upload/downscale-image.js +150 -0
- package/dist/features/messages/components/ConversationThreadView.js +45 -2
- package/dist/features/messages/components/MessageSellerButton.d.ts +15 -1
- package/dist/features/messages/components/MessageSellerButton.js +10 -2
- package/dist/features/messages/schemas/firestore.d.ts +15 -0
- package/dist/features/orders/hooks/useOrders.js +4 -2
- package/dist/features/orders/repository/orders.repository.d.ts +15 -4
- package/dist/features/orders/repository/orders.repository.js +52 -20
- package/dist/features/orders/schemas/firestore.d.ts +15 -4
- package/dist/features/orders/schemas/index.d.ts +8 -8
- package/dist/features/orders/types/index.d.ts +2 -2
- package/dist/features/payments/repository/payments.repository.js +2 -2
- package/dist/features/payments/repository/payout.repository.d.ts +23 -6
- package/dist/features/payments/repository/payout.repository.js +63 -23
- package/dist/features/payments/repository/saved-payment-methods.repository.d.ts +17 -6
- package/dist/features/payments/repository/saved-payment-methods.repository.js +59 -11
- package/dist/features/payments/schemas/firestore.d.ts +14 -3
- package/dist/features/payments/schemas/saved-methods-firestore.d.ts +12 -1
- package/dist/features/pre-orders/api/[slug]/route.js +1 -1
- package/dist/features/pre-orders/api/admin/route.js +1 -1
- package/dist/features/pre-orders/api/route.js +1 -1
- package/dist/features/pre-orders/repository/pre-orders.repository.d.ts +3 -3
- package/dist/features/pre-orders/repository/pre-orders.repository.js +6 -6
- package/dist/features/products/api/[id]/route.js +1 -1
- package/dist/features/products/components/ListingBottomActions.js +4 -0
- package/dist/features/products/components/ProductDetailPageView.js +2 -1
- package/dist/features/products/components/ProductGalleryClient.js +2 -2
- package/dist/features/products/components/ProductGrid.js +12 -1
- package/dist/features/products/components/index.d.ts +0 -2
- package/dist/features/products/components/index.js +0 -1
- package/dist/features/products/config/listing-type-listing-config.d.ts +0 -3
- package/dist/features/products/config/listing-type-listing-config.js +27 -2
- package/dist/features/products/constants/listing-tabs.d.ts +9 -0
- package/dist/features/products/constants/listing-tabs.js +3 -2
- package/dist/features/products/hooks/useProducts.js +2 -2
- package/dist/features/products/repository/products.repository.js +13 -1
- package/dist/features/products/schemas/index.d.ts +2 -2
- package/dist/features/products/types/index.d.ts +1 -1
- package/dist/features/promotions/api/route.js +1 -1
- package/dist/features/reviews/actions/review-actions.d.ts +6 -6
- package/dist/features/reviews/actions/review-actions.js +22 -8
- package/dist/features/reviews/components/ReviewDetailPageView.js +13 -1
- package/dist/features/reviews/components/ReviewsIndexPageView.js +21 -4
- package/dist/features/reviews/repository/reviews.repository.d.ts +19 -7
- package/dist/features/reviews/repository/reviews.repository.js +63 -12
- package/dist/features/reviews/schemas/firestore.d.ts +13 -2
- package/dist/features/reviews/schemas/index.d.ts +2 -2
- package/dist/features/scams/actions/scam-actions.js +16 -4
- package/dist/features/search/components/SearchResultsPageView.js +2 -1
- package/dist/features/search/hooks/useSearchIndex.d.ts +34 -0
- package/dist/features/search/hooks/useSearchIndex.js +172 -0
- package/dist/features/search/repository/search.repository.js +2 -2
- package/dist/features/seller/actions/offer-actions.d.ts +5 -5
- package/dist/features/seller/actions/offer-actions.js +38 -8
- package/dist/features/seller/actions/seller-actions.js +34 -7
- package/dist/features/seller/api/coupons/route.js +1 -1
- package/dist/features/seller/api/products/route.js +1 -1
- package/dist/features/seller/api/store/route.js +1 -1
- package/dist/features/seller/components/SellerBidsView.js +1 -1
- package/dist/features/seller/components/SellerCouponsView.js +1 -1
- package/dist/features/seller/components/SellerListingTypeView.js +9 -1
- package/dist/features/seller/components/SellerOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +0 -1
- package/dist/features/seller/components/SellerPayoutsView.js +1 -1
- package/dist/features/seller/components/SellerProductShell.js +0 -1
- package/dist/features/seller/components/SellerProductsView.js +1 -1
- package/dist/features/seller/components/SellerShippingView.js +0 -1
- package/dist/features/seller/components/SellerStorefrontView.js +0 -1
- package/dist/features/seller/components/index.d.ts +0 -4
- package/dist/features/seller/components/index.js +0 -2
- package/dist/features/seller/repository/offer.repository.d.ts +15 -3
- package/dist/features/seller/repository/offer.repository.js +43 -7
- package/dist/features/seller/schemas/firestore.d.ts +14 -3
- package/dist/features/seller/schemas/index.d.ts +4 -4
- package/dist/features/seller/schemas/order-forms.d.ts +39 -0
- package/dist/features/seller/schemas/order-forms.js +37 -0
- package/dist/features/shell/FormShell.js +6 -2
- package/dist/features/shell/QuickFormDrawer.js +15 -1
- package/dist/features/shipments/components/AdminShipmentEditorView.js +0 -1
- package/dist/features/shipments/components/AdminShipmentsView.js +1 -1
- package/dist/features/sticker-trace/components/StickerCommitPanel.d.ts +30 -0
- package/dist/features/sticker-trace/components/StickerCommitPanel.js +93 -0
- package/dist/features/sticker-trace/components/StickerPrintPanel.d.ts +33 -0
- package/dist/features/sticker-trace/components/StickerPrintPanel.js +104 -0
- package/dist/features/sticker-trace/components/StickerRetryPanel.d.ts +20 -0
- package/dist/features/sticker-trace/components/StickerRetryPanel.js +128 -0
- package/dist/features/sticker-trace/components/StickerRunHistoryPanel.d.ts +45 -0
- package/dist/features/sticker-trace/components/StickerRunHistoryPanel.js +84 -0
- package/dist/features/sticker-trace/components/StickerTraceStudio.d.ts +27 -0
- package/dist/features/sticker-trace/components/StickerTraceStudio.js +171 -0
- package/dist/features/sticker-trace/constants/help-content.d.ts +23 -0
- package/dist/features/sticker-trace/constants/help-content.js +172 -0
- package/dist/features/sticker-trace/hooks/useLiveTrace.d.ts +27 -0
- package/dist/features/sticker-trace/hooks/useLiveTrace.js +160 -0
- package/dist/features/sticker-trace/hooks/useStickerTraceProgress.d.ts +22 -0
- package/dist/features/sticker-trace/hooks/useStickerTraceProgress.js +106 -0
- package/dist/features/sticker-trace/repository/sticker-sheets.repository.d.ts +113 -0
- package/dist/features/sticker-trace/repository/sticker-sheets.repository.js +146 -0
- package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.d.ts +132 -0
- package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.js +174 -0
- package/dist/features/sticker-trace/schemas/firestore.d.ts +248 -0
- package/dist/features/sticker-trace/schemas/firestore.js +79 -0
- package/dist/features/sticker-trace/server.d.ts +8 -0
- package/dist/features/sticker-trace/server.js +51 -0
- package/dist/features/stores/actions/store-query-actions.d.ts +2 -2
- package/dist/features/stores/actions/store-query-actions.js +7 -2
- package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -3
- package/dist/features/stores/api/[storeSlug]/products/route.js +3 -3
- package/dist/features/stores/api/[storeSlug]/reviews/route.js +1 -1
- package/dist/features/stores/api/[storeSlug]/route.js +1 -1
- package/dist/features/stores/components/StoreNavTabs.js +17 -2
- package/dist/features/stores/manifest.js +8 -4
- package/dist/features/support/repository/support.repository.d.ts +14 -3
- package/dist/features/support/repository/support.repository.js +93 -13
- package/dist/features/support/schemas/firestore.d.ts +16 -5
- package/dist/features/tester/seed-data/authored/admin__events-raffles-spin.js +61 -19
- package/dist/features/tester/seed-data/authored/buying__browsing-search.js +19 -3
- 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 +243 -0
- package/dist/features/tester/seed-data/authored/content-discovery__events.js +36 -10
- package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.js +209 -0
- package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.js +90 -0
- package/dist/features/tester/seed-data/authored/design-ux__header-controls-and-messages.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/design-ux__header-controls-and-messages.js +85 -0
- package/dist/features/tester/seed-data/authored/index.js +10 -0
- package/dist/features/tester/seed-data/authored/selling__media-limits.js +19 -17
- package/dist/features/tester/seed-data/authored/selling__product-upload-details.js +10 -5
- package/dist/features/tester/seed-data/authored/tools__sticker-tracer.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +283 -0
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +235 -22
- package/dist/index.d.ts +10 -23
- package/dist/index.js +27 -19
- package/dist/next/api/routeHandler.js +9 -0
- package/dist/next/routing/require-record.d.ts +13 -0
- package/dist/next/routing/require-record.js +62 -0
- package/dist/next/routing/route-map.d.ts +4 -4
- package/dist/next/routing/route-map.js +25 -3
- package/dist/providers/db-firebase/base.d.ts +4 -2
- package/dist/providers/db-firebase/base.js +21 -5
- package/dist/providers/db-firebase/base.repository.d.ts +11 -9
- package/dist/providers/db-firebase/base.repository.js +19 -0
- package/dist/providers/db-firebase/rtdb-paths.d.ts +12 -0
- package/dist/providers/db-firebase/rtdb-paths.js +12 -0
- package/dist/react/ErrorBoundary.js +6 -1
- package/dist/react/hooks/realtime-event-constants.d.ts +1 -0
- package/dist/react/hooks/realtime-event-constants.js +8 -0
- package/dist/react/hooks/useEntityDelete.js +5 -1
- package/dist/react/hooks/useMessage.js +5 -1
- package/dist/repositories/index.d.ts +2 -2
- package/dist/repositories/index.js +6 -1
- package/dist/schemas/registry.d.ts +13 -20
- package/dist/schemas/registry.js +31 -14
- package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
- package/dist/security/encrypted.d.ts +117 -0
- package/dist/security/encrypted.js +100 -0
- package/dist/security/index.d.ts +5 -2
- package/dist/security/index.js +16 -2
- package/dist/security/pii-accessors.d.ts +71 -0
- package/dist/security/pii-accessors.js +150 -0
- package/dist/security/pii-encrypt.d.ts +0 -8
- package/dist/security/pii-encrypt.js +22 -15
- package/dist/security/pii-mask.d.ts +18 -0
- package/dist/security/pii-mask.js +27 -0
- package/dist/seed/_helpers/search-txt-wrappers.d.ts +6 -6
- package/dist/seed/_helpers/search-txt-wrappers.js +22 -0
- package/dist/seed/addresses-seed-data.d.ts +2 -2
- package/dist/seed/authenticity-knowledge-seed-data.d.ts +34 -0
- package/dist/seed/authenticity-knowledge-seed-data.js +1277 -0
- package/dist/seed/bids-seed-data.d.ts +2 -2
- package/dist/seed/bids-seed-data.js +23 -2
- package/dist/seed/events-seed-data.d.ts +2 -2
- package/dist/seed/events-seed-data.js +5 -0
- package/dist/seed/faq-seed-data.js +175 -5
- package/dist/seed/homepage-sections-seed-data.js +39 -23
- package/dist/seed/index.d.ts +1 -0
- package/dist/seed/index.js +1 -0
- package/dist/seed/lottery-entries-seed-data.d.ts +2 -2
- package/dist/seed/offers-seed-data.d.ts +2 -2
- package/dist/seed/offers-seed-data.js +1 -1
- package/dist/seed/orders-seed-data.d.ts +2 -2
- package/dist/seed/payouts-seed-data.d.ts +2 -2
- package/dist/seed/payouts-seed-data.js +1 -1
- package/dist/seed/reviews-seed-data.d.ts +1 -2
- package/dist/seed/seed-purpose.js +7 -0
- package/dist/seed/sessions-seed-data.d.ts +2 -2
- package/dist/seed/sessions-seed-data.js +5 -0
- package/dist/seed/site-settings-seed-data.js +1 -1
- package/dist/seed/support-tickets-seed-data.d.ts +2 -2
- package/dist/seed/support-tickets-seed-data.js +1 -1
- package/dist/seed/users-seed-data.d.ts +2 -2
- package/dist/seed/users-seed-data.js +1 -1
- package/dist/seo/json-ld.js +5 -1
- package/dist/server.d.ts +18 -3
- package/dist/server.js +59 -3
- package/dist/styles.css +237 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/Button.js +7 -1
- package/dist/ui/components/FilterChipGroup.d.ts +11 -0
- package/dist/ui/components/FilterChipGroup.js +1 -1
- package/dist/ui/components/ImageGallery.js +6 -1
- package/dist/ui/components/ListingLayout.js +14 -8
- package/dist/ui/components/OverflowRow.d.ts +92 -0
- package/dist/ui/components/OverflowRow.js +203 -0
- package/dist/ui/components/OverflowRow.style.css +235 -0
- package/dist/ui/components/RecordDetailModal.js +14 -1
- package/dist/ui/components/RowActionMenu.js +5 -1
- package/dist/ui/components/SideDrawer.js +5 -1
- package/dist/ui/components/SideModal.js +9 -1
- package/dist/ui/components/TabBarShell.d.ts +12 -1
- package/dist/ui/components/TabBarShell.js +3 -2
- package/dist/ui/components/Tabs.js +36 -24
- package/dist/ui/components/Toast.d.ts +3 -24
- package/dist/ui/components/Toast.js +2 -19
- package/dist/ui/components/TopBannerPortal.d.ts +15 -0
- package/dist/ui/components/TopBannerPortal.js +19 -0
- package/dist/ui/components/UnsavedChangesModal.js +5 -1
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/components/row-collapse.d.ts +15 -0
- package/dist/ui/components/row-collapse.js +127 -0
- package/dist/ui/components/toast-context.d.ts +63 -0
- package/dist/ui/components/toast-context.js +48 -0
- package/dist/ui/components/top-banner-slot.d.ts +37 -0
- package/dist/ui/components/top-banner-slot.js +45 -0
- package/dist/ui/icons/icon-registry.d.ts +6 -0
- package/dist/ui/icons/icon-registry.js +17 -1
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +1 -0
- package/dist/utils/array.helper.d.ts +2 -2
- package/dist/utils/array.helper.js +5 -5
- package/dist/utils/id-generators.d.ts +6 -0
- package/dist/utils/id-generators.js +10 -0
- package/dist/utils/media-url.js +0 -2
- package/dist/utils/search-txt-builders.d.ts +28 -4
- package/dist/utils/search-txt-builders.js +41 -1
- package/dist/validation/schemas.d.ts +8 -8
- package/package.json +6 -2
- package/scripts/seed-cli.mjs +3 -0
- package/dist/features/account/components/UserAddressesView.d.ts +0 -13
- package/dist/features/account/components/UserAddressesView.js +0 -5
- package/dist/features/account/components/UserNotificationsView.d.ts +0 -15
- package/dist/features/account/components/UserNotificationsView.js +0 -12
- package/dist/features/account/components/UserSettingsView.d.ts +0 -16
- package/dist/features/account/components/UserSettingsView.js +0 -13
- package/dist/features/account/components/UserSupportView.d.ts +0 -3
- package/dist/features/account/components/UserSupportView.js +0 -166
- package/dist/features/admin/components/DemoSeedView.d.ts +0 -11
- package/dist/features/admin/components/DemoSeedView.js +0 -5
- package/dist/features/auth/components/AuthStatusPanel.d.ts +0 -10
- package/dist/features/auth/components/AuthStatusPanel.js +0 -22
- package/dist/features/categories/components/CategoryProductsView.d.ts +0 -45
- package/dist/features/categories/components/CategoryProductsView.js +0 -21
- package/dist/features/homepage/components/HowItWorksInfoView.d.ts +0 -36
- package/dist/features/homepage/components/HowItWorksInfoView.js +0 -10
- package/dist/features/layout/BottomActions.d.ts +0 -1
- package/dist/features/layout/BottomActions.js +0 -311
- package/dist/features/products/components/ProductsView.d.ts +0 -6
- package/dist/features/products/components/ProductsView.js +0 -5
- package/dist/features/seller/components/SellerStoreView.d.ts +0 -8
- package/dist/features/seller/components/SellerStoreView.js +0 -8
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { SearchIndexType } from "../../../../shared/search/index-record";
|
|
2
|
+
import type { FirestoreValue } from "../../../../../schemas/types";
|
|
3
|
+
export type IndexDocData = Record<string, FirestoreValue>;
|
|
4
|
+
/** One record under construction. `null` drops the document from the index. */
|
|
5
|
+
export interface BuiltRecord {
|
|
6
|
+
readonly title: string;
|
|
7
|
+
readonly detail: string;
|
|
8
|
+
readonly facets?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface IndexSource {
|
|
11
|
+
/** Matches a `SearchIndexType.key`. */
|
|
12
|
+
readonly typeKey: string;
|
|
13
|
+
readonly collection: string;
|
|
14
|
+
/** Fields to project. A builder reads documents, not whole collections. */
|
|
15
|
+
readonly select: readonly string[];
|
|
16
|
+
/**
|
|
17
|
+
* Extra equality narrowing applied as a query clause. Only use this for a
|
|
18
|
+
* value every public row genuinely carries — otherwise filter in `toRecord`,
|
|
19
|
+
* because a Firestore equality on an absent field matches nothing and an
|
|
20
|
+
* inequality excludes every document lacking it.
|
|
21
|
+
*/
|
|
22
|
+
readonly where?: ReadonlyArray<readonly [string, unknown]>;
|
|
23
|
+
/**
|
|
24
|
+
* The record's stable identity, and the artifact's patch key.
|
|
25
|
+
*
|
|
26
|
+
* 🛑 SEPARATE from `toRecord` on purpose. An incremental build must be able
|
|
27
|
+
* to key a document it is REMOVING — one that just became unpublished — and
|
|
28
|
+
* at that moment `toRecord` has returned null and cannot supply a slug. With
|
|
29
|
+
* the slug folded into `toRecord` the two paths keyed differently (doc id on
|
|
30
|
+
* the way out, slug on the way in), which agrees only where slug === id: so
|
|
31
|
+
* every changed product would have been ADDED as a duplicate rather than
|
|
32
|
+
* replaced, while categories and stores looked fine.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Resolve the type PER DOCUMENT, when one collection holds several.
|
|
36
|
+
* `products` is the only such collection today: all nine listing types live
|
|
37
|
+
* in it and each has its own detail route.
|
|
38
|
+
*/
|
|
39
|
+
readonly typeKeyOf?: (d: IndexDocData) => string;
|
|
40
|
+
readonly slugOf: (id: string, d: IndexDocData) => string | null;
|
|
41
|
+
readonly toRecord: (id: string, d: IndexDocData) => BuiltRecord | null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The type table shipped inside the artifact.
|
|
45
|
+
*
|
|
46
|
+
* 🛑 No `label`. The client maps `key` to a translated string; a heading baked
|
|
47
|
+
* in here could not be localised. Weights are a ranking nudge between types
|
|
48
|
+
* that scored equally, not a statement about importance.
|
|
49
|
+
*/
|
|
50
|
+
export declare const INDEX_TYPES: readonly SearchIndexType[];
|
|
51
|
+
export declare const PUBLIC_INDEX_SOURCES: readonly IndexSource[];
|
|
52
|
+
/** Index into `INDEX_TYPES` for a source's type key. */
|
|
53
|
+
export declare function typeIndexFor(typeKey: string): number;
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: What goes into the public search artifact — an unauthenticated,
|
|
3
|
+
* immutable, CDN-cached body downloaded by every visitor who searches.
|
|
4
|
+
* WHAT: The membership allowlist and the per-collection record mapping.
|
|
5
|
+
*
|
|
6
|
+
* ## 🛑 MEMBERSHIP IS AN ALLOWLIST. It is deliberately NOT `LISTERS`.
|
|
7
|
+
*
|
|
8
|
+
* `listingProcessor.ts`'s `LISTERS` is a tempting source registry — one entry
|
|
9
|
+
* per collection, already routed through the Sieve adapter, with its own
|
|
10
|
+
* header inviting "a one-line addition". It is the wrong list. Counted
|
|
11
|
+
* 2026-10-19 it holds **20** entries, and four of them are **`users`,
|
|
12
|
+
* `payouts`, `orders`, `notifications`**. "Index everything LISTERS knows
|
|
13
|
+
* about" is one line away from publishing every customer's name to every
|
|
14
|
+
* browser, permanently, for the life of that artifact version.
|
|
15
|
+
*
|
|
16
|
+
* So this file names what is public, and `LISTERS` is only used to READ it.
|
|
17
|
+
* `audit-search-index-artifact` R6 asserts the intersection of this list with
|
|
18
|
+
* the PII and private registries is empty, with "add `users` → must fail" as
|
|
19
|
+
* its negative control.
|
|
20
|
+
*
|
|
21
|
+
* ## 🛑 Every field here was read off the LIVE documents
|
|
22
|
+
*
|
|
23
|
+
* The same rule `search-sources.ts` states, and it earned its keep again:
|
|
24
|
+
* `scammerProfiles` carries `displayNames` (an ARRAY) not `displayName`, and
|
|
25
|
+
* a string read would have produced a null title for every row — the group
|
|
26
|
+
* would simply never have appeared. `partGlossary`'s page needs TWO path
|
|
27
|
+
* segments and its document id already encodes them as `${slot}--${code}`.
|
|
28
|
+
*
|
|
29
|
+
* ## What a record carries, and what it must never carry
|
|
30
|
+
*
|
|
31
|
+
* Title, a one-line detail, a slug and optional facets. No amount of any kind
|
|
32
|
+
* (§ Guest price gating cannot reach an unauthenticated artifact) and no PII.
|
|
33
|
+
*
|
|
34
|
+
* @tag domain:search
|
|
35
|
+
* @tag layer:server
|
|
36
|
+
* @tag pattern:none
|
|
37
|
+
* @tag access:server
|
|
38
|
+
* @tag consumers:index-build/build,searchIndexBuild
|
|
39
|
+
* @tag sideEffects:none
|
|
40
|
+
*/
|
|
41
|
+
import { pluginFor } from "../../../../shared/listing-types/_registry.js";
|
|
42
|
+
// Defined here, not in `_registry` — imported from the DEFINING module
|
|
43
|
+
// (Root Cause #18).
|
|
44
|
+
import { ALL_LISTING_TYPES } from "../../../../shared/listing-types/feature-flags.js";
|
|
45
|
+
const str = (v) => typeof v === "string" && v.trim() ? v.trim() : null;
|
|
46
|
+
/**
|
|
47
|
+
* The type table shipped inside the artifact.
|
|
48
|
+
*
|
|
49
|
+
* 🛑 No `label`. The client maps `key` to a translated string; a heading baked
|
|
50
|
+
* in here could not be localised. Weights are a ranking nudge between types
|
|
51
|
+
* that scored equally, not a statement about importance.
|
|
52
|
+
*/
|
|
53
|
+
export const INDEX_TYPES = [
|
|
54
|
+
/*
|
|
55
|
+
* 🛑 ONE ENTRY PER LISTING TYPE, DERIVED from the plugin registry — not one
|
|
56
|
+
* `product` entry for the whole collection.
|
|
57
|
+
*
|
|
58
|
+
* The first draft had a single `{ key: "product", hrefTemplate:
|
|
59
|
+
* "/products/{s}" }`, which is Root Cause #48 rebuilt from scratch: "a
|
|
60
|
+
* per-listing-type detailRoute() that silently defaults to the standard
|
|
61
|
+
* product page". An auction lives at `/auctions/{slug}`, a pre-order at
|
|
62
|
+
* `/pre-orders/{slug}`, a classified at `/classified/{slug}`. Every one of
|
|
63
|
+
* those results would have rendered correctly and navigated to the wrong
|
|
64
|
+
* page — the exact failure that made non-standard listings "revert to
|
|
65
|
+
* standard" the first time.
|
|
66
|
+
*
|
|
67
|
+
* `detailRoute` and `browseRoute` come from `pluginFor`, so a tenth listing
|
|
68
|
+
* type is covered the day it is added rather than the day someone notices.
|
|
69
|
+
* Hand-writing them here would be the eleventh enumeration of that union
|
|
70
|
+
* (Root Cause #61).
|
|
71
|
+
*/
|
|
72
|
+
...ALL_LISTING_TYPES.map((t) => {
|
|
73
|
+
const plugin = pluginFor(t);
|
|
74
|
+
return {
|
|
75
|
+
key: t,
|
|
76
|
+
// `detailRoute` builds a concrete path, so hand it the placeholder and
|
|
77
|
+
// let it produce the template. One source of truth, no second mapping.
|
|
78
|
+
hrefTemplate: plugin.detailRoute("{s}"),
|
|
79
|
+
moreHref: String(plugin.browseRoute),
|
|
80
|
+
// Standard listings are the catalogue's centre of gravity; the rest sit
|
|
81
|
+
// just below so a same-score tie favours the commonest thing.
|
|
82
|
+
weight: t === "standard" ? 1.0 : 0.98,
|
|
83
|
+
};
|
|
84
|
+
}),
|
|
85
|
+
{ key: "category", hrefTemplate: "/categories/{s}", moreHref: "/categories", weight: 0.95 },
|
|
86
|
+
{ key: "brand", hrefTemplate: "/brands/{s}", moreHref: "/brands", weight: 0.9 },
|
|
87
|
+
{ key: "part", hrefTemplate: "/parts/{s}", moreHref: "/parts", weight: 0.9 },
|
|
88
|
+
{ key: "model", hrefTemplate: "/categories/{s}", moreHref: "/categories", weight: 0.85 },
|
|
89
|
+
{ key: "store", hrefTemplate: "/stores/{s}", moreHref: "/stores", weight: 0.8 },
|
|
90
|
+
{ key: "blog", hrefTemplate: "/blog/{s}", moreHref: "/blog", weight: 0.7 },
|
|
91
|
+
{ key: "event", hrefTemplate: "/events/{s}", moreHref: "/events", weight: 0.7 },
|
|
92
|
+
{ key: "faq", hrefTemplate: "/faqs/{s}", moreHref: "/faqs", weight: 0.6 },
|
|
93
|
+
{ key: "review", hrefTemplate: "/reviews/{s}", moreHref: "/reviews", weight: 0.5 },
|
|
94
|
+
{ key: "group", hrefTemplate: "/groups/{s}", moreHref: "/products", weight: 0.5 },
|
|
95
|
+
{ key: "scammer", hrefTemplate: "/scams/{s}", moreHref: "/scams", weight: 0.5 },
|
|
96
|
+
/* `/promotions` has no per-coupon page, so `{s}` is absent on purpose and
|
|
97
|
+
* `hrefFor`'s replace is a no-op. Eleven rows all landing on one page would
|
|
98
|
+
* be noise in the federated GROUP (which is why `search-sources.ts` omits
|
|
99
|
+
* coupons), but in the index it is the difference between a code being
|
|
100
|
+
* findable and not. */
|
|
101
|
+
{ key: "coupon", hrefTemplate: "/promotions", moreHref: "/promotions", weight: 0.4 },
|
|
102
|
+
];
|
|
103
|
+
const facet = (pairs) => {
|
|
104
|
+
const parts = pairs
|
|
105
|
+
.filter(([, v]) => typeof v === "string" && v)
|
|
106
|
+
.map(([k, v]) => `${k}:${v}`);
|
|
107
|
+
return parts.length > 0 ? parts.join("|") : undefined;
|
|
108
|
+
};
|
|
109
|
+
export const PUBLIC_INDEX_SOURCES = [
|
|
110
|
+
{
|
|
111
|
+
/*
|
|
112
|
+
* 🛑 The type key is RESOLVED PER DOCUMENT — see `typeKeyOf`. A source
|
|
113
|
+
* normally maps one collection to one type, but `products` holds all nine
|
|
114
|
+
* listing types and each has its own detail route.
|
|
115
|
+
*/
|
|
116
|
+
typeKey: "standard",
|
|
117
|
+
typeKeyOf: (d) => {
|
|
118
|
+
const lt = str(d.listingType);
|
|
119
|
+
return lt && ALL_LISTING_TYPES.includes(lt) ? lt : "standard";
|
|
120
|
+
},
|
|
121
|
+
collection: "products",
|
|
122
|
+
where: [["status", "published"]],
|
|
123
|
+
select: ["title", "slug", "brand", "categoryNames", "listingType", "condition", "franchiseSlug"],
|
|
124
|
+
slugOf: (id, d) => str(d.slug) ?? id,
|
|
125
|
+
toRecord: (id, d) => {
|
|
126
|
+
const title = str(d.title);
|
|
127
|
+
if (!title)
|
|
128
|
+
return null;
|
|
129
|
+
const names = Array.isArray(d.categoryNames) ? d.categoryNames : [];
|
|
130
|
+
/*
|
|
131
|
+
* 🛑 The enum VALUES go in `detail`, which is SEARCHED — the `facets`
|
|
132
|
+
* string is filter-only and never matched as text. Without this,
|
|
133
|
+
* typing "auction" or "sealed" finds nothing, because the only place
|
|
134
|
+
* those words appeared was a facet nobody searches. Humanised, so
|
|
135
|
+
* "pre-order" and "digital code" read as words rather than slugs.
|
|
136
|
+
*/
|
|
137
|
+
const human = (v) => (str(v) ?? "").replace(/[-_]/g, " ");
|
|
138
|
+
return {
|
|
139
|
+
title,
|
|
140
|
+
// Leaf-first, so [0] is the most specific label.
|
|
141
|
+
detail: [
|
|
142
|
+
str(d.brand),
|
|
143
|
+
str(names[0]),
|
|
144
|
+
human(d.listingType),
|
|
145
|
+
human(d.condition),
|
|
146
|
+
]
|
|
147
|
+
.filter(Boolean)
|
|
148
|
+
.join(" · "),
|
|
149
|
+
facets: facet([
|
|
150
|
+
["lt", d.listingType],
|
|
151
|
+
["cn", d.condition],
|
|
152
|
+
["fr", d.franchiseSlug],
|
|
153
|
+
]),
|
|
154
|
+
};
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
typeKey: "category",
|
|
159
|
+
collection: "categories",
|
|
160
|
+
/*
|
|
161
|
+
* 🛑 No `where` on `categoryType`. A plain listing category OMITS the
|
|
162
|
+
* field entirely — the convention CLAUDE.md records — so `== "category"`
|
|
163
|
+
* matches nothing and `!=` excludes every real row. Brands are their own
|
|
164
|
+
* type below and are rejected here rather than dropped.
|
|
165
|
+
*/
|
|
166
|
+
select: ["name", "slug", "categoryType", "path", "isActive"],
|
|
167
|
+
slugOf: (id) => id,
|
|
168
|
+
toRecord: (id, d) => {
|
|
169
|
+
const name = str(d.name);
|
|
170
|
+
if (!name)
|
|
171
|
+
return null;
|
|
172
|
+
const type = str(d.categoryType);
|
|
173
|
+
if (type && type !== "sublisting")
|
|
174
|
+
return null;
|
|
175
|
+
if (d.isActive === false)
|
|
176
|
+
return null;
|
|
177
|
+
return { title: name, detail: str(d.path) ?? "", slug: id };
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
typeKey: "brand",
|
|
182
|
+
collection: "categories",
|
|
183
|
+
where: [["categoryType", "brand"]],
|
|
184
|
+
select: ["name", "brandCountry", "isActive"],
|
|
185
|
+
slugOf: (id) => id,
|
|
186
|
+
toRecord: (id, d) => {
|
|
187
|
+
const name = str(d.name);
|
|
188
|
+
if (!name)
|
|
189
|
+
return null;
|
|
190
|
+
if (d.isActive === false)
|
|
191
|
+
return null;
|
|
192
|
+
return { title: name, detail: str(d.brandCountry) ?? "", slug: id };
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
typeKey: "part",
|
|
197
|
+
collection: "partGlossary",
|
|
198
|
+
select: ["name", "code", "classification", "slot"],
|
|
199
|
+
slugOf: (id) => (id.includes("--") ? id.replace("--", "/") : null),
|
|
200
|
+
toRecord: (id, d) => {
|
|
201
|
+
const name = str(d.name);
|
|
202
|
+
if (!name)
|
|
203
|
+
return null;
|
|
204
|
+
/*
|
|
205
|
+
* 🛑 TWO path segments, and the document id already encodes them.
|
|
206
|
+
* `ROUTES.PUBLIC.PART_DETAIL` is `/parts/{classification}/{code}`, and
|
|
207
|
+
* the route-map comment explains why a code alone cannot be a URL:
|
|
208
|
+
* "`105` is a Metal Fight spin-track height, a bare number in Burst is
|
|
209
|
+
* a disc, and `1-60` is a Beyblade X ratchet." The id is
|
|
210
|
+
* `${slot}--${code}` (e.g. `armour--1b`), so splitting it is the one
|
|
211
|
+
* derivation guaranteed to agree with the page that exists.
|
|
212
|
+
*/
|
|
213
|
+
if (!id.includes("--"))
|
|
214
|
+
return null;
|
|
215
|
+
const code = str(d.code);
|
|
216
|
+
const classification = str(d.classification);
|
|
217
|
+
return {
|
|
218
|
+
title: name,
|
|
219
|
+
// The classification IS the disambiguation — it is why a user
|
|
220
|
+
// searching "105" can tell three results apart.
|
|
221
|
+
detail: [classification, code].filter(Boolean).join(" · "),
|
|
222
|
+
};
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
typeKey: "model",
|
|
227
|
+
collection: "modelComposition",
|
|
228
|
+
select: ["name", "system", "categoryId"],
|
|
229
|
+
slugOf: (_id, d) => str(d.categoryId),
|
|
230
|
+
toRecord: (_id, d) => {
|
|
231
|
+
const name = str(d.name);
|
|
232
|
+
if (!name)
|
|
233
|
+
return null;
|
|
234
|
+
/*
|
|
235
|
+
* 🛑 A composition has no page of its own — it is rendered on its model
|
|
236
|
+
* CATEGORY page, reached by `categoryId`. Measured in `parts/data.ts`:
|
|
237
|
+
* 210 of 259 join. The 49 that do not are DROPPED rather than linked to
|
|
238
|
+
* a guess, because a search result that navigates to the wrong bey is
|
|
239
|
+
* worse than one that does not exist. The builder reports the count.
|
|
240
|
+
*/
|
|
241
|
+
const categoryId = str(d.categoryId);
|
|
242
|
+
if (!categoryId)
|
|
243
|
+
return null;
|
|
244
|
+
return { title: name, detail: str(d.system) ?? "", slug: categoryId };
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
typeKey: "store",
|
|
249
|
+
collection: "stores",
|
|
250
|
+
where: [["status", "active"]],
|
|
251
|
+
// `storeName`, not `name` — read off the live documents.
|
|
252
|
+
select: ["storeName", "storeCategory"],
|
|
253
|
+
slugOf: (id) => id,
|
|
254
|
+
toRecord: (id, d) => {
|
|
255
|
+
const name = str(d.storeName);
|
|
256
|
+
if (!name)
|
|
257
|
+
return null;
|
|
258
|
+
return { title: name, detail: str(d.storeCategory) ?? "", slug: id };
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
typeKey: "blog",
|
|
263
|
+
collection: "blogPosts",
|
|
264
|
+
where: [["status", "published"]],
|
|
265
|
+
select: ["title", "slug", "category", "excerpt"],
|
|
266
|
+
slugOf: (id, d) => str(d.slug) ?? id,
|
|
267
|
+
toRecord: (id, d) => {
|
|
268
|
+
const title = str(d.title);
|
|
269
|
+
if (!title)
|
|
270
|
+
return null;
|
|
271
|
+
return {
|
|
272
|
+
title,
|
|
273
|
+
detail: str(d.category) ?? (str(d.excerpt) ?? "").slice(0, 90),
|
|
274
|
+
};
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
typeKey: "event",
|
|
279
|
+
collection: "events",
|
|
280
|
+
// Three public statuses, one `==` — so it is filtered in memory, the same
|
|
281
|
+
// reason `search-sources.ts` gives.
|
|
282
|
+
select: ["title", "slug", "type", "status"],
|
|
283
|
+
slugOf: (id, d) => str(d.slug) ?? id,
|
|
284
|
+
toRecord: (id, d) => {
|
|
285
|
+
const title = str(d.title);
|
|
286
|
+
if (!title)
|
|
287
|
+
return null;
|
|
288
|
+
const status = str(d.status);
|
|
289
|
+
if (status === "draft" || status === "cancelled")
|
|
290
|
+
return null;
|
|
291
|
+
return { title, detail: (str(d.type) ?? "").replace(/_/g, " "), slug: str(d.slug) ?? id };
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
typeKey: "faq",
|
|
296
|
+
collection: "faqs",
|
|
297
|
+
where: [["isActive", true]],
|
|
298
|
+
select: ["question", "category"],
|
|
299
|
+
slugOf: (_id, d) => str(d.category),
|
|
300
|
+
toRecord: (_id, d) => {
|
|
301
|
+
const question = str(d.question);
|
|
302
|
+
const category = str(d.category);
|
|
303
|
+
// `/faqs/[category]`, never a question slug — the route matches on the
|
|
304
|
+
// category key and silently falls back to "all" for anything else.
|
|
305
|
+
if (!question || !category)
|
|
306
|
+
return null;
|
|
307
|
+
return { title: question, detail: category.replace(/_/g, " "), slug: category };
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
typeKey: "review",
|
|
312
|
+
collection: "reviews",
|
|
313
|
+
where: [["status", "approved"]],
|
|
314
|
+
// 🛑 `productTitle`, never `userName`. The field exists on the document
|
|
315
|
+
// and is deliberately absent from `buildReviewSearchTxt` because it is
|
|
316
|
+
// encrypted; a public artifact must not carry a reviewer's name.
|
|
317
|
+
select: ["title", "productTitle"],
|
|
318
|
+
slugOf: (id) => id,
|
|
319
|
+
toRecord: (id, d) => {
|
|
320
|
+
const title = str(d.title);
|
|
321
|
+
if (!title)
|
|
322
|
+
return null;
|
|
323
|
+
return { title, detail: str(d.productTitle) ?? "", slug: id };
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
typeKey: "group",
|
|
328
|
+
collection: "groupedListings",
|
|
329
|
+
where: [["isActive", true]],
|
|
330
|
+
select: ["title", "slug", "groupTheme", "visibilityStatus"],
|
|
331
|
+
slugOf: (id, d) => str(d.slug) ?? id,
|
|
332
|
+
toRecord: (id, d) => {
|
|
333
|
+
const title = str(d.title);
|
|
334
|
+
if (!title)
|
|
335
|
+
return null;
|
|
336
|
+
if (str(d.visibilityStatus) !== "visible")
|
|
337
|
+
return null;
|
|
338
|
+
return { title, detail: str(d.groupTheme) ?? "", slug: str(d.slug) ?? id };
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
typeKey: "scammer",
|
|
343
|
+
collection: "scammerProfiles",
|
|
344
|
+
/*
|
|
345
|
+
* 🛑 `verified` ONLY. Live: verified 3, pending_review 1, rejected 1.
|
|
346
|
+
* Publishing an unaccepted allegation against a named person — with their
|
|
347
|
+
* phone and UPI on the destination page — into an artifact every browser
|
|
348
|
+
* downloads is the most consequential clause in this file.
|
|
349
|
+
*/
|
|
350
|
+
where: [["status", "verified"]],
|
|
351
|
+
select: ["displayNames", "scamType", "slug"],
|
|
352
|
+
slugOf: (id, d) => str(d.slug) ?? id,
|
|
353
|
+
toRecord: (id, d) => {
|
|
354
|
+
const names = Array.isArray(d.displayNames) ? d.displayNames : [];
|
|
355
|
+
const title = str(names[0]);
|
|
356
|
+
if (!title)
|
|
357
|
+
return null;
|
|
358
|
+
return {
|
|
359
|
+
title,
|
|
360
|
+
detail: (str(d.scamType) ?? "").replace(/_/g, " "),
|
|
361
|
+
};
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
typeKey: "coupon",
|
|
366
|
+
collection: "coupons",
|
|
367
|
+
select: ["code", "name", "validity"],
|
|
368
|
+
slugOf: (_id, d) => str(d.code),
|
|
369
|
+
toRecord: (_id, d) => {
|
|
370
|
+
const code = str(d.code);
|
|
371
|
+
if (!code)
|
|
372
|
+
return null;
|
|
373
|
+
const validity = d.validity;
|
|
374
|
+
if (validity?.isActive === false)
|
|
375
|
+
return null;
|
|
376
|
+
// No amount — the discount VALUE is money and stays out. The code and
|
|
377
|
+
// its name are what someone types.
|
|
378
|
+
return { title: code, detail: str(d.name) ?? "", slug: code };
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
];
|
|
382
|
+
/** Index into `INDEX_TYPES` for a source's type key. */
|
|
383
|
+
export function typeIndexFor(typeKey) {
|
|
384
|
+
return INDEX_TYPES.findIndex((t) => t.key === typeKey);
|
|
385
|
+
}
|
|
@@ -1,17 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* D2 Fix 4 — which collections `/search` spans, and how each row becomes a hit.
|
|
3
|
-
*
|
|
4
|
-
* 🛑 SIX SOURCES, not fifteen. The redirect page maps 15 `SearchResourceType`
|
|
5
|
-
* values, but nine of them are LISTING TYPES inside `products` — auctions,
|
|
6
|
-
* pre-orders, prize-draws, classified, digital-codes, live, art, bundles. One
|
|
7
|
-
* `products` query covers all of them, and a per-type query would be nine
|
|
8
|
-
* fan-outs returning overlapping rows from one collection.
|
|
9
|
-
*
|
|
10
|
-
* 🛑 Every field here was read off the live documents, not assumed. `stores`
|
|
11
|
-
* uses `storeName` (not `name`), `faqs` uses `question` + `seo.slug`, and
|
|
12
|
-
* `categories` must be filtered to listing rows because brands and bundles
|
|
13
|
-
* share the collection — the same trap that made the `/products` category
|
|
14
|
-
* facet offer "Takara-Tomy" as a browsable category (A1 item 4).
|
|
15
|
-
*/
|
|
16
1
|
import type { SearchSource } from "./search-everything";
|
|
17
2
|
export declare const SEARCH_SOURCES: readonly SearchSource[];
|
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D2 Fix 4 — which collections `/search` spans, and how each row becomes a hit.
|
|
3
|
+
*
|
|
4
|
+
* 🛑 NINE SOURCES, not fifteen. The redirect page maps 15 `SearchResourceType`
|
|
5
|
+
* values, but nine of them are LISTING TYPES inside `products` — auctions,
|
|
6
|
+
* pre-orders, prize-draws, classified, digital-codes, live, art, bundles. One
|
|
7
|
+
* `products` query covers all of them, and a per-type query would be nine
|
|
8
|
+
* fan-outs returning overlapping rows from one collection.
|
|
9
|
+
*
|
|
10
|
+
* 🛑 THREE MORE WERE PLANNED FOR THIS PASS AND DELIBERATELY LEFT OUT. Each
|
|
11
|
+
* would have been a source that renders as a working group and matches
|
|
12
|
+
* nothing, which is worse than an absent one:
|
|
13
|
+
*
|
|
14
|
+
* partGlossary (752 rows) and groupedListings (10) — **0% `searchTxt`
|
|
15
|
+
* coverage**, measured 2026-10-19. This file's mechanism is a single
|
|
16
|
+
* `array-contains` push-down on that field, so a source over either
|
|
17
|
+
* returns zero rows for every query, forever, with a 200. They are the
|
|
18
|
+
* headline gap and they are answered by the prebuilt client index, which
|
|
19
|
+
* needs a title and a slug rather than tokens — not by adding a token
|
|
20
|
+
* writer for 762 documents to serve a query path that index replaces.
|
|
21
|
+
*
|
|
22
|
+
* coupons — 100% token coverage, but there is no per-coupon public route.
|
|
23
|
+
* Every hit would link to `/promotions`, which is already this group's
|
|
24
|
+
* `moreHref`, so eleven rows would all point at one page. The code is
|
|
25
|
+
* worth finding; a group of identical links is not the way.
|
|
26
|
+
*
|
|
27
|
+
* 🛑 Every field here was read off the live documents, not assumed. `stores`
|
|
28
|
+
* uses `storeName` (not `name`), `faqs` uses `question` + `seo.slug`, and
|
|
29
|
+
* `categories` must be filtered to listing rows because brands and bundles
|
|
30
|
+
* share the collection — the same trap that made the `/products` category
|
|
31
|
+
* facet offer "Takara-Tomy" as a browsable category (A1 item 4).
|
|
32
|
+
*/
|
|
33
|
+
// Imported from the DEFINING module, not a barrel (Root Cause #18) — and
|
|
34
|
+
// never from `@mohasinac/appkit/client`, which is `"use client"` and would
|
|
35
|
+
// make ROUTES a client-reference proxy in this server file (Root Cause #76).
|
|
36
|
+
import { ROUTES } from "../../../../next/routing/route-map.js";
|
|
1
37
|
const str = (v) => typeof v === "string" && v.trim() ? v.trim() : null;
|
|
2
38
|
const withQ = (base, q) => q.trim() ? `${base}?q=${encodeURIComponent(q.trim())}` : base;
|
|
3
39
|
export const SEARCH_SOURCES = [
|
|
@@ -28,7 +64,7 @@ export const SEARCH_SOURCES = [
|
|
|
28
64
|
...(detail ? { detail } : {}),
|
|
29
65
|
};
|
|
30
66
|
},
|
|
31
|
-
moreHref: (q) => withQ(
|
|
67
|
+
moreHref: (q) => withQ(ROUTES.PUBLIC.PRODUCTS, q),
|
|
32
68
|
},
|
|
33
69
|
{
|
|
34
70
|
key: "categories",
|
|
@@ -55,7 +91,7 @@ export const SEARCH_SOURCES = [
|
|
|
55
91
|
return null;
|
|
56
92
|
return { id, title: name, href: `/categories/${id}` };
|
|
57
93
|
},
|
|
58
|
-
moreHref: (q) => withQ(
|
|
94
|
+
moreHref: (q) => withQ(ROUTES.PUBLIC.CATEGORIES, q),
|
|
59
95
|
},
|
|
60
96
|
{
|
|
61
97
|
key: "brands",
|
|
@@ -71,7 +107,7 @@ export const SEARCH_SOURCES = [
|
|
|
71
107
|
const detail = str(d.brandCountry);
|
|
72
108
|
return { id, title: name, href: `/brands/${id}`, ...(detail ? { detail } : {}) };
|
|
73
109
|
},
|
|
74
|
-
moreHref: (q) => withQ(
|
|
110
|
+
moreHref: (q) => withQ(ROUTES.PUBLIC.BRANDS, q),
|
|
75
111
|
},
|
|
76
112
|
{
|
|
77
113
|
key: "stores",
|
|
@@ -86,7 +122,7 @@ export const SEARCH_SOURCES = [
|
|
|
86
122
|
return null;
|
|
87
123
|
return { id, title: name, href: `/stores/${id}` };
|
|
88
124
|
},
|
|
89
|
-
moreHref: (q) => withQ(
|
|
125
|
+
moreHref: (q) => withQ(ROUTES.PUBLIC.STORES, q),
|
|
90
126
|
},
|
|
91
127
|
{
|
|
92
128
|
key: "blog",
|
|
@@ -106,7 +142,7 @@ export const SEARCH_SOURCES = [
|
|
|
106
142
|
...(detail ? { detail } : {}),
|
|
107
143
|
};
|
|
108
144
|
},
|
|
109
|
-
moreHref: (q) => withQ(
|
|
145
|
+
moreHref: (q) => withQ(ROUTES.BLOG.LIST, q),
|
|
110
146
|
},
|
|
111
147
|
{
|
|
112
148
|
key: "faqs",
|
|
@@ -129,10 +165,109 @@ export const SEARCH_SOURCES = [
|
|
|
129
165
|
return {
|
|
130
166
|
id,
|
|
131
167
|
title: question,
|
|
132
|
-
href: category ?
|
|
168
|
+
href: category ? ROUTES.PUBLIC.FAQ_CATEGORY(category) : ROUTES.PUBLIC.FAQS,
|
|
133
169
|
...(category ? { detail: category.replace(/_/g, " ") } : {}),
|
|
134
170
|
};
|
|
135
171
|
},
|
|
136
|
-
moreHref: (q) => withQ(
|
|
172
|
+
moreHref: (q) => withQ(ROUTES.PUBLIC.FAQS, q),
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
key: "events",
|
|
176
|
+
label: "Events",
|
|
177
|
+
collection: "events",
|
|
178
|
+
/*
|
|
179
|
+
* 🛑 No `where` clause, and that is forced rather than lazy. Measured on
|
|
180
|
+
* the live collection: `active` 8, `draft` 1, `paused` 1, `ended` 1,
|
|
181
|
+
* `cancelled` 1. The public set is "not draft, not cancelled" — three
|
|
182
|
+
* values — and `where` here applies `==` only, so a single clause would
|
|
183
|
+
* either publish drafts or hide every paused and ended event. Firestore
|
|
184
|
+
* cannot express the negation either (Root Cause #59). Same in-memory
|
|
185
|
+
* shape the `categories` source uses, for the same reason.
|
|
186
|
+
*
|
|
187
|
+
* `ended` stays visible deliberately: a search answers "do you have this",
|
|
188
|
+
* and an event that happened is a real answer with a real page.
|
|
189
|
+
*/
|
|
190
|
+
select: ["title", "slug", "type", "status"],
|
|
191
|
+
toHit: (id, d) => {
|
|
192
|
+
const title = str(d.title);
|
|
193
|
+
if (!title)
|
|
194
|
+
return null;
|
|
195
|
+
const status = str(d.status);
|
|
196
|
+
if (status === "draft" || status === "cancelled")
|
|
197
|
+
return null;
|
|
198
|
+
const detail = str(d.type);
|
|
199
|
+
return {
|
|
200
|
+
id,
|
|
201
|
+
title,
|
|
202
|
+
href: ROUTES.PUBLIC.EVENT_DETAIL(str(d.slug) ?? id),
|
|
203
|
+
...(detail ? { detail: detail.replace(/_/g, " ") } : {}),
|
|
204
|
+
};
|
|
205
|
+
},
|
|
206
|
+
moreHref: (q) => withQ(ROUTES.PUBLIC.EVENTS, q),
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
key: "reviews",
|
|
210
|
+
label: "Reviews",
|
|
211
|
+
collection: "reviews",
|
|
212
|
+
// All 79 live rows are `approved`; the clause is still explicit, because a
|
|
213
|
+
// rejected review surfacing publicly is the failure that matters here.
|
|
214
|
+
where: [["status", "approved"]],
|
|
215
|
+
/*
|
|
216
|
+
* 🛑 `productTitle` as the detail, NEVER `userName`. The field exists on
|
|
217
|
+
* the document and is deliberately absent from `buildReviewSearchTxt`
|
|
218
|
+
* because it is encrypted; `maskPublicReview` is what the public read path
|
|
219
|
+
* uses. A search hit is a public surface and has no business carrying a
|
|
220
|
+
* reviewer's name even in a subtitle.
|
|
221
|
+
*/
|
|
222
|
+
select: ["title", "productTitle", "status"],
|
|
223
|
+
toHit: (id, d) => {
|
|
224
|
+
const title = str(d.title);
|
|
225
|
+
if (!title)
|
|
226
|
+
return null;
|
|
227
|
+
const detail = str(d.productTitle);
|
|
228
|
+
return {
|
|
229
|
+
id,
|
|
230
|
+
title,
|
|
231
|
+
href: ROUTES.PUBLIC.REVIEW_DETAIL(id),
|
|
232
|
+
...(detail ? { detail } : {}),
|
|
233
|
+
};
|
|
234
|
+
},
|
|
235
|
+
moreHref: (q) => withQ(ROUTES.PUBLIC.REVIEWS, q),
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
key: "scammers",
|
|
239
|
+
label: "Scam reports",
|
|
240
|
+
collection: "scammerProfiles",
|
|
241
|
+
/*
|
|
242
|
+
* 🛑 `verified` ONLY, and this clause is the whole point of the source.
|
|
243
|
+
* Measured live: `verified` 3, `pending_review` 1, `rejected` 1. Surfacing
|
|
244
|
+
* an unverified or rejected accusation in site-wide search publishes an
|
|
245
|
+
* allegation the moderation queue has not accepted — against a named
|
|
246
|
+
* person, with their phone and UPI on the page. The scam registry is
|
|
247
|
+
* deliberately public and plaintext-indexed for SEO, which makes getting
|
|
248
|
+
* this clause right more load-bearing here than anywhere else, not less.
|
|
249
|
+
*/
|
|
250
|
+
where: [["status", "verified"]],
|
|
251
|
+
/*
|
|
252
|
+
* 🛑 `displayNames` is an ARRAY, not a string — read off the live
|
|
253
|
+
* documents, which is what this file's header asks for and what caught it.
|
|
254
|
+
* A `str(d.displayName)` would have returned null for every row and the
|
|
255
|
+
* group would simply never have appeared.
|
|
256
|
+
*/
|
|
257
|
+
select: ["displayNames", "scamType", "slug"],
|
|
258
|
+
toHit: (id, d) => {
|
|
259
|
+
const names = Array.isArray(d.displayNames) ? d.displayNames : [];
|
|
260
|
+
const title = str(names[0]);
|
|
261
|
+
if (!title)
|
|
262
|
+
return null;
|
|
263
|
+
const detail = str(d.scamType);
|
|
264
|
+
return {
|
|
265
|
+
id,
|
|
266
|
+
title,
|
|
267
|
+
href: ROUTES.PUBLIC.SCAM_DETAIL(str(d.slug) ?? id),
|
|
268
|
+
...(detail ? { detail: detail.replace(/_/g, " ") } : {}),
|
|
269
|
+
};
|
|
270
|
+
},
|
|
271
|
+
moreHref: (q) => withQ(ROUTES.PUBLIC.SCAMS, q),
|
|
137
272
|
},
|
|
138
273
|
];
|