@mohasinac/appkit 4.52.5 → 4.53.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.build-stamp.json +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/client/scaffolds/AppShell.js +1 -1
- package/dist/_internal/server/features/auctions/actions.js +1 -1
- package/dist/_internal/server/features/auctions/og.d.ts +3 -1
- package/dist/_internal/server/features/auctions/og.js +3 -1
- package/dist/_internal/server/features/bundles/actions.js +1 -1
- package/dist/_internal/server/features/business-documents/download.d.ts +41 -0
- package/dist/_internal/server/features/business-documents/download.js +91 -0
- package/dist/_internal/server/features/categories/adapters.d.ts +1 -1
- package/dist/_internal/server/features/categories/adapters.js +10 -0
- package/dist/_internal/server/features/categories/data.js +23 -7
- package/dist/_internal/server/features/checkout/actions.d.ts +14 -0
- package/dist/_internal/server/features/checkout/actions.js +116 -15
- package/dist/_internal/server/features/checkout/bundle-expansion.js +17 -0
- package/dist/_internal/server/features/checkout/data.d.ts +37 -0
- package/dist/_internal/server/features/checkout/data.js +20 -3
- package/dist/_internal/server/features/checkout/group-rule-revalidation.d.ts +34 -0
- package/dist/_internal/server/features/checkout/group-rule-revalidation.js +124 -0
- package/dist/_internal/server/features/checkout/supplier-identity.d.ts +55 -0
- package/dist/_internal/server/features/checkout/supplier-identity.js +81 -0
- package/dist/_internal/server/features/classified/metadata.js +1 -1
- package/dist/_internal/server/features/classified/og.d.ts +3 -1
- package/dist/_internal/server/features/classified/og.js +3 -1
- package/dist/_internal/server/features/digital-code/metadata.js +1 -1
- package/dist/_internal/server/features/digital-code/og.d.ts +3 -1
- package/dist/_internal/server/features/digital-code/og.js +3 -1
- package/dist/_internal/server/features/digital-code/pool.d.ts +19 -4
- package/dist/_internal/server/features/digital-code/pool.js +19 -4
- package/dist/_internal/server/features/live/metadata.js +1 -1
- package/dist/_internal/server/features/live/og.d.ts +3 -1
- package/dist/_internal/server/features/live/og.js +3 -1
- package/dist/_internal/server/features/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 +5 -1
- 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/parts/og.js +1 -1
- package/dist/_internal/server/features/pre-orders/og.d.ts +3 -1
- package/dist/_internal/server/features/pre-orders/og.js +3 -1
- package/dist/_internal/server/features/price-index/search.d.ts +18 -0
- package/dist/_internal/server/features/price-index/search.js +47 -7
- package/dist/_internal/server/features/prize-draws/og.d.ts +3 -1
- package/dist/_internal/server/features/prize-draws/og.js +3 -1
- package/dist/_internal/server/features/products/group-members.d.ts +26 -0
- package/dist/_internal/server/features/products/group-members.js +7 -1
- package/dist/_internal/server/features/products/og.d.ts +3 -1
- package/dist/_internal/server/features/products/og.js +3 -1
- package/dist/_internal/server/features/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/scoped-sources.d.ts +26 -0
- package/dist/_internal/server/features/search/scoped-sources.js +252 -0
- package/dist/_internal/server/features/search/search-everything.d.ts +57 -0
- package/dist/_internal/server/features/search/search-everything.js +70 -20
- package/dist/_internal/server/features/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 +7 -1
- package/dist/_internal/server/features/shared/listing-adapters.js +4 -2
- 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 +91 -0
- package/dist/_internal/server/features/sticker-trace/adapters.js +175 -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-to-listings.d.ts +26 -0
- package/dist/_internal/server/features/sticker-trace/promote-to-listings.js +264 -0
- package/dist/_internal/server/features/sticker-trace/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 +143 -0
- package/dist/_internal/server/features/sticker-trace/sheet-actions.js +311 -0
- package/dist/_internal/server/features/sticker-trace/storage.d.ts +154 -0
- package/dist/_internal/server/features/sticker-trace/storage.js +301 -0
- package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
- package/dist/_internal/server/features/stores/adapters.js +16 -0
- package/dist/_internal/server/features/stores/index.d.ts +1 -0
- package/dist/_internal/server/features/stores/index.js +1 -0
- package/dist/_internal/server/features/stores/tabs.d.ts +25 -0
- package/dist/_internal/server/features/stores/tabs.js +122 -0
- package/dist/_internal/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/checkout/rules/_defaults.js +0 -2
- package/dist/_internal/shared/checkout/rules/_limits.d.ts +14 -1
- package/dist/_internal/shared/checkout/rules/_limits.js +14 -1
- package/dist/_internal/shared/checkout/rules/_registry.js +2 -0
- package/dist/_internal/shared/checkout/rules/auction.rule.js +9 -1
- package/dist/_internal/shared/checkout/rules/bundle.rule.js +13 -0
- package/dist/_internal/shared/checkout/rules/index.d.ts +2 -0
- package/dist/_internal/shared/checkout/rules/index.js +9 -0
- package/dist/_internal/shared/checkout/rules/offer.rule.js +0 -1
- package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +26 -0
- package/dist/_internal/shared/checkout/rules/payment-gate.js +133 -0
- package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +29 -8
- package/dist/_internal/shared/checkout/rules/spares.rule.d.ts +16 -0
- package/dist/_internal/shared/checkout/rules/spares.rule.js +5 -0
- package/dist/_internal/shared/checkout/rules/types.d.ts +26 -2
- package/dist/_internal/shared/config/schema.d.ts +122 -0
- package/dist/_internal/shared/features/cart/schema.js +3 -2
- package/dist/_internal/shared/features/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/products/group-rules.d.ts +75 -0
- package/dist/_internal/shared/features/products/group-rules.js +142 -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 +35 -0
- package/dist/_internal/shared/listing-types/_registry.js +39 -1
- package/dist/_internal/shared/listing-types/art/config.d.ts +2 -0
- package/dist/_internal/shared/listing-types/art/config.js +3 -0
- package/dist/_internal/shared/listing-types/auction/config.d.ts +2 -0
- package/dist/_internal/shared/listing-types/auction/config.js +3 -0
- package/dist/_internal/shared/listing-types/availability.js +48 -0
- package/dist/_internal/shared/listing-types/capabilities.js +19 -0
- package/dist/_internal/shared/listing-types/classified/config.d.ts +2 -0
- package/dist/_internal/shared/listing-types/classified/config.js +3 -0
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +2 -0
- package/dist/_internal/shared/listing-types/digital-code/config.js +3 -0
- package/dist/_internal/shared/listing-types/feature-flags.d.ts +7 -0
- package/dist/_internal/shared/listing-types/feature-flags.js +10 -0
- package/dist/_internal/shared/listing-types/live/config.d.ts +2 -0
- package/dist/_internal/shared/listing-types/live/config.js +3 -0
- package/dist/_internal/shared/listing-types/pre-order/config.d.ts +2 -0
- package/dist/_internal/shared/listing-types/pre-order/config.js +3 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +2 -0
- package/dist/_internal/shared/listing-types/prize-draw/config.js +3 -0
- package/dist/_internal/shared/listing-types/spares/config.d.ts +74 -0
- package/dist/_internal/shared/listing-types/spares/config.js +60 -0
- package/dist/_internal/shared/listing-types/spares/ctas.d.ts +1 -0
- package/dist/_internal/shared/listing-types/spares/ctas.js +4 -0
- package/dist/_internal/shared/listing-types/spares/og.js +1 -0
- package/dist/_internal/shared/listing-types/spares/schema.d.ts +2 -0
- package/dist/_internal/shared/listing-types/spares/schema.js +3 -0
- package/dist/_internal/shared/listing-types/spares/seed-factory.d.ts +1 -0
- package/dist/_internal/shared/listing-types/spares/seed-factory.js +1 -0
- package/dist/_internal/shared/listing-types/standard/config.d.ts +2 -0
- package/dist/_internal/shared/listing-types/standard/config.js +3 -0
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +2 -0
- package/dist/_internal/shared/listing-types/stickers/config.js +3 -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 +76 -0
- package/dist/_internal/shared/search/match.js +264 -0
- package/dist/_internal/shared/search/to-groups.d.ts +52 -0
- package/dist/_internal/shared/search/to-groups.js +141 -0
- package/dist/client.d.ts +16 -9
- package/dist/client.js +16 -6
- package/dist/configs/eslint.js +22 -2
- package/dist/constants/api-endpoints.d.ts +107 -15
- package/dist/constants/api-endpoints.js +60 -5
- package/dist/constants/cache-invalidation.js +3 -1
- package/dist/constants/field-names.d.ts +13 -1
- package/dist/constants/field-names.js +42 -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/about/components/PolicyPageView.d.ts +22 -2
- package/dist/features/about/components/PolicyPageView.js +14 -2
- package/dist/features/about/components/PublicProfileView.js +2 -1
- package/dist/features/about/components/ShippingPolicyView.js +42 -2
- package/dist/features/account/api/[userId]/addresses/route.js +1 -1
- package/dist/features/account/components/NotificationBell.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/account/hooks/useProfileStats.js +5 -1
- package/dist/features/addresses/repository/addresses.repository.d.ts +33 -6
- package/dist/features/addresses/repository/addresses.repository.js +86 -9
- package/dist/features/addresses/schemas/firestore.d.ts +17 -6
- package/dist/features/admin/actions/admin-actions.js +16 -1
- 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 +19 -3
- package/dist/features/admin/components/AdminContactView.js +1 -1
- package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -3
- package/dist/features/admin/components/AdminNavigationView.js +1 -1
- package/dist/features/admin/components/AdminNewsletterView.js +1 -1
- package/dist/features/admin/components/AdminOrdersView.js +9 -2
- package/dist/features/admin/components/AdminPageHeader.js +1 -1
- 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 +41 -39
- 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/AdminSidebar.js +1 -1
- package/dist/features/admin/components/AdminSiteSettingsView.js +39 -8
- package/dist/features/admin/components/AdminSparesView.d.ts +12 -0
- package/dist/features/admin/components/AdminSparesView.js +30 -0
- package/dist/features/admin/components/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 +10 -8
- 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/components/index.d.ts +2 -0
- package/dist/features/admin/components/index.js +1 -0
- package/dist/features/admin/components/sections/adminSectionsTypes.js +7 -0
- package/dist/features/admin/constants/filter-tabs.d.ts +3 -0
- package/dist/features/admin/constants/filter-tabs.js +1 -0
- package/dist/features/admin/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 +88 -3
- 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/components/AuctionDetailPageView.js +4 -11
- 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 +46 -7
- package/dist/features/auth/repository/user.repository.js +128 -15
- package/dist/features/auth/schemas/firestore.d.ts +65 -12
- package/dist/features/auth/schemas/firestore.js +13 -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/business-documents/repository/business-documents.repository.d.ts +58 -0
- package/dist/features/business-documents/repository/business-documents.repository.js +54 -0
- package/dist/features/business-documents/schemas/firestore.d.ts +105 -0
- package/dist/features/business-documents/schemas/firestore.js +75 -0
- package/dist/features/cart/actions/cart-actions.js +83 -6
- package/dist/features/cart/api/route.js +1 -1
- package/dist/features/cart/repository/cart.repository.js +32 -4
- package/dist/features/cart/schemas/firestore.d.ts +20 -0
- package/dist/features/cart/schemas/index.d.ts +2 -2
- package/dist/features/catalogue/components/PublicCatalogueItemDetailView.js +1 -1
- package/dist/features/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/[id]/price-guidance/route.d.ts +42 -0
- package/dist/features/categories/api/[id]/price-guidance/route.js +113 -0
- package/dist/features/categories/api/route.js +10 -10
- package/dist/features/categories/components/BrandDetailPageView.js +19 -3
- package/dist/features/categories/components/BrandDetailTabs.js +10 -0
- package/dist/features/categories/components/CategoriesIndexListing.js +23 -8
- package/dist/features/categories/components/CategoryDetailPageView.js +170 -13
- package/dist/features/categories/components/CategoryDetailTabs.js +12 -0
- package/dist/features/categories/components/CategoryGrid.js +10 -1
- package/dist/features/categories/components/CategorySelectorCreate.js +0 -1
- package/dist/features/categories/components/PriceGuidanceHint.d.ts +29 -0
- package/dist/features/categories/components/PriceGuidanceHint.js +61 -0
- package/dist/features/categories/components/SubcategoryCardRow.d.ts +27 -0
- package/dist/features/categories/components/SubcategoryCardRow.js +98 -0
- package/dist/features/categories/components/index.d.ts +0 -2
- package/dist/features/categories/components/index.js +0 -1
- package/dist/features/categories/constants/category-tabs.d.ts +20 -25
- package/dist/features/categories/constants/category-tabs.js +22 -39
- package/dist/features/categories/repository/categories.repository.d.ts +13 -0
- package/dist/features/categories/repository/categories.repository.js +51 -1
- package/dist/features/categories/schemas/firestore.d.ts +22 -1
- package/dist/features/categories/schemas/firestore.js +10 -0
- package/dist/features/categories/schemas/index.d.ts +8 -2
- package/dist/features/categories/schemas/index.js +2 -0
- package/dist/features/categories/types/index.d.ts +8 -0
- package/dist/features/categories/utils/taxonomy-visual.d.ts +34 -0
- package/dist/features/categories/utils/taxonomy-visual.js +74 -0
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +8 -1
- package/dist/features/classified/components/ClassifiedDetailPageView.js +4 -9
- 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/contact/components/ContactPageView.d.ts +33 -1
- package/dist/features/contact/components/ContactPageView.js +58 -28
- 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/digital-codes/components/DigitalCodeDetailPageView.js +4 -9
- 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/GroupedListingDetailView.js +9 -1
- package/dist/features/grouped/components/GroupedListingEditorView.js +17 -2
- package/dist/features/grouped/schemas/firestore.d.ts +5 -0
- package/dist/features/homepage/actions/homepage-section-actions.d.ts +3 -3
- package/dist/features/homepage/api/carousel/[id]/route.js +1 -1
- package/dist/features/homepage/api/carousel/route.js +4 -4
- package/dist/features/homepage/components/AnnouncementBar.d.ts +1 -9
- package/dist/features/homepage/components/AnnouncementBar.js +13 -19
- package/dist/features/homepage/components/CollectionCardsSection.d.ts +28 -6
- package/dist/features/homepage/components/CollectionCardsSection.js +43 -8
- package/dist/features/homepage/components/HowItWorksSection.d.ts +23 -6
- package/dist/features/homepage/components/HowItWorksSection.js +4 -4
- package/dist/features/homepage/components/MarketplaceHomepageView.js +6 -1
- package/dist/features/homepage/components/PromoGrid.d.ts +31 -2
- package/dist/features/homepage/components/PromoGrid.js +12 -3
- package/dist/features/homepage/components/TestimonialsCarousel.d.ts +34 -2
- package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
- package/dist/features/homepage/components/index.d.ts +0 -22
- package/dist/features/homepage/components/index.js +0 -12
- package/dist/features/homepage/index.d.ts +0 -2
- package/dist/features/homepage/index.js +0 -2
- package/dist/features/homepage/lib/section-renderer.d.ts +9 -0
- package/dist/features/homepage/lib/section-renderer.js +202 -58
- package/dist/features/homepage/repository/homepage-sections.repository.d.ts +35 -3
- package/dist/features/homepage/repository/homepage-sections.repository.js +58 -8
- package/dist/features/homepage/schemas/firestore.d.ts +112 -3
- package/dist/features/homepage/schemas/firestore.js +32 -2
- package/dist/features/homepage/schemas/index.d.ts +46 -17
- package/dist/features/homepage/schemas/index.js +39 -27
- package/dist/features/homepage/server.d.ts +0 -3
- package/dist/features/homepage/server.js +0 -3
- package/dist/features/homepage/types/index.d.ts +0 -47
- package/dist/features/homepage/types/index.js +49 -0
- package/dist/features/layout/AppLayoutShell.d.ts +11 -0
- 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/BottomNavItem.js +1 -1
- package/dist/features/layout/BottomNavbar.d.ts +14 -0
- package/dist/features/layout/BottomNavbar.js +43 -3
- package/dist/features/layout/BottomSheet.js +1 -1
- package/dist/features/layout/MainNavbar.d.ts +11 -0
- package/dist/features/layout/NavbarLayout.d.ts +3 -0
- package/dist/features/layout/NavbarLayout.js +88 -11
- package/dist/features/layout/SideActionDock.d.ts +1 -0
- package/dist/features/layout/SideActionDock.js +219 -0
- package/dist/features/layout/TitleBarLayout.js +1 -1
- package/dist/features/layout/cta-anchor.d.ts +31 -0
- package/dist/features/layout/cta-anchor.js +31 -0
- package/dist/features/layout/hooks/useBottomActions.d.ts +7 -0
- package/dist/features/layout/hooks/useBottomActions.js +6 -1
- package/dist/features/layout/index.d.ts +9 -1
- package/dist/features/layout/index.js +9 -1
- package/dist/features/layout/useCtaReveal.d.ts +24 -0
- package/dist/features/layout/useCtaReveal.js +82 -0
- package/dist/features/layout/useHoldToOpen.d.ts +41 -0
- package/dist/features/layout/useHoldToOpen.js +84 -0
- package/dist/features/live/components/LiveItemDetailPageView.js +4 -9
- 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/hooks/useMedia.js +17 -0
- 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 +65 -0
- package/dist/features/media/repository/media-assets.repository.js +31 -0
- package/dist/features/media/trust-signals.d.ts +85 -0
- package/dist/features/media/trust-signals.js +126 -0
- package/dist/features/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/parts/components/PartDetailPageView.d.ts +14 -1
- package/dist/features/parts/components/PartDetailPageView.js +2 -2
- package/dist/features/parts/components/PartsIndexPageView.d.ts +11 -2
- package/dist/features/parts/components/PartsIndexPageView.js +2 -2
- package/dist/features/parts/components/PartsSearchBox.d.ts +9 -0
- package/dist/features/parts/components/PartsSearchBox.js +57 -0
- package/dist/features/parts/schemas/firestore.d.ts +149 -3
- package/dist/features/parts/schemas/firestore.js +184 -0
- package/dist/features/payments/repository/payments.repository.js +2 -2
- package/dist/features/payments/repository/payout.repository.d.ts +38 -6
- package/dist/features/payments/repository/payout.repository.js +84 -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/components/PreOrderDetailPageView.js +4 -11
- package/dist/features/pre-orders/components/PreOrdersIndexListing.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/price-index/components/PriceIndexToolView.d.ts +3 -1
- package/dist/features/price-index/components/PriceIndexToolView.js +92 -13
- package/dist/features/products/api/[id]/route.js +1 -1
- package/dist/features/products/components/CompareOverlay.d.ts +18 -1
- package/dist/features/products/components/CompareOverlay.js +21 -2
- package/dist/features/products/components/CustomSectionTabContent.d.ts +31 -0
- package/dist/features/products/components/CustomSectionTabContent.js +29 -3
- package/dist/features/products/components/GroupMemberPicker.d.ts +19 -1
- package/dist/features/products/components/GroupMemberPicker.js +46 -8
- package/dist/features/products/components/GroupSettingsPanel.d.ts +11 -1
- package/dist/features/products/components/GroupSettingsPanel.js +91 -3
- package/dist/features/products/components/ListingBottomActions.js +4 -0
- package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
- package/dist/features/products/components/PrizeDrawEntryActions.d.ts +15 -1
- package/dist/features/products/components/PrizeDrawEntryActions.js +70 -8
- package/dist/features/products/components/ProductDetailPageView.js +75 -15
- package/dist/features/products/components/ProductForm.d.ts +13 -1
- package/dist/features/products/components/ProductForm.js +16 -2
- package/dist/features/products/components/ProductGalleryClient.js +2 -2
- package/dist/features/products/components/ProductGrid.js +12 -1
- package/dist/features/products/components/ProductsIndexListing.d.ts +16 -1
- package/dist/features/products/components/ProductsIndexListing.js +3 -3
- package/dist/features/products/components/ShowGroupSection.js +15 -2
- package/dist/features/products/components/SparesListView.d.ts +7 -0
- package/dist/features/products/components/SparesListView.js +39 -0
- package/dist/features/products/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/action-defs.d.ts +1 -0
- package/dist/features/products/constants/action-defs.js +1 -0
- 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.d.ts +98 -0
- package/dist/features/products/repository/products.repository.js +248 -18
- package/dist/features/products/schemas/firestore.d.ts +97 -4
- package/dist/features/products/schemas/firestore.js +104 -0
- package/dist/features/products/schemas/index.d.ts +12 -21
- package/dist/features/products/schemas/index.js +23 -6
- package/dist/features/products/types/index.d.ts +46 -2
- package/dist/features/products/utils/group-member-image.d.ts +39 -0
- package/dist/features/products/utils/group-member-image.js +3 -0
- package/dist/features/products/utils/listing-badge-variant.js +4 -0
- package/dist/features/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/components/ReviewsList.js +1 -1
- 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/scams/components/ScamProfileView.js +1 -1
- package/dist/features/search/components/EntityTypeahead.d.ts +44 -0
- package/dist/features/search/components/EntityTypeahead.js +92 -0
- package/dist/features/search/components/Search.d.ts +12 -1
- package/dist/features/search/components/Search.js +47 -3
- package/dist/features/search/components/SearchFacetRail.d.ts +11 -0
- package/dist/features/search/components/SearchFacetRail.js +92 -0
- package/dist/features/search/components/SearchResultsClient.d.ts +33 -0
- package/dist/features/search/components/SearchResultsClient.js +103 -0
- package/dist/features/search/components/SearchResultsPageView.d.ts +15 -1
- package/dist/features/search/components/SearchResultsPageView.js +3 -2
- package/dist/features/search/components/index.d.ts +0 -6
- package/dist/features/search/components/index.js +0 -3
- package/dist/features/search/hooks/useNavSuggestions.d.ts +13 -0
- package/dist/features/search/hooks/useScopedSearch.d.ts +34 -0
- package/dist/features/search/hooks/useScopedSearch.js +114 -0
- package/dist/features/search/hooks/useSearchIndex.d.ts +34 -0
- package/dist/features/search/hooks/useSearchIndex.js +172 -0
- package/dist/features/search/hooks/useSiteSearch.d.ts +26 -0
- package/dist/features/search/hooks/useSiteSearch.js +149 -0
- package/dist/features/search/index.d.ts +0 -4
- package/dist/features/search/index.js +0 -4
- package/dist/features/search/manifest.d.ts +12 -0
- package/dist/features/search/manifest.js +17 -2
- package/dist/features/search/server.d.ts +0 -3
- package/dist/features/search/server.js +0 -3
- package/dist/features/seller/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.d.ts +1 -1
- package/dist/features/seller/components/SellerListingTypeView.js +29 -1
- package/dist/features/seller/components/SellerOrdersView.js +1 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +35 -15
- package/dist/features/seller/components/SellerPayoutsView.js +1 -1
- package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
- package/dist/features/seller/components/SellerProductShell.js +2 -2
- package/dist/features/seller/components/SellerProductsView.js +1 -1
- package/dist/features/seller/components/SellerShippingView.js +0 -1
- package/dist/features/seller/components/SellerSidebar.js +1 -1
- package/dist/features/seller/components/SellerSparesView.d.ts +17 -0
- package/dist/features/seller/components/SellerSparesView.js +6 -0
- package/dist/features/seller/components/SellerStorefrontView.js +0 -1
- package/dist/features/seller/components/index.d.ts +2 -4
- package/dist/features/seller/components/index.js +1 -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/CommandPalette.js +1 -1
- 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 +267 -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/StoreDetailLayoutView.d.ts +1 -1
- package/dist/features/stores/components/StoreDetailLayoutView.js +7 -82
- package/dist/features/stores/components/StoreHeader.js +1 -2
- package/dist/features/stores/components/StoreNavTabs.js +17 -2
- package/dist/features/stores/components/StoreSparesPageView.d.ts +27 -0
- package/dist/features/stores/components/StoreSparesPageView.js +48 -0
- package/dist/features/stores/manifest.js +8 -4
- package/dist/features/stores/schemas/firestore.d.ts +19 -0
- 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/buying__spares-and-groups.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/buying__spares-and-groups.js +96 -0
- package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +4 -0
- package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +478 -0
- package/dist/features/tester/seed-data/authored/content-discovery__category-tabs-franchise-bundles.js +54 -32
- package/dist/features/tester/seed-data/authored/content-discovery__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/content-discovery__parts-database.js +3 -2
- package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.js +73 -0
- package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.js +340 -0
- package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.js +90 -0
- package/dist/features/tester/seed-data/authored/index.js +24 -0
- package/dist/features/tester/seed-data/authored/search-and-nav__header-search.d.ts +1 -0
- package/dist/features/tester/seed-data/authored/search-and-nav__header-search.js +57 -0
- package/dist/features/tester/seed-data/authored/selling__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/selling__spares-and-group-editing.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.js +77 -0
- package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.js +58 -0
- package/dist/features/tester/seed-data/authored/tools__sticker-tracer.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +284 -0
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +558 -34
- package/dist/index.d.ts +27 -80
- package/dist/index.js +62 -115
- 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 +46 -5
- package/dist/next/routing/route-map.js +70 -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 +33 -9
- package/dist/providers/db-firebase/base.repository.js +55 -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 +28 -26
- package/dist/schemas/registry.js +31 -14
- package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
- package/dist/security/blind-index-tokens.d.ts +54 -0
- package/dist/security/blind-index-tokens.js +152 -0
- package/dist/security/encrypted.d.ts +117 -0
- package/dist/security/encrypted.js +100 -0
- package/dist/security/index.d.ts +6 -3
- package/dist/security/index.js +17 -3
- 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/security/settings-encryption.d.ts +35 -0
- package/dist/security/settings-encryption.js +91 -0
- package/dist/seed/_helpers/brand-rows.js +38 -14
- package/dist/seed/_helpers/category-forest.js +73 -7
- package/dist/seed/_helpers/category-images-generated.d.ts +25 -6
- package/dist/seed/_helpers/category-images-generated.js +81 -6
- package/dist/seed/_helpers/category-models.d.ts +1 -1
- package/dist/seed/_helpers/category-models.js +7 -1
- package/dist/seed/_helpers/category-parts-glossary-map.js +8 -0
- package/dist/seed/_helpers/category-parts.d.ts +1 -1
- package/dist/seed/_helpers/category-parts.js +50 -2
- package/dist/seed/_helpers/character-features.d.ts +1 -1
- package/dist/seed/_helpers/character-features.js +2 -1
- package/dist/seed/_helpers/franchise-rows.js +10 -2
- package/dist/seed/_helpers/media.d.ts +47 -0
- package/dist/seed/_helpers/media.js +34 -0
- package/dist/seed/_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 +78 -0
- package/dist/seed/authenticity-knowledge-seed-data.js +10729 -0
- package/dist/seed/bids-seed-data.d.ts +2 -2
- package/dist/seed/bids-seed-data.js +23 -2
- package/dist/seed/categories-seed-data.js +124 -20
- 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/grouped-listings-seed-data.js +16 -0
- package/dist/seed/homepage-sections-seed-data.js +131 -26
- package/dist/seed/index.d.ts +3 -3
- package/dist/seed/index.js +3 -2
- package/dist/seed/lottery-entries-seed-data.d.ts +2 -2
- package/dist/seed/manifest.js +3 -0
- package/dist/seed/media-assets-seed-data.d.ts +1 -1
- package/dist/seed/media-assets-seed-data.js +746 -196
- package/dist/seed/model-composition-seed-data.js +122 -6
- package/dist/seed/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/part-glossary-seed-data.d.ts +1 -1
- package/dist/seed/part-glossary-seed-data.js +37219 -463
- package/dist/seed/payouts-seed-data.d.ts +2 -2
- package/dist/seed/payouts-seed-data.js +1 -1
- package/dist/seed/products-art-seed-data.js +7 -18
- package/dist/seed/products-auctions-seed-data.js +56 -47
- package/dist/seed/products-beyblade-x-seed-data.d.ts +2 -0
- package/dist/seed/products-beyblade-x-seed-data.js +441 -0
- package/dist/seed/products-catalogue-seed-data.d.ts +5 -5
- package/dist/seed/products-catalogue-seed-data.js +1500 -1240
- package/dist/seed/products-classifieds-seed-data.js +9 -27
- package/dist/seed/products-digital-codes-seed-data.js +9 -18
- package/dist/seed/products-live-items-seed-data.js +5 -13
- package/dist/seed/products-preorders-seed-data.js +67 -33
- package/dist/seed/products-prize-draws-seed-data.js +8 -17
- package/dist/seed/products-spares-seed-data.d.ts +2 -0
- package/dist/seed/products-spares-seed-data.js +368 -0
- package/dist/seed/products-standard-seed-data.js +39 -126
- package/dist/seed/products-stickers-seed-data.js +59 -15
- package/dist/seed/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 +9 -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.d.ts +25 -0
- package/dist/seo/json-ld.js +33 -1
- package/dist/server-entry.d.ts +3 -1
- package/dist/server-entry.js +2 -2
- package/dist/server.d.ts +27 -12
- package/dist/server.js +86 -28
- package/dist/styles.css +438 -1
- package/dist/tailwind-input.css +31 -17
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/Accordion.js +1 -1
- package/dist/ui/components/Breadcrumb.js +1 -1
- package/dist/ui/components/Button.js +7 -1
- package/dist/ui/components/DetailPageGallery.js +0 -2
- package/dist/ui/components/DetailPageHero.js +0 -1
- package/dist/ui/components/DetailPageTabs.js +1 -1
- package/dist/ui/components/Divider.js +3 -3
- package/dist/ui/components/FilterChipGroup.d.ts +11 -0
- package/dist/ui/components/FilterChipGroup.js +1 -1
- package/dist/ui/components/GatedPrice.js +5 -1
- package/dist/ui/components/HorizontalScroller.js +1 -1
- package/dist/ui/components/ImageGallery.js +6 -1
- package/dist/ui/components/ListingLayout.js +17 -11
- package/dist/ui/components/MediaTabs.style.css +81 -0
- 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/Pagination.js +1 -1
- package/dist/ui/components/PendingValue.d.ts +45 -0
- package/dist/ui/components/PendingValue.js +7 -0
- package/dist/ui/components/Radio.style.css +119 -0
- package/dist/ui/components/RatingDisplay.js +2 -2
- package/dist/ui/components/RecordDetailModal.js +14 -1
- package/dist/ui/components/RowActionMenu.js +5 -1
- package/dist/ui/components/SettingsSection.js +0 -2
- package/dist/ui/components/SideDrawer.js +5 -1
- package/dist/ui/components/SideModal.js +9 -1
- package/dist/ui/components/SiteLogo.js +3 -0
- package/dist/ui/components/SiteMark.js +3 -0
- package/dist/ui/components/SortDropdown.js +1 -1
- package/dist/ui/components/SpecTable.d.ts +58 -0
- package/dist/ui/components/SpecTable.js +8 -0
- package/dist/ui/components/StarRating.js +1 -3
- package/dist/ui/components/SummaryCard.js +1 -1
- package/dist/ui/components/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 +2 -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 +7 -0
- package/dist/ui/icons/icon-registry.js +25 -1
- package/dist/ui/index.d.ts +6 -0
- package/dist/ui/index.js +3 -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/utils/search-txt-query.d.ts +12 -0
- package/dist/utils/search-txt-query.js +12 -0
- package/dist/validation/schemas.d.ts +8 -8
- package/package.json +6 -2
- package/scripts/dedupe-peer-deps.mjs +18 -0
- package/scripts/seed-cli.mjs +138 -26
- package/scripts/verify-css-build.mjs +118 -37
- package/dist/_internal/server/features/search/actions.d.ts +0 -7
- package/dist/_internal/server/features/search/actions.js +0 -21
- package/dist/_internal/server/features/search/data.d.ts +0 -15
- package/dist/_internal/server/features/search/data.js +0 -18
- package/dist/_internal/server/features/search/index.d.ts +0 -3
- package/dist/_internal/server/features/search/index.js +0 -2
- package/dist/features/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/api/[id]/route.d.ts +0 -23
- package/dist/features/homepage/api/[id]/route.js +0 -103
- package/dist/features/homepage/api/route.d.ts +0 -14
- package/dist/features/homepage/api/route.js +0 -140
- package/dist/features/homepage/api/sections/[id]/route.d.ts +0 -26
- package/dist/features/homepage/api/sections/[id]/route.js +0 -95
- package/dist/features/homepage/api/sections/route.d.ts +0 -13
- package/dist/features/homepage/api/sections/route.js +0 -82
- package/dist/features/homepage/components/AdvertisementBanner.d.ts +0 -14
- package/dist/features/homepage/components/AdvertisementBanner.js +0 -35
- package/dist/features/homepage/components/BeforeAfterCard.d.ts +0 -9
- package/dist/features/homepage/components/BeforeAfterCard.js +0 -73
- package/dist/features/homepage/components/FeaturedResultsSection.d.ts +0 -17
- package/dist/features/homepage/components/FeaturedResultsSection.js +0 -17
- package/dist/features/homepage/components/HeroBanner.d.ts +0 -7
- package/dist/features/homepage/components/HeroBanner.js +0 -43
- package/dist/features/homepage/components/HeroSection.d.ts +0 -7
- package/dist/features/homepage/components/HeroSection.js +0 -6
- package/dist/features/homepage/components/HomepageSkeleton.d.ts +0 -2
- package/dist/features/homepage/components/HomepageSkeleton.js +0 -21
- package/dist/features/homepage/components/HomepageView.d.ts +0 -25
- package/dist/features/homepage/components/HomepageView.js +0 -5
- package/dist/features/homepage/components/HowItWorksInfoView.d.ts +0 -36
- package/dist/features/homepage/components/HowItWorksInfoView.js +0 -10
- package/dist/features/homepage/components/NewsletterBanner.d.ts +0 -23
- package/dist/features/homepage/components/NewsletterBanner.js +0 -37
- package/dist/features/homepage/components/SiteFeaturesSection.d.ts +0 -14
- package/dist/features/homepage/components/SiteFeaturesSection.js +0 -11
- package/dist/features/homepage/components/TrustBadges.d.ts +0 -6
- package/dist/features/homepage/components/TrustBadges.js +0 -46
- package/dist/features/homepage/components/TrustIndicatorsSection.d.ts +0 -12
- package/dist/features/homepage/components/TrustIndicatorsSection.js +0 -11
- package/dist/features/homepage/hooks/useHomepage.d.ts +0 -11
- package/dist/features/homepage/hooks/useHomepage.js +0 -17
- package/dist/features/homepage/hooks/useHomepageSections.d.ts +0 -2
- package/dist/features/homepage/hooks/useHomepageSections.js +0 -10
- package/dist/features/homepage/repository/homepage.repository.d.ts +0 -11
- package/dist/features/homepage/repository/homepage.repository.js +0 -25
- package/dist/features/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/search/actions/index.d.ts +0 -1
- package/dist/features/search/actions/index.js +0 -1
- package/dist/features/search/actions/search-actions.d.ts +0 -18
- package/dist/features/search/actions/search-actions.js +0 -43
- package/dist/features/search/api/route.d.ts +0 -22
- package/dist/features/search/api/route.js +0 -128
- package/dist/features/search/columns/index.d.ts +0 -17
- package/dist/features/search/columns/index.js +0 -49
- package/dist/features/search/components/SearchFiltersRow.d.ts +0 -22
- package/dist/features/search/components/SearchFiltersRow.js +0 -21
- package/dist/features/search/components/SearchResultsSection.d.ts +0 -53
- package/dist/features/search/components/SearchResultsSection.js +0 -35
- package/dist/features/search/components/SearchView.d.ts +0 -27
- package/dist/features/search/components/SearchView.js +0 -8
- package/dist/features/search/hooks/useSearch.d.ts +0 -21
- package/dist/features/search/hooks/useSearch.js +0 -33
- package/dist/features/search/repository/search.repository.d.ts +0 -14
- package/dist/features/search/repository/search.repository.js +0 -59
- package/dist/features/search/schemas/index.d.ts +0 -70
- package/dist/features/search/schemas/index.js +0 -36
- package/dist/features/search/types/index.d.ts +0 -48
- package/dist/features/seller/components/SellerStoreView.d.ts +0 -8
- package/dist/features/seller/components/SellerStoreView.js +0 -8
- package/dist/features/stores/components/StoreScopedSearch.d.ts +0 -17
- package/dist/features/stores/components/StoreScopedSearch.js +0 -27
- package/dist/seed/defaults/homepage-sections.d.ts +0 -2
- package/dist/seed/defaults/homepage-sections.js +0 -60
- package/dist/seed/factories/homepage-section.factory.d.ts +0 -10
- package/dist/seed/factories/homepage-section.factory.js +0 -13
- /package/dist/{features/search/types/index.js → _internal/shared/listing-types/spares/og.d.ts} +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provenance signals on uploaded imagery — plan A7.
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 A FLAG, never a rejection
|
|
5
|
+
*
|
|
6
|
+
* Nothing here blocks an upload or hides a listing. Every signal is recorded
|
|
7
|
+
* on the `mediaAssets` row for a human to look at, because every one of them
|
|
8
|
+
* has a legitimate explanation: a seller may genuinely own the Amazon listing
|
|
9
|
+
* the photo came from, and an AI-generated image is a reasonable choice for an
|
|
10
|
+
* art listing's mock-up. Auto-rejecting on a heuristic means refusing honest
|
|
11
|
+
* sellers on a filename.
|
|
12
|
+
*
|
|
13
|
+
* ## What is grounded in measurement
|
|
14
|
+
*
|
|
15
|
+
* From the fifteen-site competitor crawl
|
|
16
|
+
* (`docs/research/competitor-crawl-2026-10/images.md`):
|
|
17
|
+
*
|
|
18
|
+
* bladekingbeys — **138 images named with Amazon's CDN pattern**
|
|
19
|
+
* (`..._AC_SL1500_.jpg`) plus `ChatGPT-Image-*.png` files.
|
|
20
|
+
* A storefront built from other people's product shots.
|
|
21
|
+
*
|
|
22
|
+
* ## 🛑 What is deliberately NOT a signal
|
|
23
|
+
*
|
|
24
|
+
* `rn-image_picker_lib_temp_*` (React Native's image picker) and
|
|
25
|
+
* `WhatsApp-Image-*` are what REAL sellers' uploads look like — measured,
|
|
26
|
+
* toycollectorsindia and beyyuniverse upload exactly that way, and
|
|
27
|
+
* beyyuniverse's entire catalogue is `WhatsApp-Image-*.jpeg`. Flagging them
|
|
28
|
+
* would put a flag on nearly every honest phone upload, which trains
|
|
29
|
+
* moderators to dismiss the queue — and a queue nobody reads is worse than no
|
|
30
|
+
* queue, because it looks like oversight.
|
|
31
|
+
*
|
|
32
|
+
* That asymmetry is the whole design: flag the patterns that indicate the
|
|
33
|
+
* image came from someone ELSE'S listing, never the ones that merely indicate
|
|
34
|
+
* it came from a phone.
|
|
35
|
+
*/
|
|
36
|
+
/** One recorded provenance concern. Stable strings — they are persisted. */
|
|
37
|
+
export declare const MEDIA_TRUST_FLAG: {
|
|
38
|
+
/** Filename carries Amazon's CDN size suffix, e.g. `..._AC_SL1500_.jpg`. */
|
|
39
|
+
readonly AMAZON_CDN_FILENAME: "amazon-cdn-filename";
|
|
40
|
+
/** Filename is an AI image generator's default output name. */
|
|
41
|
+
readonly AI_GENERATED_FILENAME: "ai-generated-filename";
|
|
42
|
+
/**
|
|
43
|
+
* Byte-level near-duplicate of an image a DIFFERENT uploader already has.
|
|
44
|
+
*
|
|
45
|
+
* Same-uploader duplicates are normal and are NOT flagged — a seller
|
|
46
|
+
* reusing one photo across their own variants is ordinary behaviour.
|
|
47
|
+
*/
|
|
48
|
+
readonly CROSS_SELLER_DUPLICATE: "cross-seller-duplicate";
|
|
49
|
+
};
|
|
50
|
+
export type MediaTrustFlag = (typeof MEDIA_TRUST_FLAG)[keyof typeof MEDIA_TRUST_FLAG];
|
|
51
|
+
/**
|
|
52
|
+
* Provenance flags derivable from the filename alone.
|
|
53
|
+
*
|
|
54
|
+
* Takes the ORIGINAL client filename, not the storage path — our own paths are
|
|
55
|
+
* content-derived slugs (§ Media Filename Slug Patterns) and carry none of
|
|
56
|
+
* this.
|
|
57
|
+
*/
|
|
58
|
+
export declare function filenameTrustFlags(originalFilename: string | undefined | null): MediaTrustFlag[];
|
|
59
|
+
/**
|
|
60
|
+
* Hamming distance between two hex dHashes — the number of differing bits.
|
|
61
|
+
*
|
|
62
|
+
* 0 is byte-identical-after-downscale; under ~5 is "the same photograph,
|
|
63
|
+
* re-encoded or lightly cropped". Returns `null` when the two cannot be
|
|
64
|
+
* compared (different lengths, non-hex), because a fabricated distance would
|
|
65
|
+
* feed a flag.
|
|
66
|
+
*/
|
|
67
|
+
export declare function dHashDistance(a: string | undefined, b: string | undefined): number | null;
|
|
68
|
+
/**
|
|
69
|
+
* How close two dHashes must be to count as the same photograph.
|
|
70
|
+
*
|
|
71
|
+
* 🛑 Deliberately TIGHT, and the number comes from measurement rather than
|
|
72
|
+
* from the usual "distance < 10" folklore. Against one real catalogue image:
|
|
73
|
+
*
|
|
74
|
+
* resized to 220px wide -> 0
|
|
75
|
+
* re-encoded jpeg q55 -> 3
|
|
76
|
+
* a DIFFERENT bey -> 9
|
|
77
|
+
*
|
|
78
|
+
* So the usable gap is 3-vs-9, which is real but not generous: product
|
|
79
|
+
* photography is self-similar (same item class, same white background, same
|
|
80
|
+
* angle), so a loose threshold here is a flag GENERATOR rather than a signal,
|
|
81
|
+
* and a queue full of false flags is worse than no queue because it looks like
|
|
82
|
+
* oversight. 5 sits above the re-encode and well below the different-item
|
|
83
|
+
* case.
|
|
84
|
+
*/
|
|
85
|
+
export declare const DHASH_DUPLICATE_MAX_DISTANCE = 5;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provenance signals on uploaded imagery — plan A7.
|
|
3
|
+
*
|
|
4
|
+
* ## 🛑 A FLAG, never a rejection
|
|
5
|
+
*
|
|
6
|
+
* Nothing here blocks an upload or hides a listing. Every signal is recorded
|
|
7
|
+
* on the `mediaAssets` row for a human to look at, because every one of them
|
|
8
|
+
* has a legitimate explanation: a seller may genuinely own the Amazon listing
|
|
9
|
+
* the photo came from, and an AI-generated image is a reasonable choice for an
|
|
10
|
+
* art listing's mock-up. Auto-rejecting on a heuristic means refusing honest
|
|
11
|
+
* sellers on a filename.
|
|
12
|
+
*
|
|
13
|
+
* ## What is grounded in measurement
|
|
14
|
+
*
|
|
15
|
+
* From the fifteen-site competitor crawl
|
|
16
|
+
* (`docs/research/competitor-crawl-2026-10/images.md`):
|
|
17
|
+
*
|
|
18
|
+
* bladekingbeys — **138 images named with Amazon's CDN pattern**
|
|
19
|
+
* (`..._AC_SL1500_.jpg`) plus `ChatGPT-Image-*.png` files.
|
|
20
|
+
* A storefront built from other people's product shots.
|
|
21
|
+
*
|
|
22
|
+
* ## 🛑 What is deliberately NOT a signal
|
|
23
|
+
*
|
|
24
|
+
* `rn-image_picker_lib_temp_*` (React Native's image picker) and
|
|
25
|
+
* `WhatsApp-Image-*` are what REAL sellers' uploads look like — measured,
|
|
26
|
+
* toycollectorsindia and beyyuniverse upload exactly that way, and
|
|
27
|
+
* beyyuniverse's entire catalogue is `WhatsApp-Image-*.jpeg`. Flagging them
|
|
28
|
+
* would put a flag on nearly every honest phone upload, which trains
|
|
29
|
+
* moderators to dismiss the queue — and a queue nobody reads is worse than no
|
|
30
|
+
* queue, because it looks like oversight.
|
|
31
|
+
*
|
|
32
|
+
* That asymmetry is the whole design: flag the patterns that indicate the
|
|
33
|
+
* image came from someone ELSE'S listing, never the ones that merely indicate
|
|
34
|
+
* it came from a phone.
|
|
35
|
+
*/
|
|
36
|
+
/** One recorded provenance concern. Stable strings — they are persisted. */
|
|
37
|
+
export const MEDIA_TRUST_FLAG = {
|
|
38
|
+
/** Filename carries Amazon's CDN size suffix, e.g. `..._AC_SL1500_.jpg`. */
|
|
39
|
+
AMAZON_CDN_FILENAME: "amazon-cdn-filename",
|
|
40
|
+
/** Filename is an AI image generator's default output name. */
|
|
41
|
+
AI_GENERATED_FILENAME: "ai-generated-filename",
|
|
42
|
+
/**
|
|
43
|
+
* Byte-level near-duplicate of an image a DIFFERENT uploader already has.
|
|
44
|
+
*
|
|
45
|
+
* Same-uploader duplicates are normal and are NOT flagged — a seller
|
|
46
|
+
* reusing one photo across their own variants is ordinary behaviour.
|
|
47
|
+
*/
|
|
48
|
+
CROSS_SELLER_DUPLICATE: "cross-seller-duplicate",
|
|
49
|
+
};
|
|
50
|
+
/*
|
|
51
|
+
* `_AC_` is Amazon's image-transform marker and `_SL<digits>_` its size
|
|
52
|
+
* directive; together they are unmistakable and do not occur in ordinary
|
|
53
|
+
* filenames. Matching `_AC_` alone would false-positive on anything with those
|
|
54
|
+
* letters between underscores.
|
|
55
|
+
*/
|
|
56
|
+
const AMAZON_CDN_RX = /_AC_[A-Z]{0,4}\d*_|_SL\d{3,4}_/;
|
|
57
|
+
/*
|
|
58
|
+
* Default output names from the common generators. Anchored to the START so a
|
|
59
|
+
* seller who writes "chatgpt-image-of-my-bey.jpg" by hand is not caught by a
|
|
60
|
+
* substring — the signal is "this is the tool's untouched default", not "the
|
|
61
|
+
* word appears".
|
|
62
|
+
*/
|
|
63
|
+
const AI_FILENAME_RX = /^(?:chatgpt-image-|dall[·e-]*e-|midjourney_|stable-?diffusion-|gemini-generated-image)/i;
|
|
64
|
+
/**
|
|
65
|
+
* Provenance flags derivable from the filename alone.
|
|
66
|
+
*
|
|
67
|
+
* Takes the ORIGINAL client filename, not the storage path — our own paths are
|
|
68
|
+
* content-derived slugs (§ Media Filename Slug Patterns) and carry none of
|
|
69
|
+
* this.
|
|
70
|
+
*/
|
|
71
|
+
export function filenameTrustFlags(originalFilename) {
|
|
72
|
+
if (!originalFilename)
|
|
73
|
+
return [];
|
|
74
|
+
const name = originalFilename.trim();
|
|
75
|
+
if (!name)
|
|
76
|
+
return [];
|
|
77
|
+
const flags = [];
|
|
78
|
+
if (AMAZON_CDN_RX.test(name))
|
|
79
|
+
flags.push(MEDIA_TRUST_FLAG.AMAZON_CDN_FILENAME);
|
|
80
|
+
if (AI_FILENAME_RX.test(name))
|
|
81
|
+
flags.push(MEDIA_TRUST_FLAG.AI_GENERATED_FILENAME);
|
|
82
|
+
return flags;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Hamming distance between two hex dHashes — the number of differing bits.
|
|
86
|
+
*
|
|
87
|
+
* 0 is byte-identical-after-downscale; under ~5 is "the same photograph,
|
|
88
|
+
* re-encoded or lightly cropped". Returns `null` when the two cannot be
|
|
89
|
+
* compared (different lengths, non-hex), because a fabricated distance would
|
|
90
|
+
* feed a flag.
|
|
91
|
+
*/
|
|
92
|
+
export function dHashDistance(a, b) {
|
|
93
|
+
if (!a || !b || a.length !== b.length)
|
|
94
|
+
return null;
|
|
95
|
+
let distance = 0;
|
|
96
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
97
|
+
const x = Number.parseInt(a[i], 16);
|
|
98
|
+
const y = Number.parseInt(b[i], 16);
|
|
99
|
+
if (Number.isNaN(x) || Number.isNaN(y))
|
|
100
|
+
return null;
|
|
101
|
+
let diff = x ^ y;
|
|
102
|
+
while (diff) {
|
|
103
|
+
distance += diff & 1;
|
|
104
|
+
diff >>= 1;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return distance;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* How close two dHashes must be to count as the same photograph.
|
|
111
|
+
*
|
|
112
|
+
* 🛑 Deliberately TIGHT, and the number comes from measurement rather than
|
|
113
|
+
* from the usual "distance < 10" folklore. Against one real catalogue image:
|
|
114
|
+
*
|
|
115
|
+
* resized to 220px wide -> 0
|
|
116
|
+
* re-encoded jpeg q55 -> 3
|
|
117
|
+
* a DIFFERENT bey -> 9
|
|
118
|
+
*
|
|
119
|
+
* So the usable gap is 3-vs-9, which is real but not generous: product
|
|
120
|
+
* photography is self-similar (same item class, same white background, same
|
|
121
|
+
* angle), so a loose threshold here is a flag GENERATOR rather than a signal,
|
|
122
|
+
* and a queue full of false flags is worse than no queue because it looks like
|
|
123
|
+
* oversight. 5 sits above the re-encode and well below the different-item
|
|
124
|
+
* case.
|
|
125
|
+
*/
|
|
126
|
+
export const DHASH_DUPLICATE_MAX_DISTANCE = 5;
|
|
@@ -9,7 +9,22 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
import { useEffect, useState } from "react";
|
|
10
10
|
import { useTranslations } from "next-intl";
|
|
11
11
|
import { useCamera } from "../../../react/index.js";
|
|
12
|
-
|
|
12
|
+
/*
|
|
13
|
+
* Defining modules, not the `ui` barrel — Root Cause #18.
|
|
14
|
+
*
|
|
15
|
+
* `ui/index.ts` re-exports `FormField`, `PaginatedSelect` and
|
|
16
|
+
* `RecordDetailModal`, and those three import back INTO `features/media` and
|
|
17
|
+
* `features/shell`. So reaching a primitive through the barrel closed a
|
|
18
|
+
* ten-module cycle (`audit-import-cycles` component 1) — while the deep paths
|
|
19
|
+
* below have one direction only. `ui → features/media` is the real dependency
|
|
20
|
+
* and it stays; the barrel hop is what did not need to exist.
|
|
21
|
+
*/
|
|
22
|
+
import { Alert } from "../../../ui/components/Alert.js";
|
|
23
|
+
import { Button } from "../../../ui/components/Button.js";
|
|
24
|
+
import { Div } from "../../../ui/components/Div.js";
|
|
25
|
+
import { Row, Stack } from "../../../ui/components/Layout.js";
|
|
26
|
+
import { Spinner } from "../../../ui/components/Spinner.js";
|
|
27
|
+
import { Span } from "../../../ui/components/Typography.js";
|
|
13
28
|
export default function CameraCapture({ mode, facingMode = "environment", onCapture, onError, className, }) {
|
|
14
29
|
const t = useTranslations("camera");
|
|
15
30
|
const camera = useCamera();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { IMAGE_ACCEPT_ATTR } from "../../../_internal/shared/media/limits.js";
|
|
3
|
+
import { IMAGE_ACCEPT_ATTR, MAX_IMAGE_BYTES, MEGABYTE, } from "../../../_internal/shared/media/limits.js";
|
|
4
|
+
import { downscaleImageFile } from "./downscale-image.js";
|
|
4
5
|
import { normalizeError } from "../../../errors/normalize.js";
|
|
5
6
|
/**
|
|
6
7
|
* ImageUpload — canonical image upload component for @mohasinac/feat-media.
|
|
@@ -13,7 +14,24 @@ import { useState, useRef } from "react";
|
|
|
13
14
|
import dynamic from "next/dynamic.js";
|
|
14
15
|
import { useTranslations } from "next-intl";
|
|
15
16
|
import { useCamera } from "../../../react/index.js";
|
|
16
|
-
|
|
17
|
+
/*
|
|
18
|
+
* Defining modules, not the `ui` barrel — Root Cause #18.
|
|
19
|
+
*
|
|
20
|
+
* `ui/index.ts` re-exports `FormField`, `PaginatedSelect` and
|
|
21
|
+
* `RecordDetailModal`, and those three import back INTO `features/media` and
|
|
22
|
+
* `features/shell`. So reaching a primitive through the barrel closed a
|
|
23
|
+
* ten-module cycle (`audit-import-cycles` component 1) — while the deep paths
|
|
24
|
+
* below have one direction only. `ui → features/media` is the real dependency
|
|
25
|
+
* and it stays; the barrel hop is what did not need to exist.
|
|
26
|
+
*/
|
|
27
|
+
import { Alert } from "../../../ui/components/Alert.js";
|
|
28
|
+
import { Button } from "../../../ui/components/Button.js";
|
|
29
|
+
import { Div } from "../../../ui/components/Div.js";
|
|
30
|
+
import { Row, Stack } from "../../../ui/components/Layout.js";
|
|
31
|
+
import { Progress } from "../../../ui/components/Progress.js";
|
|
32
|
+
import { Spinner } from "../../../ui/components/Spinner.js";
|
|
33
|
+
import { Label, Text } from "../../../ui/components/Typography.js";
|
|
34
|
+
import { useToast } from "../../../ui/components/toast-context.js";
|
|
17
35
|
import { MediaImage } from "../MediaImage.js";
|
|
18
36
|
import CameraCapture from "./CameraCapture.js";
|
|
19
37
|
// Crop/editor modals pull in image-manipulation libraries (react-advanced-cropper
|
|
@@ -40,7 +58,12 @@ function matchesMimeAccept(fileType, accept) {
|
|
|
40
58
|
return pSub === "*" || pSub === fSub;
|
|
41
59
|
});
|
|
42
60
|
}
|
|
43
|
-
export function ImageUpload({ currentImage, onUpload, onChange,
|
|
61
|
+
export function ImageUpload({ currentImage, onUpload, onChange,
|
|
62
|
+
// 🛑 Never `image/*` — that wildcard matches `image/svg+xml`, which
|
|
63
|
+
// `ALLOWED_IMAGE_MIMES` deliberately excludes as an XSS surface and which the
|
|
64
|
+
// server 422s only after the crop editor has already opened on it. See
|
|
65
|
+
// `IMAGE_ACCEPT_ATTR`'s own docstring in `_internal/shared/media/limits.ts`.
|
|
66
|
+
accept = IMAGE_ACCEPT_ATTR, maxSizeMB = MAX_IMAGE_BYTES / MEGABYTE, label = "Upload Image", helperText, captureSource = "both", enableCrop = true, enableAdvancedCrop = false, cropAspectRatio, onCropDataChange, }) {
|
|
44
67
|
const [uploading, setUploading] = useState(false);
|
|
45
68
|
const [preview, setPreview] = useState(currentImage || "");
|
|
46
69
|
const [error, setError] = useState("");
|
|
@@ -65,7 +88,22 @@ export function ImageUpload({ currentImage, onUpload, onChange, accept = "image/
|
|
|
65
88
|
try {
|
|
66
89
|
setUploading(true);
|
|
67
90
|
setProgress(30);
|
|
68
|
-
|
|
91
|
+
/*
|
|
92
|
+
* The single choke point for all six upload paths (direct, crop-save,
|
|
93
|
+
* crop-close, advanced-save, advanced-close, camera), so bounding the
|
|
94
|
+
* master here covers every one.
|
|
95
|
+
*
|
|
96
|
+
* 🛑 Safe to apply even when `cropData` is present: `ImageCropData` is
|
|
97
|
+
* `{ position, zoom }` in CSS PERCENTAGES — the modal's own header says
|
|
98
|
+
* "Returns CSS position/zoom percentages" and applies them as
|
|
99
|
+
* `left: ${position.x}%` — so it is scale-invariant and a uniform
|
|
100
|
+
* downscale cannot misalign a crop. Pixel-rect crop data would not be.
|
|
101
|
+
*
|
|
102
|
+
* A file already produced by `ImageEditor` comes back untouched (it is
|
|
103
|
+
* webp within 2048 already), so there is no double re-encode.
|
|
104
|
+
*/
|
|
105
|
+
const prepared = await downscaleImageFile(file);
|
|
106
|
+
const url = await onUpload(prepared);
|
|
69
107
|
setProgress(100);
|
|
70
108
|
setPreview(url);
|
|
71
109
|
onChange?.(url);
|
|
@@ -9,14 +9,32 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
9
9
|
import { useState, useRef, useEffect } from "react";
|
|
10
10
|
import { useTranslations } from "next-intl";
|
|
11
11
|
import { useCamera } from "../../../react/index.js";
|
|
12
|
-
|
|
12
|
+
/*
|
|
13
|
+
* Defining modules, not the `ui` barrel — Root Cause #18.
|
|
14
|
+
*
|
|
15
|
+
* `ui/index.ts` re-exports `FormField`, `PaginatedSelect` and
|
|
16
|
+
* `RecordDetailModal`, and those three import back INTO `features/media` and
|
|
17
|
+
* `features/shell`. So reaching a primitive through the barrel closed a
|
|
18
|
+
* ten-module cycle (`audit-import-cycles` component 1) — while the deep paths
|
|
19
|
+
* below have one direction only. `ui → features/media` is the real dependency
|
|
20
|
+
* and it stays; the barrel hop is what did not need to exist.
|
|
21
|
+
*/
|
|
22
|
+
import { Alert } from "../../../ui/components/Alert.js";
|
|
23
|
+
import { Anchor } from "../../../ui/components/Anchor.js";
|
|
24
|
+
import { Button } from "../../../ui/components/Button.js";
|
|
25
|
+
import { Div } from "../../../ui/components/Div.js";
|
|
26
|
+
import { Row, Stack } from "../../../ui/components/Layout.js";
|
|
27
|
+
import { Spinner } from "../../../ui/components/Spinner.js";
|
|
28
|
+
import { Label, Span, Text } from "../../../ui/components/Typography.js";
|
|
13
29
|
import { MediaImage } from "../MediaImage.js";
|
|
14
30
|
import { MediaVideo } from "../MediaVideo.js";
|
|
15
31
|
import dynamic from "next/dynamic.js";
|
|
16
32
|
import { VideoThumbnailSelector } from "../modals/VideoThumbnailSelector.js";
|
|
17
33
|
import CameraCapture from "./CameraCapture.js";
|
|
18
34
|
import { extractVideoPosterFrame, posterBlobAsFile } from "./video-poster.js";
|
|
35
|
+
import { downscaleImageFile } from "./downscale-image.js";
|
|
19
36
|
import { inferMediaTypeFromMime } from "../types/index.js";
|
|
37
|
+
import { ALLOWED_DOC_MIMES, ALLOWED_MIMES, ALLOWED_VIDEO_MIMES, IMAGE_ACCEPT_ATTR, MAX_IMAGE_BYTES, MAX_PDF_BYTES, MAX_VIDEO_BYTES, MEGABYTE, } from "../../../_internal/shared/media/limits.js";
|
|
20
38
|
import { normalizeError } from "../../../errors/normalize.js";
|
|
21
39
|
// Pulls in video-processing libraries most upload sessions never touch —
|
|
22
40
|
// lazy-load rather than bundle into every page rendering a MediaUploadField.
|
|
@@ -24,14 +42,35 @@ const VideoTrimModal = dynamic(() => import("../modals/VideoTrimModal.js").then(
|
|
|
24
42
|
const CLS_PDF_BADGE = "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-error-surface text-error dark:bg-error-surface dark:text-error";
|
|
25
43
|
const CLS_PDF_NAME = "text-[length:var(--appkit-text-sm)] font-medium text-info underline break-all dark:text-info";
|
|
26
44
|
const CLS_PDF_LINK = "text-[length:var(--appkit-text-sm)] underline break-all text-info dark:text-info";
|
|
45
|
+
/*
|
|
46
|
+
* 🛑 DERIVED from the canonical registry, not restated.
|
|
47
|
+
*
|
|
48
|
+
* The `kind` docstring above has always claimed these "auto-derive … from the
|
|
49
|
+
* canonical media-limits registry". They did not — they were hand-written, and
|
|
50
|
+
* every one of them was MORE PERMISSIVE than the server, which enforces
|
|
51
|
+
* `MAX_BYTES[kind]` in BOTH `/api/media/sign` and `/api/media/finalize`. So the
|
|
52
|
+
* picker accepted work the upload could never complete:
|
|
53
|
+
*
|
|
54
|
+
* image 25 MB → server 10 MB
|
|
55
|
+
* video 200 MB → server 50 MB
|
|
56
|
+
* accept "image/*" → matches `image/svg+xml`, which `ALLOWED_IMAGE_MIMES`
|
|
57
|
+
* deliberately excludes as an XSS surface, and which the
|
|
58
|
+
* server 422s only AFTER the crop editor has opened on it
|
|
59
|
+
* (limits.ts's own `IMAGE_ACCEPT_ATTR` docstring).
|
|
60
|
+
*
|
|
61
|
+
* Deriving makes the refusal happen in the file picker, where it is a rule,
|
|
62
|
+
* rather than at the end, where it reads as a failure.
|
|
63
|
+
*/
|
|
27
64
|
const KIND_DEFAULTS = {
|
|
28
|
-
image: { accept:
|
|
29
|
-
video: { accept: "
|
|
30
|
-
pdf: { accept: "
|
|
65
|
+
image: { accept: IMAGE_ACCEPT_ATTR, maxSizeMB: MAX_IMAGE_BYTES / MEGABYTE },
|
|
66
|
+
video: { accept: ALLOWED_VIDEO_MIMES.join(","), maxSizeMB: MAX_VIDEO_BYTES / MEGABYTE },
|
|
67
|
+
pdf: { accept: ALLOWED_DOC_MIMES.join(","), maxSizeMB: MAX_PDF_BYTES / MEGABYTE },
|
|
31
68
|
};
|
|
32
69
|
const AUTO_KIND_DEFAULTS = {
|
|
33
|
-
accept: "
|
|
34
|
-
|
|
70
|
+
accept: ALLOWED_MIMES.join(","),
|
|
71
|
+
// The most permissive of the three, because `auto` genuinely does not know
|
|
72
|
+
// the kind yet — the per-kind cap is re-checked server-side once it does.
|
|
73
|
+
maxSizeMB: Math.max(MAX_IMAGE_BYTES, MAX_VIDEO_BYTES, MAX_PDF_BYTES) / MEGABYTE,
|
|
35
74
|
};
|
|
36
75
|
function isVideo(url) {
|
|
37
76
|
return /\.(mp4|webm|ogg|mov|avi)(\?|$)/i.test(url);
|
|
@@ -277,14 +316,24 @@ kind, accept: acceptProp, maxSizeMB: maxSizeMBProp, disabled = false, helperText
|
|
|
277
316
|
setPendingVideoUrl(null);
|
|
278
317
|
};
|
|
279
318
|
const uploadSingleFile = async (file) => {
|
|
280
|
-
|
|
319
|
+
/*
|
|
320
|
+
* Bound the pixel dimensions BEFORE the byte check, deliberately.
|
|
321
|
+
*
|
|
322
|
+
* The cap is about what we STORE, and a 9 MB phone photo becomes a few
|
|
323
|
+
* hundred KB here — so checking first would refuse an upload we were about
|
|
324
|
+
* to make acceptable. Non-images and anything undecodable come back
|
|
325
|
+
* untouched (see `downscale-image.ts`), so the check below still does its
|
|
326
|
+
* job for video and PDF.
|
|
327
|
+
*/
|
|
328
|
+
const prepared = await downscaleImageFile(file);
|
|
329
|
+
const fileSizeMB = prepared.size / 1024 / 1024;
|
|
281
330
|
if (fileSizeMB > maxSizeMB) {
|
|
282
|
-
setError(`${
|
|
331
|
+
setError(`${prepared.name}: exceeds ${maxSizeMB}MB limit`);
|
|
283
332
|
return null;
|
|
284
333
|
}
|
|
285
|
-
const url = await onUpload(
|
|
334
|
+
const url = await onUpload(prepared);
|
|
286
335
|
stageUrl(url);
|
|
287
|
-
return { url, type:
|
|
336
|
+
return { url, type: prepared.type };
|
|
288
337
|
};
|
|
289
338
|
/**
|
|
290
339
|
* Client-side first-frame extraction for video uploads. Runs after the
|
|
@@ -373,10 +422,17 @@ kind, accept: acceptProp, maxSizeMB: maxSizeMBProp, disabled = false, helperText
|
|
|
373
422
|
setError(null);
|
|
374
423
|
setIsLoading(true);
|
|
375
424
|
try {
|
|
376
|
-
|
|
377
|
-
|
|
425
|
+
/*
|
|
426
|
+
* Routed through `uploadSingleFile` rather than calling `onUpload`
|
|
427
|
+
* directly, which is what this did until 2026-10-19 — so a camera capture
|
|
428
|
+
* skipped BOTH the `maxSizeMB` check and (once added) the downscale. A
|
|
429
|
+
* full-sensor capture is precisely the large image both exist for.
|
|
430
|
+
*/
|
|
431
|
+
const result = await uploadSingleFile(file);
|
|
432
|
+
if (!result)
|
|
433
|
+
return;
|
|
378
434
|
const poster = await maybeCaptureVideoPoster(file);
|
|
379
|
-
afterUpload(url,
|
|
435
|
+
afterUpload(result.url, result.type, poster?.posterUrl, poster?.duration);
|
|
380
436
|
}
|
|
381
437
|
catch (err) {
|
|
382
438
|
void normalizeError(err);
|
|
@@ -0,0 +1,56 @@
|
|
|
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
|
+
/** Longest edge, in CSS pixels, of the stored master. */
|
|
43
|
+
export declare const IMAGE_DOWNSCALE_MAX_EDGE = 2048;
|
|
44
|
+
/** Output MIME for a re-encoded master. */
|
|
45
|
+
export declare const IMAGE_DOWNSCALE_FORMAT = "image/webp";
|
|
46
|
+
/** Output quality for a re-encoded master. */
|
|
47
|
+
export declare const IMAGE_DOWNSCALE_QUALITY = 0.9;
|
|
48
|
+
export interface DownscaleImageOptions {
|
|
49
|
+
/** Longest edge of the output. Default `IMAGE_DOWNSCALE_MAX_EDGE`. */
|
|
50
|
+
maxEdge?: number;
|
|
51
|
+
/** Output MIME. Default `IMAGE_DOWNSCALE_FORMAT`. */
|
|
52
|
+
format?: string;
|
|
53
|
+
/** Output quality, 0..1. Default `IMAGE_DOWNSCALE_QUALITY`. */
|
|
54
|
+
quality?: number;
|
|
55
|
+
}
|
|
56
|
+
export declare function downscaleImageFile(file: File, options?: DownscaleImageOptions): Promise<File>;
|
|
@@ -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
|
+
}
|