@mohasinac/appkit 4.53.0 → 4.53.2

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 (520) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/scaffolds/AppShell.js +1 -1
  3. package/dist/_internal/client/theme/ThemeProvider.js +15 -1
  4. package/dist/_internal/server/features/auctions/og.d.ts +3 -1
  5. package/dist/_internal/server/features/auctions/og.js +3 -1
  6. package/dist/_internal/server/features/bundles/actions.js +1 -1
  7. package/dist/_internal/server/features/business-documents/download.d.ts +41 -0
  8. package/dist/_internal/server/features/business-documents/download.js +91 -0
  9. package/dist/_internal/server/features/categories/adapters.d.ts +1 -1
  10. package/dist/_internal/server/features/categories/adapters.js +10 -0
  11. package/dist/_internal/server/features/categories/price-guidance-resolve.d.ts +66 -0
  12. package/dist/_internal/server/features/categories/price-guidance-resolve.js +138 -0
  13. package/dist/_internal/server/features/checkout/actions.d.ts +14 -0
  14. package/dist/_internal/server/features/checkout/actions.js +106 -12
  15. package/dist/_internal/server/features/checkout/bundle-expansion.js +17 -0
  16. package/dist/_internal/server/features/checkout/data.d.ts +22 -0
  17. package/dist/_internal/server/features/checkout/group-rule-revalidation.d.ts +34 -0
  18. package/dist/_internal/server/features/checkout/group-rule-revalidation.js +124 -0
  19. package/dist/_internal/server/features/checkout/supplier-identity.d.ts +55 -0
  20. package/dist/_internal/server/features/checkout/supplier-identity.js +81 -0
  21. package/dist/_internal/server/features/classified/metadata.js +1 -1
  22. package/dist/_internal/server/features/classified/og.d.ts +3 -1
  23. package/dist/_internal/server/features/classified/og.js +3 -1
  24. package/dist/_internal/server/features/digital-code/metadata.js +1 -1
  25. package/dist/_internal/server/features/digital-code/og.d.ts +3 -1
  26. package/dist/_internal/server/features/digital-code/og.js +3 -1
  27. package/dist/_internal/server/features/digital-code/pool.d.ts +19 -4
  28. package/dist/_internal/server/features/digital-code/pool.js +19 -4
  29. package/dist/_internal/server/features/live/metadata.js +1 -1
  30. package/dist/_internal/server/features/live/og.d.ts +3 -1
  31. package/dist/_internal/server/features/live/og.js +3 -1
  32. package/dist/_internal/server/features/messages/actions.js +1 -1
  33. package/dist/_internal/server/features/parts/og.js +1 -1
  34. package/dist/_internal/server/features/pre-orders/og.d.ts +3 -1
  35. package/dist/_internal/server/features/pre-orders/og.js +3 -1
  36. package/dist/_internal/server/features/price-index/market.d.ts +57 -0
  37. package/dist/_internal/server/features/price-index/market.js +120 -0
  38. package/dist/_internal/server/features/price-index/search.d.ts +18 -0
  39. package/dist/_internal/server/features/price-index/search.js +47 -7
  40. package/dist/_internal/server/features/prize-draws/og.d.ts +3 -1
  41. package/dist/_internal/server/features/prize-draws/og.js +3 -1
  42. package/dist/_internal/server/features/products/group-members.d.ts +26 -0
  43. package/dist/_internal/server/features/products/group-members.js +7 -1
  44. package/dist/_internal/server/features/products/list-public.d.ts +12 -0
  45. package/dist/_internal/server/features/products/list-public.js +10 -1
  46. package/dist/_internal/server/features/products/listing-tab-counts.d.ts +25 -1
  47. package/dist/_internal/server/features/products/listing-tab-counts.js +128 -10
  48. package/dist/_internal/server/features/products/og.d.ts +3 -1
  49. package/dist/_internal/server/features/products/og.js +3 -1
  50. package/dist/_internal/server/features/search/scoped-sources.d.ts +26 -0
  51. package/dist/_internal/server/features/search/scoped-sources.js +252 -0
  52. package/dist/_internal/server/features/search/search-everything.d.ts +57 -0
  53. package/dist/_internal/server/features/search/search-everything.js +70 -20
  54. package/dist/_internal/server/features/seo/sitemap.js +6 -0
  55. package/dist/_internal/server/features/shared/listing-adapters.js +4 -2
  56. package/dist/_internal/server/features/sticker-trace/adapters.d.ts +11 -0
  57. package/dist/_internal/server/features/sticker-trace/adapters.js +1 -0
  58. package/dist/_internal/server/features/sticker-trace/promote-to-listings.d.ts +26 -0
  59. package/dist/_internal/server/features/sticker-trace/promote-to-listings.js +264 -0
  60. package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +3 -1
  61. package/dist/_internal/server/features/sticker-trace/sheet-actions.js +32 -0
  62. package/dist/_internal/server/features/sticker-trace/storage.d.ts +20 -1
  63. package/dist/_internal/server/features/sticker-trace/storage.js +20 -1
  64. package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
  65. package/dist/_internal/server/features/stores/adapters.js +16 -0
  66. package/dist/_internal/server/features/stores/index.d.ts +1 -0
  67. package/dist/_internal/server/features/stores/index.js +1 -0
  68. package/dist/_internal/server/features/stores/tabs.d.ts +30 -0
  69. package/dist/_internal/server/features/stores/tabs.js +124 -0
  70. package/dist/_internal/shared/checkout/rules/_defaults.js +0 -2
  71. package/dist/_internal/shared/checkout/rules/_limits.d.ts +14 -1
  72. package/dist/_internal/shared/checkout/rules/_limits.js +14 -1
  73. package/dist/_internal/shared/checkout/rules/_registry.js +2 -0
  74. package/dist/_internal/shared/checkout/rules/auction.rule.js +9 -1
  75. package/dist/_internal/shared/checkout/rules/bundle.rule.js +13 -0
  76. package/dist/_internal/shared/checkout/rules/index.d.ts +2 -0
  77. package/dist/_internal/shared/checkout/rules/index.js +9 -0
  78. package/dist/_internal/shared/checkout/rules/offer.rule.js +0 -1
  79. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +26 -0
  80. package/dist/_internal/shared/checkout/rules/payment-gate.js +133 -0
  81. package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +29 -8
  82. package/dist/_internal/shared/checkout/rules/spares.rule.d.ts +16 -0
  83. package/dist/_internal/shared/checkout/rules/spares.rule.js +5 -0
  84. package/dist/_internal/shared/checkout/rules/types.d.ts +26 -2
  85. package/dist/_internal/shared/config/schema.d.ts +122 -0
  86. package/dist/_internal/shared/features/cart/schema.js +3 -2
  87. package/dist/_internal/shared/features/products/group-rules.d.ts +75 -0
  88. package/dist/_internal/shared/features/products/group-rules.js +142 -0
  89. package/dist/_internal/shared/listing-types/_registry.d.ts +24 -0
  90. package/dist/_internal/shared/listing-types/_registry.js +39 -1
  91. package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
  92. package/dist/_internal/shared/listing-types/art/config.js +2 -0
  93. package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
  94. package/dist/_internal/shared/listing-types/auction/config.js +2 -0
  95. package/dist/_internal/shared/listing-types/availability.js +48 -0
  96. package/dist/_internal/shared/listing-types/capabilities.js +19 -0
  97. package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
  98. package/dist/_internal/shared/listing-types/classified/config.js +2 -0
  99. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
  100. package/dist/_internal/shared/listing-types/digital-code/config.js +2 -0
  101. package/dist/_internal/shared/listing-types/feature-flags.js +1 -0
  102. package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
  103. package/dist/_internal/shared/listing-types/live/config.js +2 -0
  104. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
  105. package/dist/_internal/shared/listing-types/pre-order/config.js +2 -0
  106. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
  107. package/dist/_internal/shared/listing-types/prize-draw/config.js +2 -0
  108. package/dist/_internal/shared/listing-types/spares/config.d.ts +74 -0
  109. package/dist/_internal/shared/listing-types/spares/config.js +60 -0
  110. package/dist/_internal/shared/listing-types/spares/ctas.d.ts +1 -0
  111. package/dist/_internal/shared/listing-types/spares/ctas.js +4 -0
  112. package/dist/_internal/shared/listing-types/spares/og.js +1 -0
  113. package/dist/_internal/shared/listing-types/spares/schema.d.ts +2 -0
  114. package/dist/_internal/shared/listing-types/spares/schema.js +3 -0
  115. package/dist/_internal/shared/listing-types/spares/seed-factory.d.ts +1 -0
  116. package/dist/_internal/shared/listing-types/spares/seed-factory.js +1 -0
  117. package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
  118. package/dist/_internal/shared/listing-types/standard/config.js +2 -0
  119. package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
  120. package/dist/_internal/shared/listing-types/stickers/config.js +2 -0
  121. package/dist/_internal/shared/search/match.d.ts +11 -0
  122. package/dist/_internal/shared/search/match.js +30 -3
  123. package/dist/_internal/shared/search/to-groups.d.ts +52 -0
  124. package/dist/_internal/shared/search/to-groups.js +141 -0
  125. package/dist/client.d.ts +8 -2
  126. package/dist/client.js +4 -1
  127. package/dist/constants/api-endpoints.d.ts +46 -15
  128. package/dist/constants/api-endpoints.js +35 -5
  129. package/dist/constants/cache-invalidation.js +3 -1
  130. package/dist/constants/field-names.d.ts +6 -0
  131. package/dist/constants/field-names.js +6 -0
  132. package/dist/features/about/components/PolicyPageView.d.ts +22 -2
  133. package/dist/features/about/components/PolicyPageView.js +14 -2
  134. package/dist/features/about/components/PublicProfileView.js +2 -1
  135. package/dist/features/about/components/ShippingPolicyView.js +42 -2
  136. package/dist/features/account/components/NotificationBell.js +1 -1
  137. package/dist/features/account/hooks/useProfileStats.js +5 -1
  138. package/dist/features/addresses/repository/addresses.repository.d.ts +16 -0
  139. package/dist/features/addresses/repository/addresses.repository.js +21 -0
  140. package/dist/features/admin/actions/admin-actions.js +16 -1
  141. package/dist/features/admin/components/AdminCategoryEditorView.js +19 -2
  142. package/dist/features/admin/components/AdminNavigationView.js +1 -1
  143. package/dist/features/admin/components/AdminPageHeader.js +1 -1
  144. package/dist/features/admin/components/AdminProductEditorView.js +17 -2
  145. package/dist/features/admin/components/AdminSidebar.js +1 -1
  146. package/dist/features/admin/components/AdminSiteSettingsView.js +39 -8
  147. package/dist/features/admin/components/AdminSparesView.d.ts +12 -0
  148. package/dist/features/admin/components/AdminSparesView.js +30 -0
  149. package/dist/features/admin/components/AdminUsersView.js +9 -7
  150. package/dist/features/admin/components/index.d.ts +2 -0
  151. package/dist/features/admin/components/index.js +1 -0
  152. package/dist/features/admin/components/sections/adminSectionsTypes.js +7 -0
  153. package/dist/features/admin/constants/filter-tabs.d.ts +3 -0
  154. package/dist/features/admin/constants/filter-tabs.js +1 -0
  155. package/dist/features/admin/schemas/firestore.d.ts +26 -2
  156. package/dist/features/auctions/components/AuctionDetailPageView.js +12 -18
  157. package/dist/features/auth/repository/user.repository.d.ts +13 -0
  158. package/dist/features/auth/repository/user.repository.js +28 -0
  159. package/dist/features/auth/schemas/firestore.d.ts +2 -0
  160. package/dist/features/auth/schemas/firestore.js +2 -0
  161. package/dist/features/business-documents/repository/business-documents.repository.d.ts +58 -0
  162. package/dist/features/business-documents/repository/business-documents.repository.js +54 -0
  163. package/dist/features/business-documents/schemas/firestore.d.ts +105 -0
  164. package/dist/features/business-documents/schemas/firestore.js +75 -0
  165. package/dist/features/cart/actions/cart-actions.js +83 -6
  166. package/dist/features/cart/repository/cart.repository.js +32 -4
  167. package/dist/features/cart/schemas/firestore.d.ts +20 -0
  168. package/dist/features/cart/schemas/index.d.ts +2 -2
  169. package/dist/features/catalogue/components/PublicCatalogueItemDetailView.js +1 -1
  170. package/dist/features/categories/api/[id]/price-guidance/route.d.ts +42 -0
  171. package/dist/features/categories/api/[id]/price-guidance/route.js +90 -0
  172. package/dist/features/categories/components/BrandDetailPageView.js +32 -8
  173. package/dist/features/categories/components/BrandDetailTabs.d.ts +7 -1
  174. package/dist/features/categories/components/BrandDetailTabs.js +28 -3
  175. package/dist/features/categories/components/BundleCollage.js +3 -2
  176. package/dist/features/categories/components/BundleItemsPicker.js +3 -4
  177. package/dist/features/categories/components/CategoriesIndexListing.js +23 -8
  178. package/dist/features/categories/components/CategoryDetailPageView.js +157 -20
  179. package/dist/features/categories/components/CategoryDetailTabs.d.ts +7 -1
  180. package/dist/features/categories/components/CategoryDetailTabs.js +41 -7
  181. package/dist/features/categories/components/CategoryGrid.js +10 -1
  182. package/dist/features/categories/components/PriceGuidanceHint.d.ts +29 -0
  183. package/dist/features/categories/components/PriceGuidanceHint.js +61 -0
  184. package/dist/features/categories/components/SubcategoryCardRow.d.ts +27 -0
  185. package/dist/features/categories/components/SubcategoryCardRow.js +98 -0
  186. package/dist/features/categories/constants/category-tabs.d.ts +20 -25
  187. package/dist/features/categories/constants/category-tabs.js +22 -39
  188. package/dist/features/categories/repository/categories.repository.d.ts +12 -0
  189. package/dist/features/categories/repository/categories.repository.js +20 -0
  190. package/dist/features/categories/schemas/firestore.d.ts +22 -1
  191. package/dist/features/categories/schemas/firestore.js +10 -0
  192. package/dist/features/categories/schemas/index.d.ts +6 -0
  193. package/dist/features/categories/schemas/index.js +2 -0
  194. package/dist/features/categories/types/index.d.ts +8 -0
  195. package/dist/features/categories/utils/taxonomy-visual.d.ts +16 -3
  196. package/dist/features/categories/utils/taxonomy-visual.js +26 -10
  197. package/dist/features/classified/components/ClassifiedDetailPageView.js +14 -10
  198. package/dist/features/contact/components/ContactPageView.d.ts +33 -1
  199. package/dist/features/contact/components/ContactPageView.js +58 -28
  200. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +14 -10
  201. package/dist/features/grouped/components/GroupedListingDetailView.js +9 -1
  202. package/dist/features/grouped/schemas/firestore.d.ts +5 -0
  203. package/dist/features/homepage/actions/homepage-section-actions.d.ts +3 -3
  204. package/dist/features/homepage/components/CollectionCardsSection.d.ts +28 -6
  205. package/dist/features/homepage/components/CollectionCardsSection.js +43 -8
  206. package/dist/features/homepage/components/HowItWorksSection.d.ts +23 -6
  207. package/dist/features/homepage/components/HowItWorksSection.js +4 -4
  208. package/dist/features/homepage/components/PromoGrid.d.ts +31 -2
  209. package/dist/features/homepage/components/PromoGrid.js +12 -3
  210. package/dist/features/homepage/components/TestimonialsCarousel.d.ts +34 -2
  211. package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
  212. package/dist/features/homepage/components/index.d.ts +0 -20
  213. package/dist/features/homepage/components/index.js +0 -11
  214. package/dist/features/homepage/index.d.ts +0 -2
  215. package/dist/features/homepage/index.js +0 -2
  216. package/dist/features/homepage/lib/section-renderer.d.ts +9 -0
  217. package/dist/features/homepage/lib/section-renderer.js +202 -58
  218. package/dist/features/homepage/repository/homepage-sections.repository.d.ts +35 -3
  219. package/dist/features/homepage/repository/homepage-sections.repository.js +58 -8
  220. package/dist/features/homepage/schemas/firestore.d.ts +106 -3
  221. package/dist/features/homepage/schemas/firestore.js +32 -2
  222. package/dist/features/homepage/schemas/index.d.ts +36 -7
  223. package/dist/features/homepage/schemas/index.js +39 -27
  224. package/dist/features/homepage/server.d.ts +0 -3
  225. package/dist/features/homepage/server.js +0 -3
  226. package/dist/features/homepage/types/index.d.ts +0 -47
  227. package/dist/features/homepage/types/index.js +49 -0
  228. package/dist/features/layout/AppLayoutShell.js +1 -1
  229. package/dist/features/layout/BottomNavItem.js +1 -1
  230. package/dist/features/layout/BottomSheet.js +1 -1
  231. package/dist/features/layout/TitleBarLayout.js +1 -1
  232. package/dist/features/live/components/LiveItemDetailPageView.js +14 -10
  233. package/dist/features/media/hooks/useMedia.js +17 -0
  234. package/dist/features/media/repository/media-assets.repository.d.ts +46 -0
  235. package/dist/features/media/repository/media-assets.repository.js +31 -0
  236. package/dist/features/media/trust-signals.d.ts +85 -0
  237. package/dist/features/media/trust-signals.js +126 -0
  238. package/dist/features/parts/components/PartDetailPageView.d.ts +14 -1
  239. package/dist/features/parts/components/PartDetailPageView.js +2 -2
  240. package/dist/features/parts/components/PartsIndexPageView.d.ts +11 -2
  241. package/dist/features/parts/components/PartsIndexPageView.js +2 -2
  242. package/dist/features/parts/components/PartsSearchBox.d.ts +9 -0
  243. package/dist/features/parts/components/PartsSearchBox.js +57 -0
  244. package/dist/features/parts/schemas/firestore.d.ts +149 -3
  245. package/dist/features/parts/schemas/firestore.js +184 -0
  246. package/dist/features/payments/repository/payout.repository.d.ts +15 -0
  247. package/dist/features/payments/repository/payout.repository.js +21 -0
  248. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +12 -18
  249. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +1 -1
  250. package/dist/features/price-index/components/PriceIndexToolView.d.ts +24 -1
  251. package/dist/features/price-index/components/PriceIndexToolView.js +299 -17
  252. package/dist/features/price-index/lookup-target.d.ts +48 -0
  253. package/dist/features/price-index/lookup-target.js +107 -0
  254. package/dist/features/products/components/AvailabilityScopeHint.d.ts +22 -0
  255. package/dist/features/products/components/AvailabilityScopeHint.js +27 -0
  256. package/dist/features/products/components/CompareOverlay.d.ts +20 -2
  257. package/dist/features/products/components/CompareOverlay.js +23 -3
  258. package/dist/features/products/components/CustomSectionTabContent.d.ts +31 -0
  259. package/dist/features/products/components/CustomSectionTabContent.js +29 -3
  260. package/dist/features/products/components/GroupMemberPicker.d.ts +19 -1
  261. package/dist/features/products/components/GroupMemberPicker.js +46 -8
  262. package/dist/features/products/components/GroupSettingsPanel.d.ts +11 -1
  263. package/dist/features/products/components/GroupSettingsPanel.js +92 -3
  264. package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
  265. package/dist/features/products/components/PrizeDrawEntryActions.d.ts +15 -1
  266. package/dist/features/products/components/PrizeDrawEntryActions.js +70 -8
  267. package/dist/features/products/components/ProductDetailPageView.js +81 -17
  268. package/dist/features/products/components/ProductForm.d.ts +13 -1
  269. package/dist/features/products/components/ProductForm.js +16 -2
  270. package/dist/features/products/components/ProductsIndexListing.d.ts +16 -1
  271. package/dist/features/products/components/ProductsIndexListing.js +3 -3
  272. package/dist/features/products/components/ShowGroupSection.js +15 -2
  273. package/dist/features/products/components/SparesListView.d.ts +7 -0
  274. package/dist/features/products/components/SparesListView.js +39 -0
  275. package/dist/features/products/components/SublistingCarouselSection.js +2 -1
  276. package/dist/features/products/constants/action-defs.d.ts +1 -0
  277. package/dist/features/products/constants/action-defs.js +1 -0
  278. package/dist/features/products/repository/products.repository.d.ts +99 -0
  279. package/dist/features/products/repository/products.repository.js +240 -18
  280. package/dist/features/products/schemas/firestore.d.ts +97 -4
  281. package/dist/features/products/schemas/firestore.js +104 -0
  282. package/dist/features/products/schemas/index.d.ts +10 -19
  283. package/dist/features/products/schemas/index.js +23 -6
  284. package/dist/features/products/types/index.d.ts +45 -1
  285. package/dist/features/products/utils/group-member-image.d.ts +46 -0
  286. package/dist/features/products/utils/group-member-image.js +4 -0
  287. package/dist/features/products/utils/listing-badge-variant.js +4 -0
  288. package/dist/features/reviews/components/ReviewsList.js +1 -1
  289. package/dist/features/scams/components/ScamProfileView.js +1 -1
  290. package/dist/features/search/components/EntityTypeahead.d.ts +44 -0
  291. package/dist/features/search/components/EntityTypeahead.js +92 -0
  292. package/dist/features/search/components/Search.d.ts +12 -1
  293. package/dist/features/search/components/Search.js +47 -3
  294. package/dist/features/search/components/SearchFacetRail.d.ts +11 -0
  295. package/dist/features/search/components/SearchFacetRail.js +92 -0
  296. package/dist/features/search/components/SearchResultsClient.d.ts +33 -0
  297. package/dist/features/search/components/SearchResultsClient.js +103 -0
  298. package/dist/features/search/components/SearchResultsPageView.d.ts +15 -1
  299. package/dist/features/search/components/SearchResultsPageView.js +2 -2
  300. package/dist/features/search/components/index.d.ts +0 -6
  301. package/dist/features/search/components/index.js +0 -3
  302. package/dist/features/search/hooks/useNavSuggestions.d.ts +13 -0
  303. package/dist/features/search/hooks/useScopedSearch.d.ts +34 -0
  304. package/dist/features/search/hooks/useScopedSearch.js +114 -0
  305. package/dist/features/search/hooks/useSiteSearch.d.ts +26 -0
  306. package/dist/features/search/hooks/useSiteSearch.js +149 -0
  307. package/dist/features/search/index.d.ts +0 -4
  308. package/dist/features/search/index.js +0 -4
  309. package/dist/features/search/manifest.d.ts +12 -0
  310. package/dist/features/search/manifest.js +17 -2
  311. package/dist/features/search/server.d.ts +0 -3
  312. package/dist/features/search/server.js +0 -3
  313. package/dist/features/seller/components/SellerListingTypeView.d.ts +1 -1
  314. package/dist/features/seller/components/SellerListingTypeView.js +20 -0
  315. package/dist/features/seller/components/SellerPayoutSettingsView.js +35 -14
  316. package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
  317. package/dist/features/seller/components/SellerProductShell.js +2 -1
  318. package/dist/features/seller/components/SellerProductsView.js +3 -2
  319. package/dist/features/seller/components/SellerSidebar.js +1 -1
  320. package/dist/features/seller/components/SellerSparesView.d.ts +17 -0
  321. package/dist/features/seller/components/SellerSparesView.js +6 -0
  322. package/dist/features/seller/components/index.d.ts +2 -0
  323. package/dist/features/seller/components/index.js +1 -0
  324. package/dist/features/shell/CommandPalette.js +1 -1
  325. package/dist/features/sticker-trace/schemas/firestore.d.ts +19 -0
  326. package/dist/features/stores/components/StoreAuctionsListing.js +2 -1
  327. package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
  328. package/dist/features/stores/components/StoreDetailLayoutView.js +7 -82
  329. package/dist/features/stores/components/StoreHeader.js +1 -2
  330. package/dist/features/stores/components/StoreSparesPageView.d.ts +27 -0
  331. package/dist/features/stores/components/StoreSparesPageView.js +48 -0
  332. package/dist/features/stores/schemas/firestore.d.ts +19 -0
  333. package/dist/features/tester/seed-data/authored/buying__spares-and-groups.d.ts +2 -0
  334. package/dist/features/tester/seed-data/authored/buying__spares-and-groups.js +96 -0
  335. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
  336. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +392 -45
  337. package/dist/features/tester/seed-data/authored/content-discovery__category-tabs-franchise-bundles.js +54 -32
  338. package/dist/features/tester/seed-data/authored/content-discovery__parts-database.js +3 -2
  339. package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.d.ts +2 -0
  340. package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.js +73 -0
  341. package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.d.ts +2 -0
  342. package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.js +340 -0
  343. package/dist/features/tester/seed-data/authored/index.js +16 -0
  344. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.d.ts +1 -0
  345. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.js +57 -0
  346. package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.d.ts +2 -0
  347. package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.js +77 -0
  348. package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.d.ts +2 -0
  349. package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.js +58 -0
  350. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +5 -4
  351. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +384 -18
  352. package/dist/index.d.ts +17 -57
  353. package/dist/index.js +35 -96
  354. package/dist/next/routing/route-map.d.ts +42 -1
  355. package/dist/next/routing/route-map.js +45 -0
  356. package/dist/providers/db-firebase/base.repository.d.ts +22 -0
  357. package/dist/providers/db-firebase/base.repository.js +36 -0
  358. package/dist/schemas/registry.d.ts +15 -6
  359. package/dist/security/blind-index-tokens.d.ts +54 -0
  360. package/dist/security/blind-index-tokens.js +152 -0
  361. package/dist/security/index.d.ts +1 -1
  362. package/dist/security/index.js +1 -1
  363. package/dist/security/settings-encryption.d.ts +35 -0
  364. package/dist/security/settings-encryption.js +91 -0
  365. package/dist/seed/_helpers/brand-rows.js +38 -14
  366. package/dist/seed/_helpers/category-forest.js +73 -7
  367. package/dist/seed/_helpers/category-images-generated.d.ts +25 -6
  368. package/dist/seed/_helpers/category-images-generated.js +81 -6
  369. package/dist/seed/_helpers/category-models.d.ts +1 -1
  370. package/dist/seed/_helpers/category-models.js +7 -1
  371. package/dist/seed/_helpers/category-parts-glossary-map.js +8 -0
  372. package/dist/seed/_helpers/category-parts.d.ts +1 -1
  373. package/dist/seed/_helpers/category-parts.js +50 -2
  374. package/dist/seed/_helpers/character-features.d.ts +1 -1
  375. package/dist/seed/_helpers/character-features.js +2 -1
  376. package/dist/seed/_helpers/franchise-rows.js +10 -2
  377. package/dist/seed/_helpers/media.d.ts +47 -0
  378. package/dist/seed/_helpers/media.js +34 -0
  379. package/dist/seed/authenticity-knowledge-seed-data.d.ts +49 -5
  380. package/dist/seed/authenticity-knowledge-seed-data.js +10001 -549
  381. package/dist/seed/categories-seed-data.js +124 -20
  382. package/dist/seed/grouped-listings-seed-data.js +16 -0
  383. package/dist/seed/homepage-sections-seed-data.js +94 -5
  384. package/dist/seed/index.d.ts +2 -3
  385. package/dist/seed/index.js +2 -2
  386. package/dist/seed/manifest.js +3 -0
  387. package/dist/seed/media-assets-seed-data.d.ts +1 -1
  388. package/dist/seed/media-assets-seed-data.js +746 -196
  389. package/dist/seed/model-composition-seed-data.js +122 -6
  390. package/dist/seed/part-glossary-seed-data.d.ts +1 -1
  391. package/dist/seed/part-glossary-seed-data.js +37219 -463
  392. package/dist/seed/products-art-seed-data.js +7 -18
  393. package/dist/seed/products-auctions-seed-data.js +56 -47
  394. package/dist/seed/products-beyblade-x-seed-data.d.ts +2 -0
  395. package/dist/seed/products-beyblade-x-seed-data.js +476 -0
  396. package/dist/seed/products-catalogue-seed-data.d.ts +5 -5
  397. package/dist/seed/products-catalogue-seed-data.js +1500 -1240
  398. package/dist/seed/products-classifieds-seed-data.js +9 -27
  399. package/dist/seed/products-digital-codes-seed-data.js +9 -18
  400. package/dist/seed/products-live-items-seed-data.js +5 -13
  401. package/dist/seed/products-preorders-seed-data.js +67 -33
  402. package/dist/seed/products-prize-draws-seed-data.js +8 -17
  403. package/dist/seed/products-spares-seed-data.d.ts +2 -0
  404. package/dist/seed/products-spares-seed-data.js +368 -0
  405. package/dist/seed/products-standard-seed-data.js +39 -126
  406. package/dist/seed/products-stickers-seed-data.js +59 -15
  407. package/dist/seed/site-settings-seed-data.js +8 -0
  408. package/dist/seo/json-ld.d.ts +25 -0
  409. package/dist/seo/json-ld.js +28 -0
  410. package/dist/server-entry.d.ts +3 -1
  411. package/dist/server-entry.js +2 -2
  412. package/dist/server.d.ts +11 -9
  413. package/dist/server.js +35 -25
  414. package/dist/styles.css +202 -1
  415. package/dist/tailwind-input.css +31 -17
  416. package/dist/tailwind-utilities.css +1 -1
  417. package/dist/ui/components/Accordion.js +1 -1
  418. package/dist/ui/components/Breadcrumb.js +1 -1
  419. package/dist/ui/components/DetailPageGallery.js +0 -2
  420. package/dist/ui/components/DetailPageHero.js +0 -1
  421. package/dist/ui/components/DetailPageTabs.js +1 -1
  422. package/dist/ui/components/Divider.js +3 -3
  423. package/dist/ui/components/GatedPrice.js +5 -1
  424. package/dist/ui/components/HorizontalScroller.js +1 -1
  425. package/dist/ui/components/ListingLayout.js +3 -3
  426. package/dist/ui/components/MediaTabs.style.css +81 -0
  427. package/dist/ui/components/Pagination.js +1 -1
  428. package/dist/ui/components/PendingValue.d.ts +45 -0
  429. package/dist/ui/components/PendingValue.js +7 -0
  430. package/dist/ui/components/Radio.style.css +119 -0
  431. package/dist/ui/components/RatingDisplay.js +2 -2
  432. package/dist/ui/components/SettingsSection.js +0 -2
  433. package/dist/ui/components/SiteLogo.js +3 -0
  434. package/dist/ui/components/SiteMark.js +3 -0
  435. package/dist/ui/components/SortDropdown.js +1 -1
  436. package/dist/ui/components/SpecTable.d.ts +58 -0
  437. package/dist/ui/components/SpecTable.js +8 -0
  438. package/dist/ui/components/StarRating.js +1 -3
  439. package/dist/ui/components/SummaryCard.js +1 -1
  440. package/dist/ui/components/index.style.css +1 -0
  441. package/dist/ui/icons/icon-registry.d.ts +1 -0
  442. package/dist/ui/icons/icon-registry.js +9 -1
  443. package/dist/ui/index.d.ts +4 -0
  444. package/dist/ui/index.js +2 -0
  445. package/dist/utils/search-txt-query.d.ts +12 -0
  446. package/dist/utils/search-txt-query.js +12 -0
  447. package/package.json +1 -1
  448. package/scripts/dedupe-peer-deps.mjs +18 -0
  449. package/scripts/seed-cli.mjs +250 -35
  450. package/scripts/verify-css-build.mjs +118 -37
  451. package/dist/_internal/server/features/search/actions.d.ts +0 -7
  452. package/dist/_internal/server/features/search/actions.js +0 -21
  453. package/dist/_internal/server/features/search/data.d.ts +0 -15
  454. package/dist/_internal/server/features/search/data.js +0 -18
  455. package/dist/_internal/server/features/search/index.d.ts +0 -3
  456. package/dist/_internal/server/features/search/index.js +0 -2
  457. package/dist/features/homepage/api/[id]/route.d.ts +0 -23
  458. package/dist/features/homepage/api/[id]/route.js +0 -103
  459. package/dist/features/homepage/api/route.d.ts +0 -14
  460. package/dist/features/homepage/api/route.js +0 -140
  461. package/dist/features/homepage/api/sections/[id]/route.d.ts +0 -26
  462. package/dist/features/homepage/api/sections/[id]/route.js +0 -95
  463. package/dist/features/homepage/api/sections/route.d.ts +0 -13
  464. package/dist/features/homepage/api/sections/route.js +0 -82
  465. package/dist/features/homepage/components/AdvertisementBanner.d.ts +0 -14
  466. package/dist/features/homepage/components/AdvertisementBanner.js +0 -35
  467. package/dist/features/homepage/components/BeforeAfterCard.d.ts +0 -9
  468. package/dist/features/homepage/components/BeforeAfterCard.js +0 -73
  469. package/dist/features/homepage/components/FeaturedResultsSection.d.ts +0 -17
  470. package/dist/features/homepage/components/FeaturedResultsSection.js +0 -17
  471. package/dist/features/homepage/components/HeroBanner.d.ts +0 -7
  472. package/dist/features/homepage/components/HeroBanner.js +0 -43
  473. package/dist/features/homepage/components/HeroSection.d.ts +0 -7
  474. package/dist/features/homepage/components/HeroSection.js +0 -6
  475. package/dist/features/homepage/components/HomepageSkeleton.d.ts +0 -2
  476. package/dist/features/homepage/components/HomepageSkeleton.js +0 -21
  477. package/dist/features/homepage/components/HomepageView.d.ts +0 -25
  478. package/dist/features/homepage/components/HomepageView.js +0 -5
  479. package/dist/features/homepage/components/NewsletterBanner.d.ts +0 -23
  480. package/dist/features/homepage/components/NewsletterBanner.js +0 -37
  481. package/dist/features/homepage/components/SiteFeaturesSection.d.ts +0 -14
  482. package/dist/features/homepage/components/SiteFeaturesSection.js +0 -11
  483. package/dist/features/homepage/components/TrustBadges.d.ts +0 -6
  484. package/dist/features/homepage/components/TrustBadges.js +0 -46
  485. package/dist/features/homepage/components/TrustIndicatorsSection.d.ts +0 -12
  486. package/dist/features/homepage/components/TrustIndicatorsSection.js +0 -11
  487. package/dist/features/homepage/hooks/useHomepage.d.ts +0 -11
  488. package/dist/features/homepage/hooks/useHomepage.js +0 -17
  489. package/dist/features/homepage/hooks/useHomepageSections.d.ts +0 -2
  490. package/dist/features/homepage/hooks/useHomepageSections.js +0 -10
  491. package/dist/features/homepage/repository/homepage.repository.d.ts +0 -11
  492. package/dist/features/homepage/repository/homepage.repository.js +0 -25
  493. package/dist/features/search/actions/index.d.ts +0 -1
  494. package/dist/features/search/actions/index.js +0 -1
  495. package/dist/features/search/actions/search-actions.d.ts +0 -18
  496. package/dist/features/search/actions/search-actions.js +0 -43
  497. package/dist/features/search/api/route.d.ts +0 -22
  498. package/dist/features/search/api/route.js +0 -128
  499. package/dist/features/search/columns/index.d.ts +0 -17
  500. package/dist/features/search/columns/index.js +0 -49
  501. package/dist/features/search/components/SearchFiltersRow.d.ts +0 -22
  502. package/dist/features/search/components/SearchFiltersRow.js +0 -21
  503. package/dist/features/search/components/SearchResultsSection.d.ts +0 -53
  504. package/dist/features/search/components/SearchResultsSection.js +0 -35
  505. package/dist/features/search/components/SearchView.d.ts +0 -27
  506. package/dist/features/search/components/SearchView.js +0 -8
  507. package/dist/features/search/hooks/useSearch.d.ts +0 -21
  508. package/dist/features/search/hooks/useSearch.js +0 -33
  509. package/dist/features/search/repository/search.repository.d.ts +0 -14
  510. package/dist/features/search/repository/search.repository.js +0 -59
  511. package/dist/features/search/schemas/index.d.ts +0 -70
  512. package/dist/features/search/schemas/index.js +0 -36
  513. package/dist/features/search/types/index.d.ts +0 -48
  514. package/dist/features/stores/components/StoreScopedSearch.d.ts +0 -17
  515. package/dist/features/stores/components/StoreScopedSearch.js +0 -27
  516. package/dist/seed/defaults/homepage-sections.d.ts +0 -2
  517. package/dist/seed/defaults/homepage-sections.js +0 -60
  518. package/dist/seed/factories/homepage-section.factory.d.ts +0 -10
  519. package/dist/seed/factories/homepage-section.factory.js +0 -13
  520. /package/dist/{features/search/types/index.js → _internal/shared/listing-types/spares/og.d.ts} +0 -0
@@ -267,16 +267,106 @@ export declare class ProductRepository extends BaseRepository<ProductDocument> {
267
267
  updateAvailableQuantity(productId: string, quantity: number): Promise<void>;
268
268
  updateBid(productId: string, bidAmount: number, bidCount: number): Promise<void>;
269
269
  findAvailable(): Promise<ProductDocument[]>;
270
+ /**
271
+ * Every member of a group, UNFILTERED — drafts, and every listing type.
272
+ *
273
+ * 🛑 This is the scope `dissolveGroup` needs and the ONLY one that may be
274
+ * unfiltered. A filtered dissolve leaves the excluded members carrying a
275
+ * `groupId` pointing at a group that no longer exists, which nothing ever
276
+ * clears — and that orphan is invisible until someone wonders why a product
277
+ * claims to be in a group with no other members.
278
+ */
279
+ findAllByGroupId(groupId: string): Promise<ProductDocument[]>;
280
+ /**
281
+ * Group members a BUYER may see: eligible types, published only.
282
+ *
283
+ * 🛑 The type filter is DERIVED from `canJoinProductGroup`, not hard-coded.
284
+ * It used to be a literal `["standard", "pre-order"]`, which silently dropped
285
+ * every `stickers` / `art` member from the query — so `ShowGroupSection` saw
286
+ * one member and returned null, and the picker was unreachable with nothing
287
+ * erroring anywhere (Root Cause #58).
288
+ *
289
+ * 🛑 The `status` filter is NEW and is a leak fix, not a tightening. There
290
+ * was no status filter at all, so DRAFT members were reaching the public
291
+ * `/api/products/group/[groupId]` payload; widening the type list without
292
+ * this would have widened that leak at the same time.
293
+ */
294
+ findGroupMembersForPublic(groupId: string): Promise<ProductDocument[]>;
295
+ /**
296
+ * Union the child-side query with the PARENT's own `groupChildSlugs`.
297
+ *
298
+ * Mirrors `resolveBundleMemberIds`, and exists for the same reason: Root
299
+ * Cause #42 documented a parent carrying `groupChildSlugs` while its children
300
+ * had no `groupId`, so a child-side query resolved only the parent and the
301
+ * group rendered as one member. The repository's six mutating methods all
302
+ * write both sides in one batch, so code cannot produce that state — but a
303
+ * seeded fixture or a direct Firestore edit still can, and the READER was
304
+ * never made resilient. `listBundleMembers` got this fix; this did not.
305
+ */
306
+ private withParentSideFallback;
307
+ /**
308
+ * @deprecated Ambiguous about scope — say which one you mean.
309
+ * Kept so no caller silently changes behaviour; it resolves to the PUBLIC
310
+ * scope, which is what every existing caller wanted.
311
+ */
270
312
  findByGroupId(groupId: string): Promise<ProductDocument[]>;
271
313
  startGroup(productId: string, slug: string): Promise<void>;
272
314
  updateGroupTitle(productId: string, groupTitle: string): Promise<void>;
273
315
  dissolveGroup(groupId: string): Promise<void>;
316
+ /**
317
+ * Link ONE child into a parent's group.
318
+ *
319
+ * 🛑 `arrayUnion`, not a spread of the in-memory `parent.groupChildSlugs`.
320
+ *
321
+ * The spread read a snapshot the CALLER was holding, so linking N children in
322
+ * a loop produced exactly ONE entry: every iteration computed
323
+ * `[...(stale ?? []), child]` from the same pre-loop document and the last
324
+ * write won. Nothing errored — each child got its own `groupId` correctly, so
325
+ * `findAllByGroupId` found them all while the parent's own
326
+ * `groupChildSlugs` claimed one member, which is what the group picker's
327
+ * fallback path and `GroupSettingsPanel` read.
328
+ *
329
+ * `arrayUnion` is also idempotent, so re-linking an existing child is a
330
+ * no-op instead of a duplicate id.
331
+ *
332
+ * For a known set, prefer `linkChildrenToGroup` below — one batch instead of
333
+ * N, which matters against Rule #6's round-trip budget when promoting a
334
+ * 60-part sticker sheet.
335
+ */
274
336
  linkChildToGroup(parent: ProductDocument, child: ProductDocument): Promise<void>;
337
+ /**
338
+ * Link SEVERAL children into a parent's group in one batch.
339
+ *
340
+ * Built for `promoteStickerSheetToListings`, which links every unique part of
341
+ * a sheet at once — N calls to `linkChildToGroup` would be N batch commits
342
+ * for work that is one logical change.
343
+ */
344
+ linkChildrenToGroup(parent: ProductDocument, children: readonly ProductDocument[]): Promise<void>;
275
345
  unlinkChildFromGroup(parent: ProductDocument, child: ProductDocument): Promise<void>;
276
346
  leaveGroup(child: ProductDocument, parent: ProductDocument | null): Promise<void>;
277
347
  addChildProduct(parent: ProductDocument, child: Omit<import("../schemas/firestore").ProductCreateInput, "groupId" | "isGroupParent" | "groupParentSlug" | "groupTitle">): Promise<ProductDocument>;
278
348
  deleteByStore(storeId: string): Promise<number>;
279
349
  delete(id: string): Promise<void>;
350
+ /**
351
+ * Every live listing OF one glossary part, across all stores.
352
+ *
353
+ * 🛑 NOT filtered by `listingType`, deliberately. Both `spares` and the
354
+ * 972 generated per-leaf catalogue rows (which are `standard`) carry
355
+ * `partGlossaryId`, and a buyer on `/parts/{slot}/{code}` wants any listing
356
+ * of that part — not only the ones that happen to be filed under the newer
357
+ * type. Narrowing to `spares` would hide most of the real inventory.
358
+ *
359
+ * 🛑 `orderBy` is `createdAt`, which EVERY document carries
360
+ * (`BaseRepository.create` writes it). Ordering by an optional field silently
361
+ * excludes every row lacking it — Root Cause #100, where `itemsSold` on zero
362
+ * of 95 products made a store`s whole review endpoint return nothing.
363
+ *
364
+ * Availability is filtered IN MEMORY rather than in the query: "available" is
365
+ * negation-shaped and no query expresses it, which is the asymmetry
366
+ * `baseAvailable` exists for. The window is bounded, so the cost is a few
367
+ * rows read and discarded.
368
+ */
369
+ findByPartGlossaryId(partGlossaryId: string, limit?: number): Promise<ProductDocument[]>;
280
370
  static readonly SIEVE_FIELDS: {
281
371
  id: {
282
372
  canFilter: boolean;
@@ -330,6 +420,14 @@ export declare class ProductRepository extends BaseRepository<ProductDocument> {
330
420
  canFilter: boolean;
331
421
  canSort: boolean;
332
422
  };
423
+ partGlossaryId: {
424
+ canFilter: boolean;
425
+ canSort: boolean;
426
+ };
427
+ colourway: {
428
+ canFilter: boolean;
429
+ canSort: boolean;
430
+ };
333
431
  isPromoted: {
334
432
  canFilter: boolean;
335
433
  canSort: boolean;
@@ -596,6 +694,7 @@ export declare class ProductRepository extends BaseRepository<ProductDocument> {
596
694
  status?: string;
597
695
  categoriesIn?: string[];
598
696
  search?: string;
697
+ brandName?: string;
599
698
  }): Promise<FirebaseSieveResult<ProductDocument>>;
600
699
  /**
601
700
  * How many products of each listing type exist within a scope — the numbers
@@ -1,5 +1,5 @@
1
1
  import { normalizeError } from "../../../errors/normalize.js";
2
- import { increment, serverTimestamp } from "../../../contracts/field-ops.js";
2
+ import { arrayUnion, increment, serverTimestamp } from "../../../contracts/field-ops.js";
3
3
  // 🛑 `../../../errors` re-exports the REAL ValidationError (errors/validation-error),
4
4
  // which is the one `mapToHttpError` instanceof-checks to produce a 400. The
5
5
  // unrelated same-named class under `_internal/shared/errors` falls through every
@@ -24,7 +24,7 @@ import { planSearchTxt, beginSearchWindow, emptySearchResult, } from "../../../u
24
24
  // One definition of "which fields feed searchTxt", shared with the seed
25
25
  // wrapper. Three copies existed and two were missing the same three fields.
26
26
  import { buildProductSearchTxt } from "../../../utils/search-txt-builders.js";
27
- import { PRODUCT_COLLECTION, ProductStatusValues } from "../schemas/index.js";
27
+ import { PRODUCT_COLLECTION, ProductStatusValues, toProductImages } from "../schemas/index.js";
28
28
  // Collection NAMES only — deliberately not `categoriesRepository` or
29
29
  // `taxCodesRepository`. See deriveTaxonomy()'s header for why these are raw
30
30
  // reads: no repository in this codebase imports another feature's, because of
@@ -45,6 +45,12 @@ import { MAX_FEATURES_PER_PRODUCT } from "../schemas/product-features.js";
45
45
  // The ONE `{{placeholder}}` implementation, promoted out of the FAQ schema in
46
46
  // B3. A second regex here would be Root Cause #75's shape.
47
47
  import { interpolate } from "../../../_internal/shared/templating/placeholders.js";
48
+ /*
49
+ * From their DEFINING modules, not a barrel — a repository reaching the wide
50
+ * entry is how the Turbopack client-bundle trap gets re-opened (Root Cause #18).
51
+ */
52
+ import { ALL_LISTING_TYPES } from "../../../_internal/shared/listing-types/feature-flags.js";
53
+ import { pluginFor } from "../../../_internal/shared/listing-types/_registry.js";
48
54
  import { PRODUCT_FIELDS } from "../../../constants/field-names.js";
49
55
  /**
50
56
  * Canonical listing-kind tokens used in `listingType`. Note: the public Sieve
@@ -73,6 +79,21 @@ const LISTING_KIND_ALIAS_MAP = {
73
79
  live: LISTING_TYPE_VALUES.LIVE,
74
80
  art: LISTING_TYPE_VALUES.ART,
75
81
  stickers: LISTING_TYPE_VALUES.STICKERS,
82
+ /*
83
+ * 🛑 Root Cause #58 lives here, and it is the single most expensive line to
84
+ * omit in this whole change. The alias returns `""` for an unrecognised
85
+ * token and `expandFilterAliases` then DROPS the empty clause — so a missing
86
+ * entry does not error, it deletes the `listingType` filter from the query.
87
+ * `art` and `stickers` were added to the union, the registry and the
88
+ * capability map and not to this map, and every art/sticker browse page
89
+ * silently returned the entire catalogue until someone reported it.
90
+ *
91
+ * `Record<ProductListingKind, string>` makes it compile-checked against THAT
92
+ * union — but `ProductListingKind` is itself hand-written above and is not
93
+ * checked against `ListingType`, which is why this is still on the unchecked
94
+ * list.
95
+ */
96
+ spares: LISTING_TYPE_VALUES.SPARES,
76
97
  // Legacy → canonical.
77
98
  product: LISTING_TYPE_VALUES.STANDARD,
78
99
  preorder: LISTING_TYPE_VALUES.PRE_ORDER,
@@ -232,6 +253,17 @@ export class ProductRepository extends BaseRepository {
232
253
  if (!doc.categorySlugs || doc.categorySlugs.length === 0) {
233
254
  doc.categorySlugs = doc.category ? [doc.category] : [];
234
255
  }
256
+ /*
257
+ * A6 — widen a legacy `images: string[]` document to `ProductImage[]`.
258
+ *
259
+ * 🛑 This is HALF the normalisation and must stay paired with the write
260
+ * half in `create`/`update` below. Read-only widening is Root Cause #101
261
+ * exactly: the field would be the object form on every object anyone
262
+ * inspects and still a bare string array in Firestore, so the next write
263
+ * of an untouched document would persist whichever shape the caller
264
+ * happened to hold.
265
+ */
266
+ doc.images = toProductImages(doc.images);
235
267
  return doc;
236
268
  }
237
269
  /**
@@ -833,6 +865,13 @@ export class ProductRepository extends BaseRepository {
833
865
  ...data,
834
866
  ...derived,
835
867
  ...stock,
868
+ /*
869
+ * A6 — only when the write NAMES `images`. An unconditional
870
+ * `toProductImages(data.images)` would write `[]` over a real gallery on
871
+ * every stock decrement and status flip, because `data` does not carry
872
+ * the field at all on those paths.
873
+ */
874
+ ...(data.images !== undefined ? { images: toProductImages(data.images) } : {}),
836
875
  searchTxt: buildProductSearchTxt(merged),
837
876
  });
838
877
  this.cacheSet(updated);
@@ -907,7 +946,17 @@ export class ProductRepository extends BaseRepository {
907
946
  // all. A seed row already carrying the correct chain derives to the same
908
947
  // value, so this is a no-op for every existing fixture.
909
948
  const derived = await this.deriveTaxonomy(input, true);
910
- const withTaxonomy = { ...input, ...derived };
949
+ /*
950
+ * A6 — the WRITE half of the `images` normalisation (the read half is in
951
+ * `mapDoc`). Every create path funnels through here, so a caller handing
952
+ * us `string[]` — a seed row, an older client, the shipment-link route —
953
+ * stores the object form rather than leaving the collection mixed.
954
+ */
955
+ const withTaxonomy = {
956
+ ...input,
957
+ ...derived,
958
+ ...(input.images !== undefined ? { images: toProductImages(input.images) } : {}),
959
+ };
911
960
  const productData = {
912
961
  ...withTaxonomy,
913
962
  barcodeId,
@@ -1053,17 +1102,89 @@ export class ProductRepository extends BaseRepository {
1053
1102
  .get();
1054
1103
  return snapshot.docs.map((doc) => this.mapDoc(doc));
1055
1104
  }
1056
- async findByGroupId(groupId) {
1057
- // Tier GP: groups may mix standard products + pre-orders (never auctions).
1105
+ /**
1106
+ * Every member of a group, UNFILTERED — drafts, and every listing type.
1107
+ *
1108
+ * 🛑 This is the scope `dissolveGroup` needs and the ONLY one that may be
1109
+ * unfiltered. A filtered dissolve leaves the excluded members carrying a
1110
+ * `groupId` pointing at a group that no longer exists, which nothing ever
1111
+ * clears — and that orphan is invisible until someone wonders why a product
1112
+ * claims to be in a group with no other members.
1113
+ */
1114
+ async findAllByGroupId(groupId) {
1058
1115
  const snapshot = await this.db
1059
1116
  .collection(this.collection)
1060
1117
  .where("groupId", "==", groupId)
1061
- .where(PRODUCT_FIELDS.LISTING_TYPE, "in", [
1062
- LISTING_TYPE_VALUES.STANDARD,
1063
- LISTING_TYPE_VALUES.PRE_ORDER,
1064
- ])
1065
1118
  .get();
1066
- return snapshot.docs.map((doc) => this.mapDoc(doc));
1119
+ const byQuery = snapshot.docs.map((doc) => this.mapDoc(doc));
1120
+ return this.withParentSideFallback(groupId, byQuery);
1121
+ }
1122
+ /**
1123
+ * Group members a BUYER may see: eligible types, published only.
1124
+ *
1125
+ * 🛑 The type filter is DERIVED from `canJoinProductGroup`, not hard-coded.
1126
+ * It used to be a literal `["standard", "pre-order"]`, which silently dropped
1127
+ * every `stickers` / `art` member from the query — so `ShowGroupSection` saw
1128
+ * one member and returned null, and the picker was unreachable with nothing
1129
+ * erroring anywhere (Root Cause #58).
1130
+ *
1131
+ * 🛑 The `status` filter is NEW and is a leak fix, not a tightening. There
1132
+ * was no status filter at all, so DRAFT members were reaching the public
1133
+ * `/api/products/group/[groupId]` payload; widening the type list without
1134
+ * this would have widened that leak at the same time.
1135
+ */
1136
+ async findGroupMembersForPublic(groupId) {
1137
+ const eligible = ALL_LISTING_TYPES.filter((t) => pluginFor(t).canJoinProductGroup);
1138
+ const snapshot = await this.db
1139
+ .collection(this.collection)
1140
+ .where("groupId", "==", groupId)
1141
+ // `in` caps at 30 values; this is 4 of 9 today and cannot approach it.
1142
+ .where(PRODUCT_FIELDS.LISTING_TYPE, "in", eligible)
1143
+ .where(PRODUCT_FIELDS.STATUS, "==", ProductStatusValues.PUBLISHED)
1144
+ .get();
1145
+ const byQuery = snapshot.docs.map((doc) => this.mapDoc(doc));
1146
+ const withFallback = await this.withParentSideFallback(groupId, byQuery);
1147
+ /*
1148
+ * 🛑 The fallback results are filtered TOO. Without this the fallback
1149
+ * becomes the hole the query just closed — a draft or an ineligible member
1150
+ * would reach the public payload through the parent's own list.
1151
+ */
1152
+ const eligibleSet = new Set(eligible);
1153
+ return withFallback.filter((p) => eligibleSet.has(String(p.listingType ?? LISTING_TYPE_VALUES.STANDARD)) &&
1154
+ p.status === ProductStatusValues.PUBLISHED);
1155
+ }
1156
+ /**
1157
+ * Union the child-side query with the PARENT's own `groupChildSlugs`.
1158
+ *
1159
+ * Mirrors `resolveBundleMemberIds`, and exists for the same reason: Root
1160
+ * Cause #42 documented a parent carrying `groupChildSlugs` while its children
1161
+ * had no `groupId`, so a child-side query resolved only the parent and the
1162
+ * group rendered as one member. The repository's six mutating methods all
1163
+ * write both sides in one batch, so code cannot produce that state — but a
1164
+ * seeded fixture or a direct Firestore edit still can, and the READER was
1165
+ * never made resilient. `listBundleMembers` got this fix; this did not.
1166
+ */
1167
+ async withParentSideFallback(groupId, byQuery) {
1168
+ const seen = new Set(byQuery.map((p) => p.id));
1169
+ /*
1170
+ * `startGroup` sets `groupId = parent.slug`, so the group id IS the
1171
+ * parent's slug and one lookup finds it. If that ever stops being true the
1172
+ * fallback simply finds nothing, which is the same behaviour as today.
1173
+ */
1174
+ const parent = byQuery.find((p) => p.isGroupParent) ?? (await this.findById(groupId));
1175
+ const missing = (parent?.groupChildSlugs ?? []).filter((id) => !seen.has(id));
1176
+ if (missing.length === 0)
1177
+ return byQuery;
1178
+ const extra = await Promise.all(missing.map((id) => this.findById(id)));
1179
+ return [...byQuery, ...extra.filter((p) => p !== null)];
1180
+ }
1181
+ /**
1182
+ * @deprecated Ambiguous about scope — say which one you mean.
1183
+ * Kept so no caller silently changes behaviour; it resolves to the PUBLIC
1184
+ * scope, which is what every existing caller wanted.
1185
+ */
1186
+ async findByGroupId(groupId) {
1187
+ return this.findGroupMembersForPublic(groupId);
1067
1188
  }
1068
1189
  async startGroup(productId, slug) {
1069
1190
  await this.getCollection().doc(productId).update({
@@ -1076,7 +1197,10 @@ export class ProductRepository extends BaseRepository {
1076
1197
  await this.getCollection().doc(productId).update({ groupTitle });
1077
1198
  }
1078
1199
  async dissolveGroup(groupId) {
1079
- const members = await this.findByGroupId(groupId);
1200
+ // UNFILTERED on purpose — see findAllByGroupId. Dissolving must clear every
1201
+ // member's fields, including drafts and ineligible types, or they keep a
1202
+ // groupId pointing at nothing.
1203
+ const members = await this.findAllByGroupId(groupId);
1080
1204
  const batch = this.db.batch();
1081
1205
  const clearFields = {
1082
1206
  groupId: null,
@@ -1090,15 +1214,62 @@ export class ProductRepository extends BaseRepository {
1090
1214
  }
1091
1215
  await batch.commit();
1092
1216
  }
1217
+ /**
1218
+ * Link ONE child into a parent's group.
1219
+ *
1220
+ * 🛑 `arrayUnion`, not a spread of the in-memory `parent.groupChildSlugs`.
1221
+ *
1222
+ * The spread read a snapshot the CALLER was holding, so linking N children in
1223
+ * a loop produced exactly ONE entry: every iteration computed
1224
+ * `[...(stale ?? []), child]` from the same pre-loop document and the last
1225
+ * write won. Nothing errored — each child got its own `groupId` correctly, so
1226
+ * `findAllByGroupId` found them all while the parent's own
1227
+ * `groupChildSlugs` claimed one member, which is what the group picker's
1228
+ * fallback path and `GroupSettingsPanel` read.
1229
+ *
1230
+ * `arrayUnion` is also idempotent, so re-linking an existing child is a
1231
+ * no-op instead of a duplicate id.
1232
+ *
1233
+ * For a known set, prefer `linkChildrenToGroup` below — one batch instead of
1234
+ * N, which matters against Rule #6's round-trip budget when promoting a
1235
+ * 60-part sticker sheet.
1236
+ */
1093
1237
  async linkChildToGroup(parent, child) {
1238
+ await this.linkChildrenToGroup(parent, [child]);
1239
+ }
1240
+ /**
1241
+ * Link SEVERAL children into a parent's group in one batch.
1242
+ *
1243
+ * Built for `promoteStickerSheetToListings`, which links every unique part of
1244
+ * a sheet at once — N calls to `linkChildToGroup` would be N batch commits
1245
+ * for work that is one logical change.
1246
+ */
1247
+ async linkChildrenToGroup(parent, children) {
1248
+ if (children.length === 0)
1249
+ return;
1094
1250
  const batch = this.db.batch();
1095
- batch.update(this.getCollection().doc(child.id), {
1096
- groupId: parent.groupId,
1097
- groupParentSlug: parent.slug ?? parent.id,
1098
- groupTitle: parent.groupTitle ?? null,
1099
- });
1251
+ for (const child of children) {
1252
+ batch.update(this.getCollection().doc(child.id), {
1253
+ groupId: parent.groupId,
1254
+ groupParentSlug: parent.slug ?? parent.id,
1255
+ groupTitle: parent.groupTitle ?? null,
1256
+ });
1257
+ }
1100
1258
  batch.update(this.getCollection().doc(parent.id), {
1101
- groupChildSlugs: [...(parent.groupChildSlugs ?? []), child.id],
1259
+ /*
1260
+ * Ids, matching `unlinkChildFromGroup`'s filter, which removes by id OR
1261
+ * slug. These are pure slugs for products (`id === slug`), so the two
1262
+ * agree — but the field name says "slugs" and the stored values are ids,
1263
+ * which is worth knowing before writing a reader that assumes either.
1264
+ */
1265
+ /*
1266
+ * 🛑 `arrayUnion` from the CONTRACTS layer, not `firebase-admin`
1267
+ * directly. Two sibling repositories import `FieldValue` from
1268
+ * firebase-admin and this one deliberately does not — its own imports go
1269
+ * through `contracts/field-ops`, which is what keeps the admin SDK out of
1270
+ * this module's static import graph (Root Cause #24/#6).
1271
+ */
1272
+ groupChildSlugs: arrayUnion(...children.map((c) => c.id)),
1102
1273
  });
1103
1274
  await batch.commit();
1104
1275
  }
@@ -1185,6 +1356,39 @@ export class ProductRepository extends BaseRepository {
1185
1356
  await super.delete(id);
1186
1357
  await this.syncCategoryCounts(prior, null);
1187
1358
  }
1359
+ /**
1360
+ * Every live listing OF one glossary part, across all stores.
1361
+ *
1362
+ * 🛑 NOT filtered by `listingType`, deliberately. Both `spares` and the
1363
+ * 972 generated per-leaf catalogue rows (which are `standard`) carry
1364
+ * `partGlossaryId`, and a buyer on `/parts/{slot}/{code}` wants any listing
1365
+ * of that part — not only the ones that happen to be filed under the newer
1366
+ * type. Narrowing to `spares` would hide most of the real inventory.
1367
+ *
1368
+ * 🛑 `orderBy` is `createdAt`, which EVERY document carries
1369
+ * (`BaseRepository.create` writes it). Ordering by an optional field silently
1370
+ * excludes every row lacking it — Root Cause #100, where `itemsSold` on zero
1371
+ * of 95 products made a store`s whole review endpoint return nothing.
1372
+ *
1373
+ * Availability is filtered IN MEMORY rather than in the query: "available" is
1374
+ * negation-shaped and no query expresses it, which is the asymmetry
1375
+ * `baseAvailable` exists for. The window is bounded, so the cost is a few
1376
+ * rows read and discarded.
1377
+ */
1378
+ async findByPartGlossaryId(partGlossaryId, limit = 12) {
1379
+ if (!partGlossaryId)
1380
+ return [];
1381
+ const snap = await this.getCollection()
1382
+ .where(PRODUCT_FIELDS.PART_GLOSSARY_ID, "==", partGlossaryId)
1383
+ .where(PRODUCT_FIELDS.STATUS, "==", PRODUCT_FIELDS.STATUS_VALUES.PUBLISHED)
1384
+ .orderBy(PRODUCT_FIELDS.CREATED_AT, "desc")
1385
+ // Over-fetch, because the availability filter below removes rows. Taking
1386
+ // exactly `limit` here would return fewer than `limit` buyable listings
1387
+ // whenever any of them were sold.
1388
+ .limit(Math.min(60, limit * 3))
1389
+ .get();
1390
+ return snap.docs.map((d) => this.mapDoc(d)).slice(0, limit);
1391
+ }
1188
1392
  /**
1189
1393
  * Shared scope construction for `list()` and `countBy*()` — both must narrow
1190
1394
  * by exactly the same store/status/category/search predicates or a tab's
@@ -1247,7 +1451,11 @@ export class ProductRepository extends BaseRepository {
1247
1451
  }
1248
1452
  return baseQuery;
1249
1453
  }
1250
- async list(model, opts) {
1454
+ async list(model,
1455
+ // `brandName` was already honoured by `buildScopedQuery` and simply not
1456
+ // declared here, so a brand-scoped caller had to express the brand as a
1457
+ // Sieve clause instead — a second spelling of one filter.
1458
+ opts) {
1251
1459
  /*
1252
1460
  * 🛑 THE EMPTY GUARD — a non-blank query that yields NO usable token must
1253
1461
  * return nothing, not everything.
@@ -1481,6 +1689,20 @@ ProductRepository.SIEVE_FIELDS = {
1481
1689
  // admin and seller product lists.
1482
1690
  featured: { canFilter: true, canSort: true },
1483
1691
  listingType: { canFilter: true, canSort: false },
1692
+ /*
1693
+ * 🛑 Filterable so a `partGlossaryId` filter is not SILENTLY DROPPED.
1694
+ * `sieve.ts` sets `throwExceptions: false`, so a field absent from this map
1695
+ * does not raise — `findField` returns undefined and the clause vanishes,
1696
+ * which on a page scoped to one part means the ENTIRE catalogue comes back
1697
+ * (Root Cause #62). Both of these are real `ProductDocument` fields, so
1698
+ * neither is the orphan half of that pattern.
1699
+ *
1700
+ * `canSort: false` on both: they are identity, not an ordering anyone wants
1701
+ * — and a sort option whose field is `canSort: false` is dropped just as
1702
+ * silently (Root Cause #63).
1703
+ */
1704
+ partGlossaryId: { canFilter: true, canSort: false },
1705
+ colourway: { canFilter: true, canSort: false },
1484
1706
  isPromoted: { canFilter: true, canSort: true },
1485
1707
  isOnSale: { canFilter: true, canSort: false },
1486
1708
  price: { canFilter: true, canSort: true },
@@ -2,7 +2,8 @@
2
2
  * Products Firestore Document Types & Constants
3
3
  */
4
4
  import { type GenerateProductIdInput, type GenerateAuctionIdInput, type GeneratePreOrderIdInput } from "../../../utils/id-generators";
5
- import type { ProductStatus, ListingType } from "../types";
5
+ import type { ProductStatus, ListingType, ProductImage } from "../types";
6
+ export type { ProductImage };
6
7
  import type { BaseDocument } from "../../../_internal/shared/types/base-document";
7
8
  import type { LotteryConfig } from "../../lottery/types";
8
9
  export interface ProductVideoField {
@@ -12,6 +13,31 @@ export interface ProductVideoField {
12
13
  trimStart?: number;
13
14
  trimEnd?: number;
14
15
  }
16
+ /**
17
+ * Whatever a document, a request body or a seed row happens to hold, as
18
+ * `ProductImage[]`.
19
+ *
20
+ * 🛑 This is called on the WRITE path (`ProductRepository.create`/`update`)
21
+ * **and** on the read path (`mapDoc`), and both are required. Root Cause #101
22
+ * is exactly this shape: `mapDoc` backfilled `categorySlugs` on read while the
23
+ * write schema stripped it, so the field was present on every object anyone
24
+ * inspected and absent from the stored document — invisible to every query,
25
+ * and latent until a human created a listing.
26
+ *
27
+ * Accepts `string`, `ProductImage`, and a mixed array of both, because a
28
+ * partially-migrated collection genuinely contains all three.
29
+ */
30
+ export declare function toProductImages(input: unknown): ProductImage[];
31
+ /**
32
+ * Just the URLs, in order — for the many call sites that only ever needed a
33
+ * `string[]` (a lightbox's source list, an OG image pick, a media-abort
34
+ * cleanup list).
35
+ *
36
+ * This is a PROJECTION, computed on demand, not a stored mirror — so it cannot
37
+ * drift from `images` the way a denormalised second field would (Root Cause
38
+ * #42). Takes `unknown` so it also works on a legacy `string[]`.
39
+ */
40
+ export declare function productImageUrls(input: unknown): string[];
15
41
  export interface ProductSpecification {
16
42
  name: string;
17
43
  value: string;
@@ -256,7 +282,14 @@ export interface ProductDocument extends BaseDocument {
256
282
  stockQuantity: number;
257
283
  availableQuantity: number;
258
284
  mainImage: string;
259
- images: string[];
285
+ /**
286
+ * 🛑 `ProductImage[]`, not `string[]` (changed 2026-10-20, plan A6).
287
+ *
288
+ * Normalised by `toProductImages()` on BOTH the write path and `mapDoc`, so
289
+ * a legacy `string[]` document widens losslessly and a new write stores the
290
+ * object form. Call sites that only want URLs use `productImageUrls()`.
291
+ */
292
+ images: ProductImage[];
260
293
  video?: ProductVideoField;
261
294
  status: ProductStatus;
262
295
  storeId: string;
@@ -449,6 +482,52 @@ export interface ProductDocument extends BaseDocument {
449
482
  isPromoted?: boolean;
450
483
  isOnSale?: boolean;
451
484
  isSold?: boolean;
485
+ /**
486
+ * This listing is PRINTED OR BUILT WHEN ORDERED, so stock does not gate it.
487
+ *
488
+ * A per-LISTING flag, deliberately not implied by `listingType`. A seller can
489
+ * hold a finite run of pre-cut sticker sheets and also offer a
490
+ * print-on-demand sheet, and the two must coexist on the same type — which a
491
+ * type-level rule cannot express. (`showsStockQuantity` on the plugin is the
492
+ * type-level field and must NOT be repurposed for this.)
493
+ *
494
+ * 🛑 It bypasses the stock CHECK and never the DECREMENT. `availableQuantity`
495
+ * going negative on a made-to-order row IS the production queue — how many
496
+ * are owed — and `stock-restore.ts` requires the restore to mirror the
497
+ * decrement exactly, so skipping the decrement would make a cancelled order
498
+ * restore stock that was never taken.
499
+ *
500
+ * 🛑 Not snapshotted onto `CartLineMember`. A snapshot goes stale the moment
501
+ * the flag is flipped, and every check site already holds the product
502
+ * document — so it is derived, never copied (Root Cause #42).
503
+ *
504
+ * 🛑 CHECKED, not assumed: nothing auto-sets `isSold` when quantity reaches
505
+ * zero, so a made-to-order listing does NOT destroy itself on its first
506
+ * sale. `buildStockUpdatePayload` writes `availableQuantity` and the rule's
507
+ * `stockDecrementExtras` and nothing else; the only two writers of
508
+ * `isSold: true` in the whole tree are auction settlement and the auction
509
+ * buyout, both of which are selling a unique lot and are correct to do it.
510
+ * If a future "mark sold out automatically" feature is added, it must skip
511
+ * made-to-order rows or every one of them dies on its first order.
512
+ */
513
+ madeToOrder?: boolean;
514
+ /**
515
+ * The `stickerSheets` document this listing was promoted from.
516
+ *
517
+ * Set on BOTH the parent (the whole sheet) and every child (one cut), so the
518
+ * relationship is answerable from either end without a query — "which sheet
519
+ * is this sticker off" and "has this sheet already been promoted" are both
520
+ * questions the admin UI asks.
521
+ */
522
+ sourceStickerSheetId?: string;
523
+ /**
524
+ * Which cut of that sheet, by `SheetPart.ordinal`.
525
+ *
526
+ * 🛑 The ordinal, never an array index — `parts[]` is not guaranteed dense or
527
+ * ordered and a re-promote rewrites it, so an index would silently point at a
528
+ * different sticker. Absent on the parent, which is the whole sheet.
529
+ */
530
+ sourceStickerPartOrdinal?: number;
452
531
  /** When true, an EMI order for this product ships as soon as it's confirmed instead of waiting for every installment to be paid. Default false. */
453
532
  allowShipBeforeEmiComplete?: boolean;
454
533
  /**
@@ -514,6 +593,20 @@ export interface ProductDocument extends BaseDocument {
514
593
  groupParentSlug?: string;
515
594
  groupChildSlugs?: string[];
516
595
  groupTitle?: string;
596
+ groupMinMembers?: number;
597
+ groupMaxMembers?: number;
598
+ groupMaxUnitsPerMember?: number;
599
+ groupRequiredMemberIds?: string[];
600
+ /**
601
+ * Percentage off a self-assembled selection's subtotal, 0–100.
602
+ *
603
+ * 🛑 Applied in exactly ONE place: the repository's private
604
+ * `deriveLinePrice`, which runs on every `groupMembers` write and feeds
605
+ * `expandCartLineToOrderRows`' per-member GST proration through
606
+ * `allocateAcrossMembers`. A second application anywhere makes the cart total
607
+ * disagree with the invoice (Root Cause #75).
608
+ */
609
+ groupDiscountPercent?: number;
517
610
  /**
518
611
  * W1-45 — optional icon shown as an overlay badge on every card whose
519
612
  * product belongs to this group. Set once on the group parent; cards
@@ -683,8 +776,8 @@ export declare const ProductStatusValues: {
683
776
  export declare const PRODUCT_COLLECTION: "products";
684
777
  export declare const PRODUCT_INDEXED_FIELDS: readonly ["storeId", "status", "category", "categoryIds", "featured", "listingType", "isPromoted", "isOnSale", "isSold", "searchTxt", "createdAt", "barcodeId", "physicalLocation.zone"];
685
778
  export declare const DEFAULT_PRODUCT_DATA: Partial<ProductDocument>;
686
- export declare const PRODUCT_PUBLIC_FIELDS: readonly ["allowOffers", "minOfferPercent", "id", "title", "description", "category", "categoryIds", "categoryIdNames", "subcategory", "brand", "price", "originalPrice", "currency", "stockQuantity", "availableQuantity", "images", "status", "storeName", "featured", "tags", "specifications", "features", "shippingInfo", "returnPolicy", "finalSale", "isLot", "lotSize", "unitLabel", "partGlossaryId", "colourway", "mouldVariant", "assembledFrom", "views7d", "views30d", "unitLabel", "partGlossaryId", "colourway", "mouldVariant", "assembledFrom", "listingType", "auctionEndDate", "startingBid", "currentBid", "bidCount", "reservePrice", "buyNowPrice", "minBidIncrement", "autoExtendable", "auctionExtensionMinutes", "auctionShippingPaidBy", "bidsHaveStarted", "grading", "card", "classified", "digitalCode", "liveItem", "catalogProductId", "preOrderDeliveryDate", "preOrderDepositPercent", "preOrderDepositAmount", "preOrderMaxQuantity", "preOrderCurrentCount", "preOrderProductionStatus", "preOrderCancellable", "condition", "insurance", "insuranceCost", "shippingPaidBy", "isPromoted", "isOnSale", "isSold", "slug", "seoTitle", "seoDescription", "seoKeywords", "viewCount", "customFields", "customSections", "sublistingCategoryId", "groupId", "isGroupParent", "groupParentSlug", "groupChildSlugs", "groupTitle", "createdAt"];
687
- export declare const PRODUCT_UPDATABLE_FIELDS: readonly ["title", "description", "category", "categoryIds", "subcategory", "brand", "price", "originalPrice", "stockQuantity", "images", "status", "tags", "specifications", "features", "shippingInfo", "returnPolicy", "finalSale", "isLot", "lotSize", "pickupAddressId", "condition", "insurance", "shippingPaidBy", "autoExtendable", "auctionExtensionMinutes", "auctionShippingPaidBy", "reservePrice", "buyNowPrice", "minBidIncrement", "bidsHaveStarted", "grading", "card", "classified", "digitalCode", "liveItem", "catalogProductId", "listingType", "preOrderDeliveryDate", "preOrderDepositPercent", "preOrderDepositAmount", "preOrderMaxQuantity", "preOrderProductionStatus", "preOrderCancellable", "isOnSale", "isSold", "allowShipBeforeEmiComplete", "gstRate", "hsnCode", "authenticity", "printMeta", "seoTitle", "seoDescription", "seoKeywords", "customFields", "customSections", "sublistingCategoryId", "groupId", "isGroupParent", "groupParentSlug", "groupChildSlugs", "groupTitle", "barcodeId"];
779
+ export declare const PRODUCT_PUBLIC_FIELDS: readonly ["allowOffers", "minOfferPercent", "id", "title", "description", "category", "categoryIds", "categoryIdNames", "subcategory", "brand", "price", "originalPrice", "currency", "stockQuantity", "availableQuantity", "images", "status", "storeName", "featured", "tags", "specifications", "features", "shippingInfo", "returnPolicy", "finalSale", "isLot", "lotSize", "unitLabel", "partGlossaryId", "colourway", "mouldVariant", "assembledFrom", "views7d", "views30d", "unitLabel", "partGlossaryId", "colourway", "mouldVariant", "assembledFrom", "listingType", "auctionEndDate", "startingBid", "currentBid", "bidCount", "reservePrice", "buyNowPrice", "minBidIncrement", "autoExtendable", "auctionExtensionMinutes", "auctionShippingPaidBy", "bidsHaveStarted", "grading", "card", "classified", "digitalCode", "liveItem", "catalogProductId", "preOrderDeliveryDate", "preOrderDepositPercent", "preOrderDepositAmount", "preOrderMaxQuantity", "preOrderCurrentCount", "preOrderProductionStatus", "preOrderCancellable", "condition", "insurance", "insuranceCost", "shippingPaidBy", "isPromoted", "isOnSale", "isSold", "madeToOrder", "sourceStickerSheetId", "sourceStickerPartOrdinal", "slug", "seoTitle", "seoDescription", "seoKeywords", "viewCount", "customFields", "customSections", "sublistingCategoryId", "groupId", "isGroupParent", "groupParentSlug", "groupChildSlugs", "groupTitle", "groupMinMembers", "groupMaxMembers", "groupMaxUnitsPerMember", "groupRequiredMemberIds", "groupDiscountPercent", "createdAt"];
780
+ export declare const PRODUCT_UPDATABLE_FIELDS: readonly ["title", "description", "category", "categoryIds", "subcategory", "brand", "price", "originalPrice", "stockQuantity", "images", "status", "tags", "specifications", "features", "shippingInfo", "returnPolicy", "finalSale", "isLot", "lotSize", "pickupAddressId", "condition", "insurance", "shippingPaidBy", "autoExtendable", "auctionExtensionMinutes", "auctionShippingPaidBy", "reservePrice", "buyNowPrice", "minBidIncrement", "bidsHaveStarted", "grading", "card", "classified", "digitalCode", "liveItem", "catalogProductId", "listingType", "preOrderDeliveryDate", "preOrderDepositPercent", "preOrderDepositAmount", "preOrderMaxQuantity", "preOrderProductionStatus", "preOrderCancellable", "isOnSale", "isSold", "madeToOrder", "sourceStickerSheetId", "sourceStickerPartOrdinal", "allowShipBeforeEmiComplete", "gstRate", "hsnCode", "authenticity", "printMeta", "seoTitle", "seoDescription", "seoKeywords", "customFields", "customSections", "sublistingCategoryId", "groupId", "isGroupParent", "groupParentSlug", "groupChildSlugs", "groupTitle", "groupMinMembers", "groupMaxMembers", "groupMaxUnitsPerMember", "groupRequiredMemberIds", "groupDiscountPercent", "barcodeId"];
688
781
  export type ProductCreateInput = Omit<ProductDocument, "id" | "createdAt" | "updatedAt" | "availableQuantity" | "bidCount" | "currentBid" | "auctionOriginalEndDate">;
689
782
  export type ProductUpdateInput = Partial<Pick<ProductDocument, (typeof PRODUCT_UPDATABLE_FIELDS)[number]>>;
690
783
  export type ProductAdminUpdateInput = Partial<Omit<ProductDocument, "id" | "createdAt">>;