@open-mercato/core 0.9.1-develop.7474.1.51db10479d → 0.9.1-develop.7475.1.28ca93ed97

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 (597) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/catalog_price_history_entry/index.js +53 -0
  3. package/dist/generated/entities/catalog_price_history_entry/index.js.map +7 -0
  4. package/dist/generated/entities/customer_group_terms/index.js +2 -0
  5. package/dist/generated/entities/customer_group_terms/index.js.map +2 -2
  6. package/dist/generated/entities/ecommerce_store/index.js +33 -0
  7. package/dist/generated/entities/ecommerce_store/index.js.map +7 -0
  8. package/dist/generated/entities/ecommerce_store_channel_binding/index.js +29 -0
  9. package/dist/generated/entities/ecommerce_store_channel_binding/index.js.map +7 -0
  10. package/dist/generated/entities/ecommerce_store_domain_binding/index.js +23 -0
  11. package/dist/generated/entities/ecommerce_store_domain_binding/index.js.map +7 -0
  12. package/dist/generated/entities.ids.generated.js +8 -1
  13. package/dist/generated/entities.ids.generated.js.map +2 -2
  14. package/dist/generated/entity-fields-registry.js +72 -0
  15. package/dist/generated/entity-fields-registry.js.map +2 -2
  16. package/dist/helpers/integration/customerGroupsFixtures.js.map +2 -2
  17. package/dist/modules/catalog/acl.js +8 -1
  18. package/dist/modules/catalog/acl.js.map +2 -2
  19. package/dist/modules/catalog/api/config/omnibus/route.js +184 -0
  20. package/dist/modules/catalog/api/config/omnibus/route.js.map +7 -0
  21. package/dist/modules/catalog/api/prices/history/route.js +131 -0
  22. package/dist/modules/catalog/api/prices/history/route.js.map +7 -0
  23. package/dist/modules/catalog/api/prices/omnibus-preview/route.js +184 -0
  24. package/dist/modules/catalog/api/prices/omnibus-preview/route.js.map +7 -0
  25. package/dist/modules/catalog/api/products/route.js +54 -245
  26. package/dist/modules/catalog/api/products/route.js.map +3 -3
  27. package/dist/modules/catalog/api/tags/route.js +6 -0
  28. package/dist/modules/catalog/api/tags/route.js.map +2 -2
  29. package/dist/modules/catalog/backend/config/catalog/page.js +3 -1
  30. package/dist/modules/catalog/backend/config/catalog/page.js.map +2 -2
  31. package/dist/modules/catalog/cli.js +80 -2
  32. package/dist/modules/catalog/cli.js.map +2 -2
  33. package/dist/modules/catalog/commands/categories.js +51 -2
  34. package/dist/modules/catalog/commands/categories.js.map +2 -2
  35. package/dist/modules/catalog/commands/prices.js +43 -1
  36. package/dist/modules/catalog/commands/prices.js.map +2 -2
  37. package/dist/modules/catalog/commands/products.js +71 -0
  38. package/dist/modules/catalog/commands/products.js.map +2 -2
  39. package/dist/modules/catalog/commands/variants.js +7 -0
  40. package/dist/modules/catalog/commands/variants.js.map +2 -2
  41. package/dist/modules/catalog/components/OmnibusSettings.js +703 -0
  42. package/dist/modules/catalog/components/OmnibusSettings.js.map +7 -0
  43. package/dist/modules/catalog/components/PriceEditorOmnibusRow.js +152 -0
  44. package/dist/modules/catalog/components/PriceEditorOmnibusRow.js.map +7 -0
  45. package/dist/modules/catalog/components/lookupSources.js +31 -0
  46. package/dist/modules/catalog/components/lookupSources.js.map +7 -0
  47. package/dist/modules/catalog/components/prices/PriceScopeSelectors.js +8 -2
  48. package/dist/modules/catalog/components/prices/PriceScopeSelectors.js.map +2 -2
  49. package/dist/modules/catalog/components/products/VariantBuilder.js +11 -1
  50. package/dist/modules/catalog/components/products/VariantBuilder.js.map +2 -2
  51. package/dist/modules/catalog/data/entities.js +122 -1
  52. package/dist/modules/catalog/data/entities.js.map +2 -2
  53. package/dist/modules/catalog/data/validators.js +78 -0
  54. package/dist/modules/catalog/data/validators.js.map +2 -2
  55. package/dist/modules/catalog/di.js +18 -0
  56. package/dist/modules/catalog/di.js.map +2 -2
  57. package/dist/modules/catalog/lib/omnibus.js +285 -0
  58. package/dist/modules/catalog/lib/omnibus.js.map +7 -0
  59. package/dist/modules/catalog/lib/omnibusBackfill.js +146 -0
  60. package/dist/modules/catalog/lib/omnibusBackfill.js.map +7 -0
  61. package/dist/modules/catalog/lib/omnibusCache.js +89 -0
  62. package/dist/modules/catalog/lib/omnibusCache.js.map +7 -0
  63. package/dist/modules/catalog/lib/omnibusConfig.js +64 -0
  64. package/dist/modules/catalog/lib/omnibusConfig.js.map +7 -0
  65. package/dist/modules/catalog/lib/omnibusHistoryQueries.js +191 -0
  66. package/dist/modules/catalog/lib/omnibusHistoryQueries.js.map +7 -0
  67. package/dist/modules/catalog/lib/omnibusPresentedEntry.js +73 -0
  68. package/dist/modules/catalog/lib/omnibusPresentedEntry.js.map +7 -0
  69. package/dist/modules/catalog/lib/omnibusProductListEnrichment.js +94 -0
  70. package/dist/modules/catalog/lib/omnibusProductListEnrichment.js.map +7 -0
  71. package/dist/modules/catalog/lib/omnibusTypes.js +115 -0
  72. package/dist/modules/catalog/lib/omnibusTypes.js.map +7 -0
  73. package/dist/modules/catalog/lib/optionSchemaTranslations.js +55 -0
  74. package/dist/modules/catalog/lib/optionSchemaTranslations.js.map +7 -0
  75. package/dist/modules/catalog/lib/priceHistoryQuery.js +103 -0
  76. package/dist/modules/catalog/lib/priceHistoryQuery.js.map +7 -0
  77. package/dist/modules/catalog/lib/pricing.js +26 -2
  78. package/dist/modules/catalog/lib/pricing.js.map +2 -2
  79. package/dist/modules/catalog/lib/productFilters.js +273 -0
  80. package/dist/modules/catalog/lib/productFilters.js.map +7 -0
  81. package/dist/modules/catalog/lib/productScopeKeys.js +105 -0
  82. package/dist/modules/catalog/lib/productScopeKeys.js.map +7 -0
  83. package/dist/modules/catalog/lib/productScopeReindex.js +73 -0
  84. package/dist/modules/catalog/lib/productScopeReindex.js.map +7 -0
  85. package/dist/modules/catalog/migrations/Migration20261005105352_catalog.js +39 -0
  86. package/dist/modules/catalog/migrations/Migration20261005105352_catalog.js.map +7 -0
  87. package/dist/modules/catalog/migrations/Migration20261005150824_catalog.js +39 -0
  88. package/dist/modules/catalog/migrations/Migration20261005150824_catalog.js.map +7 -0
  89. package/dist/modules/catalog/services/catalogOmnibusService.js +480 -0
  90. package/dist/modules/catalog/services/catalogOmnibusService.js.map +7 -0
  91. package/dist/modules/catalog/setup.js +3 -1
  92. package/dist/modules/catalog/setup.js.map +2 -2
  93. package/dist/modules/catalog/subscribers/product-scope-keys-category-deleted.js +16 -0
  94. package/dist/modules/catalog/subscribers/product-scope-keys-category-deleted.js.map +7 -0
  95. package/dist/modules/catalog/subscribers/product-scope-keys-category-updated.js +17 -0
  96. package/dist/modules/catalog/subscribers/product-scope-keys-category-updated.js.map +7 -0
  97. package/dist/modules/catalog/translations.js +10 -0
  98. package/dist/modules/catalog/translations.js.map +2 -2
  99. package/dist/modules/configs/lib/upgrade-actions.js +28 -0
  100. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  101. package/dist/modules/customer_groups/api/customer-groups/[id]/terms/route.js +5 -0
  102. package/dist/modules/customer_groups/api/customer-groups/[id]/terms/route.js.map +2 -2
  103. package/dist/modules/customer_groups/components/CustomerGroupTermsSection.js +111 -3
  104. package/dist/modules/customer_groups/components/CustomerGroupTermsSection.js.map +2 -2
  105. package/dist/modules/customer_groups/components/customerGroupAssortmentScope.js +43 -0
  106. package/dist/modules/customer_groups/components/customerGroupAssortmentScope.js.map +7 -0
  107. package/dist/modules/customer_groups/data/entities.js +3 -0
  108. package/dist/modules/customer_groups/data/entities.js.map +2 -2
  109. package/dist/modules/customer_groups/data/validators.js +9 -0
  110. package/dist/modules/customer_groups/data/validators.js.map +2 -2
  111. package/dist/modules/customer_groups/migrations/Migration20261005110250_customer_groups.js +17 -0
  112. package/dist/modules/customer_groups/migrations/Migration20261005110250_customer_groups.js.map +7 -0
  113. package/dist/modules/customer_groups/services/customerGroupsService.js +62 -15
  114. package/dist/modules/customer_groups/services/customerGroupsService.js.map +2 -2
  115. package/dist/modules/ecommerce/acl.js +13 -0
  116. package/dist/modules/ecommerce/acl.js.map +7 -0
  117. package/dist/modules/ecommerce/api/domain-mappings/route.js +72 -0
  118. package/dist/modules/ecommerce/api/domain-mappings/route.js.map +7 -0
  119. package/dist/modules/ecommerce/api/openapi.js +27 -0
  120. package/dist/modules/ecommerce/api/openapi.js.map +7 -0
  121. package/dist/modules/ecommerce/api/store-channel-bindings/[id]/assortment-count/route.js +109 -0
  122. package/dist/modules/ecommerce/api/store-channel-bindings/[id]/assortment-count/route.js.map +7 -0
  123. package/dist/modules/ecommerce/api/store-channel-bindings/crud.js +265 -0
  124. package/dist/modules/ecommerce/api/store-channel-bindings/crud.js.map +7 -0
  125. package/dist/modules/ecommerce/api/store-channel-bindings/route.js +67 -0
  126. package/dist/modules/ecommerce/api/store-channel-bindings/route.js.map +7 -0
  127. package/dist/modules/ecommerce/api/store-domain-bindings/crud.js +296 -0
  128. package/dist/modules/ecommerce/api/store-domain-bindings/crud.js.map +7 -0
  129. package/dist/modules/ecommerce/api/store-domain-bindings/route.js +73 -0
  130. package/dist/modules/ecommerce/api/store-domain-bindings/route.js.map +7 -0
  131. package/dist/modules/ecommerce/api/storefront/categories/[slug]/route.js +87 -0
  132. package/dist/modules/ecommerce/api/storefront/categories/[slug]/route.js.map +7 -0
  133. package/dist/modules/ecommerce/api/storefront/categories/openapiSchemas.js +50 -0
  134. package/dist/modules/ecommerce/api/storefront/categories/openapiSchemas.js.map +7 -0
  135. package/dist/modules/ecommerce/api/storefront/categories/route.js +75 -0
  136. package/dist/modules/ecommerce/api/storefront/categories/route.js.map +7 -0
  137. package/dist/modules/ecommerce/api/storefront/context/route.js +163 -0
  138. package/dist/modules/ecommerce/api/storefront/context/route.js.map +7 -0
  139. package/dist/modules/ecommerce/api/storefront/products/[idOrHandle]/route.js +87 -0
  140. package/dist/modules/ecommerce/api/storefront/products/[idOrHandle]/route.js.map +7 -0
  141. package/dist/modules/ecommerce/api/storefront/products/openapiSchemas.js +177 -0
  142. package/dist/modules/ecommerce/api/storefront/products/openapiSchemas.js.map +7 -0
  143. package/dist/modules/ecommerce/api/storefront/products/route.js +78 -0
  144. package/dist/modules/ecommerce/api/storefront/products/route.js.map +7 -0
  145. package/dist/modules/ecommerce/api/storefront/search/suggest/openapiSchemas.js +25 -0
  146. package/dist/modules/ecommerce/api/storefront/search/suggest/openapiSchemas.js.map +7 -0
  147. package/dist/modules/ecommerce/api/storefront/search/suggest/route.js +75 -0
  148. package/dist/modules/ecommerce/api/storefront/search/suggest/route.js.map +7 -0
  149. package/dist/modules/ecommerce/api/storefront/storefrontRouteSupport.js +58 -0
  150. package/dist/modules/ecommerce/api/storefront/storefrontRouteSupport.js.map +7 -0
  151. package/dist/modules/ecommerce/api/stores/[id]/branding/route.js +183 -0
  152. package/dist/modules/ecommerce/api/stores/[id]/branding/route.js.map +7 -0
  153. package/dist/modules/ecommerce/api/stores/[id]/preview-branding/route.js +92 -0
  154. package/dist/modules/ecommerce/api/stores/[id]/preview-branding/route.js.map +7 -0
  155. package/dist/modules/ecommerce/api/stores/crud.js +401 -0
  156. package/dist/modules/ecommerce/api/stores/crud.js.map +7 -0
  157. package/dist/modules/ecommerce/api/stores/route.js +64 -0
  158. package/dist/modules/ecommerce/api/stores/route.js.map +7 -0
  159. package/dist/modules/ecommerce/backend/config/ecommerce/[id]/page.js +9 -0
  160. package/dist/modules/ecommerce/backend/config/ecommerce/[id]/page.js.map +7 -0
  161. package/dist/modules/ecommerce/backend/config/ecommerce/[id]/page.meta.js +16 -0
  162. package/dist/modules/ecommerce/backend/config/ecommerce/[id]/page.meta.js.map +7 -0
  163. package/dist/modules/ecommerce/backend/config/ecommerce/page.js +9 -0
  164. package/dist/modules/ecommerce/backend/config/ecommerce/page.js.map +7 -0
  165. package/dist/modules/ecommerce/backend/config/ecommerce/page.meta.js +16 -0
  166. package/dist/modules/ecommerce/backend/config/ecommerce/page.meta.js.map +7 -0
  167. package/dist/modules/ecommerce/commands/stores.js +110 -0
  168. package/dist/modules/ecommerce/commands/stores.js.map +7 -0
  169. package/dist/modules/ecommerce/components/ChannelAssortmentCount.js +90 -0
  170. package/dist/modules/ecommerce/components/ChannelAssortmentCount.js.map +7 -0
  171. package/dist/modules/ecommerce/components/ChannelBindingFormSections.js +33 -0
  172. package/dist/modules/ecommerce/components/ChannelBindingFormSections.js.map +7 -0
  173. package/dist/modules/ecommerce/components/ChannelLookupPicker.js +11 -0
  174. package/dist/modules/ecommerce/components/ChannelLookupPicker.js.map +7 -0
  175. package/dist/modules/ecommerce/components/DomainStatusWarning.js +24 -0
  176. package/dist/modules/ecommerce/components/DomainStatusWarning.js.map +7 -0
  177. package/dist/modules/ecommerce/components/StoreAvailabilityDefaultsSection.js +190 -0
  178. package/dist/modules/ecommerce/components/StoreAvailabilityDefaultsSection.js.map +7 -0
  179. package/dist/modules/ecommerce/components/StoreBrandingControls.js +67 -0
  180. package/dist/modules/ecommerce/components/StoreBrandingControls.js.map +7 -0
  181. package/dist/modules/ecommerce/components/StoreBrandingPreview.js +69 -0
  182. package/dist/modules/ecommerce/components/StoreBrandingPreview.js.map +7 -0
  183. package/dist/modules/ecommerce/components/StoreBrandingTab.js +218 -0
  184. package/dist/modules/ecommerce/components/StoreBrandingTab.js.map +7 -0
  185. package/dist/modules/ecommerce/components/StoreChannelBindingDialog.js +270 -0
  186. package/dist/modules/ecommerce/components/StoreChannelBindingDialog.js.map +7 -0
  187. package/dist/modules/ecommerce/components/StoreChannelsTab.js +313 -0
  188. package/dist/modules/ecommerce/components/StoreChannelsTab.js.map +7 -0
  189. package/dist/modules/ecommerce/components/StoreCreateDialog.js +164 -0
  190. package/dist/modules/ecommerce/components/StoreCreateDialog.js.map +7 -0
  191. package/dist/modules/ecommerce/components/StoreDomainBindingDialog.js +162 -0
  192. package/dist/modules/ecommerce/components/StoreDomainBindingDialog.js.map +7 -0
  193. package/dist/modules/ecommerce/components/StoreDomainsTab.js +357 -0
  194. package/dist/modules/ecommerce/components/StoreDomainsTab.js.map +7 -0
  195. package/dist/modules/ecommerce/components/StoreEditPage.js +155 -0
  196. package/dist/modules/ecommerce/components/StoreEditPage.js.map +7 -0
  197. package/dist/modules/ecommerce/components/StoreGeneralTab.js +167 -0
  198. package/dist/modules/ecommerce/components/StoreGeneralTab.js.map +7 -0
  199. package/dist/modules/ecommerce/components/StoreListPage.js +290 -0
  200. package/dist/modules/ecommerce/components/StoreListPage.js.map +7 -0
  201. package/dist/modules/ecommerce/components/StoreSeoTab.js +132 -0
  202. package/dist/modules/ecommerce/components/StoreSeoTab.js.map +7 -0
  203. package/dist/modules/ecommerce/components/StoreStatusBadge.js +20 -0
  204. package/dist/modules/ecommerce/components/StoreStatusBadge.js.map +7 -0
  205. package/dist/modules/ecommerce/components/channelLookups.js +28 -0
  206. package/dist/modules/ecommerce/components/channelLookups.js.map +7 -0
  207. package/dist/modules/ecommerce/components/storeAdmin.js +41 -0
  208. package/dist/modules/ecommerce/components/storeAdmin.js.map +7 -0
  209. package/dist/modules/ecommerce/components/storeBrandingForm.js +197 -0
  210. package/dist/modules/ecommerce/components/storeBrandingForm.js.map +7 -0
  211. package/dist/modules/ecommerce/components/storeChannels.js +140 -0
  212. package/dist/modules/ecommerce/components/storeChannels.js.map +7 -0
  213. package/dist/modules/ecommerce/components/storeDomains.js +167 -0
  214. package/dist/modules/ecommerce/components/storeDomains.js.map +7 -0
  215. package/dist/modules/ecommerce/components/storeEditTabs.js +62 -0
  216. package/dist/modules/ecommerce/components/storeEditTabs.js.map +7 -0
  217. package/dist/modules/ecommerce/components/storeGeneral.js +95 -0
  218. package/dist/modules/ecommerce/components/storeGeneral.js.map +7 -0
  219. package/dist/modules/ecommerce/components/storeSeo.js +69 -0
  220. package/dist/modules/ecommerce/components/storeSeo.js.map +7 -0
  221. package/dist/modules/ecommerce/components/useChannelAssortmentCount.js +45 -0
  222. package/dist/modules/ecommerce/components/useChannelAssortmentCount.js.map +7 -0
  223. package/dist/modules/ecommerce/components/useStoreAccess.js +28 -0
  224. package/dist/modules/ecommerce/components/useStoreAccess.js.map +7 -0
  225. package/dist/modules/ecommerce/data/enrichers.js +157 -0
  226. package/dist/modules/ecommerce/data/enrichers.js.map +7 -0
  227. package/dist/modules/ecommerce/data/entities.js +197 -0
  228. package/dist/modules/ecommerce/data/entities.js.map +7 -0
  229. package/dist/modules/ecommerce/data/validators.js +406 -0
  230. package/dist/modules/ecommerce/data/validators.js.map +7 -0
  231. package/dist/modules/ecommerce/di.js +11 -0
  232. package/dist/modules/ecommerce/di.js.map +7 -0
  233. package/dist/modules/ecommerce/events.js +27 -0
  234. package/dist/modules/ecommerce/events.js.map +7 -0
  235. package/dist/modules/ecommerce/index.js +16 -0
  236. package/dist/modules/ecommerce/index.js.map +7 -0
  237. package/dist/modules/ecommerce/lib/assortmentCount.js +112 -0
  238. package/dist/modules/ecommerce/lib/assortmentCount.js.map +7 -0
  239. package/dist/modules/ecommerce/lib/brandingStyles.js +184 -0
  240. package/dist/modules/ecommerce/lib/brandingStyles.js.map +7 -0
  241. package/dist/modules/ecommerce/lib/buyerContext.js +284 -0
  242. package/dist/modules/ecommerce/lib/buyerContext.js.map +7 -0
  243. package/dist/modules/ecommerce/lib/cacheInvalidation.js +186 -0
  244. package/dist/modules/ecommerce/lib/cacheInvalidation.js.map +7 -0
  245. package/dist/modules/ecommerce/lib/cacheKeys.js +236 -0
  246. package/dist/modules/ecommerce/lib/cacheKeys.js.map +7 -0
  247. package/dist/modules/ecommerce/lib/createConflictRecheck.js +29 -0
  248. package/dist/modules/ecommerce/lib/createConflictRecheck.js.map +7 -0
  249. package/dist/modules/ecommerce/lib/crudEvents.js +94 -0
  250. package/dist/modules/ecommerce/lib/crudEvents.js.map +7 -0
  251. package/dist/modules/ecommerce/lib/crudSupport.js +64 -0
  252. package/dist/modules/ecommerce/lib/crudSupport.js.map +7 -0
  253. package/dist/modules/ecommerce/lib/domainBindingRebind.js +99 -0
  254. package/dist/modules/ecommerce/lib/domainBindingRebind.js.map +7 -0
  255. package/dist/modules/ecommerce/lib/domainMappingSummaries.js +39 -0
  256. package/dist/modules/ecommerce/lib/domainMappingSummaries.js.map +7 -0
  257. package/dist/modules/ecommerce/lib/exclusiveFlag.js +57 -0
  258. package/dist/modules/ecommerce/lib/exclusiveFlag.js.map +7 -0
  259. package/dist/modules/ecommerce/lib/references.js +70 -0
  260. package/dist/modules/ecommerce/lib/references.js.map +7 -0
  261. package/dist/modules/ecommerce/lib/seedDraftStore.js +99 -0
  262. package/dist/modules/ecommerce/lib/seedDraftStore.js.map +7 -0
  263. package/dist/modules/ecommerce/lib/storeBindingCascade.js +109 -0
  264. package/dist/modules/ecommerce/lib/storeBindingCascade.js.map +7 -0
  265. package/dist/modules/ecommerce/lib/storeBranding.js +40 -0
  266. package/dist/modules/ecommerce/lib/storeBranding.js.map +7 -0
  267. package/dist/modules/ecommerce/lib/storeBrandingRoute.js +76 -0
  268. package/dist/modules/ecommerce/lib/storeBrandingRoute.js.map +7 -0
  269. package/dist/modules/ecommerce/lib/storeContext.js +393 -0
  270. package/dist/modules/ecommerce/lib/storeContext.js.map +7 -0
  271. package/dist/modules/ecommerce/lib/storeContextService.js +43 -0
  272. package/dist/modules/ecommerce/lib/storeContextService.js.map +7 -0
  273. package/dist/modules/ecommerce/lib/storeLocale.js +60 -0
  274. package/dist/modules/ecommerce/lib/storeLocale.js.map +7 -0
  275. package/dist/modules/ecommerce/lib/storeNotifications.js +41 -0
  276. package/dist/modules/ecommerce/lib/storeNotifications.js.map +7 -0
  277. package/dist/modules/ecommerce/lib/storefrontCatalogSupport.js +248 -0
  278. package/dist/modules/ecommerce/lib/storefrontCatalogSupport.js.map +7 -0
  279. package/dist/modules/ecommerce/lib/storefrontCategories.js +241 -0
  280. package/dist/modules/ecommerce/lib/storefrontCategories.js.map +7 -0
  281. package/dist/modules/ecommerce/lib/storefrontCategoryCache.js +71 -0
  282. package/dist/modules/ecommerce/lib/storefrontCategoryCache.js.map +7 -0
  283. package/dist/modules/ecommerce/lib/storefrontDetail.js +447 -0
  284. package/dist/modules/ecommerce/lib/storefrontDetail.js.map +7 -0
  285. package/dist/modules/ecommerce/lib/storefrontFacets.js +441 -0
  286. package/dist/modules/ecommerce/lib/storefrontFacets.js.map +7 -0
  287. package/dist/modules/ecommerce/lib/storefrontOptionFilter.js +15 -0
  288. package/dist/modules/ecommerce/lib/storefrontOptionFilter.js.map +7 -0
  289. package/dist/modules/ecommerce/lib/storefrontPricing.js +393 -0
  290. package/dist/modules/ecommerce/lib/storefrontPricing.js.map +7 -0
  291. package/dist/modules/ecommerce/lib/storefrontProductCache.js +90 -0
  292. package/dist/modules/ecommerce/lib/storefrontProductCache.js.map +7 -0
  293. package/dist/modules/ecommerce/lib/storefrontProductScope.js +107 -0
  294. package/dist/modules/ecommerce/lib/storefrontProductScope.js.map +7 -0
  295. package/dist/modules/ecommerce/lib/storefrontProducts.js +670 -0
  296. package/dist/modules/ecommerce/lib/storefrontProducts.js.map +7 -0
  297. package/dist/modules/ecommerce/lib/storefrontQuery.js +156 -0
  298. package/dist/modules/ecommerce/lib/storefrontQuery.js.map +7 -0
  299. package/dist/modules/ecommerce/lib/storefrontRateLimit.js +99 -0
  300. package/dist/modules/ecommerce/lib/storefrontRateLimit.js.map +7 -0
  301. package/dist/modules/ecommerce/lib/storefrontSearch.js +303 -0
  302. package/dist/modules/ecommerce/lib/storefrontSearch.js.map +7 -0
  303. package/dist/modules/ecommerce/lib/storefrontSearchCache.js +35 -0
  304. package/dist/modules/ecommerce/lib/storefrontSearchCache.js.map +7 -0
  305. package/dist/modules/ecommerce/lib/subscriberSupport.js +33 -0
  306. package/dist/modules/ecommerce/lib/subscriberSupport.js.map +7 -0
  307. package/dist/modules/ecommerce/lib/types.js +1 -0
  308. package/dist/modules/ecommerce/lib/types.js.map +7 -0
  309. package/dist/modules/ecommerce/migrations/Migration20261005113233_ecommerce.js +32 -0
  310. package/dist/modules/ecommerce/migrations/Migration20261005113233_ecommerce.js.map +7 -0
  311. package/dist/modules/ecommerce/migrations/Migration20261006112733_ecommerce.js +17 -0
  312. package/dist/modules/ecommerce/migrations/Migration20261006112733_ecommerce.js.map +7 -0
  313. package/dist/modules/ecommerce/notifications.client.js +47 -0
  314. package/dist/modules/ecommerce/notifications.client.js.map +7 -0
  315. package/dist/modules/ecommerce/notifications.js +48 -0
  316. package/dist/modules/ecommerce/notifications.js.map +7 -0
  317. package/dist/modules/ecommerce/search.js +83 -0
  318. package/dist/modules/ecommerce/search.js.map +7 -0
  319. package/dist/modules/ecommerce/setup.js +17 -0
  320. package/dist/modules/ecommerce/setup.js.map +7 -0
  321. package/dist/modules/ecommerce/subscribers/assortment-empty-notifications.js +14 -0
  322. package/dist/modules/ecommerce/subscribers/assortment-empty-notifications.js.map +7 -0
  323. package/dist/modules/ecommerce/subscribers/availability-policy-cache-invalidation.js +14 -0
  324. package/dist/modules/ecommerce/subscribers/availability-policy-cache-invalidation.js.map +7 -0
  325. package/dist/modules/ecommerce/subscribers/catalog-category-cache-invalidation.js +14 -0
  326. package/dist/modules/ecommerce/subscribers/catalog-category-cache-invalidation.js.map +7 -0
  327. package/dist/modules/ecommerce/subscribers/catalog-price-cache-invalidation.js +14 -0
  328. package/dist/modules/ecommerce/subscribers/catalog-price-cache-invalidation.js.map +7 -0
  329. package/dist/modules/ecommerce/subscribers/catalog-product-cache-invalidation.js +14 -0
  330. package/dist/modules/ecommerce/subscribers/catalog-product-cache-invalidation.js.map +7 -0
  331. package/dist/modules/ecommerce/subscribers/catalog-variant-cache-invalidation.js +14 -0
  332. package/dist/modules/ecommerce/subscribers/catalog-variant-cache-invalidation.js.map +7 -0
  333. package/dist/modules/ecommerce/subscribers/customer-group-cache-invalidation.js +14 -0
  334. package/dist/modules/ecommerce/subscribers/customer-group-cache-invalidation.js.map +7 -0
  335. package/dist/modules/ecommerce/subscribers/customer-group-membership-cache-invalidation.js +14 -0
  336. package/dist/modules/ecommerce/subscribers/customer-group-membership-cache-invalidation.js.map +7 -0
  337. package/dist/modules/ecommerce/subscribers/customer-group-terms-cache-invalidation.js +14 -0
  338. package/dist/modules/ecommerce/subscribers/customer-group-terms-cache-invalidation.js.map +7 -0
  339. package/dist/modules/ecommerce/subscribers/customer-user-deleted-cache-invalidation.js +14 -0
  340. package/dist/modules/ecommerce/subscribers/customer-user-deleted-cache-invalidation.js.map +7 -0
  341. package/dist/modules/ecommerce/subscribers/customer-user-updated-cache-invalidation.js +14 -0
  342. package/dist/modules/ecommerce/subscribers/customer-user-updated-cache-invalidation.js.map +7 -0
  343. package/dist/modules/ecommerce/subscribers/domain-binding-rebind.js +16 -0
  344. package/dist/modules/ecommerce/subscribers/domain-binding-rebind.js.map +7 -0
  345. package/dist/modules/ecommerce/subscribers/domain-mapping-cache-invalidation.js +14 -0
  346. package/dist/modules/ecommerce/subscribers/domain-mapping-cache-invalidation.js.map +7 -0
  347. package/dist/modules/ecommerce/subscribers/store-cache-invalidation.js +14 -0
  348. package/dist/modules/ecommerce/subscribers/store-cache-invalidation.js.map +7 -0
  349. package/dist/modules/ecommerce/subscribers/store-channel-binding-cache-invalidation.js +14 -0
  350. package/dist/modules/ecommerce/subscribers/store-channel-binding-cache-invalidation.js.map +7 -0
  351. package/dist/modules/ecommerce/subscribers/store-domain-binding-cache-invalidation.js +14 -0
  352. package/dist/modules/ecommerce/subscribers/store-domain-binding-cache-invalidation.js.map +7 -0
  353. package/dist/modules/ecommerce/subscribers/store-notifications.js +14 -0
  354. package/dist/modules/ecommerce/subscribers/store-notifications.js.map +7 -0
  355. package/dist/modules/query_index/lib/batch.js +23 -9
  356. package/dist/modules/query_index/lib/batch.js.map +2 -2
  357. package/dist/modules/query_index/lib/doc-enrichers.js +212 -0
  358. package/dist/modules/query_index/lib/doc-enrichers.js.map +7 -0
  359. package/dist/modules/query_index/lib/document.js +2 -0
  360. package/dist/modules/query_index/lib/document.js.map +2 -2
  361. package/dist/modules/query_index/lib/engine.js +68 -1
  362. package/dist/modules/query_index/lib/engine.js.map +2 -2
  363. package/dist/modules/query_index/lib/indexer.js +7 -0
  364. package/dist/modules/query_index/lib/indexer.js.map +2 -2
  365. package/dist/modules/query_index/lib/search-tokens.js +2 -0
  366. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  367. package/dist/modules/query_index/migrations/Migration20261005201500_query_index.js +17 -0
  368. package/dist/modules/query_index/migrations/Migration20261005201500_query_index.js.map +7 -0
  369. package/dist/modules/translations/components/TranslationManager.js +3 -3
  370. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  371. package/dist/modules/translations/data/validators.js +1 -1
  372. package/dist/modules/translations/data/validators.js.map +1 -1
  373. package/dist/modules/translations/lib/batch.js +21 -1
  374. package/dist/modules/translations/lib/batch.js.map +2 -2
  375. package/dist/modules/translations/lib/helpers.js +3 -0
  376. package/dist/modules/translations/lib/helpers.js.map +2 -2
  377. package/dist/modules/translations/lib/resolve-field-list.js +14 -2
  378. package/dist/modules/translations/lib/resolve-field-list.js.map +2 -2
  379. package/generated/entities/catalog_price_history_entry/index.ts +25 -0
  380. package/generated/entities/customer_group_terms/index.ts +1 -0
  381. package/generated/entities/ecommerce_store/index.ts +15 -0
  382. package/generated/entities/ecommerce_store_channel_binding/index.ts +13 -0
  383. package/generated/entities/ecommerce_store_domain_binding/index.ts +10 -0
  384. package/generated/entities.ids.generated.ts +8 -1
  385. package/generated/entity-fields-registry.ts +72 -0
  386. package/package.json +7 -7
  387. package/src/helpers/integration/customerGroupsFixtures.ts +2 -0
  388. package/src/modules/auth/i18n/de.json +8 -0
  389. package/src/modules/auth/i18n/en.json +8 -0
  390. package/src/modules/auth/i18n/es.json +8 -0
  391. package/src/modules/auth/i18n/ko.json +8 -0
  392. package/src/modules/auth/i18n/pl.json +8 -0
  393. package/src/modules/catalog/AGENTS.md +5 -2
  394. package/src/modules/catalog/acl.ts +7 -0
  395. package/src/modules/catalog/api/config/omnibus/route.ts +204 -0
  396. package/src/modules/catalog/api/prices/history/route.ts +139 -0
  397. package/src/modules/catalog/api/prices/omnibus-preview/route.ts +202 -0
  398. package/src/modules/catalog/api/products/route.ts +53 -308
  399. package/src/modules/catalog/api/tags/route.ts +6 -0
  400. package/src/modules/catalog/backend/config/catalog/page.tsx +2 -0
  401. package/src/modules/catalog/cli.ts +84 -1
  402. package/src/modules/catalog/commands/categories.ts +54 -2
  403. package/src/modules/catalog/commands/prices.ts +43 -1
  404. package/src/modules/catalog/commands/products.ts +84 -1
  405. package/src/modules/catalog/commands/variants.ts +7 -0
  406. package/src/modules/catalog/components/OmnibusSettings.tsx +832 -0
  407. package/src/modules/catalog/components/PriceEditorOmnibusRow.tsx +219 -0
  408. package/src/modules/catalog/components/lookupSources.ts +29 -0
  409. package/src/modules/catalog/components/prices/PriceScopeSelectors.tsx +9 -0
  410. package/src/modules/catalog/components/products/VariantBuilder.tsx +9 -0
  411. package/src/modules/catalog/data/entities.ts +123 -1
  412. package/src/modules/catalog/data/validators.ts +118 -0
  413. package/src/modules/catalog/di.ts +23 -0
  414. package/src/modules/catalog/i18n/de.json +77 -0
  415. package/src/modules/catalog/i18n/en.json +77 -0
  416. package/src/modules/catalog/i18n/es.json +77 -0
  417. package/src/modules/catalog/i18n/ko.json +77 -0
  418. package/src/modules/catalog/i18n/pl.json +77 -0
  419. package/src/modules/catalog/lib/omnibus.ts +406 -0
  420. package/src/modules/catalog/lib/omnibusBackfill.ts +198 -0
  421. package/src/modules/catalog/lib/omnibusCache.ts +111 -0
  422. package/src/modules/catalog/lib/omnibusConfig.ts +73 -0
  423. package/src/modules/catalog/lib/omnibusHistoryQueries.ts +248 -0
  424. package/src/modules/catalog/lib/omnibusPresentedEntry.ts +76 -0
  425. package/src/modules/catalog/lib/omnibusProductListEnrichment.ts +125 -0
  426. package/src/modules/catalog/lib/omnibusTypes.ts +202 -0
  427. package/src/modules/catalog/lib/optionSchemaTranslations.ts +55 -0
  428. package/src/modules/catalog/lib/priceHistoryQuery.ts +155 -0
  429. package/src/modules/catalog/lib/pricing.ts +42 -4
  430. package/src/modules/catalog/lib/productFilters.ts +349 -0
  431. package/src/modules/catalog/lib/productScopeKeys.ts +162 -0
  432. package/src/modules/catalog/lib/productScopeReindex.ts +139 -0
  433. package/src/modules/catalog/migrations/.snapshot-open-mercato.json +572 -0
  434. package/src/modules/catalog/migrations/Migration20261005105352_catalog.ts +39 -0
  435. package/src/modules/catalog/migrations/Migration20261005150824_catalog.ts +39 -0
  436. package/src/modules/catalog/services/catalogOmnibusService.ts +642 -0
  437. package/src/modules/catalog/setup.ts +2 -0
  438. package/src/modules/catalog/subscribers/product-scope-keys-category-deleted.ts +18 -0
  439. package/src/modules/catalog/subscribers/product-scope-keys-category-updated.ts +19 -0
  440. package/src/modules/catalog/translations.ts +12 -0
  441. package/src/modules/configs/i18n/de.json +5 -1
  442. package/src/modules/configs/i18n/en.json +5 -1
  443. package/src/modules/configs/i18n/es.json +5 -1
  444. package/src/modules/configs/i18n/ko.json +5 -1
  445. package/src/modules/configs/i18n/pl.json +5 -1
  446. package/src/modules/configs/lib/upgrade-actions.ts +35 -0
  447. package/src/modules/customer_groups/api/customer-groups/[id]/terms/route.ts +7 -0
  448. package/src/modules/customer_groups/components/CustomerGroupTermsSection.tsx +124 -2
  449. package/src/modules/customer_groups/components/customerGroupAssortmentScope.ts +46 -0
  450. package/src/modules/customer_groups/data/entities.ts +4 -0
  451. package/src/modules/customer_groups/data/validators.ts +14 -0
  452. package/src/modules/customer_groups/i18n/de.json +12 -0
  453. package/src/modules/customer_groups/i18n/en.json +12 -0
  454. package/src/modules/customer_groups/i18n/es.json +12 -0
  455. package/src/modules/customer_groups/i18n/ko.json +12 -0
  456. package/src/modules/customer_groups/i18n/pl.json +12 -0
  457. package/src/modules/customer_groups/migrations/.snapshot-open-mercato.json +17 -0
  458. package/src/modules/customer_groups/migrations/Migration20261005110250_customer_groups.ts +15 -0
  459. package/src/modules/customer_groups/services/customerGroupsService.ts +74 -23
  460. package/src/modules/ecommerce/acl.ts +9 -0
  461. package/src/modules/ecommerce/api/domain-mappings/route.ts +76 -0
  462. package/src/modules/ecommerce/api/openapi.ts +28 -0
  463. package/src/modules/ecommerce/api/store-channel-bindings/[id]/assortment-count/route.ts +141 -0
  464. package/src/modules/ecommerce/api/store-channel-bindings/crud.ts +283 -0
  465. package/src/modules/ecommerce/api/store-channel-bindings/route.ts +67 -0
  466. package/src/modules/ecommerce/api/store-domain-bindings/crud.ts +324 -0
  467. package/src/modules/ecommerce/api/store-domain-bindings/route.ts +73 -0
  468. package/src/modules/ecommerce/api/storefront/categories/[slug]/route.ts +94 -0
  469. package/src/modules/ecommerce/api/storefront/categories/openapiSchemas.ts +63 -0
  470. package/src/modules/ecommerce/api/storefront/categories/route.ts +78 -0
  471. package/src/modules/ecommerce/api/storefront/context/route.ts +203 -0
  472. package/src/modules/ecommerce/api/storefront/products/[idOrHandle]/route.ts +94 -0
  473. package/src/modules/ecommerce/api/storefront/products/openapiSchemas.ts +193 -0
  474. package/src/modules/ecommerce/api/storefront/products/route.ts +81 -0
  475. package/src/modules/ecommerce/api/storefront/search/suggest/openapiSchemas.ts +25 -0
  476. package/src/modules/ecommerce/api/storefront/search/suggest/route.ts +78 -0
  477. package/src/modules/ecommerce/api/storefront/storefrontRouteSupport.ts +68 -0
  478. package/src/modules/ecommerce/api/stores/[id]/branding/route.ts +205 -0
  479. package/src/modules/ecommerce/api/stores/[id]/preview-branding/route.ts +99 -0
  480. package/src/modules/ecommerce/api/stores/crud.ts +457 -0
  481. package/src/modules/ecommerce/api/stores/route.ts +66 -0
  482. package/src/modules/ecommerce/backend/config/ecommerce/[id]/page.meta.ts +12 -0
  483. package/src/modules/ecommerce/backend/config/ecommerce/[id]/page.tsx +5 -0
  484. package/src/modules/ecommerce/backend/config/ecommerce/page.meta.ts +12 -0
  485. package/src/modules/ecommerce/backend/config/ecommerce/page.tsx +5 -0
  486. package/src/modules/ecommerce/commands/stores.ts +154 -0
  487. package/src/modules/ecommerce/components/ChannelAssortmentCount.tsx +138 -0
  488. package/src/modules/ecommerce/components/ChannelBindingFormSections.tsx +40 -0
  489. package/src/modules/ecommerce/components/ChannelLookupPicker.tsx +5 -0
  490. package/src/modules/ecommerce/components/DomainStatusWarning.tsx +32 -0
  491. package/src/modules/ecommerce/components/StoreAvailabilityDefaultsSection.tsx +219 -0
  492. package/src/modules/ecommerce/components/StoreBrandingControls.tsx +73 -0
  493. package/src/modules/ecommerce/components/StoreBrandingPreview.tsx +77 -0
  494. package/src/modules/ecommerce/components/StoreBrandingTab.tsx +242 -0
  495. package/src/modules/ecommerce/components/StoreChannelBindingDialog.tsx +306 -0
  496. package/src/modules/ecommerce/components/StoreChannelsTab.tsx +375 -0
  497. package/src/modules/ecommerce/components/StoreCreateDialog.tsx +204 -0
  498. package/src/modules/ecommerce/components/StoreDomainBindingDialog.tsx +198 -0
  499. package/src/modules/ecommerce/components/StoreDomainsTab.tsx +426 -0
  500. package/src/modules/ecommerce/components/StoreEditPage.tsx +193 -0
  501. package/src/modules/ecommerce/components/StoreGeneralTab.tsx +189 -0
  502. package/src/modules/ecommerce/components/StoreListPage.tsx +326 -0
  503. package/src/modules/ecommerce/components/StoreSeoTab.tsx +152 -0
  504. package/src/modules/ecommerce/components/StoreStatusBadge.tsx +22 -0
  505. package/src/modules/ecommerce/components/channelLookups.ts +24 -0
  506. package/src/modules/ecommerce/components/storeAdmin.ts +56 -0
  507. package/src/modules/ecommerce/components/storeBrandingForm.ts +230 -0
  508. package/src/modules/ecommerce/components/storeChannels.ts +210 -0
  509. package/src/modules/ecommerce/components/storeDomains.ts +221 -0
  510. package/src/modules/ecommerce/components/storeEditTabs.tsx +76 -0
  511. package/src/modules/ecommerce/components/storeGeneral.ts +155 -0
  512. package/src/modules/ecommerce/components/storeSeo.ts +78 -0
  513. package/src/modules/ecommerce/components/useChannelAssortmentCount.ts +67 -0
  514. package/src/modules/ecommerce/components/useStoreAccess.ts +36 -0
  515. package/src/modules/ecommerce/data/enrichers.ts +213 -0
  516. package/src/modules/ecommerce/data/entities.ts +168 -0
  517. package/src/modules/ecommerce/data/validators.ts +587 -0
  518. package/src/modules/ecommerce/di.ts +9 -0
  519. package/src/modules/ecommerce/events.ts +27 -0
  520. package/src/modules/ecommerce/i18n/de.json +341 -0
  521. package/src/modules/ecommerce/i18n/en.json +341 -0
  522. package/src/modules/ecommerce/i18n/es.json +341 -0
  523. package/src/modules/ecommerce/i18n/ko.json +341 -0
  524. package/src/modules/ecommerce/i18n/pl.json +341 -0
  525. package/src/modules/ecommerce/index.ts +14 -0
  526. package/src/modules/ecommerce/lib/assortmentCount.ts +175 -0
  527. package/src/modules/ecommerce/lib/brandingStyles.ts +215 -0
  528. package/src/modules/ecommerce/lib/buyerContext.ts +401 -0
  529. package/src/modules/ecommerce/lib/cacheInvalidation.ts +302 -0
  530. package/src/modules/ecommerce/lib/cacheKeys.ts +340 -0
  531. package/src/modules/ecommerce/lib/createConflictRecheck.ts +31 -0
  532. package/src/modules/ecommerce/lib/crudEvents.ts +128 -0
  533. package/src/modules/ecommerce/lib/crudSupport.ts +85 -0
  534. package/src/modules/ecommerce/lib/domainBindingRebind.ts +138 -0
  535. package/src/modules/ecommerce/lib/domainMappingSummaries.ts +71 -0
  536. package/src/modules/ecommerce/lib/exclusiveFlag.ts +90 -0
  537. package/src/modules/ecommerce/lib/references.ts +93 -0
  538. package/src/modules/ecommerce/lib/seedDraftStore.ts +125 -0
  539. package/src/modules/ecommerce/lib/storeBindingCascade.ts +138 -0
  540. package/src/modules/ecommerce/lib/storeBranding.ts +48 -0
  541. package/src/modules/ecommerce/lib/storeBrandingRoute.ts +91 -0
  542. package/src/modules/ecommerce/lib/storeContext.ts +669 -0
  543. package/src/modules/ecommerce/lib/storeContextService.ts +71 -0
  544. package/src/modules/ecommerce/lib/storeLocale.ts +88 -0
  545. package/src/modules/ecommerce/lib/storeNotifications.ts +55 -0
  546. package/src/modules/ecommerce/lib/storefrontCatalogSupport.ts +427 -0
  547. package/src/modules/ecommerce/lib/storefrontCategories.ts +419 -0
  548. package/src/modules/ecommerce/lib/storefrontCategoryCache.ts +113 -0
  549. package/src/modules/ecommerce/lib/storefrontDetail.ts +654 -0
  550. package/src/modules/ecommerce/lib/storefrontFacets.ts +697 -0
  551. package/src/modules/ecommerce/lib/storefrontOptionFilter.ts +44 -0
  552. package/src/modules/ecommerce/lib/storefrontPricing.ts +583 -0
  553. package/src/modules/ecommerce/lib/storefrontProductCache.ts +126 -0
  554. package/src/modules/ecommerce/lib/storefrontProductScope.ts +181 -0
  555. package/src/modules/ecommerce/lib/storefrontProducts.ts +963 -0
  556. package/src/modules/ecommerce/lib/storefrontQuery.ts +215 -0
  557. package/src/modules/ecommerce/lib/storefrontRateLimit.ts +126 -0
  558. package/src/modules/ecommerce/lib/storefrontSearch.ts +454 -0
  559. package/src/modules/ecommerce/lib/storefrontSearchCache.ts +49 -0
  560. package/src/modules/ecommerce/lib/subscriberSupport.ts +41 -0
  561. package/src/modules/ecommerce/lib/types.ts +69 -0
  562. package/src/modules/ecommerce/migrations/.snapshot-open-mercato.json +829 -0
  563. package/src/modules/ecommerce/migrations/Migration20261005113233_ecommerce.ts +32 -0
  564. package/src/modules/ecommerce/migrations/Migration20261006112733_ecommerce.ts +15 -0
  565. package/src/modules/ecommerce/notifications.client.ts +46 -0
  566. package/src/modules/ecommerce/notifications.ts +46 -0
  567. package/src/modules/ecommerce/search.ts +93 -0
  568. package/src/modules/ecommerce/setup.ts +15 -0
  569. package/src/modules/ecommerce/subscribers/assortment-empty-notifications.ts +12 -0
  570. package/src/modules/ecommerce/subscribers/availability-policy-cache-invalidation.ts +12 -0
  571. package/src/modules/ecommerce/subscribers/catalog-category-cache-invalidation.ts +12 -0
  572. package/src/modules/ecommerce/subscribers/catalog-price-cache-invalidation.ts +12 -0
  573. package/src/modules/ecommerce/subscribers/catalog-product-cache-invalidation.ts +12 -0
  574. package/src/modules/ecommerce/subscribers/catalog-variant-cache-invalidation.ts +12 -0
  575. package/src/modules/ecommerce/subscribers/customer-group-cache-invalidation.ts +12 -0
  576. package/src/modules/ecommerce/subscribers/customer-group-membership-cache-invalidation.ts +12 -0
  577. package/src/modules/ecommerce/subscribers/customer-group-terms-cache-invalidation.ts +12 -0
  578. package/src/modules/ecommerce/subscribers/customer-user-deleted-cache-invalidation.ts +12 -0
  579. package/src/modules/ecommerce/subscribers/customer-user-updated-cache-invalidation.ts +12 -0
  580. package/src/modules/ecommerce/subscribers/domain-binding-rebind.ts +14 -0
  581. package/src/modules/ecommerce/subscribers/domain-mapping-cache-invalidation.ts +12 -0
  582. package/src/modules/ecommerce/subscribers/store-cache-invalidation.ts +12 -0
  583. package/src/modules/ecommerce/subscribers/store-channel-binding-cache-invalidation.ts +12 -0
  584. package/src/modules/ecommerce/subscribers/store-domain-binding-cache-invalidation.ts +12 -0
  585. package/src/modules/ecommerce/subscribers/store-notifications.ts +12 -0
  586. package/src/modules/query_index/lib/batch.ts +25 -9
  587. package/src/modules/query_index/lib/doc-enrichers.ts +306 -0
  588. package/src/modules/query_index/lib/document.ts +2 -0
  589. package/src/modules/query_index/lib/engine.ts +58 -1
  590. package/src/modules/query_index/lib/indexer.ts +8 -0
  591. package/src/modules/query_index/lib/search-tokens.ts +2 -0
  592. package/src/modules/query_index/migrations/Migration20261005201500_query_index.ts +42 -0
  593. package/src/modules/translations/components/TranslationManager.tsx +3 -3
  594. package/src/modules/translations/data/validators.ts +1 -1
  595. package/src/modules/translations/lib/batch.ts +47 -0
  596. package/src/modules/translations/lib/helpers.ts +4 -0
  597. package/src/modules/translations/lib/resolve-field-list.ts +16 -2
@@ -0,0 +1,670 @@
1
+ import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
2
+ import { sanitizeSearchTerm } from "@open-mercato/shared/lib/query/sanitizeSearchTerm";
3
+ import { SortDir } from "@open-mercato/shared/lib/query/types";
4
+ import { E } from "../../../generated/entities.ids.generated.js";
5
+ import {
6
+ CatalogProductCategory,
7
+ CatalogProductCategoryAssignment,
8
+ CatalogProductPrice,
9
+ CatalogProductTag,
10
+ CatalogProductTagAssignment,
11
+ CatalogProductVariant
12
+ } from "@open-mercato/core/modules/catalog/data/entities";
13
+ import {
14
+ buildProductFilters,
15
+ scoreProductSearchRelevance
16
+ } from "@open-mercato/core/modules/catalog/lib/productFilters";
17
+ import {
18
+ STOREFRONT_FACET_UNIVERSE_CAP,
19
+ countStorefrontFacets,
20
+ labelStorefrontCountFacets,
21
+ loadStorefrontFacetSource,
22
+ loadStorefrontProductTypeLabeler,
23
+ readCachedStorefrontCountFacets,
24
+ storefrontAvailabilityFacet,
25
+ storefrontFacetTranslationRequests,
26
+ storefrontFacetVariantIndex,
27
+ storefrontPriceRangeFacet,
28
+ writeCachedStorefrontCountFacets
29
+ } from "./storefrontFacets.js";
30
+ import { buildStorefrontProductScope, composeStorefrontProductFilters } from "./storefrontProductScope.js";
31
+ import { resolveStorefrontPrices } from "./storefrontPricing.js";
32
+ import { queryStorefrontOptionProductIds } from "./storefrontOptionFilter.js";
33
+ import {
34
+ STOREFRONT_CATEGORY_ENTITY_TYPE,
35
+ STOREFRONT_PRODUCT_ENTITY_TYPE,
36
+ STOREFRONT_TAG_ENTITY_TYPE,
37
+ buildStorefrontListItem,
38
+ isCategoryInAssortment,
39
+ selectCategoriesWithActiveAncestors,
40
+ loadStorefrontTranslations,
41
+ localeChain,
42
+ nonEmptyString,
43
+ referenceId,
44
+ resolvePublicDefaultMediaUrls,
45
+ resolveStorefrontAvailability,
46
+ storefrontAvailabilityKey,
47
+ stringList,
48
+ toStorefrontAvailability,
49
+ tryResolve
50
+ } from "./storefrontCatalogSupport.js";
51
+ import { isCategoryInAssortment as isCategoryInAssortment2 } from "./storefrontCatalogSupport.js";
52
+ const STOREFRONT_PRICE_SORT_CAP = 5e3;
53
+ const STOREFRONT_APPROXIMATE_SORT_CEILING = 5e4;
54
+ const APPROXIMATE_PRICE_CHUNK = 1e3;
55
+ const NO_MATCH_ID = "00000000-0000-0000-0000-000000000000";
56
+ const LIST_FIELDS = [
57
+ "id",
58
+ "title",
59
+ "subtitle",
60
+ "handle",
61
+ "sku",
62
+ "product_type",
63
+ "is_configurable",
64
+ "default_media_id",
65
+ "default_media_url",
66
+ "created_at"
67
+ ];
68
+ const CANDIDATE_FIELDS = ["id", "title", "sku"];
69
+ const SORT_ORDER = [
70
+ "relevance",
71
+ "price_asc",
72
+ "price_desc",
73
+ "title_asc",
74
+ "title_desc",
75
+ "newest",
76
+ "featured"
77
+ ];
78
+ const EMPTY_COUNT_FACETS = { categories: [], tags: [], options: [], productTypes: [] };
79
+ function isPriceSort(sort) {
80
+ return sort === "price_asc" || sort === "price_desc";
81
+ }
82
+ function sqlSortFor(sort) {
83
+ switch (sort) {
84
+ case "title_desc":
85
+ return [{ field: "title", dir: SortDir.Desc }];
86
+ case "newest":
87
+ case "featured":
88
+ return [{ field: "created_at", dir: SortDir.Desc }];
89
+ default:
90
+ return [{ field: "title", dir: SortDir.Asc }];
91
+ }
92
+ }
93
+ async function resolveCategoryFilter(runtime, query) {
94
+ if (!query.categoryId && !query.categorySlug) return null;
95
+ const { ctx } = runtime;
96
+ const where = {
97
+ tenantId: ctx.tenantId,
98
+ organizationId: ctx.organizationId,
99
+ deletedAt: null,
100
+ isActive: true,
101
+ ...query.categoryId ? { id: query.categoryId } : { slug: query.categorySlug }
102
+ };
103
+ const [category] = await findWithDecryption(
104
+ runtime.em,
105
+ CatalogProductCategory,
106
+ where,
107
+ { fields: ["id", "slug", "ancestorIds", "descendantIds"], limit: 1 },
108
+ runtime.decryptionScope
109
+ );
110
+ if (!category) return null;
111
+ const lineage = {
112
+ id: category.id,
113
+ ancestorIds: stringList(category.ancestorIds),
114
+ descendantIds: stringList(category.descendantIds)
115
+ };
116
+ if (!isCategoryInAssortment(lineage, ctx.buyer.assortmentScope)) return null;
117
+ const { visibleIds } = await selectCategoriesWithActiveAncestors(runtime.em, ctx, [lineage]);
118
+ if (!visibleIds.has(category.id)) return null;
119
+ return { id: category.id, slug: category.slug ?? null };
120
+ }
121
+ async function resolveTagFilter(runtime, slugs) {
122
+ if (!slugs?.length) return [];
123
+ const { ctx } = runtime;
124
+ const tags = await findWithDecryption(
125
+ runtime.em,
126
+ CatalogProductTag,
127
+ { tenantId: ctx.tenantId, organizationId: ctx.organizationId, slug: { $in: slugs } },
128
+ { fields: ["id", "slug"] },
129
+ runtime.decryptionScope
130
+ );
131
+ const bySlug = new Map(tags.map((tag) => [tag.slug, tag.id]));
132
+ return slugs.flatMap((slug) => {
133
+ const id = bySlug.get(slug);
134
+ return id ? [{ id, slug }] : [];
135
+ });
136
+ }
137
+ const OPTION_FILTER_OVER_CAP = "over_cap";
138
+ async function resolveOptionProductIds(runtime, options) {
139
+ if (!options) return null;
140
+ const ids = await queryStorefrontOptionProductIds(
141
+ runtime.em,
142
+ runtime.decryptionScope,
143
+ options,
144
+ runtime.facetUniverseCap ?? STOREFRONT_FACET_UNIVERSE_CAP
145
+ );
146
+ return ids ?? OPTION_FILTER_OVER_CAP;
147
+ }
148
+ async function productFilterClause(runtime, filterQuery) {
149
+ return buildStorefrontProductFilterClause(runtime.container, runtime.ctx, filterQuery);
150
+ }
151
+ async function buildStorefrontProductFilterClause(container, ctx, filterQuery) {
152
+ const crudCtx = {
153
+ container,
154
+ auth: { sub: "ecommerce:storefront", tenantId: ctx.tenantId, orgId: ctx.organizationId },
155
+ organizationScope: null,
156
+ selectedOrganizationId: ctx.organizationId,
157
+ organizationIds: [ctx.organizationId]
158
+ };
159
+ const productFilters = await buildProductFilters({ page: 1, pageSize: 1, ...filterQuery }, crudCtx, {
160
+ includeCategoryDescendants: true
161
+ });
162
+ return Object.keys(productFilters).length ? productFilters : null;
163
+ }
164
+ function andClauses(clauses) {
165
+ const present = clauses.filter((clause) => clause !== null);
166
+ if (present.length === 0) return null;
167
+ return present.length === 1 ? present[0] : { $and: present };
168
+ }
169
+ async function resolveListFilters(runtime, query) {
170
+ const applied = {};
171
+ const searchTerm = sanitizeSearchTerm(query.search);
172
+ const [category, resolvedTags, optionProductIds] = await Promise.all([
173
+ resolveCategoryFilter(runtime, query),
174
+ resolveTagFilter(runtime, query.tagSlugs),
175
+ resolveOptionProductIds(runtime, query.options)
176
+ ]);
177
+ if (searchTerm) applied.search = searchTerm;
178
+ if (category) applied.category = { id: category.id, slug: category.slug, includesDescendants: true };
179
+ if (resolvedTags.length) applied.tagSlugs = resolvedTags.map((tag) => tag.slug);
180
+ if (query.productType) applied.productType = query.productType;
181
+ const optionsApplied = Array.isArray(optionProductIds);
182
+ if (optionsApplied && query.options) applied.options = query.options;
183
+ const [searchClause, facetClause] = await Promise.all([
184
+ searchTerm ? productFilterClause(runtime, { search: searchTerm }) : Promise.resolve(null),
185
+ category || resolvedTags.length || query.productType ? productFilterClause(runtime, {
186
+ categoryIds: category?.id,
187
+ tagIds: resolvedTags.length ? resolvedTags.map((tag) => tag.id).join(",") : void 0,
188
+ productType: query.productType
189
+ }) : Promise.resolve(null)
190
+ ]);
191
+ const optionClause = Array.isArray(optionProductIds) ? optionProductIds.length ? { id: { $in: optionProductIds } } : { id: { $eq: NO_MATCH_ID } } : null;
192
+ return {
193
+ extra: andClauses([searchClause, facetClause, optionClause]),
194
+ universe: searchClause,
195
+ selection: {
196
+ categoryId: category?.id ?? null,
197
+ tagIds: resolvedTags.map((tag) => tag.id),
198
+ productType: query.productType ?? null,
199
+ options: optionsApplied ? query.options ?? {} : {}
200
+ },
201
+ applied,
202
+ searchTerm: searchTerm || null
203
+ };
204
+ }
205
+ async function queryCandidates(runtime, filters, sort, pageSize) {
206
+ const result = await runtime.queryEngine.query(E.catalog.catalog_product, {
207
+ tenantId: runtime.scope.tenantId,
208
+ organizationId: runtime.scope.organizationId,
209
+ withDeleted: runtime.scope.withDeleted,
210
+ filters,
211
+ fields: CANDIDATE_FIELDS,
212
+ sort,
213
+ page: { page: 1, pageSize: Math.max(1, pageSize) }
214
+ });
215
+ const items = result.items.filter((item) => typeof item.id === "string").map((item) => ({ id: item.id, title: nonEmptyString(item.title) ?? "", sku: nonEmptyString(item.sku) }));
216
+ return { items, total: result.total };
217
+ }
218
+ async function queryProductsByIds(runtime, ids) {
219
+ if (!ids.length) return [];
220
+ const result = await runtime.queryEngine.query(E.catalog.catalog_product, {
221
+ tenantId: runtime.scope.tenantId,
222
+ organizationId: runtime.scope.organizationId,
223
+ withDeleted: runtime.scope.withDeleted,
224
+ filters: composeStorefrontProductFilters(runtime.scope, { id: { $in: ids } }),
225
+ fields: LIST_FIELDS,
226
+ page: { page: 1, pageSize: ids.length }
227
+ });
228
+ const byId = new Map(result.items.map((item) => [item.id, item]));
229
+ return ids.map((id) => byId.get(id)).filter((item) => !!item);
230
+ }
231
+ async function loadVariantIds(runtime, productIds) {
232
+ const byProduct = /* @__PURE__ */ new Map();
233
+ if (!productIds.length) return byProduct;
234
+ const { ctx } = runtime;
235
+ const variants = await findWithDecryption(
236
+ runtime.em,
237
+ CatalogProductVariant,
238
+ {
239
+ tenantId: ctx.tenantId,
240
+ organizationId: ctx.organizationId,
241
+ deletedAt: null,
242
+ isActive: true,
243
+ product: { $in: productIds }
244
+ },
245
+ { fields: ["id", "product"] },
246
+ runtime.decryptionScope
247
+ );
248
+ for (const variant of variants) {
249
+ const productId = referenceId(variant.product);
250
+ if (!productId) continue;
251
+ const bucket = byProduct.get(productId) ?? [];
252
+ bucket.push(variant.id);
253
+ byProduct.set(productId, bucket);
254
+ }
255
+ return byProduct;
256
+ }
257
+ async function loadCategories(runtime, productIds) {
258
+ const candidates = /* @__PURE__ */ new Map();
259
+ const { ctx } = runtime;
260
+ const assignments = await findWithDecryption(
261
+ runtime.em,
262
+ CatalogProductCategoryAssignment,
263
+ { tenantId: ctx.tenantId, organizationId: ctx.organizationId, product: { $in: productIds } },
264
+ { populate: ["category"], orderBy: { position: "asc" } },
265
+ runtime.decryptionScope
266
+ );
267
+ const categoryIds = /* @__PURE__ */ new Set();
268
+ for (const assignment of assignments) {
269
+ const productId = referenceId(assignment.product);
270
+ const category = typeof assignment.category === "object" ? assignment.category : null;
271
+ if (!productId || !category || category.deletedAt || category.isActive === false) continue;
272
+ const lineage = {
273
+ id: category.id,
274
+ ancestorIds: stringList(category.ancestorIds),
275
+ descendantIds: stringList(category.descendantIds)
276
+ };
277
+ if (!isCategoryInAssortment(lineage, ctx.buyer.assortmentScope)) continue;
278
+ const bucket = candidates.get(productId) ?? [];
279
+ if (bucket.some((entry) => entry.id === category.id)) continue;
280
+ bucket.push({ id: category.id, name: category.name, slug: category.slug ?? null, ancestorIds: lineage.ancestorIds });
281
+ candidates.set(productId, bucket);
282
+ categoryIds.add(category.id);
283
+ }
284
+ const allCandidates = Array.from(candidates.values()).flat();
285
+ const { visibleIds: visible } = await selectCategoriesWithActiveAncestors(runtime.em, ctx, allCandidates, {
286
+ activeIds: categoryIds
287
+ });
288
+ const byProduct = /* @__PURE__ */ new Map();
289
+ for (const [productId, bucket] of candidates) {
290
+ const refs = bucket.filter((entry) => visible.has(entry.id)).map(({ id, name, slug }) => ({ id, name, slug }));
291
+ if (refs.length > 0) byProduct.set(productId, refs);
292
+ }
293
+ return { byProduct, categoryIds: Array.from(categoryIds).filter((id) => visible.has(id)) };
294
+ }
295
+ async function loadTags(runtime, productIds) {
296
+ const byProduct = /* @__PURE__ */ new Map();
297
+ const { ctx } = runtime;
298
+ const assignments = await findWithDecryption(
299
+ runtime.em,
300
+ CatalogProductTagAssignment,
301
+ { tenantId: ctx.tenantId, organizationId: ctx.organizationId, product: { $in: productIds } },
302
+ { populate: ["tag"] },
303
+ runtime.decryptionScope
304
+ );
305
+ const tagIds = /* @__PURE__ */ new Set();
306
+ for (const assignment of assignments) {
307
+ const productId = referenceId(assignment.product);
308
+ const tag = typeof assignment.tag === "object" ? assignment.tag : null;
309
+ if (!productId || !tag) continue;
310
+ const bucket = byProduct.get(productId) ?? [];
311
+ if (bucket.some((entry) => entry.id === tag.id)) continue;
312
+ bucket.push({ id: tag.id, label: tag.label });
313
+ byProduct.set(productId, bucket);
314
+ tagIds.add(tag.id);
315
+ }
316
+ return { byProduct, tagIds: Array.from(tagIds) };
317
+ }
318
+ async function resolvePageAvailability(runtime, productIds) {
319
+ const results = /* @__PURE__ */ new Map();
320
+ if (!productIds.length) return results;
321
+ const targets = productIds.map((productId) => ({ productId, variantId: null }));
322
+ const resolved = await resolveStorefrontAvailability(runtime.container, runtime.ctx, runtime.em, targets);
323
+ for (const target of targets) {
324
+ const entry = resolved.get(storefrontAvailabilityKey(target));
325
+ results.set(target.productId, {
326
+ result: entry?.result ?? null,
327
+ hideWhenOutOfStock: entry?.policy?.hideWhenOutOfStock?.value === true
328
+ });
329
+ }
330
+ return results;
331
+ }
332
+ const IN_STOCK_STATES = /* @__PURE__ */ new Set(["in_stock", "low_stock", "not_tracked"]);
333
+ function matchesAvailabilityFilter(availability, filter) {
334
+ if (filter === "in_stock") return IN_STOCK_STATES.has(availability.state) && availability.canFulfil;
335
+ if (filter === "available") return availability.state !== "out_of_stock" && availability.canFulfil;
336
+ return true;
337
+ }
338
+ async function hydratePage(runtime, records, query, prefetch, extraTranslations) {
339
+ const { ctx, container } = runtime;
340
+ if (!records.length) {
341
+ const translations2 = extraTranslations.length ? await loadStorefrontTranslations(runtime.em, ctx, extraTranslations) : /* @__PURE__ */ new Map();
342
+ return { items: [], availabilityStates: [], translations: translations2 };
343
+ }
344
+ const productIds = records.map((record) => record.id);
345
+ const [variantsByProduct, categories, tags] = await Promise.all([
346
+ prefetch.variants ?? loadVariantIds(runtime, productIds),
347
+ loadCategories(runtime, productIds),
348
+ loadTags(runtime, productIds)
349
+ ]);
350
+ const [pricing, translations, availability, mediaUrls] = await Promise.all([
351
+ prefetch.pricing ?? resolveStorefrontPrices(
352
+ container,
353
+ ctx,
354
+ productIds.map((productId) => ({ productId, variantIds: variantsByProduct.get(productId) ?? [] })),
355
+ { date: runtime.date }
356
+ ),
357
+ loadStorefrontTranslations(runtime.em, ctx, [
358
+ { entityType: STOREFRONT_PRODUCT_ENTITY_TYPE, ids: productIds },
359
+ { entityType: STOREFRONT_CATEGORY_ENTITY_TYPE, ids: categories.categoryIds },
360
+ { entityType: STOREFRONT_TAG_ENTITY_TYPE, ids: tags.tagIds },
361
+ ...extraTranslations
362
+ ]),
363
+ resolvePageAvailability(runtime, productIds),
364
+ resolvePublicDefaultMediaUrls(
365
+ runtime.em,
366
+ ctx,
367
+ records.map((record) => ({
368
+ id: record.id,
369
+ defaultMediaId: record.default_media_id,
370
+ defaultMediaUrl: record.default_media_url
371
+ }))
372
+ )
373
+ ]);
374
+ const locales = localeChain(ctx);
375
+ const productTranslations = translations.get(STOREFRONT_PRODUCT_ENTITY_TYPE);
376
+ const categoryTranslations = translations.get(STOREFRONT_CATEGORY_ENTITY_TYPE);
377
+ const tagTranslations = translations.get(STOREFRONT_TAG_ENTITY_TYPE);
378
+ const items = [];
379
+ const availabilityStates = [];
380
+ for (const record of records) {
381
+ const productAvailability = availability.get(record.id);
382
+ const storefrontAvailability = toStorefrontAvailability(productAvailability?.result ?? null);
383
+ if (productAvailability?.hideWhenOutOfStock && storefrontAvailability.state === "out_of_stock") continue;
384
+ availabilityStates.push(storefrontAvailability.state);
385
+ if (!matchesAvailabilityFilter(storefrontAvailability, query.availability)) continue;
386
+ items.push(
387
+ buildStorefrontListItem(
388
+ {
389
+ id: record.id,
390
+ handle: record.handle,
391
+ title: record.title,
392
+ subtitle: record.subtitle,
393
+ defaultMediaUrl: mediaUrls.get(record.id) ?? null,
394
+ productType: record.product_type,
395
+ isConfigurable: record.is_configurable
396
+ },
397
+ {
398
+ locales,
399
+ overlay: productTranslations?.get(record.id),
400
+ variantCount: variantsByProduct.get(record.id)?.length ?? 0,
401
+ categories: categories.byProduct.get(record.id) ?? [],
402
+ categoryTranslations,
403
+ tags: tags.byProduct.get(record.id) ?? [],
404
+ tagTranslations,
405
+ pricing: pricing.get(record.id),
406
+ availability: storefrontAvailability
407
+ }
408
+ )
409
+ );
410
+ }
411
+ return { items, availabilityStates, translations };
412
+ }
413
+ function pricingAmount(pricing) {
414
+ if (!pricing) return null;
415
+ return pricing.price?.amount ?? pricing.priceRange?.min ?? null;
416
+ }
417
+ function parseAmount(value) {
418
+ if (value === null || value === void 0 || value === "") return null;
419
+ const numeric = typeof value === "number" ? value : Number(value);
420
+ return Number.isFinite(numeric) ? numeric : null;
421
+ }
422
+ function chunk(values, size) {
423
+ const chunks = [];
424
+ for (let index = 0; index < values.length; index += size) chunks.push(values.slice(index, index + size));
425
+ return chunks;
426
+ }
427
+ async function loadApproximateAmounts(runtime, productIds) {
428
+ const { ctx } = runtime;
429
+ const amounts = /* @__PURE__ */ new Map();
430
+ const priceKindId = ctx.channel?.priceKindId ?? null;
431
+ if (!priceKindId || !productIds.length) return amounts;
432
+ const rows = [];
433
+ for (const ids of chunk(productIds, APPROXIMATE_PRICE_CHUNK)) {
434
+ rows.push(
435
+ ...await findWithDecryption(
436
+ runtime.em,
437
+ CatalogProductPrice,
438
+ {
439
+ tenantId: ctx.tenantId,
440
+ organizationId: ctx.organizationId,
441
+ priceKind: priceKindId,
442
+ currencyCode: ctx.currencyCode,
443
+ customerId: null,
444
+ customerGroupId: null,
445
+ userId: null,
446
+ userGroupId: null,
447
+ $or: [{ product: { $in: ids } }, { variant: { product: { $in: ids } } }]
448
+ },
449
+ { populate: ["variant"] },
450
+ runtime.decryptionScope
451
+ )
452
+ );
453
+ }
454
+ const wantedIds = new Set(productIds);
455
+ const channelId = ctx.channel?.salesChannelId ?? null;
456
+ const now = runtime.date;
457
+ for (const row of rows) {
458
+ if (row.channelId && row.channelId !== channelId) continue;
459
+ if ((row.minQuantity ?? 1) > 1) continue;
460
+ if (row.startsAt && row.startsAt > now) continue;
461
+ if (row.endsAt && row.endsAt < now) continue;
462
+ const productId = referenceId(row.product) ?? (row.variant && typeof row.variant === "object" ? referenceId(row.variant.product) : null);
463
+ if (!productId || !wantedIds.has(productId)) continue;
464
+ const wanted = parseAmount(ctx.buyer.taxMode === "gross" ? row.unitPriceGross : row.unitPriceNet);
465
+ const amount = wanted ?? parseAmount(ctx.buyer.taxMode === "gross" ? row.unitPriceNet : row.unitPriceGross);
466
+ if (amount === null) continue;
467
+ const current = amounts.get(productId);
468
+ if (current === void 0 || amount < current) amounts.set(productId, amount);
469
+ }
470
+ return amounts;
471
+ }
472
+ function compareAmounts(left, right, direction) {
473
+ if (left === null && right === null) return 0;
474
+ if (left === null) return 1;
475
+ if (right === null) return -1;
476
+ return (left - right) * direction;
477
+ }
478
+ function rankByRelevance(items, searchTerm) {
479
+ const needle = searchTerm.toLowerCase();
480
+ return items.map((item, index) => ({ item, index, score: scoreProductSearchRelevance(needle, item.title, item.sku) })).sort((left, right) => left.score - right.score || left.item.title.localeCompare(right.item.title) || left.index - right.index).map((entry) => entry.item);
481
+ }
482
+ function matchesPriceFilter(amount, query) {
483
+ if (amount === null) return false;
484
+ if (query.priceMin !== void 0 && amount < query.priceMin) return false;
485
+ if (query.priceMax !== void 0 && amount > query.priceMax) return false;
486
+ return true;
487
+ }
488
+ function availableSortsFor(searchTerm, priceSortsOffered) {
489
+ return SORT_ORDER.filter((sort) => {
490
+ if (sort === "relevance") return !!searchTerm;
491
+ if (isPriceSort(sort)) return priceSortsOffered;
492
+ return true;
493
+ });
494
+ }
495
+ async function resolveCountFacetState(runtime, selection, searchTerm, universe) {
496
+ const cached = await readCachedStorefrontCountFacets(runtime.container, runtime.ctx, selection, searchTerm);
497
+ if (cached) return { cached, source: null, overCap: false };
498
+ const source = await loadStorefrontFacetSource(
499
+ runtime,
500
+ composeStorefrontProductFilters(runtime.scope, universe),
501
+ runtime.facetUniverseCap
502
+ );
503
+ return { cached: null, source, overCap: source === null };
504
+ }
505
+ async function listStorefrontProducts(container, ctx, query, options = {}) {
506
+ const em = tryResolve(container, "em");
507
+ const queryEngine = tryResolve(container, "queryEngine");
508
+ if (!em || !queryEngine) throw new Error("[internal] ecommerce storefront listing requires em and queryEngine");
509
+ const scope = buildStorefrontProductScope(ctx);
510
+ const runtime = {
511
+ container,
512
+ ctx,
513
+ em,
514
+ queryEngine,
515
+ scope,
516
+ decryptionScope: { tenantId: ctx.tenantId, organizationId: ctx.organizationId },
517
+ date: options.date ?? /* @__PURE__ */ new Date(),
518
+ facetUniverseCap: options.facetUniverseCap
519
+ };
520
+ const cap = Math.max(1, options.priceSortCap ?? STOREFRONT_PRICE_SORT_CAP);
521
+ const approximateCeiling = Math.max(cap, options.approximateSortCeiling ?? STOREFRONT_APPROXIMATE_SORT_CEILING);
522
+ const channelFallback = ctx.channel?.priceSortFallback ?? "approximate";
523
+ const { page, pageSize } = query;
524
+ const { extra, universe, selection, applied, searchTerm } = await resolveListFilters(runtime, query);
525
+ const filters = composeStorefrontProductFilters(scope, extra);
526
+ if (query.availability === "in_stock" || query.availability === "available") {
527
+ applied.availability = { value: query.availability, scope: "page" };
528
+ }
529
+ const defaultSort = searchTerm ? "relevance" : "featured";
530
+ const requestedSort = query.sort ?? defaultSort;
531
+ const priceSortRequested = isPriceSort(requestedSort);
532
+ const priceFilterRequested = query.priceMin !== void 0 || query.priceMax !== void 0;
533
+ const baseSort = priceSortRequested || requestedSort === "relevance" ? "title_asc" : requestedSort;
534
+ const [countFacetState, first] = await Promise.all([
535
+ resolveCountFacetState(runtime, selection, searchTerm, universe),
536
+ queryCandidates(runtime, filters, sqlSortFor(baseSort), cap)
537
+ ]);
538
+ const facetVariants = countFacetState.source ? storefrontFacetVariantIndex(countFacetState.source) : null;
539
+ const capExceeded = first.total > cap;
540
+ const fallback = capExceeded && first.total > approximateCeiling ? "unavailable" : channelFallback;
541
+ const priceOnOffer = !capExceeded || fallback === "approximate";
542
+ let sortApproximate = false;
543
+ let sortUnavailable = false;
544
+ let appliedSort = requestedSort === "relevance" && !searchTerm ? defaultSort : requestedSort;
545
+ let total = 0;
546
+ let records = [];
547
+ let prefetch = {};
548
+ let candidates = null;
549
+ let amounts = null;
550
+ if (!capExceeded) {
551
+ candidates = first.items;
552
+ const candidateIds = candidates.map((candidate) => candidate.id);
553
+ const variants = facetVariants ? new Map(candidateIds.map((id) => [id, facetVariants.get(id) ?? []])) : await loadVariantIds(runtime, candidateIds);
554
+ const pricing = await resolveStorefrontPrices(
555
+ container,
556
+ ctx,
557
+ candidateIds.map((id) => ({ productId: id, variantIds: variants.get(id) ?? [] })),
558
+ { date: runtime.date }
559
+ );
560
+ prefetch = { variants, pricing };
561
+ amounts = new Map(candidateIds.map((id) => [id, pricingAmount(pricing.get(id))]));
562
+ } else if (priceOnOffer && (priceSortRequested || priceFilterRequested)) {
563
+ const all = await queryCandidates(runtime, filters, sqlSortFor(baseSort), first.total);
564
+ const approximate = await loadApproximateAmounts(runtime, all.items.map((candidate) => candidate.id));
565
+ amounts = new Map(all.items.map((candidate) => [candidate.id, approximate.get(candidate.id) ?? null]));
566
+ candidates = all.items;
567
+ }
568
+ const priceRange = amounts ? storefrontPriceRangeFacet(amounts.values(), ctx.currencyCode) : null;
569
+ if (priceFilterRequested && priceOnOffer) {
570
+ applied.price = { min: query.priceMin ?? null, max: query.priceMax ?? null, approximate: capExceeded };
571
+ }
572
+ if (priceSortRequested && !priceOnOffer) {
573
+ sortUnavailable = true;
574
+ appliedSort = defaultSort;
575
+ }
576
+ if (candidates) {
577
+ let ordered = priceFilterRequested && priceOnOffer ? candidates.filter((candidate) => matchesPriceFilter(amounts?.get(candidate.id) ?? null, query)) : candidates;
578
+ if (appliedSort === "relevance" && searchTerm) {
579
+ ordered = rankByRelevance(ordered, searchTerm);
580
+ } else if (isPriceSort(appliedSort)) {
581
+ const direction = appliedSort === "price_asc" ? 1 : -1;
582
+ ordered = ordered.map((candidate, index) => ({ candidate, index })).sort(
583
+ (left, right) => compareAmounts(amounts?.get(left.candidate.id) ?? null, amounts?.get(right.candidate.id) ?? null, direction) || left.index - right.index
584
+ ).map((entry) => entry.candidate);
585
+ sortApproximate = capExceeded;
586
+ }
587
+ total = ordered.length;
588
+ const pageIds = ordered.slice((page - 1) * pageSize, page * pageSize).map((candidate) => candidate.id);
589
+ records = await queryProductsByIds(runtime, pageIds);
590
+ } else {
591
+ const sqlOrder = appliedSort === "relevance" ? "title_asc" : appliedSort;
592
+ const result = await runtime.queryEngine.query(E.catalog.catalog_product, {
593
+ tenantId: scope.tenantId,
594
+ organizationId: scope.organizationId,
595
+ withDeleted: scope.withDeleted,
596
+ filters,
597
+ fields: LIST_FIELDS,
598
+ sort: sqlSortFor(sqlOrder),
599
+ page: { page, pageSize }
600
+ });
601
+ total = result.total;
602
+ records = result.items.filter((item) => typeof item.id === "string");
603
+ if (appliedSort === "relevance" && searchTerm) {
604
+ records = rankByRelevance(
605
+ records.map((record) => ({ record, title: nonEmptyString(record.title) ?? "", sku: nonEmptyString(record.sku) })),
606
+ searchTerm
607
+ ).map((entry) => entry.record);
608
+ sortApproximate = true;
609
+ }
610
+ if (facetVariants) prefetch = { variants: new Map(records.map((record) => [record.id, facetVariants.get(record.id) ?? []])) };
611
+ }
612
+ const availableSorts = availableSortsFor(searchTerm, !(capExceeded && fallback === "unavailable"));
613
+ const { source, cached, overCap } = countFacetState;
614
+ const rawCounts = source ? countStorefrontFacets(source, selection) : null;
615
+ const hydrated = await hydratePage(
616
+ runtime,
617
+ records,
618
+ query,
619
+ prefetch,
620
+ source && rawCounts ? storefrontFacetTranslationRequests(source, rawCounts) : []
621
+ );
622
+ let countFacets = cached ?? EMPTY_COUNT_FACETS;
623
+ if (source && rawCounts) {
624
+ countFacets = labelStorefrontCountFacets(source, rawCounts, {
625
+ locales: localeChain(ctx),
626
+ translations: hydrated.translations,
627
+ assortmentScope: ctx.buyer.assortmentScope,
628
+ productTypeLabel: await loadStorefrontProductTypeLabeler(ctx.effectiveLocale)
629
+ });
630
+ await writeCachedStorefrontCountFacets(container, ctx, selection, searchTerm, countFacets);
631
+ } else if (overCap) {
632
+ await writeCachedStorefrontCountFacets(container, ctx, selection, searchTerm, EMPTY_COUNT_FACETS);
633
+ }
634
+ const facets = {
635
+ categories: countFacets.categories,
636
+ tags: countFacets.tags,
637
+ priceRange,
638
+ options: countFacets.options,
639
+ productTypes: countFacets.productTypes,
640
+ availability: storefrontAvailabilityFacet(hydrated.availabilityStates),
641
+ availabilityScope: "page",
642
+ total
643
+ };
644
+ return {
645
+ items: hydrated.items,
646
+ total,
647
+ page,
648
+ pageSize,
649
+ totalPages: Math.ceil(total / pageSize),
650
+ facets,
651
+ effectiveLocale: ctx.effectiveLocale,
652
+ requestedLocale: ctx.requestedLocale,
653
+ currencyCode: ctx.currencyCode,
654
+ taxMode: ctx.buyer.taxMode,
655
+ appliedFilters: applied,
656
+ availableSorts,
657
+ appliedSort,
658
+ priceSort: { cap, fallback, capExceeded },
659
+ sortApproximate,
660
+ sortUnavailable
661
+ };
662
+ }
663
+ export {
664
+ STOREFRONT_APPROXIMATE_SORT_CEILING,
665
+ STOREFRONT_PRICE_SORT_CAP,
666
+ buildStorefrontProductFilterClause,
667
+ isCategoryInAssortment2 as isCategoryInAssortment,
668
+ listStorefrontProducts
669
+ };
670
+ //# sourceMappingURL=storefrontProducts.js.map