@open-mercato/search 0.4.2-canary-c02407ff85
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/AGENTS.md +678 -0
- package/build.mjs +92 -0
- package/dist/di.js +157 -0
- package/dist/di.js.map +7 -0
- package/dist/fulltext/drivers/index.js +21 -0
- package/dist/fulltext/drivers/index.js.map +7 -0
- package/dist/fulltext/drivers/meilisearch/index.js +320 -0
- package/dist/fulltext/drivers/meilisearch/index.js.map +7 -0
- package/dist/fulltext/index.js +7 -0
- package/dist/fulltext/index.js.map +7 -0
- package/dist/fulltext/types.js +1 -0
- package/dist/fulltext/types.js.map +7 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +7 -0
- package/dist/indexer/index.js +8 -0
- package/dist/indexer/index.js.map +7 -0
- package/dist/indexer/search-indexer.js +848 -0
- package/dist/indexer/search-indexer.js.map +7 -0
- package/dist/indexer/subscribers/delete.js +41 -0
- package/dist/indexer/subscribers/delete.js.map +7 -0
- package/dist/lib/debug.js +34 -0
- package/dist/lib/debug.js.map +7 -0
- package/dist/lib/fallback-presenter.js +107 -0
- package/dist/lib/fallback-presenter.js.map +7 -0
- package/dist/lib/field-policy.js +75 -0
- package/dist/lib/field-policy.js.map +7 -0
- package/dist/lib/index.js +19 -0
- package/dist/lib/index.js.map +7 -0
- package/dist/lib/merger.js +93 -0
- package/dist/lib/merger.js.map +7 -0
- package/dist/lib/presenter-enricher.js +192 -0
- package/dist/lib/presenter-enricher.js.map +7 -0
- package/dist/modules/search/acl.js +14 -0
- package/dist/modules/search/acl.js.map +7 -0
- package/dist/modules/search/ai-tools.js +284 -0
- package/dist/modules/search/ai-tools.js.map +7 -0
- package/dist/modules/search/api/embeddings/reindex/cancel/route.js +65 -0
- package/dist/modules/search/api/embeddings/reindex/cancel/route.js.map +7 -0
- package/dist/modules/search/api/embeddings/reindex/route.js +165 -0
- package/dist/modules/search/api/embeddings/reindex/route.js.map +7 -0
- package/dist/modules/search/api/embeddings/route.js +246 -0
- package/dist/modules/search/api/embeddings/route.js.map +7 -0
- package/dist/modules/search/api/index/route.js +245 -0
- package/dist/modules/search/api/index/route.js.map +7 -0
- package/dist/modules/search/api/reindex/cancel/route.js +65 -0
- package/dist/modules/search/api/reindex/cancel/route.js.map +7 -0
- package/dist/modules/search/api/reindex/route.js +332 -0
- package/dist/modules/search/api/reindex/route.js.map +7 -0
- package/dist/modules/search/api/search/global/route.js +100 -0
- package/dist/modules/search/api/search/global/route.js.map +7 -0
- package/dist/modules/search/api/search/route.js +101 -0
- package/dist/modules/search/api/search/route.js.map +7 -0
- package/dist/modules/search/api/settings/fulltext/route.js +55 -0
- package/dist/modules/search/api/settings/fulltext/route.js.map +7 -0
- package/dist/modules/search/api/settings/global-search/route.js +80 -0
- package/dist/modules/search/api/settings/global-search/route.js.map +7 -0
- package/dist/modules/search/api/settings/route.js +118 -0
- package/dist/modules/search/api/settings/route.js.map +7 -0
- package/dist/modules/search/api/settings/vector-store/route.js +77 -0
- package/dist/modules/search/api/settings/vector-store/route.js.map +7 -0
- package/dist/modules/search/backend/config/search/page.js +10 -0
- package/dist/modules/search/backend/config/search/page.js.map +7 -0
- package/dist/modules/search/backend/config/search/page.meta.js +24 -0
- package/dist/modules/search/backend/config/search/page.meta.js.map +7 -0
- package/dist/modules/search/cli.js +698 -0
- package/dist/modules/search/cli.js.map +7 -0
- package/dist/modules/search/di.js +32 -0
- package/dist/modules/search/di.js.map +7 -0
- package/dist/modules/search/frontend/components/GlobalSearchDialog.js +357 -0
- package/dist/modules/search/frontend/components/GlobalSearchDialog.js.map +7 -0
- package/dist/modules/search/frontend/components/HybridSearchTable.js +343 -0
- package/dist/modules/search/frontend/components/HybridSearchTable.js.map +7 -0
- package/dist/modules/search/frontend/components/SearchSettingsPageClient.js +303 -0
- package/dist/modules/search/frontend/components/SearchSettingsPageClient.js.map +7 -0
- package/dist/modules/search/frontend/components/sections/FulltextSearchSection.js +360 -0
- package/dist/modules/search/frontend/components/sections/FulltextSearchSection.js.map +7 -0
- package/dist/modules/search/frontend/components/sections/GlobalSearchSection.js +101 -0
- package/dist/modules/search/frontend/components/sections/GlobalSearchSection.js.map +7 -0
- package/dist/modules/search/frontend/components/sections/VectorSearchSection.js +608 -0
- package/dist/modules/search/frontend/components/sections/VectorSearchSection.js.map +7 -0
- package/dist/modules/search/frontend/index.js +9 -0
- package/dist/modules/search/frontend/index.js.map +7 -0
- package/dist/modules/search/frontend/utils.js +41 -0
- package/dist/modules/search/frontend/utils.js.map +7 -0
- package/dist/modules/search/i18n/de.json +61 -0
- package/dist/modules/search/i18n/en.json +72 -0
- package/dist/modules/search/i18n/es.json +61 -0
- package/dist/modules/search/i18n/pl.json +61 -0
- package/dist/modules/search/index.js +11 -0
- package/dist/modules/search/index.js.map +7 -0
- package/dist/modules/search/lib/auto-indexing.js +29 -0
- package/dist/modules/search/lib/auto-indexing.js.map +7 -0
- package/dist/modules/search/lib/embedding-config.js +131 -0
- package/dist/modules/search/lib/embedding-config.js.map +7 -0
- package/dist/modules/search/lib/global-search-config.js +45 -0
- package/dist/modules/search/lib/global-search-config.js.map +7 -0
- package/dist/modules/search/lib/reindex-lock.js +99 -0
- package/dist/modules/search/lib/reindex-lock.js.map +7 -0
- package/dist/modules/search/subscribers/fulltext_upsert.js +64 -0
- package/dist/modules/search/subscribers/fulltext_upsert.js.map +7 -0
- package/dist/modules/search/subscribers/vector_delete.js +58 -0
- package/dist/modules/search/subscribers/vector_delete.js.map +7 -0
- package/dist/modules/search/subscribers/vector_purge.js +142 -0
- package/dist/modules/search/subscribers/vector_purge.js.map +7 -0
- package/dist/modules/search/subscribers/vector_upsert.js +58 -0
- package/dist/modules/search/subscribers/vector_upsert.js.map +7 -0
- package/dist/modules/search/workers/fulltext-index.worker.js +240 -0
- package/dist/modules/search/workers/fulltext-index.worker.js.map +7 -0
- package/dist/modules/search/workers/vector-index.worker.js +234 -0
- package/dist/modules/search/workers/vector-index.worker.js.map +7 -0
- package/dist/queue/fulltext-indexing.js +15 -0
- package/dist/queue/fulltext-indexing.js.map +7 -0
- package/dist/queue/index.js +3 -0
- package/dist/queue/index.js.map +7 -0
- package/dist/queue/vector-indexing.js +15 -0
- package/dist/queue/vector-indexing.js.map +7 -0
- package/dist/service.js +286 -0
- package/dist/service.js.map +7 -0
- package/dist/strategies/fulltext.strategy.js +116 -0
- package/dist/strategies/fulltext.strategy.js.map +7 -0
- package/dist/strategies/index.js +12 -0
- package/dist/strategies/index.js.map +7 -0
- package/dist/strategies/token.strategy.js +80 -0
- package/dist/strategies/token.strategy.js.map +7 -0
- package/dist/strategies/vector.strategy.js +137 -0
- package/dist/strategies/vector.strategy.js.map +7 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +7 -0
- package/dist/vector/drivers/chromadb/index.js +44 -0
- package/dist/vector/drivers/chromadb/index.js.map +7 -0
- package/dist/vector/drivers/index.js +9 -0
- package/dist/vector/drivers/index.js.map +7 -0
- package/dist/vector/drivers/pgvector/index.js +509 -0
- package/dist/vector/drivers/pgvector/index.js.map +7 -0
- package/dist/vector/drivers/qdrant/index.js +44 -0
- package/dist/vector/drivers/qdrant/index.js.map +7 -0
- package/dist/vector/index.js +4 -0
- package/dist/vector/index.js.map +7 -0
- package/dist/vector/lib/vector-logs.js +33 -0
- package/dist/vector/lib/vector-logs.js.map +7 -0
- package/dist/vector/services/checksum.js +20 -0
- package/dist/vector/services/checksum.js.map +7 -0
- package/dist/vector/services/embedding.js +222 -0
- package/dist/vector/services/embedding.js.map +7 -0
- package/dist/vector/services/index.js +4 -0
- package/dist/vector/services/index.js.map +7 -0
- package/dist/vector/services/vector-index.service.js +960 -0
- package/dist/vector/services/vector-index.service.js.map +7 -0
- package/dist/vector/types/pg.d.js +1 -0
- package/dist/vector/types/pg.d.js.map +7 -0
- package/dist/vector/types.js +75 -0
- package/dist/vector/types.js.map +7 -0
- package/jest.config.cjs +19 -0
- package/package.json +142 -0
- package/src/__tests__/queue.test.ts +148 -0
- package/src/__tests__/service.test.ts +345 -0
- package/src/__tests__/workers.test.ts +319 -0
- package/src/di.ts +291 -0
- package/src/fulltext/drivers/index.ts +41 -0
- package/src/fulltext/drivers/meilisearch/index.ts +410 -0
- package/src/fulltext/index.ts +13 -0
- package/src/fulltext/types.ts +115 -0
- package/src/index.ts +36 -0
- package/src/indexer/index.ts +13 -0
- package/src/indexer/search-indexer.ts +1141 -0
- package/src/indexer/subscribers/delete.ts +49 -0
- package/src/lib/debug.ts +46 -0
- package/src/lib/fallback-presenter.ts +106 -0
- package/src/lib/field-policy.ts +169 -0
- package/src/lib/index.ts +13 -0
- package/src/lib/merger.ts +159 -0
- package/src/lib/presenter-enricher.ts +323 -0
- package/src/modules/search/README.md +694 -0
- package/src/modules/search/acl.ts +10 -0
- package/src/modules/search/ai-tools.ts +467 -0
- package/src/modules/search/api/embeddings/reindex/cancel/route.ts +77 -0
- package/src/modules/search/api/embeddings/reindex/route.ts +197 -0
- package/src/modules/search/api/embeddings/route.ts +304 -0
- package/src/modules/search/api/index/route.ts +297 -0
- package/src/modules/search/api/reindex/cancel/route.ts +77 -0
- package/src/modules/search/api/reindex/route.ts +419 -0
- package/src/modules/search/api/search/global/route.ts +120 -0
- package/src/modules/search/api/search/route.ts +121 -0
- package/src/modules/search/api/settings/fulltext/route.ts +82 -0
- package/src/modules/search/api/settings/global-search/route.ts +91 -0
- package/src/modules/search/api/settings/route.ts +187 -0
- package/src/modules/search/api/settings/vector-store/route.ts +105 -0
- package/src/modules/search/backend/config/search/page.meta.ts +22 -0
- package/src/modules/search/backend/config/search/page.tsx +12 -0
- package/src/modules/search/cli.ts +818 -0
- package/src/modules/search/di.ts +50 -0
- package/src/modules/search/frontend/components/GlobalSearchDialog.tsx +436 -0
- package/src/modules/search/frontend/components/HybridSearchTable.tsx +418 -0
- package/src/modules/search/frontend/components/SearchSettingsPageClient.tsx +476 -0
- package/src/modules/search/frontend/components/sections/FulltextSearchSection.tsx +624 -0
- package/src/modules/search/frontend/components/sections/GlobalSearchSection.tsx +124 -0
- package/src/modules/search/frontend/components/sections/VectorSearchSection.tsx +943 -0
- package/src/modules/search/frontend/index.ts +3 -0
- package/src/modules/search/frontend/utils.ts +82 -0
- package/src/modules/search/i18n/de.json +61 -0
- package/src/modules/search/i18n/en.json +72 -0
- package/src/modules/search/i18n/es.json +61 -0
- package/src/modules/search/i18n/pl.json +61 -0
- package/src/modules/search/index.ts +9 -0
- package/src/modules/search/lib/auto-indexing.ts +35 -0
- package/src/modules/search/lib/embedding-config.ts +161 -0
- package/src/modules/search/lib/global-search-config.ts +69 -0
- package/src/modules/search/lib/reindex-lock.ts +201 -0
- package/src/modules/search/subscribers/fulltext_upsert.ts +83 -0
- package/src/modules/search/subscribers/vector_delete.ts +75 -0
- package/src/modules/search/subscribers/vector_purge.ts +161 -0
- package/src/modules/search/subscribers/vector_upsert.ts +75 -0
- package/src/modules/search/workers/fulltext-index.worker.ts +318 -0
- package/src/modules/search/workers/vector-index.worker.ts +292 -0
- package/src/queue/fulltext-indexing.ts +87 -0
- package/src/queue/index.ts +2 -0
- package/src/queue/vector-indexing.ts +66 -0
- package/src/service.ts +397 -0
- package/src/strategies/fulltext.strategy.ts +155 -0
- package/src/strategies/index.ts +17 -0
- package/src/strategies/token.strategy.ts +153 -0
- package/src/strategies/vector.strategy.ts +234 -0
- package/src/types.ts +38 -0
- package/src/vector/drivers/chromadb/index.ts +49 -0
- package/src/vector/drivers/index.ts +4 -0
- package/src/vector/drivers/pgvector/index.ts +627 -0
- package/src/vector/drivers/qdrant/index.ts +49 -0
- package/src/vector/index.ts +3 -0
- package/src/vector/lib/vector-logs.ts +46 -0
- package/src/vector/services/checksum.ts +18 -0
- package/src/vector/services/embedding.ts +275 -0
- package/src/vector/services/index.ts +3 -0
- package/src/vector/services/vector-index.service.ts +1234 -0
- package/src/vector/types/pg.d.ts +1 -0
- package/src/vector/types.ts +220 -0
- package/tsconfig.json +9 -0
- package/watch.mjs +6 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
5
|
+
import { readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
|
|
6
|
+
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
7
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
8
|
+
import { Spinner } from "@open-mercato/ui/primitives/spinner";
|
|
9
|
+
import { GlobalSearchSection } from "./sections/GlobalSearchSection.js";
|
|
10
|
+
import { FulltextSearchSection } from "./sections/FulltextSearchSection.js";
|
|
11
|
+
import { VectorSearchSection } from "./sections/VectorSearchSection.js";
|
|
12
|
+
const normalizeErrorMessage = (error, fallback) => {
|
|
13
|
+
if (typeof error === "string" && error.trim().length) return error.trim();
|
|
14
|
+
if (error instanceof Error && error.message.trim().length) return error.message.trim();
|
|
15
|
+
return fallback;
|
|
16
|
+
};
|
|
17
|
+
function SearchSettingsPageClient() {
|
|
18
|
+
const t = useT();
|
|
19
|
+
const [settings, setSettings] = React.useState(null);
|
|
20
|
+
const [loading, setLoading] = React.useState(true);
|
|
21
|
+
const [error, setError] = React.useState(null);
|
|
22
|
+
const [embeddingSettings, setEmbeddingSettings] = React.useState(null);
|
|
23
|
+
const [embeddingLoading, setEmbeddingLoading] = React.useState(true);
|
|
24
|
+
const [globalSearchStrategies, setGlobalSearchStrategies] = React.useState(() => /* @__PURE__ */ new Set(["fulltext", "vector", "tokens"]));
|
|
25
|
+
const [globalSearchInitial, setGlobalSearchInitial] = React.useState(() => /* @__PURE__ */ new Set(["fulltext", "vector", "tokens"]));
|
|
26
|
+
const [globalSearchLoading, setGlobalSearchLoading] = React.useState(true);
|
|
27
|
+
const [globalSearchSaving, setGlobalSearchSaving] = React.useState(false);
|
|
28
|
+
const [fulltextConfig, setFulltextConfig] = React.useState(null);
|
|
29
|
+
const [fulltextConfigLoading, setFulltextConfigLoading] = React.useState(true);
|
|
30
|
+
const [vectorStoreConfig, setVectorStoreConfig] = React.useState(null);
|
|
31
|
+
const [vectorStoreConfigLoading, setVectorStoreConfigLoading] = React.useState(true);
|
|
32
|
+
const fetchSettings = React.useCallback(async () => {
|
|
33
|
+
setLoading(true);
|
|
34
|
+
setError(null);
|
|
35
|
+
try {
|
|
36
|
+
const body = await readApiResultOrThrow(
|
|
37
|
+
"/api/search/settings",
|
|
38
|
+
void 0,
|
|
39
|
+
{ errorMessage: t("search.settings.errorLabel", "Failed to load settings"), allowNullResult: true }
|
|
40
|
+
);
|
|
41
|
+
if (body?.settings) {
|
|
42
|
+
setSettings(body.settings);
|
|
43
|
+
} else {
|
|
44
|
+
setSettings({
|
|
45
|
+
strategies: [],
|
|
46
|
+
fulltextConfigured: false,
|
|
47
|
+
fulltextStats: null,
|
|
48
|
+
vectorConfigured: false,
|
|
49
|
+
tokensEnabled: true,
|
|
50
|
+
defaultStrategies: [],
|
|
51
|
+
reindexLock: null,
|
|
52
|
+
fulltextReindexLock: null,
|
|
53
|
+
vectorReindexLock: null
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
} catch (err) {
|
|
57
|
+
const message = normalizeErrorMessage(err, t("search.settings.errorLabel", "Failed to load settings"));
|
|
58
|
+
setError(message);
|
|
59
|
+
flash(message, "error");
|
|
60
|
+
} finally {
|
|
61
|
+
setLoading(false);
|
|
62
|
+
}
|
|
63
|
+
}, [t]);
|
|
64
|
+
React.useEffect(() => {
|
|
65
|
+
fetchSettings();
|
|
66
|
+
}, [fetchSettings]);
|
|
67
|
+
const refreshStatsOnly = React.useCallback(async () => {
|
|
68
|
+
try {
|
|
69
|
+
const body = await readApiResultOrThrow(
|
|
70
|
+
"/api/search/settings",
|
|
71
|
+
{ cache: "no-store" },
|
|
72
|
+
{ errorMessage: "", allowNullResult: true }
|
|
73
|
+
);
|
|
74
|
+
if (body?.settings) {
|
|
75
|
+
setSettings(body.settings);
|
|
76
|
+
}
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
}, []);
|
|
80
|
+
const refreshEmbeddingStatsOnly = React.useCallback(async () => {
|
|
81
|
+
try {
|
|
82
|
+
const body = await readApiResultOrThrow(
|
|
83
|
+
"/api/search/embeddings",
|
|
84
|
+
{ cache: "no-store" },
|
|
85
|
+
{ errorMessage: "", allowNullResult: true }
|
|
86
|
+
);
|
|
87
|
+
if (body?.settings) {
|
|
88
|
+
setEmbeddingSettings(body.settings);
|
|
89
|
+
}
|
|
90
|
+
} catch {
|
|
91
|
+
}
|
|
92
|
+
}, []);
|
|
93
|
+
const wasPollingRef = React.useRef(false);
|
|
94
|
+
const pollCountAfterClearRef = React.useRef(0);
|
|
95
|
+
React.useEffect(() => {
|
|
96
|
+
const hasFulltextLock = settings?.fulltextReindexLock !== null;
|
|
97
|
+
const hasVectorLock = settings?.vectorReindexLock !== null;
|
|
98
|
+
const shouldPoll = hasFulltextLock || hasVectorLock || wasPollingRef.current && pollCountAfterClearRef.current < 3;
|
|
99
|
+
if (!shouldPoll) {
|
|
100
|
+
wasPollingRef.current = false;
|
|
101
|
+
pollCountAfterClearRef.current = 0;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (hasFulltextLock || hasVectorLock) {
|
|
105
|
+
wasPollingRef.current = true;
|
|
106
|
+
pollCountAfterClearRef.current = 0;
|
|
107
|
+
}
|
|
108
|
+
const pollInterval = setInterval(() => {
|
|
109
|
+
if (!hasFulltextLock && !hasVectorLock) {
|
|
110
|
+
pollCountAfterClearRef.current += 1;
|
|
111
|
+
}
|
|
112
|
+
refreshStatsOnly();
|
|
113
|
+
if (hasVectorLock) {
|
|
114
|
+
refreshEmbeddingStatsOnly();
|
|
115
|
+
}
|
|
116
|
+
}, 3e3);
|
|
117
|
+
return () => clearInterval(pollInterval);
|
|
118
|
+
}, [settings?.fulltextReindexLock, settings?.vectorReindexLock, refreshStatsOnly, refreshEmbeddingStatsOnly]);
|
|
119
|
+
const fetchEmbeddingSettings = React.useCallback(async () => {
|
|
120
|
+
setEmbeddingLoading(true);
|
|
121
|
+
try {
|
|
122
|
+
const body = await readApiResultOrThrow(
|
|
123
|
+
"/api/search/embeddings",
|
|
124
|
+
void 0,
|
|
125
|
+
{ errorMessage: t("search.settings.errors.loadFailed", "Failed to load settings"), allowNullResult: true }
|
|
126
|
+
);
|
|
127
|
+
if (body?.settings) {
|
|
128
|
+
setEmbeddingSettings(body.settings);
|
|
129
|
+
} else {
|
|
130
|
+
setEmbeddingSettings({
|
|
131
|
+
openaiConfigured: false,
|
|
132
|
+
autoIndexingEnabled: true,
|
|
133
|
+
autoIndexingLocked: false,
|
|
134
|
+
lockReason: null,
|
|
135
|
+
embeddingConfig: null,
|
|
136
|
+
configuredProviders: [],
|
|
137
|
+
indexedDimension: null,
|
|
138
|
+
reindexRequired: false,
|
|
139
|
+
documentCount: null
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
} catch {
|
|
143
|
+
} finally {
|
|
144
|
+
setEmbeddingLoading(false);
|
|
145
|
+
}
|
|
146
|
+
}, [t]);
|
|
147
|
+
React.useEffect(() => {
|
|
148
|
+
fetchEmbeddingSettings();
|
|
149
|
+
}, [fetchEmbeddingSettings]);
|
|
150
|
+
const fetchGlobalSearchSettings = React.useCallback(async () => {
|
|
151
|
+
setGlobalSearchLoading(true);
|
|
152
|
+
try {
|
|
153
|
+
const response = await fetch("/api/search/settings/global-search");
|
|
154
|
+
if (response.ok) {
|
|
155
|
+
const body = await response.json();
|
|
156
|
+
if (body.enabledStrategies && Array.isArray(body.enabledStrategies) && body.enabledStrategies.length > 0) {
|
|
157
|
+
const strategies = new Set(body.enabledStrategies);
|
|
158
|
+
setGlobalSearchStrategies(strategies);
|
|
159
|
+
setGlobalSearchInitial(new Set(strategies));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
} catch {
|
|
163
|
+
} finally {
|
|
164
|
+
setGlobalSearchLoading(false);
|
|
165
|
+
}
|
|
166
|
+
}, []);
|
|
167
|
+
React.useEffect(() => {
|
|
168
|
+
fetchGlobalSearchSettings();
|
|
169
|
+
}, [fetchGlobalSearchSettings]);
|
|
170
|
+
const fetchFulltextConfig = React.useCallback(async () => {
|
|
171
|
+
setFulltextConfigLoading(true);
|
|
172
|
+
try {
|
|
173
|
+
const response = await fetch("/api/search/settings/fulltext");
|
|
174
|
+
if (response.ok) {
|
|
175
|
+
const body = await response.json();
|
|
176
|
+
setFulltextConfig(body);
|
|
177
|
+
}
|
|
178
|
+
} catch {
|
|
179
|
+
} finally {
|
|
180
|
+
setFulltextConfigLoading(false);
|
|
181
|
+
}
|
|
182
|
+
}, []);
|
|
183
|
+
React.useEffect(() => {
|
|
184
|
+
fetchFulltextConfig();
|
|
185
|
+
}, [fetchFulltextConfig]);
|
|
186
|
+
const fetchVectorStoreConfig = React.useCallback(async () => {
|
|
187
|
+
setVectorStoreConfigLoading(true);
|
|
188
|
+
try {
|
|
189
|
+
const response = await fetch("/api/search/settings/vector-store");
|
|
190
|
+
if (response.ok) {
|
|
191
|
+
const body = await response.json();
|
|
192
|
+
setVectorStoreConfig(body);
|
|
193
|
+
}
|
|
194
|
+
} catch {
|
|
195
|
+
} finally {
|
|
196
|
+
setVectorStoreConfigLoading(false);
|
|
197
|
+
}
|
|
198
|
+
}, []);
|
|
199
|
+
React.useEffect(() => {
|
|
200
|
+
fetchVectorStoreConfig();
|
|
201
|
+
}, [fetchVectorStoreConfig]);
|
|
202
|
+
const toggleGlobalSearchStrategy = React.useCallback(async (strategyId) => {
|
|
203
|
+
const newStrategies = new Set(globalSearchStrategies);
|
|
204
|
+
if (newStrategies.has(strategyId)) {
|
|
205
|
+
if (newStrategies.size > 1) {
|
|
206
|
+
newStrategies.delete(strategyId);
|
|
207
|
+
} else {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
} else {
|
|
211
|
+
newStrategies.add(strategyId);
|
|
212
|
+
}
|
|
213
|
+
setGlobalSearchStrategies(newStrategies);
|
|
214
|
+
setGlobalSearchSaving(true);
|
|
215
|
+
try {
|
|
216
|
+
const response = await fetch("/api/search/settings/global-search", {
|
|
217
|
+
method: "POST",
|
|
218
|
+
headers: { "Content-Type": "application/json" },
|
|
219
|
+
body: JSON.stringify({ enabledStrategies: Array.from(newStrategies) })
|
|
220
|
+
});
|
|
221
|
+
if (!response.ok) {
|
|
222
|
+
const body = await response.json().catch(() => ({}));
|
|
223
|
+
throw new Error(body.error || t("search.settings.globalSearch.saveError", "Failed to save settings"));
|
|
224
|
+
}
|
|
225
|
+
setGlobalSearchInitial(new Set(newStrategies));
|
|
226
|
+
} catch (err) {
|
|
227
|
+
setGlobalSearchStrategies(globalSearchInitial);
|
|
228
|
+
flash(normalizeErrorMessage(err, t("search.settings.globalSearch.saveError", "Failed to save settings")), "error");
|
|
229
|
+
} finally {
|
|
230
|
+
setGlobalSearchSaving(false);
|
|
231
|
+
}
|
|
232
|
+
}, [globalSearchStrategies, globalSearchInitial, t]);
|
|
233
|
+
const handleFulltextStatsUpdate = React.useCallback((stats) => {
|
|
234
|
+
setSettings((prev) => prev ? { ...prev, fulltextStats: stats } : prev);
|
|
235
|
+
}, []);
|
|
236
|
+
const handleEmbeddingSettingsUpdate = React.useCallback((newSettings) => {
|
|
237
|
+
setEmbeddingSettings(newSettings);
|
|
238
|
+
}, []);
|
|
239
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
240
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
241
|
+
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold", children: t("search.settings.pageTitle", "Search Settings") }),
|
|
242
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: t("search.settings.pageDescription", "Configure search strategies and view their availability.") })
|
|
243
|
+
] }),
|
|
244
|
+
/* @__PURE__ */ jsx(
|
|
245
|
+
GlobalSearchSection,
|
|
246
|
+
{
|
|
247
|
+
loading: globalSearchLoading,
|
|
248
|
+
saving: globalSearchSaving,
|
|
249
|
+
strategies: globalSearchStrategies,
|
|
250
|
+
fulltextConfigured: settings?.fulltextConfigured ?? false,
|
|
251
|
+
vectorConfigured: settings?.vectorConfigured ?? false,
|
|
252
|
+
onToggleStrategy: toggleGlobalSearchStrategy
|
|
253
|
+
}
|
|
254
|
+
),
|
|
255
|
+
/* @__PURE__ */ jsx(
|
|
256
|
+
FulltextSearchSection,
|
|
257
|
+
{
|
|
258
|
+
fulltextConfig,
|
|
259
|
+
fulltextConfigLoading,
|
|
260
|
+
fulltextStats: settings?.fulltextStats ?? null,
|
|
261
|
+
fulltextReindexLock: settings?.fulltextReindexLock ?? null,
|
|
262
|
+
loading,
|
|
263
|
+
onStatsUpdate: handleFulltextStatsUpdate,
|
|
264
|
+
onRefresh: fetchSettings
|
|
265
|
+
}
|
|
266
|
+
),
|
|
267
|
+
/* @__PURE__ */ jsx(
|
|
268
|
+
VectorSearchSection,
|
|
269
|
+
{
|
|
270
|
+
embeddingSettings,
|
|
271
|
+
embeddingLoading,
|
|
272
|
+
vectorStoreConfig,
|
|
273
|
+
vectorStoreConfigLoading,
|
|
274
|
+
vectorReindexLock: settings?.vectorReindexLock ?? null,
|
|
275
|
+
onEmbeddingSettingsUpdate: handleEmbeddingSettingsUpdate,
|
|
276
|
+
onRefreshEmbeddings: fetchEmbeddingSettings
|
|
277
|
+
}
|
|
278
|
+
),
|
|
279
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
280
|
+
/* @__PURE__ */ jsx(
|
|
281
|
+
Button,
|
|
282
|
+
{
|
|
283
|
+
type: "button",
|
|
284
|
+
variant: "outline",
|
|
285
|
+
size: "sm",
|
|
286
|
+
onClick: () => fetchSettings(),
|
|
287
|
+
disabled: loading,
|
|
288
|
+
children: loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
289
|
+
/* @__PURE__ */ jsx(Spinner, { size: "sm", className: "mr-2" }),
|
|
290
|
+
t("search.settings.loadingLabel", "Loading settings...")
|
|
291
|
+
] }) : t("search.settings.refreshLabel", "Refresh")
|
|
292
|
+
}
|
|
293
|
+
),
|
|
294
|
+
error && /* @__PURE__ */ jsx("span", { className: "text-sm text-destructive", children: error })
|
|
295
|
+
] })
|
|
296
|
+
] });
|
|
297
|
+
}
|
|
298
|
+
var SearchSettingsPageClient_default = SearchSettingsPageClient;
|
|
299
|
+
export {
|
|
300
|
+
SearchSettingsPageClient,
|
|
301
|
+
SearchSettingsPageClient_default as default
|
|
302
|
+
};
|
|
303
|
+
//# sourceMappingURL=SearchSettingsPageClient.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/search/frontend/components/SearchSettingsPageClient.tsx"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { GlobalSearchSection } from './sections/GlobalSearchSection'\nimport { FulltextSearchSection } from './sections/FulltextSearchSection'\nimport { VectorSearchSection } from './sections/VectorSearchSection'\n\n// Types\ntype StrategyStatus = {\n id: string\n name: string\n priority: number\n available: boolean\n}\n\ntype FulltextStats = {\n numberOfDocuments: number\n isIndexing: boolean\n fieldDistribution: Record<string, number>\n}\n\ntype ReindexLock = {\n type: 'fulltext' | 'vector'\n action: string\n startedAt: string\n elapsedMinutes: number\n}\n\ntype SearchSettings = {\n strategies: StrategyStatus[]\n fulltextConfigured: boolean\n fulltextStats: FulltextStats | null\n vectorConfigured: boolean\n tokensEnabled: boolean\n defaultStrategies: string[]\n reindexLock: ReindexLock | null\n fulltextReindexLock: ReindexLock | null\n vectorReindexLock: ReindexLock | null\n}\n\ntype SettingsResponse = {\n settings?: SearchSettings\n error?: string\n}\n\n// Embedding types\ntype EmbeddingProviderId = 'openai' | 'google' | 'mistral' | 'cohere' | 'bedrock' | 'ollama'\n\ntype EmbeddingProviderConfig = {\n providerId: EmbeddingProviderId\n model: string\n dimension: number\n outputDimensionality?: number\n baseUrl?: string\n updatedAt: string\n}\n\ntype EmbeddingSettings = {\n openaiConfigured: boolean\n autoIndexingEnabled: boolean\n autoIndexingLocked: boolean\n lockReason: string | null\n embeddingConfig: EmbeddingProviderConfig | null\n configuredProviders: EmbeddingProviderId[]\n indexedDimension: number | null\n reindexRequired: boolean\n documentCount: number | null\n}\n\ntype EmbeddingSettingsResponse = {\n settings?: EmbeddingSettings\n error?: string\n}\n\n// Full-text search config types\ntype FulltextEnvVarStatus = {\n set: boolean\n hint: string\n}\n\ntype FulltextOptionalEnvVarStatus = {\n set: boolean\n value?: string | boolean\n default?: string | boolean\n hint: string\n}\n\ntype FulltextConfigResponse = {\n driver: 'meilisearch' | null\n configured: boolean\n envVars: {\n MEILISEARCH_HOST: FulltextEnvVarStatus\n MEILISEARCH_API_KEY: FulltextEnvVarStatus\n }\n optionalEnvVars: {\n MEILISEARCH_INDEX_PREFIX: FulltextOptionalEnvVarStatus\n SEARCH_EXCLUDE_ENCRYPTED_FIELDS: FulltextOptionalEnvVarStatus\n }\n}\n\n// Vector store driver types\ntype VectorDriverId = 'pgvector' | 'qdrant' | 'chromadb'\n\ntype VectorDriverEnvVar = {\n name: string\n set: boolean\n hint: string\n}\n\ntype VectorDriverStatus = {\n id: VectorDriverId\n name: string\n configured: boolean\n implemented: boolean\n envVars: VectorDriverEnvVar[]\n}\n\ntype VectorStoreConfigResponse = {\n currentDriver: VectorDriverId\n configured: boolean\n drivers: VectorDriverStatus[]\n}\n\nconst normalizeErrorMessage = (error: unknown, fallback: string): string => {\n if (typeof error === 'string' && error.trim().length) return error.trim()\n if (error instanceof Error && error.message.trim().length) return error.message.trim()\n return fallback\n}\n\nexport function SearchSettingsPageClient() {\n const t = useT()\n\n // Main settings state\n const [settings, setSettings] = React.useState<SearchSettings | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n\n // Embedding settings state\n const [embeddingSettings, setEmbeddingSettings] = React.useState<EmbeddingSettings | null>(null)\n const [embeddingLoading, setEmbeddingLoading] = React.useState(true)\n\n // Global search settings state\n const [globalSearchStrategies, setGlobalSearchStrategies] = React.useState<Set<string>>(() => new Set(['fulltext', 'vector', 'tokens']))\n const [globalSearchInitial, setGlobalSearchInitial] = React.useState<Set<string>>(() => new Set(['fulltext', 'vector', 'tokens']))\n const [globalSearchLoading, setGlobalSearchLoading] = React.useState(true)\n const [globalSearchSaving, setGlobalSearchSaving] = React.useState(false)\n\n // Full-text search config state\n const [fulltextConfig, setFulltextConfig] = React.useState<FulltextConfigResponse | null>(null)\n const [fulltextConfigLoading, setFulltextConfigLoading] = React.useState(true)\n\n // Vector store config state\n const [vectorStoreConfig, setVectorStoreConfig] = React.useState<VectorStoreConfigResponse | null>(null)\n const [vectorStoreConfigLoading, setVectorStoreConfigLoading] = React.useState(true)\n\n // Fetch main settings\n const fetchSettings = React.useCallback(async () => {\n setLoading(true)\n setError(null)\n try {\n const body = await readApiResultOrThrow<SettingsResponse>(\n '/api/search/settings',\n undefined,\n { errorMessage: t('search.settings.errorLabel', 'Failed to load settings'), allowNullResult: true },\n )\n if (body?.settings) {\n setSettings(body.settings)\n } else {\n setSettings({\n strategies: [],\n fulltextConfigured: false,\n fulltextStats: null,\n vectorConfigured: false,\n tokensEnabled: true,\n defaultStrategies: [],\n reindexLock: null,\n fulltextReindexLock: null,\n vectorReindexLock: null,\n })\n }\n } catch (err) {\n const message = normalizeErrorMessage(err, t('search.settings.errorLabel', 'Failed to load settings'))\n setError(message)\n flash(message, 'error')\n } finally {\n setLoading(false)\n }\n }, [t])\n\n React.useEffect(() => {\n fetchSettings()\n }, [fetchSettings])\n\n // Lightweight stats refresh for polling during reindex\n const refreshStatsOnly = React.useCallback(async () => {\n try {\n const body = await readApiResultOrThrow<SettingsResponse>(\n '/api/search/settings',\n { cache: 'no-store' },\n { errorMessage: '', allowNullResult: true },\n )\n if (body?.settings) {\n setSettings(body.settings)\n }\n } catch {\n // Silently ignore errors during polling\n }\n }, [])\n\n // Lightweight embedding stats refresh\n const refreshEmbeddingStatsOnly = React.useCallback(async () => {\n try {\n const body = await readApiResultOrThrow<EmbeddingSettingsResponse>(\n '/api/search/embeddings',\n { cache: 'no-store' },\n { errorMessage: '', allowNullResult: true },\n )\n if (body?.settings) {\n setEmbeddingSettings(body.settings)\n }\n } catch {\n // Silently ignore errors during polling\n }\n }, [])\n\n // Polling logic\n const wasPollingRef = React.useRef(false)\n const pollCountAfterClearRef = React.useRef(0)\n\n React.useEffect(() => {\n const hasFulltextLock = settings?.fulltextReindexLock !== null\n const hasVectorLock = settings?.vectorReindexLock !== null\n\n const shouldPoll = hasFulltextLock || hasVectorLock ||\n (wasPollingRef.current && pollCountAfterClearRef.current < 3)\n\n if (!shouldPoll) {\n wasPollingRef.current = false\n pollCountAfterClearRef.current = 0\n return\n }\n\n if (hasFulltextLock || hasVectorLock) {\n wasPollingRef.current = true\n pollCountAfterClearRef.current = 0\n }\n\n const pollInterval = setInterval(() => {\n if (!hasFulltextLock && !hasVectorLock) {\n pollCountAfterClearRef.current += 1\n }\n\n refreshStatsOnly()\n if (hasVectorLock) {\n refreshEmbeddingStatsOnly()\n }\n }, 3000)\n\n return () => clearInterval(pollInterval)\n }, [settings?.fulltextReindexLock, settings?.vectorReindexLock, refreshStatsOnly, refreshEmbeddingStatsOnly])\n\n // Fetch embedding settings\n const fetchEmbeddingSettings = React.useCallback(async () => {\n setEmbeddingLoading(true)\n try {\n const body = await readApiResultOrThrow<EmbeddingSettingsResponse>(\n '/api/search/embeddings',\n undefined,\n { errorMessage: t('search.settings.errors.loadFailed', 'Failed to load settings'), allowNullResult: true },\n )\n if (body?.settings) {\n setEmbeddingSettings(body.settings)\n } else {\n setEmbeddingSettings({\n openaiConfigured: false,\n autoIndexingEnabled: true,\n autoIndexingLocked: false,\n lockReason: null,\n embeddingConfig: null,\n configuredProviders: [],\n indexedDimension: null,\n reindexRequired: false,\n documentCount: null,\n })\n }\n } catch {\n // Error already handled\n } finally {\n setEmbeddingLoading(false)\n }\n }, [t])\n\n React.useEffect(() => {\n fetchEmbeddingSettings()\n }, [fetchEmbeddingSettings])\n\n // Fetch global search settings\n const fetchGlobalSearchSettings = React.useCallback(async () => {\n setGlobalSearchLoading(true)\n try {\n const response = await fetch('/api/search/settings/global-search')\n if (response.ok) {\n const body = await response.json() as { enabledStrategies?: string[] }\n if (body.enabledStrategies && Array.isArray(body.enabledStrategies) && body.enabledStrategies.length > 0) {\n const strategies = new Set(body.enabledStrategies)\n setGlobalSearchStrategies(strategies)\n setGlobalSearchInitial(new Set(strategies))\n }\n }\n } catch {\n // Silently use defaults\n } finally {\n setGlobalSearchLoading(false)\n }\n }, [])\n\n React.useEffect(() => {\n fetchGlobalSearchSettings()\n }, [fetchGlobalSearchSettings])\n\n // Fetch fulltext config\n const fetchFulltextConfig = React.useCallback(async () => {\n setFulltextConfigLoading(true)\n try {\n const response = await fetch('/api/search/settings/fulltext')\n if (response.ok) {\n const body = await response.json() as FulltextConfigResponse\n setFulltextConfig(body)\n }\n } catch {\n // Silently use null\n } finally {\n setFulltextConfigLoading(false)\n }\n }, [])\n\n React.useEffect(() => {\n fetchFulltextConfig()\n }, [fetchFulltextConfig])\n\n // Fetch vector store config\n const fetchVectorStoreConfig = React.useCallback(async () => {\n setVectorStoreConfigLoading(true)\n try {\n const response = await fetch('/api/search/settings/vector-store')\n if (response.ok) {\n const body = await response.json() as VectorStoreConfigResponse\n setVectorStoreConfig(body)\n }\n } catch {\n // Silently use null\n } finally {\n setVectorStoreConfigLoading(false)\n }\n }, [])\n\n React.useEffect(() => {\n fetchVectorStoreConfig()\n }, [fetchVectorStoreConfig])\n\n // Global search settings handlers - auto-save on toggle\n const toggleGlobalSearchStrategy = React.useCallback(async (strategyId: string) => {\n const newStrategies = new Set(globalSearchStrategies)\n if (newStrategies.has(strategyId)) {\n if (newStrategies.size > 1) {\n newStrategies.delete(strategyId)\n } else {\n return\n }\n } else {\n newStrategies.add(strategyId)\n }\n\n setGlobalSearchStrategies(newStrategies)\n setGlobalSearchSaving(true)\n\n try {\n const response = await fetch('/api/search/settings/global-search', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ enabledStrategies: Array.from(newStrategies) }),\n })\n\n if (!response.ok) {\n const body = await response.json().catch(() => ({})) as { error?: string }\n throw new Error(body.error || t('search.settings.globalSearch.saveError', 'Failed to save settings'))\n }\n\n setGlobalSearchInitial(new Set(newStrategies))\n } catch (err) {\n setGlobalSearchStrategies(globalSearchInitial)\n flash(normalizeErrorMessage(err, t('search.settings.globalSearch.saveError', 'Failed to save settings')), 'error')\n } finally {\n setGlobalSearchSaving(false)\n }\n }, [globalSearchStrategies, globalSearchInitial, t])\n\n // Callbacks for section components\n const handleFulltextStatsUpdate = React.useCallback((stats: FulltextStats | null) => {\n setSettings(prev => prev ? { ...prev, fulltextStats: stats } : prev)\n }, [])\n\n const handleEmbeddingSettingsUpdate = React.useCallback((newSettings: EmbeddingSettings) => {\n setEmbeddingSettings(newSettings)\n }, [])\n\n return (\n <div className=\"flex flex-col gap-6\">\n {/* Header */}\n <div className=\"space-y-1\">\n <h1 className=\"text-2xl font-bold\">{t('search.settings.pageTitle', 'Search Settings')}</h1>\n <p className=\"text-muted-foreground\">{t('search.settings.pageDescription', 'Configure search strategies and view their availability.')}</p>\n </div>\n\n {/* Section 1: Global Search Settings */}\n <GlobalSearchSection\n loading={globalSearchLoading}\n saving={globalSearchSaving}\n strategies={globalSearchStrategies}\n fulltextConfigured={settings?.fulltextConfigured ?? false}\n vectorConfigured={settings?.vectorConfigured ?? false}\n onToggleStrategy={toggleGlobalSearchStrategy}\n />\n\n {/* Section 2: Full-Text Search (with tabs) */}\n <FulltextSearchSection\n fulltextConfig={fulltextConfig}\n fulltextConfigLoading={fulltextConfigLoading}\n fulltextStats={settings?.fulltextStats ?? null}\n fulltextReindexLock={settings?.fulltextReindexLock ?? null}\n loading={loading}\n onStatsUpdate={handleFulltextStatsUpdate}\n onRefresh={fetchSettings}\n />\n\n {/* Section 3: Vector Search (with tabs) */}\n <VectorSearchSection\n embeddingSettings={embeddingSettings}\n embeddingLoading={embeddingLoading}\n vectorStoreConfig={vectorStoreConfig}\n vectorStoreConfigLoading={vectorStoreConfigLoading}\n vectorReindexLock={settings?.vectorReindexLock ?? null}\n onEmbeddingSettingsUpdate={handleEmbeddingSettingsUpdate}\n onRefreshEmbeddings={fetchEmbeddingSettings}\n />\n\n {/* Refresh Button */}\n <div className=\"flex items-center gap-3\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => fetchSettings()}\n disabled={loading}\n >\n {loading ? (\n <>\n <Spinner size=\"sm\" className=\"mr-2\" />\n {t('search.settings.loadingLabel', 'Loading settings...')}\n </>\n ) : (\n t('search.settings.refreshLabel', 'Refresh')\n )}\n </Button>\n {error && <span className=\"text-sm text-destructive\">{error}</span>}\n </div>\n </div>\n )\n}\n\nexport default SearchSettingsPageClient\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|