@mohasinac/appkit 4.52.5 → 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 (630) 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 +11 -0
  336. package/dist/features/layout/AppLayoutShell.js +64 -12
  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.js +1 -1
  348. package/dist/features/layout/cta-anchor.d.ts +31 -0
  349. package/dist/features/layout/cta-anchor.js +31 -0
  350. package/dist/features/layout/hooks/useBottomActions.d.ts +7 -0
  351. package/dist/features/layout/hooks/useBottomActions.js +6 -1
  352. package/dist/features/layout/index.d.ts +9 -1
  353. package/dist/features/layout/index.js +9 -1
  354. package/dist/features/layout/useCtaReveal.d.ts +24 -0
  355. package/dist/features/layout/useCtaReveal.js +82 -0
  356. package/dist/features/layout/useHoldToOpen.d.ts +41 -0
  357. package/dist/features/layout/useHoldToOpen.js +84 -0
  358. package/dist/features/lottery/repository/lottery-entry.repository.d.ts +18 -3
  359. package/dist/features/lottery/repository/lottery-entry.repository.js +48 -6
  360. package/dist/features/lottery/schemas/firestore.d.ts +33 -5
  361. package/dist/features/loyalty/api/balance/route.js +1 -1
  362. package/dist/features/loyalty/api/history/route.js +1 -1
  363. package/dist/features/media/MediaImage.js +0 -1
  364. package/dist/features/media/MediaPickerModal.js +7 -1
  365. package/dist/features/media/modals/ImageEditor.js +5 -1
  366. package/dist/features/media/modals/VideoThumbnailSelector.js +17 -1
  367. package/dist/features/media/repository/media-assets.repository.d.ts +19 -0
  368. package/dist/features/media/upload/CameraCapture.js +16 -1
  369. package/dist/features/media/upload/ImageUpload.js +42 -4
  370. package/dist/features/media/upload/MediaUploadField.js +69 -13
  371. package/dist/features/media/upload/downscale-image.d.ts +56 -0
  372. package/dist/features/media/upload/downscale-image.js +150 -0
  373. package/dist/features/messages/components/ConversationThreadView.js +45 -2
  374. package/dist/features/messages/components/MessageSellerButton.d.ts +15 -1
  375. package/dist/features/messages/components/MessageSellerButton.js +10 -2
  376. package/dist/features/messages/schemas/firestore.d.ts +15 -0
  377. package/dist/features/orders/hooks/useOrders.js +4 -2
  378. package/dist/features/orders/repository/orders.repository.d.ts +15 -4
  379. package/dist/features/orders/repository/orders.repository.js +52 -20
  380. package/dist/features/orders/schemas/firestore.d.ts +15 -4
  381. package/dist/features/orders/schemas/index.d.ts +8 -8
  382. package/dist/features/orders/types/index.d.ts +2 -2
  383. package/dist/features/payments/repository/payments.repository.js +2 -2
  384. package/dist/features/payments/repository/payout.repository.d.ts +23 -6
  385. package/dist/features/payments/repository/payout.repository.js +63 -23
  386. package/dist/features/payments/repository/saved-payment-methods.repository.d.ts +17 -6
  387. package/dist/features/payments/repository/saved-payment-methods.repository.js +59 -11
  388. package/dist/features/payments/schemas/firestore.d.ts +14 -3
  389. package/dist/features/payments/schemas/saved-methods-firestore.d.ts +12 -1
  390. package/dist/features/pre-orders/api/[slug]/route.js +1 -1
  391. package/dist/features/pre-orders/api/admin/route.js +1 -1
  392. package/dist/features/pre-orders/api/route.js +1 -1
  393. package/dist/features/pre-orders/repository/pre-orders.repository.d.ts +3 -3
  394. package/dist/features/pre-orders/repository/pre-orders.repository.js +6 -6
  395. package/dist/features/products/api/[id]/route.js +1 -1
  396. package/dist/features/products/components/ListingBottomActions.js +4 -0
  397. package/dist/features/products/components/ProductDetailPageView.js +2 -1
  398. package/dist/features/products/components/ProductGalleryClient.js +2 -2
  399. package/dist/features/products/components/ProductGrid.js +12 -1
  400. package/dist/features/products/components/index.d.ts +0 -2
  401. package/dist/features/products/components/index.js +0 -1
  402. package/dist/features/products/config/listing-type-listing-config.d.ts +0 -3
  403. package/dist/features/products/config/listing-type-listing-config.js +27 -2
  404. package/dist/features/products/constants/listing-tabs.d.ts +9 -0
  405. package/dist/features/products/constants/listing-tabs.js +3 -2
  406. package/dist/features/products/hooks/useProducts.js +2 -2
  407. package/dist/features/products/repository/products.repository.js +13 -1
  408. package/dist/features/products/schemas/index.d.ts +2 -2
  409. package/dist/features/products/types/index.d.ts +1 -1
  410. package/dist/features/promotions/api/route.js +1 -1
  411. package/dist/features/reviews/actions/review-actions.d.ts +6 -6
  412. package/dist/features/reviews/actions/review-actions.js +22 -8
  413. package/dist/features/reviews/components/ReviewDetailPageView.js +13 -1
  414. package/dist/features/reviews/components/ReviewsIndexPageView.js +21 -4
  415. package/dist/features/reviews/repository/reviews.repository.d.ts +19 -7
  416. package/dist/features/reviews/repository/reviews.repository.js +63 -12
  417. package/dist/features/reviews/schemas/firestore.d.ts +13 -2
  418. package/dist/features/reviews/schemas/index.d.ts +2 -2
  419. package/dist/features/scams/actions/scam-actions.js +16 -4
  420. package/dist/features/search/components/SearchResultsPageView.js +2 -1
  421. package/dist/features/search/hooks/useSearchIndex.d.ts +34 -0
  422. package/dist/features/search/hooks/useSearchIndex.js +172 -0
  423. package/dist/features/search/repository/search.repository.js +2 -2
  424. package/dist/features/seller/actions/offer-actions.d.ts +5 -5
  425. package/dist/features/seller/actions/offer-actions.js +38 -8
  426. package/dist/features/seller/actions/seller-actions.js +34 -7
  427. package/dist/features/seller/api/coupons/route.js +1 -1
  428. package/dist/features/seller/api/products/route.js +1 -1
  429. package/dist/features/seller/api/store/route.js +1 -1
  430. package/dist/features/seller/components/SellerBidsView.js +1 -1
  431. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  432. package/dist/features/seller/components/SellerListingTypeView.js +9 -1
  433. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  434. package/dist/features/seller/components/SellerPayoutSettingsView.js +0 -1
  435. package/dist/features/seller/components/SellerPayoutsView.js +1 -1
  436. package/dist/features/seller/components/SellerProductShell.js +0 -1
  437. package/dist/features/seller/components/SellerProductsView.js +1 -1
  438. package/dist/features/seller/components/SellerShippingView.js +0 -1
  439. package/dist/features/seller/components/SellerStorefrontView.js +0 -1
  440. package/dist/features/seller/components/index.d.ts +0 -4
  441. package/dist/features/seller/components/index.js +0 -2
  442. package/dist/features/seller/repository/offer.repository.d.ts +15 -3
  443. package/dist/features/seller/repository/offer.repository.js +43 -7
  444. package/dist/features/seller/schemas/firestore.d.ts +14 -3
  445. package/dist/features/seller/schemas/index.d.ts +4 -4
  446. package/dist/features/seller/schemas/order-forms.d.ts +39 -0
  447. package/dist/features/seller/schemas/order-forms.js +37 -0
  448. package/dist/features/shell/FormShell.js +6 -2
  449. package/dist/features/shell/QuickFormDrawer.js +15 -1
  450. package/dist/features/shipments/components/AdminShipmentEditorView.js +0 -1
  451. package/dist/features/shipments/components/AdminShipmentsView.js +1 -1
  452. package/dist/features/sticker-trace/components/StickerCommitPanel.d.ts +30 -0
  453. package/dist/features/sticker-trace/components/StickerCommitPanel.js +93 -0
  454. package/dist/features/sticker-trace/components/StickerPrintPanel.d.ts +33 -0
  455. package/dist/features/sticker-trace/components/StickerPrintPanel.js +104 -0
  456. package/dist/features/sticker-trace/components/StickerRetryPanel.d.ts +20 -0
  457. package/dist/features/sticker-trace/components/StickerRetryPanel.js +128 -0
  458. package/dist/features/sticker-trace/components/StickerRunHistoryPanel.d.ts +45 -0
  459. package/dist/features/sticker-trace/components/StickerRunHistoryPanel.js +84 -0
  460. package/dist/features/sticker-trace/components/StickerTraceStudio.d.ts +27 -0
  461. package/dist/features/sticker-trace/components/StickerTraceStudio.js +171 -0
  462. package/dist/features/sticker-trace/constants/help-content.d.ts +23 -0
  463. package/dist/features/sticker-trace/constants/help-content.js +172 -0
  464. package/dist/features/sticker-trace/hooks/useLiveTrace.d.ts +27 -0
  465. package/dist/features/sticker-trace/hooks/useLiveTrace.js +160 -0
  466. package/dist/features/sticker-trace/hooks/useStickerTraceProgress.d.ts +22 -0
  467. package/dist/features/sticker-trace/hooks/useStickerTraceProgress.js +106 -0
  468. package/dist/features/sticker-trace/repository/sticker-sheets.repository.d.ts +113 -0
  469. package/dist/features/sticker-trace/repository/sticker-sheets.repository.js +146 -0
  470. package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.d.ts +132 -0
  471. package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.js +174 -0
  472. package/dist/features/sticker-trace/schemas/firestore.d.ts +248 -0
  473. package/dist/features/sticker-trace/schemas/firestore.js +79 -0
  474. package/dist/features/sticker-trace/server.d.ts +8 -0
  475. package/dist/features/sticker-trace/server.js +51 -0
  476. package/dist/features/stores/actions/store-query-actions.d.ts +2 -2
  477. package/dist/features/stores/actions/store-query-actions.js +7 -2
  478. package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -3
  479. package/dist/features/stores/api/[storeSlug]/products/route.js +3 -3
  480. package/dist/features/stores/api/[storeSlug]/reviews/route.js +1 -1
  481. package/dist/features/stores/api/[storeSlug]/route.js +1 -1
  482. package/dist/features/stores/components/StoreNavTabs.js +17 -2
  483. package/dist/features/stores/manifest.js +8 -4
  484. package/dist/features/support/repository/support.repository.d.ts +14 -3
  485. package/dist/features/support/repository/support.repository.js +93 -13
  486. package/dist/features/support/schemas/firestore.d.ts +16 -5
  487. package/dist/features/tester/seed-data/authored/admin__events-raffles-spin.js +61 -19
  488. package/dist/features/tester/seed-data/authored/buying__browsing-search.js +19 -3
  489. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
  490. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +243 -0
  491. package/dist/features/tester/seed-data/authored/content-discovery__events.js +36 -10
  492. package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.d.ts +2 -0
  493. package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.js +209 -0
  494. package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.d.ts +2 -0
  495. package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.js +90 -0
  496. package/dist/features/tester/seed-data/authored/index.js +8 -0
  497. package/dist/features/tester/seed-data/authored/selling__media-limits.js +19 -17
  498. package/dist/features/tester/seed-data/authored/selling__product-upload-details.js +10 -5
  499. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.d.ts +2 -0
  500. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +283 -0
  501. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +192 -22
  502. package/dist/index.d.ts +10 -23
  503. package/dist/index.js +27 -19
  504. package/dist/next/api/routeHandler.js +9 -0
  505. package/dist/next/routing/require-record.d.ts +13 -0
  506. package/dist/next/routing/require-record.js +62 -0
  507. package/dist/next/routing/route-map.d.ts +4 -4
  508. package/dist/next/routing/route-map.js +25 -3
  509. package/dist/providers/db-firebase/base.d.ts +4 -2
  510. package/dist/providers/db-firebase/base.js +21 -5
  511. package/dist/providers/db-firebase/base.repository.d.ts +11 -9
  512. package/dist/providers/db-firebase/base.repository.js +19 -0
  513. package/dist/providers/db-firebase/rtdb-paths.d.ts +12 -0
  514. package/dist/providers/db-firebase/rtdb-paths.js +12 -0
  515. package/dist/react/ErrorBoundary.js +6 -1
  516. package/dist/react/hooks/realtime-event-constants.d.ts +1 -0
  517. package/dist/react/hooks/realtime-event-constants.js +8 -0
  518. package/dist/react/hooks/useEntityDelete.js +5 -1
  519. package/dist/react/hooks/useMessage.js +5 -1
  520. package/dist/repositories/index.d.ts +2 -2
  521. package/dist/repositories/index.js +6 -1
  522. package/dist/schemas/registry.d.ts +13 -20
  523. package/dist/schemas/registry.js +31 -14
  524. package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
  525. package/dist/security/encrypted.d.ts +117 -0
  526. package/dist/security/encrypted.js +100 -0
  527. package/dist/security/index.d.ts +5 -2
  528. package/dist/security/index.js +16 -2
  529. package/dist/security/pii-accessors.d.ts +71 -0
  530. package/dist/security/pii-accessors.js +150 -0
  531. package/dist/security/pii-encrypt.d.ts +0 -8
  532. package/dist/security/pii-encrypt.js +22 -15
  533. package/dist/security/pii-mask.d.ts +18 -0
  534. package/dist/security/pii-mask.js +27 -0
  535. package/dist/seed/_helpers/search-txt-wrappers.d.ts +6 -6
  536. package/dist/seed/_helpers/search-txt-wrappers.js +22 -0
  537. package/dist/seed/addresses-seed-data.d.ts +2 -2
  538. package/dist/seed/authenticity-knowledge-seed-data.d.ts +34 -0
  539. package/dist/seed/authenticity-knowledge-seed-data.js +1277 -0
  540. package/dist/seed/bids-seed-data.d.ts +2 -2
  541. package/dist/seed/bids-seed-data.js +23 -2
  542. package/dist/seed/events-seed-data.d.ts +2 -2
  543. package/dist/seed/events-seed-data.js +5 -0
  544. package/dist/seed/faq-seed-data.js +175 -5
  545. package/dist/seed/homepage-sections-seed-data.js +39 -23
  546. package/dist/seed/index.d.ts +1 -0
  547. package/dist/seed/index.js +1 -0
  548. package/dist/seed/lottery-entries-seed-data.d.ts +2 -2
  549. package/dist/seed/offers-seed-data.d.ts +2 -2
  550. package/dist/seed/offers-seed-data.js +1 -1
  551. package/dist/seed/orders-seed-data.d.ts +2 -2
  552. package/dist/seed/payouts-seed-data.d.ts +2 -2
  553. package/dist/seed/payouts-seed-data.js +1 -1
  554. package/dist/seed/reviews-seed-data.d.ts +1 -2
  555. package/dist/seed/seed-purpose.js +7 -0
  556. package/dist/seed/sessions-seed-data.d.ts +2 -2
  557. package/dist/seed/sessions-seed-data.js +5 -0
  558. package/dist/seed/site-settings-seed-data.js +1 -1
  559. package/dist/seed/support-tickets-seed-data.d.ts +2 -2
  560. package/dist/seed/support-tickets-seed-data.js +1 -1
  561. package/dist/seed/users-seed-data.d.ts +2 -2
  562. package/dist/seed/users-seed-data.js +1 -1
  563. package/dist/seo/json-ld.js +5 -1
  564. package/dist/server.d.ts +18 -3
  565. package/dist/server.js +59 -3
  566. package/dist/styles.css +237 -1
  567. package/dist/tailwind-utilities.css +1 -1
  568. package/dist/ui/components/Button.js +7 -1
  569. package/dist/ui/components/FilterChipGroup.d.ts +11 -0
  570. package/dist/ui/components/FilterChipGroup.js +1 -1
  571. package/dist/ui/components/ImageGallery.js +6 -1
  572. package/dist/ui/components/ListingLayout.js +14 -8
  573. package/dist/ui/components/OverflowRow.d.ts +92 -0
  574. package/dist/ui/components/OverflowRow.js +203 -0
  575. package/dist/ui/components/OverflowRow.style.css +235 -0
  576. package/dist/ui/components/RecordDetailModal.js +14 -1
  577. package/dist/ui/components/RowActionMenu.js +5 -1
  578. package/dist/ui/components/SideDrawer.js +5 -1
  579. package/dist/ui/components/SideModal.js +9 -1
  580. package/dist/ui/components/TabBarShell.d.ts +12 -1
  581. package/dist/ui/components/TabBarShell.js +3 -2
  582. package/dist/ui/components/Tabs.js +36 -24
  583. package/dist/ui/components/Toast.d.ts +3 -24
  584. package/dist/ui/components/Toast.js +2 -19
  585. package/dist/ui/components/TopBannerPortal.d.ts +15 -0
  586. package/dist/ui/components/TopBannerPortal.js +19 -0
  587. package/dist/ui/components/UnsavedChangesModal.js +5 -1
  588. package/dist/ui/components/index.style.css +1 -0
  589. package/dist/ui/components/row-collapse.d.ts +15 -0
  590. package/dist/ui/components/row-collapse.js +127 -0
  591. package/dist/ui/components/toast-context.d.ts +63 -0
  592. package/dist/ui/components/toast-context.js +48 -0
  593. package/dist/ui/components/top-banner-slot.d.ts +37 -0
  594. package/dist/ui/components/top-banner-slot.js +45 -0
  595. package/dist/ui/icons/icon-registry.d.ts +6 -0
  596. package/dist/ui/icons/icon-registry.js +17 -1
  597. package/dist/ui/index.d.ts +2 -0
  598. package/dist/ui/index.js +1 -0
  599. package/dist/utils/array.helper.d.ts +2 -2
  600. package/dist/utils/array.helper.js +5 -5
  601. package/dist/utils/id-generators.d.ts +6 -0
  602. package/dist/utils/id-generators.js +10 -0
  603. package/dist/utils/media-url.js +0 -2
  604. package/dist/utils/search-txt-builders.d.ts +28 -4
  605. package/dist/utils/search-txt-builders.js +41 -1
  606. package/dist/validation/schemas.d.ts +8 -8
  607. package/package.json +6 -2
  608. package/scripts/seed-cli.mjs +3 -0
  609. package/dist/features/account/components/UserAddressesView.d.ts +0 -13
  610. package/dist/features/account/components/UserAddressesView.js +0 -5
  611. package/dist/features/account/components/UserNotificationsView.d.ts +0 -15
  612. package/dist/features/account/components/UserNotificationsView.js +0 -12
  613. package/dist/features/account/components/UserSettingsView.d.ts +0 -16
  614. package/dist/features/account/components/UserSettingsView.js +0 -13
  615. package/dist/features/account/components/UserSupportView.d.ts +0 -3
  616. package/dist/features/account/components/UserSupportView.js +0 -166
  617. package/dist/features/admin/components/DemoSeedView.d.ts +0 -11
  618. package/dist/features/admin/components/DemoSeedView.js +0 -5
  619. package/dist/features/auth/components/AuthStatusPanel.d.ts +0 -10
  620. package/dist/features/auth/components/AuthStatusPanel.js +0 -22
  621. package/dist/features/categories/components/CategoryProductsView.d.ts +0 -45
  622. package/dist/features/categories/components/CategoryProductsView.js +0 -21
  623. package/dist/features/homepage/components/HowItWorksInfoView.d.ts +0 -36
  624. package/dist/features/homepage/components/HowItWorksInfoView.js +0 -10
  625. package/dist/features/layout/BottomActions.d.ts +0 -1
  626. package/dist/features/layout/BottomActions.js +0 -311
  627. package/dist/features/products/components/ProductsView.d.ts +0 -6
  628. package/dist/features/products/components/ProductsView.js +0 -5
  629. package/dist/features/seller/components/SellerStoreView.d.ts +0 -8
  630. package/dist/features/seller/components/SellerStoreView.js +0 -8
@@ -0,0 +1,119 @@
1
+ /*
2
+ * WHY: The browser and the builder must agree on where the search artifact
3
+ * lives, and the obvious URL for a public Storage object is the wrong
4
+ * one.
5
+ * WHAT: The two public URLs — the manifest and a versioned artifact — derived
6
+ * from the bucket name alone, with no Firebase SDK on either side.
7
+ *
8
+ * ## 🛑 The plain `GCS_HOST` URL does NOT work. Measured.
9
+ *
10
+ * It is the first one anyone reaches for and it returns **403**:
11
+ *
12
+ * GET https://{GCS_HOST}/<bucket>/search-index/v3.json -> 403
13
+ * GET https://{FIREBASE_STORAGE_HOST}/v0/b/<bucket>/o/
14
+ * search-index%2Fv3.json?alt=media -> 200
15
+ *
16
+ * (Both hosts are named by their constants rather than spelled out, because
17
+ * `audit-firestore-storage-urls` is strict-zero on the literals and does not
18
+ * strip comments. That is the correct constraint, not a nuisance: the hosts
19
+ * have exactly one declaration, in `utils/media-url.ts`, and this file
20
+ * imports it rather than becoming a second.)
21
+ *
22
+ * `storage.rules`'s `allow read: if true` is a **Firebase Storage** rule. It
23
+ * is evaluated by the Firebase download endpoint and has no bearing on the
24
+ * plain GCS JSON/XML API, which answers to IAM and object ACLs — neither of
25
+ * which grants `allUsers`. So the rule that makes this artifact public only
26
+ * applies on one of the two hosts.
27
+ *
28
+ * ## 🛑 Why this is NOT a `/media/<slug>` reference
29
+ *
30
+ * That audit's stated rule is "every MEDIA reference flows through
31
+ * `/media/<slug>`", and this is not media. Two reasons it must not be routed
32
+ * that way:
33
+ *
34
+ * 1. the proxy resolves a slug through a `mediaAssets/{slug}` Firestore read
35
+ * and then watermarks images — neither of which means anything for a JSON
36
+ * data file;
37
+ * 2. it would put a Vercel function in the path of a 405 KB download for
38
+ * every cold visitor. Root Cause #104 is precisely that bill — 52.52 GB
39
+ * of Fast Origin Transfer against a 10 GB allowance — and the whole point
40
+ * of an immutable version-addressed object is that nothing of ours serves
41
+ * it twice.
42
+ *
43
+ * Verified on the live bucket 2026-10-19, on the second host:
44
+ *
45
+ * Cache-Control: public, max-age=31536000, immutable (passed through)
46
+ * Access-Control-Allow-Origin: https://www.letitrip.in
47
+ * Vary: Origin
48
+ * Content-Length: 418830
49
+ *
50
+ * So the response is cacheable, CORS-readable and non-opaque — which is the
51
+ * whole precondition for the service worker rule and for being able to tell a
52
+ * 404 apart from an empty index.
53
+ *
54
+ * ## 🛑 The tracked CORS config had drifted from the live bucket
55
+ *
56
+ * Found while verifying the above. `appkit/firebase/base/storage-cors.json`
57
+ * is the tracked source of truth and `npm run storage:cors` applies it — but
58
+ * the live bucket had an origin (`letitrip-in-app.vercel.app`), a method
59
+ * (`POST`) and two response headers (`x-goog-resumable`,
60
+ * `x-goog-content-length-range`) the file did not, all of which the
61
+ * resumable-upload path uses. So running the script to "sync" it would have
62
+ * NARROWED the live config and broken uploads, in a repo where that command
63
+ * reads like the safe, idempotent thing to do.
64
+ *
65
+ * The file is now a strict SUPERSET of what was measured live, so applying it
66
+ * can only widen. The config was NOT re-applied as part of this work: GET
67
+ * from the app origins already worked, and re-applying is an upload-path
68
+ * change that has no business riding along with a search feature.
69
+ *
70
+ * ## The path must be percent-encoded WHOLE
71
+ *
72
+ * `/v0/b/<bucket>/o/<object>` takes the object name as ONE path segment, so
73
+ * the `/` inside `search-index/v3.json` has to become `%2F`. `encodeURIComponent`
74
+ * does exactly that; `encodeURI` does not, and would 404 in a way that reads
75
+ * like a missing artifact rather than a malformed URL.
76
+ *
77
+ * @tag domain:search
78
+ * @tag layer:shared
79
+ * @tag pattern:none
80
+ * @tag access:isomorphic
81
+ * @tag consumers:useSearchIndex,artifact-store,verify-search-serving
82
+ * @tag sideEffects:none
83
+ */
84
+ /*
85
+ * The host comes from its ONE declaration. `utils/media-url.ts` is named in
86
+ * `audit-firestore-storage-urls`'s allowlist as the sole place these strings
87
+ * may appear, with every other module importing from it — so importing is
88
+ * the sanctioned mechanism here, not an exemption carved out for search.
89
+ */
90
+ import { FIREBASE_STORAGE_HOST } from "../../../utils/media-url.js";
91
+ /** `search-index/v{n}.json` — the version IS the cache key. */
92
+ export const SEARCH_INDEX_PREFIX = "search-index";
93
+ /**
94
+ * The manifest mirror's object name.
95
+ *
96
+ * 🛑 A MIRROR of `searchIndex/manifest` in Firestore, never the source of
97
+ * truth. The build writes Firestore first and this second, because the
98
+ * Firestore document is what the next build reads to decide its mode — a
99
+ * mirror that disagrees costs a stale client for 60 seconds, whereas a
100
+ * manifest the builder cannot trust costs a full rebuild.
101
+ *
102
+ * It exists so the client bootstrap is two plain `fetch`es and no Firebase
103
+ * SDK: pulling in the client SDK to read one small document would cost more
104
+ * bytes than the index it is pointing at.
105
+ */
106
+ export const SEARCH_MANIFEST_OBJECT = `${SEARCH_INDEX_PREFIX}/manifest.json`;
107
+ export function searchIndexObjectPath(version) {
108
+ return `${SEARCH_INDEX_PREFIX}/v${version}.json`;
109
+ }
110
+ /** Public download URL for any object in the app's Storage bucket. */
111
+ export function firebaseDownloadUrl(bucket, objectPath) {
112
+ return `https://${FIREBASE_STORAGE_HOST}/v0/b/${bucket}/o/${encodeURIComponent(objectPath)}?alt=media`;
113
+ }
114
+ export function searchManifestUrl(bucket) {
115
+ return firebaseDownloadUrl(bucket, SEARCH_MANIFEST_OBJECT);
116
+ }
117
+ export function searchArtifactUrl(bucket, version) {
118
+ return firebaseDownloadUrl(bucket, searchIndexObjectPath(version));
119
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Bumped when the tuple or the envelope changes shape.
3
+ *
4
+ * 🛑 The client REFUSES an artifact whose schema it does not recognise and
5
+ * falls back to the server path, rather than rendering a half-understood one.
6
+ * That is why this is in the envelope and not implied by the URL.
7
+ */
8
+ export declare const SEARCH_INDEX_SCHEMA_VERSION = 1;
9
+ /**
10
+ * The incremental build's watermark field.
11
+ *
12
+ * 🛑 ONE shared constant for the same reason `SEARCH_TXT_FIELD` is one:
13
+ * `updatedAt` is a CROSS-COLLECTION convention declared on `BaseDocument`, and
14
+ * `field-names.ts` repeats it in four separate per-feature blocks. A builder
15
+ * that queries THIRTEEN collections cannot honestly borrow any single
16
+ * feature's copy — `PRODUCT_FIELDS.UPDATED_AT` naming the field on a `faqs`
17
+ * query is a true string and a false statement.
18
+ */
19
+ export declare const INDEX_UPDATED_AT_FIELD = "updatedAt";
20
+ /** One searchable kind. The artifact carries the table so the client needs no map. */
21
+ export interface SearchIndexType {
22
+ /** Stable key — `product`, `category`, `part`, … Also the i18n label key. */
23
+ readonly key: string;
24
+ /** `"/products/{s}"` — exactly one substitution, `{s}`, the record's slug. */
25
+ readonly hrefTemplate: string;
26
+ /** The indexable browse page, for the group's "see all" footer. */
27
+ readonly moreHref: string;
28
+ /** Type-level ranking nudge. A product outranks a review for the same score. */
29
+ readonly weight: number;
30
+ }
31
+ /** Tuple positions, named once so no call site indexes by magic number. */
32
+ export declare const REC_TYPE = 0;
33
+ export declare const REC_TITLE = 1;
34
+ export declare const REC_DETAIL = 2;
35
+ export declare const REC_SLUG = 3;
36
+ export declare const REC_FACETS = 4;
37
+ /**
38
+ * `[typeIdx, title, detail, slug, facets?]`
39
+ *
40
+ * `facets` is a compact pipe-joined string (`"lt:auction|br:takara-tomy"`) and
41
+ * is absent rather than empty when a record has none — an omitted trailing
42
+ * element costs two bytes, `""` costs four, times 3,730.
43
+ */
44
+ export type SearchIndexRecord = readonly [
45
+ number,
46
+ string,
47
+ string,
48
+ string,
49
+ string?
50
+ ];
51
+ export interface SearchIndexArtifact {
52
+ readonly schema: number;
53
+ /** Monotonic build number. The artifact is addressed by it and immutable. */
54
+ readonly version: number;
55
+ readonly builtAt: string;
56
+ readonly types: readonly SearchIndexType[];
57
+ readonly r: readonly SearchIndexRecord[];
58
+ }
59
+ /** Resolve a record's destination from the type table. */
60
+ export declare function hrefFor(artifact: Pick<SearchIndexArtifact, "types">, rec: SearchIndexRecord): string;
61
+ /**
62
+ * Parse the compact facet string into pairs.
63
+ *
64
+ * Returns an empty array for an absent or malformed field rather than
65
+ * throwing: a facet is a refinement, and a record whose facets cannot be read
66
+ * is still a record somebody should be able to find.
67
+ */
68
+ export declare function facetsOf(rec: SearchIndexRecord): ReadonlyArray<readonly [string, string]>;
@@ -0,0 +1,96 @@
1
+ /*
2
+ * WHY: The public search index is one artifact fetched once per visitor and
3
+ * searched in the browser, so its shape is a wire format — every field
4
+ * costs bytes on every download, and every field that can be DERIVED
5
+ * instead of stored should be.
6
+ * WHAT: The record tuple, the type table, and the artifact envelope. Shared by
7
+ * the builder (server) and the matcher (browser) so the two cannot drift.
8
+ *
9
+ * ## 🛑 Why a tuple and not an object
10
+ *
11
+ * 3,730 records. An object repeats its keys on every row; a tuple does not.
12
+ * Measured on the real corpus: 373 KB raw / 63 KB gzip / 46 KB brotli as
13
+ * tuples. The readability cost is paid once, here, by naming the positions.
14
+ *
15
+ * ## What is deliberately ABSENT, and why each
16
+ *
17
+ * href derivable from `types[typeIdx].hrefTemplate`
18
+ * normalised derived once at load with the SAME `normalizeSearchText` the
19
+ * title write path uses — storing it would be a second copy of a
20
+ * string we already ship
21
+ * tokens derived by calling the SAME `aliasVariantsForName` /
22
+ * `partAliasTokens` that are already in the bundle. Shipping
23
+ * them would duplicate a corpus the client already has
24
+ * label 🛑 NOT on the type table. A human-readable group heading baked
25
+ * into the artifact is untranslatable, and this app is
26
+ * `[locale]`-routed with every other UI string going through the
27
+ * label system. The client maps `key` -> label at render time
28
+ * price § Guest price gating is a CLIENT gate; it reaches the rendered
29
+ * DOM and nothing else. This artifact is unauthenticated and
30
+ * immutable-cached, so no gate can reach it — an amount here is
31
+ * published to everyone, permanently, for that version
32
+ * PII same argument, one step worse. Includes blind-index digests: a
33
+ * deterministic per-person identifier is cross-referenceable
34
+ * even unbroken
35
+ *
36
+ * The last two are enforced, not merely documented — see
37
+ * scripts/audit-search-index-artifact.mjs.
38
+ *
39
+ * @tag domain:search
40
+ * @tag layer:shared
41
+ * @tag pattern:none
42
+ * @tag access:isomorphic
43
+ * @tag consumers:index-build,match,verify-search-local
44
+ * @tag sideEffects:none
45
+ */
46
+ /**
47
+ * Bumped when the tuple or the envelope changes shape.
48
+ *
49
+ * 🛑 The client REFUSES an artifact whose schema it does not recognise and
50
+ * falls back to the server path, rather than rendering a half-understood one.
51
+ * That is why this is in the envelope and not implied by the URL.
52
+ */
53
+ export const SEARCH_INDEX_SCHEMA_VERSION = 1;
54
+ /**
55
+ * The incremental build's watermark field.
56
+ *
57
+ * 🛑 ONE shared constant for the same reason `SEARCH_TXT_FIELD` is one:
58
+ * `updatedAt` is a CROSS-COLLECTION convention declared on `BaseDocument`, and
59
+ * `field-names.ts` repeats it in four separate per-feature blocks. A builder
60
+ * that queries THIRTEEN collections cannot honestly borrow any single
61
+ * feature's copy — `PRODUCT_FIELDS.UPDATED_AT` naming the field on a `faqs`
62
+ * query is a true string and a false statement.
63
+ */
64
+ export const INDEX_UPDATED_AT_FIELD = "updatedAt";
65
+ /** Tuple positions, named once so no call site indexes by magic number. */
66
+ export const REC_TYPE = 0;
67
+ export const REC_TITLE = 1;
68
+ export const REC_DETAIL = 2;
69
+ export const REC_SLUG = 3;
70
+ export const REC_FACETS = 4;
71
+ /** Resolve a record's destination from the type table. */
72
+ export function hrefFor(artifact, rec) {
73
+ const type = artifact.types[rec[REC_TYPE]];
74
+ if (!type)
75
+ return "/";
76
+ return type.hrefTemplate.replace("{s}", rec[REC_SLUG]);
77
+ }
78
+ /**
79
+ * Parse the compact facet string into pairs.
80
+ *
81
+ * Returns an empty array for an absent or malformed field rather than
82
+ * throwing: a facet is a refinement, and a record whose facets cannot be read
83
+ * is still a record somebody should be able to find.
84
+ */
85
+ export function facetsOf(rec) {
86
+ const raw = rec[REC_FACETS];
87
+ if (!raw)
88
+ return [];
89
+ const out = [];
90
+ for (const part of raw.split("|")) {
91
+ const i = part.indexOf(":");
92
+ if (i > 0)
93
+ out.push([part.slice(0, i), part.slice(i + 1)]);
94
+ }
95
+ return out;
96
+ }
@@ -0,0 +1,65 @@
1
+ import { type SearchIndexArtifact, type SearchIndexRecord } from "./index-record";
2
+ export interface ResolvedEntity {
3
+ /** Index into `artifact.types`. */
4
+ readonly typeIdx: number;
5
+ readonly typeKey: string;
6
+ readonly title: string;
7
+ readonly detail: string;
8
+ readonly href: string;
9
+ readonly score: number;
10
+ }
11
+ export interface ResolveOptions {
12
+ readonly limit?: number;
13
+ /** Restrict to these type keys. Empty/absent means every type. */
14
+ readonly types?: readonly string[];
15
+ /** Require every one of these `k:v` facet pairs. */
16
+ readonly facets?: readonly string[];
17
+ }
18
+ /** One record's searchable text, prepared once at load. */
19
+ interface Prepared {
20
+ readonly rec: SearchIndexRecord;
21
+ readonly titleWords: readonly string[];
22
+ readonly titleFlat: string;
23
+ readonly detailWords: readonly string[];
24
+ readonly detailFlat: string;
25
+ /** Alias + misspelling forms of the TITLE. See `prepareIndex`. */
26
+ readonly aliasWords: readonly string[];
27
+ readonly aliasFlat: string;
28
+ }
29
+ /**
30
+ * Prepare an artifact for searching.
31
+ *
32
+ * 🛑 Call this ONCE per artifact, not per query. It normalises every title and
33
+ * detail up front — ~3,700 × 2 `normalizeSearchText` calls, a few milliseconds
34
+ * — so that the per-keystroke path does no allocation beyond the query's own
35
+ * terms. Doing it inside `search` would move that cost onto every keystroke,
36
+ * which is the one thing this design exists to avoid.
37
+ */
38
+ export declare function prepareIndex(artifact: SearchIndexArtifact): readonly Prepared[];
39
+ /**
40
+ * Search a prepared artifact.
41
+ *
42
+ * Returns a flat, score-ordered list. Grouping by type is the caller's job —
43
+ * the dropdown and the results page group differently, and a tool wants
44
+ * neither.
45
+ */
46
+ export declare function searchIndex(artifact: SearchIndexArtifact, prepared: readonly Prepared[], query: string, opts?: ResolveOptions): readonly ResolvedEntity[];
47
+ /**
48
+ * The named primitive the tools call.
49
+ *
50
+ * 🛑 `types` is a parameter from day one BECAUSE the tools exist. `/parts`
51
+ * wants parts, the price index wants category leaves, the authenticity
52
+ * typeahead wants canonical models — three consumers, three subsets. Adding
53
+ * the filter later would mean changing every call site that had already been
54
+ * written without it.
55
+ *
56
+ * 🛑 It must NOT be wired into `/tools/authenticity`'s VERDICT path. That
57
+ * engine's fuzzy matching is evidence — a near-miss fires a trademark-evasion
58
+ * warning — and this matcher's alias corpus is built from a counterfeit
59
+ * seller's own spellings. Feeding one into the other would silence the warning
60
+ * by construction. The typeahead may propose a canonical entity; the engine
61
+ * must still analyse what the user actually typed. Enforced by
62
+ * audit-entity-resolver-consumers R2.
63
+ */
64
+ export declare function resolveEntity(artifact: SearchIndexArtifact, prepared: readonly Prepared[], query: string, opts?: ResolveOptions): readonly ResolvedEntity[];
65
+ export type { Prepared as PreparedIndex };
@@ -0,0 +1,263 @@
1
+ /*
2
+ * WHY: Searching a 3,730-record artifact in the browser, at zero Firestore
3
+ * reads per keystroke. The action-index route already states the
4
+ * doctrine this follows: "One request per session per portal, never per
5
+ * keystroke… a typeahead has to answer in under 16 ms, which a network
6
+ * hop cannot."
7
+ * WHAT: A pure, isomorphic matcher plus `resolveEntity`, the named primitive
8
+ * the /tools surfaces call.
9
+ *
10
+ * ## 🛑 ONE normaliser, and it is imported, not reimplemented
11
+ *
12
+ * `normalizeSearchText` is the same function the write path and the Firestore
13
+ * path use. `audit-search-parity`'s R2 exists because a second tokeniser
14
+ * writes tokens the query side cannot match — "and re-running the backfill
15
+ * does NOT fix it". A library would have brought a third; this file must not
16
+ * grow a local lowercase/NFD pipeline. Enforced by that audit.
17
+ *
18
+ * ## Why hand-rolled rather than MiniSearch
19
+ *
20
+ * Three reasons, in order of weight:
21
+ *
22
+ * 1. the normaliser argument above;
23
+ * 2. typo tolerance is already solved at WRITE time with evidence —
24
+ * `alias-variants` derives its suffix swaps from a crawl of a counterfeit
25
+ * seller's 1,277 titles, which is better grounded than generic edit
26
+ * distance and costs nothing at query time;
27
+ * 3. ~3,700 records is below where an inverted index earns its complexity. A
28
+ * linear scan is a few thousand cheap iterations.
29
+ *
30
+ * 🛑 (3) is a claim with a number attached, and the number is checked —
31
+ * `scripts/verify-search-local.mjs` times it and prints the result. If that
32
+ * ever stops being true, this comment is the thing to come back and delete.
33
+ *
34
+ * ## 🛑 It is NOT BM25 and must not be described as BM25
35
+ *
36
+ * BM25's two moving parts are IDF and length normalisation. Titles here
37
+ * average 20 characters, so length normalisation is degenerate; IDF over one
38
+ * domain mostly re-derives "beyblade is common", which `weight` already
39
+ * encodes. Calling an ordered weight sum "BM25-ish" would be decoration
40
+ * (Root Cause #92). It is a weighted match score, the weights are below, and
41
+ * they are tuned against the verify script.
42
+ *
43
+ * ## What this has that the Firestore path structurally cannot
44
+ *
45
+ * SUBSTRING. `search-txt.ts` states the limit outright: "Word-prefix, not
46
+ * mid-word. 'ariza' will not match 'charizard'." A linear scan gets mid-word
47
+ * for free, which is why Tier 1 is better at its job than Tier 2, not merely
48
+ * cheaper.
49
+ *
50
+ * @tag domain:search
51
+ * @tag layer:shared
52
+ * @tag pattern:none
53
+ * @tag access:isomorphic
54
+ * @tag consumers:useSiteSearch,/parts,/tools/price-index,verify-search-local
55
+ * @tag sideEffects:none
56
+ */
57
+ import { normalizeSearchText, parseSearchTxtQuery } from "../../../utils/search-txt.js";
58
+ import { aliasVariantsForName } from "./alias-variants.js";
59
+ import { partAliasTokens } from "./part-aliases.js";
60
+ import { facetsOf, hrefFor, REC_DETAIL, REC_TITLE, REC_TYPE, } from "./index-record.js";
61
+ /** Field weights. Title dominates; a detail match is corroboration. */
62
+ const W_TITLE = 3;
63
+ const W_DETAIL = 1;
64
+ /** Match-quality weights, highest first. */
65
+ const S_EXACT = 100;
66
+ const S_PREFIX = 60;
67
+ const S_SUBSTRING = 30;
68
+ const S_ALIAS = 15;
69
+ /** Default cap. A dropdown shows ~6 per group; a page shows more. */
70
+ const DEFAULT_LIMIT = 50;
71
+ /**
72
+ * Prepare an artifact for searching.
73
+ *
74
+ * 🛑 Call this ONCE per artifact, not per query. It normalises every title and
75
+ * detail up front — ~3,700 × 2 `normalizeSearchText` calls, a few milliseconds
76
+ * — so that the per-keystroke path does no allocation beyond the query's own
77
+ * terms. Doing it inside `search` would move that cost onto every keystroke,
78
+ * which is the one thing this design exists to avoid.
79
+ */
80
+ export function prepareIndex(artifact) {
81
+ return artifact.r.map((rec) => {
82
+ const title = rec[REC_TITLE] ?? "";
83
+ const titleFlat = normalizeSearchText(title);
84
+ const detailFlat = normalizeSearchText(rec[REC_DETAIL] ?? "");
85
+ /*
86
+ * 🛑 The alias corpus is expanded against the DOCUMENT, not the query, and
87
+ * getting this backwards is a real bug I shipped into the first draft.
88
+ *
89
+ * `aliasVariantsForName` is DIRECTIONAL: `doubledLetterVariants` collapses
90
+ * `dragoon -> dragon`, it does not expand `dragon -> dragoon`. The
91
+ * Firestore path works because `buildProductSearchTxt` runs it over the
92
+ * TITLE at write time, so the document carries "dragon" as a token.
93
+ * Expanding the query instead produces nothing for that rule, and the
94
+ * verify script caught it: searching "dragon" found no "Dragoon Storm".
95
+ *
96
+ * So the client does at LOAD what the server does at WRITE — same
97
+ * function, same direction, same result. It also keeps the variants out
98
+ * of the artifact, which is why `index-record.ts` does not carry them.
99
+ *
100
+ * `partAliasTokens` is symmetric (a code <-> name table), so it would have
101
+ * worked either way; it runs here too so there is one rule, not two.
102
+ */
103
+ const aliasSet = new Set();
104
+ for (const v of aliasVariantsForName(title))
105
+ aliasSet.add(normalizeSearchText(v));
106
+ for (const v of partAliasTokens(`${title} ${rec[REC_DETAIL] ?? ""}`)) {
107
+ aliasSet.add(normalizeSearchText(v));
108
+ }
109
+ aliasSet.delete(titleFlat); // a variant identical to the title adds nothing
110
+ const aliasFlat = [...aliasSet].filter(Boolean).join(" ");
111
+ return {
112
+ rec,
113
+ titleFlat,
114
+ detailFlat,
115
+ aliasFlat,
116
+ titleWords: titleFlat ? titleFlat.split(" ") : [],
117
+ detailWords: detailFlat ? detailFlat.split(" ") : [],
118
+ aliasWords: aliasFlat ? aliasFlat.split(" ") : [],
119
+ };
120
+ });
121
+ }
122
+ /** Best match quality for one term against one field. 0 means no match. */
123
+ function fieldScore(term, words, flat) {
124
+ if (!flat)
125
+ return 0;
126
+ for (const w of words)
127
+ if (w === term)
128
+ return S_EXACT;
129
+ for (const w of words)
130
+ if (w.startsWith(term))
131
+ return S_PREFIX;
132
+ // Mid-word. The capability the token index cannot have.
133
+ if (flat.includes(term))
134
+ return S_SUBSTRING;
135
+ return 0;
136
+ }
137
+ function recordScore(p, terms, typeWeight) {
138
+ let total = 0;
139
+ for (const term of terms) {
140
+ /*
141
+ * An alias match is real but WEAKER than a direct one: `S_ALIAS` is the
142
+ * ceiling for that field, so "Dragoon Storm" still outranks a record that
143
+ * only matched through a generated misspelling.
144
+ */
145
+ const aliasHit = fieldScore(term, p.aliasWords, p.aliasFlat) > 0 ? S_ALIAS : 0;
146
+ const best = Math.max(fieldScore(term, p.titleWords, p.titleFlat) * W_TITLE, fieldScore(term, p.detailWords, p.detailFlat) * W_DETAIL, aliasHit);
147
+ // AND semantics: a record missing any term is out, regardless of how well
148
+ // it matched the others. "red dranzer" returning everything with "dranzer"
149
+ // is the exact complaint that made search feel broken.
150
+ if (best === 0)
151
+ return 0;
152
+ total += best;
153
+ }
154
+ return total * typeWeight;
155
+ }
156
+ function facetsSatisfied(rec, required) {
157
+ if (required.length === 0)
158
+ return true;
159
+ const have = new Set(facetsOf(rec).map(([k, v]) => `${k}:${v}`));
160
+ return required.every((f) => have.has(f));
161
+ }
162
+ /**
163
+ * Search a prepared artifact.
164
+ *
165
+ * Returns a flat, score-ordered list. Grouping by type is the caller's job —
166
+ * the dropdown and the results page group differently, and a tool wants
167
+ * neither.
168
+ */
169
+ export function searchIndex(artifact, prepared, query, opts = {}) {
170
+ const terms = parseSearchTxtQuery(query);
171
+ /*
172
+ * 🛑 A query that normalises to nothing returns NOTHING, never everything.
173
+ * "!!!" and "—" have no terms, and treating that as "no filter" is how a
174
+ * punctuation search returns the whole catalogue AS SEARCH RESULTS — the
175
+ * bug A2 fixed on /api/products, and the one `plan.empty` exists for.
176
+ */
177
+ if (terms.length === 0)
178
+ return [];
179
+ const limit = opts.limit ?? DEFAULT_LIMIT;
180
+ const wantTypes = new Set(opts.types ?? []);
181
+ const facets = opts.facets ?? [];
182
+ const collect = (useTerms, aliasPass) => {
183
+ const hits = [];
184
+ for (const p of prepared) {
185
+ const type = artifact.types[p.rec[REC_TYPE]];
186
+ if (!type)
187
+ continue;
188
+ if (wantTypes.size > 0 && !wantTypes.has(type.key))
189
+ continue;
190
+ if (!facetsSatisfied(p.rec, facets))
191
+ continue;
192
+ const score = recordScore(p, useTerms, type.weight);
193
+ if (score === 0)
194
+ continue;
195
+ hits.push({
196
+ typeIdx: p.rec[REC_TYPE],
197
+ typeKey: type.key,
198
+ title: p.rec[REC_TITLE],
199
+ detail: p.rec[REC_DETAIL],
200
+ href: hrefFor(artifact, p.rec),
201
+ // An alias hit is a weaker signal than a direct one and must not
202
+ // outrank it when both are present in a later, wider query.
203
+ score: aliasPass ? score - S_ALIAS : score,
204
+ });
205
+ }
206
+ return hits;
207
+ };
208
+ /*
209
+ * ONE pass. The alias forms live on the prepared record (see
210
+ * `prepareIndex`), so there is nothing to retry with — an earlier draft had
211
+ * a second query-expansion pass here and it was both redundant and
212
+ * directionally wrong.
213
+ */
214
+ const hits = collect(terms, false);
215
+ hits.sort((a, b) => b.score - a.score || a.title.localeCompare(b.title));
216
+ /*
217
+ * 🛑 Dedupe by DESTINATION, not by key. Two types can legitimately resolve
218
+ * to the same page: `model` (a composition) and `category` (the model leaf)
219
+ * both render `/categories/{s}`, because a composition has no page of its
220
+ * own. Found running the first real build — 222 model records sit on top of
221
+ * 1,144 categories, so a bey name could return two rows that go to the same
222
+ * place, which reads as a duplicate-results bug rather than as two ways of
223
+ * finding one thing.
224
+ *
225
+ * Keeping the HIGHER-scoring one is what preserves the value of both: the
226
+ * composition's name is often the longer, more specific form ("Aero Knight
227
+ * MS (Aero Knight Metal Sky)" against the category's "Aero Knight MS"), so
228
+ * whichever actually matched the query is the one worth showing.
229
+ *
230
+ * After the sort, so "first seen" is "best scoring".
231
+ */
232
+ const seen = new Set();
233
+ const deduped = [];
234
+ for (const hit of hits) {
235
+ if (seen.has(hit.href))
236
+ continue;
237
+ seen.add(hit.href);
238
+ deduped.push(hit);
239
+ if (deduped.length >= limit)
240
+ break;
241
+ }
242
+ return deduped;
243
+ }
244
+ /**
245
+ * The named primitive the tools call.
246
+ *
247
+ * 🛑 `types` is a parameter from day one BECAUSE the tools exist. `/parts`
248
+ * wants parts, the price index wants category leaves, the authenticity
249
+ * typeahead wants canonical models — three consumers, three subsets. Adding
250
+ * the filter later would mean changing every call site that had already been
251
+ * written without it.
252
+ *
253
+ * 🛑 It must NOT be wired into `/tools/authenticity`'s VERDICT path. That
254
+ * engine's fuzzy matching is evidence — a near-miss fires a trademark-evasion
255
+ * warning — and this matcher's alias corpus is built from a counterfeit
256
+ * seller's own spellings. Feeding one into the other would silence the warning
257
+ * by construction. The typeahead may propose a canonical entity; the engine
258
+ * must still analyse what the user actually typed. Enforced by
259
+ * audit-entity-resolver-consumers R2.
260
+ */
261
+ export function resolveEntity(artifact, prepared, query, opts = {}) {
262
+ return searchIndex(artifact, prepared, query, opts);
263
+ }
package/dist/client.d.ts CHANGED
@@ -41,6 +41,8 @@ export { Tabs, TabsList, TabsTrigger, TabsContent } from "./ui/components/Tabs";
41
41
  export type { TabsProps, TabsListProps, TabsTriggerProps, TabsContentProps } from "./ui/components/Tabs";
42
42
  export { TabBarShell, TabBarButton, TabsNavSelect } from "./ui/components/TabBarShell";
43
43
  export type { TabBarShellProps, TabBarButtonProps, TabsNavSelectProps } from "./ui/components/TabBarShell";
44
+ export { OverflowRow } from "./ui/components/OverflowRow";
45
+ export type { OverflowRowProps, OverflowRowItem, OverflowRowDotTone, OverflowRowLinkProps } from "./ui/components/OverflowRow";
44
46
  export { SellerProductsView } from "./features/seller/components/SellerProductsView";
45
47
  export { SellerOrderDetailPanel } from "./features/seller/components/SellerOrdersView";
46
48
  export { SellerPayoutDetailContent } from "./features/seller/components/SellerPayoutsView";
@@ -264,7 +266,7 @@ export { buildEventEntryDetailFields } from "./features/events/components/event-
264
266
  export type { EntryFieldRow } from "./features/events/components/event-entry-detail-fields";
265
267
  export type { BidDetailViewer } from "./features/auctions/components/bid-detail-fields";
266
268
  export type { AuctionBidsTableProps, AuctionWithBids } from "./features/auctions/components/AuctionBidsTable";
267
- export { ProtectedRoute, AuthStatusPanel, ForgotPasswordView, LoginForm, RegisterForm, ResetPasswordView, VerifyEmailView } from "./features/auth/index";
269
+ export { ProtectedRoute, ForgotPasswordView, LoginForm, RegisterForm, ResetPasswordView, VerifyEmailView } from "./features/auth/index";
268
270
  export type { AuthGuardUser, ForgotPasswordViewProps, LoginFormProps, LoginFormValues, RegisterFormProps, RegisterFormValues, ResetPasswordViewProps, VerifyEmailViewProps, } from "./features/auth/index";
269
271
  export { useLogout, useLogin, useGoogleLogin, useLinkGoogleAccount, useRegister, useForgotPassword, useResetPassword, useVerifyEmail, useChangeEmail } from "./features/auth/index";
270
272
  export type { LoginCredentials, RegisterData, ForgotPasswordData, ResetPasswordData, VerifyEmailData, ChangeEmailData } from "./features/auth/index";
@@ -284,7 +286,6 @@ export { AddressBook, AddressCard, AddressForm } from "./features/account/index"
284
286
  export type { AddressCardAddress, AddressCardProps } from "./features/account/index";
285
287
  export { useProfile, useUpdateProfile } from "./features/account/index";
286
288
  export { updateProfileSchema } from "./features/account/index";
287
- export { CategoryProductsView } from "./features/categories/index";
288
289
  export type { CategoryItem } from "./features/categories/index";
289
290
  export { MediaImage } from "./features/media/index";
290
291
  export { StoreSidebar } from "./features/seller/components/SellerSidebar";
@@ -293,8 +294,8 @@ export { StoreProductsView, StoreAboutView } from "./features/stores/index";
293
294
  export type { StoreProductItem, StoreAboutViewProps, StoreDetail } from "./features/stores/index";
294
295
  export { SearchView } from "./features/search/index";
295
296
  export type { SearchViewProps } from "./features/search/index";
296
- export { UserSettingsView } from "./features/account/index";
297
- export type { UserSettingsViewProps, UserSettingsViewLabels } from "./features/account/index";
297
+ export { useSearchIndex, ensureSearchIndex } from "./features/search/hooks/useSearchIndex";
298
+ export type { SearchIndexState, SearchIndexStatus, LoadedSearchIndex, UseSearchIndexOptions, } from "./features/search/hooks/useSearchIndex";
298
299
  export { AdSlot } from "./features/homepage/components/AdSlot";
299
300
  export { useActiveAd } from "./features/homepage/hooks/useActiveAd";
300
301
  export type { ActiveAdRecord, ActiveAdCreative } from "./features/homepage/hooks/useActiveAd";
@@ -370,8 +371,8 @@ export type { SellerPayoutSettingsViewProps, SellerShippingViewProps, SellerRevi
370
371
  export { couponDraftToPayload } from "./features/seller/schemas/coupon-form";
371
372
  export type { SellerCouponPayload } from "./features/seller/schemas/coupon-form";
372
373
  export type { SellerAnalyticsSummary, SellerAnalyticsTopProduct } from "./features/seller/types/index";
373
- export { UserAccountHubView, UserOrdersView, UserBidsView, OrderDetailView, UserNotificationsView, UserReturnsView, UserSupportView, useNotifications } from "./features/account/index";
374
- export type { UserAccountHubViewProps, UserAccountHubViewLabels, UserOrdersViewProps, OrderDetailViewProps, OrderDetailViewLabels, UserNotificationsViewProps, UserNotificationsViewLabels, UserReturnsViewProps, UserSupportViewProps } from "./features/account/index";
374
+ export { UserAccountHubView, UserOrdersView, UserBidsView, OrderDetailView, UserReturnsView, useNotifications } from "./features/account/index";
375
+ export type { UserAccountHubViewProps, UserAccountHubViewLabels, UserOrdersViewProps, OrderDetailViewProps, OrderDetailViewLabels, UserReturnsViewProps } from "./features/account/index";
375
376
  export { useOrders, useOrder, OrdersList } from "./features/orders/index";
376
377
  export { OrderStatusTimeline } from "./features/orders/components/OrderStatusTimeline";
377
378
  export type { OrderStatusTimelineProps } from "./features/orders/components/OrderStatusTimeline";
@@ -407,7 +408,7 @@ export type { TrackArgs as TrackHistoryArgs } from "./features/history/hooks/use
407
408
  export { WISHLIST_MAX, HISTORY_MAX, CART_MAX_ITEMS, } from "./constants/limits";
408
409
  export { normalizeListingType, isAuctionListing, isPreOrderListing, isStandardListing, isPrizeDrawListing, isClassifiedListing, isDigitalCodeListing, isLiveListing, isArtListing, isStickersListing, } from "./features/products/utils/listing-type";
409
410
  export { isFinalSale, acceptsChangeOfMindReturns, } from "./features/products/constants/final-sale";
410
- export { isListingTypeEnabled, isCategoryTypeEnabled, enabledListingTypes, enabledCategoryTypes, ALL_LISTING_TYPES, } from "./_internal/shared/listing-types/feature-flags";
411
+ export { isListingTypeEnabled, isCategoryTypeEnabled, enabledListingTypes, enabledCategoryTypes, ALL_LISTING_TYPES, isListingType, } from "./_internal/shared/listing-types/feature-flags";
411
412
  export { actionTracker, setActionTrackerSink, resetActionTrackerSink, type ActionEvent, type ActionTrackerSink, } from "./_internal/shared/listing-types/action-tracker";
412
413
  export { cartRequiresShipping, cartIsDigitalOnly, cartIsChatOnly, } from "./_internal/shared/listing-types/cart-shipping";
413
414
  export { ACTIONS, action, act, canPerformAction, actionsForListingType, actionLabel, type ActionDef, type ActionKind, type ActionResource, type ActionTree, type ActionConfirmation, } from "./_internal/shared/actions/action-registry";