@mohasinac/appkit 4.52.4 → 4.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (633) hide show
  1. package/dist/.build-stamp.json +4 -4
  2. package/dist/_internal/client/features/sticker-trace/canvas-codec.d.ts +2 -0
  3. package/dist/_internal/client/features/sticker-trace/canvas-codec.js +148 -0
  4. package/dist/_internal/server/features/auctions/actions.js +1 -1
  5. package/dist/_internal/server/features/categories/data.js +23 -7
  6. package/dist/_internal/server/features/checkout/actions.js +10 -3
  7. package/dist/_internal/server/features/checkout/data.d.ts +15 -0
  8. package/dist/_internal/server/features/checkout/data.js +20 -3
  9. package/dist/_internal/server/features/lottery/actions.js +9 -1
  10. package/dist/_internal/server/features/lottery/og.d.ts +40 -0
  11. package/dist/_internal/server/features/lottery/og.js +79 -0
  12. package/dist/_internal/server/features/messages/actions.js +4 -0
  13. package/dist/_internal/server/features/offers/adapters.js +17 -3
  14. package/dist/_internal/server/features/orders/actions.js +7 -2
  15. package/dist/_internal/server/features/raffle/actions.d.ts +19 -0
  16. package/dist/_internal/server/features/raffle/actions.js +25 -0
  17. package/dist/_internal/server/features/reviews/actions.js +1 -1
  18. package/dist/_internal/server/features/reviews/data.d.ts +1 -1
  19. package/dist/_internal/server/features/search/index-build/artifact-store.d.ts +89 -0
  20. package/dist/_internal/server/features/search/index-build/artifact-store.js +208 -0
  21. package/dist/_internal/server/features/search/index-build/build.d.ts +57 -0
  22. package/dist/_internal/server/features/search/index-build/build.js +285 -0
  23. package/dist/_internal/server/features/search/index-build/sources.d.ts +53 -0
  24. package/dist/_internal/server/features/search/index-build/sources.js +385 -0
  25. package/dist/_internal/server/features/search/search-sources.d.ts +0 -15
  26. package/dist/_internal/server/features/search/search-sources.js +142 -7
  27. package/dist/_internal/server/features/seo/robots.js +21 -1
  28. package/dist/_internal/server/features/seo/sitemap.js +1 -1
  29. package/dist/_internal/server/features/shared/listing-data-factory.js +16 -4
  30. package/dist/_internal/server/features/site-settings/adapters.d.ts +1 -1
  31. package/dist/_internal/server/features/site-settings/adapters.js +26 -0
  32. package/dist/_internal/server/features/sticker-trace/actions.d.ts +109 -0
  33. package/dist/_internal/server/features/sticker-trace/actions.js +172 -0
  34. package/dist/_internal/server/features/sticker-trace/adapters.d.ts +80 -0
  35. package/dist/_internal/server/features/sticker-trace/adapters.js +174 -0
  36. package/dist/_internal/server/features/sticker-trace/build-cut-file.d.ts +26 -0
  37. package/dist/_internal/server/features/sticker-trace/build-cut-file.js +127 -0
  38. package/dist/_internal/server/features/sticker-trace/coordinator.d.ts +27 -0
  39. package/dist/_internal/server/features/sticker-trace/coordinator.js +169 -0
  40. package/dist/_internal/server/features/sticker-trace/fanout.d.ts +43 -0
  41. package/dist/_internal/server/features/sticker-trace/fanout.js +180 -0
  42. package/dist/_internal/server/features/sticker-trace/finalizer.d.ts +25 -0
  43. package/dist/_internal/server/features/sticker-trace/finalizer.js +123 -0
  44. package/dist/_internal/server/features/sticker-trace/mosaic-inputs.d.ts +30 -0
  45. package/dist/_internal/server/features/sticker-trace/mosaic-inputs.js +112 -0
  46. package/dist/_internal/server/features/sticker-trace/progress.d.ts +81 -0
  47. package/dist/_internal/server/features/sticker-trace/progress.js +198 -0
  48. package/dist/_internal/server/features/sticker-trace/promote.d.ts +23 -0
  49. package/dist/_internal/server/features/sticker-trace/promote.js +193 -0
  50. package/dist/_internal/server/features/sticker-trace/shard.d.ts +50 -0
  51. package/dist/_internal/server/features/sticker-trace/shard.js +174 -0
  52. package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +141 -0
  53. package/dist/_internal/server/features/sticker-trace/sheet-actions.js +279 -0
  54. package/dist/_internal/server/features/sticker-trace/storage.d.ts +135 -0
  55. package/dist/_internal/server/features/sticker-trace/storage.js +282 -0
  56. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  57. package/dist/_internal/server/functions/scheduled.js +25 -1
  58. package/dist/_internal/server/jobs/core/_event-ref.d.ts +51 -0
  59. package/dist/_internal/server/jobs/core/_event-ref.js +63 -0
  60. package/dist/_internal/server/jobs/core/assignSpinPrize.d.ts +18 -0
  61. package/dist/_internal/server/jobs/core/assignSpinPrize.js +77 -16
  62. package/dist/_internal/server/jobs/core/auctionSettlement.js +13 -4
  63. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +44 -15
  64. package/dist/_internal/server/jobs/core/bundleStockSync.js +3 -4
  65. package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +44 -0
  66. package/dist/_internal/server/jobs/core/event-draw-reasons.d.ts +78 -0
  67. package/dist/_internal/server/jobs/core/event-draw-reasons.js +133 -0
  68. package/dist/_internal/server/jobs/core/listingProcessor.js +28 -8
  69. package/dist/_internal/server/jobs/core/onOrderCreate.js +12 -1
  70. package/dist/_internal/server/jobs/core/onScamReportCreate.js +13 -2
  71. package/dist/_internal/server/jobs/core/onScamReportRejected.js +8 -2
  72. package/dist/_internal/server/jobs/core/onScamReportVerified.js +8 -2
  73. package/dist/_internal/server/jobs/core/onStoreWrite.js +11 -4
  74. package/dist/_internal/server/jobs/core/prizeDrawAssignWinner.js +5 -4
  75. package/dist/_internal/server/jobs/core/prizeDrawExpiryReveal.js +1 -4
  76. package/dist/_internal/server/jobs/core/prizeDrawSoldOutReveal.js +1 -2
  77. package/dist/_internal/server/jobs/core/promotions.js +7 -4
  78. package/dist/_internal/server/jobs/core/searchIndexBuild.d.ts +7 -0
  79. package/dist/_internal/server/jobs/core/searchIndexBuild.js +211 -0
  80. package/dist/_internal/server/jobs/core/triggerEventRaffle.d.ts +35 -0
  81. package/dist/_internal/server/jobs/core/triggerEventRaffle.js +213 -31
  82. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +20 -14
  83. package/dist/_internal/server/jobs/handlers/assignSpinPrize.d.ts +8 -0
  84. package/dist/_internal/server/jobs/handlers/assignSpinPrize.js +15 -15
  85. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  86. package/dist/_internal/server/jobs/handlers/index.js +1 -0
  87. package/dist/_internal/server/jobs/handlers/onCategoryWrite.js +18 -0
  88. package/dist/_internal/server/jobs/handlers/onProductWrite.js +18 -0
  89. package/dist/_internal/server/jobs/handlers/onReviewWrite.js +18 -0
  90. package/dist/_internal/server/jobs/handlers/onScamReportUpdate.js +18 -0
  91. package/dist/_internal/server/jobs/handlers/onStoreWrite.js +18 -0
  92. package/dist/_internal/server/jobs/handlers/searchIndexBuild.d.ts +2 -0
  93. package/dist/_internal/server/jobs/handlers/searchIndexBuild.js +2 -0
  94. package/dist/_internal/server/jobs/handlers/triggerEventRaffle.d.ts +8 -0
  95. package/dist/_internal/server/jobs/handlers/triggerEventRaffle.js +15 -6
  96. package/dist/_internal/shared/actions/action-registry.js +29 -0
  97. package/dist/_internal/shared/cache/revalidate-targets.d.ts +0 -1
  98. package/dist/_internal/shared/cache/revalidate-targets.js +10 -8
  99. package/dist/_internal/shared/features/events/config.d.ts +14 -0
  100. package/dist/_internal/shared/features/events/config.js +14 -0
  101. package/dist/_internal/shared/features/notifications/action-url.js +8 -0
  102. package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
  103. package/dist/_internal/shared/features/sticker-trace/codec.d.ts +81 -0
  104. package/dist/_internal/shared/features/sticker-trace/codec.js +30 -0
  105. package/dist/_internal/shared/features/sticker-trace/config.d.ts +81 -0
  106. package/dist/_internal/shared/features/sticker-trace/config.js +177 -0
  107. package/dist/_internal/shared/features/sticker-trace/cut-contour.d.ts +20 -0
  108. package/dist/_internal/shared/features/sticker-trace/cut-contour.js +60 -0
  109. package/dist/_internal/shared/features/sticker-trace/export/build-export-set.d.ts +65 -0
  110. package/dist/_internal/shared/features/sticker-trace/export/build-export-set.js +176 -0
  111. package/dist/_internal/shared/features/sticker-trace/export/cut-svg.d.ts +56 -0
  112. package/dist/_internal/shared/features/sticker-trace/export/cut-svg.js +120 -0
  113. package/dist/_internal/shared/features/sticker-trace/export/machine-profiles.d.ts +92 -0
  114. package/dist/_internal/shared/features/sticker-trace/export/machine-profiles.js +153 -0
  115. package/dist/_internal/shared/features/sticker-trace/export/nesting.d.ts +51 -0
  116. package/dist/_internal/shared/features/sticker-trace/export/nesting.js +110 -0
  117. package/dist/_internal/shared/features/sticker-trace/export/page-sizes.d.ts +68 -0
  118. package/dist/_internal/shared/features/sticker-trace/export/page-sizes.js +223 -0
  119. package/dist/_internal/shared/features/sticker-trace/export/part-tiling.d.ts +51 -0
  120. package/dist/_internal/shared/features/sticker-trace/export/part-tiling.js +178 -0
  121. package/dist/_internal/shared/features/sticker-trace/export/simplify-budget.d.ts +26 -0
  122. package/dist/_internal/shared/features/sticker-trace/export/simplify-budget.js +134 -0
  123. package/dist/_internal/shared/features/sticker-trace/export/vectorise-art.d.ts +40 -0
  124. package/dist/_internal/shared/features/sticker-trace/export/vectorise-art.js +195 -0
  125. package/dist/_internal/shared/features/sticker-trace/index.d.ts +2 -0
  126. package/dist/_internal/shared/features/sticker-trace/index.js +59 -0
  127. package/dist/_internal/shared/features/sticker-trace/math/catmull-rom.d.ts +11 -0
  128. package/dist/_internal/shared/features/sticker-trace/math/catmull-rom.js +66 -0
  129. package/dist/_internal/shared/features/sticker-trace/math/edt.d.ts +27 -0
  130. package/dist/_internal/shared/features/sticker-trace/math/edt.js +165 -0
  131. package/dist/_internal/shared/features/sticker-trace/math/label.d.ts +15 -0
  132. package/dist/_internal/shared/features/sticker-trace/math/label.js +156 -0
  133. package/dist/_internal/shared/features/sticker-trace/math/marching-squares.d.ts +16 -0
  134. package/dist/_internal/shared/features/sticker-trace/math/marching-squares.js +242 -0
  135. package/dist/_internal/shared/features/sticker-trace/math/morphology.d.ts +46 -0
  136. package/dist/_internal/shared/features/sticker-trace/math/morphology.js +168 -0
  137. package/dist/_internal/shared/features/sticker-trace/math/rasterize-path.d.ts +88 -0
  138. package/dist/_internal/shared/features/sticker-trace/math/rasterize-path.js +286 -0
  139. package/dist/_internal/shared/features/sticker-trace/math/rdp.d.ts +10 -0
  140. package/dist/_internal/shared/features/sticker-trace/math/rdp.js +74 -0
  141. package/dist/_internal/shared/features/sticker-trace/resume.d.ts +50 -0
  142. package/dist/_internal/shared/features/sticker-trace/resume.js +160 -0
  143. package/dist/_internal/shared/features/sticker-trace/trace/cluster.d.ts +20 -0
  144. package/dist/_internal/shared/features/sticker-trace/trace/cluster.js +132 -0
  145. package/dist/_internal/shared/features/sticker-trace/trace/cross-profile.d.ts +28 -0
  146. package/dist/_internal/shared/features/sticker-trace/trace/cross-profile.js +120 -0
  147. package/dist/_internal/shared/features/sticker-trace/trace/flood.d.ts +21 -0
  148. package/dist/_internal/shared/features/sticker-trace/trace/flood.js +104 -0
  149. package/dist/_internal/shared/features/sticker-trace/trace/geometry.d.ts +3 -0
  150. package/dist/_internal/shared/features/sticker-trace/trace/geometry.js +140 -0
  151. package/dist/_internal/shared/features/sticker-trace/trace/line-filter.d.ts +15 -0
  152. package/dist/_internal/shared/features/sticker-trace/trace/line-filter.js +138 -0
  153. package/dist/_internal/shared/features/sticker-trace/trace/merge.d.ts +27 -0
  154. package/dist/_internal/shared/features/sticker-trace/trace/merge.js +187 -0
  155. package/dist/_internal/shared/features/sticker-trace/trace/paper.d.ts +32 -0
  156. package/dist/_internal/shared/features/sticker-trace/trace/paper.js +147 -0
  157. package/dist/_internal/shared/features/sticker-trace/trace/prefilter.d.ts +30 -0
  158. package/dist/_internal/shared/features/sticker-trace/trace/prefilter.js +125 -0
  159. package/dist/_internal/shared/features/sticker-trace/trace/quantise.d.ts +10 -0
  160. package/dist/_internal/shared/features/sticker-trace/trace/quantise.js +153 -0
  161. package/dist/_internal/shared/features/sticker-trace/trace/ridge.d.ts +88 -0
  162. package/dist/_internal/shared/features/sticker-trace/trace/ridge.js +344 -0
  163. package/dist/_internal/shared/features/sticker-trace/trace/segment.d.ts +10 -0
  164. package/dist/_internal/shared/features/sticker-trace/trace/segment.js +251 -0
  165. package/dist/_internal/shared/features/sticker-trace/types.d.ts +197 -0
  166. package/dist/_internal/shared/features/sticker-trace/types.js +49 -0
  167. package/dist/_internal/shared/listing-types/_registry.d.ts +11 -0
  168. package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
  169. package/dist/_internal/shared/listing-types/art/config.js +1 -0
  170. package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
  171. package/dist/_internal/shared/listing-types/auction/config.js +1 -0
  172. package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
  173. package/dist/_internal/shared/listing-types/classified/config.js +1 -0
  174. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
  175. package/dist/_internal/shared/listing-types/digital-code/config.js +1 -0
  176. package/dist/_internal/shared/listing-types/feature-flags.d.ts +7 -0
  177. package/dist/_internal/shared/listing-types/feature-flags.js +9 -0
  178. package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
  179. package/dist/_internal/shared/listing-types/live/config.js +1 -0
  180. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
  181. package/dist/_internal/shared/listing-types/pre-order/config.js +1 -0
  182. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
  183. package/dist/_internal/shared/listing-types/prize-draw/config.js +1 -0
  184. package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
  185. package/dist/_internal/shared/listing-types/standard/config.js +1 -0
  186. package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
  187. package/dist/_internal/shared/listing-types/stickers/config.js +1 -0
  188. package/dist/_internal/shared/media/limits.d.ts +12 -2
  189. package/dist/_internal/shared/media/limits.js +12 -2
  190. package/dist/_internal/shared/search/artifact-url.d.ts +35 -0
  191. package/dist/_internal/shared/search/artifact-url.js +119 -0
  192. package/dist/_internal/shared/search/index-record.d.ts +68 -0
  193. package/dist/_internal/shared/search/index-record.js +96 -0
  194. package/dist/_internal/shared/search/match.d.ts +65 -0
  195. package/dist/_internal/shared/search/match.js +263 -0
  196. package/dist/client.d.ts +8 -7
  197. package/dist/client.js +12 -5
  198. package/dist/configs/eslint.js +22 -2
  199. package/dist/constants/api-endpoints.d.ts +68 -0
  200. package/dist/constants/api-endpoints.js +32 -0
  201. package/dist/constants/field-names.d.ts +7 -1
  202. package/dist/constants/field-names.js +36 -1
  203. package/dist/contracts/repository.d.ts +8 -7
  204. package/dist/contracts/search.d.ts +2 -2
  205. package/dist/contracts/table.d.ts +3 -3
  206. package/dist/contracts/table.js +3 -3
  207. package/dist/core/contact-submissions.repository.js +2 -2
  208. package/dist/core/integration-keys.js +7 -1
  209. package/dist/core/newsletter.repository.js +2 -2
  210. package/dist/core/site-config.js +1 -1
  211. package/dist/errors/error-codes.d.ts +30 -0
  212. package/dist/errors/error-codes.js +30 -0
  213. package/dist/errors/error-display-map.js +40 -1
  214. package/dist/features/account/api/[userId]/addresses/route.js +1 -1
  215. package/dist/features/account/components/UserBidsView.js +1 -1
  216. package/dist/features/account/components/index.d.ts +0 -8
  217. package/dist/features/account/components/index.js +0 -4
  218. package/dist/features/addresses/repository/addresses.repository.d.ts +17 -6
  219. package/dist/features/addresses/repository/addresses.repository.js +65 -9
  220. package/dist/features/addresses/schemas/firestore.d.ts +17 -6
  221. package/dist/features/admin/actions/notification-actions.js +15 -6
  222. package/dist/features/admin/api/bids/route.js +1 -1
  223. package/dist/features/admin/api/coupons/route.js +1 -1
  224. package/dist/features/admin/api/products/route.js +1 -1
  225. package/dist/features/admin/api/reviews/route.js +1 -1
  226. package/dist/features/admin/components/AdminAdEditorView.js +19 -5
  227. package/dist/features/admin/components/AdminAuditLogView.js +1 -1
  228. package/dist/features/admin/components/AdminBlogEditorView.js +0 -1
  229. package/dist/features/admin/components/AdminBlogView.js +1 -1
  230. package/dist/features/admin/components/AdminBrandsView.js +17 -1
  231. package/dist/features/admin/components/AdminCategoryEditorView.js +0 -1
  232. package/dist/features/admin/components/AdminContactView.js +1 -1
  233. package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -3
  234. package/dist/features/admin/components/AdminNewsletterView.js +1 -1
  235. package/dist/features/admin/components/AdminOrdersView.js +9 -2
  236. package/dist/features/admin/components/AdminPayoutsView.js +1 -1
  237. package/dist/features/admin/components/AdminPrizeDrawsView.js +11 -0
  238. package/dist/features/admin/components/AdminProductEditorView.d.ts +10 -1
  239. package/dist/features/admin/components/AdminProductEditorView.js +24 -37
  240. package/dist/features/admin/components/AdminProductsView.js +10 -3
  241. package/dist/features/admin/components/AdminScammersView.js +1 -1
  242. package/dist/features/admin/components/AdminSectionsView.js +21 -5
  243. package/dist/features/admin/components/AdminSessionsView.js +1 -1
  244. package/dist/features/admin/components/AdminSublistingCategoriesView.js +22 -1
  245. package/dist/features/admin/components/AdminTeamView.js +1 -1
  246. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +0 -1
  247. package/dist/features/admin/components/AdminUsersView.js +1 -1
  248. package/dist/features/admin/components/DataListingView.d.ts +2 -1
  249. package/dist/features/admin/components/DataListingView.js +9 -4
  250. package/dist/features/admin/components/analytics/AdminPageViewsReportView.js +0 -2
  251. package/dist/features/admin/hooks/useAdminListing.d.ts +1 -1
  252. package/dist/features/admin/repository/site-settings.repository.js +8 -3
  253. package/dist/features/admin/schemas/firestore.d.ts +62 -1
  254. package/dist/features/admin/schemas/firestore.js +32 -0
  255. package/dist/features/admin/types/index.d.ts +1 -1
  256. package/dist/features/auctions/actions/bid-actions.d.ts +2 -2
  257. package/dist/features/auctions/actions/bid-actions.js +16 -4
  258. package/dist/features/auctions/api/route.js +1 -1
  259. package/dist/features/auctions/components/AuctionBottomActions.js +4 -0
  260. package/dist/features/auctions/repository/bid.repository.d.ts +46 -4
  261. package/dist/features/auctions/repository/bid.repository.js +114 -13
  262. package/dist/features/auctions/schemas/firestore.d.ts +24 -4
  263. package/dist/features/auctions/schemas/firestore.js +1 -0
  264. package/dist/features/auth/actions/profile-actions.js +30 -4
  265. package/dist/features/auth/components/index.d.ts +0 -1
  266. package/dist/features/auth/components/index.js +0 -1
  267. package/dist/features/auth/repository/session.repository.d.ts +17 -3
  268. package/dist/features/auth/repository/session.repository.js +46 -5
  269. package/dist/features/auth/repository/token.repository.d.ts +27 -4
  270. package/dist/features/auth/repository/token.repository.js +65 -11
  271. package/dist/features/auth/repository/user.repository.d.ts +33 -7
  272. package/dist/features/auth/repository/user.repository.js +100 -15
  273. package/dist/features/auth/schemas/firestore.d.ts +63 -12
  274. package/dist/features/auth/schemas/firestore.js +11 -0
  275. package/dist/features/before-after/api/route.js +1 -1
  276. package/dist/features/blog/components/BlogListView.js +16 -3
  277. package/dist/features/blog/components/BlogPostView.js +1 -1
  278. package/dist/features/blog/schemas/index.d.ts +2 -2
  279. package/dist/features/cart/api/route.js +1 -1
  280. package/dist/features/catalogue/repository/catalogue.repository.d.ts +7 -7
  281. package/dist/features/catalogue/repository/catalogue.repository.js +28 -10
  282. package/dist/features/catalogue/schemas/firestore.d.ts +11 -0
  283. package/dist/features/categories/api/route.js +10 -10
  284. package/dist/features/categories/components/CategoryDetailPageView.js +35 -5
  285. package/dist/features/categories/components/CategorySelectorCreate.js +0 -1
  286. package/dist/features/categories/components/index.d.ts +0 -2
  287. package/dist/features/categories/components/index.js +0 -1
  288. package/dist/features/categories/repository/categories.repository.d.ts +1 -0
  289. package/dist/features/categories/repository/categories.repository.js +31 -1
  290. package/dist/features/categories/schemas/index.d.ts +2 -2
  291. package/dist/features/categories/utils/taxonomy-visual.d.ts +21 -0
  292. package/dist/features/categories/utils/taxonomy-visual.js +58 -0
  293. package/dist/features/checkout/actions/checkout-value-otp-actions.js +8 -1
  294. package/dist/features/collections/api/[slug]/route.js +3 -3
  295. package/dist/features/collections/api/route.js +1 -1
  296. package/dist/features/consultation/api/route.js +1 -1
  297. package/dist/features/consultation/repository/consultations.repository.js +1 -1
  298. package/dist/features/consultation/types/index.d.ts +1 -1
  299. package/dist/features/contact/components/ContactForm.js +1 -3
  300. package/dist/features/corporate/api/route.js +1 -1
  301. package/dist/features/corporate/repository/corporate.repository.js +1 -1
  302. package/dist/features/corporate/types/index.d.ts +1 -1
  303. package/dist/features/cron/jobs/auction-expiry.job.js +1 -1
  304. package/dist/features/cron/jobs/preorder-reminder.job.js +1 -1
  305. package/dist/features/events/actions/event-actions.d.ts +14 -0
  306. package/dist/features/events/actions/event-actions.js +82 -3
  307. package/dist/features/events/api/[id]/route.js +2 -2
  308. package/dist/features/events/components/AdminEventEditorView.js +22 -3
  309. package/dist/features/events/components/AdminEventsView.js +32 -8
  310. package/dist/features/events/components/EventRafflesSection.d.ts +34 -1
  311. package/dist/features/events/components/EventRafflesSection.js +52 -3
  312. package/dist/features/events/components/SpinWheelView.d.ts +2 -2
  313. package/dist/features/events/components/SpinWheelView.js +41 -4
  314. package/dist/features/events/repository/event-entry.repository.d.ts +14 -2
  315. package/dist/features/events/repository/event-entry.repository.js +41 -7
  316. package/dist/features/events/schemas/firestore.d.ts +17 -4
  317. package/dist/features/events/types/index.d.ts +37 -0
  318. package/dist/features/faq/repository/faqs.repository.js +1 -1
  319. package/dist/features/faq/schemas/index.d.ts +5 -2
  320. package/dist/features/faq/schemas/index.js +6 -0
  321. package/dist/features/faq/types/index.d.ts +0 -1
  322. package/dist/features/grouped/components/GroupedListingEditorView.js +17 -2
  323. package/dist/features/homepage/api/carousel/[id]/route.js +1 -1
  324. package/dist/features/homepage/api/carousel/route.js +4 -4
  325. package/dist/features/homepage/api/route.js +2 -2
  326. package/dist/features/homepage/api/sections/route.js +1 -1
  327. package/dist/features/homepage/components/AnnouncementBar.d.ts +1 -9
  328. package/dist/features/homepage/components/AnnouncementBar.js +13 -19
  329. package/dist/features/homepage/components/MarketplaceHomepageView.js +6 -1
  330. package/dist/features/homepage/components/index.d.ts +0 -2
  331. package/dist/features/homepage/components/index.js +0 -1
  332. package/dist/features/homepage/repository/homepage.repository.js +1 -1
  333. package/dist/features/homepage/schemas/firestore.d.ts +6 -0
  334. package/dist/features/homepage/schemas/index.d.ts +10 -10
  335. package/dist/features/layout/AppLayoutShell.d.ts +12 -3
  336. package/dist/features/layout/AppLayoutShell.js +65 -13
  337. package/dist/features/layout/BottomActionsContext.d.ts +16 -0
  338. package/dist/features/layout/BottomActionsContext.js +5 -0
  339. package/dist/features/layout/BottomChrome.js +48 -9
  340. package/dist/features/layout/BottomNavbar.d.ts +14 -0
  341. package/dist/features/layout/BottomNavbar.js +43 -3
  342. package/dist/features/layout/MainNavbar.d.ts +11 -0
  343. package/dist/features/layout/NavbarLayout.d.ts +3 -0
  344. package/dist/features/layout/NavbarLayout.js +88 -11
  345. package/dist/features/layout/SideActionDock.d.ts +1 -0
  346. package/dist/features/layout/SideActionDock.js +219 -0
  347. package/dist/features/layout/TitleBarLayout.d.ts +1 -3
  348. package/dist/features/layout/TitleBarLayout.js +3 -4
  349. package/dist/features/layout/cta-anchor.d.ts +31 -0
  350. package/dist/features/layout/cta-anchor.js +31 -0
  351. package/dist/features/layout/hooks/useBottomActions.d.ts +7 -0
  352. package/dist/features/layout/hooks/useBottomActions.js +6 -1
  353. package/dist/features/layout/index.d.ts +9 -1
  354. package/dist/features/layout/index.js +9 -1
  355. package/dist/features/layout/useCtaReveal.d.ts +24 -0
  356. package/dist/features/layout/useCtaReveal.js +82 -0
  357. package/dist/features/layout/useHoldToOpen.d.ts +41 -0
  358. package/dist/features/layout/useHoldToOpen.js +84 -0
  359. package/dist/features/lottery/repository/lottery-entry.repository.d.ts +18 -3
  360. package/dist/features/lottery/repository/lottery-entry.repository.js +48 -6
  361. package/dist/features/lottery/schemas/firestore.d.ts +33 -5
  362. package/dist/features/loyalty/api/balance/route.js +1 -1
  363. package/dist/features/loyalty/api/history/route.js +1 -1
  364. package/dist/features/media/MediaImage.js +0 -1
  365. package/dist/features/media/MediaPickerModal.js +7 -1
  366. package/dist/features/media/modals/ImageEditor.js +5 -1
  367. package/dist/features/media/modals/VideoThumbnailSelector.js +17 -1
  368. package/dist/features/media/repository/media-assets.repository.d.ts +19 -0
  369. package/dist/features/media/upload/CameraCapture.js +16 -1
  370. package/dist/features/media/upload/ImageUpload.js +42 -4
  371. package/dist/features/media/upload/MediaUploadField.js +69 -13
  372. package/dist/features/media/upload/downscale-image.d.ts +56 -0
  373. package/dist/features/media/upload/downscale-image.js +150 -0
  374. package/dist/features/messages/components/ConversationThreadView.js +45 -2
  375. package/dist/features/messages/components/MessageSellerButton.d.ts +15 -1
  376. package/dist/features/messages/components/MessageSellerButton.js +10 -2
  377. package/dist/features/messages/schemas/firestore.d.ts +15 -0
  378. package/dist/features/orders/hooks/useOrders.js +4 -2
  379. package/dist/features/orders/repository/orders.repository.d.ts +15 -4
  380. package/dist/features/orders/repository/orders.repository.js +52 -20
  381. package/dist/features/orders/schemas/firestore.d.ts +15 -4
  382. package/dist/features/orders/schemas/index.d.ts +8 -8
  383. package/dist/features/orders/types/index.d.ts +2 -2
  384. package/dist/features/payments/repository/payments.repository.js +2 -2
  385. package/dist/features/payments/repository/payout.repository.d.ts +23 -6
  386. package/dist/features/payments/repository/payout.repository.js +63 -23
  387. package/dist/features/payments/repository/saved-payment-methods.repository.d.ts +17 -6
  388. package/dist/features/payments/repository/saved-payment-methods.repository.js +59 -11
  389. package/dist/features/payments/schemas/firestore.d.ts +14 -3
  390. package/dist/features/payments/schemas/saved-methods-firestore.d.ts +12 -1
  391. package/dist/features/pre-orders/api/[slug]/route.js +1 -1
  392. package/dist/features/pre-orders/api/admin/route.js +1 -1
  393. package/dist/features/pre-orders/api/route.js +1 -1
  394. package/dist/features/pre-orders/repository/pre-orders.repository.d.ts +3 -3
  395. package/dist/features/pre-orders/repository/pre-orders.repository.js +6 -6
  396. package/dist/features/products/api/[id]/route.js +1 -1
  397. package/dist/features/products/components/ListingBottomActions.js +4 -0
  398. package/dist/features/products/components/ProductDetailPageView.js +2 -1
  399. package/dist/features/products/components/ProductGalleryClient.js +2 -2
  400. package/dist/features/products/components/ProductGrid.js +12 -1
  401. package/dist/features/products/components/index.d.ts +0 -2
  402. package/dist/features/products/components/index.js +0 -1
  403. package/dist/features/products/config/listing-type-listing-config.d.ts +0 -3
  404. package/dist/features/products/config/listing-type-listing-config.js +27 -2
  405. package/dist/features/products/constants/listing-tabs.d.ts +9 -0
  406. package/dist/features/products/constants/listing-tabs.js +3 -2
  407. package/dist/features/products/hooks/useProducts.js +2 -2
  408. package/dist/features/products/repository/products.repository.js +13 -1
  409. package/dist/features/products/schemas/index.d.ts +2 -2
  410. package/dist/features/products/types/index.d.ts +1 -1
  411. package/dist/features/promotions/api/route.js +1 -1
  412. package/dist/features/reviews/actions/review-actions.d.ts +6 -6
  413. package/dist/features/reviews/actions/review-actions.js +22 -8
  414. package/dist/features/reviews/components/ReviewDetailPageView.js +13 -1
  415. package/dist/features/reviews/components/ReviewsIndexPageView.js +21 -4
  416. package/dist/features/reviews/repository/reviews.repository.d.ts +19 -7
  417. package/dist/features/reviews/repository/reviews.repository.js +63 -12
  418. package/dist/features/reviews/schemas/firestore.d.ts +13 -2
  419. package/dist/features/reviews/schemas/index.d.ts +2 -2
  420. package/dist/features/scams/actions/scam-actions.js +16 -4
  421. package/dist/features/search/components/SearchResultsPageView.js +2 -1
  422. package/dist/features/search/hooks/useSearchIndex.d.ts +34 -0
  423. package/dist/features/search/hooks/useSearchIndex.js +172 -0
  424. package/dist/features/search/repository/search.repository.js +2 -2
  425. package/dist/features/seller/actions/offer-actions.d.ts +5 -5
  426. package/dist/features/seller/actions/offer-actions.js +38 -8
  427. package/dist/features/seller/actions/seller-actions.js +34 -7
  428. package/dist/features/seller/api/coupons/route.js +1 -1
  429. package/dist/features/seller/api/products/route.js +1 -1
  430. package/dist/features/seller/api/store/route.js +1 -1
  431. package/dist/features/seller/components/SellerBidsView.js +1 -1
  432. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  433. package/dist/features/seller/components/SellerListingTypeView.js +9 -1
  434. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  435. package/dist/features/seller/components/SellerPayoutSettingsView.js +0 -1
  436. package/dist/features/seller/components/SellerPayoutsView.js +1 -1
  437. package/dist/features/seller/components/SellerProductShell.js +0 -1
  438. package/dist/features/seller/components/SellerProductsView.js +1 -1
  439. package/dist/features/seller/components/SellerShippingView.js +0 -1
  440. package/dist/features/seller/components/SellerStorefrontView.js +0 -1
  441. package/dist/features/seller/components/index.d.ts +0 -4
  442. package/dist/features/seller/components/index.js +0 -2
  443. package/dist/features/seller/repository/offer.repository.d.ts +15 -3
  444. package/dist/features/seller/repository/offer.repository.js +43 -7
  445. package/dist/features/seller/schemas/firestore.d.ts +14 -3
  446. package/dist/features/seller/schemas/index.d.ts +4 -4
  447. package/dist/features/seller/schemas/order-forms.d.ts +39 -0
  448. package/dist/features/seller/schemas/order-forms.js +37 -0
  449. package/dist/features/shell/FormShell.js +6 -2
  450. package/dist/features/shell/QuickFormDrawer.js +15 -1
  451. package/dist/features/shipments/components/AdminShipmentEditorView.js +0 -1
  452. package/dist/features/shipments/components/AdminShipmentsView.js +1 -1
  453. package/dist/features/sticker-trace/components/StickerCommitPanel.d.ts +30 -0
  454. package/dist/features/sticker-trace/components/StickerCommitPanel.js +93 -0
  455. package/dist/features/sticker-trace/components/StickerPrintPanel.d.ts +33 -0
  456. package/dist/features/sticker-trace/components/StickerPrintPanel.js +104 -0
  457. package/dist/features/sticker-trace/components/StickerRetryPanel.d.ts +20 -0
  458. package/dist/features/sticker-trace/components/StickerRetryPanel.js +128 -0
  459. package/dist/features/sticker-trace/components/StickerRunHistoryPanel.d.ts +45 -0
  460. package/dist/features/sticker-trace/components/StickerRunHistoryPanel.js +84 -0
  461. package/dist/features/sticker-trace/components/StickerTraceStudio.d.ts +27 -0
  462. package/dist/features/sticker-trace/components/StickerTraceStudio.js +171 -0
  463. package/dist/features/sticker-trace/constants/help-content.d.ts +23 -0
  464. package/dist/features/sticker-trace/constants/help-content.js +172 -0
  465. package/dist/features/sticker-trace/hooks/useLiveTrace.d.ts +27 -0
  466. package/dist/features/sticker-trace/hooks/useLiveTrace.js +160 -0
  467. package/dist/features/sticker-trace/hooks/useStickerTraceProgress.d.ts +22 -0
  468. package/dist/features/sticker-trace/hooks/useStickerTraceProgress.js +106 -0
  469. package/dist/features/sticker-trace/repository/sticker-sheets.repository.d.ts +113 -0
  470. package/dist/features/sticker-trace/repository/sticker-sheets.repository.js +146 -0
  471. package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.d.ts +132 -0
  472. package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.js +174 -0
  473. package/dist/features/sticker-trace/schemas/firestore.d.ts +248 -0
  474. package/dist/features/sticker-trace/schemas/firestore.js +79 -0
  475. package/dist/features/sticker-trace/server.d.ts +8 -0
  476. package/dist/features/sticker-trace/server.js +51 -0
  477. package/dist/features/stores/actions/store-query-actions.d.ts +2 -2
  478. package/dist/features/stores/actions/store-query-actions.js +7 -2
  479. package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -3
  480. package/dist/features/stores/api/[storeSlug]/products/route.js +3 -3
  481. package/dist/features/stores/api/[storeSlug]/reviews/route.js +1 -1
  482. package/dist/features/stores/api/[storeSlug]/route.js +1 -1
  483. package/dist/features/stores/components/StoreNavTabs.js +17 -2
  484. package/dist/features/stores/manifest.js +8 -4
  485. package/dist/features/support/repository/support.repository.d.ts +14 -3
  486. package/dist/features/support/repository/support.repository.js +93 -13
  487. package/dist/features/support/schemas/firestore.d.ts +16 -5
  488. package/dist/features/tester/seed-data/authored/admin__events-raffles-spin.js +61 -19
  489. package/dist/features/tester/seed-data/authored/buying__browsing-search.js +19 -3
  490. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
  491. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +243 -0
  492. package/dist/features/tester/seed-data/authored/content-discovery__events.js +36 -10
  493. package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.d.ts +2 -0
  494. package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.js +209 -0
  495. package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.d.ts +2 -0
  496. package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.js +90 -0
  497. package/dist/features/tester/seed-data/authored/design-ux__header-controls-and-messages.d.ts +2 -0
  498. package/dist/features/tester/seed-data/authored/design-ux__header-controls-and-messages.js +85 -0
  499. package/dist/features/tester/seed-data/authored/index.js +10 -0
  500. package/dist/features/tester/seed-data/authored/selling__media-limits.js +19 -17
  501. package/dist/features/tester/seed-data/authored/selling__product-upload-details.js +10 -5
  502. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.d.ts +2 -0
  503. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +283 -0
  504. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +235 -22
  505. package/dist/index.d.ts +10 -23
  506. package/dist/index.js +27 -19
  507. package/dist/next/api/routeHandler.js +9 -0
  508. package/dist/next/routing/require-record.d.ts +13 -0
  509. package/dist/next/routing/require-record.js +62 -0
  510. package/dist/next/routing/route-map.d.ts +4 -4
  511. package/dist/next/routing/route-map.js +25 -3
  512. package/dist/providers/db-firebase/base.d.ts +4 -2
  513. package/dist/providers/db-firebase/base.js +21 -5
  514. package/dist/providers/db-firebase/base.repository.d.ts +11 -9
  515. package/dist/providers/db-firebase/base.repository.js +19 -0
  516. package/dist/providers/db-firebase/rtdb-paths.d.ts +12 -0
  517. package/dist/providers/db-firebase/rtdb-paths.js +12 -0
  518. package/dist/react/ErrorBoundary.js +6 -1
  519. package/dist/react/hooks/realtime-event-constants.d.ts +1 -0
  520. package/dist/react/hooks/realtime-event-constants.js +8 -0
  521. package/dist/react/hooks/useEntityDelete.js +5 -1
  522. package/dist/react/hooks/useMessage.js +5 -1
  523. package/dist/repositories/index.d.ts +2 -2
  524. package/dist/repositories/index.js +6 -1
  525. package/dist/schemas/registry.d.ts +13 -20
  526. package/dist/schemas/registry.js +31 -14
  527. package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
  528. package/dist/security/encrypted.d.ts +117 -0
  529. package/dist/security/encrypted.js +100 -0
  530. package/dist/security/index.d.ts +5 -2
  531. package/dist/security/index.js +16 -2
  532. package/dist/security/pii-accessors.d.ts +71 -0
  533. package/dist/security/pii-accessors.js +150 -0
  534. package/dist/security/pii-encrypt.d.ts +0 -8
  535. package/dist/security/pii-encrypt.js +22 -15
  536. package/dist/security/pii-mask.d.ts +18 -0
  537. package/dist/security/pii-mask.js +27 -0
  538. package/dist/seed/_helpers/search-txt-wrappers.d.ts +6 -6
  539. package/dist/seed/_helpers/search-txt-wrappers.js +22 -0
  540. package/dist/seed/addresses-seed-data.d.ts +2 -2
  541. package/dist/seed/authenticity-knowledge-seed-data.d.ts +34 -0
  542. package/dist/seed/authenticity-knowledge-seed-data.js +1277 -0
  543. package/dist/seed/bids-seed-data.d.ts +2 -2
  544. package/dist/seed/bids-seed-data.js +23 -2
  545. package/dist/seed/events-seed-data.d.ts +2 -2
  546. package/dist/seed/events-seed-data.js +5 -0
  547. package/dist/seed/faq-seed-data.js +175 -5
  548. package/dist/seed/homepage-sections-seed-data.js +39 -23
  549. package/dist/seed/index.d.ts +1 -0
  550. package/dist/seed/index.js +1 -0
  551. package/dist/seed/lottery-entries-seed-data.d.ts +2 -2
  552. package/dist/seed/offers-seed-data.d.ts +2 -2
  553. package/dist/seed/offers-seed-data.js +1 -1
  554. package/dist/seed/orders-seed-data.d.ts +2 -2
  555. package/dist/seed/payouts-seed-data.d.ts +2 -2
  556. package/dist/seed/payouts-seed-data.js +1 -1
  557. package/dist/seed/reviews-seed-data.d.ts +1 -2
  558. package/dist/seed/seed-purpose.js +7 -0
  559. package/dist/seed/sessions-seed-data.d.ts +2 -2
  560. package/dist/seed/sessions-seed-data.js +5 -0
  561. package/dist/seed/site-settings-seed-data.js +1 -1
  562. package/dist/seed/support-tickets-seed-data.d.ts +2 -2
  563. package/dist/seed/support-tickets-seed-data.js +1 -1
  564. package/dist/seed/users-seed-data.d.ts +2 -2
  565. package/dist/seed/users-seed-data.js +1 -1
  566. package/dist/seo/json-ld.js +5 -1
  567. package/dist/server.d.ts +18 -3
  568. package/dist/server.js +59 -3
  569. package/dist/styles.css +237 -1
  570. package/dist/tailwind-utilities.css +1 -1
  571. package/dist/ui/components/Button.js +7 -1
  572. package/dist/ui/components/FilterChipGroup.d.ts +11 -0
  573. package/dist/ui/components/FilterChipGroup.js +1 -1
  574. package/dist/ui/components/ImageGallery.js +6 -1
  575. package/dist/ui/components/ListingLayout.js +14 -8
  576. package/dist/ui/components/OverflowRow.d.ts +92 -0
  577. package/dist/ui/components/OverflowRow.js +203 -0
  578. package/dist/ui/components/OverflowRow.style.css +235 -0
  579. package/dist/ui/components/RecordDetailModal.js +14 -1
  580. package/dist/ui/components/RowActionMenu.js +5 -1
  581. package/dist/ui/components/SideDrawer.js +5 -1
  582. package/dist/ui/components/SideModal.js +9 -1
  583. package/dist/ui/components/TabBarShell.d.ts +12 -1
  584. package/dist/ui/components/TabBarShell.js +3 -2
  585. package/dist/ui/components/Tabs.js +36 -24
  586. package/dist/ui/components/Toast.d.ts +3 -24
  587. package/dist/ui/components/Toast.js +2 -19
  588. package/dist/ui/components/TopBannerPortal.d.ts +15 -0
  589. package/dist/ui/components/TopBannerPortal.js +19 -0
  590. package/dist/ui/components/UnsavedChangesModal.js +5 -1
  591. package/dist/ui/components/index.style.css +1 -0
  592. package/dist/ui/components/row-collapse.d.ts +15 -0
  593. package/dist/ui/components/row-collapse.js +127 -0
  594. package/dist/ui/components/toast-context.d.ts +63 -0
  595. package/dist/ui/components/toast-context.js +48 -0
  596. package/dist/ui/components/top-banner-slot.d.ts +37 -0
  597. package/dist/ui/components/top-banner-slot.js +45 -0
  598. package/dist/ui/icons/icon-registry.d.ts +6 -0
  599. package/dist/ui/icons/icon-registry.js +17 -1
  600. package/dist/ui/index.d.ts +2 -0
  601. package/dist/ui/index.js +1 -0
  602. package/dist/utils/array.helper.d.ts +2 -2
  603. package/dist/utils/array.helper.js +5 -5
  604. package/dist/utils/id-generators.d.ts +6 -0
  605. package/dist/utils/id-generators.js +10 -0
  606. package/dist/utils/media-url.js +0 -2
  607. package/dist/utils/search-txt-builders.d.ts +28 -4
  608. package/dist/utils/search-txt-builders.js +41 -1
  609. package/dist/validation/schemas.d.ts +8 -8
  610. package/package.json +6 -2
  611. package/scripts/seed-cli.mjs +3 -0
  612. package/dist/features/account/components/UserAddressesView.d.ts +0 -13
  613. package/dist/features/account/components/UserAddressesView.js +0 -5
  614. package/dist/features/account/components/UserNotificationsView.d.ts +0 -15
  615. package/dist/features/account/components/UserNotificationsView.js +0 -12
  616. package/dist/features/account/components/UserSettingsView.d.ts +0 -16
  617. package/dist/features/account/components/UserSettingsView.js +0 -13
  618. package/dist/features/account/components/UserSupportView.d.ts +0 -3
  619. package/dist/features/account/components/UserSupportView.js +0 -166
  620. package/dist/features/admin/components/DemoSeedView.d.ts +0 -11
  621. package/dist/features/admin/components/DemoSeedView.js +0 -5
  622. package/dist/features/auth/components/AuthStatusPanel.d.ts +0 -10
  623. package/dist/features/auth/components/AuthStatusPanel.js +0 -22
  624. package/dist/features/categories/components/CategoryProductsView.d.ts +0 -45
  625. package/dist/features/categories/components/CategoryProductsView.js +0 -21
  626. package/dist/features/homepage/components/HowItWorksInfoView.d.ts +0 -36
  627. package/dist/features/homepage/components/HowItWorksInfoView.js +0 -10
  628. package/dist/features/layout/BottomActions.d.ts +0 -1
  629. package/dist/features/layout/BottomActions.js +0 -311
  630. package/dist/features/products/components/ProductsView.d.ts +0 -6
  631. package/dist/features/products/components/ProductsView.js +0 -5
  632. package/dist/features/seller/components/SellerStoreView.d.ts +0 -8
  633. package/dist/features/seller/components/SellerStoreView.js +0 -8
@@ -0,0 +1,53 @@
1
+ import type { SearchIndexType } from "../../../../shared/search/index-record";
2
+ import type { FirestoreValue } from "../../../../../schemas/types";
3
+ export type IndexDocData = Record<string, FirestoreValue>;
4
+ /** One record under construction. `null` drops the document from the index. */
5
+ export interface BuiltRecord {
6
+ readonly title: string;
7
+ readonly detail: string;
8
+ readonly facets?: string;
9
+ }
10
+ export interface IndexSource {
11
+ /** Matches a `SearchIndexType.key`. */
12
+ readonly typeKey: string;
13
+ readonly collection: string;
14
+ /** Fields to project. A builder reads documents, not whole collections. */
15
+ readonly select: readonly string[];
16
+ /**
17
+ * Extra equality narrowing applied as a query clause. Only use this for a
18
+ * value every public row genuinely carries — otherwise filter in `toRecord`,
19
+ * because a Firestore equality on an absent field matches nothing and an
20
+ * inequality excludes every document lacking it.
21
+ */
22
+ readonly where?: ReadonlyArray<readonly [string, unknown]>;
23
+ /**
24
+ * The record's stable identity, and the artifact's patch key.
25
+ *
26
+ * 🛑 SEPARATE from `toRecord` on purpose. An incremental build must be able
27
+ * to key a document it is REMOVING — one that just became unpublished — and
28
+ * at that moment `toRecord` has returned null and cannot supply a slug. With
29
+ * the slug folded into `toRecord` the two paths keyed differently (doc id on
30
+ * the way out, slug on the way in), which agrees only where slug === id: so
31
+ * every changed product would have been ADDED as a duplicate rather than
32
+ * replaced, while categories and stores looked fine.
33
+ */
34
+ /**
35
+ * Resolve the type PER DOCUMENT, when one collection holds several.
36
+ * `products` is the only such collection today: all nine listing types live
37
+ * in it and each has its own detail route.
38
+ */
39
+ readonly typeKeyOf?: (d: IndexDocData) => string;
40
+ readonly slugOf: (id: string, d: IndexDocData) => string | null;
41
+ readonly toRecord: (id: string, d: IndexDocData) => BuiltRecord | null;
42
+ }
43
+ /**
44
+ * The type table shipped inside the artifact.
45
+ *
46
+ * 🛑 No `label`. The client maps `key` to a translated string; a heading baked
47
+ * in here could not be localised. Weights are a ranking nudge between types
48
+ * that scored equally, not a statement about importance.
49
+ */
50
+ export declare const INDEX_TYPES: readonly SearchIndexType[];
51
+ export declare const PUBLIC_INDEX_SOURCES: readonly IndexSource[];
52
+ /** Index into `INDEX_TYPES` for a source's type key. */
53
+ export declare function typeIndexFor(typeKey: string): number;
@@ -0,0 +1,385 @@
1
+ /*
2
+ * WHY: What goes into the public search artifact — an unauthenticated,
3
+ * immutable, CDN-cached body downloaded by every visitor who searches.
4
+ * WHAT: The membership allowlist and the per-collection record mapping.
5
+ *
6
+ * ## 🛑 MEMBERSHIP IS AN ALLOWLIST. It is deliberately NOT `LISTERS`.
7
+ *
8
+ * `listingProcessor.ts`'s `LISTERS` is a tempting source registry — one entry
9
+ * per collection, already routed through the Sieve adapter, with its own
10
+ * header inviting "a one-line addition". It is the wrong list. Counted
11
+ * 2026-10-19 it holds **20** entries, and four of them are **`users`,
12
+ * `payouts`, `orders`, `notifications`**. "Index everything LISTERS knows
13
+ * about" is one line away from publishing every customer's name to every
14
+ * browser, permanently, for the life of that artifact version.
15
+ *
16
+ * So this file names what is public, and `LISTERS` is only used to READ it.
17
+ * `audit-search-index-artifact` R6 asserts the intersection of this list with
18
+ * the PII and private registries is empty, with "add `users` → must fail" as
19
+ * its negative control.
20
+ *
21
+ * ## 🛑 Every field here was read off the LIVE documents
22
+ *
23
+ * The same rule `search-sources.ts` states, and it earned its keep again:
24
+ * `scammerProfiles` carries `displayNames` (an ARRAY) not `displayName`, and
25
+ * a string read would have produced a null title for every row — the group
26
+ * would simply never have appeared. `partGlossary`'s page needs TWO path
27
+ * segments and its document id already encodes them as `${slot}--${code}`.
28
+ *
29
+ * ## What a record carries, and what it must never carry
30
+ *
31
+ * Title, a one-line detail, a slug and optional facets. No amount of any kind
32
+ * (§ Guest price gating cannot reach an unauthenticated artifact) and no PII.
33
+ *
34
+ * @tag domain:search
35
+ * @tag layer:server
36
+ * @tag pattern:none
37
+ * @tag access:server
38
+ * @tag consumers:index-build/build,searchIndexBuild
39
+ * @tag sideEffects:none
40
+ */
41
+ import { pluginFor } from "../../../../shared/listing-types/_registry.js";
42
+ // Defined here, not in `_registry` — imported from the DEFINING module
43
+ // (Root Cause #18).
44
+ import { ALL_LISTING_TYPES } from "../../../../shared/listing-types/feature-flags.js";
45
+ const str = (v) => typeof v === "string" && v.trim() ? v.trim() : null;
46
+ /**
47
+ * The type table shipped inside the artifact.
48
+ *
49
+ * 🛑 No `label`. The client maps `key` to a translated string; a heading baked
50
+ * in here could not be localised. Weights are a ranking nudge between types
51
+ * that scored equally, not a statement about importance.
52
+ */
53
+ export const INDEX_TYPES = [
54
+ /*
55
+ * 🛑 ONE ENTRY PER LISTING TYPE, DERIVED from the plugin registry — not one
56
+ * `product` entry for the whole collection.
57
+ *
58
+ * The first draft had a single `{ key: "product", hrefTemplate:
59
+ * "/products/{s}" }`, which is Root Cause #48 rebuilt from scratch: "a
60
+ * per-listing-type detailRoute() that silently defaults to the standard
61
+ * product page". An auction lives at `/auctions/{slug}`, a pre-order at
62
+ * `/pre-orders/{slug}`, a classified at `/classified/{slug}`. Every one of
63
+ * those results would have rendered correctly and navigated to the wrong
64
+ * page — the exact failure that made non-standard listings "revert to
65
+ * standard" the first time.
66
+ *
67
+ * `detailRoute` and `browseRoute` come from `pluginFor`, so a tenth listing
68
+ * type is covered the day it is added rather than the day someone notices.
69
+ * Hand-writing them here would be the eleventh enumeration of that union
70
+ * (Root Cause #61).
71
+ */
72
+ ...ALL_LISTING_TYPES.map((t) => {
73
+ const plugin = pluginFor(t);
74
+ return {
75
+ key: t,
76
+ // `detailRoute` builds a concrete path, so hand it the placeholder and
77
+ // let it produce the template. One source of truth, no second mapping.
78
+ hrefTemplate: plugin.detailRoute("{s}"),
79
+ moreHref: String(plugin.browseRoute),
80
+ // Standard listings are the catalogue's centre of gravity; the rest sit
81
+ // just below so a same-score tie favours the commonest thing.
82
+ weight: t === "standard" ? 1.0 : 0.98,
83
+ };
84
+ }),
85
+ { key: "category", hrefTemplate: "/categories/{s}", moreHref: "/categories", weight: 0.95 },
86
+ { key: "brand", hrefTemplate: "/brands/{s}", moreHref: "/brands", weight: 0.9 },
87
+ { key: "part", hrefTemplate: "/parts/{s}", moreHref: "/parts", weight: 0.9 },
88
+ { key: "model", hrefTemplate: "/categories/{s}", moreHref: "/categories", weight: 0.85 },
89
+ { key: "store", hrefTemplate: "/stores/{s}", moreHref: "/stores", weight: 0.8 },
90
+ { key: "blog", hrefTemplate: "/blog/{s}", moreHref: "/blog", weight: 0.7 },
91
+ { key: "event", hrefTemplate: "/events/{s}", moreHref: "/events", weight: 0.7 },
92
+ { key: "faq", hrefTemplate: "/faqs/{s}", moreHref: "/faqs", weight: 0.6 },
93
+ { key: "review", hrefTemplate: "/reviews/{s}", moreHref: "/reviews", weight: 0.5 },
94
+ { key: "group", hrefTemplate: "/groups/{s}", moreHref: "/products", weight: 0.5 },
95
+ { key: "scammer", hrefTemplate: "/scams/{s}", moreHref: "/scams", weight: 0.5 },
96
+ /* `/promotions` has no per-coupon page, so `{s}` is absent on purpose and
97
+ * `hrefFor`'s replace is a no-op. Eleven rows all landing on one page would
98
+ * be noise in the federated GROUP (which is why `search-sources.ts` omits
99
+ * coupons), but in the index it is the difference between a code being
100
+ * findable and not. */
101
+ { key: "coupon", hrefTemplate: "/promotions", moreHref: "/promotions", weight: 0.4 },
102
+ ];
103
+ const facet = (pairs) => {
104
+ const parts = pairs
105
+ .filter(([, v]) => typeof v === "string" && v)
106
+ .map(([k, v]) => `${k}:${v}`);
107
+ return parts.length > 0 ? parts.join("|") : undefined;
108
+ };
109
+ export const PUBLIC_INDEX_SOURCES = [
110
+ {
111
+ /*
112
+ * 🛑 The type key is RESOLVED PER DOCUMENT — see `typeKeyOf`. A source
113
+ * normally maps one collection to one type, but `products` holds all nine
114
+ * listing types and each has its own detail route.
115
+ */
116
+ typeKey: "standard",
117
+ typeKeyOf: (d) => {
118
+ const lt = str(d.listingType);
119
+ return lt && ALL_LISTING_TYPES.includes(lt) ? lt : "standard";
120
+ },
121
+ collection: "products",
122
+ where: [["status", "published"]],
123
+ select: ["title", "slug", "brand", "categoryNames", "listingType", "condition", "franchiseSlug"],
124
+ slugOf: (id, d) => str(d.slug) ?? id,
125
+ toRecord: (id, d) => {
126
+ const title = str(d.title);
127
+ if (!title)
128
+ return null;
129
+ const names = Array.isArray(d.categoryNames) ? d.categoryNames : [];
130
+ /*
131
+ * 🛑 The enum VALUES go in `detail`, which is SEARCHED — the `facets`
132
+ * string is filter-only and never matched as text. Without this,
133
+ * typing "auction" or "sealed" finds nothing, because the only place
134
+ * those words appeared was a facet nobody searches. Humanised, so
135
+ * "pre-order" and "digital code" read as words rather than slugs.
136
+ */
137
+ const human = (v) => (str(v) ?? "").replace(/[-_]/g, " ");
138
+ return {
139
+ title,
140
+ // Leaf-first, so [0] is the most specific label.
141
+ detail: [
142
+ str(d.brand),
143
+ str(names[0]),
144
+ human(d.listingType),
145
+ human(d.condition),
146
+ ]
147
+ .filter(Boolean)
148
+ .join(" · "),
149
+ facets: facet([
150
+ ["lt", d.listingType],
151
+ ["cn", d.condition],
152
+ ["fr", d.franchiseSlug],
153
+ ]),
154
+ };
155
+ },
156
+ },
157
+ {
158
+ typeKey: "category",
159
+ collection: "categories",
160
+ /*
161
+ * 🛑 No `where` on `categoryType`. A plain listing category OMITS the
162
+ * field entirely — the convention CLAUDE.md records — so `== "category"`
163
+ * matches nothing and `!=` excludes every real row. Brands are their own
164
+ * type below and are rejected here rather than dropped.
165
+ */
166
+ select: ["name", "slug", "categoryType", "path", "isActive"],
167
+ slugOf: (id) => id,
168
+ toRecord: (id, d) => {
169
+ const name = str(d.name);
170
+ if (!name)
171
+ return null;
172
+ const type = str(d.categoryType);
173
+ if (type && type !== "sublisting")
174
+ return null;
175
+ if (d.isActive === false)
176
+ return null;
177
+ return { title: name, detail: str(d.path) ?? "", slug: id };
178
+ },
179
+ },
180
+ {
181
+ typeKey: "brand",
182
+ collection: "categories",
183
+ where: [["categoryType", "brand"]],
184
+ select: ["name", "brandCountry", "isActive"],
185
+ slugOf: (id) => id,
186
+ toRecord: (id, d) => {
187
+ const name = str(d.name);
188
+ if (!name)
189
+ return null;
190
+ if (d.isActive === false)
191
+ return null;
192
+ return { title: name, detail: str(d.brandCountry) ?? "", slug: id };
193
+ },
194
+ },
195
+ {
196
+ typeKey: "part",
197
+ collection: "partGlossary",
198
+ select: ["name", "code", "classification", "slot"],
199
+ slugOf: (id) => (id.includes("--") ? id.replace("--", "/") : null),
200
+ toRecord: (id, d) => {
201
+ const name = str(d.name);
202
+ if (!name)
203
+ return null;
204
+ /*
205
+ * 🛑 TWO path segments, and the document id already encodes them.
206
+ * `ROUTES.PUBLIC.PART_DETAIL` is `/parts/{classification}/{code}`, and
207
+ * the route-map comment explains why a code alone cannot be a URL:
208
+ * "`105` is a Metal Fight spin-track height, a bare number in Burst is
209
+ * a disc, and `1-60` is a Beyblade X ratchet." The id is
210
+ * `${slot}--${code}` (e.g. `armour--1b`), so splitting it is the one
211
+ * derivation guaranteed to agree with the page that exists.
212
+ */
213
+ if (!id.includes("--"))
214
+ return null;
215
+ const code = str(d.code);
216
+ const classification = str(d.classification);
217
+ return {
218
+ title: name,
219
+ // The classification IS the disambiguation — it is why a user
220
+ // searching "105" can tell three results apart.
221
+ detail: [classification, code].filter(Boolean).join(" · "),
222
+ };
223
+ },
224
+ },
225
+ {
226
+ typeKey: "model",
227
+ collection: "modelComposition",
228
+ select: ["name", "system", "categoryId"],
229
+ slugOf: (_id, d) => str(d.categoryId),
230
+ toRecord: (_id, d) => {
231
+ const name = str(d.name);
232
+ if (!name)
233
+ return null;
234
+ /*
235
+ * 🛑 A composition has no page of its own — it is rendered on its model
236
+ * CATEGORY page, reached by `categoryId`. Measured in `parts/data.ts`:
237
+ * 210 of 259 join. The 49 that do not are DROPPED rather than linked to
238
+ * a guess, because a search result that navigates to the wrong bey is
239
+ * worse than one that does not exist. The builder reports the count.
240
+ */
241
+ const categoryId = str(d.categoryId);
242
+ if (!categoryId)
243
+ return null;
244
+ return { title: name, detail: str(d.system) ?? "", slug: categoryId };
245
+ },
246
+ },
247
+ {
248
+ typeKey: "store",
249
+ collection: "stores",
250
+ where: [["status", "active"]],
251
+ // `storeName`, not `name` — read off the live documents.
252
+ select: ["storeName", "storeCategory"],
253
+ slugOf: (id) => id,
254
+ toRecord: (id, d) => {
255
+ const name = str(d.storeName);
256
+ if (!name)
257
+ return null;
258
+ return { title: name, detail: str(d.storeCategory) ?? "", slug: id };
259
+ },
260
+ },
261
+ {
262
+ typeKey: "blog",
263
+ collection: "blogPosts",
264
+ where: [["status", "published"]],
265
+ select: ["title", "slug", "category", "excerpt"],
266
+ slugOf: (id, d) => str(d.slug) ?? id,
267
+ toRecord: (id, d) => {
268
+ const title = str(d.title);
269
+ if (!title)
270
+ return null;
271
+ return {
272
+ title,
273
+ detail: str(d.category) ?? (str(d.excerpt) ?? "").slice(0, 90),
274
+ };
275
+ },
276
+ },
277
+ {
278
+ typeKey: "event",
279
+ collection: "events",
280
+ // Three public statuses, one `==` — so it is filtered in memory, the same
281
+ // reason `search-sources.ts` gives.
282
+ select: ["title", "slug", "type", "status"],
283
+ slugOf: (id, d) => str(d.slug) ?? id,
284
+ toRecord: (id, d) => {
285
+ const title = str(d.title);
286
+ if (!title)
287
+ return null;
288
+ const status = str(d.status);
289
+ if (status === "draft" || status === "cancelled")
290
+ return null;
291
+ return { title, detail: (str(d.type) ?? "").replace(/_/g, " "), slug: str(d.slug) ?? id };
292
+ },
293
+ },
294
+ {
295
+ typeKey: "faq",
296
+ collection: "faqs",
297
+ where: [["isActive", true]],
298
+ select: ["question", "category"],
299
+ slugOf: (_id, d) => str(d.category),
300
+ toRecord: (_id, d) => {
301
+ const question = str(d.question);
302
+ const category = str(d.category);
303
+ // `/faqs/[category]`, never a question slug — the route matches on the
304
+ // category key and silently falls back to "all" for anything else.
305
+ if (!question || !category)
306
+ return null;
307
+ return { title: question, detail: category.replace(/_/g, " "), slug: category };
308
+ },
309
+ },
310
+ {
311
+ typeKey: "review",
312
+ collection: "reviews",
313
+ where: [["status", "approved"]],
314
+ // 🛑 `productTitle`, never `userName`. The field exists on the document
315
+ // and is deliberately absent from `buildReviewSearchTxt` because it is
316
+ // encrypted; a public artifact must not carry a reviewer's name.
317
+ select: ["title", "productTitle"],
318
+ slugOf: (id) => id,
319
+ toRecord: (id, d) => {
320
+ const title = str(d.title);
321
+ if (!title)
322
+ return null;
323
+ return { title, detail: str(d.productTitle) ?? "", slug: id };
324
+ },
325
+ },
326
+ {
327
+ typeKey: "group",
328
+ collection: "groupedListings",
329
+ where: [["isActive", true]],
330
+ select: ["title", "slug", "groupTheme", "visibilityStatus"],
331
+ slugOf: (id, d) => str(d.slug) ?? id,
332
+ toRecord: (id, d) => {
333
+ const title = str(d.title);
334
+ if (!title)
335
+ return null;
336
+ if (str(d.visibilityStatus) !== "visible")
337
+ return null;
338
+ return { title, detail: str(d.groupTheme) ?? "", slug: str(d.slug) ?? id };
339
+ },
340
+ },
341
+ {
342
+ typeKey: "scammer",
343
+ collection: "scammerProfiles",
344
+ /*
345
+ * 🛑 `verified` ONLY. Live: verified 3, pending_review 1, rejected 1.
346
+ * Publishing an unaccepted allegation against a named person — with their
347
+ * phone and UPI on the destination page — into an artifact every browser
348
+ * downloads is the most consequential clause in this file.
349
+ */
350
+ where: [["status", "verified"]],
351
+ select: ["displayNames", "scamType", "slug"],
352
+ slugOf: (id, d) => str(d.slug) ?? id,
353
+ toRecord: (id, d) => {
354
+ const names = Array.isArray(d.displayNames) ? d.displayNames : [];
355
+ const title = str(names[0]);
356
+ if (!title)
357
+ return null;
358
+ return {
359
+ title,
360
+ detail: (str(d.scamType) ?? "").replace(/_/g, " "),
361
+ };
362
+ },
363
+ },
364
+ {
365
+ typeKey: "coupon",
366
+ collection: "coupons",
367
+ select: ["code", "name", "validity"],
368
+ slugOf: (_id, d) => str(d.code),
369
+ toRecord: (_id, d) => {
370
+ const code = str(d.code);
371
+ if (!code)
372
+ return null;
373
+ const validity = d.validity;
374
+ if (validity?.isActive === false)
375
+ return null;
376
+ // No amount — the discount VALUE is money and stays out. The code and
377
+ // its name are what someone types.
378
+ return { title: code, detail: str(d.name) ?? "", slug: code };
379
+ },
380
+ },
381
+ ];
382
+ /** Index into `INDEX_TYPES` for a source's type key. */
383
+ export function typeIndexFor(typeKey) {
384
+ return INDEX_TYPES.findIndex((t) => t.key === typeKey);
385
+ }
@@ -1,17 +1,2 @@
1
- /**
2
- * D2 Fix 4 — which collections `/search` spans, and how each row becomes a hit.
3
- *
4
- * 🛑 SIX SOURCES, not fifteen. The redirect page maps 15 `SearchResourceType`
5
- * values, but nine of them are LISTING TYPES inside `products` — auctions,
6
- * pre-orders, prize-draws, classified, digital-codes, live, art, bundles. One
7
- * `products` query covers all of them, and a per-type query would be nine
8
- * fan-outs returning overlapping rows from one collection.
9
- *
10
- * 🛑 Every field here was read off the live documents, not assumed. `stores`
11
- * uses `storeName` (not `name`), `faqs` uses `question` + `seo.slug`, and
12
- * `categories` must be filtered to listing rows because brands and bundles
13
- * share the collection — the same trap that made the `/products` category
14
- * facet offer "Takara-Tomy" as a browsable category (A1 item 4).
15
- */
16
1
  import type { SearchSource } from "./search-everything";
17
2
  export declare const SEARCH_SOURCES: readonly SearchSource[];
@@ -1,3 +1,39 @@
1
+ /**
2
+ * D2 Fix 4 — which collections `/search` spans, and how each row becomes a hit.
3
+ *
4
+ * 🛑 NINE SOURCES, not fifteen. The redirect page maps 15 `SearchResourceType`
5
+ * values, but nine of them are LISTING TYPES inside `products` — auctions,
6
+ * pre-orders, prize-draws, classified, digital-codes, live, art, bundles. One
7
+ * `products` query covers all of them, and a per-type query would be nine
8
+ * fan-outs returning overlapping rows from one collection.
9
+ *
10
+ * 🛑 THREE MORE WERE PLANNED FOR THIS PASS AND DELIBERATELY LEFT OUT. Each
11
+ * would have been a source that renders as a working group and matches
12
+ * nothing, which is worse than an absent one:
13
+ *
14
+ * partGlossary (752 rows) and groupedListings (10) — **0% `searchTxt`
15
+ * coverage**, measured 2026-10-19. This file's mechanism is a single
16
+ * `array-contains` push-down on that field, so a source over either
17
+ * returns zero rows for every query, forever, with a 200. They are the
18
+ * headline gap and they are answered by the prebuilt client index, which
19
+ * needs a title and a slug rather than tokens — not by adding a token
20
+ * writer for 762 documents to serve a query path that index replaces.
21
+ *
22
+ * coupons — 100% token coverage, but there is no per-coupon public route.
23
+ * Every hit would link to `/promotions`, which is already this group's
24
+ * `moreHref`, so eleven rows would all point at one page. The code is
25
+ * worth finding; a group of identical links is not the way.
26
+ *
27
+ * 🛑 Every field here was read off the live documents, not assumed. `stores`
28
+ * uses `storeName` (not `name`), `faqs` uses `question` + `seo.slug`, and
29
+ * `categories` must be filtered to listing rows because brands and bundles
30
+ * share the collection — the same trap that made the `/products` category
31
+ * facet offer "Takara-Tomy" as a browsable category (A1 item 4).
32
+ */
33
+ // Imported from the DEFINING module, not a barrel (Root Cause #18) — and
34
+ // never from `@mohasinac/appkit/client`, which is `"use client"` and would
35
+ // make ROUTES a client-reference proxy in this server file (Root Cause #76).
36
+ import { ROUTES } from "../../../../next/routing/route-map.js";
1
37
  const str = (v) => typeof v === "string" && v.trim() ? v.trim() : null;
2
38
  const withQ = (base, q) => q.trim() ? `${base}?q=${encodeURIComponent(q.trim())}` : base;
3
39
  export const SEARCH_SOURCES = [
@@ -28,7 +64,7 @@ export const SEARCH_SOURCES = [
28
64
  ...(detail ? { detail } : {}),
29
65
  };
30
66
  },
31
- moreHref: (q) => withQ("/products", q),
67
+ moreHref: (q) => withQ(ROUTES.PUBLIC.PRODUCTS, q),
32
68
  },
33
69
  {
34
70
  key: "categories",
@@ -55,7 +91,7 @@ export const SEARCH_SOURCES = [
55
91
  return null;
56
92
  return { id, title: name, href: `/categories/${id}` };
57
93
  },
58
- moreHref: (q) => withQ("/categories", q),
94
+ moreHref: (q) => withQ(ROUTES.PUBLIC.CATEGORIES, q),
59
95
  },
60
96
  {
61
97
  key: "brands",
@@ -71,7 +107,7 @@ export const SEARCH_SOURCES = [
71
107
  const detail = str(d.brandCountry);
72
108
  return { id, title: name, href: `/brands/${id}`, ...(detail ? { detail } : {}) };
73
109
  },
74
- moreHref: (q) => withQ("/brands", q),
110
+ moreHref: (q) => withQ(ROUTES.PUBLIC.BRANDS, q),
75
111
  },
76
112
  {
77
113
  key: "stores",
@@ -86,7 +122,7 @@ export const SEARCH_SOURCES = [
86
122
  return null;
87
123
  return { id, title: name, href: `/stores/${id}` };
88
124
  },
89
- moreHref: (q) => withQ("/stores", q),
125
+ moreHref: (q) => withQ(ROUTES.PUBLIC.STORES, q),
90
126
  },
91
127
  {
92
128
  key: "blog",
@@ -106,7 +142,7 @@ export const SEARCH_SOURCES = [
106
142
  ...(detail ? { detail } : {}),
107
143
  };
108
144
  },
109
- moreHref: (q) => withQ("/blog", q),
145
+ moreHref: (q) => withQ(ROUTES.BLOG.LIST, q),
110
146
  },
111
147
  {
112
148
  key: "faqs",
@@ -129,10 +165,109 @@ export const SEARCH_SOURCES = [
129
165
  return {
130
166
  id,
131
167
  title: question,
132
- href: category ? `/faqs/${category}` : "/faqs",
168
+ href: category ? ROUTES.PUBLIC.FAQ_CATEGORY(category) : ROUTES.PUBLIC.FAQS,
133
169
  ...(category ? { detail: category.replace(/_/g, " ") } : {}),
134
170
  };
135
171
  },
136
- moreHref: (q) => withQ("/faqs", q),
172
+ moreHref: (q) => withQ(ROUTES.PUBLIC.FAQS, q),
173
+ },
174
+ {
175
+ key: "events",
176
+ label: "Events",
177
+ collection: "events",
178
+ /*
179
+ * 🛑 No `where` clause, and that is forced rather than lazy. Measured on
180
+ * the live collection: `active` 8, `draft` 1, `paused` 1, `ended` 1,
181
+ * `cancelled` 1. The public set is "not draft, not cancelled" — three
182
+ * values — and `where` here applies `==` only, so a single clause would
183
+ * either publish drafts or hide every paused and ended event. Firestore
184
+ * cannot express the negation either (Root Cause #59). Same in-memory
185
+ * shape the `categories` source uses, for the same reason.
186
+ *
187
+ * `ended` stays visible deliberately: a search answers "do you have this",
188
+ * and an event that happened is a real answer with a real page.
189
+ */
190
+ select: ["title", "slug", "type", "status"],
191
+ toHit: (id, d) => {
192
+ const title = str(d.title);
193
+ if (!title)
194
+ return null;
195
+ const status = str(d.status);
196
+ if (status === "draft" || status === "cancelled")
197
+ return null;
198
+ const detail = str(d.type);
199
+ return {
200
+ id,
201
+ title,
202
+ href: ROUTES.PUBLIC.EVENT_DETAIL(str(d.slug) ?? id),
203
+ ...(detail ? { detail: detail.replace(/_/g, " ") } : {}),
204
+ };
205
+ },
206
+ moreHref: (q) => withQ(ROUTES.PUBLIC.EVENTS, q),
207
+ },
208
+ {
209
+ key: "reviews",
210
+ label: "Reviews",
211
+ collection: "reviews",
212
+ // All 79 live rows are `approved`; the clause is still explicit, because a
213
+ // rejected review surfacing publicly is the failure that matters here.
214
+ where: [["status", "approved"]],
215
+ /*
216
+ * 🛑 `productTitle` as the detail, NEVER `userName`. The field exists on
217
+ * the document and is deliberately absent from `buildReviewSearchTxt`
218
+ * because it is encrypted; `maskPublicReview` is what the public read path
219
+ * uses. A search hit is a public surface and has no business carrying a
220
+ * reviewer's name even in a subtitle.
221
+ */
222
+ select: ["title", "productTitle", "status"],
223
+ toHit: (id, d) => {
224
+ const title = str(d.title);
225
+ if (!title)
226
+ return null;
227
+ const detail = str(d.productTitle);
228
+ return {
229
+ id,
230
+ title,
231
+ href: ROUTES.PUBLIC.REVIEW_DETAIL(id),
232
+ ...(detail ? { detail } : {}),
233
+ };
234
+ },
235
+ moreHref: (q) => withQ(ROUTES.PUBLIC.REVIEWS, q),
236
+ },
237
+ {
238
+ key: "scammers",
239
+ label: "Scam reports",
240
+ collection: "scammerProfiles",
241
+ /*
242
+ * 🛑 `verified` ONLY, and this clause is the whole point of the source.
243
+ * Measured live: `verified` 3, `pending_review` 1, `rejected` 1. Surfacing
244
+ * an unverified or rejected accusation in site-wide search publishes an
245
+ * allegation the moderation queue has not accepted — against a named
246
+ * person, with their phone and UPI on the page. The scam registry is
247
+ * deliberately public and plaintext-indexed for SEO, which makes getting
248
+ * this clause right more load-bearing here than anywhere else, not less.
249
+ */
250
+ where: [["status", "verified"]],
251
+ /*
252
+ * 🛑 `displayNames` is an ARRAY, not a string — read off the live
253
+ * documents, which is what this file's header asks for and what caught it.
254
+ * A `str(d.displayName)` would have returned null for every row and the
255
+ * group would simply never have appeared.
256
+ */
257
+ select: ["displayNames", "scamType", "slug"],
258
+ toHit: (id, d) => {
259
+ const names = Array.isArray(d.displayNames) ? d.displayNames : [];
260
+ const title = str(names[0]);
261
+ if (!title)
262
+ return null;
263
+ const detail = str(d.scamType);
264
+ return {
265
+ id,
266
+ title,
267
+ href: ROUTES.PUBLIC.SCAM_DETAIL(str(d.slug) ?? id),
268
+ ...(detail ? { detail: detail.replace(/_/g, " ") } : {}),
269
+ };
270
+ },
271
+ moreHref: (q) => withQ(ROUTES.PUBLIC.SCAMS, q),
137
272
  },
138
273
  ];