@floxiz/medusa-plugin-meilisearch 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/src/admin/index.js +266 -0
- package/.medusa/server/src/admin/index.mjs +265 -0
- package/.medusa/server/src/api/admin/meilisearch/categories-hits/route.d.ts +32 -0
- package/.medusa/server/src/api/admin/meilisearch/categories-hits/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/meilisearch/categories-hits/route.js +46 -0
- package/.medusa/server/src/api/admin/meilisearch/products-hits/route.d.ts +32 -0
- package/.medusa/server/src/api/admin/meilisearch/products-hits/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/meilisearch/products-hits/route.js +49 -0
- package/.medusa/server/src/api/admin/meilisearch/sync/route.d.ts +6 -0
- package/.medusa/server/src/api/admin/meilisearch/sync/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/meilisearch/sync/route.js +15 -0
- package/.medusa/server/src/api/admin/meilisearch/vector-status/route.d.ts +11 -0
- package/.medusa/server/src/api/admin/meilisearch/vector-status/route.d.ts.map +1 -0
- package/.medusa/server/src/api/admin/meilisearch/vector-status/route.js +11 -0
- package/.medusa/server/src/api/middlewares.d.ts +3 -0
- package/.medusa/server/src/api/middlewares.d.ts.map +1 -0
- package/.medusa/server/src/api/middlewares.js +44 -0
- package/.medusa/server/src/api/store/meilisearch/categories/route.d.ts +37 -0
- package/.medusa/server/src/api/store/meilisearch/categories/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/meilisearch/categories/route.js +105 -0
- package/.medusa/server/src/api/store/meilisearch/categories-hits/route.d.ts +32 -0
- package/.medusa/server/src/api/store/meilisearch/categories-hits/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/meilisearch/categories-hits/route.js +49 -0
- package/.medusa/server/src/api/store/meilisearch/products/route.d.ts +43 -0
- package/.medusa/server/src/api/store/meilisearch/products/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/meilisearch/products/route.js +118 -0
- package/.medusa/server/src/api/store/meilisearch/products-hits/route.d.ts +32 -0
- package/.medusa/server/src/api/store/meilisearch/products-hits/route.d.ts.map +1 -0
- package/.medusa/server/src/api/store/meilisearch/products-hits/route.js +49 -0
- package/.medusa/server/src/index.d.ts +3 -0
- package/.medusa/server/src/index.d.ts.map +1 -0
- package/.medusa/server/src/index.js +19 -0
- package/.medusa/server/src/jobs/meilisearch-categories-index.d.ts +5 -0
- package/.medusa/server/src/jobs/meilisearch-categories-index.d.ts.map +1 -0
- package/.medusa/server/src/jobs/meilisearch-categories-index.js +19 -0
- package/.medusa/server/src/jobs/meilisearch-products-index.d.ts +5 -0
- package/.medusa/server/src/jobs/meilisearch-products-index.d.ts.map +1 -0
- package/.medusa/server/src/jobs/meilisearch-products-index.js +19 -0
- package/.medusa/server/src/models/CronJobConfig.d.ts +7 -0
- package/.medusa/server/src/models/CronJobConfig.d.ts.map +1 -0
- package/.medusa/server/src/models/CronJobConfig.js +3 -0
- package/.medusa/server/src/modules/meilisearch/index.d.ts +9 -0
- package/.medusa/server/src/modules/meilisearch/index.d.ts.map +1 -0
- package/.medusa/server/src/modules/meilisearch/index.js +31 -0
- package/.medusa/server/src/modules/meilisearch/loaders/index.d.ts +5 -0
- package/.medusa/server/src/modules/meilisearch/loaders/index.d.ts.map +1 -0
- package/.medusa/server/src/modules/meilisearch/loaders/index.js +18 -0
- package/.medusa/server/src/modules/meilisearch/services/index.d.ts +2 -0
- package/.medusa/server/src/modules/meilisearch/services/index.d.ts.map +1 -0
- package/.medusa/server/src/modules/meilisearch/services/index.js +18 -0
- package/.medusa/server/src/modules/meilisearch/services/meilisearch.d.ts +52 -0
- package/.medusa/server/src/modules/meilisearch/services/meilisearch.d.ts.map +1 -0
- package/.medusa/server/src/modules/meilisearch/services/meilisearch.js +177 -0
- package/.medusa/server/src/modules/meilisearch/types/index.d.ts +3 -0
- package/.medusa/server/src/modules/meilisearch/types/index.d.ts.map +1 -0
- package/.medusa/server/src/modules/meilisearch/types/index.js +19 -0
- package/.medusa/server/src/modules/meilisearch/types/meilisearch.d.ts +127 -0
- package/.medusa/server/src/modules/meilisearch/types/meilisearch.d.ts.map +1 -0
- package/.medusa/server/src/modules/meilisearch/types/meilisearch.js +7 -0
- package/.medusa/server/src/modules/meilisearch/types/translation.d.ts +64 -0
- package/.medusa/server/src/modules/meilisearch/types/translation.d.ts.map +1 -0
- package/.medusa/server/src/modules/meilisearch/types/translation.js +36 -0
- package/.medusa/server/src/modules/meilisearch/utils/embedder.d.ts +54 -0
- package/.medusa/server/src/modules/meilisearch/utils/embedder.d.ts.map +1 -0
- package/.medusa/server/src/modules/meilisearch/utils/embedder.js +151 -0
- package/.medusa/server/src/modules/meilisearch/utils/transformer.d.ts +8 -0
- package/.medusa/server/src/modules/meilisearch/utils/transformer.d.ts.map +1 -0
- package/.medusa/server/src/modules/meilisearch/utils/transformer.js +121 -0
- package/.medusa/server/src/subscribers/meilisearch-category-created.d.ts +6 -0
- package/.medusa/server/src/subscribers/meilisearch-category-created.d.ts.map +1 -0
- package/.medusa/server/src/subscribers/meilisearch-category-created.js +14 -0
- package/.medusa/server/src/subscribers/meilisearch-category-deleted.d.ts +6 -0
- package/.medusa/server/src/subscribers/meilisearch-category-deleted.d.ts.map +1 -0
- package/.medusa/server/src/subscribers/meilisearch-category-deleted.js +14 -0
- package/.medusa/server/src/subscribers/meilisearch-category-updated.d.ts +6 -0
- package/.medusa/server/src/subscribers/meilisearch-category-updated.d.ts.map +1 -0
- package/.medusa/server/src/subscribers/meilisearch-category-updated.js +14 -0
- package/.medusa/server/src/subscribers/meilisearch-product-created.d.ts +6 -0
- package/.medusa/server/src/subscribers/meilisearch-product-created.d.ts.map +1 -0
- package/.medusa/server/src/subscribers/meilisearch-product-created.js +19 -0
- package/.medusa/server/src/subscribers/meilisearch-product-deleted.d.ts +6 -0
- package/.medusa/server/src/subscribers/meilisearch-product-deleted.d.ts.map +1 -0
- package/.medusa/server/src/subscribers/meilisearch-product-deleted.js +19 -0
- package/.medusa/server/src/subscribers/meilisearch-product-updated.d.ts +6 -0
- package/.medusa/server/src/subscribers/meilisearch-product-updated.d.ts.map +1 -0
- package/.medusa/server/src/subscribers/meilisearch-product-updated.js +19 -0
- package/.medusa/server/src/subscribers/meilisearch-sync.d.ts +4 -0
- package/.medusa/server/src/subscribers/meilisearch-sync.d.ts.map +1 -0
- package/.medusa/server/src/subscribers/meilisearch-sync.js +22 -0
- package/.medusa/server/src/workflows/category-created.d.ts +7 -0
- package/.medusa/server/src/workflows/category-created.d.ts.map +1 -0
- package/.medusa/server/src/workflows/category-created.js +10 -0
- package/.medusa/server/src/workflows/category-deleted.d.ts +7 -0
- package/.medusa/server/src/workflows/category-deleted.d.ts.map +1 -0
- package/.medusa/server/src/workflows/category-deleted.js +10 -0
- package/.medusa/server/src/workflows/category-updated.d.ts +7 -0
- package/.medusa/server/src/workflows/category-updated.d.ts.map +1 -0
- package/.medusa/server/src/workflows/category-updated.js +10 -0
- package/.medusa/server/src/workflows/product-created.d.ts +8 -0
- package/.medusa/server/src/workflows/product-created.d.ts.map +1 -0
- package/.medusa/server/src/workflows/product-created.js +12 -0
- package/.medusa/server/src/workflows/product-deleted.d.ts +6 -0
- package/.medusa/server/src/workflows/product-deleted.d.ts.map +1 -0
- package/.medusa/server/src/workflows/product-deleted.js +10 -0
- package/.medusa/server/src/workflows/product-updated.d.ts +8 -0
- package/.medusa/server/src/workflows/product-updated.d.ts.map +1 -0
- package/.medusa/server/src/workflows/product-updated.js +12 -0
- package/.medusa/server/src/workflows/steps/delete-category.d.ts +8 -0
- package/.medusa/server/src/workflows/steps/delete-category.d.ts.map +1 -0
- package/.medusa/server/src/workflows/steps/delete-category.js +14 -0
- package/.medusa/server/src/workflows/steps/delete-product.d.ts +6 -0
- package/.medusa/server/src/workflows/steps/delete-product.d.ts.map +1 -0
- package/.medusa/server/src/workflows/steps/delete-product.js +13 -0
- package/.medusa/server/src/workflows/steps/sync-categories.d.ts +10 -0
- package/.medusa/server/src/workflows/steps/sync-categories.d.ts.map +1 -0
- package/.medusa/server/src/workflows/steps/sync-categories.js +78 -0
- package/.medusa/server/src/workflows/steps/sync-products.d.ts +10 -0
- package/.medusa/server/src/workflows/steps/sync-products.d.ts.map +1 -0
- package/.medusa/server/src/workflows/steps/sync-products.js +79 -0
- package/.medusa/server/src/workflows/steps/upsert-category.d.ts +8 -0
- package/.medusa/server/src/workflows/steps/upsert-category.d.ts.map +1 -0
- package/.medusa/server/src/workflows/steps/upsert-category.js +28 -0
- package/.medusa/server/src/workflows/steps/upsert-product.d.ts +8 -0
- package/.medusa/server/src/workflows/steps/upsert-product.d.ts.map +1 -0
- package/.medusa/server/src/workflows/steps/upsert-product.js +29 -0
- package/.medusa/server/src/workflows/sync-categories.d.ts +10 -0
- package/.medusa/server/src/workflows/sync-categories.d.ts.map +1 -0
- package/.medusa/server/src/workflows/sync-categories.js +13 -0
- package/.medusa/server/src/workflows/sync-products.d.ts +11 -0
- package/.medusa/server/src/workflows/sync-products.d.ts.map +1 -0
- package/.medusa/server/src/workflows/sync-products.js +13 -0
- package/README.md +511 -0
- package/package.json +76 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
3
|
+
const react = require("react");
|
|
4
|
+
const ui = require("@medusajs/ui");
|
|
5
|
+
const reactQuery = require("@tanstack/react-query");
|
|
6
|
+
const adminSdk = require("@medusajs/admin-sdk");
|
|
7
|
+
const Medusa = require("@medusajs/js-sdk");
|
|
8
|
+
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
9
|
+
const Medusa__default = /* @__PURE__ */ _interopDefault(Medusa);
|
|
10
|
+
const sdk = new Medusa__default.default({
|
|
11
|
+
baseUrl: __BACKEND_URL__ || "/",
|
|
12
|
+
auth: {
|
|
13
|
+
type: "session"
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
const SyncPage = () => {
|
|
17
|
+
const [semanticSearchEnabled, setSemanticSearchEnabled] = react.useState(false);
|
|
18
|
+
const [semanticRatio, setSemanticRatio] = react.useState(0.5);
|
|
19
|
+
const [searchQuery, setSearchQuery] = react.useState("jeans");
|
|
20
|
+
const {
|
|
21
|
+
data: vectorStatus,
|
|
22
|
+
isLoading: statusLoading,
|
|
23
|
+
error: statusError,
|
|
24
|
+
refetch: refetchStatus
|
|
25
|
+
} = reactQuery.useQuery({
|
|
26
|
+
queryKey: ["meilisearch-vector-status"],
|
|
27
|
+
queryFn: async () => sdk.client.fetch("/admin/meilisearch/vector-status"),
|
|
28
|
+
retry: 2,
|
|
29
|
+
staleTime: 3e4
|
|
30
|
+
// Consider data stale after 30 seconds
|
|
31
|
+
});
|
|
32
|
+
const { mutate: syncData, isPending: syncPending } = reactQuery.useMutation({
|
|
33
|
+
mutationFn: () => sdk.client.fetch("/admin/meilisearch/sync", {
|
|
34
|
+
method: "POST"
|
|
35
|
+
}),
|
|
36
|
+
onSuccess: () => {
|
|
37
|
+
ui.toast.success("Successfully triggered data sync to Meilisearch");
|
|
38
|
+
},
|
|
39
|
+
onError: (err) => {
|
|
40
|
+
console.error(err);
|
|
41
|
+
ui.toast.error("Failed to sync data to Meilisearch");
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
const { mutate: searchProducts, isPending: searchProductsPending } = reactQuery.useMutation({
|
|
45
|
+
mutationFn: async () => {
|
|
46
|
+
if (!searchQuery.trim()) {
|
|
47
|
+
throw new Error("Search query cannot be empty");
|
|
48
|
+
}
|
|
49
|
+
return sdk.client.fetch("/admin/meilisearch/products-hits", {
|
|
50
|
+
method: "POST",
|
|
51
|
+
body: {
|
|
52
|
+
query: searchQuery.trim(),
|
|
53
|
+
semanticSearch: semanticSearchEnabled,
|
|
54
|
+
semanticRatio,
|
|
55
|
+
limit: 5,
|
|
56
|
+
offset: 0
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
onSuccess: (data) => {
|
|
61
|
+
const hybridInfo = data.hybridSearch ? ` (hybrid search with ratio ${data.semanticRatio})` : "";
|
|
62
|
+
ui.toast.success(`Search successful. Found ${data.hits.length} products${hybridInfo}`);
|
|
63
|
+
},
|
|
64
|
+
onError: (err) => {
|
|
65
|
+
console.error("Search error:", err);
|
|
66
|
+
ui.toast.error(err.message || "Search failed");
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
const { mutate: searchCategories, isPending: searchCategoriesPending } = reactQuery.useMutation({
|
|
70
|
+
mutationFn: async () => {
|
|
71
|
+
if (!searchQuery.trim()) {
|
|
72
|
+
throw new Error("Search query cannot be empty");
|
|
73
|
+
}
|
|
74
|
+
return sdk.client.fetch("/admin/meilisearch/categories-hits", {
|
|
75
|
+
method: "POST",
|
|
76
|
+
body: {
|
|
77
|
+
query: searchQuery.trim(),
|
|
78
|
+
semanticSearch: semanticSearchEnabled,
|
|
79
|
+
semanticRatio,
|
|
80
|
+
limit: 5,
|
|
81
|
+
offset: 0
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
},
|
|
85
|
+
onSuccess: (data) => {
|
|
86
|
+
const hybridInfo = data.hybridSearch ? ` (hybrid search with ratio ${data.semanticRatio})` : "";
|
|
87
|
+
ui.toast.success(`Search successful. Found ${data.hits.length} categories${hybridInfo}`);
|
|
88
|
+
},
|
|
89
|
+
onError: (err) => {
|
|
90
|
+
console.error("Search error:", err);
|
|
91
|
+
ui.toast.error(err.message || "Search failed");
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const handleSync = () => {
|
|
95
|
+
syncData();
|
|
96
|
+
};
|
|
97
|
+
const handleSearchProducts = () => {
|
|
98
|
+
searchProducts();
|
|
99
|
+
};
|
|
100
|
+
const handleSearchCategories = () => {
|
|
101
|
+
searchCategories();
|
|
102
|
+
};
|
|
103
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-6", children: [
|
|
104
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
105
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Meilisearch Configuration" }),
|
|
106
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-gray-500 mt-2", children: "Manage your Meilisearch index synchronization and AI-powered semantic search settings." })
|
|
107
|
+
] }),
|
|
108
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border border-gray-200 rounded-lg p-6", children: [
|
|
109
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
110
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
111
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "AI-Powered Semantic Search" }),
|
|
112
|
+
statusLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { children: "Loading..." }) : statusError ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "red", children: "Error" }) : (vectorStatus == null ? void 0 : vectorStatus.enabled) ? /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "green", children: "Enabled" }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "grey", children: "Disabled" })
|
|
113
|
+
] }),
|
|
114
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "secondary", size: "small", onClick: () => refetchStatus(), isLoading: statusLoading, children: "Refresh Status" })
|
|
115
|
+
] }),
|
|
116
|
+
statusError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4 p-3 bg-red-50 border border-red-200 rounded-md", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-red-800 text-sm", children: [
|
|
117
|
+
"Failed to load vector search status: ",
|
|
118
|
+
statusError.message
|
|
119
|
+
] }) }),
|
|
120
|
+
(vectorStatus == null ? void 0 : vectorStatus.enabled) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-4 mb-4", children: [
|
|
121
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
122
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm font-medium text-gray-700", children: "Provider" }),
|
|
123
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-600", children: vectorStatus.provider || "Not specified" })
|
|
124
|
+
] }),
|
|
125
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
126
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm font-medium text-gray-700", children: "Model" }),
|
|
127
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-600", children: vectorStatus.model || "Not specified" })
|
|
128
|
+
] }),
|
|
129
|
+
vectorStatus.dimensions && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
130
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm font-medium text-gray-700", children: "Vector Dimensions" }),
|
|
131
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-600", children: vectorStatus.dimensions })
|
|
132
|
+
] }),
|
|
133
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
134
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm font-medium text-gray-700", children: "Embedding Fields" }),
|
|
135
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-600", children: vectorStatus.embeddingFields.join(", ") })
|
|
136
|
+
] })
|
|
137
|
+
] }),
|
|
138
|
+
(vectorStatus == null ? void 0 : vectorStatus.enabled) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
139
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
140
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
141
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium", children: "Enable Semantic Search in Tests" }),
|
|
142
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-500", children: "Use AI-powered semantic search for better results" })
|
|
143
|
+
] }),
|
|
144
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { checked: semanticSearchEnabled, onCheckedChange: setSemanticSearchEnabled })
|
|
145
|
+
] }),
|
|
146
|
+
semanticSearchEnabled && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
147
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "font-medium mb-2", children: [
|
|
148
|
+
"Semantic Ratio: ",
|
|
149
|
+
semanticRatio
|
|
150
|
+
] }),
|
|
151
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-500 mb-3", children: "0.0 = Pure keyword search, 1.0 = Pure semantic search, 0.5 = Balanced hybrid" }),
|
|
152
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
153
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
154
|
+
ui.Input,
|
|
155
|
+
{
|
|
156
|
+
type: "range",
|
|
157
|
+
min: "0",
|
|
158
|
+
max: "1",
|
|
159
|
+
step: "0.1",
|
|
160
|
+
value: semanticRatio,
|
|
161
|
+
onChange: (e) => setSemanticRatio(parseFloat(e.target.value)),
|
|
162
|
+
className: "flex-1",
|
|
163
|
+
"aria-label": "Semantic search ratio",
|
|
164
|
+
"aria-describedby": "semantic-ratio-description"
|
|
165
|
+
}
|
|
166
|
+
),
|
|
167
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-gray-700", children: semanticRatio.toFixed(1) })
|
|
168
|
+
] }),
|
|
169
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { id: "semantic-ratio-description", className: "sr-only", children: "Adjust the balance between keyword and semantic search from 0 to 1" })
|
|
170
|
+
] })
|
|
171
|
+
] }),
|
|
172
|
+
!(vectorStatus == null ? void 0 : vectorStatus.enabled) && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-gray-500", children: "Vector search is not configured. Add vectorSearch configuration to your plugin options to enable AI-powered semantic search." })
|
|
173
|
+
] }),
|
|
174
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border border-gray-200 rounded-lg p-6", children: [
|
|
175
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3 mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Data Synchronization" }) }),
|
|
176
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-gray-500 mb-4", children: [
|
|
177
|
+
"Manually trigger synchronization of your product catalog with Meilisearch.",
|
|
178
|
+
(vectorStatus == null ? void 0 : vectorStatus.enabled) && " This will also generate embeddings for semantic search."
|
|
179
|
+
] }),
|
|
180
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { onClick: handleSync, isLoading: syncPending, variant: "primary", children: "Sync Now" })
|
|
181
|
+
] }),
|
|
182
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border border-gray-200 rounded-lg p-6", children: [
|
|
183
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3 mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Search Testing" }) }),
|
|
184
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-gray-500 mb-4", children: [
|
|
185
|
+
"Test your products search configuration with a custom query.",
|
|
186
|
+
(vectorStatus == null ? void 0 : vectorStatus.enabled) && " You can test both traditional keyword search and AI-powered semantic search."
|
|
187
|
+
] }),
|
|
188
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
189
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
190
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm font-medium text-gray-700 mb-2", children: "Search Query" }),
|
|
191
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
192
|
+
ui.Input,
|
|
193
|
+
{
|
|
194
|
+
value: searchQuery,
|
|
195
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
196
|
+
placeholder: "Enter search query (e.g., 'blue shirt', 'comfortable clothing')",
|
|
197
|
+
className: "w-full",
|
|
198
|
+
"aria-label": "Search query input",
|
|
199
|
+
"aria-describedby": "search-query-help"
|
|
200
|
+
}
|
|
201
|
+
),
|
|
202
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { id: "search-query-help", className: "sr-only", children: "Enter a search term to test the search functionality" })
|
|
203
|
+
] }),
|
|
204
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
205
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
206
|
+
ui.Button,
|
|
207
|
+
{
|
|
208
|
+
onClick: handleSearchProducts,
|
|
209
|
+
isLoading: searchProductsPending,
|
|
210
|
+
variant: "secondary",
|
|
211
|
+
disabled: !searchQuery.trim(),
|
|
212
|
+
children: "Search Products"
|
|
213
|
+
}
|
|
214
|
+
),
|
|
215
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
216
|
+
ui.Button,
|
|
217
|
+
{
|
|
218
|
+
onClick: handleSearchCategories,
|
|
219
|
+
isLoading: searchCategoriesPending,
|
|
220
|
+
variant: "secondary",
|
|
221
|
+
disabled: !searchQuery.trim(),
|
|
222
|
+
children: "Search Categories"
|
|
223
|
+
}
|
|
224
|
+
),
|
|
225
|
+
(vectorStatus == null ? void 0 : vectorStatus.enabled) && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-sm text-gray-500 self-center", children: semanticSearchEnabled ? `Using hybrid search (${Math.round(semanticRatio * 100)}% semantic)` : "Using keyword search only" })
|
|
226
|
+
] })
|
|
227
|
+
] })
|
|
228
|
+
] })
|
|
229
|
+
] }) });
|
|
230
|
+
};
|
|
231
|
+
const config = adminSdk.defineRouteConfig({
|
|
232
|
+
label: "Meilisearch"
|
|
233
|
+
});
|
|
234
|
+
const widgetModule = { widgets: [] };
|
|
235
|
+
const routeModule = {
|
|
236
|
+
routes: [
|
|
237
|
+
{
|
|
238
|
+
Component: SyncPage,
|
|
239
|
+
path: "/settings/meilisearch"
|
|
240
|
+
}
|
|
241
|
+
]
|
|
242
|
+
};
|
|
243
|
+
const menuItemModule = {
|
|
244
|
+
menuItems: [
|
|
245
|
+
{
|
|
246
|
+
label: config.label,
|
|
247
|
+
icon: void 0,
|
|
248
|
+
path: "/settings/meilisearch",
|
|
249
|
+
nested: void 0
|
|
250
|
+
}
|
|
251
|
+
]
|
|
252
|
+
};
|
|
253
|
+
const formModule = { customFields: {} };
|
|
254
|
+
const displayModule = {
|
|
255
|
+
displays: {}
|
|
256
|
+
};
|
|
257
|
+
const i18nModule = { resources: {} };
|
|
258
|
+
const plugin = {
|
|
259
|
+
widgetModule,
|
|
260
|
+
routeModule,
|
|
261
|
+
menuItemModule,
|
|
262
|
+
formModule,
|
|
263
|
+
displayModule,
|
|
264
|
+
i18nModule
|
|
265
|
+
};
|
|
266
|
+
module.exports = plugin;
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { toast, Container, Heading, Text, Badge, Button, Switch, Input } from "@medusajs/ui";
|
|
4
|
+
import { useQuery, useMutation } from "@tanstack/react-query";
|
|
5
|
+
import { defineRouteConfig } from "@medusajs/admin-sdk";
|
|
6
|
+
import Medusa from "@medusajs/js-sdk";
|
|
7
|
+
const sdk = new Medusa({
|
|
8
|
+
baseUrl: __BACKEND_URL__ || "/",
|
|
9
|
+
auth: {
|
|
10
|
+
type: "session"
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
const SyncPage = () => {
|
|
14
|
+
const [semanticSearchEnabled, setSemanticSearchEnabled] = useState(false);
|
|
15
|
+
const [semanticRatio, setSemanticRatio] = useState(0.5);
|
|
16
|
+
const [searchQuery, setSearchQuery] = useState("jeans");
|
|
17
|
+
const {
|
|
18
|
+
data: vectorStatus,
|
|
19
|
+
isLoading: statusLoading,
|
|
20
|
+
error: statusError,
|
|
21
|
+
refetch: refetchStatus
|
|
22
|
+
} = useQuery({
|
|
23
|
+
queryKey: ["meilisearch-vector-status"],
|
|
24
|
+
queryFn: async () => sdk.client.fetch("/admin/meilisearch/vector-status"),
|
|
25
|
+
retry: 2,
|
|
26
|
+
staleTime: 3e4
|
|
27
|
+
// Consider data stale after 30 seconds
|
|
28
|
+
});
|
|
29
|
+
const { mutate: syncData, isPending: syncPending } = useMutation({
|
|
30
|
+
mutationFn: () => sdk.client.fetch("/admin/meilisearch/sync", {
|
|
31
|
+
method: "POST"
|
|
32
|
+
}),
|
|
33
|
+
onSuccess: () => {
|
|
34
|
+
toast.success("Successfully triggered data sync to Meilisearch");
|
|
35
|
+
},
|
|
36
|
+
onError: (err) => {
|
|
37
|
+
console.error(err);
|
|
38
|
+
toast.error("Failed to sync data to Meilisearch");
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
const { mutate: searchProducts, isPending: searchProductsPending } = useMutation({
|
|
42
|
+
mutationFn: async () => {
|
|
43
|
+
if (!searchQuery.trim()) {
|
|
44
|
+
throw new Error("Search query cannot be empty");
|
|
45
|
+
}
|
|
46
|
+
return sdk.client.fetch("/admin/meilisearch/products-hits", {
|
|
47
|
+
method: "POST",
|
|
48
|
+
body: {
|
|
49
|
+
query: searchQuery.trim(),
|
|
50
|
+
semanticSearch: semanticSearchEnabled,
|
|
51
|
+
semanticRatio,
|
|
52
|
+
limit: 5,
|
|
53
|
+
offset: 0
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
onSuccess: (data) => {
|
|
58
|
+
const hybridInfo = data.hybridSearch ? ` (hybrid search with ratio ${data.semanticRatio})` : "";
|
|
59
|
+
toast.success(`Search successful. Found ${data.hits.length} products${hybridInfo}`);
|
|
60
|
+
},
|
|
61
|
+
onError: (err) => {
|
|
62
|
+
console.error("Search error:", err);
|
|
63
|
+
toast.error(err.message || "Search failed");
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
const { mutate: searchCategories, isPending: searchCategoriesPending } = useMutation({
|
|
67
|
+
mutationFn: async () => {
|
|
68
|
+
if (!searchQuery.trim()) {
|
|
69
|
+
throw new Error("Search query cannot be empty");
|
|
70
|
+
}
|
|
71
|
+
return sdk.client.fetch("/admin/meilisearch/categories-hits", {
|
|
72
|
+
method: "POST",
|
|
73
|
+
body: {
|
|
74
|
+
query: searchQuery.trim(),
|
|
75
|
+
semanticSearch: semanticSearchEnabled,
|
|
76
|
+
semanticRatio,
|
|
77
|
+
limit: 5,
|
|
78
|
+
offset: 0
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
onSuccess: (data) => {
|
|
83
|
+
const hybridInfo = data.hybridSearch ? ` (hybrid search with ratio ${data.semanticRatio})` : "";
|
|
84
|
+
toast.success(`Search successful. Found ${data.hits.length} categories${hybridInfo}`);
|
|
85
|
+
},
|
|
86
|
+
onError: (err) => {
|
|
87
|
+
console.error("Search error:", err);
|
|
88
|
+
toast.error(err.message || "Search failed");
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
const handleSync = () => {
|
|
92
|
+
syncData();
|
|
93
|
+
};
|
|
94
|
+
const handleSearchProducts = () => {
|
|
95
|
+
searchProducts();
|
|
96
|
+
};
|
|
97
|
+
const handleSearchCategories = () => {
|
|
98
|
+
searchCategories();
|
|
99
|
+
};
|
|
100
|
+
return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
|
|
101
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
102
|
+
/* @__PURE__ */ jsx(Heading, { level: "h1", children: "Meilisearch Configuration" }),
|
|
103
|
+
/* @__PURE__ */ jsx(Text, { className: "text-gray-500 mt-2", children: "Manage your Meilisearch index synchronization and AI-powered semantic search settings." })
|
|
104
|
+
] }),
|
|
105
|
+
/* @__PURE__ */ jsxs("div", { className: "border border-gray-200 rounded-lg p-6", children: [
|
|
106
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
107
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
108
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: "AI-Powered Semantic Search" }),
|
|
109
|
+
statusLoading ? /* @__PURE__ */ jsx(Badge, { children: "Loading..." }) : statusError ? /* @__PURE__ */ jsx(Badge, { color: "red", children: "Error" }) : (vectorStatus == null ? void 0 : vectorStatus.enabled) ? /* @__PURE__ */ jsx(Badge, { color: "green", children: "Enabled" }) : /* @__PURE__ */ jsx(Badge, { color: "grey", children: "Disabled" })
|
|
110
|
+
] }),
|
|
111
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", size: "small", onClick: () => refetchStatus(), isLoading: statusLoading, children: "Refresh Status" })
|
|
112
|
+
] }),
|
|
113
|
+
statusError && /* @__PURE__ */ jsx("div", { className: "mb-4 p-3 bg-red-50 border border-red-200 rounded-md", children: /* @__PURE__ */ jsxs(Text, { className: "text-red-800 text-sm", children: [
|
|
114
|
+
"Failed to load vector search status: ",
|
|
115
|
+
statusError.message
|
|
116
|
+
] }) }),
|
|
117
|
+
(vectorStatus == null ? void 0 : vectorStatus.enabled) && /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4 mb-4", children: [
|
|
118
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
119
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm font-medium text-gray-700", children: "Provider" }),
|
|
120
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm text-gray-600", children: vectorStatus.provider || "Not specified" })
|
|
121
|
+
] }),
|
|
122
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
123
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm font-medium text-gray-700", children: "Model" }),
|
|
124
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm text-gray-600", children: vectorStatus.model || "Not specified" })
|
|
125
|
+
] }),
|
|
126
|
+
vectorStatus.dimensions && /* @__PURE__ */ jsxs("div", { children: [
|
|
127
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm font-medium text-gray-700", children: "Vector Dimensions" }),
|
|
128
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm text-gray-600", children: vectorStatus.dimensions })
|
|
129
|
+
] }),
|
|
130
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
131
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm font-medium text-gray-700", children: "Embedding Fields" }),
|
|
132
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm text-gray-600", children: vectorStatus.embeddingFields.join(", ") })
|
|
133
|
+
] })
|
|
134
|
+
] }),
|
|
135
|
+
(vectorStatus == null ? void 0 : vectorStatus.enabled) && /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
136
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
137
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
138
|
+
/* @__PURE__ */ jsx(Text, { className: "font-medium", children: "Enable Semantic Search in Tests" }),
|
|
139
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm text-gray-500", children: "Use AI-powered semantic search for better results" })
|
|
140
|
+
] }),
|
|
141
|
+
/* @__PURE__ */ jsx(Switch, { checked: semanticSearchEnabled, onCheckedChange: setSemanticSearchEnabled })
|
|
142
|
+
] }),
|
|
143
|
+
semanticSearchEnabled && /* @__PURE__ */ jsxs("div", { children: [
|
|
144
|
+
/* @__PURE__ */ jsxs(Text, { className: "font-medium mb-2", children: [
|
|
145
|
+
"Semantic Ratio: ",
|
|
146
|
+
semanticRatio
|
|
147
|
+
] }),
|
|
148
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm text-gray-500 mb-3", children: "0.0 = Pure keyword search, 1.0 = Pure semantic search, 0.5 = Balanced hybrid" }),
|
|
149
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
150
|
+
/* @__PURE__ */ jsx(
|
|
151
|
+
Input,
|
|
152
|
+
{
|
|
153
|
+
type: "range",
|
|
154
|
+
min: "0",
|
|
155
|
+
max: "1",
|
|
156
|
+
step: "0.1",
|
|
157
|
+
value: semanticRatio,
|
|
158
|
+
onChange: (e) => setSemanticRatio(parseFloat(e.target.value)),
|
|
159
|
+
className: "flex-1",
|
|
160
|
+
"aria-label": "Semantic search ratio",
|
|
161
|
+
"aria-describedby": "semantic-ratio-description"
|
|
162
|
+
}
|
|
163
|
+
),
|
|
164
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-gray-700", children: semanticRatio.toFixed(1) })
|
|
165
|
+
] }),
|
|
166
|
+
/* @__PURE__ */ jsx("div", { id: "semantic-ratio-description", className: "sr-only", children: "Adjust the balance between keyword and semantic search from 0 to 1" })
|
|
167
|
+
] })
|
|
168
|
+
] }),
|
|
169
|
+
!(vectorStatus == null ? void 0 : vectorStatus.enabled) && /* @__PURE__ */ jsx(Text, { className: "text-gray-500", children: "Vector search is not configured. Add vectorSearch configuration to your plugin options to enable AI-powered semantic search." })
|
|
170
|
+
] }),
|
|
171
|
+
/* @__PURE__ */ jsxs("div", { className: "border border-gray-200 rounded-lg p-6", children: [
|
|
172
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-3 mb-4", children: /* @__PURE__ */ jsx(Heading, { level: "h2", children: "Data Synchronization" }) }),
|
|
173
|
+
/* @__PURE__ */ jsxs(Text, { className: "text-gray-500 mb-4", children: [
|
|
174
|
+
"Manually trigger synchronization of your product catalog with Meilisearch.",
|
|
175
|
+
(vectorStatus == null ? void 0 : vectorStatus.enabled) && " This will also generate embeddings for semantic search."
|
|
176
|
+
] }),
|
|
177
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleSync, isLoading: syncPending, variant: "primary", children: "Sync Now" })
|
|
178
|
+
] }),
|
|
179
|
+
/* @__PURE__ */ jsxs("div", { className: "border border-gray-200 rounded-lg p-6", children: [
|
|
180
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-3 mb-4", children: /* @__PURE__ */ jsx(Heading, { level: "h2", children: "Search Testing" }) }),
|
|
181
|
+
/* @__PURE__ */ jsxs(Text, { className: "text-gray-500 mb-4", children: [
|
|
182
|
+
"Test your products search configuration with a custom query.",
|
|
183
|
+
(vectorStatus == null ? void 0 : vectorStatus.enabled) && " You can test both traditional keyword search and AI-powered semantic search."
|
|
184
|
+
] }),
|
|
185
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
186
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
187
|
+
/* @__PURE__ */ jsx(Text, { className: "text-sm font-medium text-gray-700 mb-2", children: "Search Query" }),
|
|
188
|
+
/* @__PURE__ */ jsx(
|
|
189
|
+
Input,
|
|
190
|
+
{
|
|
191
|
+
value: searchQuery,
|
|
192
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
193
|
+
placeholder: "Enter search query (e.g., 'blue shirt', 'comfortable clothing')",
|
|
194
|
+
className: "w-full",
|
|
195
|
+
"aria-label": "Search query input",
|
|
196
|
+
"aria-describedby": "search-query-help"
|
|
197
|
+
}
|
|
198
|
+
),
|
|
199
|
+
/* @__PURE__ */ jsx("div", { id: "search-query-help", className: "sr-only", children: "Enter a search term to test the search functionality" })
|
|
200
|
+
] }),
|
|
201
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
|
|
202
|
+
/* @__PURE__ */ jsx(
|
|
203
|
+
Button,
|
|
204
|
+
{
|
|
205
|
+
onClick: handleSearchProducts,
|
|
206
|
+
isLoading: searchProductsPending,
|
|
207
|
+
variant: "secondary",
|
|
208
|
+
disabled: !searchQuery.trim(),
|
|
209
|
+
children: "Search Products"
|
|
210
|
+
}
|
|
211
|
+
),
|
|
212
|
+
/* @__PURE__ */ jsx(
|
|
213
|
+
Button,
|
|
214
|
+
{
|
|
215
|
+
onClick: handleSearchCategories,
|
|
216
|
+
isLoading: searchCategoriesPending,
|
|
217
|
+
variant: "secondary",
|
|
218
|
+
disabled: !searchQuery.trim(),
|
|
219
|
+
children: "Search Categories"
|
|
220
|
+
}
|
|
221
|
+
),
|
|
222
|
+
(vectorStatus == null ? void 0 : vectorStatus.enabled) && /* @__PURE__ */ jsx(Text, { className: "text-sm text-gray-500 self-center", children: semanticSearchEnabled ? `Using hybrid search (${Math.round(semanticRatio * 100)}% semantic)` : "Using keyword search only" })
|
|
223
|
+
] })
|
|
224
|
+
] })
|
|
225
|
+
] })
|
|
226
|
+
] }) });
|
|
227
|
+
};
|
|
228
|
+
const config = defineRouteConfig({
|
|
229
|
+
label: "Meilisearch"
|
|
230
|
+
});
|
|
231
|
+
const widgetModule = { widgets: [] };
|
|
232
|
+
const routeModule = {
|
|
233
|
+
routes: [
|
|
234
|
+
{
|
|
235
|
+
Component: SyncPage,
|
|
236
|
+
path: "/settings/meilisearch"
|
|
237
|
+
}
|
|
238
|
+
]
|
|
239
|
+
};
|
|
240
|
+
const menuItemModule = {
|
|
241
|
+
menuItems: [
|
|
242
|
+
{
|
|
243
|
+
label: config.label,
|
|
244
|
+
icon: void 0,
|
|
245
|
+
path: "/settings/meilisearch",
|
|
246
|
+
nested: void 0
|
|
247
|
+
}
|
|
248
|
+
]
|
|
249
|
+
};
|
|
250
|
+
const formModule = { customFields: {} };
|
|
251
|
+
const displayModule = {
|
|
252
|
+
displays: {}
|
|
253
|
+
};
|
|
254
|
+
const i18nModule = { resources: {} };
|
|
255
|
+
const plugin = {
|
|
256
|
+
widgetModule,
|
|
257
|
+
routeModule,
|
|
258
|
+
menuItemModule,
|
|
259
|
+
formModule,
|
|
260
|
+
displayModule,
|
|
261
|
+
i18nModule
|
|
262
|
+
};
|
|
263
|
+
export {
|
|
264
|
+
plugin as default
|
|
265
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SearchResponse } from 'meilisearch';
|
|
3
|
+
import { MedusaRequest, MedusaResponse } from '@medusajs/framework';
|
|
4
|
+
export declare const AdminSearchCategoriesSchema: z.ZodObject<{
|
|
5
|
+
query: z.ZodString;
|
|
6
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
7
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
8
|
+
language: z.ZodOptional<z.ZodString>;
|
|
9
|
+
semanticSearch: z.ZodDefault<z.ZodBoolean>;
|
|
10
|
+
semanticRatio: z.ZodDefault<z.ZodNumber>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
offset: number;
|
|
13
|
+
limit: number;
|
|
14
|
+
semanticSearch: boolean;
|
|
15
|
+
semanticRatio: number;
|
|
16
|
+
query: string;
|
|
17
|
+
language?: string | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
query: string;
|
|
20
|
+
language?: string | undefined;
|
|
21
|
+
offset?: number | undefined;
|
|
22
|
+
limit?: number | undefined;
|
|
23
|
+
semanticSearch?: boolean | undefined;
|
|
24
|
+
semanticRatio?: number | undefined;
|
|
25
|
+
}>;
|
|
26
|
+
export type AdminSearchCategoriesParams = z.infer<typeof AdminSearchCategoriesSchema>;
|
|
27
|
+
export type AdminCategoriesHitsResponse = SearchResponse & {
|
|
28
|
+
hybridSearch?: boolean;
|
|
29
|
+
semanticRatio?: number;
|
|
30
|
+
};
|
|
31
|
+
export declare function POST(req: MedusaRequest<any, AdminSearchCategoriesParams>, res: MedusaResponse<AdminCategoriesHitsResponse>): Promise<void>;
|
|
32
|
+
//# sourceMappingURL=route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/admin/meilisearch/categories-hits/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAGnE,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;EAOtC,CAAA;AAEF,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAA;AAErF,MAAM,MAAM,2BAA2B,GAAG,cAAc,GAAG;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7G,wBAAsB,IAAI,CACxB,GAAG,EAAE,aAAa,CAAC,GAAG,EAAE,2BAA2B,CAAC,EACpD,GAAG,EAAE,cAAc,CAAC,2BAA2B,CAAC,iBAuCjD"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AdminSearchCategoriesSchema = void 0;
|
|
4
|
+
exports.POST = POST;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const meilisearch_1 = require("../../../../modules/meilisearch");
|
|
7
|
+
exports.AdminSearchCategoriesSchema = zod_1.z.object({
|
|
8
|
+
query: zod_1.z.string(),
|
|
9
|
+
limit: zod_1.z.coerce.number().default(10),
|
|
10
|
+
offset: zod_1.z.coerce.number().default(0),
|
|
11
|
+
language: zod_1.z.string().optional(),
|
|
12
|
+
semanticSearch: zod_1.z.coerce.boolean().default(false),
|
|
13
|
+
semanticRatio: zod_1.z.coerce.number().min(0).max(1).default(0.5),
|
|
14
|
+
});
|
|
15
|
+
async function POST(req, res) {
|
|
16
|
+
const { query, language, limit, offset, semanticSearch, semanticRatio } = req.validatedBody;
|
|
17
|
+
const meilisearchService = req.scope.resolve(meilisearch_1.MEILISEARCH_MODULE);
|
|
18
|
+
const indexes = await meilisearchService.getIndexesByType('categories');
|
|
19
|
+
const results = await Promise.all(indexes.map(async (indexKey) => {
|
|
20
|
+
return await meilisearchService.search(indexKey, query, {
|
|
21
|
+
language,
|
|
22
|
+
paginationOptions: {
|
|
23
|
+
limit,
|
|
24
|
+
offset,
|
|
25
|
+
},
|
|
26
|
+
semanticSearch,
|
|
27
|
+
semanticRatio,
|
|
28
|
+
});
|
|
29
|
+
}));
|
|
30
|
+
// Merge results from all indexes
|
|
31
|
+
const mergedResults = results.reduce((acc, result) => {
|
|
32
|
+
return {
|
|
33
|
+
hits: [...acc.hits, ...result.hits],
|
|
34
|
+
estimatedTotalHits: (acc.estimatedTotalHits || 0) + (result.estimatedTotalHits || 0),
|
|
35
|
+
processingTimeMs: Math.max(acc.processingTimeMs, result.processingTimeMs),
|
|
36
|
+
query: result.query,
|
|
37
|
+
// Include vector search metadata if available
|
|
38
|
+
...(semanticSearch && {
|
|
39
|
+
hybridSearch: true,
|
|
40
|
+
semanticRatio,
|
|
41
|
+
}),
|
|
42
|
+
};
|
|
43
|
+
}, { hits: [], estimatedTotalHits: 0, processingTimeMs: 0, query });
|
|
44
|
+
res.json(mergedResults);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL21laWxpc2VhcmNoL2NhdGVnb3JpZXMtaGl0cy9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFrQkEsb0JBeUNDO0FBM0RELDZCQUF1QjtBQUd2QixpRUFBd0Y7QUFFM0UsUUFBQSwyQkFBMkIsR0FBRyxPQUFDLENBQUMsTUFBTSxDQUFDO0lBQ2xELEtBQUssRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFO0lBQ2pCLEtBQUssRUFBRSxPQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7SUFDcEMsTUFBTSxFQUFFLE9BQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUNwQyxRQUFRLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUMvQixjQUFjLEVBQUUsT0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO0lBQ2pELGFBQWEsRUFBRSxPQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQztDQUM1RCxDQUFDLENBQUE7QUFNSyxLQUFLLFVBQVUsSUFBSSxDQUN4QixHQUFvRCxFQUNwRCxHQUFnRDtJQUVoRCxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsR0FBRyxHQUFHLENBQUMsYUFBYSxDQUFBO0lBQzNGLE1BQU0sa0JBQWtCLEdBQXVCLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGdDQUFrQixDQUFDLENBQUE7SUFFcEYsTUFBTSxPQUFPLEdBQUcsTUFBTSxrQkFBa0IsQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUN2RSxNQUFNLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQy9CLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxFQUFFO1FBQzdCLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLEtBQUssRUFBRTtZQUN0RCxRQUFRO1lBQ1IsaUJBQWlCLEVBQUU7Z0JBQ2pCLEtBQUs7Z0JBQ0wsTUFBTTthQUNQO1lBQ0QsY0FBYztZQUNkLGFBQWE7U0FDZCxDQUFDLENBQUE7SUFDSixDQUFDLENBQUMsQ0FDSCxDQUFBO0lBRUQsaUNBQWlDO0lBQ2pDLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQ2xDLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQ2QsT0FBTztZQUNMLElBQUksRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDbkMsa0JBQWtCLEVBQUUsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLElBQUksQ0FBQyxDQUFDO1lBQ3BGLGdCQUFnQixFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQztZQUN6RSxLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUs7WUFDbkIsOENBQThDO1lBQzlDLEdBQUcsQ0FBQyxjQUFjLElBQUk7Z0JBQ3BCLFlBQVksRUFBRSxJQUFJO2dCQUNsQixhQUFhO2FBQ2QsQ0FBQztTQUNILENBQUE7SUFDSCxDQUFDLEVBQ0QsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLGtCQUFrQixFQUFFLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQ2hFLENBQUE7SUFFRCxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFBO0FBQ3pCLENBQUMifQ==
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { SearchResponse } from 'meilisearch';
|
|
3
|
+
import { MedusaRequest, MedusaResponse } from '@medusajs/framework';
|
|
4
|
+
export declare const AdminSearchProductsSchema: z.ZodObject<{
|
|
5
|
+
query: z.ZodString;
|
|
6
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
7
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
8
|
+
language: z.ZodOptional<z.ZodString>;
|
|
9
|
+
semanticSearch: z.ZodDefault<z.ZodBoolean>;
|
|
10
|
+
semanticRatio: z.ZodDefault<z.ZodNumber>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
offset: number;
|
|
13
|
+
limit: number;
|
|
14
|
+
semanticSearch: boolean;
|
|
15
|
+
semanticRatio: number;
|
|
16
|
+
query: string;
|
|
17
|
+
language?: string | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
query: string;
|
|
20
|
+
language?: string | undefined;
|
|
21
|
+
offset?: number | undefined;
|
|
22
|
+
limit?: number | undefined;
|
|
23
|
+
semanticSearch?: boolean | undefined;
|
|
24
|
+
semanticRatio?: number | undefined;
|
|
25
|
+
}>;
|
|
26
|
+
export type AdminSearchProductsParams = z.infer<typeof AdminSearchProductsSchema>;
|
|
27
|
+
export type AdminProductsHitsResponse = SearchResponse & {
|
|
28
|
+
hybridSearch?: boolean;
|
|
29
|
+
semanticRatio?: number;
|
|
30
|
+
};
|
|
31
|
+
export declare function POST(req: MedusaRequest<any, AdminSearchProductsParams>, res: MedusaResponse<AdminProductsHitsResponse>): Promise<void>;
|
|
32
|
+
//# sourceMappingURL=route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/api/admin/meilisearch/products-hits/route.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAA;AACnB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAGnE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;EAOpC,CAAA;AAEF,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAEjF,MAAM,MAAM,yBAAyB,GAAG,cAAc,GAAG;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3G,wBAAsB,IAAI,CACxB,GAAG,EAAE,aAAa,CAAC,GAAG,EAAE,yBAAyB,CAAC,EAClD,GAAG,EAAE,cAAc,CAAC,yBAAyB,CAAC,iBAuC/C"}
|