@mohasinac/appkit 4.52.5 → 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 +11 -0
- package/dist/features/layout/AppLayoutShell.js +64 -12
- 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.js +1 -1
- 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/index.js +8 -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 +192 -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
|
@@ -12,10 +12,10 @@ function getBusinessDayCutoff(daysAgo) {
|
|
|
12
12
|
return cutoff;
|
|
13
13
|
}
|
|
14
14
|
export async function runAutoPayoutEligibility(ctx) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
// `FEATURE_PAYOUTS` gate deleted 2026-10-19 — see `auctionSettlement.ts`.
|
|
16
|
+
// This was the one flag actually set (`functions/.env.letitrip-in-app`), so
|
|
17
|
+
// unlike its four siblings this job was running; removing the gate is a
|
|
18
|
+
// no-op in behaviour and removes the lever that could silently stop payouts.
|
|
19
19
|
ctx.logger.info("Starting daily auto-payout eligibility sweep", {
|
|
20
20
|
windowDays: AUTO_PAYOUT_WINDOW_DAYS,
|
|
21
21
|
});
|
|
@@ -48,6 +48,26 @@ export async function runAutoPayoutEligibility(ctx) {
|
|
|
48
48
|
ctx.logger.warn(`Store/seller ${storeId} not found — skipping ${orders.length} order(s)`, { orderIds: orders.map((o) => o.id) });
|
|
49
49
|
continue;
|
|
50
50
|
}
|
|
51
|
+
/*
|
|
52
|
+
* 🛑 REVEALED before building a payout. This is the fix for active data
|
|
53
|
+
* corruption, not a style change.
|
|
54
|
+
*
|
|
55
|
+
* `userRepository.findById` is ciphertext-by-default, and
|
|
56
|
+
* `payoutRepository.createPayout` ENCRYPTS `sellerEmail` and `upiId`
|
|
57
|
+
* (`PAYOUT_PII_FIELDS`). Passing the stored values straight through
|
|
58
|
+
* encrypted them a SECOND time, and nothing in the codebase ever
|
|
59
|
+
* double-decrypts — so every payout this cron wrote carried a
|
|
60
|
+
* permanently unreadable `upiId`, which is the field the money is sent to.
|
|
61
|
+
*
|
|
62
|
+
* It also poisoned the blind index: `piiIndicesFor` HMACs whatever it is
|
|
63
|
+
* given, so hashing already-encrypted input produced a valid-looking
|
|
64
|
+
* `sellerEmailIndex` that can never match a lookup by the real address.
|
|
65
|
+
*
|
|
66
|
+
* `payoutDetails` needs its own unwrap because it is encrypted by
|
|
67
|
+
* `encryptPayoutDetails`, a separate scheme from the `piiFields` path, so
|
|
68
|
+
* `revealUser` handles it explicitly.
|
|
69
|
+
*/
|
|
70
|
+
const sellerPlain = userRepository.revealUser(seller);
|
|
51
71
|
const sellerId = store.ownerId;
|
|
52
72
|
/*
|
|
53
73
|
* The TAXABLE VALUE — see `orderTaxableValue`. Two narrowings, both
|
|
@@ -65,8 +85,9 @@ export async function runAutoPayoutEligibility(ctx) {
|
|
|
65
85
|
const { platformFee, gatewayFee, gstOnFee: gstAmount, netAmount } = computePayoutDeduction(grossAmount, commissions);
|
|
66
86
|
const payoutInput = {
|
|
67
87
|
storeId,
|
|
68
|
-
|
|
69
|
-
|
|
88
|
+
// `displayName` is plaintext by D1; the email fallback must be revealed.
|
|
89
|
+
sellerName: (seller.displayName ?? sellerPlain.email ?? sellerId),
|
|
90
|
+
sellerEmail: sellerPlain.email ?? "",
|
|
70
91
|
orderIds: orders.map((o) => o.id),
|
|
71
92
|
amount: netAmount,
|
|
72
93
|
grossAmount,
|
|
@@ -79,23 +100,31 @@ export async function runAutoPayoutEligibility(ctx) {
|
|
|
79
100
|
isAutomatic: true,
|
|
80
101
|
currency: getDefaultCurrency(),
|
|
81
102
|
status: "pending",
|
|
82
|
-
paymentMethod:
|
|
103
|
+
paymentMethod: sellerPlain.payoutDetails?.method === "upi"
|
|
83
104
|
? "upi"
|
|
84
105
|
: "bank_transfer",
|
|
85
|
-
upiId:
|
|
86
|
-
|
|
87
|
-
|
|
106
|
+
upiId: sellerPlain.payoutDetails?.method === "upi"
|
|
107
|
+
? sellerPlain.payoutDetails.upiId
|
|
108
|
+
: undefined,
|
|
109
|
+
/*
|
|
110
|
+
* Only the MASKED account fields are copied, which is why this block
|
|
111
|
+
* escaped the double-encryption above — `accountNumberMasked`,
|
|
112
|
+
* `ifscCode` and `bankName` are in no PII list. The real
|
|
113
|
+
* `accountNumber` is deliberately not carried onto the payout.
|
|
114
|
+
*/
|
|
115
|
+
bankAccount: sellerPlain.payoutDetails?.method === "bank_transfer" &&
|
|
116
|
+
sellerPlain.payoutDetails.bankAccount
|
|
88
117
|
? {
|
|
89
|
-
accountHolderName:
|
|
90
|
-
accountNumberMasked:
|
|
91
|
-
ifscCode:
|
|
92
|
-
bankName:
|
|
118
|
+
accountHolderName: sellerPlain.payoutDetails.bankAccount.accountHolderName,
|
|
119
|
+
accountNumberMasked: sellerPlain.payoutDetails.bankAccount.accountNumberMasked,
|
|
120
|
+
ifscCode: sellerPlain.payoutDetails.bankAccount.ifscCode,
|
|
121
|
+
bankName: sellerPlain.payoutDetails.bankAccount.bankName,
|
|
93
122
|
}
|
|
94
123
|
: undefined,
|
|
95
124
|
notes: `Auto-payout — ${orders.length} delivered order(s) past ${AUTO_PAYOUT_WINDOW_DAYS}-day window`,
|
|
96
125
|
requestedAt: new Date(),
|
|
97
126
|
};
|
|
98
|
-
const { id: payoutId } = await payoutRepository.
|
|
127
|
+
const { id: payoutId } = await payoutRepository.createPayout(payoutInput);
|
|
99
128
|
for (let i = 0; i < orders.length; i += BATCH_LIMIT) {
|
|
100
129
|
const slice = orders.slice(i, i + BATCH_LIMIT);
|
|
101
130
|
const batch = ctx.db.batch();
|
|
@@ -51,10 +51,9 @@ async function sweepBundleMembers(productIds, ctx) {
|
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
export async function runBundleStockSync(ctx) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
54
|
+
// `FEATURE_BUNDLES` gate deleted 2026-10-19 — see `auctionSettlement.ts` for
|
|
55
|
+
// why these survived the 2026-08-29 flag retirement. Unset in
|
|
56
|
+
// `functions/.env.letitrip-in-app`, so this scheduled sweep had never run.
|
|
58
57
|
ctx.logger.info("Bundle stock sync starting (SB-UNI-V categories)");
|
|
59
58
|
const snap = await ctx.db
|
|
60
59
|
.collection(CATEGORIES_COLLECTION)
|
|
@@ -16,6 +16,16 @@ const EMAIL_STALE_MS = 60 * 60 * 1000;
|
|
|
16
16
|
/** Long enough for an open thread to notice a ping before it prunes; the
|
|
17
17
|
* message itself lives in Firestore regardless — this only clears the ping. */
|
|
18
18
|
const CHAT_STALE_MS = 15 * 60 * 1000;
|
|
19
|
+
/**
|
|
20
|
+
* 🛑 SIXTY minutes, and the four-times-longer window is load-bearing rather
|
|
21
|
+
* than cautious. A `max`-tier trace fans out across up to sixty parts and can
|
|
22
|
+
* exceed fifteen minutes end to end; a channel pruned while the run is still
|
|
23
|
+
* working reads to the client as "it died", which is the one signal this
|
|
24
|
+
* channel exists to make impossible. The durable history is on the run
|
|
25
|
+
* document, so the cost of keeping the node an hour is a handful of small
|
|
26
|
+
* nodes and the cost of dropping it early is a false failure report.
|
|
27
|
+
*/
|
|
28
|
+
const STICKER_TRACE_STALE_MS = 60 * 60 * 1000;
|
|
19
29
|
const JOBS_TTL_DAYS = 30;
|
|
20
30
|
export async function runCleanupRtdbEvents(ctx) {
|
|
21
31
|
ctx.logger.info("Starting RTDB events cleanup");
|
|
@@ -111,6 +121,40 @@ export async function runCleanupRtdbEvents(ctx) {
|
|
|
111
121
|
void normalizeError(emailErr);
|
|
112
122
|
ctx.logger.error("Email events cleanup failed (non-fatal)", emailErr);
|
|
113
123
|
}
|
|
124
|
+
/*
|
|
125
|
+
* Sticker kiss-cut tracer progress channels. One node per run, overwritten
|
|
126
|
+
* in place as the trace advances, so the channel's size is bounded by
|
|
127
|
+
* concurrent runs rather than by history — but only because this prunes it.
|
|
128
|
+
* `auction-bids/*` is the Firebase budget's one family with no TTL; do not
|
|
129
|
+
* make this the second.
|
|
130
|
+
*
|
|
131
|
+
* The run DOCUMENT keeps the durable event log, so removing a node loses
|
|
132
|
+
* nothing a retry panel or a post-mortem reads.
|
|
133
|
+
*/
|
|
134
|
+
try {
|
|
135
|
+
const traceSnap = await rtdb.ref(RTDB_PATHS.STICKER_TRACE).get();
|
|
136
|
+
if (traceSnap.exists()) {
|
|
137
|
+
const allTraceNodes = traceSnap.val();
|
|
138
|
+
const staleTraceIds = Object.entries(allTraceNodes)
|
|
139
|
+
.filter(([, node]) => {
|
|
140
|
+
const at = node.updatedAt ?? 0;
|
|
141
|
+
// Missing or non-finite is stale BY DEFINITION — it can never age
|
|
142
|
+
// out on its own, so leaving it would pin the node forever.
|
|
143
|
+
return !Number.isFinite(at) || at === 0 || at < now - STICKER_TRACE_STALE_MS;
|
|
144
|
+
})
|
|
145
|
+
.map(([id]) => id);
|
|
146
|
+
if (staleTraceIds.length > 0) {
|
|
147
|
+
await Promise.all(staleTraceIds.map((id) => rtdb.ref(`${RTDB_PATHS.STICKER_TRACE}/${id}`).remove()));
|
|
148
|
+
ctx.logger.info("Sticker trace progress nodes removed", {
|
|
149
|
+
count: staleTraceIds.length,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch (traceErr) {
|
|
155
|
+
void normalizeError(traceErr);
|
|
156
|
+
ctx.logger.error("Sticker trace cleanup failed (non-fatal)", traceErr);
|
|
157
|
+
}
|
|
114
158
|
/*
|
|
115
159
|
* D9 — chat new-message pings. Its own file says it: "an unpruned RTDB
|
|
116
160
|
* channel is precisely the thing that quietly accumulates… Do not make it
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE reason → {HTTP status, stable code} map for the two event prize-draw
|
|
3
|
+
* job cores (`assignSpinPrize`, `triggerEventRaffle`).
|
|
4
|
+
*
|
|
5
|
+
* ## Why this exists
|
|
6
|
+
*
|
|
7
|
+
* Each core returns a `reason` string instead of throwing, and each is reachable
|
|
8
|
+
* by TWO entry points — a Next.js API route and a Firebase callable handler.
|
|
9
|
+
* That made four translations of one vocabulary, and all four disagreed:
|
|
10
|
+
*
|
|
11
|
+
* · `api/events/[id]/spin/route.ts` — had `feature_disabled`, no `not_active`
|
|
12
|
+
* · `jobs/handlers/assignSpinPrize.ts` — `identity_required` → 400 (route said 401),
|
|
13
|
+
* no `feature_disabled` branch at all
|
|
14
|
+
* · `api/admin/events/[id]/trigger-raffle/route.ts` — EVERYTHING → 409
|
|
15
|
+
* · `jobs/handlers/triggerEventRaffle.ts` — only 404 / 422
|
|
16
|
+
*
|
|
17
|
+
* Root Cause #85 ("a handler reachable by two entry points with different
|
|
18
|
+
* behaviour"), four times over in one feature. The spin route's own header
|
|
19
|
+
* already documented the trap and still only fixed its own half.
|
|
20
|
+
*
|
|
21
|
+
* ## Two rules that produced real bugs
|
|
22
|
+
*
|
|
23
|
+
* 1. 🛑 **A PERMANENT refusal must never take a retryable status.** The spin
|
|
24
|
+
* route's fallback was 409 (`ALREADY_EXISTS`), described in its own comment
|
|
25
|
+
* as "a benign can't-spin-right-now state". An unlisted permanent reason
|
|
26
|
+
* therefore shipped `{code:"ALREADY_EXISTS", error:"<reason>"}` — an envelope
|
|
27
|
+
* naming two unrelated things — which the UI rendered as "Spin failed.
|
|
28
|
+
* Please try again.", inviting a retry that could never succeed.
|
|
29
|
+
*
|
|
30
|
+
* 2. 🛑 **A reason-less result is a SUCCESS to both routes.** Both check
|
|
31
|
+
* `if (data.reason && !data.<successField>)`, so a core branch that returned
|
|
32
|
+
* early *without* a `reason` fell through to `successResponse`.
|
|
33
|
+
* `triggerEventRaffle`'s feature-flag branch did exactly that and answered
|
|
34
|
+
* `200 "Raffle triggered"` with no winner. Every non-success branch in either
|
|
35
|
+
* core must set a reason from this map.
|
|
36
|
+
*
|
|
37
|
+
* There is deliberately NO fallback entry here: `reasonToHttp` is exhaustive
|
|
38
|
+
* over `EventDrawReason`, so adding a reason without a status is a compile
|
|
39
|
+
* error rather than a silent 409.
|
|
40
|
+
*/
|
|
41
|
+
export declare const EVENT_DRAW_REASON: {
|
|
42
|
+
/** Neither a signed-in user nor a hashed guest identity was supplied. */
|
|
43
|
+
readonly IDENTITY_REQUIRED: "identity_required";
|
|
44
|
+
/** Guest attempt on an event that has not opted into guest participation. */
|
|
45
|
+
readonly LOGIN_REQUIRED: "login_required";
|
|
46
|
+
readonly EVENT_NOT_FOUND: "event_not_found";
|
|
47
|
+
/** Draft / paused / cancelled / ended — see each core's status precondition. */
|
|
48
|
+
readonly NOT_ACTIVE: "not_active";
|
|
49
|
+
readonly NO_PRIZES_CONFIGURED: "no_prizes_configured";
|
|
50
|
+
readonly OUTSIDE_SPIN_WINDOW: "outside_spin_window";
|
|
51
|
+
/** This identity has already consumed its `spinMaxPerUser` allowance. */
|
|
52
|
+
readonly ALREADY_USED: "already_used";
|
|
53
|
+
readonly NOT_A_SPIN_WHEEL: "not_a_spin_wheel";
|
|
54
|
+
readonly NOT_A_RAFFLE: "not_a_raffle";
|
|
55
|
+
/** A winner is already recorded; a second draw would mean two winners. */
|
|
56
|
+
readonly ALREADY_TRIGGERED: "already_triggered";
|
|
57
|
+
readonly NO_ELIGIBLE_ENTRIES: "no_eligible_entries";
|
|
58
|
+
};
|
|
59
|
+
export type EventDrawReason = (typeof EVENT_DRAW_REASON)[keyof typeof EVENT_DRAW_REASON];
|
|
60
|
+
export interface EventDrawHttpMapping {
|
|
61
|
+
status: number;
|
|
62
|
+
/** Stable code the client resolves through `toUserMessage` / `errors.codes.*`. */
|
|
63
|
+
code: string;
|
|
64
|
+
/**
|
|
65
|
+
* Developer-facing fallback sentence. The client renders copy from `code`, so
|
|
66
|
+
* this is what shows in a log, a curl, or a locale with no key — never the
|
|
67
|
+
* primary UI string.
|
|
68
|
+
*/
|
|
69
|
+
message: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Translate a core's `reason` into the response shape both entry points use.
|
|
73
|
+
*
|
|
74
|
+
* An unrecognised reason maps to **500**, not to the old 409 fallback: a reason
|
|
75
|
+
* this map has never heard of is a bug in the core, and a 5xx is what gets it
|
|
76
|
+
* recorded by `onRequestError` instead of being filed as an ordinary conflict.
|
|
77
|
+
*/
|
|
78
|
+
export declare function reasonToHttp(reason: string | undefined): EventDrawHttpMapping;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE reason → {HTTP status, stable code} map for the two event prize-draw
|
|
3
|
+
* job cores (`assignSpinPrize`, `triggerEventRaffle`).
|
|
4
|
+
*
|
|
5
|
+
* ## Why this exists
|
|
6
|
+
*
|
|
7
|
+
* Each core returns a `reason` string instead of throwing, and each is reachable
|
|
8
|
+
* by TWO entry points — a Next.js API route and a Firebase callable handler.
|
|
9
|
+
* That made four translations of one vocabulary, and all four disagreed:
|
|
10
|
+
*
|
|
11
|
+
* · `api/events/[id]/spin/route.ts` — had `feature_disabled`, no `not_active`
|
|
12
|
+
* · `jobs/handlers/assignSpinPrize.ts` — `identity_required` → 400 (route said 401),
|
|
13
|
+
* no `feature_disabled` branch at all
|
|
14
|
+
* · `api/admin/events/[id]/trigger-raffle/route.ts` — EVERYTHING → 409
|
|
15
|
+
* · `jobs/handlers/triggerEventRaffle.ts` — only 404 / 422
|
|
16
|
+
*
|
|
17
|
+
* Root Cause #85 ("a handler reachable by two entry points with different
|
|
18
|
+
* behaviour"), four times over in one feature. The spin route's own header
|
|
19
|
+
* already documented the trap and still only fixed its own half.
|
|
20
|
+
*
|
|
21
|
+
* ## Two rules that produced real bugs
|
|
22
|
+
*
|
|
23
|
+
* 1. 🛑 **A PERMANENT refusal must never take a retryable status.** The spin
|
|
24
|
+
* route's fallback was 409 (`ALREADY_EXISTS`), described in its own comment
|
|
25
|
+
* as "a benign can't-spin-right-now state". An unlisted permanent reason
|
|
26
|
+
* therefore shipped `{code:"ALREADY_EXISTS", error:"<reason>"}` — an envelope
|
|
27
|
+
* naming two unrelated things — which the UI rendered as "Spin failed.
|
|
28
|
+
* Please try again.", inviting a retry that could never succeed.
|
|
29
|
+
*
|
|
30
|
+
* 2. 🛑 **A reason-less result is a SUCCESS to both routes.** Both check
|
|
31
|
+
* `if (data.reason && !data.<successField>)`, so a core branch that returned
|
|
32
|
+
* early *without* a `reason` fell through to `successResponse`.
|
|
33
|
+
* `triggerEventRaffle`'s feature-flag branch did exactly that and answered
|
|
34
|
+
* `200 "Raffle triggered"` with no winner. Every non-success branch in either
|
|
35
|
+
* core must set a reason from this map.
|
|
36
|
+
*
|
|
37
|
+
* There is deliberately NO fallback entry here: `reasonToHttp` is exhaustive
|
|
38
|
+
* over `EventDrawReason`, so adding a reason without a status is a compile
|
|
39
|
+
* error rather than a silent 409.
|
|
40
|
+
*/
|
|
41
|
+
import { EVENT_DRAW_ERROR_CODES } from "../../../../errors/error-codes.js";
|
|
42
|
+
export const EVENT_DRAW_REASON = {
|
|
43
|
+
/** Neither a signed-in user nor a hashed guest identity was supplied. */
|
|
44
|
+
IDENTITY_REQUIRED: "identity_required",
|
|
45
|
+
/** Guest attempt on an event that has not opted into guest participation. */
|
|
46
|
+
LOGIN_REQUIRED: "login_required",
|
|
47
|
+
EVENT_NOT_FOUND: "event_not_found",
|
|
48
|
+
/** Draft / paused / cancelled / ended — see each core's status precondition. */
|
|
49
|
+
NOT_ACTIVE: "not_active",
|
|
50
|
+
NO_PRIZES_CONFIGURED: "no_prizes_configured",
|
|
51
|
+
OUTSIDE_SPIN_WINDOW: "outside_spin_window",
|
|
52
|
+
/** This identity has already consumed its `spinMaxPerUser` allowance. */
|
|
53
|
+
ALREADY_USED: "already_used",
|
|
54
|
+
NOT_A_SPIN_WHEEL: "not_a_spin_wheel",
|
|
55
|
+
NOT_A_RAFFLE: "not_a_raffle",
|
|
56
|
+
/** A winner is already recorded; a second draw would mean two winners. */
|
|
57
|
+
ALREADY_TRIGGERED: "already_triggered",
|
|
58
|
+
NO_ELIGIBLE_ENTRIES: "no_eligible_entries",
|
|
59
|
+
};
|
|
60
|
+
const MAPPING = {
|
|
61
|
+
[EVENT_DRAW_REASON.IDENTITY_REQUIRED]: {
|
|
62
|
+
status: 401,
|
|
63
|
+
code: EVENT_DRAW_ERROR_CODES.IDENTITY_REQUIRED,
|
|
64
|
+
message: "No user or guest identity was provided",
|
|
65
|
+
},
|
|
66
|
+
[EVENT_DRAW_REASON.LOGIN_REQUIRED]: {
|
|
67
|
+
status: 401,
|
|
68
|
+
code: EVENT_DRAW_ERROR_CODES.LOGIN_REQUIRED,
|
|
69
|
+
message: "Sign in to take part in this event",
|
|
70
|
+
},
|
|
71
|
+
[EVENT_DRAW_REASON.EVENT_NOT_FOUND]: {
|
|
72
|
+
status: 404,
|
|
73
|
+
code: EVENT_DRAW_ERROR_CODES.EVENT_NOT_FOUND,
|
|
74
|
+
message: "Event not found",
|
|
75
|
+
},
|
|
76
|
+
[EVENT_DRAW_REASON.NOT_ACTIVE]: {
|
|
77
|
+
status: 409,
|
|
78
|
+
code: EVENT_DRAW_ERROR_CODES.EVENT_NOT_ACTIVE,
|
|
79
|
+
message: "This event is not running right now",
|
|
80
|
+
},
|
|
81
|
+
[EVENT_DRAW_REASON.NO_PRIZES_CONFIGURED]: {
|
|
82
|
+
status: 422,
|
|
83
|
+
code: EVENT_DRAW_ERROR_CODES.SPIN_NO_PRIZES,
|
|
84
|
+
message: "No spin prizes are configured for this event",
|
|
85
|
+
},
|
|
86
|
+
[EVENT_DRAW_REASON.OUTSIDE_SPIN_WINDOW]: {
|
|
87
|
+
status: 403,
|
|
88
|
+
code: EVENT_DRAW_ERROR_CODES.SPIN_OUTSIDE_WINDOW,
|
|
89
|
+
message: "This spin wheel is not open right now",
|
|
90
|
+
},
|
|
91
|
+
[EVENT_DRAW_REASON.ALREADY_USED]: {
|
|
92
|
+
status: 409,
|
|
93
|
+
code: EVENT_DRAW_ERROR_CODES.SPIN_ALREADY_USED,
|
|
94
|
+
message: "This identity has already used its spins for this event",
|
|
95
|
+
},
|
|
96
|
+
[EVENT_DRAW_REASON.NOT_A_SPIN_WHEEL]: {
|
|
97
|
+
status: 422,
|
|
98
|
+
code: EVENT_DRAW_ERROR_CODES.NOT_A_SPIN_WHEEL,
|
|
99
|
+
message: "This event is not a spin wheel",
|
|
100
|
+
},
|
|
101
|
+
[EVENT_DRAW_REASON.NOT_A_RAFFLE]: {
|
|
102
|
+
status: 422,
|
|
103
|
+
code: EVENT_DRAW_ERROR_CODES.RAFFLE_NOT_A_RAFFLE,
|
|
104
|
+
message: "This event does not have a raffle",
|
|
105
|
+
},
|
|
106
|
+
[EVENT_DRAW_REASON.ALREADY_TRIGGERED]: {
|
|
107
|
+
status: 409,
|
|
108
|
+
code: EVENT_DRAW_ERROR_CODES.RAFFLE_ALREADY_DRAWN,
|
|
109
|
+
message: "A winner has already been drawn for this raffle",
|
|
110
|
+
},
|
|
111
|
+
[EVENT_DRAW_REASON.NO_ELIGIBLE_ENTRIES]: {
|
|
112
|
+
status: 409,
|
|
113
|
+
code: EVENT_DRAW_ERROR_CODES.RAFFLE_NO_ELIGIBLE_ENTRIES,
|
|
114
|
+
message: "No eligible entries to draw from",
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
const UNKNOWN = {
|
|
118
|
+
status: 500,
|
|
119
|
+
code: EVENT_DRAW_ERROR_CODES.UNKNOWN_REASON,
|
|
120
|
+
message: "The event could not be processed",
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Translate a core's `reason` into the response shape both entry points use.
|
|
124
|
+
*
|
|
125
|
+
* An unrecognised reason maps to **500**, not to the old 409 fallback: a reason
|
|
126
|
+
* this map has never heard of is a bug in the core, and a 5xx is what gets it
|
|
127
|
+
* recorded by `onRequestError` instead of being filed as an ordinary conflict.
|
|
128
|
+
*/
|
|
129
|
+
export function reasonToHttp(reason) {
|
|
130
|
+
if (!reason)
|
|
131
|
+
return UNKNOWN;
|
|
132
|
+
return MAPPING[reason] ?? UNKNOWN;
|
|
133
|
+
}
|
|
@@ -53,17 +53,31 @@ function getStringArrayOpt(baseOpts, key) {
|
|
|
53
53
|
}
|
|
54
54
|
const LISTERS = {
|
|
55
55
|
products: (m, o) => productRepository.list(m, o),
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
/*
|
|
57
|
+
* 🛑 These four forward `search`, and did not until 2026-10-17.
|
|
58
|
+
*
|
|
59
|
+
* `categoriesRepository.list` and `couponsRepository.list` both accept
|
|
60
|
+
* `opts?: { search?: string }`, and all four listers below were written
|
|
61
|
+
* `(m) => repo.list(m)` — so a search term reaching the Function was
|
|
62
|
+
* DISCARDED and the page came back unfiltered with a 200, while the same
|
|
63
|
+
* route's local fallback filtered correctly. Exactly the divergence the
|
|
64
|
+
* comment further down records for orders/reviews/blogPosts/events/stores
|
|
65
|
+
* and faqs, four collections later: category, brand, coupon and
|
|
66
|
+
* sublisting-category search.
|
|
67
|
+
*
|
|
68
|
+
* Found by `audit-lister-opts-forwarding`, which now blocks the shape.
|
|
69
|
+
*/
|
|
70
|
+
categories: (m, o) => categoriesRepository.list(m, { search: getStringOpt(o, "search") }),
|
|
71
|
+
brands: (m, o) => categoriesRepository.list({
|
|
58
72
|
...m,
|
|
59
73
|
filters: m.filters
|
|
60
74
|
? `${m.filters},categoryType==brand`
|
|
61
75
|
: "categoryType==brand",
|
|
62
|
-
}),
|
|
76
|
+
}, { search: getStringOpt(o, "search") }),
|
|
63
77
|
orders: (m, o) => orderRepository.listAll(m, { search: getStringOpt(o, "search") }),
|
|
64
78
|
reviews: (m, o) => reviewRepository.listAll(m, { search: getStringOpt(o, "search") }),
|
|
65
|
-
coupons: (m) => couponsRepository.list(m),
|
|
66
|
-
bids: (m) => bidRepository.list(m),
|
|
79
|
+
coupons: (m, o) => couponsRepository.list(m, { search: getStringOpt(o, "search") }),
|
|
80
|
+
bids: (m, o) => bidRepository.list(m, { search: getStringOpt(o, "search") }),
|
|
67
81
|
payouts: (m) => payoutRepository.list(m),
|
|
68
82
|
blogPosts: (m, o) => blogRepository.listAll(m, { search: getStringOpt(o, "search") }),
|
|
69
83
|
events: (m, o) => eventRepository.list(m, { search: getStringOpt(o, "search") }),
|
|
@@ -84,13 +98,19 @@ const LISTERS = {
|
|
|
84
98
|
tags: getStringArrayOpt(o, "tags"),
|
|
85
99
|
}),
|
|
86
100
|
notifications: (m) => notificationRepository.list(m),
|
|
87
|
-
|
|
88
|
-
|
|
101
|
+
/*
|
|
102
|
+
* `/api/admin/scammers` passes `{ search: q }` to this same method locally —
|
|
103
|
+
* its route comment records that the identity arrays "were never searched at
|
|
104
|
+
* all despite the box promising them" before searchTxt. Through the Function
|
|
105
|
+
* the opt was dropped again, so the two executors disagreed.
|
|
106
|
+
*/
|
|
107
|
+
scammers: (m, o) => scammerRepository.listAll(m, { search: getStringOpt(o, "search") }),
|
|
108
|
+
sublistingCategories: (m, o) => categoriesRepository.list({
|
|
89
109
|
...m,
|
|
90
110
|
filters: m.filters
|
|
91
111
|
? `${m.filters},categoryType==sublisting`
|
|
92
112
|
: "categoryType==sublisting",
|
|
93
|
-
}),
|
|
113
|
+
}, { search: getStringOpt(o, "search") }),
|
|
94
114
|
productFeatures: (m) => productFeaturesRepository.list(m),
|
|
95
115
|
homepageSections: (m) => homepageSectionsRepository.list(m),
|
|
96
116
|
users: (m) => userRepository.list(m),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeError } from "../../../../errors/normalize.js";
|
|
2
|
+
import { ORDER_PII_FIELDS, revealPii } from "../../../../security/index.js";
|
|
2
3
|
import { adminNotificationsRepository, storeRepository, userRepository } from "../../../../repositories/index.js";
|
|
3
4
|
import { decryptPii } from "../../../../security/index.js";
|
|
4
5
|
import { sendWhatsAppBusinessMessage, buildPurchaseAnnouncementMessage, } from "../../../../features/whatsapp-bot/server.js";
|
|
@@ -91,7 +92,17 @@ export async function handleOrderCreate(input, ctx) {
|
|
|
91
92
|
* `decryptPii` was already imported in this file and used for the store
|
|
92
93
|
* owner's phone eleven lines up; the buyer's name was simply missed.
|
|
93
94
|
*/
|
|
94
|
-
|
|
95
|
+
/*
|
|
96
|
+
* The NAMED accessor, not a bare `decryptPii` cast.
|
|
97
|
+
*
|
|
98
|
+
* This already decrypted and therefore already WORKED — but through a cast
|
|
99
|
+
* that defeated the brand, so "is every reader converted?" could not be
|
|
100
|
+
* answered by grepping for `reveal*`. Routing it through `revealOrder` makes
|
|
101
|
+
* the decision visible in review and in a grep, which is the whole argument
|
|
102
|
+
* for named accessors over an inline decrypt.
|
|
103
|
+
*/
|
|
104
|
+
const buyerName = revealPii(order, ORDER_PII_FIELDS).userName ??
|
|
105
|
+
"A customer";
|
|
95
106
|
const message = buildPurchaseAnnouncementMessage({
|
|
96
107
|
buyerName,
|
|
97
108
|
firstItemName,
|
|
@@ -10,6 +10,17 @@ export async function handleScamReportCreate(input, ctx) {
|
|
|
10
10
|
if (reportedBy) {
|
|
11
11
|
try {
|
|
12
12
|
const reporter = await userRepository.findById(reportedBy);
|
|
13
|
+
/*
|
|
14
|
+
* REVEALED, because this notification is DELIVERED to the reporter and a
|
|
15
|
+
* masked address cannot receive mail.
|
|
16
|
+
*
|
|
17
|
+
* `findById` stopped decrypting when `UserRepository` went
|
|
18
|
+
* ciphertext-by-default, so `reporter.email` is an `enc:v1:` blob — it
|
|
19
|
+
* would have been handed to the mailer verbatim. The old intersection
|
|
20
|
+
* brand could not object, because `Encrypted<string>` was a subtype of
|
|
21
|
+
* `string`.
|
|
22
|
+
*/
|
|
23
|
+
const reporterPlain = reporter ? userRepository.revealUser(reporter) : null;
|
|
13
24
|
await sendNotification({
|
|
14
25
|
userId: reportedBy,
|
|
15
26
|
type: "scam_report_update",
|
|
@@ -18,8 +29,8 @@ export async function handleScamReportCreate(input, ctx) {
|
|
|
18
29
|
message: `Your report for "${name}" has been received. Our team will review it within 48 hours.`,
|
|
19
30
|
relatedId: scammerId,
|
|
20
31
|
relatedType: "scammer",
|
|
21
|
-
userEmail:
|
|
22
|
-
userPhone:
|
|
32
|
+
userEmail: reporterPlain?.email ?? undefined,
|
|
33
|
+
userPhone: reporterPlain?.phoneNumber ?? undefined,
|
|
23
34
|
});
|
|
24
35
|
}
|
|
25
36
|
catch (err) {
|
|
@@ -13,6 +13,12 @@ export async function handleScamReportRejected(input, ctx) {
|
|
|
13
13
|
const name = displayNames?.[0] ?? "Unknown";
|
|
14
14
|
try {
|
|
15
15
|
const reporter = await userRepository.findById(reportedBy);
|
|
16
|
+
/*
|
|
17
|
+
* REVEALED, because this notification is DELIVERED to the reporter and a
|
|
18
|
+
* masked address cannot receive mail. `findById` is ciphertext-by-default,
|
|
19
|
+
* so passing `.email` straight through handed the mailer an `enc:v1:` blob.
|
|
20
|
+
*/
|
|
21
|
+
const reporterPlain = reporter ? userRepository.revealUser(reporter) : null;
|
|
16
22
|
await sendNotification({
|
|
17
23
|
userId: reportedBy,
|
|
18
24
|
type: "scam_report_update",
|
|
@@ -21,8 +27,8 @@ export async function handleScamReportRejected(input, ctx) {
|
|
|
21
27
|
message: `Your report for "${name}" could not be verified with the evidence provided. You may submit a new report with additional evidence.`,
|
|
22
28
|
relatedId: scammerId,
|
|
23
29
|
relatedType: "scammer",
|
|
24
|
-
userEmail:
|
|
25
|
-
userPhone:
|
|
30
|
+
userEmail: reporterPlain?.email ?? undefined,
|
|
31
|
+
userPhone: reporterPlain?.phoneNumber ?? undefined,
|
|
26
32
|
});
|
|
27
33
|
}
|
|
28
34
|
catch (err) {
|
|
@@ -13,6 +13,12 @@ export async function handleScamReportVerified(input, ctx) {
|
|
|
13
13
|
const name = displayNames?.[0] ?? "Unknown";
|
|
14
14
|
try {
|
|
15
15
|
const reporter = await userRepository.findById(reportedBy);
|
|
16
|
+
/*
|
|
17
|
+
* REVEALED, because this notification is DELIVERED to the reporter and a
|
|
18
|
+
* masked address cannot receive mail. `findById` is ciphertext-by-default,
|
|
19
|
+
* so passing `.email` straight through handed the mailer an `enc:v1:` blob.
|
|
20
|
+
*/
|
|
21
|
+
const reporterPlain = reporter ? userRepository.revealUser(reporter) : null;
|
|
16
22
|
await sendNotification({
|
|
17
23
|
userId: reportedBy,
|
|
18
24
|
type: "scam_report_update",
|
|
@@ -21,8 +27,8 @@ export async function handleScamReportVerified(input, ctx) {
|
|
|
21
27
|
message: `The report for "${name}" has been verified and published to the Scam Registry. Thank you for helping protect the community.`,
|
|
22
28
|
relatedId: scammerId,
|
|
23
29
|
relatedType: "scammer",
|
|
24
|
-
userEmail:
|
|
25
|
-
userPhone:
|
|
30
|
+
userEmail: reporterPlain?.email ?? undefined,
|
|
31
|
+
userPhone: reporterPlain?.phoneNumber ?? undefined,
|
|
26
32
|
});
|
|
27
33
|
}
|
|
28
34
|
catch (err) {
|
|
@@ -5,9 +5,16 @@
|
|
|
5
5
|
import { notifyRevalidate } from "./revalidateNotify.js";
|
|
6
6
|
export async function handleStoreWrite(input, ctx) {
|
|
7
7
|
// The search-index sync this used to perform is gone (Firestore queries handle
|
|
8
|
-
// search now), so the only remaining side-effect is cache invalidation:
|
|
9
|
-
// the ISR entries for this store's page and the stores listing. Reuses
|
|
10
|
-
// existing trigger, so
|
|
11
|
-
//
|
|
8
|
+
// search now), so the only remaining side-effect here is cache invalidation:
|
|
9
|
+
// drop the ISR entries for this store's page and the stores listing. Reuses
|
|
10
|
+
// the existing trigger, so it costs no additional invocations, and this
|
|
11
|
+
// function performs no Firestore write.
|
|
12
|
+
//
|
|
13
|
+
// 🛑 The HANDLER above it does write one, as of the public search index:
|
|
14
|
+
// `markSearchIndexDirty` flips a boolean on `searchIndex/manifest`. That is
|
|
15
|
+
// still safe under Root Cause #92 — a different collection from the one the
|
|
16
|
+
// trigger watches, with a boolean read-then-write guard — but the old
|
|
17
|
+
// blanket claim that this trigger writes nothing is no longer true, and a
|
|
18
|
+
// comment that is false is worse than no comment.
|
|
12
19
|
await notifyRevalidate({ collection: "stores", id: input.storeId }, ctx);
|
|
13
20
|
}
|
|
@@ -14,10 +14,11 @@ const ORDER_COLLECTION = "orders";
|
|
|
14
14
|
* — do not change the selection algorithm.
|
|
15
15
|
*/
|
|
16
16
|
export async function assignPrizeDrawWinner(ctx, args) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
// The `FEATURE_PRIZE_DRAWS` gate here was deleted 2026-10-19 with the other
|
|
18
|
+
// four readers — see the header of `assignSpinPrize.ts`. This one was the
|
|
19
|
+
// worst-shaped of them: it returned `kind: "not_eligible"`, which every
|
|
20
|
+
// caller treats as "this order does not win anything", so with the env var
|
|
21
|
+
// unset a paid prize-draw entry was silently recorded as a non-winner.
|
|
21
22
|
const { orderId, productId } = args;
|
|
22
23
|
const orderRef = ctx.db.collection(ORDER_COLLECTION).doc(orderId);
|
|
23
24
|
const productRef = ctx.db.collection(PRODUCT_COLLECTION).doc(productId);
|
|
@@ -17,10 +17,7 @@ const PRIZE_DRAW_LISTING_TYPE = "prize-draw";
|
|
|
17
17
|
* "closed".
|
|
18
18
|
*/
|
|
19
19
|
export async function runPrizeDrawExpiryReveal(ctx) {
|
|
20
|
-
|
|
21
|
-
ctx.logger.info("FEATURE_PRIZE_DRAWS disabled — skipping prize-draw expiry reveal");
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
20
|
+
// `FEATURE_PRIZE_DRAWS` gate deleted 2026-10-19 — see `assignSpinPrize.ts`.
|
|
24
21
|
ctx.logger.info("Prize-draw expiry reveal sweep starting");
|
|
25
22
|
const snap = await ctx.db
|
|
26
23
|
.collection(PRODUCT_COLLECTION)
|
|
@@ -18,8 +18,7 @@ function isSoldOut(doc) {
|
|
|
18
18
|
* the draw, then closes it.
|
|
19
19
|
*/
|
|
20
20
|
export async function handlePrizeDrawSoldOut(input, ctx) {
|
|
21
|
-
|
|
22
|
-
return;
|
|
21
|
+
// `FEATURE_PRIZE_DRAWS` gate deleted 2026-10-19 — see `assignSpinPrize.ts`.
|
|
23
22
|
const { productId, before, after } = input;
|
|
24
23
|
if (!after)
|
|
25
24
|
return;
|
|
@@ -6,10 +6,13 @@ import { ProductStatusValues } from "../../../../features/products/schemas/fires
|
|
|
6
6
|
* (coupon.startDate IS NULL OR <= now) filter Firestore can't express.
|
|
7
7
|
*/
|
|
8
8
|
export async function runPromotions(_input, ctx) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
/*
|
|
10
|
+
* `FEATURE_EVENTS` gate deleted 2026-10-19 — see `auctionSettlement.ts`.
|
|
11
|
+
* Unset in the Functions env, and this branch returned three EMPTY ARRAYS,
|
|
12
|
+
* which is indistinguishable from "nothing is promoted right now" to every
|
|
13
|
+
* caller. A refusal shaped like a valid empty answer is the worst of the
|
|
14
|
+
* nine; the spin route at least produced a 503 somebody could see.
|
|
15
|
+
*/
|
|
13
16
|
ctx.logger.info("Promotions data requested");
|
|
14
17
|
const now = new Date();
|
|
15
18
|
const nowIso = now.toISOString();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { JobContext } from "../runtime/types";
|
|
2
|
+
export declare function runSearchIndexBuild(ctx: JobContext): Promise<void>;
|
|
3
|
+
/**
|
|
4
|
+
* Force a full rebuild, ignoring the manifest's cadence. For a one-off repair
|
|
5
|
+
* after a schema bump or a reseed.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runSearchIndexFullRebuild(ctx: JobContext): Promise<void>;
|