@mohasinac/appkit 4.52.4 → 4.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.build-stamp.json +4 -4
- package/dist/_internal/client/features/sticker-trace/canvas-codec.d.ts +2 -0
- package/dist/_internal/client/features/sticker-trace/canvas-codec.js +148 -0
- package/dist/_internal/server/features/auctions/actions.js +1 -1
- package/dist/_internal/server/features/categories/data.js +23 -7
- package/dist/_internal/server/features/checkout/actions.js +10 -3
- package/dist/_internal/server/features/checkout/data.d.ts +15 -0
- package/dist/_internal/server/features/checkout/data.js +20 -3
- package/dist/_internal/server/features/lottery/actions.js +9 -1
- package/dist/_internal/server/features/lottery/og.d.ts +40 -0
- package/dist/_internal/server/features/lottery/og.js +79 -0
- package/dist/_internal/server/features/messages/actions.js +4 -0
- package/dist/_internal/server/features/offers/adapters.js +17 -3
- package/dist/_internal/server/features/orders/actions.js +7 -2
- package/dist/_internal/server/features/raffle/actions.d.ts +19 -0
- package/dist/_internal/server/features/raffle/actions.js +25 -0
- package/dist/_internal/server/features/reviews/actions.js +1 -1
- package/dist/_internal/server/features/reviews/data.d.ts +1 -1
- package/dist/_internal/server/features/search/index-build/artifact-store.d.ts +89 -0
- package/dist/_internal/server/features/search/index-build/artifact-store.js +208 -0
- package/dist/_internal/server/features/search/index-build/build.d.ts +57 -0
- package/dist/_internal/server/features/search/index-build/build.js +285 -0
- package/dist/_internal/server/features/search/index-build/sources.d.ts +53 -0
- package/dist/_internal/server/features/search/index-build/sources.js +385 -0
- package/dist/_internal/server/features/search/search-sources.d.ts +0 -15
- package/dist/_internal/server/features/search/search-sources.js +142 -7
- package/dist/_internal/server/features/seo/robots.js +21 -1
- package/dist/_internal/server/features/seo/sitemap.js +1 -1
- package/dist/_internal/server/features/shared/listing-data-factory.js +16 -4
- package/dist/_internal/server/features/site-settings/adapters.d.ts +1 -1
- package/dist/_internal/server/features/site-settings/adapters.js +26 -0
- package/dist/_internal/server/features/sticker-trace/actions.d.ts +109 -0
- package/dist/_internal/server/features/sticker-trace/actions.js +172 -0
- package/dist/_internal/server/features/sticker-trace/adapters.d.ts +80 -0
- package/dist/_internal/server/features/sticker-trace/adapters.js +174 -0
- package/dist/_internal/server/features/sticker-trace/build-cut-file.d.ts +26 -0
- package/dist/_internal/server/features/sticker-trace/build-cut-file.js +127 -0
- package/dist/_internal/server/features/sticker-trace/coordinator.d.ts +27 -0
- package/dist/_internal/server/features/sticker-trace/coordinator.js +169 -0
- package/dist/_internal/server/features/sticker-trace/fanout.d.ts +43 -0
- package/dist/_internal/server/features/sticker-trace/fanout.js +180 -0
- package/dist/_internal/server/features/sticker-trace/finalizer.d.ts +25 -0
- package/dist/_internal/server/features/sticker-trace/finalizer.js +123 -0
- package/dist/_internal/server/features/sticker-trace/mosaic-inputs.d.ts +30 -0
- package/dist/_internal/server/features/sticker-trace/mosaic-inputs.js +112 -0
- package/dist/_internal/server/features/sticker-trace/progress.d.ts +81 -0
- package/dist/_internal/server/features/sticker-trace/progress.js +198 -0
- package/dist/_internal/server/features/sticker-trace/promote.d.ts +23 -0
- package/dist/_internal/server/features/sticker-trace/promote.js +193 -0
- package/dist/_internal/server/features/sticker-trace/shard.d.ts +50 -0
- package/dist/_internal/server/features/sticker-trace/shard.js +174 -0
- package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +141 -0
- package/dist/_internal/server/features/sticker-trace/sheet-actions.js +279 -0
- package/dist/_internal/server/features/sticker-trace/storage.d.ts +135 -0
- package/dist/_internal/server/features/sticker-trace/storage.js +282 -0
- package/dist/_internal/server/functions/scheduled.d.ts +2 -1
- package/dist/_internal/server/functions/scheduled.js +25 -1
- package/dist/_internal/server/jobs/core/_event-ref.d.ts +51 -0
- package/dist/_internal/server/jobs/core/_event-ref.js +63 -0
- package/dist/_internal/server/jobs/core/assignSpinPrize.d.ts +18 -0
- package/dist/_internal/server/jobs/core/assignSpinPrize.js +77 -16
- package/dist/_internal/server/jobs/core/auctionSettlement.js +13 -4
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +44 -15
- package/dist/_internal/server/jobs/core/bundleStockSync.js +3 -4
- package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +44 -0
- package/dist/_internal/server/jobs/core/event-draw-reasons.d.ts +78 -0
- package/dist/_internal/server/jobs/core/event-draw-reasons.js +133 -0
- package/dist/_internal/server/jobs/core/listingProcessor.js +28 -8
- package/dist/_internal/server/jobs/core/onOrderCreate.js +12 -1
- package/dist/_internal/server/jobs/core/onScamReportCreate.js +13 -2
- package/dist/_internal/server/jobs/core/onScamReportRejected.js +8 -2
- package/dist/_internal/server/jobs/core/onScamReportVerified.js +8 -2
- package/dist/_internal/server/jobs/core/onStoreWrite.js +11 -4
- package/dist/_internal/server/jobs/core/prizeDrawAssignWinner.js +5 -4
- package/dist/_internal/server/jobs/core/prizeDrawExpiryReveal.js +1 -4
- package/dist/_internal/server/jobs/core/prizeDrawSoldOutReveal.js +1 -2
- package/dist/_internal/server/jobs/core/promotions.js +7 -4
- package/dist/_internal/server/jobs/core/searchIndexBuild.d.ts +7 -0
- package/dist/_internal/server/jobs/core/searchIndexBuild.js +211 -0
- package/dist/_internal/server/jobs/core/triggerEventRaffle.d.ts +35 -0
- package/dist/_internal/server/jobs/core/triggerEventRaffle.js +213 -31
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +20 -14
- package/dist/_internal/server/jobs/handlers/assignSpinPrize.d.ts +8 -0
- package/dist/_internal/server/jobs/handlers/assignSpinPrize.js +15 -15
- package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
- package/dist/_internal/server/jobs/handlers/index.js +1 -0
- package/dist/_internal/server/jobs/handlers/onCategoryWrite.js +18 -0
- package/dist/_internal/server/jobs/handlers/onProductWrite.js +18 -0
- package/dist/_internal/server/jobs/handlers/onReviewWrite.js +18 -0
- package/dist/_internal/server/jobs/handlers/onScamReportUpdate.js +18 -0
- package/dist/_internal/server/jobs/handlers/onStoreWrite.js +18 -0
- package/dist/_internal/server/jobs/handlers/searchIndexBuild.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/searchIndexBuild.js +2 -0
- package/dist/_internal/server/jobs/handlers/triggerEventRaffle.d.ts +8 -0
- package/dist/_internal/server/jobs/handlers/triggerEventRaffle.js +15 -6
- package/dist/_internal/shared/actions/action-registry.js +29 -0
- package/dist/_internal/shared/cache/revalidate-targets.d.ts +0 -1
- package/dist/_internal/shared/cache/revalidate-targets.js +10 -8
- package/dist/_internal/shared/features/events/config.d.ts +14 -0
- package/dist/_internal/shared/features/events/config.js +14 -0
- package/dist/_internal/shared/features/notifications/action-url.js +8 -0
- package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
- package/dist/_internal/shared/features/sticker-trace/codec.d.ts +81 -0
- package/dist/_internal/shared/features/sticker-trace/codec.js +30 -0
- package/dist/_internal/shared/features/sticker-trace/config.d.ts +81 -0
- package/dist/_internal/shared/features/sticker-trace/config.js +177 -0
- package/dist/_internal/shared/features/sticker-trace/cut-contour.d.ts +20 -0
- package/dist/_internal/shared/features/sticker-trace/cut-contour.js +60 -0
- package/dist/_internal/shared/features/sticker-trace/export/build-export-set.d.ts +65 -0
- package/dist/_internal/shared/features/sticker-trace/export/build-export-set.js +176 -0
- package/dist/_internal/shared/features/sticker-trace/export/cut-svg.d.ts +56 -0
- package/dist/_internal/shared/features/sticker-trace/export/cut-svg.js +120 -0
- package/dist/_internal/shared/features/sticker-trace/export/machine-profiles.d.ts +92 -0
- package/dist/_internal/shared/features/sticker-trace/export/machine-profiles.js +153 -0
- package/dist/_internal/shared/features/sticker-trace/export/nesting.d.ts +51 -0
- package/dist/_internal/shared/features/sticker-trace/export/nesting.js +110 -0
- package/dist/_internal/shared/features/sticker-trace/export/page-sizes.d.ts +68 -0
- package/dist/_internal/shared/features/sticker-trace/export/page-sizes.js +223 -0
- package/dist/_internal/shared/features/sticker-trace/export/part-tiling.d.ts +51 -0
- package/dist/_internal/shared/features/sticker-trace/export/part-tiling.js +178 -0
- package/dist/_internal/shared/features/sticker-trace/export/simplify-budget.d.ts +26 -0
- package/dist/_internal/shared/features/sticker-trace/export/simplify-budget.js +134 -0
- package/dist/_internal/shared/features/sticker-trace/export/vectorise-art.d.ts +40 -0
- package/dist/_internal/shared/features/sticker-trace/export/vectorise-art.js +195 -0
- package/dist/_internal/shared/features/sticker-trace/index.d.ts +2 -0
- package/dist/_internal/shared/features/sticker-trace/index.js +59 -0
- package/dist/_internal/shared/features/sticker-trace/math/catmull-rom.d.ts +11 -0
- package/dist/_internal/shared/features/sticker-trace/math/catmull-rom.js +66 -0
- package/dist/_internal/shared/features/sticker-trace/math/edt.d.ts +27 -0
- package/dist/_internal/shared/features/sticker-trace/math/edt.js +165 -0
- package/dist/_internal/shared/features/sticker-trace/math/label.d.ts +15 -0
- package/dist/_internal/shared/features/sticker-trace/math/label.js +156 -0
- package/dist/_internal/shared/features/sticker-trace/math/marching-squares.d.ts +16 -0
- package/dist/_internal/shared/features/sticker-trace/math/marching-squares.js +242 -0
- package/dist/_internal/shared/features/sticker-trace/math/morphology.d.ts +46 -0
- package/dist/_internal/shared/features/sticker-trace/math/morphology.js +168 -0
- package/dist/_internal/shared/features/sticker-trace/math/rasterize-path.d.ts +88 -0
- package/dist/_internal/shared/features/sticker-trace/math/rasterize-path.js +286 -0
- package/dist/_internal/shared/features/sticker-trace/math/rdp.d.ts +10 -0
- package/dist/_internal/shared/features/sticker-trace/math/rdp.js +74 -0
- package/dist/_internal/shared/features/sticker-trace/resume.d.ts +50 -0
- package/dist/_internal/shared/features/sticker-trace/resume.js +160 -0
- package/dist/_internal/shared/features/sticker-trace/trace/cluster.d.ts +20 -0
- package/dist/_internal/shared/features/sticker-trace/trace/cluster.js +132 -0
- package/dist/_internal/shared/features/sticker-trace/trace/cross-profile.d.ts +28 -0
- package/dist/_internal/shared/features/sticker-trace/trace/cross-profile.js +120 -0
- package/dist/_internal/shared/features/sticker-trace/trace/flood.d.ts +21 -0
- package/dist/_internal/shared/features/sticker-trace/trace/flood.js +104 -0
- package/dist/_internal/shared/features/sticker-trace/trace/geometry.d.ts +3 -0
- package/dist/_internal/shared/features/sticker-trace/trace/geometry.js +140 -0
- package/dist/_internal/shared/features/sticker-trace/trace/line-filter.d.ts +15 -0
- package/dist/_internal/shared/features/sticker-trace/trace/line-filter.js +138 -0
- package/dist/_internal/shared/features/sticker-trace/trace/merge.d.ts +27 -0
- package/dist/_internal/shared/features/sticker-trace/trace/merge.js +187 -0
- package/dist/_internal/shared/features/sticker-trace/trace/paper.d.ts +32 -0
- package/dist/_internal/shared/features/sticker-trace/trace/paper.js +147 -0
- package/dist/_internal/shared/features/sticker-trace/trace/prefilter.d.ts +30 -0
- package/dist/_internal/shared/features/sticker-trace/trace/prefilter.js +125 -0
- package/dist/_internal/shared/features/sticker-trace/trace/quantise.d.ts +10 -0
- package/dist/_internal/shared/features/sticker-trace/trace/quantise.js +153 -0
- package/dist/_internal/shared/features/sticker-trace/trace/ridge.d.ts +88 -0
- package/dist/_internal/shared/features/sticker-trace/trace/ridge.js +344 -0
- package/dist/_internal/shared/features/sticker-trace/trace/segment.d.ts +10 -0
- package/dist/_internal/shared/features/sticker-trace/trace/segment.js +251 -0
- package/dist/_internal/shared/features/sticker-trace/types.d.ts +197 -0
- package/dist/_internal/shared/features/sticker-trace/types.js +49 -0
- package/dist/_internal/shared/listing-types/_registry.d.ts +11 -0
- package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/art/config.js +1 -0
- package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/auction/config.js +1 -0
- package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/classified/config.js +1 -0
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/digital-code/config.js +1 -0
- package/dist/_internal/shared/listing-types/feature-flags.d.ts +7 -0
- package/dist/_internal/shared/listing-types/feature-flags.js +9 -0
- package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/live/config.js +1 -0
- package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/pre-order/config.js +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.js +1 -0
- package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/standard/config.js +1 -0
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
- package/dist/_internal/shared/listing-types/stickers/config.js +1 -0
- package/dist/_internal/shared/media/limits.d.ts +12 -2
- package/dist/_internal/shared/media/limits.js +12 -2
- package/dist/_internal/shared/search/artifact-url.d.ts +35 -0
- package/dist/_internal/shared/search/artifact-url.js +119 -0
- package/dist/_internal/shared/search/index-record.d.ts +68 -0
- package/dist/_internal/shared/search/index-record.js +96 -0
- package/dist/_internal/shared/search/match.d.ts +65 -0
- package/dist/_internal/shared/search/match.js +263 -0
- package/dist/client.d.ts +8 -7
- package/dist/client.js +12 -5
- package/dist/configs/eslint.js +22 -2
- package/dist/constants/api-endpoints.d.ts +68 -0
- package/dist/constants/api-endpoints.js +32 -0
- package/dist/constants/field-names.d.ts +7 -1
- package/dist/constants/field-names.js +36 -1
- package/dist/contracts/repository.d.ts +8 -7
- package/dist/contracts/search.d.ts +2 -2
- package/dist/contracts/table.d.ts +3 -3
- package/dist/contracts/table.js +3 -3
- package/dist/core/contact-submissions.repository.js +2 -2
- package/dist/core/integration-keys.js +7 -1
- package/dist/core/newsletter.repository.js +2 -2
- package/dist/core/site-config.js +1 -1
- package/dist/errors/error-codes.d.ts +30 -0
- package/dist/errors/error-codes.js +30 -0
- package/dist/errors/error-display-map.js +40 -1
- package/dist/features/account/api/[userId]/addresses/route.js +1 -1
- package/dist/features/account/components/UserBidsView.js +1 -1
- package/dist/features/account/components/index.d.ts +0 -8
- package/dist/features/account/components/index.js +0 -4
- package/dist/features/addresses/repository/addresses.repository.d.ts +17 -6
- package/dist/features/addresses/repository/addresses.repository.js +65 -9
- package/dist/features/addresses/schemas/firestore.d.ts +17 -6
- package/dist/features/admin/actions/notification-actions.js +15 -6
- package/dist/features/admin/api/bids/route.js +1 -1
- package/dist/features/admin/api/coupons/route.js +1 -1
- package/dist/features/admin/api/products/route.js +1 -1
- package/dist/features/admin/api/reviews/route.js +1 -1
- package/dist/features/admin/components/AdminAdEditorView.js +19 -5
- package/dist/features/admin/components/AdminAuditLogView.js +1 -1
- package/dist/features/admin/components/AdminBlogEditorView.js +0 -1
- package/dist/features/admin/components/AdminBlogView.js +1 -1
- package/dist/features/admin/components/AdminBrandsView.js +17 -1
- package/dist/features/admin/components/AdminCategoryEditorView.js +0 -1
- package/dist/features/admin/components/AdminContactView.js +1 -1
- package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -3
- package/dist/features/admin/components/AdminNewsletterView.js +1 -1
- package/dist/features/admin/components/AdminOrdersView.js +9 -2
- package/dist/features/admin/components/AdminPayoutsView.js +1 -1
- package/dist/features/admin/components/AdminPrizeDrawsView.js +11 -0
- package/dist/features/admin/components/AdminProductEditorView.d.ts +10 -1
- package/dist/features/admin/components/AdminProductEditorView.js +24 -37
- package/dist/features/admin/components/AdminProductsView.js +10 -3
- package/dist/features/admin/components/AdminScammersView.js +1 -1
- package/dist/features/admin/components/AdminSectionsView.js +21 -5
- package/dist/features/admin/components/AdminSessionsView.js +1 -1
- package/dist/features/admin/components/AdminSublistingCategoriesView.js +22 -1
- package/dist/features/admin/components/AdminTeamView.js +1 -1
- package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +0 -1
- package/dist/features/admin/components/AdminUsersView.js +1 -1
- package/dist/features/admin/components/DataListingView.d.ts +2 -1
- package/dist/features/admin/components/DataListingView.js +9 -4
- package/dist/features/admin/components/analytics/AdminPageViewsReportView.js +0 -2
- package/dist/features/admin/hooks/useAdminListing.d.ts +1 -1
- package/dist/features/admin/repository/site-settings.repository.js +8 -3
- package/dist/features/admin/schemas/firestore.d.ts +62 -1
- package/dist/features/admin/schemas/firestore.js +32 -0
- package/dist/features/admin/types/index.d.ts +1 -1
- package/dist/features/auctions/actions/bid-actions.d.ts +2 -2
- package/dist/features/auctions/actions/bid-actions.js +16 -4
- package/dist/features/auctions/api/route.js +1 -1
- package/dist/features/auctions/components/AuctionBottomActions.js +4 -0
- package/dist/features/auctions/repository/bid.repository.d.ts +46 -4
- package/dist/features/auctions/repository/bid.repository.js +114 -13
- package/dist/features/auctions/schemas/firestore.d.ts +24 -4
- package/dist/features/auctions/schemas/firestore.js +1 -0
- package/dist/features/auth/actions/profile-actions.js +30 -4
- package/dist/features/auth/components/index.d.ts +0 -1
- package/dist/features/auth/components/index.js +0 -1
- package/dist/features/auth/repository/session.repository.d.ts +17 -3
- package/dist/features/auth/repository/session.repository.js +46 -5
- package/dist/features/auth/repository/token.repository.d.ts +27 -4
- package/dist/features/auth/repository/token.repository.js +65 -11
- package/dist/features/auth/repository/user.repository.d.ts +33 -7
- package/dist/features/auth/repository/user.repository.js +100 -15
- package/dist/features/auth/schemas/firestore.d.ts +63 -12
- package/dist/features/auth/schemas/firestore.js +11 -0
- package/dist/features/before-after/api/route.js +1 -1
- package/dist/features/blog/components/BlogListView.js +16 -3
- package/dist/features/blog/components/BlogPostView.js +1 -1
- package/dist/features/blog/schemas/index.d.ts +2 -2
- package/dist/features/cart/api/route.js +1 -1
- package/dist/features/catalogue/repository/catalogue.repository.d.ts +7 -7
- package/dist/features/catalogue/repository/catalogue.repository.js +28 -10
- package/dist/features/catalogue/schemas/firestore.d.ts +11 -0
- package/dist/features/categories/api/route.js +10 -10
- package/dist/features/categories/components/CategoryDetailPageView.js +35 -5
- package/dist/features/categories/components/CategorySelectorCreate.js +0 -1
- package/dist/features/categories/components/index.d.ts +0 -2
- package/dist/features/categories/components/index.js +0 -1
- package/dist/features/categories/repository/categories.repository.d.ts +1 -0
- package/dist/features/categories/repository/categories.repository.js +31 -1
- package/dist/features/categories/schemas/index.d.ts +2 -2
- package/dist/features/categories/utils/taxonomy-visual.d.ts +21 -0
- package/dist/features/categories/utils/taxonomy-visual.js +58 -0
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +8 -1
- package/dist/features/collections/api/[slug]/route.js +3 -3
- package/dist/features/collections/api/route.js +1 -1
- package/dist/features/consultation/api/route.js +1 -1
- package/dist/features/consultation/repository/consultations.repository.js +1 -1
- package/dist/features/consultation/types/index.d.ts +1 -1
- package/dist/features/contact/components/ContactForm.js +1 -3
- package/dist/features/corporate/api/route.js +1 -1
- package/dist/features/corporate/repository/corporate.repository.js +1 -1
- package/dist/features/corporate/types/index.d.ts +1 -1
- package/dist/features/cron/jobs/auction-expiry.job.js +1 -1
- package/dist/features/cron/jobs/preorder-reminder.job.js +1 -1
- package/dist/features/events/actions/event-actions.d.ts +14 -0
- package/dist/features/events/actions/event-actions.js +82 -3
- package/dist/features/events/api/[id]/route.js +2 -2
- package/dist/features/events/components/AdminEventEditorView.js +22 -3
- package/dist/features/events/components/AdminEventsView.js +32 -8
- package/dist/features/events/components/EventRafflesSection.d.ts +34 -1
- package/dist/features/events/components/EventRafflesSection.js +52 -3
- package/dist/features/events/components/SpinWheelView.d.ts +2 -2
- package/dist/features/events/components/SpinWheelView.js +41 -4
- package/dist/features/events/repository/event-entry.repository.d.ts +14 -2
- package/dist/features/events/repository/event-entry.repository.js +41 -7
- package/dist/features/events/schemas/firestore.d.ts +17 -4
- package/dist/features/events/types/index.d.ts +37 -0
- package/dist/features/faq/repository/faqs.repository.js +1 -1
- package/dist/features/faq/schemas/index.d.ts +5 -2
- package/dist/features/faq/schemas/index.js +6 -0
- package/dist/features/faq/types/index.d.ts +0 -1
- package/dist/features/grouped/components/GroupedListingEditorView.js +17 -2
- package/dist/features/homepage/api/carousel/[id]/route.js +1 -1
- package/dist/features/homepage/api/carousel/route.js +4 -4
- package/dist/features/homepage/api/route.js +2 -2
- package/dist/features/homepage/api/sections/route.js +1 -1
- package/dist/features/homepage/components/AnnouncementBar.d.ts +1 -9
- package/dist/features/homepage/components/AnnouncementBar.js +13 -19
- package/dist/features/homepage/components/MarketplaceHomepageView.js +6 -1
- package/dist/features/homepage/components/index.d.ts +0 -2
- package/dist/features/homepage/components/index.js +0 -1
- package/dist/features/homepage/repository/homepage.repository.js +1 -1
- package/dist/features/homepage/schemas/firestore.d.ts +6 -0
- package/dist/features/homepage/schemas/index.d.ts +10 -10
- package/dist/features/layout/AppLayoutShell.d.ts +12 -3
- package/dist/features/layout/AppLayoutShell.js +65 -13
- package/dist/features/layout/BottomActionsContext.d.ts +16 -0
- package/dist/features/layout/BottomActionsContext.js +5 -0
- package/dist/features/layout/BottomChrome.js +48 -9
- package/dist/features/layout/BottomNavbar.d.ts +14 -0
- package/dist/features/layout/BottomNavbar.js +43 -3
- package/dist/features/layout/MainNavbar.d.ts +11 -0
- package/dist/features/layout/NavbarLayout.d.ts +3 -0
- package/dist/features/layout/NavbarLayout.js +88 -11
- package/dist/features/layout/SideActionDock.d.ts +1 -0
- package/dist/features/layout/SideActionDock.js +219 -0
- package/dist/features/layout/TitleBarLayout.d.ts +1 -3
- package/dist/features/layout/TitleBarLayout.js +3 -4
- package/dist/features/layout/cta-anchor.d.ts +31 -0
- package/dist/features/layout/cta-anchor.js +31 -0
- package/dist/features/layout/hooks/useBottomActions.d.ts +7 -0
- package/dist/features/layout/hooks/useBottomActions.js +6 -1
- package/dist/features/layout/index.d.ts +9 -1
- package/dist/features/layout/index.js +9 -1
- package/dist/features/layout/useCtaReveal.d.ts +24 -0
- package/dist/features/layout/useCtaReveal.js +82 -0
- package/dist/features/layout/useHoldToOpen.d.ts +41 -0
- package/dist/features/layout/useHoldToOpen.js +84 -0
- package/dist/features/lottery/repository/lottery-entry.repository.d.ts +18 -3
- package/dist/features/lottery/repository/lottery-entry.repository.js +48 -6
- package/dist/features/lottery/schemas/firestore.d.ts +33 -5
- package/dist/features/loyalty/api/balance/route.js +1 -1
- package/dist/features/loyalty/api/history/route.js +1 -1
- package/dist/features/media/MediaImage.js +0 -1
- package/dist/features/media/MediaPickerModal.js +7 -1
- package/dist/features/media/modals/ImageEditor.js +5 -1
- package/dist/features/media/modals/VideoThumbnailSelector.js +17 -1
- package/dist/features/media/repository/media-assets.repository.d.ts +19 -0
- package/dist/features/media/upload/CameraCapture.js +16 -1
- package/dist/features/media/upload/ImageUpload.js +42 -4
- package/dist/features/media/upload/MediaUploadField.js +69 -13
- package/dist/features/media/upload/downscale-image.d.ts +56 -0
- package/dist/features/media/upload/downscale-image.js +150 -0
- package/dist/features/messages/components/ConversationThreadView.js +45 -2
- package/dist/features/messages/components/MessageSellerButton.d.ts +15 -1
- package/dist/features/messages/components/MessageSellerButton.js +10 -2
- package/dist/features/messages/schemas/firestore.d.ts +15 -0
- package/dist/features/orders/hooks/useOrders.js +4 -2
- package/dist/features/orders/repository/orders.repository.d.ts +15 -4
- package/dist/features/orders/repository/orders.repository.js +52 -20
- package/dist/features/orders/schemas/firestore.d.ts +15 -4
- package/dist/features/orders/schemas/index.d.ts +8 -8
- package/dist/features/orders/types/index.d.ts +2 -2
- package/dist/features/payments/repository/payments.repository.js +2 -2
- package/dist/features/payments/repository/payout.repository.d.ts +23 -6
- package/dist/features/payments/repository/payout.repository.js +63 -23
- package/dist/features/payments/repository/saved-payment-methods.repository.d.ts +17 -6
- package/dist/features/payments/repository/saved-payment-methods.repository.js +59 -11
- package/dist/features/payments/schemas/firestore.d.ts +14 -3
- package/dist/features/payments/schemas/saved-methods-firestore.d.ts +12 -1
- package/dist/features/pre-orders/api/[slug]/route.js +1 -1
- package/dist/features/pre-orders/api/admin/route.js +1 -1
- package/dist/features/pre-orders/api/route.js +1 -1
- package/dist/features/pre-orders/repository/pre-orders.repository.d.ts +3 -3
- package/dist/features/pre-orders/repository/pre-orders.repository.js +6 -6
- package/dist/features/products/api/[id]/route.js +1 -1
- package/dist/features/products/components/ListingBottomActions.js +4 -0
- package/dist/features/products/components/ProductDetailPageView.js +2 -1
- package/dist/features/products/components/ProductGalleryClient.js +2 -2
- package/dist/features/products/components/ProductGrid.js +12 -1
- package/dist/features/products/components/index.d.ts +0 -2
- package/dist/features/products/components/index.js +0 -1
- package/dist/features/products/config/listing-type-listing-config.d.ts +0 -3
- package/dist/features/products/config/listing-type-listing-config.js +27 -2
- package/dist/features/products/constants/listing-tabs.d.ts +9 -0
- package/dist/features/products/constants/listing-tabs.js +3 -2
- package/dist/features/products/hooks/useProducts.js +2 -2
- package/dist/features/products/repository/products.repository.js +13 -1
- package/dist/features/products/schemas/index.d.ts +2 -2
- package/dist/features/products/types/index.d.ts +1 -1
- package/dist/features/promotions/api/route.js +1 -1
- package/dist/features/reviews/actions/review-actions.d.ts +6 -6
- package/dist/features/reviews/actions/review-actions.js +22 -8
- package/dist/features/reviews/components/ReviewDetailPageView.js +13 -1
- package/dist/features/reviews/components/ReviewsIndexPageView.js +21 -4
- package/dist/features/reviews/repository/reviews.repository.d.ts +19 -7
- package/dist/features/reviews/repository/reviews.repository.js +63 -12
- package/dist/features/reviews/schemas/firestore.d.ts +13 -2
- package/dist/features/reviews/schemas/index.d.ts +2 -2
- package/dist/features/scams/actions/scam-actions.js +16 -4
- package/dist/features/search/components/SearchResultsPageView.js +2 -1
- package/dist/features/search/hooks/useSearchIndex.d.ts +34 -0
- package/dist/features/search/hooks/useSearchIndex.js +172 -0
- package/dist/features/search/repository/search.repository.js +2 -2
- package/dist/features/seller/actions/offer-actions.d.ts +5 -5
- package/dist/features/seller/actions/offer-actions.js +38 -8
- package/dist/features/seller/actions/seller-actions.js +34 -7
- package/dist/features/seller/api/coupons/route.js +1 -1
- package/dist/features/seller/api/products/route.js +1 -1
- package/dist/features/seller/api/store/route.js +1 -1
- package/dist/features/seller/components/SellerBidsView.js +1 -1
- package/dist/features/seller/components/SellerCouponsView.js +1 -1
- package/dist/features/seller/components/SellerListingTypeView.js +9 -1
- package/dist/features/seller/components/SellerOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +0 -1
- package/dist/features/seller/components/SellerPayoutsView.js +1 -1
- package/dist/features/seller/components/SellerProductShell.js +0 -1
- package/dist/features/seller/components/SellerProductsView.js +1 -1
- package/dist/features/seller/components/SellerShippingView.js +0 -1
- package/dist/features/seller/components/SellerStorefrontView.js +0 -1
- package/dist/features/seller/components/index.d.ts +0 -4
- package/dist/features/seller/components/index.js +0 -2
- package/dist/features/seller/repository/offer.repository.d.ts +15 -3
- package/dist/features/seller/repository/offer.repository.js +43 -7
- package/dist/features/seller/schemas/firestore.d.ts +14 -3
- package/dist/features/seller/schemas/index.d.ts +4 -4
- package/dist/features/seller/schemas/order-forms.d.ts +39 -0
- package/dist/features/seller/schemas/order-forms.js +37 -0
- package/dist/features/shell/FormShell.js +6 -2
- package/dist/features/shell/QuickFormDrawer.js +15 -1
- package/dist/features/shipments/components/AdminShipmentEditorView.js +0 -1
- package/dist/features/shipments/components/AdminShipmentsView.js +1 -1
- package/dist/features/sticker-trace/components/StickerCommitPanel.d.ts +30 -0
- package/dist/features/sticker-trace/components/StickerCommitPanel.js +93 -0
- package/dist/features/sticker-trace/components/StickerPrintPanel.d.ts +33 -0
- package/dist/features/sticker-trace/components/StickerPrintPanel.js +104 -0
- package/dist/features/sticker-trace/components/StickerRetryPanel.d.ts +20 -0
- package/dist/features/sticker-trace/components/StickerRetryPanel.js +128 -0
- package/dist/features/sticker-trace/components/StickerRunHistoryPanel.d.ts +45 -0
- package/dist/features/sticker-trace/components/StickerRunHistoryPanel.js +84 -0
- package/dist/features/sticker-trace/components/StickerTraceStudio.d.ts +27 -0
- package/dist/features/sticker-trace/components/StickerTraceStudio.js +171 -0
- package/dist/features/sticker-trace/constants/help-content.d.ts +23 -0
- package/dist/features/sticker-trace/constants/help-content.js +172 -0
- package/dist/features/sticker-trace/hooks/useLiveTrace.d.ts +27 -0
- package/dist/features/sticker-trace/hooks/useLiveTrace.js +160 -0
- package/dist/features/sticker-trace/hooks/useStickerTraceProgress.d.ts +22 -0
- package/dist/features/sticker-trace/hooks/useStickerTraceProgress.js +106 -0
- package/dist/features/sticker-trace/repository/sticker-sheets.repository.d.ts +113 -0
- package/dist/features/sticker-trace/repository/sticker-sheets.repository.js +146 -0
- package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.d.ts +132 -0
- package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.js +174 -0
- package/dist/features/sticker-trace/schemas/firestore.d.ts +248 -0
- package/dist/features/sticker-trace/schemas/firestore.js +79 -0
- package/dist/features/sticker-trace/server.d.ts +8 -0
- package/dist/features/sticker-trace/server.js +51 -0
- package/dist/features/stores/actions/store-query-actions.d.ts +2 -2
- package/dist/features/stores/actions/store-query-actions.js +7 -2
- package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -3
- package/dist/features/stores/api/[storeSlug]/products/route.js +3 -3
- package/dist/features/stores/api/[storeSlug]/reviews/route.js +1 -1
- package/dist/features/stores/api/[storeSlug]/route.js +1 -1
- package/dist/features/stores/components/StoreNavTabs.js +17 -2
- package/dist/features/stores/manifest.js +8 -4
- package/dist/features/support/repository/support.repository.d.ts +14 -3
- package/dist/features/support/repository/support.repository.js +93 -13
- package/dist/features/support/schemas/firestore.d.ts +16 -5
- package/dist/features/tester/seed-data/authored/admin__events-raffles-spin.js +61 -19
- package/dist/features/tester/seed-data/authored/buying__browsing-search.js +19 -3
- package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +243 -0
- package/dist/features/tester/seed-data/authored/content-discovery__events.js +36 -10
- package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.js +209 -0
- package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.js +90 -0
- package/dist/features/tester/seed-data/authored/design-ux__header-controls-and-messages.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/design-ux__header-controls-and-messages.js +85 -0
- package/dist/features/tester/seed-data/authored/index.js +10 -0
- package/dist/features/tester/seed-data/authored/selling__media-limits.js +19 -17
- package/dist/features/tester/seed-data/authored/selling__product-upload-details.js +10 -5
- package/dist/features/tester/seed-data/authored/tools__sticker-tracer.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +283 -0
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +235 -22
- package/dist/index.d.ts +10 -23
- package/dist/index.js +27 -19
- package/dist/next/api/routeHandler.js +9 -0
- package/dist/next/routing/require-record.d.ts +13 -0
- package/dist/next/routing/require-record.js +62 -0
- package/dist/next/routing/route-map.d.ts +4 -4
- package/dist/next/routing/route-map.js +25 -3
- package/dist/providers/db-firebase/base.d.ts +4 -2
- package/dist/providers/db-firebase/base.js +21 -5
- package/dist/providers/db-firebase/base.repository.d.ts +11 -9
- package/dist/providers/db-firebase/base.repository.js +19 -0
- package/dist/providers/db-firebase/rtdb-paths.d.ts +12 -0
- package/dist/providers/db-firebase/rtdb-paths.js +12 -0
- package/dist/react/ErrorBoundary.js +6 -1
- package/dist/react/hooks/realtime-event-constants.d.ts +1 -0
- package/dist/react/hooks/realtime-event-constants.js +8 -0
- package/dist/react/hooks/useEntityDelete.js +5 -1
- package/dist/react/hooks/useMessage.js +5 -1
- package/dist/repositories/index.d.ts +2 -2
- package/dist/repositories/index.js +6 -1
- package/dist/schemas/registry.d.ts +13 -20
- package/dist/schemas/registry.js +31 -14
- package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
- package/dist/security/encrypted.d.ts +117 -0
- package/dist/security/encrypted.js +100 -0
- package/dist/security/index.d.ts +5 -2
- package/dist/security/index.js +16 -2
- package/dist/security/pii-accessors.d.ts +71 -0
- package/dist/security/pii-accessors.js +150 -0
- package/dist/security/pii-encrypt.d.ts +0 -8
- package/dist/security/pii-encrypt.js +22 -15
- package/dist/security/pii-mask.d.ts +18 -0
- package/dist/security/pii-mask.js +27 -0
- package/dist/seed/_helpers/search-txt-wrappers.d.ts +6 -6
- package/dist/seed/_helpers/search-txt-wrappers.js +22 -0
- package/dist/seed/addresses-seed-data.d.ts +2 -2
- package/dist/seed/authenticity-knowledge-seed-data.d.ts +34 -0
- package/dist/seed/authenticity-knowledge-seed-data.js +1277 -0
- package/dist/seed/bids-seed-data.d.ts +2 -2
- package/dist/seed/bids-seed-data.js +23 -2
- package/dist/seed/events-seed-data.d.ts +2 -2
- package/dist/seed/events-seed-data.js +5 -0
- package/dist/seed/faq-seed-data.js +175 -5
- package/dist/seed/homepage-sections-seed-data.js +39 -23
- package/dist/seed/index.d.ts +1 -0
- package/dist/seed/index.js +1 -0
- package/dist/seed/lottery-entries-seed-data.d.ts +2 -2
- package/dist/seed/offers-seed-data.d.ts +2 -2
- package/dist/seed/offers-seed-data.js +1 -1
- package/dist/seed/orders-seed-data.d.ts +2 -2
- package/dist/seed/payouts-seed-data.d.ts +2 -2
- package/dist/seed/payouts-seed-data.js +1 -1
- package/dist/seed/reviews-seed-data.d.ts +1 -2
- package/dist/seed/seed-purpose.js +7 -0
- package/dist/seed/sessions-seed-data.d.ts +2 -2
- package/dist/seed/sessions-seed-data.js +5 -0
- package/dist/seed/site-settings-seed-data.js +1 -1
- package/dist/seed/support-tickets-seed-data.d.ts +2 -2
- package/dist/seed/support-tickets-seed-data.js +1 -1
- package/dist/seed/users-seed-data.d.ts +2 -2
- package/dist/seed/users-seed-data.js +1 -1
- package/dist/seo/json-ld.js +5 -1
- package/dist/server.d.ts +18 -3
- package/dist/server.js +59 -3
- package/dist/styles.css +237 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/Button.js +7 -1
- package/dist/ui/components/FilterChipGroup.d.ts +11 -0
- package/dist/ui/components/FilterChipGroup.js +1 -1
- package/dist/ui/components/ImageGallery.js +6 -1
- package/dist/ui/components/ListingLayout.js +14 -8
- package/dist/ui/components/OverflowRow.d.ts +92 -0
- package/dist/ui/components/OverflowRow.js +203 -0
- package/dist/ui/components/OverflowRow.style.css +235 -0
- package/dist/ui/components/RecordDetailModal.js +14 -1
- package/dist/ui/components/RowActionMenu.js +5 -1
- package/dist/ui/components/SideDrawer.js +5 -1
- package/dist/ui/components/SideModal.js +9 -1
- package/dist/ui/components/TabBarShell.d.ts +12 -1
- package/dist/ui/components/TabBarShell.js +3 -2
- package/dist/ui/components/Tabs.js +36 -24
- package/dist/ui/components/Toast.d.ts +3 -24
- package/dist/ui/components/Toast.js +2 -19
- package/dist/ui/components/TopBannerPortal.d.ts +15 -0
- package/dist/ui/components/TopBannerPortal.js +19 -0
- package/dist/ui/components/UnsavedChangesModal.js +5 -1
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/components/row-collapse.d.ts +15 -0
- package/dist/ui/components/row-collapse.js +127 -0
- package/dist/ui/components/toast-context.d.ts +63 -0
- package/dist/ui/components/toast-context.js +48 -0
- package/dist/ui/components/top-banner-slot.d.ts +37 -0
- package/dist/ui/components/top-banner-slot.js +45 -0
- package/dist/ui/icons/icon-registry.d.ts +6 -0
- package/dist/ui/icons/icon-registry.js +17 -1
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +1 -0
- package/dist/utils/array.helper.d.ts +2 -2
- package/dist/utils/array.helper.js +5 -5
- package/dist/utils/id-generators.d.ts +6 -0
- package/dist/utils/id-generators.js +10 -0
- package/dist/utils/media-url.js +0 -2
- package/dist/utils/search-txt-builders.d.ts +28 -4
- package/dist/utils/search-txt-builders.js +41 -1
- package/dist/validation/schemas.d.ts +8 -8
- package/package.json +6 -2
- package/scripts/seed-cli.mjs +3 -0
- package/dist/features/account/components/UserAddressesView.d.ts +0 -13
- package/dist/features/account/components/UserAddressesView.js +0 -5
- package/dist/features/account/components/UserNotificationsView.d.ts +0 -15
- package/dist/features/account/components/UserNotificationsView.js +0 -12
- package/dist/features/account/components/UserSettingsView.d.ts +0 -16
- package/dist/features/account/components/UserSettingsView.js +0 -13
- package/dist/features/account/components/UserSupportView.d.ts +0 -3
- package/dist/features/account/components/UserSupportView.js +0 -166
- package/dist/features/admin/components/DemoSeedView.d.ts +0 -11
- package/dist/features/admin/components/DemoSeedView.js +0 -5
- package/dist/features/auth/components/AuthStatusPanel.d.ts +0 -10
- package/dist/features/auth/components/AuthStatusPanel.js +0 -22
- package/dist/features/categories/components/CategoryProductsView.d.ts +0 -45
- package/dist/features/categories/components/CategoryProductsView.js +0 -21
- package/dist/features/homepage/components/HowItWorksInfoView.d.ts +0 -36
- package/dist/features/homepage/components/HowItWorksInfoView.js +0 -10
- package/dist/features/layout/BottomActions.d.ts +0 -1
- package/dist/features/layout/BottomActions.js +0 -311
- package/dist/features/products/components/ProductsView.d.ts +0 -6
- package/dist/features/products/components/ProductsView.js +0 -5
- package/dist/features/seller/components/SellerStoreView.d.ts +0 -8
- package/dist/features/seller/components/SellerStoreView.js +0 -8
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* downscaleImageFile — bound an image's pixel dimensions and re-encode it
|
|
3
|
+
* before it ever leaves the browser.
|
|
4
|
+
*
|
|
5
|
+
* ## Why this exists
|
|
6
|
+
*
|
|
7
|
+
* Until 2026-10-19 the ONLY client-side resize in the whole upload path was
|
|
8
|
+
* inside `ImageEditor` (`modals/ImageEditor.tsx`), which runs only when the
|
|
9
|
+
* user opens the crop editor. Everything else stored the original bytes: a 9 MB
|
|
10
|
+
* phone photo was stored at 9 MB, watermarked at 9 MB, and served at 9 MB into
|
|
11
|
+
* a 64px thumbnail, because `/api/media/[...slug]` resizes nothing and
|
|
12
|
+
* `next/image` optimisation was off.
|
|
13
|
+
*
|
|
14
|
+
* That is the shape of the cost that suspended this project with HTTP 402 for
|
|
15
|
+
* Fast Origin Transfer at 5.25x its cap (Root Cause #104). Bounding the master
|
|
16
|
+
* at upload is the one fix that helps every downstream consumer at once.
|
|
17
|
+
*
|
|
18
|
+
* ## Why 2048
|
|
19
|
+
*
|
|
20
|
+
* Measured (docs/research/competitor-crawl-2026-10/images.md): worldhobbyshop
|
|
21
|
+
* serves a 2048x2048 master to photoswipe for zoom, and WordPress's own
|
|
22
|
+
* `-scaled` threshold is 2560. 2048 survives our lightbox's 300% zoom over a
|
|
23
|
+
* ~680px display box with detail to spare, and is 1/4 the pixels of a 4096px
|
|
24
|
+
* phone capture.
|
|
25
|
+
*
|
|
26
|
+
* ## Four cases where it deliberately returns the ORIGINAL file
|
|
27
|
+
*
|
|
28
|
+
* 1. **Not a raster image we own the pipeline for** — anything outside
|
|
29
|
+
* `CONVERTIBLE_MIMES`. SVG is never rasterised (it is also not in
|
|
30
|
+
* `ALLOWED_IMAGE_MIMES`), and GIF is never touched because re-encoding an
|
|
31
|
+
* animated GIF to a still WebP silently destroys the animation.
|
|
32
|
+
* 2. **Already small enough AND already a compact format** — re-encoding a
|
|
33
|
+
* 1200px WebP buys nothing and loses a generation of quality.
|
|
34
|
+
* 3. **The re-encode came out BIGGER.** A small, already-optimised JPEG can
|
|
35
|
+
* grow under WebP q0.9. Shipping the larger file would make this helper a
|
|
36
|
+
* pessimisation, so the original wins.
|
|
37
|
+
* 4. **Anything threw.** 🛑 Fail OPEN. A canvas decode failure, a tainted
|
|
38
|
+
* canvas, a browser without `createImageBitmap` — none of those are a reason
|
|
39
|
+
* to block a seller's upload. The server still enforces `MAX_BYTES[kind]`,
|
|
40
|
+
* so the worst case is the pre-2026-10-19 behaviour, not a hole.
|
|
41
|
+
*/
|
|
42
|
+
import { normalizeError } from "../../../errors/normalize.js";
|
|
43
|
+
/** Longest edge, in CSS pixels, of the stored master. */
|
|
44
|
+
export const IMAGE_DOWNSCALE_MAX_EDGE = 2048;
|
|
45
|
+
/** Output MIME for a re-encoded master. */
|
|
46
|
+
export const IMAGE_DOWNSCALE_FORMAT = "image/webp";
|
|
47
|
+
/** Output quality for a re-encoded master. */
|
|
48
|
+
export const IMAGE_DOWNSCALE_QUALITY = 0.9;
|
|
49
|
+
/**
|
|
50
|
+
* MIMEs this helper is willing to decode and re-encode.
|
|
51
|
+
*
|
|
52
|
+
* 🛑 Deliberately NOT derived from `ALLOWED_IMAGE_MIMES` — that list is about
|
|
53
|
+
* what the server will STORE, this one is about what a canvas may safely
|
|
54
|
+
* round-trip. `image/gif` is in the first and must stay out of the second
|
|
55
|
+
* (animation loss), and the two lists answering different questions is exactly
|
|
56
|
+
* why one must not be spelled in terms of the other.
|
|
57
|
+
*/
|
|
58
|
+
const CONVERTIBLE_MIMES = new Set(["image/jpeg", "image/jpg", "image/png", "image/webp"]);
|
|
59
|
+
/** Formats already compact enough that a same-size re-encode is pointless. */
|
|
60
|
+
const ALREADY_COMPACT = new Set(["image/webp", "image/avif"]);
|
|
61
|
+
function replaceExtension(name, mime) {
|
|
62
|
+
const ext = mime.split("/")[1] || "webp";
|
|
63
|
+
const dot = name.lastIndexOf(".");
|
|
64
|
+
const stem = dot > 0 ? name.slice(0, dot) : name;
|
|
65
|
+
return `${stem}.${ext}`;
|
|
66
|
+
}
|
|
67
|
+
async function decode(file) {
|
|
68
|
+
if (typeof createImageBitmap === "function") {
|
|
69
|
+
const bitmap = await createImageBitmap(file);
|
|
70
|
+
return { width: bitmap.width, height: bitmap.height, source: bitmap, release: () => bitmap.close() };
|
|
71
|
+
}
|
|
72
|
+
const url = URL.createObjectURL(file);
|
|
73
|
+
try {
|
|
74
|
+
const img = await new Promise((resolve, reject) => {
|
|
75
|
+
const el = new Image();
|
|
76
|
+
el.onload = () => resolve(el);
|
|
77
|
+
el.onerror = () => reject(new Error("image decode failed"));
|
|
78
|
+
el.src = url;
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
width: img.naturalWidth,
|
|
82
|
+
height: img.naturalHeight,
|
|
83
|
+
source: img,
|
|
84
|
+
release: () => URL.revokeObjectURL(url),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
URL.revokeObjectURL(url);
|
|
89
|
+
throw err;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export async function downscaleImageFile(file, options = {}) {
|
|
93
|
+
const maxEdge = options.maxEdge ?? IMAGE_DOWNSCALE_MAX_EDGE;
|
|
94
|
+
const format = options.format ?? IMAGE_DOWNSCALE_FORMAT;
|
|
95
|
+
const quality = options.quality ?? IMAGE_DOWNSCALE_QUALITY;
|
|
96
|
+
// Case 1 — not something we are willing to round-trip through a canvas.
|
|
97
|
+
if (!CONVERTIBLE_MIMES.has(file.type))
|
|
98
|
+
return file;
|
|
99
|
+
let decoded = null;
|
|
100
|
+
try {
|
|
101
|
+
decoded = await decode(file);
|
|
102
|
+
const { width, height, source } = decoded;
|
|
103
|
+
if (!width || !height)
|
|
104
|
+
return file;
|
|
105
|
+
const longest = Math.max(width, height);
|
|
106
|
+
const scale = longest > maxEdge ? maxEdge / longest : 1;
|
|
107
|
+
// Case 2 — small enough already, and re-encoding would only lose a generation.
|
|
108
|
+
if (scale === 1 && ALREADY_COMPACT.has(file.type))
|
|
109
|
+
return file;
|
|
110
|
+
const targetW = Math.max(1, Math.round(width * scale));
|
|
111
|
+
const targetH = Math.max(1, Math.round(height * scale));
|
|
112
|
+
const canvas = document.createElement("canvas");
|
|
113
|
+
canvas.width = targetW;
|
|
114
|
+
canvas.height = targetH;
|
|
115
|
+
const ctx = canvas.getContext("2d");
|
|
116
|
+
if (!ctx)
|
|
117
|
+
return file;
|
|
118
|
+
ctx.imageSmoothingQuality = "high";
|
|
119
|
+
ctx.drawImage(source, 0, 0, targetW, targetH);
|
|
120
|
+
const blob = await new Promise((resolve) => canvas.toBlob(resolve, format, quality));
|
|
121
|
+
if (!blob || blob.size === 0)
|
|
122
|
+
return file;
|
|
123
|
+
// Case 3 — the re-encode is bigger than what we started with.
|
|
124
|
+
if (blob.size >= file.size && scale === 1)
|
|
125
|
+
return file;
|
|
126
|
+
return new File([blob], replaceExtension(file.name, format), {
|
|
127
|
+
type: format,
|
|
128
|
+
lastModified: file.lastModified,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
void normalizeError(err);
|
|
133
|
+
/*
|
|
134
|
+
* Case 4 — fail open. See the header.
|
|
135
|
+
*
|
|
136
|
+
* Reported rather than swallowed silently: `normalizeError` fires the
|
|
137
|
+
* observability hook, so a browser that cannot decode what it just accepted
|
|
138
|
+
* is visible instead of merely producing a suspiciously large upload. The
|
|
139
|
+
* upload itself still proceeds, with the original file.
|
|
140
|
+
*
|
|
141
|
+
* 🛑 The call sits on the line directly below the `catch` on purpose —
|
|
142
|
+
* `audit-catch-normalize` only looks a few lines ahead, so putting this
|
|
143
|
+
* comment first was enough to make it read as an unnormalised catch.
|
|
144
|
+
*/
|
|
145
|
+
return file;
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
decoded?.release();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
import { useSearchParams } from "next/navigation.js";
|
|
4
5
|
import { useAuth } from "../../../react/contexts/SessionContext.js";
|
|
5
6
|
import { useConversationThread, useSendMessage, useMarkConversationRead, useBlockConversation, } from "../hooks/useMessages.js";
|
|
6
7
|
import { Div } from "../../../ui/components/Div.js";
|
|
@@ -10,6 +11,10 @@ import { Button } from "../../../ui/components/Button.js";
|
|
|
10
11
|
import { FieldTextarea } from "../../../ui/forms/FieldTextarea.js";
|
|
11
12
|
import { EmptyState } from "../../../ui/components/EmptyState.js";
|
|
12
13
|
import { MediaImage } from "../../media/MediaImage.js";
|
|
14
|
+
import { TextLink } from "../../../ui/components/TextLink.js";
|
|
15
|
+
import { pluginFor } from "../../../_internal/shared/listing-types/_registry.js";
|
|
16
|
+
import { isListingType } from "../../../_internal/shared/listing-types/feature-flags.js";
|
|
17
|
+
import { formatCurrency } from "../../../utils/number.formatter.js";
|
|
13
18
|
function newClientMessageId() {
|
|
14
19
|
// crypto.randomUUID is available in every browser this app targets; a
|
|
15
20
|
// retry reuses the SAME id generated at compose time, not a fresh one per
|
|
@@ -22,7 +27,32 @@ function MessageBubble({ message, isSelf }) {
|
|
|
22
27
|
if (message.deletedAt) {
|
|
23
28
|
return (_jsx(Row, { justify: isSelf ? "end" : "start", children: _jsx(Text, { size: "sm", color: "muted", className: "italic", children: "Message deleted" }) }));
|
|
24
29
|
}
|
|
25
|
-
return (_jsx(Row, { justify: isSelf ? "end" : "start", children: _jsxs(Stack, { gap: "xs", surface: isSelf ? "interactive" : "muted", padding: "sm", rounded: "lg", className: "max-w-[75%]", children: [message.productRef && (
|
|
30
|
+
return (_jsx(Row, { justify: isSelf ? "end" : "start", children: _jsxs(Stack, { gap: "xs", surface: isSelf ? "interactive" : "muted", padding: "sm", rounded: "lg", className: "max-w-[75%]", children: [message.productRef && (
|
|
31
|
+
/*
|
|
32
|
+
* A LINK, and it shows the price.
|
|
33
|
+
*
|
|
34
|
+
* `MessageProductRef` captures `price` and this block ignored it —
|
|
35
|
+
* a declared field with no reader (Root Cause #51's shape) — and the
|
|
36
|
+
* card was not clickable, so the one thing a buyer and seller both
|
|
37
|
+
* want from it (open the item) was missing. The snapshot is taken at
|
|
38
|
+
* send time on purpose, so it keeps reading correctly after the
|
|
39
|
+
* listing changes or is deleted.
|
|
40
|
+
*
|
|
41
|
+
* No `GatedPrice` here: chat requires auth, so there is no signed-out
|
|
42
|
+
* viewer to gate, and the price shown is the one the buyer was
|
|
43
|
+
* looking at when they asked.
|
|
44
|
+
*/
|
|
45
|
+
_jsx(TextLink, { variant: "inherit", href: String(
|
|
46
|
+
/*
|
|
47
|
+
* Narrowed, not cast. The snapshot stores `listingType` as a
|
|
48
|
+
* plain `string` (a message written before the field existed has
|
|
49
|
+
* none), and anything unrecognised falls back to the `standard`
|
|
50
|
+
* route — the correct reading for those older rows and for a type
|
|
51
|
+
* that has since been removed.
|
|
52
|
+
*/
|
|
53
|
+
pluginFor(isListingType(message.productRef.listingType)
|
|
54
|
+
? message.productRef.listingType
|
|
55
|
+
: "standard").detailRoute(message.productRef.productId)), layout: "flex-col", rounded: "md", children: _jsxs(Row, { gap: "sm", surface: "card", padding: "xs", rounded: "md", align: "center", children: [message.productRef.image && (_jsx(Div, { className: "relative h-10 w-10 flex-shrink-0", rounded: "default", overflow: "hidden", children: _jsx(MediaImage, { src: message.productRef.image, alt: message.productRef.title, size: "thumbnail" }) })), _jsxs(Stack, { gap: "none", className: "min-w-0", children: [_jsx(Text, { size: "xs", weight: "semibold", className: "truncate", children: message.productRef.title }), typeof message.productRef.price === "number" && (_jsx(Text, { size: "xs", color: "muted", children: formatCurrency(message.productRef.price, "INR") }))] })] }) })), _jsx(Text, { size: "sm", className: "whitespace-pre-wrap break-words", children: message.body })] }) }));
|
|
26
56
|
}
|
|
27
57
|
export function ConversationThreadView({ conversationId }) {
|
|
28
58
|
const { user, loading } = useAuth();
|
|
@@ -31,6 +61,17 @@ export function ConversationThreadView({ conversationId }) {
|
|
|
31
61
|
const markRead = useMarkConversationRead();
|
|
32
62
|
const block = useBlockConversation();
|
|
33
63
|
const [draft, setDraft] = useState("");
|
|
64
|
+
/*
|
|
65
|
+
* The listing the buyer arrived from, attached to the NEXT message and then
|
|
66
|
+
* cleared — so the card appears once, on the message that asked about it,
|
|
67
|
+
* rather than on every subsequent reply in the thread.
|
|
68
|
+
*
|
|
69
|
+
* Read from `?product=` rather than held on the conversation because the
|
|
70
|
+
* schema is explicit that a product belongs to a message: one thread per
|
|
71
|
+
* pair of people, however many items they discuss.
|
|
72
|
+
*/
|
|
73
|
+
const searchParams = useSearchParams();
|
|
74
|
+
const [attachedProductId, setAttachedProductId] = useState(() => searchParams.get("product") ?? undefined);
|
|
34
75
|
const markedRef = useRef(false);
|
|
35
76
|
const bottomRef = useRef(null);
|
|
36
77
|
useEffect(() => {
|
|
@@ -57,8 +98,10 @@ export function ConversationThreadView({ conversationId }) {
|
|
|
57
98
|
if (!trimmed)
|
|
58
99
|
return;
|
|
59
100
|
const clientMessageId = newClientMessageId();
|
|
60
|
-
send({ body: trimmed, clientMessageId });
|
|
101
|
+
send({ body: trimmed, clientMessageId, productId: attachedProductId });
|
|
61
102
|
setDraft("");
|
|
103
|
+
// Once attached, it is spent — the next message is a plain reply.
|
|
104
|
+
setAttachedProductId(undefined);
|
|
62
105
|
};
|
|
63
106
|
// Newest-first from the API, so reverse for display (oldest at top).
|
|
64
107
|
const items = data ? [...data.items].reverse() : [];
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
export interface MessageSellerButtonProps {
|
|
2
2
|
storeId: string;
|
|
3
|
+
/**
|
|
4
|
+
* The listing this button was clicked from, carried into the thread so the
|
|
5
|
+
* buyer's first message renders as a PRODUCT CARD.
|
|
6
|
+
*
|
|
7
|
+
* 🛑 Without it the whole card pipeline is unreachable. `sendMessage` builds
|
|
8
|
+
* a `MessageProductRef` from a `productId`, `MessageBubble` renders it, and
|
|
9
|
+
* `POST /api/messages/[conversationId]` accepts it — but the ONLY caller of
|
|
10
|
+
* this button is the product detail page, which had the id right there and
|
|
11
|
+
* never passed it. So a buyer landed in a bare thread and had to TYPE which
|
|
12
|
+
* item they meant: a block of words where a card belongs. Root Cause #103's
|
|
13
|
+
* shape — a feature complete in every direction except the one that puts
|
|
14
|
+
* data in.
|
|
15
|
+
*/
|
|
16
|
+
productId?: string;
|
|
3
17
|
/** Render nothing when the viewer owns this store — comparing storeId
|
|
4
18
|
* client-side is an optional convenience; the server refuses it either way. */
|
|
5
19
|
isOwnStore?: boolean;
|
|
@@ -14,4 +28,4 @@ export interface MessageSellerButtonProps {
|
|
|
14
28
|
* Absent entirely when chat is off or the viewer is the store's own owner —
|
|
15
29
|
* never rendered-but-disabled, same discipline as the nav icon.
|
|
16
30
|
*/
|
|
17
|
-
export declare function MessageSellerButton({ storeId, isOwnStore, className }: MessageSellerButtonProps): import("react").JSX.Element | null;
|
|
31
|
+
export declare function MessageSellerButton({ storeId, productId, isOwnStore, className }: MessageSellerButtonProps): import("react").JSX.Element | null;
|
|
@@ -16,7 +16,7 @@ import { ACTIONS } from "../../../_internal/shared/actions/action-registry.js";
|
|
|
16
16
|
* Absent entirely when chat is off or the viewer is the store's own owner —
|
|
17
17
|
* never rendered-but-disabled, same discipline as the nav icon.
|
|
18
18
|
*/
|
|
19
|
-
export function MessageSellerButton({ storeId, isOwnStore, className }) {
|
|
19
|
+
export function MessageSellerButton({ storeId, productId, isOwnStore, className }) {
|
|
20
20
|
const router = useRouter();
|
|
21
21
|
const { user } = useAuth();
|
|
22
22
|
const { data: settings } = useSiteSettings();
|
|
@@ -26,7 +26,15 @@ export function MessageSellerButton({ storeId, isOwnStore, className }) {
|
|
|
26
26
|
return (_jsx(Button, { action: ACTIONS.PRODUCT["message-seller"], size: "sm", isLoading: isPending, className: className, onClick: () => {
|
|
27
27
|
mutate({ storeId }, {
|
|
28
28
|
onSuccess: (conversation) => {
|
|
29
|
-
|
|
29
|
+
/*
|
|
30
|
+
* `?product=` rather than a new conversation per listing. The
|
|
31
|
+
* schema is explicit that a product attaches to a MESSAGE, never
|
|
32
|
+
* to the thread — "a buyer with three questions about three items
|
|
33
|
+
* wants one thread, not three" — so the id rides in the URL and
|
|
34
|
+
* the composer attaches it to the next message sent.
|
|
35
|
+
*/
|
|
36
|
+
const href = String(ROUTES.USER.MESSAGE_THREAD(conversation.id));
|
|
37
|
+
router.push(productId ? `${href}?product=${encodeURIComponent(productId)}` : href);
|
|
30
38
|
},
|
|
31
39
|
});
|
|
32
40
|
} }));
|
|
@@ -44,6 +44,21 @@ export interface MessageProductRef {
|
|
|
44
44
|
productId: string;
|
|
45
45
|
title: string;
|
|
46
46
|
image?: string;
|
|
47
|
+
/**
|
|
48
|
+
* 🛑 Required for the card to LINK anywhere correct.
|
|
49
|
+
*
|
|
50
|
+
* Nine listing types have five different detail routes
|
|
51
|
+
* (`/auctions/…`, `/pre-orders/…`, `/prize-draws/…`, `/classified/…`, …) and
|
|
52
|
+
* `pluginFor(type).detailRoute()` is the only thing that knows which. A card
|
|
53
|
+
* that hardcodes `/products/{slug}` sends an auction to the standard product
|
|
54
|
+
* page — which is Root Cause #48 exactly: a doc→card mapper dropping
|
|
55
|
+
* `listingType` and the link going wrong because of the one field it lost.
|
|
56
|
+
*
|
|
57
|
+
* Optional only because a message sent before this field existed has none;
|
|
58
|
+
* `normalizeListingType` resolves an absent value to `"standard"`, which is
|
|
59
|
+
* the correct reading for those rows.
|
|
60
|
+
*/
|
|
61
|
+
listingType?: string;
|
|
47
62
|
/** Omitted for a guest-gated listing snapshot taken while signed out is not
|
|
48
63
|
* possible here — chat requires auth — but still optional: a product can be
|
|
49
64
|
* archived/deleted between send and render. */
|
|
@@ -18,8 +18,10 @@ export function useOrders(params = {}, opts) {
|
|
|
18
18
|
sp.set("sort", params.sort);
|
|
19
19
|
if (params.page)
|
|
20
20
|
sp.set("page", String(params.page));
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
// `pageSize` is what the route prefers; it keeps reading `perPage` only for
|
|
22
|
+
// links built before the rename, so there is no reason to emit the old name.
|
|
23
|
+
if (params.pageSize)
|
|
24
|
+
sp.set("pageSize", String(params.pageSize));
|
|
23
25
|
const qs = sp.toString();
|
|
24
26
|
// ORDER_ENDPOINTS.LIST ("/api/orders") has no GET route handler — every
|
|
25
27
|
// real caller of this hook wants the current user's own orders, served by
|
|
@@ -2,7 +2,7 @@ import type { JsonValue } from "../../../schemas/types";
|
|
|
2
2
|
import type { DocumentReference, WriteBatch } from "firebase-admin/firestore";
|
|
3
3
|
import type { FirebaseSieveResult, SieveModel } from "../../../providers/db-firebase";
|
|
4
4
|
import { BaseRepository, parseSieveDateValue } from "../../../providers/db-firebase";
|
|
5
|
-
import { type OrderCreateInput, type OrderDocument, type OrderRefundEvent } from "../schemas";
|
|
5
|
+
import { type OrderCreateInput, type OrderDocument, type OrderPlain, type OrderRefundEvent } from "../schemas";
|
|
6
6
|
import { type HistoryActor, type FieldChange } from "../../../_internal/shared/history/index";
|
|
7
7
|
import type { OrderStatus, PaymentStatus } from "../types";
|
|
8
8
|
import { type PaymentReviewQueueMode } from "../constants/payment-window";
|
|
@@ -26,7 +26,6 @@ export interface OrderWriteContext {
|
|
|
26
26
|
}
|
|
27
27
|
declare class OrderRepository extends BaseRepository<OrderDocument> {
|
|
28
28
|
constructor();
|
|
29
|
-
private decryptOrder;
|
|
30
29
|
/**
|
|
31
30
|
* Declared, not hand-rolled.
|
|
32
31
|
*
|
|
@@ -39,8 +38,20 @@ declare class OrderRepository extends BaseRepository<OrderDocument> {
|
|
|
39
38
|
* call.
|
|
40
39
|
*/
|
|
41
40
|
protected piiFields: readonly ["userName", "userEmail", "sellerEmail"];
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
/** Plaintext PII. **Opt-in and named** — shows up in review and in a grep. */
|
|
42
|
+
revealOrder(doc: OrderDocument): OrderPlain;
|
|
43
|
+
/** As `revealOrder`, for a list read. */
|
|
44
|
+
revealOrders(docs: readonly OrderDocument[]): OrderPlain[];
|
|
45
|
+
/**
|
|
46
|
+
* Masked PII — **the default for any surface that only needs to identify a
|
|
47
|
+
* row to a human.** Decrypts first, then masks: the mask helpers refuse
|
|
48
|
+
* ciphertext by design, so passing a stored field straight in would return
|
|
49
|
+
* "Anonymous" for every row.
|
|
50
|
+
*/
|
|
51
|
+
maskedOrder(doc: OrderDocument): OrderPlain;
|
|
52
|
+
/** As `maskedOrder`, for a list read. */
|
|
53
|
+
maskedOrders(docs: readonly OrderDocument[]): OrderPlain[];
|
|
54
|
+
createOrder(input: OrderCreateInput): Promise<OrderPlain>;
|
|
44
55
|
findByUser(userId: string): Promise<OrderDocument[]>;
|
|
45
56
|
findByProduct(productId: string): Promise<OrderDocument[]>;
|
|
46
57
|
findByStatus(status: OrderStatus): Promise<OrderDocument[]>;
|
|
@@ -3,7 +3,7 @@ import { planSearchTxt, beginSearchWindow, emptySearchResult, } from "../../../u
|
|
|
3
3
|
import { normalizeError } from "../../../errors/normalize.js";
|
|
4
4
|
import { DatabaseError, NotFoundError } from "../../../errors/index.js";
|
|
5
5
|
import { BaseRepository, prepareForFirestore, parseSieveDateValue, } from "../../../providers/db-firebase/index.js";
|
|
6
|
-
import {
|
|
6
|
+
import { maskPii, revealPii, ORDER_PII_FIELDS, } from "../../../security/index.js";
|
|
7
7
|
import { serverTimestamp, arrayUnion } from "../../../contracts/field-ops.js";
|
|
8
8
|
import { createOrderId, ORDER_COLLECTION, ORDER_TRACKED_FIELDS, OrderStatusValues, } from "../schemas/index.js";
|
|
9
9
|
import { withHistory } from "../../../_internal/shared/history/index.js";
|
|
@@ -37,18 +37,49 @@ class OrderRepository extends BaseRepository {
|
|
|
37
37
|
*/
|
|
38
38
|
this.piiFields = ORDER_PII_FIELDS;
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
/*
|
|
41
|
+
* 🛑 `mapDoc` is NOT overridden, and that absence IS the change.
|
|
42
|
+
*
|
|
43
|
+
* It used to decrypt on every read, so ciphertext never left the database
|
|
44
|
+
* and every caller handled plaintext without ever saying so. Following
|
|
45
|
+
* `SiteSettingsRepository`: reads return what Firestore holds, and plaintext
|
|
46
|
+
* requires one of the two named methods below.
|
|
47
|
+
*
|
|
48
|
+
* A convention would not hold this. `OrderDocument`'s PII fields are
|
|
49
|
+
* `Encrypted<string>`, assignable to nothing that wants a plain `string`, so
|
|
50
|
+
* a reader that skips both accessors is a compile error naming file and line.
|
|
51
|
+
*/
|
|
52
|
+
/** Plaintext PII. **Opt-in and named** — shows up in review and in a grep. */
|
|
53
|
+
revealOrder(doc) {
|
|
54
|
+
return revealPii(doc, ORDER_PII_FIELDS);
|
|
44
55
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return this.
|
|
56
|
+
/** As `revealOrder`, for a list read. */
|
|
57
|
+
revealOrders(docs) {
|
|
58
|
+
return docs.map((d) => this.revealOrder(d));
|
|
48
59
|
}
|
|
49
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Masked PII — **the default for any surface that only needs to identify a
|
|
62
|
+
* row to a human.** Decrypts first, then masks: the mask helpers refuse
|
|
63
|
+
* ciphertext by design, so passing a stored field straight in would return
|
|
64
|
+
* "Anonymous" for every row.
|
|
65
|
+
*/
|
|
66
|
+
maskedOrder(doc) {
|
|
67
|
+
return maskPii(doc, ORDER_PII_FIELDS);
|
|
68
|
+
}
|
|
69
|
+
/** As `maskedOrder`, for a list read. */
|
|
70
|
+
maskedOrders(docs) {
|
|
71
|
+
return docs.map((d) => this.maskedOrder(d));
|
|
72
|
+
}
|
|
73
|
+
/*
|
|
74
|
+
* 🛑 NOT an `override`. It returns the plaintext it was handed rather than
|
|
75
|
+
* re-reading (a read-after-write costs a Firestore read per order), so the
|
|
76
|
+
* return is `OrderPlain` — not assignable to the base's `Promise<T>`, and
|
|
77
|
+
* correctly so, because the two differ.
|
|
78
|
+
*/
|
|
79
|
+
async createOrder(input) {
|
|
50
80
|
const orderDate = new Date();
|
|
51
81
|
const id = createOrderId(input.quantity, orderDate);
|
|
82
|
+
// Plain in, ciphertext out — `applyWriteHooks` encrypts below.
|
|
52
83
|
const orderData = {
|
|
53
84
|
...input,
|
|
54
85
|
orderDate,
|
|
@@ -116,6 +147,7 @@ class OrderRepository extends BaseRepository {
|
|
|
116
147
|
});
|
|
117
148
|
// `null` means no tracked field actually changed — write the patch as-is
|
|
118
149
|
// so an untracked update never grows the array.
|
|
150
|
+
// Plain: this is a write payload and `update` encrypts.
|
|
119
151
|
return this.update(orderId, (withEntry ?? patch));
|
|
120
152
|
}
|
|
121
153
|
async updateStatus(orderId, status, additionalData, ctx) {
|
|
@@ -172,7 +204,7 @@ class OrderRepository extends BaseRepository {
|
|
|
172
204
|
.orderBy(ORDER_FIELDS.CREATED_AT, "asc")
|
|
173
205
|
.limit(200)
|
|
174
206
|
.get();
|
|
175
|
-
return snap.docs.map((doc) =>
|
|
207
|
+
return snap.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
|
|
176
208
|
}
|
|
177
209
|
async updatePaymentStatus(orderId, paymentStatus, paymentId, ctx) {
|
|
178
210
|
return this.updateWithHistory(orderId, {
|
|
@@ -202,7 +234,7 @@ class OrderRepository extends BaseRepository {
|
|
|
202
234
|
.where(ORDER_FIELDS.ORDER_DATE, ">=", new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000))
|
|
203
235
|
.orderBy(ORDER_FIELDS.ORDER_DATE, "desc")
|
|
204
236
|
.get();
|
|
205
|
-
return snapshot.docs.map((doc) =>
|
|
237
|
+
return snapshot.docs.map((doc) => ({
|
|
206
238
|
id: doc.id,
|
|
207
239
|
...doc.data(),
|
|
208
240
|
}));
|
|
@@ -412,7 +444,7 @@ class OrderRepository extends BaseRepository {
|
|
|
412
444
|
.where("paymentBatchId", "==", batchId)
|
|
413
445
|
.limit(20)
|
|
414
446
|
.get();
|
|
415
|
-
return snap.docs.map((d) =>
|
|
447
|
+
return snap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
416
448
|
}
|
|
417
449
|
/**
|
|
418
450
|
* Fetch every order recorded against a single gateway payment id (e.g. a
|
|
@@ -428,7 +460,7 @@ class OrderRepository extends BaseRepository {
|
|
|
428
460
|
.where(ORDER_FIELDS.PAYMENT_ID, "==", paymentId)
|
|
429
461
|
.limit(20)
|
|
430
462
|
.get();
|
|
431
|
-
return snap.docs.map((d) =>
|
|
463
|
+
return snap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
432
464
|
}
|
|
433
465
|
/**
|
|
434
466
|
* Cloud Functions: find pending orders created before a timeout threshold.
|
|
@@ -447,7 +479,7 @@ class OrderRepository extends BaseRepository {
|
|
|
447
479
|
return snap.docs.map((d) => ({
|
|
448
480
|
id: d.id,
|
|
449
481
|
ref: d.ref,
|
|
450
|
-
data:
|
|
482
|
+
data: { id: d.id, ...d.data() },
|
|
451
483
|
}));
|
|
452
484
|
}
|
|
453
485
|
/**
|
|
@@ -470,7 +502,7 @@ class OrderRepository extends BaseRepository {
|
|
|
470
502
|
.map((d) => ({
|
|
471
503
|
id: d.id,
|
|
472
504
|
ref: d.ref,
|
|
473
|
-
data:
|
|
505
|
+
data: { id: d.id, ...d.data() },
|
|
474
506
|
}))
|
|
475
507
|
.filter((entry) => !entry.data.paymentProofUrl);
|
|
476
508
|
}
|
|
@@ -495,7 +527,7 @@ class OrderRepository extends BaseRepository {
|
|
|
495
527
|
.map((d) => ({
|
|
496
528
|
id: d.id,
|
|
497
529
|
ref: d.ref,
|
|
498
|
-
data:
|
|
530
|
+
data: { id: d.id, ...d.data() },
|
|
499
531
|
}))
|
|
500
532
|
.filter((entry) => !!entry.data.paymentProofUrl && !entry.data.paymentReviewOutcome);
|
|
501
533
|
}
|
|
@@ -537,7 +569,7 @@ class OrderRepository extends BaseRepository {
|
|
|
537
569
|
.limit(PAYMENT_REVIEW_QUEUE_SCAN_LIMIT)
|
|
538
570
|
.get();
|
|
539
571
|
const matches = snap.docs
|
|
540
|
-
.map((d) =>
|
|
572
|
+
.map((d) => ({ id: d.id, ...d.data() }))
|
|
541
573
|
.filter((order) => MANUAL_PAYMENT_METHODS.includes(order.paymentMethod ?? ""))
|
|
542
574
|
.filter((order) => mode === "awaiting_proof"
|
|
543
575
|
? !order.paymentProofUrl
|
|
@@ -573,7 +605,7 @@ class OrderRepository extends BaseRepository {
|
|
|
573
605
|
.map((d) => ({
|
|
574
606
|
id: d.id,
|
|
575
607
|
ref: d.ref,
|
|
576
|
-
data:
|
|
608
|
+
data: { id: d.id, ...d.data() },
|
|
577
609
|
}))
|
|
578
610
|
.filter((o) => !o.data.emiEnabled || o.data.emiComplete);
|
|
579
611
|
}
|
|
@@ -596,7 +628,7 @@ class OrderRepository extends BaseRepository {
|
|
|
596
628
|
.map((d) => ({
|
|
597
629
|
id: d.id,
|
|
598
630
|
ref: d.ref,
|
|
599
|
-
data:
|
|
631
|
+
data: { id: d.id, ...d.data() },
|
|
600
632
|
}))
|
|
601
633
|
.filter((o) => !o.data.emiEnabled || o.data.emiComplete);
|
|
602
634
|
}
|
|
@@ -616,7 +648,7 @@ class OrderRepository extends BaseRepository {
|
|
|
616
648
|
return snap.docs.map((d) => ({
|
|
617
649
|
id: d.id,
|
|
618
650
|
ref: d.ref,
|
|
619
|
-
data:
|
|
651
|
+
data: { id: d.id, ...d.data() },
|
|
620
652
|
}));
|
|
621
653
|
}
|
|
622
654
|
/**
|
|
@@ -8,6 +8,7 @@ import type { ListingType } from "../../products/types";
|
|
|
8
8
|
import type { StatusChangeEntry } from "../../../_internal/shared/history/index";
|
|
9
9
|
import type { ReturnReason } from "../../../_internal/shared/features/orders/return-reasons";
|
|
10
10
|
import type { ReturnCustodyState } from "../../../_internal/shared/features/returns/custody";
|
|
11
|
+
import type { Encrypted, Plaintext } from "../../../security/encrypted";
|
|
11
12
|
export interface OrderSourceStandard {
|
|
12
13
|
path: "standard";
|
|
13
14
|
listPrice: number;
|
|
@@ -320,14 +321,24 @@ export interface AppliedOrderDiscount {
|
|
|
320
321
|
scope?: "admin" | "seller";
|
|
321
322
|
storeId?: string;
|
|
322
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* `OrderDocument` with its PII as plain `string` — what the named repository
|
|
326
|
+
* accessors return, and what a WRITE path accepts (the repository encrypts).
|
|
327
|
+
*
|
|
328
|
+
* `Plaintext<T>` is the one definition of this shape; see `security/encrypted.ts`.
|
|
329
|
+
* It is deliberately NOT distinguishable from a MASKED value — `maskPii`
|
|
330
|
+
* returns plain strings too, and no type can express "these characters are
|
|
331
|
+
* asterisks". The distinction is which named method you called.
|
|
332
|
+
*/
|
|
333
|
+
export type OrderPlain = Plaintext<OrderDocument>;
|
|
323
334
|
export interface OrderDocument extends BaseDocument {
|
|
324
335
|
/** Word-prefix search tokens. Derived on write; never fed by a PII field. */
|
|
325
336
|
searchTxt?: string[];
|
|
326
337
|
productId: string;
|
|
327
338
|
productTitle: string;
|
|
328
339
|
userId: string;
|
|
329
|
-
userName: string
|
|
330
|
-
userEmail: string
|
|
340
|
+
userName: Encrypted<string>;
|
|
341
|
+
userEmail: Encrypted<string>;
|
|
331
342
|
storeId?: string;
|
|
332
343
|
storeName?: string;
|
|
333
344
|
items?: OrderDocumentItem[];
|
|
@@ -778,9 +789,9 @@ export declare const ORDER_UPDATABLE_FIELDS: readonly ["notes", "shippingAddress
|
|
|
778
789
|
* which is every single write — and exhaust the FIFO cap within days.
|
|
779
790
|
*/
|
|
780
791
|
export declare const ORDER_TRACKED_FIELDS: readonly ["status", "paymentStatus", "paymentReviewOutcome", "trackingNumber", "cancellationReason"];
|
|
781
|
-
export type OrderCreateInput = Omit<
|
|
792
|
+
export type OrderCreateInput = Omit<OrderPlain, "id" | "createdAt" | "updatedAt" | "orderDate">;
|
|
782
793
|
export type OrderUpdateInput = Partial<Pick<OrderDocument, (typeof ORDER_UPDATABLE_FIELDS)[number]>>;
|
|
783
|
-
export type OrderAdminUpdateInput = Partial<Omit<
|
|
794
|
+
export type OrderAdminUpdateInput = Partial<Omit<OrderPlain, "id" | "createdAt">>;
|
|
784
795
|
export declare const orderQueryHelpers: {
|
|
785
796
|
readonly byUser: (userId: string) => readonly ["userId", "==", string];
|
|
786
797
|
readonly byStore: (storeId: string) => readonly ["storeId", "==", string];
|