@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
package/dist/.build-stamp.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"stampVersion": 1,
|
|
3
|
-
"version": "4.
|
|
4
|
-
"head": "
|
|
3
|
+
"version": "4.53.0",
|
|
4
|
+
"head": "78e72eb24243b0ee3afea21614fbbadee45d2b51",
|
|
5
5
|
"branch": "main",
|
|
6
|
-
"dirty":
|
|
7
|
-
"builtAt": "2026-10-
|
|
6
|
+
"dirty": false,
|
|
7
|
+
"builtAt": "2026-10-19T12:44:44.499Z"
|
|
8
8
|
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
/*
|
|
3
|
+
* One message, three throw sites. A 2d context is only ever null when the
|
|
4
|
+
* browser refuses the canvas outright (memory pressure, or a hardened
|
|
5
|
+
* environment), so all three mean the same thing and should read the same.
|
|
6
|
+
*/
|
|
7
|
+
const NO_CONTEXT = "OffscreenCanvas 2d context unavailable";
|
|
8
|
+
/** RGBA out of a canvas, in exactly the layout DecodedRaster promises. */
|
|
9
|
+
function toRaster(bitmap, dpi) {
|
|
10
|
+
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
11
|
+
const ctx = canvas.getContext("2d", { willReadFrequently: true });
|
|
12
|
+
if (!ctx)
|
|
13
|
+
throw new Error(NO_CONTEXT);
|
|
14
|
+
ctx.drawImage(bitmap, 0, 0);
|
|
15
|
+
const data = ctx.getImageData(0, 0, bitmap.width, bitmap.height).data;
|
|
16
|
+
bitmap.close();
|
|
17
|
+
return {
|
|
18
|
+
width: canvas.width,
|
|
19
|
+
height: canvas.height,
|
|
20
|
+
data: new Uint8Array(data.buffer),
|
|
21
|
+
...(dpi !== undefined ? { dpi } : {}),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
async function encode(canvas, format) {
|
|
25
|
+
const type = format === "webp" ? "image/webp" : "image/png";
|
|
26
|
+
const blob = await canvas.convertToBlob({ type, ...(format === "webp" ? { quality: 0.82 } : {}) });
|
|
27
|
+
return { bytes: new Uint8Array(await blob.arrayBuffer()), contentType: type };
|
|
28
|
+
}
|
|
29
|
+
function canvasOf(raster) {
|
|
30
|
+
const canvas = new OffscreenCanvas(raster.width, raster.height);
|
|
31
|
+
const ctx = canvas.getContext("2d");
|
|
32
|
+
if (!ctx)
|
|
33
|
+
throw new Error(NO_CONTEXT);
|
|
34
|
+
ctx.putImageData(new ImageData(new Uint8ClampedArray(raster.data), raster.width, raster.height), 0, 0);
|
|
35
|
+
return canvas;
|
|
36
|
+
}
|
|
37
|
+
export const canvasCodec = {
|
|
38
|
+
/**
|
|
39
|
+
* 🛑 `declaredDpi` is ALWAYS absent here, and that is the one real asymmetry
|
|
40
|
+
* with the sharp codec.
|
|
41
|
+
*
|
|
42
|
+
* sharp reads the file's density header; a browser exposes no such API, and
|
|
43
|
+
* parsing EXIF/pHYs by hand would be a second metadata implementation whose
|
|
44
|
+
* disagreements with sharp nobody would notice. So the browser reports
|
|
45
|
+
* dimensions only — which costs nothing, because the operator confirms dpi
|
|
46
|
+
* anyway (five of the nine reference scans declare 72 or 96, an encoder
|
|
47
|
+
* default rather than a measurement) and a sheet with no trustworthy dpi
|
|
48
|
+
* already renders `bboxMm: null` rather than a fabricated figure.
|
|
49
|
+
*
|
|
50
|
+
* Also NOT header-only, unlike sharp's: `createImageBitmap` decodes. A
|
|
51
|
+
* browser cannot read a header without decoding, so this is dimensions at
|
|
52
|
+
* the cost of a decode — acceptable for one file the user just picked, and
|
|
53
|
+
* the reason the server probe exists for the upload path.
|
|
54
|
+
*/
|
|
55
|
+
async probe(source) {
|
|
56
|
+
const bitmap = await createImageBitmap(new Blob([source]));
|
|
57
|
+
const result = { width: bitmap.width, height: bitmap.height };
|
|
58
|
+
bitmap.close();
|
|
59
|
+
return result;
|
|
60
|
+
},
|
|
61
|
+
async decode(source, opts) {
|
|
62
|
+
const blob = new Blob([source]);
|
|
63
|
+
// Probe dimensions first so the resize preserves aspect ratio and never
|
|
64
|
+
// ENLARGES — upscaling would invent sub-pixel detail the ridge detector
|
|
65
|
+
// would then find cut lines in.
|
|
66
|
+
const probe = await createImageBitmap(blob);
|
|
67
|
+
const longEdge = Math.max(probe.width, probe.height);
|
|
68
|
+
probe.close();
|
|
69
|
+
if (longEdge <= opts.maxLongEdge) {
|
|
70
|
+
return toRaster(await createImageBitmap(blob));
|
|
71
|
+
}
|
|
72
|
+
const k = opts.maxLongEdge / longEdge;
|
|
73
|
+
return toRaster(await createImageBitmap(blob, {
|
|
74
|
+
resizeWidth: Math.max(1, Math.round(probe.width * k)),
|
|
75
|
+
resizeHeight: Math.max(1, Math.round(probe.height * k)),
|
|
76
|
+
resizeQuality: "high",
|
|
77
|
+
}));
|
|
78
|
+
},
|
|
79
|
+
/**
|
|
80
|
+
* No resize — a tile is already bounded by the caller, and the `max` tier
|
|
81
|
+
* tiles precisely so it can read native pixels.
|
|
82
|
+
*/
|
|
83
|
+
async decodeTile(source, tile) {
|
|
84
|
+
return toRaster(await createImageBitmap(new Blob([source]), {
|
|
85
|
+
sx: tile.x,
|
|
86
|
+
sy: tile.y,
|
|
87
|
+
sw: tile.width,
|
|
88
|
+
sh: tile.height,
|
|
89
|
+
}));
|
|
90
|
+
},
|
|
91
|
+
async encodePng(raster) {
|
|
92
|
+
return encode(canvasOf(raster), "png");
|
|
93
|
+
},
|
|
94
|
+
async encodePngRegion(source, region, alpha) {
|
|
95
|
+
const expected = region.width * region.height;
|
|
96
|
+
if (alpha.length !== expected) {
|
|
97
|
+
// Loud, matching the sharp codec: a silent mismatch yields a part with a
|
|
98
|
+
// plausible outline and the wrong transparency, invisible until it is cut.
|
|
99
|
+
throw new Error(`alpha mask is ${alpha.length} px, expected ${expected} for ${region.width}x${region.height}`);
|
|
100
|
+
}
|
|
101
|
+
const raster = await this.decodeTile(source, region);
|
|
102
|
+
const px = raster.data;
|
|
103
|
+
for (let i = 0; i < expected; i++)
|
|
104
|
+
px[i * 4 + 3] = alpha[i];
|
|
105
|
+
return encode(canvasOf({ width: region.width, height: region.height, data: px }), "png");
|
|
106
|
+
},
|
|
107
|
+
async encodePreview(source, opts) {
|
|
108
|
+
const raster = await this.decode(source, { maxLongEdge: opts.maxLongEdge });
|
|
109
|
+
return encode(canvasOf(raster), opts.format);
|
|
110
|
+
},
|
|
111
|
+
/**
|
|
112
|
+
* Uniform-cell grid, identical in layout to the sharp codec's — the frames
|
|
113
|
+
* map is a contract the review UI reads, so the two must agree on geometry
|
|
114
|
+
* even though they agree on nothing about how they draw.
|
|
115
|
+
*/
|
|
116
|
+
async encodeAtlas(tiles, opts) {
|
|
117
|
+
if (tiles.length === 0) {
|
|
118
|
+
// A zero-part run is a real outcome; a valid 1x1 beats throwing.
|
|
119
|
+
return {
|
|
120
|
+
image: await encode(new OffscreenCanvas(1, 1), "png"),
|
|
121
|
+
frames: {},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const cols = Math.ceil(Math.sqrt(tiles.length));
|
|
125
|
+
const rows = Math.ceil(tiles.length / cols);
|
|
126
|
+
const cell = Math.max(1, Math.min(Math.floor(opts.maxLongEdge / cols), ...tiles.map((t) => Math.max(t.raster.width, t.raster.height))));
|
|
127
|
+
const canvas = new OffscreenCanvas(cols * cell, rows * cell);
|
|
128
|
+
const ctx = canvas.getContext("2d");
|
|
129
|
+
if (!ctx)
|
|
130
|
+
throw new Error(NO_CONTEXT);
|
|
131
|
+
const frames = {};
|
|
132
|
+
for (let i = 0; i < tiles.length; i++) {
|
|
133
|
+
const t = tiles[i];
|
|
134
|
+
const left = (i % cols) * cell;
|
|
135
|
+
const top = Math.floor(i / cols) * cell;
|
|
136
|
+
// `fit: inside` equivalent — preserve aspect, never enlarge.
|
|
137
|
+
const k = Math.min(cell / t.raster.width, cell / t.raster.height, 1);
|
|
138
|
+
const w = Math.max(1, Math.round(t.raster.width * k));
|
|
139
|
+
const h = Math.max(1, Math.round(t.raster.height * k));
|
|
140
|
+
ctx.drawImage(canvasOf(t.raster), left, top, w, h);
|
|
141
|
+
// The frame is the tile's ACTUAL size, not the cell: a wide sticker does
|
|
142
|
+
// not fill a square cell, and a client slicing by `cell` would include
|
|
143
|
+
// its neighbours' padding.
|
|
144
|
+
frames[t.ordinal] = { x: left, y: top, width: w, height: h };
|
|
145
|
+
}
|
|
146
|
+
return { image: await encode(canvas, "png"), frames };
|
|
147
|
+
},
|
|
148
|
+
};
|
|
@@ -31,7 +31,7 @@ export async function placeBidAction(input) {
|
|
|
31
31
|
// marking included. It cost a full-collection query and an exception per
|
|
32
32
|
// bid placed, and the real `setWinningBid(bid.id, …)` below already marks
|
|
33
33
|
// every other bid for this product as outbid.)
|
|
34
|
-
const bid = await bidRepository.
|
|
34
|
+
const bid = await bidRepository.createBid({
|
|
35
35
|
productId: auctionId,
|
|
36
36
|
productTitle: product.title ?? auctionId,
|
|
37
37
|
userId: user.uid,
|
|
@@ -63,11 +63,27 @@ export const getCategoryTree = cache(async (rootId) => {
|
|
|
63
63
|
});
|
|
64
64
|
/** Flat category list for sitemap generation. */
|
|
65
65
|
export const listSitemapCategories = cache(async () => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
/*
|
|
67
|
+
* 🛑 `safeRead`, not `.catch(() => [])`. This function feeds the SITEMAP,
|
|
68
|
+
* so a swallowed Firestore failure publishes an empty category sitemap to
|
|
69
|
+
* crawlers and nothing anywhere says why — the single worst place in the
|
|
70
|
+
* app for a failure that reads as "there is no data". Root Cause #81 is
|
|
71
|
+
* what a quietly wrong sitemap costs.
|
|
72
|
+
*
|
|
73
|
+
* The fallback is still `[]` (a sitemap must render), but the degradation
|
|
74
|
+
* is now a `DEGRADED_READ` row instead of silence. The file already used
|
|
75
|
+
* `safeRead` a few lines up; this site was simply missed.
|
|
76
|
+
*/
|
|
77
|
+
const r = await safeRead(() => categoriesRepository.list({
|
|
78
|
+
filters: "isActive==true",
|
|
79
|
+
sorts: "-updatedAt",
|
|
80
|
+
page: 1,
|
|
81
|
+
pageSize: CATEGORIES_SITEMAP_LIMIT,
|
|
82
|
+
}), {
|
|
83
|
+
route: "sitemap",
|
|
84
|
+
key: "categories.listSitemapCategories",
|
|
85
|
+
fallback: null,
|
|
86
|
+
});
|
|
87
|
+
const docs = r?.data ?? [];
|
|
88
|
+
return docs.map(({ slug, updatedAt }) => ({ slug, updatedAt }));
|
|
73
89
|
});
|
|
@@ -618,7 +618,7 @@ async function createOrderForGroup(group, orderType, ctx) {
|
|
|
618
618
|
// create-vs-create axis of Root Cause #39, and these two functions have
|
|
619
619
|
// already drifted once before (add-on fees, Root Cause #65).
|
|
620
620
|
const sourceContext = await buildOrderSourceContext(firstItem, firstProduct, orderType);
|
|
621
|
-
const order = await unitOfWork.orders.
|
|
621
|
+
const order = await unitOfWork.orders.createOrder({
|
|
622
622
|
productId: firstItem.productId,
|
|
623
623
|
productTitle: firstItem.productTitle,
|
|
624
624
|
userId: uid,
|
|
@@ -1478,7 +1478,7 @@ async function createPhonePeGroupOrder(group, orderType, ctx) {
|
|
|
1478
1478
|
// create-vs-create axis of Root Cause #39, and these two functions have
|
|
1479
1479
|
// already drifted once before (add-on fees, Root Cause #65).
|
|
1480
1480
|
const sourceContext = await buildOrderSourceContext(firstItem, group[0].product, orderType);
|
|
1481
|
-
const order = await unitOfWork.orders.
|
|
1481
|
+
const order = await unitOfWork.orders.createOrder({
|
|
1482
1482
|
productId: firstItem.productId,
|
|
1483
1483
|
productTitle: firstItem.productTitle,
|
|
1484
1484
|
userId: uid,
|
|
@@ -1654,8 +1654,15 @@ export async function verifyAndPlacePhonePeOrderAction(input) {
|
|
|
1654
1654
|
let userEmail = input.userEmail;
|
|
1655
1655
|
if (userName === undefined || userEmail === undefined) {
|
|
1656
1656
|
const userDoc = await userRepository.findById(uid);
|
|
1657
|
+
/*
|
|
1658
|
+
* 🛑 Revealed: `createOrder` encrypts `userEmail`, so handing it the
|
|
1659
|
+
* ciphertext this read returns would double-encrypt it and make the
|
|
1660
|
+
* buyer's address on the order undecryptable. `displayName` is not PII and
|
|
1661
|
+
* needs no reveal.
|
|
1662
|
+
*/
|
|
1663
|
+
const userPlain = userDoc ? userRepository.revealUser(userDoc) : null;
|
|
1657
1664
|
userName = userName ?? userDoc?.displayName ?? "Customer";
|
|
1658
|
-
userEmail = userEmail ??
|
|
1665
|
+
userEmail = userEmail ?? userPlain?.email ?? "";
|
|
1659
1666
|
}
|
|
1660
1667
|
const addressId = input.addressId ?? intent?.addressId;
|
|
1661
1668
|
const notes = input.notes ?? intent?.notes;
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import type { AddressDocument } from "../../../../features/account/schemas/index";
|
|
2
|
+
/**
|
|
3
|
+
* Flatten an address into the one-line string stored on
|
|
4
|
+
* `OrderDocument.shippingAddress` and printed on invoices and labels.
|
|
5
|
+
*
|
|
6
|
+
* 🛑 Reveals INSIDE the function, deliberately, rather than asking its two
|
|
7
|
+
* callers to.
|
|
8
|
+
*
|
|
9
|
+
* `AddressDocument` is ciphertext-by-default, and `shippingAddress` is NOT a
|
|
10
|
+
* PII field — so joining the stored values froze three `enc:v1:` blobs into one
|
|
11
|
+
* string that is no longer a valid envelope and can never be decrypted. It is
|
|
12
|
+
* then printed on every invoice, shipping label and order-confirmation email.
|
|
13
|
+
*
|
|
14
|
+
* Doing it here rather than at `actions.ts:1279` and `:2506` is the point: a
|
|
15
|
+
* third caller gets it right by construction instead of by remembering.
|
|
16
|
+
*/
|
|
2
17
|
export declare function formatShippingAddress(a: AddressDocument): string;
|
|
3
18
|
export interface CheckoutOrderResult {
|
|
4
19
|
orderIds: string[];
|
|
@@ -1,8 +1,25 @@
|
|
|
1
|
+
import { ADDRESS_PII_FIELDS, revealPii } from "../../../../security/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Flatten an address into the one-line string stored on
|
|
4
|
+
* `OrderDocument.shippingAddress` and printed on invoices and labels.
|
|
5
|
+
*
|
|
6
|
+
* 🛑 Reveals INSIDE the function, deliberately, rather than asking its two
|
|
7
|
+
* callers to.
|
|
8
|
+
*
|
|
9
|
+
* `AddressDocument` is ciphertext-by-default, and `shippingAddress` is NOT a
|
|
10
|
+
* PII field — so joining the stored values froze three `enc:v1:` blobs into one
|
|
11
|
+
* string that is no longer a valid envelope and can never be decrypted. It is
|
|
12
|
+
* then printed on every invoice, shipping label and order-confirmation email.
|
|
13
|
+
*
|
|
14
|
+
* Doing it here rather than at `actions.ts:1279` and `:2506` is the point: a
|
|
15
|
+
* third caller gets it right by construction instead of by remembering.
|
|
16
|
+
*/
|
|
1
17
|
export function formatShippingAddress(a) {
|
|
18
|
+
const plain = revealPii(a, ADDRESS_PII_FIELDS);
|
|
2
19
|
const parts = [
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
20
|
+
plain.fullName,
|
|
21
|
+
plain.addressLine1,
|
|
22
|
+
plain.addressLine2,
|
|
6
23
|
a.landmark,
|
|
7
24
|
a.city,
|
|
8
25
|
a.state,
|
|
@@ -117,7 +117,15 @@ export async function submitLotteryPullAction(input) {
|
|
|
117
117
|
});
|
|
118
118
|
return { assignedSlot: chosen, userLotteryNumber: nextNumber };
|
|
119
119
|
});
|
|
120
|
-
|
|
120
|
+
/*
|
|
121
|
+
* Create the entry document outside the transaction (acceptable — slot is
|
|
122
|
+
* already booked).
|
|
123
|
+
*
|
|
124
|
+
* Typed `LotteryEntryPlain`: this is PLAINTEXT from the session and the
|
|
125
|
+
* request body, and `createEntry` encrypts it. The document type now says
|
|
126
|
+
* `Encrypted<string>`, so annotating this `LotteryEntryDocument` is a
|
|
127
|
+
* compile error — correctly, because the values here are not ciphertext.
|
|
128
|
+
*/
|
|
121
129
|
const entryData = {
|
|
122
130
|
sourceType: data.sourceType,
|
|
123
131
|
...(data.sourceType === "event" ? { eventId: sourceId } : { productId: sourceId }),
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lottery OG image renderer.
|
|
3
|
+
*
|
|
4
|
+
* ## Why this did not exist
|
|
5
|
+
*
|
|
6
|
+
* `lottery/[id]` was the single entry in `verify-og-coverage`'s
|
|
7
|
+
* `OG_KNOWN_GAPS` — the one public dynamic detail page shipping without an
|
|
8
|
+
* `opengraph-image.tsx`, carried as a baseline since 2026-05-23 with the note
|
|
9
|
+
* "OG image follows in a follow-up". Metadata already resolved
|
|
10
|
+
* (`buildLotteryMetadata`), so a shared link rendered a title and whatever the
|
|
11
|
+
* event's cover image happened to be, with none of the branded card every
|
|
12
|
+
* other listing type gets.
|
|
13
|
+
*
|
|
14
|
+
* ## 🛑 No money, and no per-slot prices
|
|
15
|
+
*
|
|
16
|
+
* An OG image is a public image URL with its contents burned into the pixels:
|
|
17
|
+
* no sign-in gate reaches it and no paywall markup describes it, which is why
|
|
18
|
+
* all eight money-bearing renderers were stripped (Root Cause #93). A lottery
|
|
19
|
+
* is the sharpest case in the codebase — `toClientLotteryConfig` is an
|
|
20
|
+
* allow-list that exists specifically to keep `price` and `weight` off every
|
|
21
|
+
* slot — so this renderer takes the CLIENT shape and reads only what that
|
|
22
|
+
* allow-list already permits: the slot count, and how many are still free.
|
|
23
|
+
*
|
|
24
|
+
* "6 of 200 slots left" is a fact about availability rather than a disclosed
|
|
25
|
+
* amount, and it is the half of the card that earns the click — exactly the
|
|
26
|
+
* line `renderPrizeDrawOg` draws for "Free entry".
|
|
27
|
+
*/
|
|
28
|
+
import type { ReactElement } from "react";
|
|
29
|
+
import type { LotteryEventClient } from "./data";
|
|
30
|
+
export interface LotteryOgData {
|
|
31
|
+
title: string;
|
|
32
|
+
imageUrl?: string | null;
|
|
33
|
+
slotsLabel?: string | null;
|
|
34
|
+
statusLabel?: string | null;
|
|
35
|
+
}
|
|
36
|
+
export declare function renderLotteryOg(event: LotteryEventClient | null | undefined, opts: {
|
|
37
|
+
siteName: string;
|
|
38
|
+
baseUrl?: string;
|
|
39
|
+
}): ReactElement;
|
|
40
|
+
export declare function renderLotteryOgImage(data: LotteryOgData, siteName: string): ReactElement;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lottery OG image renderer.
|
|
3
|
+
*
|
|
4
|
+
* ## Why this did not exist
|
|
5
|
+
*
|
|
6
|
+
* `lottery/[id]` was the single entry in `verify-og-coverage`'s
|
|
7
|
+
* `OG_KNOWN_GAPS` — the one public dynamic detail page shipping without an
|
|
8
|
+
* `opengraph-image.tsx`, carried as a baseline since 2026-05-23 with the note
|
|
9
|
+
* "OG image follows in a follow-up". Metadata already resolved
|
|
10
|
+
* (`buildLotteryMetadata`), so a shared link rendered a title and whatever the
|
|
11
|
+
* event's cover image happened to be, with none of the branded card every
|
|
12
|
+
* other listing type gets.
|
|
13
|
+
*
|
|
14
|
+
* ## 🛑 No money, and no per-slot prices
|
|
15
|
+
*
|
|
16
|
+
* An OG image is a public image URL with its contents burned into the pixels:
|
|
17
|
+
* no sign-in gate reaches it and no paywall markup describes it, which is why
|
|
18
|
+
* all eight money-bearing renderers were stripped (Root Cause #93). A lottery
|
|
19
|
+
* is the sharpest case in the codebase — `toClientLotteryConfig` is an
|
|
20
|
+
* allow-list that exists specifically to keep `price` and `weight` off every
|
|
21
|
+
* slot — so this renderer takes the CLIENT shape and reads only what that
|
|
22
|
+
* allow-list already permits: the slot count, and how many are still free.
|
|
23
|
+
*
|
|
24
|
+
* "6 of 200 slots left" is a fact about availability rather than a disclosed
|
|
25
|
+
* amount, and it is the half of the card that earns the click — exactly the
|
|
26
|
+
* line `renderPrizeDrawOg` draws for "Free entry".
|
|
27
|
+
*/
|
|
28
|
+
import { renderOgLayout } from "../seo/og-layout.js";
|
|
29
|
+
import { resolveOgImageUrl } from "../seo/og.js";
|
|
30
|
+
/**
|
|
31
|
+
* The event's own status, as a human badge. `active` is deliberately absent:
|
|
32
|
+
* a live lottery is the default case, so a chip saying so costs a badge slot
|
|
33
|
+
* and tells the reader nothing they would not assume.
|
|
34
|
+
*/
|
|
35
|
+
const STATUS_BADGE_TEXT = {
|
|
36
|
+
draft: "Not yet open",
|
|
37
|
+
paused: "Paused",
|
|
38
|
+
ended: "Closed",
|
|
39
|
+
cancelled: "Cancelled",
|
|
40
|
+
};
|
|
41
|
+
export function renderLotteryOg(event, opts) {
|
|
42
|
+
const cfg = event?.lotteryConfig;
|
|
43
|
+
const slots = cfg?.slots ?? [];
|
|
44
|
+
/*
|
|
45
|
+
* Counted from the slot array rather than read from `totalSlots`, which is
|
|
46
|
+
* the mirror the admin write path derives FROM `slots.length` — and a mirror
|
|
47
|
+
* is the field most likely to disagree (Root Cause #42). The array is here
|
|
48
|
+
* either way, so counting it costs nothing.
|
|
49
|
+
*/
|
|
50
|
+
const total = slots.length;
|
|
51
|
+
const free = slots.filter((s) => !s.isBooked).length;
|
|
52
|
+
const slotsLabel = total > 0
|
|
53
|
+
? free > 0
|
|
54
|
+
? `${free.toLocaleString("en-IN")} of ${total.toLocaleString("en-IN")} slots left`
|
|
55
|
+
: `All ${total.toLocaleString("en-IN")} slots claimed`
|
|
56
|
+
: null;
|
|
57
|
+
const coverUrl = event?.coverImage && typeof event.coverImage.url === "string"
|
|
58
|
+
? event.coverImage.url
|
|
59
|
+
: (event?.coverImageUrl ?? null);
|
|
60
|
+
return renderLotteryOgImage({
|
|
61
|
+
title: event?.title ?? "Lottery",
|
|
62
|
+
imageUrl: resolveOgImageUrl(coverUrl, opts.baseUrl),
|
|
63
|
+
slotsLabel,
|
|
64
|
+
statusLabel: event?.status ? (STATUS_BADGE_TEXT[event.status] ?? null) : null,
|
|
65
|
+
}, opts.siteName);
|
|
66
|
+
}
|
|
67
|
+
export function renderLotteryOgImage(data, siteName) {
|
|
68
|
+
const badges = [data.statusLabel].filter((s) => Boolean(s));
|
|
69
|
+
return renderOgLayout({
|
|
70
|
+
title: data.title,
|
|
71
|
+
subtitle: data.slotsLabel ?? undefined,
|
|
72
|
+
imageUrl: data.imageUrl,
|
|
73
|
+
siteName: `${siteName} · Lottery`,
|
|
74
|
+
badges: badges.length > 0 ? badges : undefined,
|
|
75
|
+
// Violet, distinct from the prize-draw amber beside it in the nav — the two
|
|
76
|
+
// are different products and a shared accent makes shared links ambiguous.
|
|
77
|
+
theme: { accentColor: "#8b5cf6" },
|
|
78
|
+
});
|
|
79
|
+
}
|
|
@@ -12,6 +12,7 @@ import { createMessage, listMessages, softDeleteMessage, deleteAllMessages, list
|
|
|
12
12
|
import { finalizeStagedMediaArray } from "../../../../features/media/finalize.js";
|
|
13
13
|
import { sendNotification } from "../../../../features/admin/actions/notification-actions.js";
|
|
14
14
|
import { productRepository } from "../../../../features/products/repository/products.repository.js";
|
|
15
|
+
import { normalizeListingType } from "../../../../features/products/utils/listing-type.js";
|
|
15
16
|
import { siteSettingsRepository } from "../../../../repositories/index.js";
|
|
16
17
|
const MESSAGE_MAX_LENGTH = 2000;
|
|
17
18
|
/**
|
|
@@ -161,6 +162,9 @@ export async function sendMessage(input) {
|
|
|
161
162
|
title: product.title,
|
|
162
163
|
image: product.images?.[0],
|
|
163
164
|
price: product.price,
|
|
165
|
+
// Without this the card cannot pick the right detail route — see the
|
|
166
|
+
// field's own comment on `MessageProductRef`.
|
|
167
|
+
listingType: normalizeListingType(product),
|
|
164
168
|
};
|
|
165
169
|
}
|
|
166
170
|
// A missing/deleted product is not an error — the card simply doesn't
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
// Display masking only — `pii-mask.ts` is the crypto-FREE half that Root Cause
|
|
14
14
|
// #24 split out of `pii-encrypt.ts` precisely so it could be imported freely.
|
|
15
|
-
import {
|
|
15
|
+
import { offerRepository } from "../../../../features/seller/repository/offer.repository.js";
|
|
16
16
|
function toIsoOrUndefined(value) {
|
|
17
17
|
return value instanceof Date ? value.toISOString() : undefined;
|
|
18
18
|
}
|
|
@@ -21,11 +21,25 @@ function toIso(value) {
|
|
|
21
21
|
}
|
|
22
22
|
/** The three buyer keys, resolved per `buyerIdentity`. Absent keys stay absent. */
|
|
23
23
|
function buyerIdentityFields(doc, mode) {
|
|
24
|
+
/*
|
|
25
|
+
* 🛑 Both branches go through the repository's named accessors.
|
|
26
|
+
*
|
|
27
|
+
* `OfferRepository.mapDoc` no longer decrypts, so `doc.buyerName` and
|
|
28
|
+
* `doc.buyerEmail` are CIPHERTEXT here. Before this, `"full"` returned the
|
|
29
|
+
* `enc:v1:` blobs straight to the seller, and `"masked"` handed them to
|
|
30
|
+
* `maskName`/`maskEmail`, which refuse ciphertext by design and answer
|
|
31
|
+
* "Anonymous" / "***@***.***" — so neither mode worked, in opposite ways.
|
|
32
|
+
*
|
|
33
|
+
* `"full"` is the seller's own view of a buyer who made them an offer, which
|
|
34
|
+
* is a legitimate plaintext read; `"masked"` is everything else.
|
|
35
|
+
*/
|
|
24
36
|
if (mode === "full") {
|
|
25
|
-
|
|
37
|
+
const plain = offerRepository.revealOffer(doc);
|
|
38
|
+
return { buyerUid: doc.buyerUid, buyerName: plain.buyerName, buyerEmail: plain.buyerEmail };
|
|
26
39
|
}
|
|
27
40
|
if (mode === "masked") {
|
|
28
|
-
|
|
41
|
+
const masked = offerRepository.maskedOffer(doc);
|
|
42
|
+
return { buyerName: masked.buyerName, buyerEmail: masked.buyerEmail };
|
|
29
43
|
}
|
|
30
44
|
return {};
|
|
31
45
|
}
|
|
@@ -22,7 +22,7 @@ export async function createOrderAction(input) {
|
|
|
22
22
|
const parsed = createOrderSchema.safeParse(input);
|
|
23
23
|
if (!parsed.success)
|
|
24
24
|
throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid order input");
|
|
25
|
-
return orderRepository.
|
|
25
|
+
return orderRepository.createOrder({
|
|
26
26
|
...parsed.data,
|
|
27
27
|
userId: user.uid,
|
|
28
28
|
status: "pending",
|
|
@@ -211,7 +211,12 @@ export async function attachPaymentProofAction(orderId, proof) {
|
|
|
211
211
|
});
|
|
212
212
|
notifyAdminsOfPaymentProof({
|
|
213
213
|
id: orderId,
|
|
214
|
-
|
|
214
|
+
/*
|
|
215
|
+
* Revealed: this names the buyer to an admin who is about to verify
|
|
216
|
+
* their payment proof, so a mask would defeat the purpose. `order` comes
|
|
217
|
+
* from a repository read, which is ciphertext-by-default.
|
|
218
|
+
*/
|
|
219
|
+
userName: orderRepository.revealOrder(order).userName,
|
|
215
220
|
productTitle: order.productTitle,
|
|
216
221
|
totalPrice: order.totalPrice,
|
|
217
222
|
});
|
|
@@ -10,3 +10,22 @@ import { type TriggerEventRaffleInput, type TriggerEventRaffleResult } from "../
|
|
|
10
10
|
import { type AssignSpinPrizeInput, type AssignSpinPrizeResult } from "../../jobs/core/assignSpinPrize";
|
|
11
11
|
export declare function triggerEventRaffleAction(input: TriggerEventRaffleInput): Promise<ActionResult<TriggerEventRaffleResult>>;
|
|
12
12
|
export declare function assignSpinPrizeAction(input: AssignSpinPrizeInput): Promise<ActionResult<AssignSpinPrizeResult>>;
|
|
13
|
+
/**
|
|
14
|
+
* Resolve a slug-or-id to the canonical event DOCUMENT ID.
|
|
15
|
+
*
|
|
16
|
+
* Exists for one caller — `POST /api/events/[id]/spin`, which must hash a
|
|
17
|
+
* guest's identity against a stable key BEFORE calling the spin action.
|
|
18
|
+
*
|
|
19
|
+
* 🛑 Why this is not just a nicety. Public URLs link by slug, so the route
|
|
20
|
+
* received a slug and did `hashGuestIdentity(slug, request)`, while
|
|
21
|
+
* `enterEvent` hashes on the resolved doc id. Two identities for one guest on
|
|
22
|
+
* one event. While the spin core's lookup was broken that was invisible (every
|
|
23
|
+
* spin 404'd); the moment the lookup was fixed it would have become a silent
|
|
24
|
+
* `spinMaxPerUser` bypass — exhaust your spins on `/events/<slug>/participate`
|
|
25
|
+
* and get a fresh allowance on `/events/<docId>/participate`.
|
|
26
|
+
*
|
|
27
|
+
* Returns `null` for an unknown event; the route then lets the spin action
|
|
28
|
+
* produce the single authoritative `event_not_found` rather than guessing at
|
|
29
|
+
* one here.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveEventIdAction(idOrSlug: string): Promise<ActionResult<string | null>>;
|
|
@@ -10,6 +10,7 @@ import { wrapAction } from "@mohasinac/appkit/server";
|
|
|
10
10
|
import { getAdminDb } from "../../../../providers/db-firebase/admin.js";
|
|
11
11
|
import { runTriggerEventRaffle, } from "../../jobs/core/triggerEventRaffle.js";
|
|
12
12
|
import { runAssignSpinPrize, } from "../../jobs/core/assignSpinPrize.js";
|
|
13
|
+
import { resolveEventRef } from "../../jobs/core/_event-ref.js";
|
|
13
14
|
function buildContext(job) {
|
|
14
15
|
const logger = {
|
|
15
16
|
info: (msg, meta) => console.info(`[${job}] ${msg}`, meta ?? {}),
|
|
@@ -30,3 +31,27 @@ export async function triggerEventRaffleAction(input) {
|
|
|
30
31
|
export async function assignSpinPrizeAction(input) {
|
|
31
32
|
return wrapAction(async () => runAssignSpinPrize(input, buildContext("user.assignSpinPrize")));
|
|
32
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Resolve a slug-or-id to the canonical event DOCUMENT ID.
|
|
36
|
+
*
|
|
37
|
+
* Exists for one caller — `POST /api/events/[id]/spin`, which must hash a
|
|
38
|
+
* guest's identity against a stable key BEFORE calling the spin action.
|
|
39
|
+
*
|
|
40
|
+
* 🛑 Why this is not just a nicety. Public URLs link by slug, so the route
|
|
41
|
+
* received a slug and did `hashGuestIdentity(slug, request)`, while
|
|
42
|
+
* `enterEvent` hashes on the resolved doc id. Two identities for one guest on
|
|
43
|
+
* one event. While the spin core's lookup was broken that was invisible (every
|
|
44
|
+
* spin 404'd); the moment the lookup was fixed it would have become a silent
|
|
45
|
+
* `spinMaxPerUser` bypass — exhaust your spins on `/events/<slug>/participate`
|
|
46
|
+
* and get a fresh allowance on `/events/<docId>/participate`.
|
|
47
|
+
*
|
|
48
|
+
* Returns `null` for an unknown event; the route then lets the spin action
|
|
49
|
+
* produce the single authoritative `event_not_found` rather than guessing at
|
|
50
|
+
* one here.
|
|
51
|
+
*/
|
|
52
|
+
export async function resolveEventIdAction(idOrSlug) {
|
|
53
|
+
return wrapAction(async () => {
|
|
54
|
+
const resolved = await resolveEventRef(buildContext("user.resolveEventId").db, idOrSlug);
|
|
55
|
+
return resolved?.id ?? null;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -17,7 +17,7 @@ export async function createReviewAction(input) {
|
|
|
17
17
|
await assertNotDuplicateReview(productId, user.uid);
|
|
18
18
|
const product = await productRepository.findById(productId);
|
|
19
19
|
const profile = await userRepository.findById(user.uid);
|
|
20
|
-
return reviewRepository.
|
|
20
|
+
return reviewRepository.createReview({
|
|
21
21
|
productId,
|
|
22
22
|
productTitle: product?.title ?? productId,
|
|
23
23
|
storeId: storeId || product?.storeId,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const getReviewsForProduct: (productId: string, limit?: number) => Promise<import("../../../..").ReviewDocument[]>;
|
|
2
|
-
export declare const getReviewsForStore: (storeId: string, page?: number, pageSize?: number) => Promise<import("../../../..").FirebaseSieveResult<import("../../../..").ReviewDocument
|
|
2
|
+
export declare const getReviewsForStore: (storeId: string, page?: number, pageSize?: number) => Promise<import("../../../..").FirebaseSieveResult<import("../../../../security/encrypted").Plaintext<import("../../../..").ReviewDocument>> | {
|
|
3
3
|
items: never[];
|
|
4
4
|
total: number;
|
|
5
5
|
page: number;
|