@mohasinac/appkit 4.13.1 → 4.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (493) hide show
  1. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +14 -5
  2. package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +3 -0
  3. package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +6 -0
  4. package/dist/_internal/client/features/lottery/LotteryDetailView.d.ts +8 -0
  5. package/dist/_internal/client/features/lottery/LotteryDetailView.js +4 -1
  6. package/dist/_internal/client/features/lottery/LotteryListView.d.ts +7 -0
  7. package/dist/_internal/client/features/lottery/LotteryListView.js +1 -1
  8. package/dist/_internal/client/features/lottery/PrizeDrawLotteryDetailView.js +4 -1
  9. package/dist/_internal/client/features/lottery/slot-collage-items.d.ts +15 -0
  10. package/dist/_internal/client/features/lottery/slot-collage-items.js +13 -0
  11. package/dist/_internal/server/features/auctions/actions.js +8 -2
  12. package/dist/_internal/server/features/bundles/data.d.ts +16 -0
  13. package/dist/_internal/server/features/bundles/data.js +26 -0
  14. package/dist/_internal/server/features/bundles/index.d.ts +1 -1
  15. package/dist/_internal/server/features/bundles/index.js +1 -1
  16. package/dist/_internal/server/features/cart/service.d.ts +3 -3
  17. package/dist/_internal/server/features/checkout/actions.js +25 -0
  18. package/dist/_internal/server/features/checkout/locked-lines.d.ts +38 -0
  19. package/dist/_internal/server/features/checkout/locked-lines.js +171 -0
  20. package/dist/_internal/server/features/checkout/source-context.d.ts +5 -0
  21. package/dist/_internal/server/features/checkout/source-context.js +157 -0
  22. package/dist/_internal/server/features/homepage/index.d.ts +0 -1
  23. package/dist/_internal/server/features/homepage/index.js +7 -1
  24. package/dist/_internal/server/features/lottery/adapters.js +4 -0
  25. package/dist/_internal/server/features/offers/adapters.d.ts +103 -0
  26. package/dist/_internal/server/features/offers/adapters.js +88 -0
  27. package/dist/_internal/server/features/offers/index.d.ts +2 -0
  28. package/dist/_internal/server/features/offers/index.js +1 -0
  29. package/dist/_internal/server/features/orders/adapters.js +24 -0
  30. package/dist/_internal/server/features/products/data.js +15 -37
  31. package/dist/_internal/server/features/products/index.d.ts +1 -1
  32. package/dist/_internal/server/features/products/index.js +1 -1
  33. package/dist/_internal/server/features/products/list-public.d.ts +46 -20
  34. package/dist/_internal/server/features/products/list-public.js +266 -90
  35. package/dist/_internal/server/features/products/listing-tab-counts.d.ts +44 -0
  36. package/dist/_internal/server/features/products/listing-tab-counts.js +97 -0
  37. package/dist/_internal/server/features/site-settings/adapters.d.ts +51 -0
  38. package/dist/_internal/server/features/site-settings/adapters.js +75 -0
  39. package/dist/_internal/server/features/site-settings/index.d.ts +1 -0
  40. package/dist/_internal/server/features/site-settings/index.js +1 -0
  41. package/dist/_internal/server/features/stores/adapters.d.ts +56 -0
  42. package/dist/_internal/server/features/stores/adapters.js +91 -0
  43. package/dist/_internal/server/features/stores/index.d.ts +1 -0
  44. package/dist/_internal/server/features/stores/index.js +1 -0
  45. package/dist/_internal/server/jobs/core/auctionSettlement.js +56 -2
  46. package/dist/_internal/server/jobs/core/offerExpiry.js +55 -19
  47. package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.d.ts +5 -0
  48. package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.js +33 -1
  49. package/dist/_internal/server/jobs/handlers/messages.d.ts +7 -0
  50. package/dist/_internal/server/jobs/handlers/messages.js +10 -0
  51. package/dist/_internal/shared/actions/action-registry.js +17 -1
  52. package/dist/_internal/shared/checkout/lanes.d.ts +25 -0
  53. package/dist/_internal/shared/checkout/lanes.js +26 -0
  54. package/dist/_internal/shared/features/auctions/config.d.ts +27 -0
  55. package/dist/_internal/shared/features/auctions/config.js +27 -0
  56. package/dist/_internal/shared/features/auctions/schema.d.ts +14 -2
  57. package/dist/_internal/shared/features/auctions/schema.js +13 -1
  58. package/dist/_internal/shared/features/blog/schema.d.ts +2 -2
  59. package/dist/_internal/shared/features/cart/schema.d.ts +20 -15
  60. package/dist/_internal/shared/features/cart/schema.js +15 -0
  61. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +32 -32
  62. package/dist/_internal/shared/features/emi/schedule.d.ts +24 -3
  63. package/dist/_internal/shared/features/emi/schedule.js +20 -5
  64. package/dist/_internal/shared/features/events/schema.d.ts +2 -2
  65. package/dist/_internal/shared/features/homepage/section-gate.d.ts +14 -0
  66. package/dist/_internal/shared/features/homepage/section-gate.js +51 -0
  67. package/dist/_internal/shared/features/offers/config.d.ts +30 -0
  68. package/dist/_internal/shared/features/offers/config.js +59 -0
  69. package/dist/_internal/shared/features/orders/schema.d.ts +8 -8
  70. package/dist/_internal/shared/features/products/schema.d.ts +30 -30
  71. package/dist/_internal/shared/features/products/to-product-item.js +6 -0
  72. package/dist/_internal/shared/features/reviews/schema.d.ts +2 -2
  73. package/dist/_internal/shared/features/site-settings/fees.d.ts +60 -0
  74. package/dist/_internal/shared/features/site-settings/fees.js +39 -0
  75. package/dist/_internal/shared/features/site-settings/types.d.ts +40 -0
  76. package/dist/_internal/shared/features/site-settings/types.js +1 -0
  77. package/dist/_internal/shared/history/history.d.ts +88 -0
  78. package/dist/_internal/shared/history/history.js +198 -0
  79. package/dist/_internal/shared/history/index.d.ts +4 -0
  80. package/dist/_internal/shared/history/index.js +2 -0
  81. package/dist/_internal/shared/history/types.d.ts +61 -0
  82. package/dist/_internal/shared/history/types.js +6 -0
  83. package/dist/_internal/shared/listing-types/_registry.d.ts +54 -1
  84. package/dist/_internal/shared/listing-types/_registry.js +67 -0
  85. package/dist/_internal/shared/listing-types/art/config.d.ts +3 -0
  86. package/dist/_internal/shared/listing-types/art/config.js +5 -0
  87. package/dist/_internal/shared/listing-types/auction/config.d.ts +13 -0
  88. package/dist/_internal/shared/listing-types/auction/config.js +21 -0
  89. package/dist/_internal/shared/listing-types/availability.d.ts +79 -0
  90. package/dist/_internal/shared/listing-types/availability.js +104 -0
  91. package/dist/_internal/shared/listing-types/capabilities.d.ts +15 -0
  92. package/dist/_internal/shared/listing-types/capabilities.js +12 -0
  93. package/dist/_internal/shared/listing-types/classified/config.d.ts +3 -0
  94. package/dist/_internal/shared/listing-types/classified/config.js +5 -0
  95. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +11 -0
  96. package/dist/_internal/shared/listing-types/digital-code/config.js +22 -2
  97. package/dist/_internal/shared/listing-types/live/config.d.ts +3 -0
  98. package/dist/_internal/shared/listing-types/live/config.js +5 -0
  99. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +3 -0
  100. package/dist/_internal/shared/listing-types/pre-order/config.js +19 -0
  101. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +11 -0
  102. package/dist/_internal/shared/listing-types/prize-draw/config.js +15 -0
  103. package/dist/_internal/shared/listing-types/standard/config.d.ts +3 -0
  104. package/dist/_internal/shared/listing-types/standard/config.js +5 -0
  105. package/dist/_internal/shared/listing-types/stickers/config.d.ts +3 -0
  106. package/dist/_internal/shared/listing-types/stickers/config.js +5 -0
  107. package/dist/client.d.ts +20 -7
  108. package/dist/client.js +22 -4
  109. package/dist/constants/api-endpoints.d.ts +6 -0
  110. package/dist/constants/api-endpoints.js +2 -0
  111. package/dist/constants/field-names.d.ts +57 -8
  112. package/dist/constants/field-names.js +101 -8
  113. package/dist/constants/table-keys.d.ts +17 -0
  114. package/dist/constants/table-keys.js +17 -0
  115. package/dist/errors/error-codes.d.ts +13 -1
  116. package/dist/errors/error-codes.js +13 -1
  117. package/dist/errors/error-display-map.js +12 -3
  118. package/dist/errors/messages.d.ts +10 -2
  119. package/dist/errors/messages.js +10 -2
  120. package/dist/features/about/components/AboutView.d.ts +3 -0
  121. package/dist/features/about/components/AboutView.js +3 -2
  122. package/dist/features/about/components/PolicyPageView.d.ts +2 -1
  123. package/dist/features/about/components/PolicyPageView.js +61 -23
  124. package/dist/features/about/components/PublicProfileView.js +5 -0
  125. package/dist/features/about/schemas/firestore.d.ts +3 -0
  126. package/dist/features/account/components/UserBidsView.js +12 -4
  127. package/dist/features/account/components/UserOrdersView.js +7 -0
  128. package/dist/features/account/components/UserReturnsView.d.ts +3 -0
  129. package/dist/features/account/components/UserReturnsView.js +17 -1
  130. package/dist/features/account/components/index.d.ts +0 -2
  131. package/dist/features/account/components/index.js +0 -1
  132. package/dist/features/account/schemas/index.d.ts +2 -2
  133. package/dist/features/account/types/index.d.ts +21 -2
  134. package/dist/features/addresses/schemas/index.d.ts +4 -4
  135. package/dist/features/admin/components/AdminArtView.js +8 -3
  136. package/dist/features/admin/components/AdminAuditLogView.js +1 -0
  137. package/dist/features/admin/components/AdminBidsView.js +15 -2
  138. package/dist/features/admin/components/AdminBlogEditorView.js +65 -33
  139. package/dist/features/admin/components/AdminClassifiedView.js +8 -3
  140. package/dist/features/admin/components/AdminDigitalCodesView.js +8 -3
  141. package/dist/features/admin/components/AdminFeatureEditorView.js +35 -6
  142. package/dist/features/admin/components/AdminFeatureFlagsView.js +1 -0
  143. package/dist/features/admin/components/AdminLiveView.js +8 -3
  144. package/dist/features/admin/components/AdminNavEditorView.js +15 -5
  145. package/dist/features/admin/components/AdminNewsletterView.js +18 -2
  146. package/dist/features/admin/components/AdminOffersView.d.ts +4 -0
  147. package/dist/features/admin/components/AdminOffersView.js +230 -0
  148. package/dist/features/admin/components/AdminOrdersView.js +10 -1
  149. package/dist/features/admin/components/AdminPaymentMethodsView.js +24 -4
  150. package/dist/features/admin/components/AdminPrizeDrawsView.js +5 -0
  151. package/dist/features/admin/components/AdminProductsView.js +16 -29
  152. package/dist/features/admin/components/AdminScammerEditorView.d.ts +2 -1
  153. package/dist/features/admin/components/AdminScammerEditorView.js +3 -13
  154. package/dist/features/admin/components/AdminScammersView.js +3 -8
  155. package/dist/features/admin/components/AdminSectionsView.js +32 -23
  156. package/dist/features/admin/components/AdminSessionsView.js +17 -2
  157. package/dist/features/admin/components/AdminSiteSettingsView.js +31 -13
  158. package/dist/features/admin/components/AdminSiteView.js +6 -2
  159. package/dist/features/admin/components/AdminStickersView.js +8 -3
  160. package/dist/features/admin/components/ViewAuditLogEntryModal.js +1 -0
  161. package/dist/features/admin/components/index.d.ts +2 -0
  162. package/dist/features/admin/components/index.js +1 -0
  163. package/dist/features/admin/components/sections/adminSectionsTypes.d.ts +4 -2
  164. package/dist/features/admin/components/sections/adminSectionsTypes.js +45 -27
  165. package/dist/features/admin/constants/filter-tabs.d.ts +89 -0
  166. package/dist/features/admin/constants/filter-tabs.js +56 -0
  167. package/dist/features/admin/schemas/firestore.d.ts +122 -3
  168. package/dist/features/admin/schemas/firestore.js +1 -0
  169. package/dist/features/admin/schemas/homepage-section-form.d.ts +22 -0
  170. package/dist/features/admin/schemas/homepage-section-form.js +68 -0
  171. package/dist/features/admin/schemas/nav-item-form.d.ts +74 -0
  172. package/dist/features/admin/schemas/nav-item-form.js +72 -0
  173. package/dist/features/auctions/actions/bid-actions.d.ts +20 -5
  174. package/dist/features/auctions/actions/bid-actions.js +93 -20
  175. package/dist/features/auctions/components/AuctionBidsTable.d.ts +10 -1
  176. package/dist/features/auctions/components/AuctionBidsTable.js +22 -4
  177. package/dist/features/auctions/components/AuctionDetailPageView.js +11 -6
  178. package/dist/features/auctions/components/AuctionsListView.js +5 -6
  179. package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +7 -0
  180. package/dist/features/auctions/components/MarketplaceAuctionCard.js +19 -2
  181. package/dist/features/auctions/components/PlaceBidFormClient.d.ts +1 -2
  182. package/dist/features/auctions/components/PlaceBidFormClient.js +8 -4
  183. package/dist/features/auctions/components/bid-detail-fields.d.ts +29 -0
  184. package/dist/features/auctions/components/bid-detail-fields.js +103 -0
  185. package/dist/features/auctions/repository/bid.repository.d.ts +13 -0
  186. package/dist/features/auctions/repository/bid.repository.js +23 -0
  187. package/dist/features/auctions/schemas/firestore.d.ts +17 -0
  188. package/dist/features/auctions/schemas/index.d.ts +12 -12
  189. package/dist/features/audit-log/schemas/firestore.d.ts +14 -0
  190. package/dist/features/audit-log/schemas/firestore.js +7 -0
  191. package/dist/features/auth/permissions/constants.d.ts +1 -1
  192. package/dist/features/auth/permissions/constants.js +10 -1
  193. package/dist/features/blog/actions/blog-actions.d.ts +7 -7
  194. package/dist/features/blog/schemas/blog-form.d.ts +80 -0
  195. package/dist/features/blog/schemas/blog-form.js +100 -0
  196. package/dist/features/blog/schemas/index.d.ts +6 -6
  197. package/dist/features/cart/repository/cart.repository.js +1 -0
  198. package/dist/features/cart/schemas/firestore.d.ts +15 -0
  199. package/dist/features/catalogue/schemas/validation.d.ts +4 -4
  200. package/dist/features/categories/components/BrandDetailPageView.js +23 -40
  201. package/dist/features/categories/components/BrandDetailTabs.d.ts +7 -7
  202. package/dist/features/categories/components/BrandDetailTabs.js +8 -12
  203. package/dist/features/categories/components/BundleCollage.js +1 -1
  204. package/dist/features/categories/components/CategoryDetailPageView.js +53 -57
  205. package/dist/features/categories/components/CategoryDetailTabs.d.ts +10 -8
  206. package/dist/features/categories/components/CategoryDetailTabs.js +11 -16
  207. package/dist/features/categories/components/CategoryProductsListing.js +11 -1
  208. package/dist/features/categories/components/ConcernCard.js +7 -1
  209. package/dist/features/categories/schemas/firestore.d.ts +13 -0
  210. package/dist/features/categories/schemas/index.d.ts +26 -26
  211. package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +16 -1
  212. package/dist/features/classified/components/ClassifiedDetailPageView.js +23 -3
  213. package/dist/features/events/components/AdminEventEditorView.js +32 -54
  214. package/dist/features/events/components/AdminEventEntriesView.js +22 -3
  215. package/dist/features/events/components/AdminEventsView.js +15 -11
  216. package/dist/features/events/components/EventFilters.d.ts +9 -1
  217. package/dist/features/events/components/EventFilters.js +45 -21
  218. package/dist/features/events/components/EventsIndexListing.d.ts +6 -1
  219. package/dist/features/events/components/EventsIndexListing.js +2 -2
  220. package/dist/features/events/components/EventsListPageView.js +13 -4
  221. package/dist/features/events/repository/events.repository.d.ts +17 -0
  222. package/dist/features/events/repository/events.repository.js +27 -0
  223. package/dist/features/events/schemas/event-form.d.ts +113 -0
  224. package/dist/features/events/schemas/event-form.js +82 -0
  225. package/dist/features/events/schemas/firestore.d.ts +12 -0
  226. package/dist/features/events/schemas/firestore.js +12 -0
  227. package/dist/features/events/schemas/index.d.ts +50 -50
  228. package/dist/features/events/types/index.d.ts +11 -0
  229. package/dist/features/events/types/index.js +57 -1
  230. package/dist/features/faq/actions/faq-actions.d.ts +12 -12
  231. package/dist/features/faq/schemas/index.d.ts +8 -8
  232. package/dist/features/filters/FilterFacetSection.d.ts +7 -1
  233. package/dist/features/filters/FilterFacetSection.js +11 -3
  234. package/dist/features/grouped/schemas/grouped-listing-form.d.ts +101 -0
  235. package/dist/features/grouped/schemas/grouped-listing-form.js +89 -0
  236. package/dist/features/grouped/schemas/index.d.ts +4 -4
  237. package/dist/features/homepage/actions/homepage-section-actions.d.ts +11 -3
  238. package/dist/features/homepage/actions/homepage-section-actions.js +33 -1
  239. package/dist/features/homepage/components/AnnouncementBar.d.ts +7 -1
  240. package/dist/features/homepage/components/AnnouncementBar.js +3 -3
  241. package/dist/features/homepage/components/MarketplaceHomepageView.js +20 -6
  242. package/dist/features/homepage/hooks/homepage-query.d.ts +16 -0
  243. package/dist/features/homepage/hooks/homepage-query.js +45 -0
  244. package/dist/features/homepage/hooks/useFeaturedAuctions.d.ts +10 -0
  245. package/dist/features/homepage/hooks/useFeaturedAuctions.js +28 -8
  246. package/dist/features/homepage/hooks/useFeaturedPreOrders.js +17 -8
  247. package/dist/features/homepage/hooks/useFeaturedProducts.js +15 -8
  248. package/dist/features/homepage/schemas/index.d.ts +33 -2
  249. package/dist/features/homepage/schemas/index.js +24 -0
  250. package/dist/features/layout/AppLayoutShell.d.ts +11 -1
  251. package/dist/features/layout/AppLayoutShell.js +15 -14
  252. package/dist/features/layout/BackToTop.d.ts +9 -0
  253. package/dist/features/layout/BackToTop.js +10 -1
  254. package/dist/features/layout/BottomActions.js +28 -25
  255. package/dist/features/layout/BottomChrome.d.ts +34 -0
  256. package/dist/features/layout/BottomChrome.js +55 -0
  257. package/dist/features/layout/BottomNavLayout.d.ts +6 -0
  258. package/dist/features/layout/BottomNavLayout.js +7 -1
  259. package/dist/features/layout/BottomNavbar.js +15 -2
  260. package/dist/features/layout/FooterLayout.js +11 -1
  261. package/dist/features/layout/NavbarLayout.js +1 -1
  262. package/dist/features/layout/TitleBarLayout.d.ts +7 -0
  263. package/dist/features/layout/TitleBarLayout.js +28 -5
  264. package/dist/features/layout/index.d.ts +2 -0
  265. package/dist/features/layout/index.js +1 -0
  266. package/dist/features/lottery/types/index.d.ts +3 -0
  267. package/dist/features/media/MediaPickerModal.js +5 -1
  268. package/dist/features/messages/schemas/index.d.ts +2 -2
  269. package/dist/features/orders/components/OrderScopeTabs.d.ts +20 -0
  270. package/dist/features/orders/components/OrderScopeTabs.js +31 -0
  271. package/dist/features/orders/components/OrderStatusTimeline.d.ts +5 -1
  272. package/dist/features/orders/components/OrderStatusTimeline.js +39 -20
  273. package/dist/features/orders/constants/order-scope.d.ts +48 -0
  274. package/dist/features/orders/constants/order-scope.js +111 -0
  275. package/dist/features/orders/repository/orders.repository.d.ts +54 -7
  276. package/dist/features/orders/repository/orders.repository.js +121 -22
  277. package/dist/features/orders/schemas/firestore.d.ts +152 -0
  278. package/dist/features/orders/schemas/firestore.js +30 -0
  279. package/dist/features/orders/schemas/index.d.ts +18 -18
  280. package/dist/features/orders/types/index.d.ts +35 -7
  281. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +14 -9
  282. package/dist/features/pre-orders/components/PreOrdersListView.js +6 -5
  283. package/dist/features/pre-orders/schemas/index.d.ts +1 -1
  284. package/dist/features/products/actions/product-actions.d.ts +14 -0
  285. package/dist/features/products/actions/product-actions.js +49 -11
  286. package/dist/features/products/api/route.d.ts +12 -0
  287. package/dist/features/products/api/route.js +42 -100
  288. package/dist/features/products/components/ArtStickersListView.js +2 -2
  289. package/dist/features/products/components/AuctionsIndexListing.js +13 -11
  290. package/dist/features/products/components/AvailabilityTabs.d.ts +11 -0
  291. package/dist/features/products/components/AvailabilityTabs.js +47 -0
  292. package/dist/features/products/components/GroupSettingsPanel.js +5 -1
  293. package/dist/features/products/components/MakeOfferButton.js +48 -49
  294. package/dist/features/products/components/PrizeDrawCollage.d.ts +20 -4
  295. package/dist/features/products/components/PrizeDrawCollage.js +9 -1
  296. package/dist/features/products/components/PrizeDrawsIndexListing.js +14 -12
  297. package/dist/features/products/components/PrizeDrawsListingView.js +2 -2
  298. package/dist/features/products/components/PrizeDrawsSection.d.ts +7 -1
  299. package/dist/features/products/components/PrizeDrawsSection.js +23 -18
  300. package/dist/features/products/components/ProductDetailPageView.d.ts +4 -1
  301. package/dist/features/products/components/ProductDetailPageView.js +18 -4
  302. package/dist/features/products/components/ProductForm.js +5 -2
  303. package/dist/features/products/components/ProductGrid.js +6 -1
  304. package/dist/features/products/components/ProductsIndexListing.js +22 -32
  305. package/dist/features/products/components/ProductsIndexPageView.js +6 -9
  306. package/dist/features/products/components/index.d.ts +2 -2
  307. package/dist/features/products/components/index.js +1 -1
  308. package/dist/features/products/config/listing-type-listing-config.d.ts +20 -0
  309. package/dist/features/products/config/listing-type-listing-config.js +22 -10
  310. package/dist/features/products/constants/action-defs.d.ts +2 -0
  311. package/dist/features/products/constants/action-defs.js +6 -0
  312. package/dist/features/products/hooks/useAvailabilityScope.d.ts +13 -0
  313. package/dist/features/products/hooks/useAvailabilityScope.js +19 -0
  314. package/dist/features/products/hooks/useProducts.d.ts +5 -0
  315. package/dist/features/products/hooks/useProducts.js +13 -2
  316. package/dist/features/products/repository/products.repository.d.ts +31 -2
  317. package/dist/features/products/repository/products.repository.js +53 -21
  318. package/dist/features/products/schemas/firestore.d.ts +17 -3
  319. package/dist/features/products/schemas/firestore.js +7 -2
  320. package/dist/features/products/schemas/index.d.ts +64 -64
  321. package/dist/features/products/schemas/product-features.validators.d.ts +79 -6
  322. package/dist/features/products/schemas/product-features.validators.js +63 -0
  323. package/dist/features/products/types/index.d.ts +16 -1
  324. package/dist/features/promotions/schemas/index.d.ts +2 -2
  325. package/dist/features/reviews/schemas/index.d.ts +16 -16
  326. package/dist/features/scams/constants/scammer-status-display.d.ts +28 -0
  327. package/dist/features/scams/constants/scammer-status-display.js +79 -0
  328. package/dist/features/search/schemas/index.d.ts +4 -4
  329. package/dist/features/seller/actions/offer-actions.js +57 -4
  330. package/dist/features/seller/components/OfferPhaseTimeline.d.ts +59 -0
  331. package/dist/features/seller/components/OfferPhaseTimeline.js +107 -0
  332. package/dist/features/seller/components/SellerArtView.js +5 -0
  333. package/dist/features/seller/components/SellerAuctionsView.js +13 -15
  334. package/dist/features/seller/components/SellerBidsView.js +11 -4
  335. package/dist/features/seller/components/SellerClassifiedView.js +5 -0
  336. package/dist/features/seller/components/SellerCouponEditorView.js +17 -17
  337. package/dist/features/seller/components/SellerDigitalCodesView.js +5 -0
  338. package/dist/features/seller/components/SellerLiveView.js +5 -0
  339. package/dist/features/seller/components/SellerOffersView.js +2 -1
  340. package/dist/features/seller/components/SellerOrdersView.js +31 -9
  341. package/dist/features/seller/components/SellerPayoutSettingsView.js +56 -31
  342. package/dist/features/seller/components/SellerPreOrdersView.js +5 -0
  343. package/dist/features/seller/components/SellerPrizeDrawsView.js +14 -16
  344. package/dist/features/seller/components/SellerProductShell.js +7 -1
  345. package/dist/features/seller/components/SellerProductsView.js +11 -8
  346. package/dist/features/seller/components/SellerStickersView.js +5 -0
  347. package/dist/features/seller/components/index.d.ts +0 -2
  348. package/dist/features/seller/components/index.js +0 -1
  349. package/dist/features/seller/repository/offer.repository.d.ts +142 -24
  350. package/dist/features/seller/repository/offer.repository.js +165 -26
  351. package/dist/features/seller/schemas/coupon-form.d.ts +72 -0
  352. package/dist/features/seller/schemas/coupon-form.js +116 -0
  353. package/dist/features/seller/schemas/firestore.d.ts +56 -2
  354. package/dist/features/seller/schemas/firestore.js +27 -0
  355. package/dist/features/seller/schemas/index.d.ts +2 -2
  356. package/dist/features/seller/schemas/offer-forms.d.ts +46 -0
  357. package/dist/features/seller/schemas/offer-forms.js +42 -0
  358. package/dist/features/seller/server.d.ts +0 -1
  359. package/dist/features/seller/server.js +0 -1
  360. package/dist/features/shell/SectionForm.d.ts +99 -0
  361. package/dist/features/shell/SectionForm.js +128 -0
  362. package/dist/features/shell/build-sections.d.ts +63 -0
  363. package/dist/features/shell/build-sections.js +207 -0
  364. package/dist/features/shell/entity-form.d.ts +109 -0
  365. package/dist/features/shell/entity-form.js +96 -0
  366. package/dist/features/shell/field-ui-meta.d.ts +115 -0
  367. package/dist/features/shell/field-ui-meta.js +324 -0
  368. package/dist/features/shell/index.d.ts +8 -0
  369. package/dist/features/shell/index.js +4 -0
  370. package/dist/features/status-history/components/StatusTimeline.d.ts +74 -0
  371. package/dist/features/status-history/components/StatusTimeline.js +46 -0
  372. package/dist/features/status-history/index.d.ts +11 -0
  373. package/dist/features/status-history/index.js +10 -0
  374. package/dist/features/store-extensions/components/ReviewDecisionModal.d.ts +27 -0
  375. package/dist/features/store-extensions/components/ReviewDecisionModal.js +82 -0
  376. package/dist/features/store-extensions/index.d.ts +12 -0
  377. package/dist/features/store-extensions/index.js +12 -0
  378. package/dist/features/store-extensions/schemas/admin-notification-form.d.ts +36 -0
  379. package/dist/features/store-extensions/schemas/admin-notification-form.js +114 -0
  380. package/dist/features/store-extensions/schemas/analytics-forms.d.ts +57 -0
  381. package/dist/features/store-extensions/schemas/analytics-forms.js +158 -0
  382. package/dist/features/store-extensions/schemas/custom-role-form.d.ts +85 -0
  383. package/dist/features/store-extensions/schemas/custom-role-form.js +118 -0
  384. package/dist/features/store-extensions/schemas/firestore.d.ts +21 -1
  385. package/dist/features/store-extensions/schemas/firestore.js +60 -0
  386. package/dist/features/store-extensions/schemas/google-config-form.d.ts +53 -0
  387. package/dist/features/store-extensions/schemas/google-config-form.js +105 -0
  388. package/dist/features/store-extensions/schemas/item-request-create-form.d.ts +28 -0
  389. package/dist/features/store-extensions/schemas/item-request-create-form.js +80 -0
  390. package/dist/features/store-extensions/schemas/listing-template-form.d.ts +78 -0
  391. package/dist/features/store-extensions/schemas/listing-template-form.js +87 -0
  392. package/dist/features/store-extensions/schemas/moderation-review-form.d.ts +49 -0
  393. package/dist/features/store-extensions/schemas/moderation-review-form.js +101 -0
  394. package/dist/features/store-extensions/schemas/payout-method-form.d.ts +153 -0
  395. package/dist/features/store-extensions/schemas/payout-method-form.js +155 -0
  396. package/dist/features/store-extensions/schemas/report-create-form.d.ts +25 -0
  397. package/dist/features/store-extensions/schemas/report-create-form.js +79 -0
  398. package/dist/features/store-extensions/schemas/report-review-form.d.ts +47 -0
  399. package/dist/features/store-extensions/schemas/report-review-form.js +111 -0
  400. package/dist/features/store-extensions/schemas/shipping-config-form.d.ts +148 -0
  401. package/dist/features/store-extensions/schemas/shipping-config-form.js +104 -0
  402. package/dist/features/store-extensions/schemas/store-category-form.d.ts +54 -0
  403. package/dist/features/store-extensions/schemas/store-category-form.js +73 -0
  404. package/dist/features/stores/api/[storeSlug]/route.js +2 -25
  405. package/dist/features/stores/components/StoreAuctionsListing.js +15 -1
  406. package/dist/features/stores/components/StoreClassifiedsListing.js +12 -2
  407. package/dist/features/stores/components/StoreDetailLayoutView.js +24 -71
  408. package/dist/features/stores/components/StoreDigitalCodesListing.js +12 -2
  409. package/dist/features/stores/components/StoreLiveItemsListing.js +12 -2
  410. package/dist/features/stores/components/StorePreOrdersListing.js +12 -1
  411. package/dist/features/stores/components/StoreProductsListing.js +11 -1
  412. package/dist/features/stores/repository/store.repository.js +6 -0
  413. package/dist/features/stores/schemas/index.d.ts +6 -6
  414. package/dist/features/support/schemas/index.d.ts +4 -4
  415. package/dist/features/tester/actions/checklist-item-actions.d.ts +4 -4
  416. package/dist/features/tester/seed-data/offers-tester-seed-data.js +119 -3
  417. package/dist/features/tester/seed-data/products-tester-seed-data.js +131 -1
  418. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +431 -1
  419. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
  420. package/dist/index.d.ts +25 -12
  421. package/dist/index.js +26 -11
  422. package/dist/next/routing/route-map.d.ts +23 -3
  423. package/dist/next/routing/route-map.js +14 -2
  424. package/dist/providers/db-firebase/base.repository.d.ts +30 -0
  425. package/dist/providers/db-firebase/base.repository.js +50 -1
  426. package/dist/providers/db-firebase/index.d.ts +1 -1
  427. package/dist/providers/db-firebase/index.js +1 -1
  428. package/dist/providers/db-firebase/sieve.d.ts +25 -0
  429. package/dist/providers/db-firebase/sieve.js +52 -18
  430. package/dist/react/hooks/useUrlTable.js +10 -1
  431. package/dist/schemas/firestore-value.d.ts +8 -0
  432. package/dist/schemas/firestore-value.js +44 -0
  433. package/dist/schemas/index.d.ts +1 -1
  434. package/dist/schemas/index.js +1 -1
  435. package/dist/schemas/registry.d.ts +702 -69
  436. package/dist/schemas/registry.js +64 -1
  437. package/dist/seed/_helpers/category-forest.d.ts +2 -0
  438. package/dist/seed/_helpers/category-forest.js +309 -0
  439. package/dist/seed/_helpers/category-tree.d.ts +27 -0
  440. package/dist/seed/_helpers/category-tree.js +103 -0
  441. package/dist/seed/bids-seed-data.js +30 -0
  442. package/dist/seed/catalogue-seed-data.js +12 -12
  443. package/dist/seed/categories-seed-data.js +177 -162
  444. package/dist/seed/events-seed-data.js +61 -10
  445. package/dist/seed/homepage-sections-seed-data.js +5 -1
  446. package/dist/seed/offers-seed-data.js +244 -34
  447. package/dist/seed/orders-seed-data.js +336 -1
  448. package/dist/seed/products-art-seed-data.js +50 -12
  449. package/dist/seed/products-auctions-seed-data.js +138 -18
  450. package/dist/seed/products-classifieds-seed-data.js +80 -16
  451. package/dist/seed/products-digital-codes-seed-data.js +66 -18
  452. package/dist/seed/products-live-items-seed-data.js +64 -13
  453. package/dist/seed/products-preorders-seed-data.d.ts +0 -1
  454. package/dist/seed/products-preorders-seed-data.js +52 -13
  455. package/dist/seed/products-prize-draws-seed-data.js +63 -14
  456. package/dist/seed/products-standard-seed-data.js +99 -26
  457. package/dist/seed/products-stickers-seed-data.js +47 -12
  458. package/dist/seed/reviews-seed-data.js +6 -1
  459. package/dist/seed/site-settings-seed-data.d.ts +1 -38
  460. package/dist/seed/site-settings-seed-data.js +38 -76
  461. package/dist/seed/stores-seed-data.js +71 -1
  462. package/dist/seed/users-seed-data.js +15 -5
  463. package/dist/server-entry.d.ts +1 -2
  464. package/dist/server-entry.js +4 -3
  465. package/dist/server.d.ts +6 -3
  466. package/dist/server.js +13 -4
  467. package/dist/styles.css +78 -12
  468. package/dist/tailwind-utilities.css +1 -1
  469. package/dist/ui/components/Button.style.css +19 -4
  470. package/dist/ui/components/CollapsibleSection.d.ts +17 -1
  471. package/dist/ui/components/CollapsibleSection.js +6 -2
  472. package/dist/ui/components/FilterChipGroup.d.ts +25 -1
  473. package/dist/ui/components/FilterChipGroup.js +21 -4
  474. package/dist/ui/components/HandMode.style.css +47 -0
  475. package/dist/ui/components/Layout.d.ts +9 -2
  476. package/dist/ui/components/Layout.js +1 -1
  477. package/dist/ui/components/ListingLayout.js +8 -8
  478. package/dist/ui/components/ListingLayout.style.css +8 -7
  479. package/dist/ui/components/RecordDetailModal.d.ts +10 -1
  480. package/dist/ui/components/RecordDetailModal.js +2 -2
  481. package/dist/ui/components/StickyToolbar.d.ts +3 -1
  482. package/dist/ui/components/StickyToolbar.js +62 -20
  483. package/dist/ui/components/bottom-chrome-slot.d.ts +21 -0
  484. package/dist/ui/components/bottom-chrome-slot.js +29 -0
  485. package/dist/ui/components/index.style.css +3 -0
  486. package/dist/ui/forms/FormShell.d.ts +43 -13
  487. package/dist/ui/forms/FormShell.js +22 -11
  488. package/dist/ui/forms/index.d.ts +1 -1
  489. package/dist/ui/index.d.ts +1 -1
  490. package/package.json +2 -1
  491. package/scripts/node-esm-loader.mjs +65 -0
  492. package/scripts/seed-cli-loader.mjs +6 -49
  493. package/scripts/seed-cli.mjs +1 -1
@@ -24,9 +24,15 @@
24
24
  import { offerRepository } from "../../../../features/seller/repository/offer.repository";
25
25
  import { bidRepository } from "../../../../repositories";
26
26
  import { OfferStatusValues } from "../../../../features/seller/schemas";
27
+ import { BID_COLLECTION } from "../../../../features/auctions/schemas/firestore";
28
+ import { PRODUCT_COLLECTION } from "../../../../features/products/schemas/firestore";
27
29
  import { ValidationError } from "../../../../errors";
30
+ import { BID_ERROR_CODES } from "../../../../errors/error-codes";
31
+ import { ERROR_MESSAGES } from "../../../../errors";
32
+ import { getAdminDb } from "../../../../providers/db-firebase";
28
33
  import { serverLogger } from "../../../../monitoring/server-logger";
29
34
  import { normalizeError } from "../../../../errors/normalize";
35
+ import { resolveDate } from "../../../../utils/date.formatter";
30
36
  import { activeLane, laneOf, laneBlockReason } from "../../../shared/checkout/lanes";
31
37
  /**
32
38
  * Refuse a checkout that isn't the cart's active lane.
@@ -49,6 +55,108 @@ export function assertCheckoutLane(allCartItems, selectedItems) {
49
55
  }
50
56
  /** Error code the client maps to a lane-aware message. */
51
57
  export const CHECKOUT_LANE_BLOCKED = "CHECKOUT_LANE_BLOCKED";
58
+ const CLAIM_FAILURE_ERRORS = {
59
+ NOT_FOUND: {
60
+ message: ERROR_MESSAGES.BID.AUCTION_NOT_FOUND,
61
+ code: BID_ERROR_CODES.PRODUCT_NOT_FOUND,
62
+ },
63
+ ALREADY_SOLD: {
64
+ message: ERROR_MESSAGES.BID.AUCTION_ALREADY_SOLD,
65
+ code: BID_ERROR_CODES.AUCTION_ALREADY_SOLD,
66
+ },
67
+ AUCTION_ENDED: {
68
+ message: ERROR_MESSAGES.BID.AUCTION_ENDED_BEFORE_CHECKOUT,
69
+ code: BID_ERROR_CODES.AUCTION_ENDED_BEFORE_CHECKOUT,
70
+ },
71
+ LAPSED: {
72
+ message: ERROR_MESSAGES.BID.BUYOUT_LAPSED,
73
+ code: BID_ERROR_CODES.BUYOUT_LAPSED,
74
+ },
75
+ OUTBID: {
76
+ message: ERROR_MESSAGES.BID.BUYOUT_OUTBID,
77
+ code: BID_ERROR_CODES.BUYOUT_OUTBID,
78
+ },
79
+ WRONG_BUYER: {
80
+ message: ERROR_MESSAGES.BID.BUYOUT_LAPSED,
81
+ code: BID_ERROR_CODES.BUYOUT_LAPSED,
82
+ },
83
+ };
84
+ /**
85
+ * Convert a pending Buy Now claim into an actual sale, atomically.
86
+ *
87
+ * This is where a buyout is decided, and it is the ONLY place the auction is
88
+ * closed. `buyNowAuction` deliberately leaves the listing untouched: the auction
89
+ * keeps running, keeps taking bids, and keeps accepting other buyers' buyouts.
90
+ * That means several people can be holding a claim on the same auction at once,
91
+ * which is intentional — whoever reaches this transaction first gets the item,
92
+ * and everyone else is refused HERE, before their order is written and before
93
+ * any payment is captured.
94
+ *
95
+ * Four ways to lose, all of them checked inside the transaction against freshly
96
+ * read documents rather than against the caller's stale cart line:
97
+ * - the auction is already sold (another buyout committed first);
98
+ * - its clock ran out (settlement will award it to a real bidder — the user's
99
+ * explicit rule: an unfinished buyout at auction end fails);
100
+ * - the claim's own bid is no longer `active` (the deadline sweep cancelled it);
101
+ * - bidding passed the buyout price, so buying out is no longer the better deal.
102
+ *
103
+ * Returns a discriminated result rather than throwing out of the transaction
104
+ * body, so each of these precise, buyer-readable refusals survives as itself
105
+ * instead of being reshaped by the transaction wrapper. The caller throws.
106
+ */
107
+ export async function claimAuctionForCheckout(item, buyerUid) {
108
+ const productId = item.auctionId ?? item.productId;
109
+ const bidId = item.bidId;
110
+ if (!bidId)
111
+ return { ok: false, reason: "NOT_FOUND" };
112
+ const db = getAdminDb();
113
+ return db.runTransaction(async (tx) => {
114
+ const productRef = db.collection(PRODUCT_COLLECTION).doc(productId);
115
+ const bidRef = db.collection(BID_COLLECTION).doc(bidId);
116
+ const [productSnap, bidSnap] = await tx.getAll(productRef, bidRef);
117
+ if (!productSnap.exists || !bidSnap.exists) {
118
+ return { ok: false, reason: "NOT_FOUND" };
119
+ }
120
+ const product = productSnap.data();
121
+ const bid = bidSnap.data();
122
+ if (bid.userId !== buyerUid)
123
+ return { ok: false, reason: "WRONG_BUYER" };
124
+ if (bid.status !== "active")
125
+ return { ok: false, reason: "LAPSED" };
126
+ if (product.isSold === true)
127
+ return { ok: false, reason: "ALREADY_SOLD" };
128
+ const endDate = product.auctionEndDate ? resolveDate(product.auctionEndDate) : null;
129
+ if (endDate && endDate.getTime() <= Date.now()) {
130
+ return { ok: false, reason: "AUCTION_ENDED" };
131
+ }
132
+ const bidAmount = bid.bidAmount;
133
+ const standingBid = typeof product.currentBid === "number" ? product.currentBid : 0;
134
+ // `currentBid` never reflects a pending buyout (see BidDocument.isBuyout),
135
+ // so this compares against real bidding only — exactly the check the buyer
136
+ // passed when they started, re-run against the price as it is right now.
137
+ if (standingBid >= bidAmount) {
138
+ return { ok: false, reason: "OUTBID" };
139
+ }
140
+ tx.update(productRef, {
141
+ isSold: true,
142
+ availableQuantity: 0,
143
+ // Ends the auction NOW. Everything above has already established that
144
+ // nobody outbid the buyout price, so no bidder loses anything they would
145
+ // otherwise have won.
146
+ auctionEndDate: new Date(),
147
+ currentBid: bidAmount,
148
+ leadingBidderId: bid.userId,
149
+ bidsHaveStarted: true,
150
+ updatedAt: new Date(),
151
+ });
152
+ tx.update(bidRef, {
153
+ status: "won",
154
+ isWinning: true,
155
+ updatedAt: new Date(),
156
+ });
157
+ return { ok: true, bidAmount };
158
+ });
159
+ }
52
160
  /**
53
161
  * Re-validate every locked line immediately before the order is written.
54
162
  *
@@ -56,10 +164,37 @@ export const CHECKOUT_LANE_BLOCKED = "CHECKOUT_LANE_BLOCKED";
56
164
  * to the cart, but nothing re-checked at order time — so a buyer could add an
57
165
  * accepted offer, wait out the 48h window, and still be charged the locked
58
166
  * price. Throws on the first invalid line; the caller's transaction aborts.
167
+ *
168
+ * Auction lines were skipped entirely until 2026-08-24 (`if (!item.offerId)
169
+ * continue`), so a won auction's own `checkoutDeadline` had never been checked
170
+ * at order time at all — and a buyout claim, which is decided here, had nowhere
171
+ * to be decided.
59
172
  */
60
173
  export async function assertLockedLinesStillValid(items, buyerUid) {
61
174
  const now = new Date();
62
175
  for (const item of items) {
176
+ // --- Auction lines: deadline for every one, plus the claim for a buyout ---
177
+ if (item.bidId || item.isAuctionWin) {
178
+ if (item.checkoutDeadline && now > resolveDate(item.checkoutDeadline)) {
179
+ throw new ValidationError(item.isBuyout
180
+ ? ERROR_MESSAGES.BID.BUYOUT_LAPSED
181
+ : "The payment window for this auction win has expired.", { code: item.isBuyout ? BID_ERROR_CODES.BUYOUT_LAPSED : undefined });
182
+ }
183
+ if (item.isBuyout) {
184
+ const claim = await claimAuctionForCheckout(item, buyerUid);
185
+ if (!claim.ok) {
186
+ const { message, code } = CLAIM_FAILURE_ERRORS[claim.reason];
187
+ serverLogger.info("claimAuctionForCheckout refused", {
188
+ productId: item.auctionId ?? item.productId,
189
+ bidId: item.bidId,
190
+ buyerUid,
191
+ reason: claim.reason,
192
+ });
193
+ throw new ValidationError(message, { code });
194
+ }
195
+ }
196
+ continue;
197
+ }
63
198
  if (!item.offerId)
64
199
  continue;
65
200
  const offer = await offerRepository.findById(item.offerId);
@@ -112,5 +247,41 @@ export async function finalizeLockedLines(items, orderId) {
112
247
  });
113
248
  }
114
249
  }
250
+ if (item.isBuyout && item.bidId) {
251
+ await closeOutBuyoutLosers(item.auctionId ?? item.productId, item.bidId);
252
+ }
253
+ }
254
+ }
255
+ /**
256
+ * A buyout ended the auction, so everyone still bidding on it lost.
257
+ *
258
+ * Deliberately AFTER the claim transaction rather than inside it: the number of
259
+ * active bids on a hot auction is unbounded, and a transaction that touches all
260
+ * of them would either blow the 500-write limit or contend with every incoming
261
+ * bid. The claim only has to be atomic about who gets the ITEM; tidying up the
262
+ * losers is bookkeeping, so it is bounded, best-effort and logged.
263
+ *
264
+ * Their bids are `lost`, not `outbid` — the auction is over, which is the same
265
+ * distinction `auctionSettlement` draws.
266
+ */
267
+ async function closeOutBuyoutLosers(productId, winningBidId) {
268
+ try {
269
+ const active = await bidRepository.getActiveByProduct(productId);
270
+ const losers = active.filter((e) => e.id !== winningBidId);
271
+ if (losers.length === 0)
272
+ return;
273
+ await bidRepository.markManyLost(losers.map((e) => e.ref));
274
+ serverLogger.info("finalizeLockedLines: buyout closed out losing bids", {
275
+ productId,
276
+ winningBidId,
277
+ losers: losers.length,
278
+ });
279
+ }
280
+ catch (err) {
281
+ void normalizeError(err);
282
+ serverLogger.error("finalizeLockedLines: buyout loser close-out failed", {
283
+ productId,
284
+ winningBidId,
285
+ });
115
286
  }
116
287
  }
@@ -0,0 +1,5 @@
1
+ import type { CartItemDocument } from "../../../../features/cart/schemas/firestore";
2
+ import type { ProductDocument } from "../../../../features/products/schemas/firestore";
3
+ import type { OrderSourceContext } from "../../../../features/orders/schemas/firestore";
4
+ import type { OrderType } from "../../../../features/orders/utils/order-splitter";
5
+ export declare function buildOrderSourceContext(item: CartItemDocument, product: ProductDocument, orderType: OrderType): Promise<OrderSourceContext | undefined>;
@@ -0,0 +1,157 @@
1
+ /*
2
+ * WHY: An order records WHAT was bought and WHAT it cost, and nothing about how
3
+ * the buyer earned the right to buy it at that price. `orderType` has five
4
+ * values and cannot even separate "won at ₹4,200 against 11 bids" from
5
+ * "bought out at ₹6,000 while the standing bid was ₹3,800" — both land as
6
+ * `orderType: "auction"`. Everything else was recoverable only by reading
7
+ * the auction or offer document, which is mutable and eventually archived.
8
+ * WHAT: `buildOrderSourceContext()` — the ONE builder for `OrderSourceContext`,
9
+ * called by both order-creation paths (manual/COD and Razorpay).
10
+ *
11
+ * ## Why one shared function and not two inline blocks
12
+ *
13
+ * `createOrderForGroup` and `createRazorpayGroupOrder` are near-identical
14
+ * ~200-line twins that already drifted once on add-on fees (Root Cause #65).
15
+ * Two hand-written copies of this would be the create-vs-create axis of Root
16
+ * Cause #39: one lane records provenance, the other silently doesn't, and the
17
+ * difference is invisible until someone compares two orders months later.
18
+ *
19
+ * ## Written once, never recomputed
20
+ *
21
+ * These numbers describe a moment. `product.price` moves, `currentBid` is a
22
+ * mirror that a pending buyout deliberately never writes to, and a settled
23
+ * auction is eventually archived. Recomputing later would silently rewrite
24
+ * history, so nothing outside order creation may write this field.
25
+ *
26
+ * ## Read cost
27
+ *
28
+ * Standard, pre-order and prize-draw cost **zero** extra reads — everything
29
+ * comes from the product already in hand. Only the auction and offer lanes pay:
30
+ * one `findByProductSorted` for auctions (bid count, winner, runner-up, the
31
+ * standing bid — all four from one query) and one `findById` for offers. Since
32
+ * a checkout is single-lane by construction, a standard cart never pays either.
33
+ *
34
+ * ## Failure is non-fatal, deliberately
35
+ *
36
+ * A missing bid or offer document returns `undefined` rather than throwing. The
37
+ * money path must not fail because a provenance record could not be assembled —
38
+ * an order with no `sourceContext` is a thinner record; a checkout that 500s
39
+ * after payment authorisation is a support ticket.
40
+ *
41
+ * EXPORTS:
42
+ * buildOrderSourceContext
43
+ *
44
+ * @tag domain:checkout,orders
45
+ * @tag layer:server-feature
46
+ * @tag pattern:none
47
+ * @tag access:server
48
+ * @tag consumers:checkout/actions.ts
49
+ * @tag sideEffects:firestore-read
50
+ */
51
+ import { bidRepository } from "../../../../features/auctions/repository/bid.repository";
52
+ import { offerRepository } from "../../../../features/seller/repository/offer.repository";
53
+ import { normalizeError } from "../../../../errors/normalize";
54
+ import { serverLogger } from "../../../../monitoring";
55
+ /** Bids that count toward "against N bidders" — a buyout is excluded. */
56
+ function competitiveBids(bids) {
57
+ return bids.filter((b) => !b.isBuyout).sort((a, b) => b.bidAmount - a.bidAmount);
58
+ }
59
+ export async function buildOrderSourceContext(item, product, orderType) {
60
+ try {
61
+ // The offer lane is checked BEFORE orderType, because an accepted offer on
62
+ // a standard listing arrives as orderType "offer" but an accepted offer on
63
+ // a classified does not — the cart line's own `offerId` is the reliable
64
+ // discriminator, exactly as `laneOf()` treats it.
65
+ if (item.offerId) {
66
+ const offer = await offerRepository.findById(item.offerId);
67
+ if (!offer)
68
+ return undefined;
69
+ return {
70
+ path: "offer-accepted",
71
+ offerId: offer.id,
72
+ offeredAmount: offer.offerAmount,
73
+ listPriceAtOffer: offer.listedPrice,
74
+ counterAmount: offer.counterAmount,
75
+ // Persisted since W2. Before the chain fields existed this number was
76
+ // genuinely unknowable — each counter created an unlinked document.
77
+ counterRounds: offer.counterRound ?? 1,
78
+ acceptedBy: offer.storeId,
79
+ acceptedAt: offer.acceptedAt ?? offer.respondedAt ?? new Date(),
80
+ checkoutDeadline: offer.checkoutDeadline,
81
+ };
82
+ }
83
+ if (item.bidId) {
84
+ const bids = await bidRepository.findByProductSorted(item.productId);
85
+ const rivals = competitiveBids(bids);
86
+ const auctionId = item.auctionId ?? item.productId;
87
+ if (item.isBuyout) {
88
+ return {
89
+ path: "auction-buy-now",
90
+ auctionId,
91
+ bidId: item.bidId,
92
+ buyNowPrice: item.lockedPrice ?? product.buyNowPrice ?? item.price,
93
+ listPrice: product.price,
94
+ // From the bids, not `product.currentBid` — a pending buyout never
95
+ // writes that mirror, so reading it would understate the auction.
96
+ standingBidAtBuyout: rivals[0]?.bidAmount ?? 0,
97
+ bidCount: rivals.length,
98
+ boughtAt: new Date(),
99
+ checkoutDeadline: item.checkoutDeadline ?? new Date(),
100
+ auctionEndDate: product.auctionEndDate,
101
+ };
102
+ }
103
+ const winning = bids.find((b) => b.id === item.bidId);
104
+ const winningAmount = winning?.bidAmount ?? item.lockedPrice ?? item.price;
105
+ const reserve = product.reservePrice;
106
+ return {
107
+ path: "auction-won",
108
+ auctionId,
109
+ bidId: item.bidId,
110
+ winningBidAmount: winningAmount,
111
+ bidCount: rivals.length,
112
+ startingBid: product.startingBid ?? 0,
113
+ reservePrice: reserve,
114
+ // No reserve set means the reserve cannot fail, so it is met.
115
+ reserveMet: reserve == null ? true : winningAmount >= reserve,
116
+ auctionEndedAt: product.auctionEndDate ?? new Date(),
117
+ runnerUpAmount: rivals.find((b) => b.id !== item.bidId)?.bidAmount,
118
+ };
119
+ }
120
+ if (orderType === "preorder") {
121
+ const deposit = product.preOrderDepositAmount ??
122
+ (product.preOrderDepositPercent != null
123
+ ? (product.price * product.preOrderDepositPercent) / 100
124
+ : 0);
125
+ return {
126
+ path: "pre-order",
127
+ depositAmount: deposit,
128
+ balanceDue: Math.max(0, product.price - deposit),
129
+ expectedDeliveryDate: product.preOrderDeliveryDate,
130
+ };
131
+ }
132
+ if (orderType === "prize-draw") {
133
+ return {
134
+ path: "prize-draw",
135
+ prizeDrawProductId: item.productId,
136
+ pricePerEntry: product.pricePerEntry ?? product.price,
137
+ entryCount: item.quantity,
138
+ // `prizeDrawMode` is reveal-vs-lottery, a different axis. The reveal
139
+ // TIMING is what this records: a draw with a reveal window is
140
+ // scheduled, one without reveals as soon as it sells out.
141
+ revealMode: product.prizeRevealWindowEnd ? "scheduled" : "instant",
142
+ };
143
+ }
144
+ return { path: "standard", listPrice: product.price };
145
+ }
146
+ catch (err) {
147
+ const normalized = normalizeError(err);
148
+ // Non-fatal by design — see the header. Logged loudly so a systematic
149
+ // failure shows up as a pattern rather than as quietly thinner orders.
150
+ serverLogger.warn("[checkout] could not build sourceContext", {
151
+ productId: item.productId,
152
+ orderType,
153
+ error: normalized.message,
154
+ });
155
+ return undefined;
156
+ }
157
+ }
@@ -1,2 +1 @@
1
- export { getHomepageInitial, getHomepageSections, getHeroCarouselSlides, } from "./data";
2
1
  export { HOMEPAGE_FEATURED_REVIEWS_LIMIT, HOMEPAGE_RECENT_BLOG_POSTS_LIMIT, HOMEPAGE_MAX_SECTIONS, } from "../../../shared/features/homepage/config";
@@ -1,2 +1,8 @@
1
- export { getHomepageInitial, getHomepageSections, getHeroCarouselSlides, } from "./data";
1
+ // `getHomepageInitial` / `getHomepageSections` / `getHeroCarouselSlides` lived
2
+ // in ./data and were deleted 2026-08-24. All three had ZERO call sites — the
3
+ // live homepage is `MarketplaceHomepageView`, which reads its repositories
4
+ // directly — and the only part worth keeping, the feature-flag gate, moved to
5
+ // `_internal/shared/features/homepage/section-gate.ts` and is now actually
6
+ // applied. The rest was a Rule #6 liability: `findActiveAuctions()` /
7
+ // `findActivePreOrders()` were unbounded `.get()` collection scans.
2
8
  export { HOMEPAGE_FEATURED_REVIEWS_LIMIT, HOMEPAGE_RECENT_BLOG_POSTS_LIMIT, HOMEPAGE_MAX_SECTIONS, } from "../../../shared/features/homepage/config";
@@ -1,8 +1,12 @@
1
1
  /** Strip price and weight from a single slot for client consumption. */
2
2
  export function toClientLotterySlot(slot) {
3
+ // Allow-list, not a spread: every field named here is a deliberate public
4
+ // exposure with a known reader (§ Public Data Projections). `image` is read
5
+ // by the prize collage on the lottery detail page.
3
6
  return {
4
7
  slotNumber: slot.slotNumber,
5
8
  name: slot.name,
9
+ image: slot.image,
6
10
  isBooked: slot.isBooked,
7
11
  bookedByUserLotteryNumber: slot.bookedByUserLotteryNumber,
8
12
  bookedByDisplayName: slot.bookedByDisplayName,
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Offer document → API shape.
3
+ *
4
+ * Offers had **no adapter at all** before this: all three routes
5
+ * (`/api/user/offers`, `/api/store/offers`, `/api/admin/offers`) returned raw
6
+ * `OfferDocument`s straight from the repository, carrying live `Date`
7
+ * objects. `UserOffersPanel.relativeTime` still has a defensive
8
+ * `date instanceof Date ? … : new Date(…)` branch precisely because the shape
9
+ * it receives depends on whether the value survived JSON serialisation.
10
+ *
11
+ * Mirrors `orders/adapters.ts`, including its `toIsoOrUndefined` helper.
12
+ */
13
+ import type { OfferDocument } from "../../../../features/seller/schemas";
14
+ import type { FieldChange } from "../../../shared/history/index";
15
+ /** One entry on an offer's timeline — dates as ISO, ready for JSON. */
16
+ export interface OfferTimelineEntry {
17
+ at: string;
18
+ actorUid?: string;
19
+ actorRole: "buyer" | "seller" | "admin" | "system";
20
+ changes: Record<string, FieldChange>;
21
+ reason?: string;
22
+ note?: string;
23
+ trigger: string;
24
+ }
25
+ /** One round of a negotiation, as rendered in the chain rail. */
26
+ export interface OfferChainRound {
27
+ id: string;
28
+ counterRound: number;
29
+ status: OfferDocument["status"];
30
+ offerAmount: number;
31
+ counterAmount?: number;
32
+ /**
33
+ * `withdrawn` + a `supersededByOfferId` is NOT a walk-away — the buyer
34
+ * countered. The timeline renders it neutral ("Superseded") rather than
35
+ * negative ("Withdrawn"), which is why this flag is carried explicitly
36
+ * instead of being re-derived in the component.
37
+ */
38
+ superseded: boolean;
39
+ createdAt: string;
40
+ respondedAt?: string;
41
+ sellerNote?: string;
42
+ buyerNote?: string;
43
+ }
44
+ export interface Offer {
45
+ id: string;
46
+ productId: string;
47
+ productTitle: string;
48
+ productSlug?: string;
49
+ productImageUrl?: string;
50
+ storeId: string;
51
+ storeName: string;
52
+ offerAmount: number;
53
+ listedPrice: number;
54
+ counterAmount?: number;
55
+ lockedPrice?: number;
56
+ currency: string;
57
+ status: OfferDocument["status"];
58
+ buyerNote?: string;
59
+ sellerNote?: string;
60
+ expiresAt: string;
61
+ acceptedAt?: string;
62
+ checkoutDeadline?: string;
63
+ respondedAt?: string;
64
+ paidOrderId?: string;
65
+ paidAt?: string;
66
+ createdAt: string;
67
+ updatedAt: string;
68
+ timeline?: OfferTimelineEntry[];
69
+ timelineTruncated?: number;
70
+ previousOfferId?: string;
71
+ supersededByOfferId?: string;
72
+ chainRootOfferId?: string;
73
+ counterRound?: number;
74
+ /** True when this round was superseded by the buyer's own counter. */
75
+ superseded: boolean;
76
+ cancelledByAdminUid?: string;
77
+ cancelReason?: string;
78
+ buyerUid?: string;
79
+ buyerName?: string;
80
+ buyerEmail?: string;
81
+ }
82
+ export interface OfferAdapterOptions {
83
+ /**
84
+ * Include `buyerUid`/`buyerName`/`buyerEmail`.
85
+ *
86
+ * Default **false**, deliberately. The seller-facing route masks buyer
87
+ * identity, and a route that forgot to call `maskOfferForSeller` would
88
+ * previously have shipped it verbatim — there was no adapter to stop it.
89
+ * Making the omission the default means forgetting the flag under-shares
90
+ * rather than leaks.
91
+ */
92
+ includeBuyerIdentity?: boolean;
93
+ }
94
+ export declare function offerDocumentToOffer(doc: OfferDocument, opts?: OfferAdapterOptions): Offer;
95
+ /**
96
+ * A chain round — the compact shape the timeline needs, without re-sending
97
+ * the whole document for every round.
98
+ *
99
+ * Buyer identity is never included: the chain is rendered on all three
100
+ * portals from one component, and the seller's view must not gain identity
101
+ * it is masked from elsewhere.
102
+ */
103
+ export declare function offerToChainRound(doc: OfferDocument): OfferChainRound;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Offer document → API shape.
3
+ *
4
+ * Offers had **no adapter at all** before this: all three routes
5
+ * (`/api/user/offers`, `/api/store/offers`, `/api/admin/offers`) returned raw
6
+ * `OfferDocument`s straight from the repository, carrying live `Date`
7
+ * objects. `UserOffersPanel.relativeTime` still has a defensive
8
+ * `date instanceof Date ? … : new Date(…)` branch precisely because the shape
9
+ * it receives depends on whether the value survived JSON serialisation.
10
+ *
11
+ * Mirrors `orders/adapters.ts`, including its `toIsoOrUndefined` helper.
12
+ */
13
+ function toIsoOrUndefined(value) {
14
+ return value instanceof Date ? value.toISOString() : undefined;
15
+ }
16
+ function toIso(value) {
17
+ return value instanceof Date ? value.toISOString() : String(value);
18
+ }
19
+ export function offerDocumentToOffer(doc, opts = {}) {
20
+ const superseded = doc.status === "withdrawn" && Boolean(doc.supersededByOfferId);
21
+ return {
22
+ id: doc.id,
23
+ productId: doc.productId,
24
+ productTitle: doc.productTitle,
25
+ productSlug: doc.productSlug,
26
+ productImageUrl: doc.productImageUrl,
27
+ storeId: doc.storeId,
28
+ storeName: doc.storeName,
29
+ offerAmount: doc.offerAmount,
30
+ listedPrice: doc.listedPrice,
31
+ counterAmount: doc.counterAmount,
32
+ lockedPrice: doc.lockedPrice,
33
+ currency: doc.currency,
34
+ status: doc.status,
35
+ buyerNote: doc.buyerNote,
36
+ sellerNote: doc.sellerNote,
37
+ expiresAt: toIso(doc.expiresAt),
38
+ acceptedAt: toIsoOrUndefined(doc.acceptedAt),
39
+ checkoutDeadline: toIsoOrUndefined(doc.checkoutDeadline),
40
+ respondedAt: toIsoOrUndefined(doc.respondedAt),
41
+ paidOrderId: doc.paidOrderId,
42
+ paidAt: toIsoOrUndefined(doc.paidAt),
43
+ createdAt: toIso(doc.createdAt),
44
+ updatedAt: toIso(doc.updatedAt),
45
+ timeline: doc.statusHistory?.map((entry) => ({
46
+ at: entry.at instanceof Date ? entry.at.toISOString() : String(entry.at),
47
+ actorUid: entry.actorUid,
48
+ actorRole: entry.actorRole,
49
+ changes: entry.changes,
50
+ reason: entry.reason,
51
+ note: entry.note,
52
+ trigger: entry.trigger,
53
+ })),
54
+ timelineTruncated: doc.statusHistoryTruncated,
55
+ previousOfferId: doc.previousOfferId,
56
+ supersededByOfferId: doc.supersededByOfferId,
57
+ chainRootOfferId: doc.chainRootOfferId,
58
+ counterRound: doc.counterRound,
59
+ superseded,
60
+ cancelledByAdminUid: doc.cancelledByAdminUid,
61
+ cancelReason: doc.cancelReason,
62
+ ...(opts.includeBuyerIdentity
63
+ ? { buyerUid: doc.buyerUid, buyerName: doc.buyerName, buyerEmail: doc.buyerEmail }
64
+ : {}),
65
+ };
66
+ }
67
+ /**
68
+ * A chain round — the compact shape the timeline needs, without re-sending
69
+ * the whole document for every round.
70
+ *
71
+ * Buyer identity is never included: the chain is rendered on all three
72
+ * portals from one component, and the seller's view must not gain identity
73
+ * it is masked from elsewhere.
74
+ */
75
+ export function offerToChainRound(doc) {
76
+ return {
77
+ id: doc.id,
78
+ counterRound: doc.counterRound ?? 1,
79
+ status: doc.status,
80
+ offerAmount: doc.offerAmount,
81
+ counterAmount: doc.counterAmount,
82
+ superseded: doc.status === "withdrawn" && Boolean(doc.supersededByOfferId),
83
+ createdAt: toIso(doc.createdAt),
84
+ respondedAt: toIsoOrUndefined(doc.respondedAt),
85
+ sellerNote: doc.sellerNote,
86
+ buyerNote: doc.buyerNote,
87
+ };
88
+ }
@@ -0,0 +1,2 @@
1
+ export { offerDocumentToOffer, offerToChainRound, } from "./adapters";
2
+ export type { Offer, OfferAdapterOptions, OfferChainRound, OfferTimelineEntry, } from "./adapters";
@@ -0,0 +1 @@
1
+ export { offerDocumentToOffer, offerToChainRound, } from "./adapters";
@@ -104,6 +104,30 @@ export function orderDocumentToOrder(doc) {
104
104
  paymentReviewOutcome: doc.paymentReviewOutcome,
105
105
  paymentReviewNote: doc.paymentReviewNote,
106
106
  cancellationReason: doc.cancellationReason,
107
+ // ── W2: history + provenance ──────────────────────────────────────────
108
+ //
109
+ // `Order.timeline` has existed, been exported, and had ZERO writers since
110
+ // it was declared — `OrderStatusTimeline` synthesised its steps from four
111
+ // scalar dates instead, so a status change with no dedicated date field
112
+ // (payment reviewed, refund posted) was simply invisible.
113
+ //
114
+ // `statusHistory` is that field's real source. Dates are serialised to
115
+ // ISO here for the same reason every other date on this shape is: the
116
+ // client receives JSON, and a raw `Date` arrives as a string that no
117
+ // longer satisfies the type.
118
+ timeline: doc.statusHistory?.map((entry) => ({
119
+ at: entry.at instanceof Date ? entry.at.toISOString() : String(entry.at),
120
+ actorUid: entry.actorUid,
121
+ actorRole: entry.actorRole,
122
+ changes: entry.changes,
123
+ reason: entry.reason,
124
+ note: entry.note,
125
+ trigger: entry.trigger,
126
+ })),
127
+ /** Entries trimmed off the front — so the UI never implies "this is all of it". */
128
+ timelineTruncated: doc.statusHistoryTruncated,
129
+ /** How the buyer acquired the right to buy. Written once, at creation. */
130
+ sourceContext: doc.sourceContext,
107
131
  createdAt: doc.createdAt instanceof Date
108
132
  ? doc.createdAt.toISOString()
109
133
  : String(doc.createdAt),