@floxiz/medusa-plugin-meilisearch 0.1.4 → 0.1.6

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 (262) hide show
  1. package/.medusa/server/src/api/store/meilisearch/categories/route.d.ts.map +1 -1
  2. package/.medusa/server/src/api/store/meilisearch/categories/route.js +3 -2
  3. package/.medusa/server/src/api/store/meilisearch/products/route.js +2 -2
  4. package/.medusa/server/src/jobs/meilisearch-categories-index.d.ts.map +1 -1
  5. package/.medusa/server/src/jobs/meilisearch-categories-index.js +14 -4
  6. package/.medusa/server/src/jobs/meilisearch-products-index.d.ts.map +1 -1
  7. package/.medusa/server/src/jobs/meilisearch-products-index.js +14 -4
  8. package/.medusa/server/src/subscribers/meilisearch-category-delete.d.ts +6 -0
  9. package/.medusa/server/src/subscribers/meilisearch-category-delete.d.ts.map +1 -0
  10. package/.medusa/server/src/subscribers/meilisearch-category-delete.js +27 -0
  11. package/.medusa/server/src/subscribers/meilisearch-category-upsert.d.ts +6 -0
  12. package/.medusa/server/src/subscribers/meilisearch-category-upsert.d.ts.map +1 -0
  13. package/.medusa/server/src/subscribers/meilisearch-category-upsert.js +29 -0
  14. package/.medusa/server/src/subscribers/meilisearch-collection-delete.d.ts +6 -0
  15. package/.medusa/server/src/subscribers/meilisearch-collection-delete.d.ts.map +1 -0
  16. package/.medusa/server/src/subscribers/meilisearch-collection-delete.js +27 -0
  17. package/.medusa/server/src/subscribers/meilisearch-collection-upsert.d.ts +6 -0
  18. package/.medusa/server/src/subscribers/meilisearch-collection-upsert.d.ts.map +1 -0
  19. package/.medusa/server/src/subscribers/meilisearch-collection-upsert.js +33 -0
  20. package/.medusa/server/src/subscribers/meilisearch-image-upsert.d.ts +6 -0
  21. package/.medusa/server/src/subscribers/meilisearch-image-upsert.d.ts.map +1 -0
  22. package/.medusa/server/src/subscribers/meilisearch-image-upsert.js +29 -0
  23. package/.medusa/server/src/subscribers/meilisearch-inventory-delete.d.ts +6 -0
  24. package/.medusa/server/src/subscribers/meilisearch-inventory-delete.d.ts.map +1 -0
  25. package/.medusa/server/src/subscribers/meilisearch-inventory-delete.js +27 -0
  26. package/.medusa/server/src/subscribers/meilisearch-inventory-level-delete.d.ts +6 -0
  27. package/.medusa/server/src/subscribers/meilisearch-inventory-level-delete.d.ts.map +1 -0
  28. package/.medusa/server/src/subscribers/meilisearch-inventory-level-delete.js +27 -0
  29. package/.medusa/server/src/subscribers/meilisearch-inventory-level-upsert.d.ts +6 -0
  30. package/.medusa/server/src/subscribers/meilisearch-inventory-level-upsert.d.ts.map +1 -0
  31. package/.medusa/server/src/subscribers/meilisearch-inventory-level-upsert.js +29 -0
  32. package/.medusa/server/src/subscribers/meilisearch-inventory-upsert.d.ts +6 -0
  33. package/.medusa/server/src/subscribers/meilisearch-inventory-upsert.d.ts.map +1 -0
  34. package/.medusa/server/src/subscribers/meilisearch-inventory-upsert.js +29 -0
  35. package/.medusa/server/src/subscribers/meilisearch-option-delete.d.ts +6 -0
  36. package/.medusa/server/src/subscribers/meilisearch-option-delete.d.ts.map +1 -0
  37. package/.medusa/server/src/subscribers/meilisearch-option-delete.js +27 -0
  38. package/.medusa/server/src/subscribers/meilisearch-option-upsert.d.ts +6 -0
  39. package/.medusa/server/src/subscribers/meilisearch-option-upsert.d.ts.map +1 -0
  40. package/.medusa/server/src/subscribers/meilisearch-option-upsert.js +29 -0
  41. package/.medusa/server/src/subscribers/meilisearch-option-value-delete.d.ts +6 -0
  42. package/.medusa/server/src/subscribers/meilisearch-option-value-delete.d.ts.map +1 -0
  43. package/.medusa/server/src/subscribers/meilisearch-option-value-delete.js +27 -0
  44. package/.medusa/server/src/subscribers/meilisearch-option-value-upsert.d.ts +6 -0
  45. package/.medusa/server/src/subscribers/meilisearch-option-value-upsert.d.ts.map +1 -0
  46. package/.medusa/server/src/subscribers/meilisearch-option-value-upsert.js +29 -0
  47. package/.medusa/server/src/subscribers/meilisearch-price-delete.d.ts +6 -0
  48. package/.medusa/server/src/subscribers/meilisearch-price-delete.d.ts.map +1 -0
  49. package/.medusa/server/src/subscribers/meilisearch-price-delete.js +27 -0
  50. package/.medusa/server/src/subscribers/meilisearch-price-upsert.d.ts +6 -0
  51. package/.medusa/server/src/subscribers/meilisearch-price-upsert.d.ts.map +1 -0
  52. package/.medusa/server/src/subscribers/meilisearch-price-upsert.js +29 -0
  53. package/.medusa/server/src/subscribers/meilisearch-product-delete.d.ts +6 -0
  54. package/.medusa/server/src/subscribers/meilisearch-product-delete.d.ts.map +1 -0
  55. package/.medusa/server/src/subscribers/meilisearch-product-delete.js +27 -0
  56. package/.medusa/server/src/subscribers/meilisearch-product-upsert.d.ts +6 -0
  57. package/.medusa/server/src/subscribers/meilisearch-product-upsert.d.ts.map +1 -0
  58. package/.medusa/server/src/subscribers/meilisearch-product-upsert.js +29 -0
  59. package/.medusa/server/src/subscribers/meilisearch-sync.d.ts.map +1 -1
  60. package/.medusa/server/src/subscribers/meilisearch-sync.js +15 -9
  61. package/.medusa/server/src/subscribers/meilisearch-tag-delete.d.ts +6 -0
  62. package/.medusa/server/src/subscribers/meilisearch-tag-delete.d.ts.map +1 -0
  63. package/.medusa/server/src/subscribers/meilisearch-tag-delete.js +27 -0
  64. package/.medusa/server/src/subscribers/meilisearch-tag-upsert.d.ts +6 -0
  65. package/.medusa/server/src/subscribers/meilisearch-tag-upsert.d.ts.map +1 -0
  66. package/.medusa/server/src/subscribers/meilisearch-tag-upsert.js +33 -0
  67. package/.medusa/server/src/subscribers/meilisearch-type-delete.d.ts +6 -0
  68. package/.medusa/server/src/subscribers/meilisearch-type-delete.d.ts.map +1 -0
  69. package/.medusa/server/src/subscribers/meilisearch-type-delete.js +27 -0
  70. package/.medusa/server/src/subscribers/meilisearch-type-upsert.d.ts +6 -0
  71. package/.medusa/server/src/subscribers/meilisearch-type-upsert.d.ts.map +1 -0
  72. package/.medusa/server/src/subscribers/meilisearch-type-upsert.js +33 -0
  73. package/.medusa/server/src/subscribers/meilisearch-variant-delete.d.ts +6 -0
  74. package/.medusa/server/src/subscribers/meilisearch-variant-delete.d.ts.map +1 -0
  75. package/.medusa/server/src/subscribers/meilisearch-variant-delete.js +27 -0
  76. package/.medusa/server/src/subscribers/meilisearch-variant-upsert.d.ts +6 -0
  77. package/.medusa/server/src/subscribers/meilisearch-variant-upsert.d.ts.map +1 -0
  78. package/.medusa/server/src/subscribers/meilisearch-variant-upsert.js +29 -0
  79. package/.medusa/server/src/workflows/delete-category.d.ts +6 -0
  80. package/.medusa/server/src/workflows/delete-category.d.ts.map +1 -0
  81. package/.medusa/server/src/workflows/delete-category.js +10 -0
  82. package/.medusa/server/src/workflows/delete-collection.d.ts +8 -0
  83. package/.medusa/server/src/workflows/delete-collection.d.ts.map +1 -0
  84. package/.medusa/server/src/workflows/delete-collection.js +10 -0
  85. package/.medusa/server/src/workflows/delete-inventory-level.d.ts +8 -0
  86. package/.medusa/server/src/workflows/delete-inventory-level.d.ts.map +1 -0
  87. package/.medusa/server/src/workflows/delete-inventory-level.js +10 -0
  88. package/.medusa/server/src/workflows/delete-inventory.d.ts +8 -0
  89. package/.medusa/server/src/workflows/delete-inventory.d.ts.map +1 -0
  90. package/.medusa/server/src/workflows/delete-inventory.js +10 -0
  91. package/.medusa/server/src/workflows/delete-option-value.d.ts +8 -0
  92. package/.medusa/server/src/workflows/delete-option-value.d.ts.map +1 -0
  93. package/.medusa/server/src/workflows/delete-option-value.js +10 -0
  94. package/.medusa/server/src/workflows/delete-option.d.ts +8 -0
  95. package/.medusa/server/src/workflows/delete-option.d.ts.map +1 -0
  96. package/.medusa/server/src/workflows/delete-option.js +10 -0
  97. package/.medusa/server/src/workflows/delete-price.d.ts +8 -0
  98. package/.medusa/server/src/workflows/delete-price.d.ts.map +1 -0
  99. package/.medusa/server/src/workflows/delete-price.js +10 -0
  100. package/.medusa/server/src/workflows/delete-product.d.ts +6 -0
  101. package/.medusa/server/src/workflows/delete-product.d.ts.map +1 -0
  102. package/.medusa/server/src/workflows/delete-product.js +10 -0
  103. package/.medusa/server/src/workflows/delete-tag.d.ts +8 -0
  104. package/.medusa/server/src/workflows/delete-tag.d.ts.map +1 -0
  105. package/.medusa/server/src/workflows/delete-tag.js +10 -0
  106. package/.medusa/server/src/workflows/delete-type.d.ts +8 -0
  107. package/.medusa/server/src/workflows/delete-type.d.ts.map +1 -0
  108. package/.medusa/server/src/workflows/delete-type.js +10 -0
  109. package/.medusa/server/src/workflows/delete-variant.d.ts +8 -0
  110. package/.medusa/server/src/workflows/delete-variant.d.ts.map +1 -0
  111. package/.medusa/server/src/workflows/delete-variant.js +12 -0
  112. package/.medusa/server/src/workflows/steps/delete-category.d.ts +2 -2
  113. package/.medusa/server/src/workflows/steps/delete-category.d.ts.map +1 -1
  114. package/.medusa/server/src/workflows/steps/delete-category.js +4 -4
  115. package/.medusa/server/src/workflows/steps/delete-collection.d.ts +8 -0
  116. package/.medusa/server/src/workflows/steps/delete-collection.d.ts.map +1 -0
  117. package/.medusa/server/src/workflows/steps/delete-collection.js +88 -0
  118. package/.medusa/server/src/workflows/steps/delete-inventory-level.d.ts +8 -0
  119. package/.medusa/server/src/workflows/steps/delete-inventory-level.d.ts.map +1 -0
  120. package/.medusa/server/src/workflows/steps/delete-inventory-level.js +107 -0
  121. package/.medusa/server/src/workflows/steps/delete-inventory.d.ts +8 -0
  122. package/.medusa/server/src/workflows/steps/delete-inventory.d.ts.map +1 -0
  123. package/.medusa/server/src/workflows/steps/delete-inventory.js +78 -0
  124. package/.medusa/server/src/workflows/steps/delete-option-value.d.ts +8 -0
  125. package/.medusa/server/src/workflows/steps/delete-option-value.d.ts.map +1 -0
  126. package/.medusa/server/src/workflows/steps/delete-option-value.js +92 -0
  127. package/.medusa/server/src/workflows/steps/delete-option.d.ts +8 -0
  128. package/.medusa/server/src/workflows/steps/delete-option.d.ts.map +1 -0
  129. package/.medusa/server/src/workflows/steps/delete-option.js +89 -0
  130. package/.medusa/server/src/workflows/steps/delete-price.d.ts +8 -0
  131. package/.medusa/server/src/workflows/steps/delete-price.d.ts.map +1 -0
  132. package/.medusa/server/src/workflows/steps/delete-price.js +106 -0
  133. package/.medusa/server/src/workflows/steps/delete-product.d.ts +4 -2
  134. package/.medusa/server/src/workflows/steps/delete-product.d.ts.map +1 -1
  135. package/.medusa/server/src/workflows/steps/delete-product.js +6 -4
  136. package/.medusa/server/src/workflows/steps/delete-tag.d.ts +8 -0
  137. package/.medusa/server/src/workflows/steps/delete-tag.d.ts.map +1 -0
  138. package/.medusa/server/src/workflows/steps/delete-tag.js +88 -0
  139. package/.medusa/server/src/workflows/steps/delete-type.d.ts +8 -0
  140. package/.medusa/server/src/workflows/steps/delete-type.d.ts.map +1 -0
  141. package/.medusa/server/src/workflows/steps/delete-type.js +88 -0
  142. package/.medusa/server/src/workflows/steps/delete-variant.d.ts +8 -0
  143. package/.medusa/server/src/workflows/steps/delete-variant.d.ts.map +1 -0
  144. package/.medusa/server/src/workflows/steps/delete-variant.js +91 -0
  145. package/.medusa/server/src/workflows/steps/sync-categories.d.ts.map +1 -1
  146. package/.medusa/server/src/workflows/steps/sync-categories.js +3 -2
  147. package/.medusa/server/src/workflows/steps/sync-products.d.ts.map +1 -1
  148. package/.medusa/server/src/workflows/steps/sync-products.js +37 -3
  149. package/.medusa/server/src/workflows/steps/upsert-category.d.ts +1 -1
  150. package/.medusa/server/src/workflows/steps/upsert-category.d.ts.map +1 -1
  151. package/.medusa/server/src/workflows/steps/upsert-category.js +5 -4
  152. package/.medusa/server/src/workflows/steps/upsert-collection.d.ts +8 -0
  153. package/.medusa/server/src/workflows/steps/upsert-collection.d.ts.map +1 -0
  154. package/.medusa/server/src/workflows/steps/upsert-collection.js +71 -0
  155. package/.medusa/server/src/workflows/steps/upsert-image.d.ts +8 -0
  156. package/.medusa/server/src/workflows/steps/upsert-image.d.ts.map +1 -0
  157. package/.medusa/server/src/workflows/steps/upsert-image.js +72 -0
  158. package/.medusa/server/src/workflows/steps/upsert-inventory-level.d.ts +8 -0
  159. package/.medusa/server/src/workflows/steps/upsert-inventory-level.d.ts.map +1 -0
  160. package/.medusa/server/src/workflows/steps/upsert-inventory-level.js +88 -0
  161. package/.medusa/server/src/workflows/steps/upsert-inventory.d.ts +8 -0
  162. package/.medusa/server/src/workflows/steps/upsert-inventory.d.ts.map +1 -0
  163. package/.medusa/server/src/workflows/steps/upsert-inventory.js +79 -0
  164. package/.medusa/server/src/workflows/steps/upsert-option-value.d.ts +8 -0
  165. package/.medusa/server/src/workflows/steps/upsert-option-value.d.ts.map +1 -0
  166. package/.medusa/server/src/workflows/steps/upsert-option-value.js +77 -0
  167. package/.medusa/server/src/workflows/steps/upsert-option.d.ts +8 -0
  168. package/.medusa/server/src/workflows/steps/upsert-option.d.ts.map +1 -0
  169. package/.medusa/server/src/workflows/steps/upsert-option.js +69 -0
  170. package/.medusa/server/src/workflows/steps/upsert-price.d.ts +8 -0
  171. package/.medusa/server/src/workflows/steps/upsert-price.d.ts.map +1 -0
  172. package/.medusa/server/src/workflows/steps/upsert-price.js +86 -0
  173. package/.medusa/server/src/workflows/steps/upsert-product.d.ts +1 -1
  174. package/.medusa/server/src/workflows/steps/upsert-product.d.ts.map +1 -1
  175. package/.medusa/server/src/workflows/steps/upsert-product.js +39 -5
  176. package/.medusa/server/src/workflows/steps/upsert-tag.d.ts +8 -0
  177. package/.medusa/server/src/workflows/steps/upsert-tag.d.ts.map +1 -0
  178. package/.medusa/server/src/workflows/steps/upsert-tag.js +70 -0
  179. package/.medusa/server/src/workflows/steps/upsert-type.d.ts +8 -0
  180. package/.medusa/server/src/workflows/steps/upsert-type.d.ts.map +1 -0
  181. package/.medusa/server/src/workflows/steps/upsert-type.js +63 -0
  182. package/.medusa/server/src/workflows/steps/upsert-variant.d.ts +8 -0
  183. package/.medusa/server/src/workflows/steps/upsert-variant.d.ts.map +1 -0
  184. package/.medusa/server/src/workflows/steps/upsert-variant.js +72 -0
  185. package/.medusa/server/src/workflows/sync-categories.d.ts.map +1 -1
  186. package/.medusa/server/src/workflows/sync-categories.js +3 -3
  187. package/.medusa/server/src/workflows/sync-products.d.ts.map +1 -1
  188. package/.medusa/server/src/workflows/sync-products.js +1 -1
  189. package/.medusa/server/src/workflows/upsert-category.d.ts +8 -0
  190. package/.medusa/server/src/workflows/upsert-category.d.ts.map +1 -0
  191. package/.medusa/server/src/workflows/upsert-category.js +10 -0
  192. package/.medusa/server/src/workflows/upsert-collection.d.ts +8 -0
  193. package/.medusa/server/src/workflows/upsert-collection.d.ts.map +1 -0
  194. package/.medusa/server/src/workflows/upsert-collection.js +10 -0
  195. package/.medusa/server/src/workflows/upsert-image.d.ts +8 -0
  196. package/.medusa/server/src/workflows/upsert-image.d.ts.map +1 -0
  197. package/.medusa/server/src/workflows/upsert-image.js +10 -0
  198. package/.medusa/server/src/workflows/upsert-inventory-level.d.ts +8 -0
  199. package/.medusa/server/src/workflows/upsert-inventory-level.d.ts.map +1 -0
  200. package/.medusa/server/src/workflows/upsert-inventory-level.js +10 -0
  201. package/.medusa/server/src/workflows/upsert-inventory.d.ts +8 -0
  202. package/.medusa/server/src/workflows/upsert-inventory.d.ts.map +1 -0
  203. package/.medusa/server/src/workflows/upsert-inventory.js +10 -0
  204. package/.medusa/server/src/workflows/upsert-option-value.d.ts +8 -0
  205. package/.medusa/server/src/workflows/upsert-option-value.d.ts.map +1 -0
  206. package/.medusa/server/src/workflows/upsert-option-value.js +10 -0
  207. package/.medusa/server/src/workflows/upsert-option.d.ts +8 -0
  208. package/.medusa/server/src/workflows/upsert-option.d.ts.map +1 -0
  209. package/.medusa/server/src/workflows/upsert-option.js +10 -0
  210. package/.medusa/server/src/workflows/upsert-price.d.ts +8 -0
  211. package/.medusa/server/src/workflows/upsert-price.d.ts.map +1 -0
  212. package/.medusa/server/src/workflows/upsert-price.js +10 -0
  213. package/.medusa/server/src/workflows/upsert-product.d.ts +8 -0
  214. package/.medusa/server/src/workflows/upsert-product.d.ts.map +1 -0
  215. package/.medusa/server/src/workflows/upsert-product.js +12 -0
  216. package/.medusa/server/src/workflows/upsert-tag.d.ts +8 -0
  217. package/.medusa/server/src/workflows/upsert-tag.d.ts.map +1 -0
  218. package/.medusa/server/src/workflows/upsert-tag.js +10 -0
  219. package/.medusa/server/src/workflows/upsert-type.d.ts +8 -0
  220. package/.medusa/server/src/workflows/upsert-type.d.ts.map +1 -0
  221. package/.medusa/server/src/workflows/upsert-type.js +10 -0
  222. package/.medusa/server/src/workflows/upsert-variant.d.ts +8 -0
  223. package/.medusa/server/src/workflows/upsert-variant.d.ts.map +1 -0
  224. package/.medusa/server/src/workflows/upsert-variant.js +12 -0
  225. package/README.md +511 -511
  226. package/package.json +25 -26
  227. package/.medusa/server/src/subscribers/meilisearch-category-created.d.ts +0 -6
  228. package/.medusa/server/src/subscribers/meilisearch-category-created.d.ts.map +0 -1
  229. package/.medusa/server/src/subscribers/meilisearch-category-created.js +0 -14
  230. package/.medusa/server/src/subscribers/meilisearch-category-deleted.d.ts +0 -6
  231. package/.medusa/server/src/subscribers/meilisearch-category-deleted.d.ts.map +0 -1
  232. package/.medusa/server/src/subscribers/meilisearch-category-deleted.js +0 -14
  233. package/.medusa/server/src/subscribers/meilisearch-category-updated.d.ts +0 -6
  234. package/.medusa/server/src/subscribers/meilisearch-category-updated.d.ts.map +0 -1
  235. package/.medusa/server/src/subscribers/meilisearch-category-updated.js +0 -14
  236. package/.medusa/server/src/subscribers/meilisearch-product-created.d.ts +0 -6
  237. package/.medusa/server/src/subscribers/meilisearch-product-created.d.ts.map +0 -1
  238. package/.medusa/server/src/subscribers/meilisearch-product-created.js +0 -19
  239. package/.medusa/server/src/subscribers/meilisearch-product-deleted.d.ts +0 -6
  240. package/.medusa/server/src/subscribers/meilisearch-product-deleted.d.ts.map +0 -1
  241. package/.medusa/server/src/subscribers/meilisearch-product-deleted.js +0 -19
  242. package/.medusa/server/src/subscribers/meilisearch-product-updated.d.ts +0 -6
  243. package/.medusa/server/src/subscribers/meilisearch-product-updated.d.ts.map +0 -1
  244. package/.medusa/server/src/subscribers/meilisearch-product-updated.js +0 -19
  245. package/.medusa/server/src/workflows/category-created.d.ts +0 -7
  246. package/.medusa/server/src/workflows/category-created.d.ts.map +0 -1
  247. package/.medusa/server/src/workflows/category-created.js +0 -10
  248. package/.medusa/server/src/workflows/category-deleted.d.ts +0 -7
  249. package/.medusa/server/src/workflows/category-deleted.d.ts.map +0 -1
  250. package/.medusa/server/src/workflows/category-deleted.js +0 -10
  251. package/.medusa/server/src/workflows/category-updated.d.ts +0 -7
  252. package/.medusa/server/src/workflows/category-updated.d.ts.map +0 -1
  253. package/.medusa/server/src/workflows/category-updated.js +0 -10
  254. package/.medusa/server/src/workflows/product-created.d.ts +0 -8
  255. package/.medusa/server/src/workflows/product-created.d.ts.map +0 -1
  256. package/.medusa/server/src/workflows/product-created.js +0 -12
  257. package/.medusa/server/src/workflows/product-deleted.d.ts +0 -6
  258. package/.medusa/server/src/workflows/product-deleted.d.ts.map +0 -1
  259. package/.medusa/server/src/workflows/product-deleted.js +0 -10
  260. package/.medusa/server/src/workflows/product-updated.d.ts +0 -8
  261. package/.medusa/server/src/workflows/product-updated.d.ts.map +0 -1
  262. package/.medusa/server/src/workflows/product-updated.js +0 -12
package/README.md CHANGED
@@ -1,511 +1,511 @@
1
- # MedusaJS v2 MeiliSearch Plugin with i18n Support
2
-
3
- This plugin integrates MeiliSearch with your Medusa e-commerce store and adds support for internationalization (i18n) of your product catalog.
4
-
5
- ## Features
6
-
7
- - Full-text search for your Medusa store
8
- - Real-time indexing
9
- - Typo-tolerance
10
- - Faceted search
11
- - Support for both products and categories
12
- - Internationalization (i18n) support with multiple strategies:
13
- 1. Separate index per language
14
- 2. Language-specific fields with suffix
15
- - Flexible translation configuration
16
- - Custom field transformations
17
- - Automatic field detection
18
-
19
- ## Installation
20
-
21
- Run the following command to install the plugin with **npm**:
22
-
23
- ```bash
24
- npm install --save @rokmohar/medusa-plugin-meilisearch
25
- ```
26
-
27
- Or with **yarn**:
28
-
29
- ```bash
30
- yarn add @rokmohar/medusa-plugin-meilisearch
31
- ```
32
-
33
- ### Upgrade to v1.0
34
-
35
- _This step is required only if you are upgrading from previous version to v1.0._
36
-
37
- - The plugin now supports new MedusaJS plugin system.
38
- - Subscribers are included in the plugin.
39
- - You don't need custom subscribers anymore, you can remove them.
40
-
41
- ## ⚠️ MedusaJS v2.4.0 or newer
42
-
43
- This plugin is only for MedusaJS v2.4.0 or newer.
44
-
45
- If you are using MedusaJS v2.3.1 or older, please use the [older version of this plugin](https://github.com/rokmohar/medusa-plugin-meilisearch/tree/v0.2.1).
46
-
47
- ## Configuration
48
-
49
- Add the plugin to your `medusa-config.ts` file:
50
-
51
- ```js
52
- import { loadEnv, defineConfig } from '@medusajs/framework/utils'
53
- import { MeilisearchPluginOptions } from '@rokmohar/medusa-plugin-meilisearch'
54
-
55
- loadEnv(process.env.NODE_ENV || 'development', process.cwd())
56
-
57
- module.exports = defineConfig({
58
- // ... other config
59
- plugins: [
60
- // ... other plugins
61
- {
62
- resolve: '@rokmohar/medusa-plugin-meilisearch',
63
- options: {
64
- config: {
65
- host: process.env.MEILISEARCH_HOST ?? '',
66
- apiKey: process.env.MEILISEARCH_API_KEY ?? '',
67
- },
68
- settings: {
69
- // The key is used as the index name in Meilisearch
70
- products: {
71
- // Required: Index type
72
- type: 'products',
73
- // Optional: Whether the index is enabled. When disabled:
74
- // - Index won't be created or updated
75
- // - Documents won't be added or removed
76
- // - Index won't be included in searches
77
- // - All operations will be silently skipped
78
- enabled: true,
79
- // Optional: Specify which fields to include in the index
80
- // If not specified, all fields will be included
81
- fields: ['id', 'title', 'description', 'handle', 'variant_sku', 'thumbnail'],
82
- indexSettings: {
83
- searchableAttributes: ['title', 'description', 'variant_sku'],
84
- displayedAttributes: ['id', 'handle', 'title', 'description', 'variant_sku', 'thumbnail'],
85
- filterableAttributes: ['id', 'handle'],
86
- },
87
- primaryKey: 'id',
88
- // Create your own transformer
89
- /*transformer: (product) => ({
90
- id: product.id,
91
- // other attributes...
92
- }),*/
93
- },
94
- categories: {
95
- // Required: Index type
96
- type: 'categories',
97
- // Optional: Whether the index is enabled
98
- enabled: true,
99
- // Optional: Specify which fields to include in the index
100
- // If not specified, all fields will be included
101
- fields: ['id', 'name', 'description', 'handle', 'is_active', 'parent_id'],
102
- indexSettings: {
103
- searchableAttributes: ['name', 'description'],
104
- displayedAttributes: ['id', 'name', 'description', 'handle', 'is_active', 'parent_id'],
105
- filterableAttributes: ['id', 'handle', 'is_active', 'parent_id'],
106
- },
107
- primaryKey: 'id',
108
- // Create your own transformer
109
- /*transformer: (category) => ({
110
- id: category.id,
111
- name: category.name,
112
- // other attributes...
113
- }),*/
114
- },
115
- },
116
- i18n: {
117
- // Choose one of the following strategies:
118
-
119
- // 1. Separate index per language
120
- // strategy: 'separate-index',
121
- // languages: ['en', 'fr', 'de'],
122
- // defaultLanguage: 'en',
123
-
124
- // 2. Language-specific fields with suffix
125
- strategy: 'field-suffix',
126
- languages: ['en', 'fr', 'de'],
127
- defaultLanguage: 'en',
128
- translatableFields: ['title', 'description'],
129
- },
130
- } satisfies MeilisearchPluginOptions,
131
- },
132
- ],
133
- })
134
- ```
135
-
136
- ### ⚠️ Worker Mode Considerations
137
-
138
- > **Important:** Product events and background tasks will **not work** if your Medusa instance is running in `server` mode, because the server instance does **not** process subscribers or background jobs.
139
-
140
- Depending on your setup:
141
-
142
- - **Monolithic architecture** (only one backend instance):
143
- Ensure you **do not set** the `MEDUSA_WORKER_MODE` or `WORKER_MODE` environment variable. By default, Medusa will use `shared` mode, which supports both background processing and serving HTTP requests from the same instance.
144
-
145
- - **Split architecture** (separate server and worker instances):
146
- Follow the [official Medusa documentation on worker mode](https://docs.medusajs.com/learn/production/worker-mode#content).
147
- In this case, you **must add this plugin in the worker instance**, as the server instance does not handle event subscribers or background tasks.
148
-
149
- ## i18n Configuration
150
-
151
- The plugin supports two main strategies for handling translations, with flexible configuration options for each.
152
-
153
- ### Basic Configuration
154
-
155
- ```typescript
156
- {
157
- i18n: {
158
- // Choose strategy: 'separate-index' or 'field-suffix'
159
- strategy: 'field-suffix',
160
- // List of supported languages
161
- languages: ['en', 'fr', 'de'],
162
- // Default language to fall back to
163
- defaultLanguage: 'en',
164
- // Optional: List of translatable fields
165
- translatableFields: ['title', 'description', 'handle']
166
- }
167
- }
168
- ```
169
-
170
- ### Advanced Field Configuration
171
-
172
- You can provide detailed configuration for each translatable field:
173
-
174
- ```typescript
175
- {
176
- i18n: {
177
- strategy: 'field-suffix',
178
- languages: ['en', 'fr', 'de'],
179
- defaultLanguage: 'en',
180
- translatableFields: [
181
- // Simple field name
182
- 'title',
183
-
184
- // Field with different target name
185
- {
186
- source: 'description',
187
- target: 'content' // Will be indexed as content_en, content_fr, etc.
188
- },
189
-
190
- // Field with transformation
191
- {
192
- source: 'handle',
193
- transform: (value) => value.toLowerCase().replace(/\s+/g, '-')
194
- }
195
- ]
196
- }
197
- }
198
- ```
199
-
200
- ### Custom Translation Transformer
201
-
202
- The plugin provides a flexible way to transform your products with custom translations. Instead of relying on specific storage formats, you can provide translations directly to the transformer:
203
-
204
- ```typescript
205
- import { transformProduct } from '@rokmohar/medusa-plugin-meilisearch'
206
-
207
- const getProductTranslations = async (productId: string) => {
208
- // Example: fetch from your translation service/database
209
- return {
210
- title: [
211
- { language_code: 'en', value: 'Blue T-Shirt' },
212
- { language_code: 'fr', value: 'T-Shirt Bleu' },
213
- ],
214
- description: [
215
- { language_code: 'en', value: 'A comfortable blue t-shirt' },
216
- { language_code: 'fr', value: 'Un t-shirt bleu confortable' },
217
- ],
218
- }
219
- }
220
-
221
- // Example usage in your custom transformer
222
- const customTransformer = async (product, options) => {
223
- const translations = await getProductTranslations(product.id)
224
-
225
- return transformProduct(product, {
226
- ...options,
227
- translations,
228
- })
229
- }
230
- ```
231
-
232
- ### Integration with Tolgee
233
-
234
- For production environments, you'll often want to integrate with external translation management platforms. Here's an example of integrating with [Tolgee](https://tolgee.io/), a popular translations management platform:
235
-
236
- ```typescript
237
- import { default as axios } from 'axios'
238
- import { logger } from '@medusajs/framework'
239
- import { TranslationMap } from '@rokmohar/medusa-plugin-meilisearch'
240
-
241
- type TranslationsHttpResponse = {
242
- [lang: string]: {
243
- [id: string]: Record<string, string>
244
- }
245
- }
246
-
247
- const options = {
248
- apiKey: process.env.TOLGEE_API_KEY ?? '',
249
- baseURL: process.env.TOLGEE_API_URL ?? '',
250
- projectId: process.env.TOLGEE_PROJECT_ID ?? '',
251
- }
252
-
253
- const httpClient = axios.create({
254
- baseURL: `${options.baseURL}/v2/projects/${options.projectId}`,
255
- headers: {
256
- Accept: 'application/json',
257
- 'X-API-Key': options.apiKey,
258
- },
259
- maxBodyLength: Infinity,
260
- })
261
-
262
- export const getTranslations = async (id: string, langs: string[]) => {
263
- const translations: TranslationMap = {}
264
-
265
- try {
266
- const response = await httpClient.get<TranslationsHttpResponse>(`/translations/${langs.join(',')}?ns=${id}`)
267
- Object.entries(response.data).forEach(([language_code, { [id]: values }]) => {
268
- Object.entries(values).forEach(([key, value]) => {
269
- if (!(key in translations)) {
270
- translations[key] = []
271
- }
272
- translations[key].push({ language_code, value })
273
- })
274
- })
275
- } catch (e) {
276
- logger.error(e)
277
- }
278
-
279
- return translations
280
- }
281
- ```
282
-
283
- Usage in your transformer configuration:
284
-
285
- ```typescript
286
- {
287
- settings: {
288
- products: {
289
- type: 'products',
290
- // ... other config
291
- transformer: async (product, defaultTransformer, options) => {
292
- const translations = await getTranslations(product.id, ['sl', 'en'])
293
- return defaultTransformer(product, {
294
- ...options,
295
- translations,
296
- includeAllTranslations: true
297
- })
298
- },
299
- }
300
- }
301
- }
302
- ```
303
-
304
- This integration fetches translations from Tolgee's API and transforms them into the format expected by this plugin. For complete storefront translation management, consider using the [medusa-plugin-tolgee](https://github.com/SteelRazor47/medusa-plugin-tolgee) by SteelRazor47, which provides comprehensive translation management features including admin widgets.
305
-
306
- ## i18n Strategies
307
-
308
- ### 1. Separate Index per Language
309
-
310
- This strategy creates a separate MeiliSearch index for each language. For example, if your base index is named "products", it will create:
311
-
312
- - products_en
313
- - products_fr
314
- - products_de
315
-
316
- Benefits:
317
-
318
- - Better performance for language-specific searches
319
- - Language-specific settings and ranking rules
320
- - Cleaner index structure
321
-
322
- ### 2. Language-specific Fields with Suffix
323
-
324
- This strategy adds language suffixes to translatable fields in the same index. For example:
325
-
326
- - title_en, title_fr, title_de
327
- - description_en, description_fr, description_de
328
-
329
- Benefits:
330
-
331
- - Single index to maintain
332
- - Ability to search across all languages at once
333
- - Smaller storage requirements
334
-
335
- ## Custom Translatable Fields
336
-
337
- If no translatable fields are specified and using the field-suffix strategy, the plugin will automatically detect string fields as translatable. You can override this by explicitly specifying the fields:
338
-
339
- ```typescript
340
- {
341
- i18n: {
342
- strategy: 'field-suffix',
343
- languages: ['en', 'fr'],
344
- defaultLanguage: 'en',
345
- // Only these fields will be translatable
346
- translatableFields: ['title', 'description']
347
- }
348
- }
349
- ```
350
-
351
- ## Product API Endpoints
352
-
353
- ### Search for Product Hits
354
-
355
- ```http
356
- GET /store/meilisearch/products-hits
357
- ```
358
-
359
- Query Parameters:
360
-
361
- - `query`: Search query string
362
- - `limit`: (Optional) Limit results from search
363
- - `offset`: (Optional) Offset results from search
364
- - `language`: (Optional) Language code
365
- - `semanticSearch` - Enable AI-powered semantic search (boolean)
366
- - `semanticRatio` - Semantic vs keyword search ratio (0-1)
367
-
368
- ### Search for Products
369
-
370
- ```http
371
- GET /store/meilisearch/products
372
- ```
373
-
374
- Query Parameters:
375
-
376
- - `fields` - MedusaJS fields expression
377
- - `limit`: (Optional) Limit results from search
378
- - `offset`: (Optional) Offset results from search
379
- - `region_id`: (Optional, but required for `calculated_price`) Current region ID
380
- - `currency_code`: (Optional, but required for `calculated_price`) Current currency code
381
- - `query`: Search query string
382
- - `language`: (Optional) Language code
383
- - `semanticSearch` - Enable AI-powered semantic search (boolean)
384
- - `semanticRatio` - Semantic vs keyword search ratio (0-1)
385
-
386
- ## Category Support
387
-
388
- This plugin provides full support for MedusaJS v2 categories, including:
389
-
390
- - Real-time indexing of category changes
391
- - i18n support for category names and descriptions
392
- - Hierarchical category structure support with parent-child relationships
393
- - Custom category field transformations
394
-
395
- ### Category Configuration Example
396
-
397
- ```typescript
398
- {
399
- settings: {
400
- categories: {
401
- type: 'categories',
402
- enabled: true,
403
- fields: ['id', 'name', 'description', 'handle', 'is_active', 'parent_id'],
404
- indexSettings: {
405
- searchableAttributes: ['name', 'description'],
406
- displayedAttributes: ['id', 'name', 'description', 'handle', 'is_active', 'parent_id'],
407
- filterableAttributes: ['id', 'handle', 'is_active', 'parent_id'],
408
- },
409
- primaryKey: 'id',
410
- },
411
- },
412
- i18n: {
413
- strategy: 'field-suffix',
414
- languages: ['en', 'fr', 'de'],
415
- defaultLanguage: 'en',
416
- translatableFields: ['name', 'description'], // Category-specific translatable fields
417
- },
418
- }
419
- ```
420
-
421
- ### Category API Endpoints
422
-
423
- ### Search for Category Hits
424
-
425
- ```http
426
- GET /store/meilisearch/categories-hits
427
- ```
428
-
429
- Query Parameters:
430
-
431
- - `query`: Search query string
432
- - `limit`: (Optional) Limit results from search
433
- - `offset`: (Optional) Offset results from search
434
- - `language`: (Optional) Language code
435
- - `semanticSearch` - Enable AI-powered semantic search (boolean)
436
- - `semanticRatio` - Semantic vs keyword search ratio (0-1)
437
-
438
- ### Search for Categories
439
-
440
- ```http
441
- GET /store/meilisearch/categories
442
- ```
443
-
444
- Query Parameters:
445
-
446
- - `fields` - MedusaJS fields expression
447
- - `limit`: (Optional) Limit results from search
448
- - `offset`: (Optional) Offset results from search
449
- - `query`: Search query string
450
- - `language`: (Optional) Language code
451
- - `semanticSearch` - Enable AI-powered semantic search (boolean)
452
- - `semanticRatio` - Semantic vs keyword search ratio (0-1)
453
-
454
- ## AI-Powered Semantic Search
455
-
456
- This plugin supports AI-powered semantic search using vector embeddings. See [docs/semantic-search.md](docs/semantic-search.md) for detailed configuration and usage instructions.
457
-
458
- ## ENV variables
459
-
460
- Add the environment variables to your `.env` and `.env.template` file:
461
-
462
- ```env
463
- # ... others vars
464
- MEILISEARCH_HOST=
465
- MEILISEARCH_API_KEY=
466
- ```
467
-
468
- If you want to use with the `docker-compose` from this README, use the following values:
469
-
470
- ```env
471
- # ... others vars
472
- MEILISEARCH_HOST=http://127.0.0.1:7700
473
- MEILISEARCH_API_KEY=ms
474
- ```
475
-
476
- ## docker-compose
477
-
478
- You can add the following configuration for Meilisearch to your `docker-compose.yml`:
479
-
480
- ```yml
481
- services:
482
- # ... other services
483
-
484
- meilisearch:
485
- image: getmeili/meilisearch:latest
486
- ports:
487
- - '7700:7700'
488
- volumes:
489
- - ~/data.ms:/data.ms
490
- environment:
491
- - MEILI_MASTER_KEY=ms
492
- healthcheck:
493
- test: ['CMD', 'curl', '-f', 'http://localhost:7700']
494
- interval: 10s
495
- timeout: 5s
496
- retries: 5
497
- ```
498
-
499
- ## Add search to Medusa NextJS starter
500
-
501
- You can find instructions on how to add search to a Medusa NextJS starter inside the [nextjs](nextjs) folder.
502
-
503
- ## FAQ
504
-
505
- - [How do I include product categories and tags in my search index?](docs/faq-product-categories-and-tags.md)
506
- - [How do I include product variant prices (min_price, max_price) in my search index?](docs/faq-product-variant-prices.md)
507
- - [How do I include prices in the search response from the search endpoint?](docs/faq-product-search-prices.md)
508
-
509
- ## Contributing
510
-
511
- Feel free to open issues and pull requests!
1
+ # MedusaJS v2 MeiliSearch Plugin with i18n Support
2
+
3
+ This plugin integrates MeiliSearch with your Medusa e-commerce store and adds support for internationalization (i18n) of your product catalog.
4
+
5
+ ## Features
6
+
7
+ - Full-text search for your Medusa store
8
+ - Real-time indexing
9
+ - Typo-tolerance
10
+ - Faceted search
11
+ - Support for both products and categories
12
+ - Internationalization (i18n) support with multiple strategies:
13
+ 1. Separate index per language
14
+ 2. Language-specific fields with suffix
15
+ - Flexible translation configuration
16
+ - Custom field transformations
17
+ - Automatic field detection
18
+
19
+ ## Installation
20
+
21
+ Run the following command to install the plugin with **npm**:
22
+
23
+ ```bash
24
+ npm install --save @rokmohar/medusa-plugin-meilisearch
25
+ ```
26
+
27
+ Or with **yarn**:
28
+
29
+ ```bash
30
+ yarn add @rokmohar/medusa-plugin-meilisearch
31
+ ```
32
+
33
+ ### Upgrade to v1.0
34
+
35
+ _This step is required only if you are upgrading from previous version to v1.0._
36
+
37
+ - The plugin now supports new MedusaJS plugin system.
38
+ - Subscribers are included in the plugin.
39
+ - You don't need custom subscribers anymore, you can remove them.
40
+
41
+ ## ⚠️ MedusaJS v2.4.0 or newer
42
+
43
+ This plugin is only for MedusaJS v2.4.0 or newer.
44
+
45
+ If you are using MedusaJS v2.3.1 or older, please use the [older version of this plugin](https://github.com/rokmohar/medusa-plugin-meilisearch/tree/v0.2.1).
46
+
47
+ ## Configuration
48
+
49
+ Add the plugin to your `medusa-config.ts` file:
50
+
51
+ ```js
52
+ import { loadEnv, defineConfig } from '@medusajs/framework/utils'
53
+ import { MeilisearchPluginOptions } from '@rokmohar/medusa-plugin-meilisearch'
54
+
55
+ loadEnv(process.env.NODE_ENV || 'development', process.cwd())
56
+
57
+ module.exports = defineConfig({
58
+ // ... other config
59
+ plugins: [
60
+ // ... other plugins
61
+ {
62
+ resolve: '@rokmohar/medusa-plugin-meilisearch',
63
+ options: {
64
+ config: {
65
+ host: process.env.MEILISEARCH_HOST ?? '',
66
+ apiKey: process.env.MEILISEARCH_API_KEY ?? '',
67
+ },
68
+ settings: {
69
+ // The key is used as the index name in Meilisearch
70
+ products: {
71
+ // Required: Index type
72
+ type: 'products',
73
+ // Optional: Whether the index is enabled. When disabled:
74
+ // - Index won't be created or updated
75
+ // - Documents won't be added or removed
76
+ // - Index won't be included in searches
77
+ // - All operations will be silently skipped
78
+ enabled: true,
79
+ // Optional: Specify which fields to include in the index
80
+ // If not specified, all fields will be included
81
+ fields: ['id', 'title', 'description', 'handle', 'variant_sku', 'thumbnail'],
82
+ indexSettings: {
83
+ searchableAttributes: ['title', 'description', 'variant_sku'],
84
+ displayedAttributes: ['id', 'handle', 'title', 'description', 'variant_sku', 'thumbnail'],
85
+ filterableAttributes: ['id', 'handle'],
86
+ },
87
+ primaryKey: 'id',
88
+ // Create your own transformer
89
+ /*transformer: (product) => ({
90
+ id: product.id,
91
+ // other attributes...
92
+ }),*/
93
+ },
94
+ categories: {
95
+ // Required: Index type
96
+ type: 'categories',
97
+ // Optional: Whether the index is enabled
98
+ enabled: true,
99
+ // Optional: Specify which fields to include in the index
100
+ // If not specified, all fields will be included
101
+ fields: ['id', 'name', 'description', 'handle', 'is_active', 'parent_id'],
102
+ indexSettings: {
103
+ searchableAttributes: ['name', 'description'],
104
+ displayedAttributes: ['id', 'name', 'description', 'handle', 'is_active', 'parent_id'],
105
+ filterableAttributes: ['id', 'handle', 'is_active', 'parent_id'],
106
+ },
107
+ primaryKey: 'id',
108
+ // Create your own transformer
109
+ /*transformer: (category) => ({
110
+ id: category.id,
111
+ name: category.name,
112
+ // other attributes...
113
+ }),*/
114
+ },
115
+ },
116
+ i18n: {
117
+ // Choose one of the following strategies:
118
+
119
+ // 1. Separate index per language
120
+ // strategy: 'separate-index',
121
+ // languages: ['en', 'fr', 'de'],
122
+ // defaultLanguage: 'en',
123
+
124
+ // 2. Language-specific fields with suffix
125
+ strategy: 'field-suffix',
126
+ languages: ['en', 'fr', 'de'],
127
+ defaultLanguage: 'en',
128
+ translatableFields: ['title', 'description'],
129
+ },
130
+ } satisfies MeilisearchPluginOptions,
131
+ },
132
+ ],
133
+ })
134
+ ```
135
+
136
+ ### ⚠️ Worker Mode Considerations
137
+
138
+ > **Important:** Product events and background tasks will **not work** if your Medusa instance is running in `server` mode, because the server instance does **not** process subscribers or background jobs.
139
+
140
+ Depending on your setup:
141
+
142
+ - **Monolithic architecture** (only one backend instance):
143
+ Ensure you **do not set** the `MEDUSA_WORKER_MODE` or `WORKER_MODE` environment variable. By default, Medusa will use `shared` mode, which supports both background processing and serving HTTP requests from the same instance.
144
+
145
+ - **Split architecture** (separate server and worker instances):
146
+ Follow the [official Medusa documentation on worker mode](https://docs.medusajs.com/learn/production/worker-mode#content).
147
+ In this case, you **must add this plugin in the worker instance**, as the server instance does not handle event subscribers or background tasks.
148
+
149
+ ## i18n Configuration
150
+
151
+ The plugin supports two main strategies for handling translations, with flexible configuration options for each.
152
+
153
+ ### Basic Configuration
154
+
155
+ ```typescript
156
+ {
157
+ i18n: {
158
+ // Choose strategy: 'separate-index' or 'field-suffix'
159
+ strategy: 'field-suffix',
160
+ // List of supported languages
161
+ languages: ['en', 'fr', 'de'],
162
+ // Default language to fall back to
163
+ defaultLanguage: 'en',
164
+ // Optional: List of translatable fields
165
+ translatableFields: ['title', 'description', 'handle']
166
+ }
167
+ }
168
+ ```
169
+
170
+ ### Advanced Field Configuration
171
+
172
+ You can provide detailed configuration for each translatable field:
173
+
174
+ ```typescript
175
+ {
176
+ i18n: {
177
+ strategy: 'field-suffix',
178
+ languages: ['en', 'fr', 'de'],
179
+ defaultLanguage: 'en',
180
+ translatableFields: [
181
+ // Simple field name
182
+ 'title',
183
+
184
+ // Field with different target name
185
+ {
186
+ source: 'description',
187
+ target: 'content' // Will be indexed as content_en, content_fr, etc.
188
+ },
189
+
190
+ // Field with transformation
191
+ {
192
+ source: 'handle',
193
+ transform: (value) => value.toLowerCase().replace(/\s+/g, '-')
194
+ }
195
+ ]
196
+ }
197
+ }
198
+ ```
199
+
200
+ ### Custom Translation Transformer
201
+
202
+ The plugin provides a flexible way to transform your products with custom translations. Instead of relying on specific storage formats, you can provide translations directly to the transformer:
203
+
204
+ ```typescript
205
+ import { transformProduct } from '@rokmohar/medusa-plugin-meilisearch'
206
+
207
+ const getProductTranslations = async (productId: string) => {
208
+ // Example: fetch from your translation service/database
209
+ return {
210
+ title: [
211
+ { language_code: 'en', value: 'Blue T-Shirt' },
212
+ { language_code: 'fr', value: 'T-Shirt Bleu' },
213
+ ],
214
+ description: [
215
+ { language_code: 'en', value: 'A comfortable blue t-shirt' },
216
+ { language_code: 'fr', value: 'Un t-shirt bleu confortable' },
217
+ ],
218
+ }
219
+ }
220
+
221
+ // Example usage in your custom transformer
222
+ const customTransformer = async (product, options) => {
223
+ const translations = await getProductTranslations(product.id)
224
+
225
+ return transformProduct(product, {
226
+ ...options,
227
+ translations,
228
+ })
229
+ }
230
+ ```
231
+
232
+ ### Integration with Tolgee
233
+
234
+ For production environments, you'll often want to integrate with external translation management platforms. Here's an example of integrating with [Tolgee](https://tolgee.io/), a popular translations management platform:
235
+
236
+ ```typescript
237
+ import { default as axios } from 'axios'
238
+ import { logger } from '@medusajs/framework'
239
+ import { TranslationMap } from '@rokmohar/medusa-plugin-meilisearch'
240
+
241
+ type TranslationsHttpResponse = {
242
+ [lang: string]: {
243
+ [id: string]: Record<string, string>
244
+ }
245
+ }
246
+
247
+ const options = {
248
+ apiKey: process.env.TOLGEE_API_KEY ?? '',
249
+ baseURL: process.env.TOLGEE_API_URL ?? '',
250
+ projectId: process.env.TOLGEE_PROJECT_ID ?? '',
251
+ }
252
+
253
+ const httpClient = axios.create({
254
+ baseURL: `${options.baseURL}/v2/projects/${options.projectId}`,
255
+ headers: {
256
+ Accept: 'application/json',
257
+ 'X-API-Key': options.apiKey,
258
+ },
259
+ maxBodyLength: Infinity,
260
+ })
261
+
262
+ export const getTranslations = async (id: string, langs: string[]) => {
263
+ const translations: TranslationMap = {}
264
+
265
+ try {
266
+ const response = await httpClient.get<TranslationsHttpResponse>(`/translations/${langs.join(',')}?ns=${id}`)
267
+ Object.entries(response.data).forEach(([language_code, { [id]: values }]) => {
268
+ Object.entries(values).forEach(([key, value]) => {
269
+ if (!(key in translations)) {
270
+ translations[key] = []
271
+ }
272
+ translations[key].push({ language_code, value })
273
+ })
274
+ })
275
+ } catch (e) {
276
+ logger.error(e)
277
+ }
278
+
279
+ return translations
280
+ }
281
+ ```
282
+
283
+ Usage in your transformer configuration:
284
+
285
+ ```typescript
286
+ {
287
+ settings: {
288
+ products: {
289
+ type: 'products',
290
+ // ... other config
291
+ transformer: async (product, defaultTransformer, options) => {
292
+ const translations = await getTranslations(product.id, ['sl', 'en'])
293
+ return defaultTransformer(product, {
294
+ ...options,
295
+ translations,
296
+ includeAllTranslations: true
297
+ })
298
+ },
299
+ }
300
+ }
301
+ }
302
+ ```
303
+
304
+ This integration fetches translations from Tolgee's API and transforms them into the format expected by this plugin. For complete storefront translation management, consider using the [medusa-plugin-tolgee](https://github.com/SteelRazor47/medusa-plugin-tolgee) by SteelRazor47, which provides comprehensive translation management features including admin widgets.
305
+
306
+ ## i18n Strategies
307
+
308
+ ### 1. Separate Index per Language
309
+
310
+ This strategy creates a separate MeiliSearch index for each language. For example, if your base index is named "products", it will create:
311
+
312
+ - products_en
313
+ - products_fr
314
+ - products_de
315
+
316
+ Benefits:
317
+
318
+ - Better performance for language-specific searches
319
+ - Language-specific settings and ranking rules
320
+ - Cleaner index structure
321
+
322
+ ### 2. Language-specific Fields with Suffix
323
+
324
+ This strategy adds language suffixes to translatable fields in the same index. For example:
325
+
326
+ - title_en, title_fr, title_de
327
+ - description_en, description_fr, description_de
328
+
329
+ Benefits:
330
+
331
+ - Single index to maintain
332
+ - Ability to search across all languages at once
333
+ - Smaller storage requirements
334
+
335
+ ## Custom Translatable Fields
336
+
337
+ If no translatable fields are specified and using the field-suffix strategy, the plugin will automatically detect string fields as translatable. You can override this by explicitly specifying the fields:
338
+
339
+ ```typescript
340
+ {
341
+ i18n: {
342
+ strategy: 'field-suffix',
343
+ languages: ['en', 'fr'],
344
+ defaultLanguage: 'en',
345
+ // Only these fields will be translatable
346
+ translatableFields: ['title', 'description']
347
+ }
348
+ }
349
+ ```
350
+
351
+ ## Product API Endpoints
352
+
353
+ ### Search for Product Hits
354
+
355
+ ```http
356
+ GET /store/meilisearch/products-hits
357
+ ```
358
+
359
+ Query Parameters:
360
+
361
+ - `query`: Search query string
362
+ - `limit`: (Optional) Limit results from search
363
+ - `offset`: (Optional) Offset results from search
364
+ - `language`: (Optional) Language code
365
+ - `semanticSearch` - Enable AI-powered semantic search (boolean)
366
+ - `semanticRatio` - Semantic vs keyword search ratio (0-1)
367
+
368
+ ### Search for Products
369
+
370
+ ```http
371
+ GET /store/meilisearch/products
372
+ ```
373
+
374
+ Query Parameters:
375
+
376
+ - `fields` - MedusaJS fields expression
377
+ - `limit`: (Optional) Limit results from search
378
+ - `offset`: (Optional) Offset results from search
379
+ - `region_id`: (Optional, but required for `calculated_price`) Current region ID
380
+ - `currency_code`: (Optional, but required for `calculated_price`) Current currency code
381
+ - `query`: Search query string
382
+ - `language`: (Optional) Language code
383
+ - `semanticSearch` - Enable AI-powered semantic search (boolean)
384
+ - `semanticRatio` - Semantic vs keyword search ratio (0-1)
385
+
386
+ ## Category Support
387
+
388
+ This plugin provides full support for MedusaJS v2 categories, including:
389
+
390
+ - Real-time indexing of category changes
391
+ - i18n support for category names and descriptions
392
+ - Hierarchical category structure support with parent-child relationships
393
+ - Custom category field transformations
394
+
395
+ ### Category Configuration Example
396
+
397
+ ```typescript
398
+ {
399
+ settings: {
400
+ categories: {
401
+ type: 'categories',
402
+ enabled: true,
403
+ fields: ['id', 'name', 'description', 'handle', 'is_active', 'parent_id'],
404
+ indexSettings: {
405
+ searchableAttributes: ['name', 'description'],
406
+ displayedAttributes: ['id', 'name', 'description', 'handle', 'is_active', 'parent_id'],
407
+ filterableAttributes: ['id', 'handle', 'is_active', 'parent_id'],
408
+ },
409
+ primaryKey: 'id',
410
+ },
411
+ },
412
+ i18n: {
413
+ strategy: 'field-suffix',
414
+ languages: ['en', 'fr', 'de'],
415
+ defaultLanguage: 'en',
416
+ translatableFields: ['name', 'description'], // Category-specific translatable fields
417
+ },
418
+ }
419
+ ```
420
+
421
+ ### Category API Endpoints
422
+
423
+ ### Search for Category Hits
424
+
425
+ ```http
426
+ GET /store/meilisearch/categories-hits
427
+ ```
428
+
429
+ Query Parameters:
430
+
431
+ - `query`: Search query string
432
+ - `limit`: (Optional) Limit results from search
433
+ - `offset`: (Optional) Offset results from search
434
+ - `language`: (Optional) Language code
435
+ - `semanticSearch` - Enable AI-powered semantic search (boolean)
436
+ - `semanticRatio` - Semantic vs keyword search ratio (0-1)
437
+
438
+ ### Search for Categories
439
+
440
+ ```http
441
+ GET /store/meilisearch/categories
442
+ ```
443
+
444
+ Query Parameters:
445
+
446
+ - `fields` - MedusaJS fields expression
447
+ - `limit`: (Optional) Limit results from search
448
+ - `offset`: (Optional) Offset results from search
449
+ - `query`: Search query string
450
+ - `language`: (Optional) Language code
451
+ - `semanticSearch` - Enable AI-powered semantic search (boolean)
452
+ - `semanticRatio` - Semantic vs keyword search ratio (0-1)
453
+
454
+ ## AI-Powered Semantic Search
455
+
456
+ This plugin supports AI-powered semantic search using vector embeddings. See [docs/semantic-search.md](docs/semantic-search.md) for detailed configuration and usage instructions.
457
+
458
+ ## ENV variables
459
+
460
+ Add the environment variables to your `.env` and `.env.template` file:
461
+
462
+ ```env
463
+ # ... others vars
464
+ MEILISEARCH_HOST=
465
+ MEILISEARCH_API_KEY=
466
+ ```
467
+
468
+ If you want to use with the `docker-compose` from this README, use the following values:
469
+
470
+ ```env
471
+ # ... others vars
472
+ MEILISEARCH_HOST=http://127.0.0.1:7700
473
+ MEILISEARCH_API_KEY=ms
474
+ ```
475
+
476
+ ## docker-compose
477
+
478
+ You can add the following configuration for Meilisearch to your `docker-compose.yml`:
479
+
480
+ ```yml
481
+ services:
482
+ # ... other services
483
+
484
+ meilisearch:
485
+ image: getmeili/meilisearch:latest
486
+ ports:
487
+ - '7700:7700'
488
+ volumes:
489
+ - ~/data.ms:/data.ms
490
+ environment:
491
+ - MEILI_MASTER_KEY=ms
492
+ healthcheck:
493
+ test: ['CMD', 'curl', '-f', 'http://localhost:7700']
494
+ interval: 10s
495
+ timeout: 5s
496
+ retries: 5
497
+ ```
498
+
499
+ ## Add search to Medusa NextJS starter
500
+
501
+ You can find instructions on how to add search to a Medusa NextJS starter inside the [nextjs](nextjs) folder.
502
+
503
+ ## FAQ
504
+
505
+ - [How do I include product categories and tags in my search index?](docs/faq-product-categories-and-tags.md)
506
+ - [How do I include product variant prices (min_price, max_price) in my search index?](docs/faq-product-variant-prices.md)
507
+ - [How do I include prices in the search response from the search endpoint?](docs/faq-product-search-prices.md)
508
+
509
+ ## Contributing
510
+
511
+ Feel free to open issues and pull requests!