svedocs 0.1.0-beta.10
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/LICENSE +5 -0
- package/README.md +85 -0
- package/dist/ai/openai-compatible.d.ts +13 -0
- package/dist/ai/openai-compatible.d.ts.map +1 -0
- package/dist/ai/openai-compatible.js +92 -0
- package/dist/ai/providers.d.ts +20 -0
- package/dist/ai/providers.d.ts.map +1 -0
- package/dist/ai/providers.js +185 -0
- package/dist/ai/rate-limit.d.ts +18 -0
- package/dist/ai/rate-limit.d.ts.map +1 -0
- package/dist/ai/rate-limit.js +52 -0
- package/dist/ai/response.d.ts +4 -0
- package/dist/ai/response.d.ts.map +1 -0
- package/dist/ai/response.js +151 -0
- package/dist/ai/runtime.d.ts +32 -0
- package/dist/ai/runtime.d.ts.map +1 -0
- package/dist/ai/runtime.js +111 -0
- package/dist/ai/types.d.ts +93 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +1 -0
- package/dist/ai.d.ts +7 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +6 -0
- package/dist/ambient.d.ts +5 -0
- package/dist/cloudflare.d.ts +29 -0
- package/dist/cloudflare.d.ts.map +1 -0
- package/dist/cloudflare.js +149 -0
- package/dist/config.d.ts +373 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +299 -0
- package/dist/core/checks.d.ts +4 -0
- package/dist/core/checks.d.ts.map +1 -0
- package/dist/core/checks.js +267 -0
- package/dist/core/config.d.ts +6 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +178 -0
- package/dist/core/content.d.ts +7 -0
- package/dist/core/content.d.ts.map +1 -0
- package/dist/core/content.js +340 -0
- package/dist/core/i18n.d.ts +5 -0
- package/dist/core/i18n.d.ts.map +1 -0
- package/dist/core/i18n.js +117 -0
- package/dist/core/links.d.ts +5 -0
- package/dist/core/links.d.ts.map +1 -0
- package/dist/core/links.js +60 -0
- package/dist/core/messages.d.ts +149 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.js +163 -0
- package/dist/core/navigation.d.ts +5 -0
- package/dist/core/navigation.d.ts.map +1 -0
- package/dist/core/navigation.js +144 -0
- package/dist/core/routes.d.ts +36 -0
- package/dist/core/routes.d.ts.map +1 -0
- package/dist/core/routes.js +152 -0
- package/dist/core/search.d.ts +5 -0
- package/dist/core/search.d.ts.map +1 -0
- package/dist/core/search.js +41 -0
- package/dist/core/types.d.ts +468 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +4 -0
- package/dist/core/utils.d.ts +13 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +60 -0
- package/dist/core.d.ts +9 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +8 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/mdx/ast.d.ts +32 -0
- package/dist/mdx/ast.d.ts.map +1 -0
- package/dist/mdx/ast.js +148 -0
- package/dist/mdx/code.d.ts +17 -0
- package/dist/mdx/code.d.ts.map +1 -0
- package/dist/mdx/code.js +327 -0
- package/dist/mdx/compile.d.ts +29 -0
- package/dist/mdx/compile.d.ts.map +1 -0
- package/dist/mdx/compile.js +59 -0
- package/dist/mdx/diff.d.ts +9 -0
- package/dist/mdx/diff.d.ts.map +1 -0
- package/dist/mdx/diff.js +171 -0
- package/dist/mdx/headings.d.ts +4 -0
- package/dist/mdx/headings.d.ts.map +1 -0
- package/dist/mdx/headings.js +42 -0
- package/dist/mdx/links.d.ts +4 -0
- package/dist/mdx/links.d.ts.map +1 -0
- package/dist/mdx/links.js +144 -0
- package/dist/mdx/utils.d.ts +10 -0
- package/dist/mdx/utils.d.ts.map +1 -0
- package/dist/mdx/utils.js +64 -0
- package/dist/og/image.d.ts +25 -0
- package/dist/og/image.d.ts.map +1 -0
- package/dist/og/image.js +224 -0
- package/dist/og/metadata.d.ts +7 -0
- package/dist/og/metadata.d.ts.map +1 -0
- package/dist/og/metadata.js +198 -0
- package/dist/og/response.d.ts +4 -0
- package/dist/og/response.d.ts.map +1 -0
- package/dist/og/response.js +49 -0
- package/dist/og/rss.d.ts +4 -0
- package/dist/og/rss.d.ts.map +1 -0
- package/dist/og/rss.js +96 -0
- package/dist/og/sitemap.d.ts +7 -0
- package/dist/og/sitemap.d.ts.map +1 -0
- package/dist/og/sitemap.js +90 -0
- package/dist/og/types.d.ts +65 -0
- package/dist/og/types.d.ts.map +1 -0
- package/dist/og/types.js +1 -0
- package/dist/og.d.ts +6 -0
- package/dist/og.d.ts.map +1 -0
- package/dist/og.js +5 -0
- package/dist/routes.d.ts +2 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +1 -0
- package/dist/search/algolia.d.ts +10 -0
- package/dist/search/algolia.d.ts.map +1 -0
- package/dist/search/algolia.js +82 -0
- package/dist/search/cloudflare-sync.d.ts +5 -0
- package/dist/search/cloudflare-sync.d.ts.map +1 -0
- package/dist/search/cloudflare-sync.js +169 -0
- package/dist/search/cloudflare.d.ts +11 -0
- package/dist/search/cloudflare.d.ts.map +1 -0
- package/dist/search/cloudflare.js +126 -0
- package/dist/search/local.d.ts +9 -0
- package/dist/search/local.d.ts.map +1 -0
- package/dist/search/local.js +165 -0
- package/dist/search/runtime.d.ts +41 -0
- package/dist/search/runtime.d.ts.map +1 -0
- package/dist/search/runtime.js +152 -0
- package/dist/search/types.d.ts +172 -0
- package/dist/search/types.d.ts.map +1 -0
- package/dist/search/types.js +1 -0
- package/dist/search/typesense.d.ts +11 -0
- package/dist/search/typesense.d.ts.map +1 -0
- package/dist/search/typesense.js +91 -0
- package/dist/search/utils.d.ts +11 -0
- package/dist/search/utils.d.ts.map +1 -0
- package/dist/search/utils.js +93 -0
- package/dist/search.d.ts +8 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +7 -0
- package/dist/svelte.d.ts +27 -0
- package/dist/svelte.d.ts.map +1 -0
- package/dist/svelte.js +45 -0
- package/dist/testing.d.ts +3 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +23 -0
- package/dist/theme/Article.svelte +145 -0
- package/dist/theme/Article.svelte.d.ts +36 -0
- package/dist/theme/Article.svelte.d.ts.map +1 -0
- package/dist/theme/AskAiPanel.svelte +241 -0
- package/dist/theme/AskAiPanel.svelte.d.ts +31 -0
- package/dist/theme/AskAiPanel.svelte.d.ts.map +1 -0
- package/dist/theme/Brand.svelte +19 -0
- package/dist/theme/Brand.svelte.d.ts +22 -0
- package/dist/theme/Brand.svelte.d.ts.map +1 -0
- package/dist/theme/Button.svelte +34 -0
- package/dist/theme/Button.svelte.d.ts +41 -0
- package/dist/theme/Button.svelte.d.ts.map +1 -0
- package/dist/theme/Checkbox.svelte +63 -0
- package/dist/theme/Checkbox.svelte.d.ts +45 -0
- package/dist/theme/Checkbox.svelte.d.ts.map +1 -0
- package/dist/theme/CodeBlock.svelte +6 -0
- package/dist/theme/CodeBlock.svelte.d.ts +22 -0
- package/dist/theme/CodeBlock.svelte.d.ts.map +1 -0
- package/dist/theme/DocPage.svelte +15 -0
- package/dist/theme/DocPage.svelte.d.ts +33 -0
- package/dist/theme/DocPage.svelte.d.ts.map +1 -0
- package/dist/theme/DocsApp.svelte +194 -0
- package/dist/theme/DocsApp.svelte.d.ts +60 -0
- package/dist/theme/DocsApp.svelte.d.ts.map +1 -0
- package/dist/theme/DocsLayout.svelte +99 -0
- package/dist/theme/DocsLayout.svelte.d.ts +39 -0
- package/dist/theme/DocsLayout.svelte.d.ts.map +1 -0
- package/dist/theme/DocsShell.svelte +91 -0
- package/dist/theme/DocsShell.svelte.d.ts +34 -0
- package/dist/theme/DocsShell.svelte.d.ts.map +1 -0
- package/dist/theme/ErrorPage.svelte +113 -0
- package/dist/theme/ErrorPage.svelte.d.ts +34 -0
- package/dist/theme/ErrorPage.svelte.d.ts.map +1 -0
- package/dist/theme/FloatingToolbar.svelte +8 -0
- package/dist/theme/FloatingToolbar.svelte.d.ts +22 -0
- package/dist/theme/FloatingToolbar.svelte.d.ts.map +1 -0
- package/dist/theme/Footer.svelte +18 -0
- package/dist/theme/Footer.svelte.d.ts +24 -0
- package/dist/theme/Footer.svelte.d.ts.map +1 -0
- package/dist/theme/FooterLinks.svelte +37 -0
- package/dist/theme/FooterLinks.svelte.d.ts +22 -0
- package/dist/theme/FooterLinks.svelte.d.ts.map +1 -0
- package/dist/theme/FormField.svelte +41 -0
- package/dist/theme/FormField.svelte.d.ts +35 -0
- package/dist/theme/FormField.svelte.d.ts.map +1 -0
- package/dist/theme/HomePage.svelte +284 -0
- package/dist/theme/HomePage.svelte.d.ts +65 -0
- package/dist/theme/HomePage.svelte.d.ts.map +1 -0
- package/dist/theme/Input.svelte +36 -0
- package/dist/theme/Input.svelte.d.ts +34 -0
- package/dist/theme/Input.svelte.d.ts.map +1 -0
- package/dist/theme/LayoutShell.svelte +120 -0
- package/dist/theme/LayoutShell.svelte.d.ts +43 -0
- package/dist/theme/LayoutShell.svelte.d.ts.map +1 -0
- package/dist/theme/LocalizedLink.svelte +21 -0
- package/dist/theme/LocalizedLink.svelte.d.ts +38 -0
- package/dist/theme/LocalizedLink.svelte.d.ts.map +1 -0
- package/dist/theme/MobileNav.svelte +20 -0
- package/dist/theme/MobileNav.svelte.d.ts +26 -0
- package/dist/theme/MobileNav.svelte.d.ts.map +1 -0
- package/dist/theme/Navbar.svelte +69 -0
- package/dist/theme/Navbar.svelte.d.ts +29 -0
- package/dist/theme/Navbar.svelte.d.ts.map +1 -0
- package/dist/theme/PageLayout.svelte +49 -0
- package/dist/theme/PageLayout.svelte.d.ts +34 -0
- package/dist/theme/PageLayout.svelte.d.ts.map +1 -0
- package/dist/theme/PageShell.svelte +98 -0
- package/dist/theme/PageShell.svelte.d.ts +35 -0
- package/dist/theme/PageShell.svelte.d.ts.map +1 -0
- package/dist/theme/PageTools.svelte +87 -0
- package/dist/theme/PageTools.svelte.d.ts +25 -0
- package/dist/theme/PageTools.svelte.d.ts.map +1 -0
- package/dist/theme/RenderError.svelte +62 -0
- package/dist/theme/RenderError.svelte.d.ts +31 -0
- package/dist/theme/RenderError.svelte.d.ts.map +1 -0
- package/dist/theme/RootLayout.svelte +274 -0
- package/dist/theme/RootLayout.svelte.d.ts +47 -0
- package/dist/theme/RootLayout.svelte.d.ts.map +1 -0
- package/dist/theme/RouteRenderError.svelte +53 -0
- package/dist/theme/RouteRenderError.svelte.d.ts +34 -0
- package/dist/theme/RouteRenderError.svelte.d.ts.map +1 -0
- package/dist/theme/SafeRenderError.svelte +49 -0
- package/dist/theme/SafeRenderError.svelte.d.ts +33 -0
- package/dist/theme/SafeRenderError.svelte.d.ts.map +1 -0
- package/dist/theme/ScopeSwitcher.svelte +107 -0
- package/dist/theme/ScopeSwitcher.svelte.d.ts +26 -0
- package/dist/theme/ScopeSwitcher.svelte.d.ts.map +1 -0
- package/dist/theme/SearchDialog.svelte +200 -0
- package/dist/theme/SearchDialog.svelte.d.ts +31 -0
- package/dist/theme/SearchDialog.svelte.d.ts.map +1 -0
- package/dist/theme/Select.svelte +37 -0
- package/dist/theme/Select.svelte.d.ts +42 -0
- package/dist/theme/Select.svelte.d.ts.map +1 -0
- package/dist/theme/SidebarTree.svelte +148 -0
- package/dist/theme/SidebarTree.svelte.d.ts +24 -0
- package/dist/theme/SidebarTree.svelte.d.ts.map +1 -0
- package/dist/theme/SocialNav.svelte +17 -0
- package/dist/theme/SocialNav.svelte.d.ts +22 -0
- package/dist/theme/SocialNav.svelte.d.ts.map +1 -0
- package/dist/theme/TableOfContents.svelte +73 -0
- package/dist/theme/TableOfContents.svelte.d.ts +25 -0
- package/dist/theme/TableOfContents.svelte.d.ts.map +1 -0
- package/dist/theme/Textarea.svelte +33 -0
- package/dist/theme/Textarea.svelte.d.ts +33 -0
- package/dist/theme/Textarea.svelte.d.ts.map +1 -0
- package/dist/theme/ThemeInit.svelte +16 -0
- package/dist/theme/ThemeInit.svelte.d.ts +23 -0
- package/dist/theme/ThemeInit.svelte.d.ts.map +1 -0
- package/dist/theme/ThemeToggle.svelte +37 -0
- package/dist/theme/ThemeToggle.svelte.d.ts +23 -0
- package/dist/theme/ThemeToggle.svelte.d.ts.map +1 -0
- package/dist/theme/TopNav.svelte +23 -0
- package/dist/theme/TopNav.svelte.d.ts +22 -0
- package/dist/theme/TopNav.svelte.d.ts.map +1 -0
- package/dist/theme/base.css +240 -0
- package/dist/theme/defaults.d.ts +4 -0
- package/dist/theme/defaults.d.ts.map +1 -0
- package/dist/theme/defaults.js +55 -0
- package/dist/theme/forms.d.ts +4 -0
- package/dist/theme/forms.d.ts.map +1 -0
- package/dist/theme/forms.js +3 -0
- package/dist/theme/headless.d.ts +62 -0
- package/dist/theme/headless.d.ts.map +1 -0
- package/dist/theme/headless.js +1064 -0
- package/dist/theme/index.d.ts +41 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +38 -0
- package/dist/theme/portal.d.ts +6 -0
- package/dist/theme/portal.d.ts.map +1 -0
- package/dist/theme/portal.js +59 -0
- package/dist/theme/styles.css +4232 -0
- package/dist/theme/types.d.ts +363 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +1 -0
- package/dist/virtual.d.ts +65 -0
- package/dist/vite.d.ts +16 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +386 -0
- package/package.json +132 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import MiniSearch from 'minisearch';
|
|
2
|
+
import { createExcerpt, jsonResponse, normalizeSearchText, tokenizeSearchQuery, tokenizeSearchText } from './utils.js';
|
|
3
|
+
const miniSearchCache = new WeakMap();
|
|
4
|
+
const localSearchBoost = {
|
|
5
|
+
title: 5,
|
|
6
|
+
section: 4,
|
|
7
|
+
url: 1.5,
|
|
8
|
+
metadataText: 0.8,
|
|
9
|
+
content: 1
|
|
10
|
+
};
|
|
11
|
+
export function createLocalSearchProvider(records = []) {
|
|
12
|
+
let indexed = records;
|
|
13
|
+
return {
|
|
14
|
+
name: 'local-json',
|
|
15
|
+
index(nextRecords) {
|
|
16
|
+
indexed = nextRecords;
|
|
17
|
+
},
|
|
18
|
+
search(input) {
|
|
19
|
+
return searchRecords(indexed, input);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export const localSearchProvider = createLocalSearchProvider();
|
|
24
|
+
export function searchRecords(records, input) {
|
|
25
|
+
const query = normalizeSearchText(input.query);
|
|
26
|
+
if (!query)
|
|
27
|
+
return [];
|
|
28
|
+
const limit = input.limit ?? 10;
|
|
29
|
+
const entry = getMiniSearchIndex(records);
|
|
30
|
+
const primary = runLocalSearch(entry, input, 'AND');
|
|
31
|
+
const selected = primary.slice(0, limit);
|
|
32
|
+
if (selected.length < limit && tokenizeSearchQuery(input.query).length > 1) {
|
|
33
|
+
const seen = new Set(selected.map((hit) => hit.record.id));
|
|
34
|
+
const fallbackScoreCeiling = selected.at(-1)?.score;
|
|
35
|
+
selected.push(...runLocalSearch(entry, input, 'OR')
|
|
36
|
+
.filter((hit) => !seen.has(hit.record.id))
|
|
37
|
+
.map((hit) => ({
|
|
38
|
+
...hit,
|
|
39
|
+
score: fallbackScoreCeiling ? Math.min(hit.score * 0.6, fallbackScoreCeiling * 0.95) : hit.score * 0.6
|
|
40
|
+
}))
|
|
41
|
+
.slice(0, limit - selected.length));
|
|
42
|
+
}
|
|
43
|
+
return selected.map(({ record, score }) => ({
|
|
44
|
+
id: record.id,
|
|
45
|
+
title: record.title,
|
|
46
|
+
url: record.url,
|
|
47
|
+
...(record.section ? { section: record.section } : {}),
|
|
48
|
+
excerpt: createExcerpt(record.content, input.query),
|
|
49
|
+
score,
|
|
50
|
+
metadata: record.metadata
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
function runLocalSearch(entry, input, combineWith) {
|
|
54
|
+
const scoped = entry.index.search(input.query, {
|
|
55
|
+
prefix: true,
|
|
56
|
+
fuzzy: (term) => term.length > 4 ? 0.18 : false,
|
|
57
|
+
combineWith,
|
|
58
|
+
boost: localSearchBoost
|
|
59
|
+
});
|
|
60
|
+
return scoped
|
|
61
|
+
.map((hit) => {
|
|
62
|
+
const record = entry.recordsById.get(hit.id);
|
|
63
|
+
return record ? { record, score: scoreLocalSearchHit(record, hit.score, input.query) } : undefined;
|
|
64
|
+
})
|
|
65
|
+
.filter((item) => Boolean(item))
|
|
66
|
+
.filter((item) => matchesSearchScope(item.record, input))
|
|
67
|
+
.sort((a, b) => b.score - a.score)
|
|
68
|
+
.map((hit) => ({ ...hit, score: Number(hit.score.toFixed(4)) }));
|
|
69
|
+
}
|
|
70
|
+
export function filterSearchRecords(records, scope = {}) {
|
|
71
|
+
return records.filter((record) => matchesSearchScope(record, scope));
|
|
72
|
+
}
|
|
73
|
+
export function matchesSearchScope(record, scope = {}) {
|
|
74
|
+
return matchesMetadata(record.metadata.locale, scope.locale)
|
|
75
|
+
&& matchesMetadata(record.metadata.kind, scope.kind);
|
|
76
|
+
}
|
|
77
|
+
export async function createSearchResponse(records, request) {
|
|
78
|
+
const url = new URL(request.url);
|
|
79
|
+
const query = url.searchParams.get('q') ?? url.searchParams.get('query') ?? '';
|
|
80
|
+
const limit = clampLimit(Number(url.searchParams.get('limit') ?? 10));
|
|
81
|
+
const locale = readScopeParam(url, 'locale');
|
|
82
|
+
const kind = readScopeParam(url, 'kind');
|
|
83
|
+
const results = searchRecords(records, {
|
|
84
|
+
query,
|
|
85
|
+
limit,
|
|
86
|
+
...(locale ? { locale } : {}),
|
|
87
|
+
...(kind ? { kind } : {})
|
|
88
|
+
});
|
|
89
|
+
return jsonResponse({ query, results });
|
|
90
|
+
}
|
|
91
|
+
function getMiniSearchIndex(records) {
|
|
92
|
+
const cached = miniSearchCache.get(records);
|
|
93
|
+
if (cached)
|
|
94
|
+
return cached;
|
|
95
|
+
const documents = records.map(toMiniSearchDocument);
|
|
96
|
+
const index = new MiniSearch({
|
|
97
|
+
fields: ['title', 'section', 'url', 'content', 'metadataText'],
|
|
98
|
+
storeFields: ['id', 'title', 'section', 'url', 'content', 'metadata'],
|
|
99
|
+
idField: 'id',
|
|
100
|
+
searchOptions: {
|
|
101
|
+
prefix: true,
|
|
102
|
+
fuzzy: 0.18
|
|
103
|
+
},
|
|
104
|
+
tokenize: tokenizeSearchText,
|
|
105
|
+
processTerm: (term) => normalizeSearchText(term) || false
|
|
106
|
+
});
|
|
107
|
+
index.addAll(documents);
|
|
108
|
+
const entry = {
|
|
109
|
+
index,
|
|
110
|
+
recordsById: new Map(records.map((record) => [record.id, record]))
|
|
111
|
+
};
|
|
112
|
+
miniSearchCache.set(records, entry);
|
|
113
|
+
return entry;
|
|
114
|
+
}
|
|
115
|
+
function toMiniSearchDocument(record) {
|
|
116
|
+
return {
|
|
117
|
+
id: record.id,
|
|
118
|
+
title: record.title,
|
|
119
|
+
section: record.section ?? '',
|
|
120
|
+
url: record.url,
|
|
121
|
+
content: record.content,
|
|
122
|
+
metadataText: Object.values(record.metadata).flat().join(' '),
|
|
123
|
+
metadata: record.metadata
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function matchesMetadata(value, expected) {
|
|
127
|
+
if (!expected)
|
|
128
|
+
return true;
|
|
129
|
+
if (Array.isArray(value))
|
|
130
|
+
return value.some((item) => String(item) === expected);
|
|
131
|
+
return value === expected;
|
|
132
|
+
}
|
|
133
|
+
function scoreLocalSearchHit(record, score, query) {
|
|
134
|
+
const normalizedQuery = normalizeSearchText(query);
|
|
135
|
+
const title = normalizeSearchText(record.title);
|
|
136
|
+
const section = normalizeSearchText(record.section ?? '');
|
|
137
|
+
const url = normalizeSearchText(record.url);
|
|
138
|
+
const sourcePath = normalizeSearchText(typeof record.metadata.sourcePath === 'string' ? record.metadata.sourcePath : '');
|
|
139
|
+
const terms = tokenizeSearchQuery(query);
|
|
140
|
+
let multiplier = 1;
|
|
141
|
+
if (title === normalizedQuery || section === normalizedQuery) {
|
|
142
|
+
multiplier *= 1.6;
|
|
143
|
+
}
|
|
144
|
+
else if (title.startsWith(normalizedQuery) || section.startsWith(normalizedQuery)) {
|
|
145
|
+
multiplier *= 1.35;
|
|
146
|
+
}
|
|
147
|
+
else if (title.includes(normalizedQuery) || section.includes(normalizedQuery)) {
|
|
148
|
+
multiplier *= 1.2;
|
|
149
|
+
}
|
|
150
|
+
else if (terms.length > 1 && terms.every((term) => title.includes(term) || section.includes(term))) {
|
|
151
|
+
multiplier *= 1.15;
|
|
152
|
+
}
|
|
153
|
+
if (url.includes(normalizedQuery) || sourcePath.includes(normalizedQuery))
|
|
154
|
+
multiplier *= 1.1;
|
|
155
|
+
return score * multiplier;
|
|
156
|
+
}
|
|
157
|
+
function readScopeParam(url, key) {
|
|
158
|
+
const value = url.searchParams.get(key);
|
|
159
|
+
return value?.trim() || undefined;
|
|
160
|
+
}
|
|
161
|
+
function clampLimit(value) {
|
|
162
|
+
if (!Number.isFinite(value))
|
|
163
|
+
return 10;
|
|
164
|
+
return Math.min(50, Math.max(1, Math.floor(value)));
|
|
165
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { SvedocsResolvedConfig, SvedocsSearchRecord } from '../core.js';
|
|
2
|
+
import type { CloudflareAiSearchInstance, CloudflareAiSearchNamespace, SearchProvider, SearchQuery } from './types.js';
|
|
3
|
+
export interface SvedocsSearchRuntimeEnv {
|
|
4
|
+
SVEDOCS_AI_SEARCH?: CloudflareAiSearchInstance | CloudflareAiSearchNamespace | undefined;
|
|
5
|
+
ALGOLIA_APP_ID?: string | undefined;
|
|
6
|
+
ALGOLIA_SEARCH_KEY?: string | undefined;
|
|
7
|
+
ALGOLIA_API_KEY?: string | undefined;
|
|
8
|
+
ALGOLIA_INDEX_NAME?: string | undefined;
|
|
9
|
+
SVEDOCS_ALGOLIA_APP_ID?: string | undefined;
|
|
10
|
+
SVEDOCS_ALGOLIA_SEARCH_KEY?: string | undefined;
|
|
11
|
+
SVEDOCS_ALGOLIA_API_KEY?: string | undefined;
|
|
12
|
+
SVEDOCS_ALGOLIA_INDEX_NAME?: string | undefined;
|
|
13
|
+
TYPESENSE_HOST?: string | undefined;
|
|
14
|
+
TYPESENSE_URL?: string | undefined;
|
|
15
|
+
TYPESENSE_SEARCH_KEY?: string | undefined;
|
|
16
|
+
TYPESENSE_API_KEY?: string | undefined;
|
|
17
|
+
TYPESENSE_COLLECTION?: string | undefined;
|
|
18
|
+
TYPESENSE_COLLECTION_NAME?: string | undefined;
|
|
19
|
+
SVEDOCS_TYPESENSE_HOST?: string | undefined;
|
|
20
|
+
SVEDOCS_TYPESENSE_URL?: string | undefined;
|
|
21
|
+
SVEDOCS_TYPESENSE_SEARCH_KEY?: string | undefined;
|
|
22
|
+
SVEDOCS_TYPESENSE_API_KEY?: string | undefined;
|
|
23
|
+
SVEDOCS_TYPESENSE_COLLECTION?: string | undefined;
|
|
24
|
+
SVEDOCS_TYPESENSE_COLLECTION_NAME?: string | undefined;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
export interface CreateConfiguredSearchProviderOptions {
|
|
28
|
+
config: Pick<SvedocsResolvedConfig, 'search' | 'cloudflare'>;
|
|
29
|
+
records?: SvedocsSearchRecord[];
|
|
30
|
+
env?: SvedocsSearchRuntimeEnv;
|
|
31
|
+
provider?: string;
|
|
32
|
+
fetch?: typeof fetch;
|
|
33
|
+
}
|
|
34
|
+
export interface CreateConfiguredSearchResponseOptions extends Omit<CreateConfiguredSearchProviderOptions, 'config' | 'records' | 'provider'> {
|
|
35
|
+
provider?: string;
|
|
36
|
+
}
|
|
37
|
+
export declare function createConfiguredSearchProvider(options: CreateConfiguredSearchProviderOptions): SearchProvider;
|
|
38
|
+
export declare function createConfiguredSearchResponse(config: Pick<SvedocsResolvedConfig, 'search' | 'cloudflare'>, records: SvedocsSearchRecord[], request: Request, options?: CreateConfiguredSearchResponseOptions): Promise<Response>;
|
|
39
|
+
export declare function readSearchQuery(request: Request): SearchQuery;
|
|
40
|
+
export declare function readProviderParam(request: Request): string | undefined;
|
|
41
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/search/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAK7E,OAAO,KAAK,EACV,0BAA0B,EAC1B,2BAA2B,EAC3B,cAAc,EACd,WAAW,EAEZ,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,uBAAuB;IACtC,iBAAiB,CAAC,EAAE,0BAA0B,GAAG,2BAA2B,GAAG,SAAS,CAAC;IACzF,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,sBAAsB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,0BAA0B,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,uBAAuB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,0BAA0B,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,yBAAyB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,sBAAsB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,4BAA4B,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClD,yBAAyB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,4BAA4B,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClD,iCAAiC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,qCAAqC;IACpD,MAAM,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,GAAG,YAAY,CAAC,CAAC;IAC7D,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAChC,GAAG,CAAC,EAAE,uBAAuB,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,qCAAsC,SAAQ,IAAI,CAAC,qCAAqC,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;IAC3I,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,qCAAqC,GAAG,cAAc,CAmD7G;AAED,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,GAAG,YAAY,CAAC,EAC5D,OAAO,EAAE,mBAAmB,EAAE,EAC9B,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,qCAA0C,GAClD,OAAO,CAAC,QAAQ,CAAC,CAkBnB;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAU7D;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAGtE"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { createAlgoliaSearchProvider } from './algolia.js';
|
|
2
|
+
import { createCloudflareAiSearchProvider } from './cloudflare.js';
|
|
3
|
+
import { createLocalSearchProvider, createSearchResponse } from './local.js';
|
|
4
|
+
import { createTypesenseSearchProvider } from './typesense.js';
|
|
5
|
+
import { jsonResponse } from './utils.js';
|
|
6
|
+
export function createConfiguredSearchProvider(options) {
|
|
7
|
+
const provider = normalizeProviderName(options.provider ?? options.config.search.provider);
|
|
8
|
+
const records = options.records ?? [];
|
|
9
|
+
if (!options.config.search.enabled)
|
|
10
|
+
return createDisabledSearchProvider();
|
|
11
|
+
if (provider === 'cloudflare-ai-search') {
|
|
12
|
+
const binding = readCloudflareAiSearchBinding(options.env, options.config);
|
|
13
|
+
if (binding) {
|
|
14
|
+
return createCloudflareAiSearchProvider({
|
|
15
|
+
binding,
|
|
16
|
+
instanceName: options.config.cloudflare.aiSearch.instanceName,
|
|
17
|
+
namespace: Boolean(options.config.cloudflare.aiSearch.namespace)
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return createLocalSearchProvider(records);
|
|
21
|
+
}
|
|
22
|
+
if (provider === 'algolia') {
|
|
23
|
+
const appId = readFirstEnv(options.env, ['SVEDOCS_ALGOLIA_APP_ID', 'ALGOLIA_APP_ID']);
|
|
24
|
+
const apiKey = readFirstEnv(options.env, ['SVEDOCS_ALGOLIA_SEARCH_KEY', 'SVEDOCS_ALGOLIA_API_KEY', 'ALGOLIA_SEARCH_KEY', 'ALGOLIA_API_KEY']);
|
|
25
|
+
const indexName = readFirstEnv(options.env, ['SVEDOCS_ALGOLIA_INDEX_NAME', 'ALGOLIA_INDEX_NAME']);
|
|
26
|
+
if (appId && apiKey && indexName) {
|
|
27
|
+
return createAlgoliaSearchProvider({
|
|
28
|
+
appId,
|
|
29
|
+
apiKey,
|
|
30
|
+
indexName,
|
|
31
|
+
filters: createAlgoliaScopeFilters,
|
|
32
|
+
...(options.fetch ? { fetch: options.fetch } : {})
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return createLocalSearchProvider(records);
|
|
36
|
+
}
|
|
37
|
+
if (provider === 'typesense') {
|
|
38
|
+
const host = readFirstEnv(options.env, ['SVEDOCS_TYPESENSE_HOST', 'SVEDOCS_TYPESENSE_URL', 'TYPESENSE_HOST', 'TYPESENSE_URL']);
|
|
39
|
+
const apiKey = readFirstEnv(options.env, ['SVEDOCS_TYPESENSE_SEARCH_KEY', 'SVEDOCS_TYPESENSE_API_KEY', 'TYPESENSE_SEARCH_KEY', 'TYPESENSE_API_KEY']);
|
|
40
|
+
const collection = readFirstEnv(options.env, [
|
|
41
|
+
'SVEDOCS_TYPESENSE_COLLECTION',
|
|
42
|
+
'SVEDOCS_TYPESENSE_COLLECTION_NAME',
|
|
43
|
+
'TYPESENSE_COLLECTION',
|
|
44
|
+
'TYPESENSE_COLLECTION_NAME'
|
|
45
|
+
]) ?? 'docs';
|
|
46
|
+
if (host && apiKey) {
|
|
47
|
+
return createTypesenseSearchProvider({
|
|
48
|
+
host,
|
|
49
|
+
apiKey,
|
|
50
|
+
collection,
|
|
51
|
+
filterBy: createTypesenseScopeFilters,
|
|
52
|
+
...(options.fetch ? { fetch: options.fetch } : {})
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return createLocalSearchProvider(records);
|
|
56
|
+
}
|
|
57
|
+
return createLocalSearchProvider(records);
|
|
58
|
+
}
|
|
59
|
+
export async function createConfiguredSearchResponse(config, records, request, options = {}) {
|
|
60
|
+
if (!config.search.enabled) {
|
|
61
|
+
return jsonResponse({ query: readSearchQuery(request).query, results: [] });
|
|
62
|
+
}
|
|
63
|
+
const providerName = options.provider ?? config.search.provider;
|
|
64
|
+
const provider = createConfiguredSearchProvider({
|
|
65
|
+
config,
|
|
66
|
+
records,
|
|
67
|
+
provider: providerName,
|
|
68
|
+
...(options.env ? { env: options.env } : {}),
|
|
69
|
+
...(options.fetch ? { fetch: options.fetch } : {})
|
|
70
|
+
});
|
|
71
|
+
if (provider.name === 'local-json' || provider.name === 'disabled') {
|
|
72
|
+
return createSearchResponse(records, request);
|
|
73
|
+
}
|
|
74
|
+
const query = readSearchQuery(request);
|
|
75
|
+
const results = await provider.search(query);
|
|
76
|
+
return jsonResponse({ query: query.query, provider: provider.name, results });
|
|
77
|
+
}
|
|
78
|
+
export function readSearchQuery(request) {
|
|
79
|
+
const url = new URL(request.url);
|
|
80
|
+
const locale = readScopeParam(url, 'locale');
|
|
81
|
+
const kind = readScopeParam(url, 'kind');
|
|
82
|
+
return {
|
|
83
|
+
query: url.searchParams.get('q') ?? url.searchParams.get('query') ?? '',
|
|
84
|
+
limit: clampLimit(Number(url.searchParams.get('limit') ?? 10)),
|
|
85
|
+
...(locale ? { locale } : {}),
|
|
86
|
+
...(kind ? { kind } : {})
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
export function readProviderParam(request) {
|
|
90
|
+
const provider = new URL(request.url).searchParams.get('provider')?.trim();
|
|
91
|
+
return provider || undefined;
|
|
92
|
+
}
|
|
93
|
+
function createDisabledSearchProvider() {
|
|
94
|
+
return {
|
|
95
|
+
name: 'disabled',
|
|
96
|
+
index() { },
|
|
97
|
+
search() {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function readCloudflareAiSearchBinding(env, config) {
|
|
103
|
+
const bindingName = config.cloudflare.aiSearch.binding;
|
|
104
|
+
const dynamicBinding = env?.[bindingName];
|
|
105
|
+
if (isCloudflareAiSearchBinding(dynamicBinding))
|
|
106
|
+
return dynamicBinding;
|
|
107
|
+
if (isCloudflareAiSearchBinding(env?.SVEDOCS_AI_SEARCH))
|
|
108
|
+
return env.SVEDOCS_AI_SEARCH;
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
function isCloudflareAiSearchBinding(value) {
|
|
112
|
+
if (!value || typeof value !== 'object')
|
|
113
|
+
return false;
|
|
114
|
+
return 'search' in value || 'get' in value;
|
|
115
|
+
}
|
|
116
|
+
function readFirstEnv(env, keys) {
|
|
117
|
+
for (const key of keys) {
|
|
118
|
+
const value = env?.[key];
|
|
119
|
+
if (typeof value === 'string' && value.trim())
|
|
120
|
+
return value.trim();
|
|
121
|
+
}
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
function createAlgoliaScopeFilters(query) {
|
|
125
|
+
return [
|
|
126
|
+
query.locale ? `locale:${quoteAlgoliaFilterValue(query.locale)}` : undefined,
|
|
127
|
+
query.kind ? `kind:${quoteAlgoliaFilterValue(query.kind)}` : undefined
|
|
128
|
+
].filter(Boolean).join(' AND ') || undefined;
|
|
129
|
+
}
|
|
130
|
+
function quoteAlgoliaFilterValue(value) {
|
|
131
|
+
return /^[\w-]+$/.test(value) ? value : JSON.stringify(value);
|
|
132
|
+
}
|
|
133
|
+
function createTypesenseScopeFilters(query) {
|
|
134
|
+
return [
|
|
135
|
+
query.locale ? `locale:=${quoteTypesenseFilterValue(query.locale)}` : undefined,
|
|
136
|
+
query.kind ? `kind:=${quoteTypesenseFilterValue(query.kind)}` : undefined
|
|
137
|
+
].filter(Boolean).join(' && ') || undefined;
|
|
138
|
+
}
|
|
139
|
+
function quoteTypesenseFilterValue(value) {
|
|
140
|
+
return /^[\w-]+$/.test(value) ? value : `\`${value.replace(/`/g, '\\`')}\``;
|
|
141
|
+
}
|
|
142
|
+
function normalizeProviderName(provider) {
|
|
143
|
+
return provider?.trim().toLowerCase() || 'local';
|
|
144
|
+
}
|
|
145
|
+
function readScopeParam(url, key) {
|
|
146
|
+
return url.searchParams.get(key)?.trim() || undefined;
|
|
147
|
+
}
|
|
148
|
+
function clampLimit(value) {
|
|
149
|
+
if (!Number.isFinite(value))
|
|
150
|
+
return 10;
|
|
151
|
+
return Math.min(50, Math.max(1, Math.floor(value)));
|
|
152
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { SvedocsSearchRecord } from '../core.js';
|
|
2
|
+
export interface SearchQuery {
|
|
3
|
+
query: string;
|
|
4
|
+
limit?: number;
|
|
5
|
+
locale?: string;
|
|
6
|
+
kind?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface SearchScope {
|
|
9
|
+
locale?: string;
|
|
10
|
+
kind?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface SearchResult {
|
|
13
|
+
id: string;
|
|
14
|
+
title: string;
|
|
15
|
+
url: string;
|
|
16
|
+
excerpt: string;
|
|
17
|
+
score: number;
|
|
18
|
+
section?: string;
|
|
19
|
+
metadata: SvedocsSearchRecord['metadata'];
|
|
20
|
+
}
|
|
21
|
+
export interface SearchProvider {
|
|
22
|
+
name: string;
|
|
23
|
+
index(records: SvedocsSearchRecord[]): Promise<void> | void;
|
|
24
|
+
search(query: SearchQuery): Promise<SearchResult[]> | SearchResult[];
|
|
25
|
+
}
|
|
26
|
+
export interface CloudflareAiSearchSyncDocument {
|
|
27
|
+
id: string;
|
|
28
|
+
title: string;
|
|
29
|
+
url: string;
|
|
30
|
+
content: string;
|
|
31
|
+
metadata: Record<string, string>;
|
|
32
|
+
}
|
|
33
|
+
export interface CloudflareAiSearchSyncOptions {
|
|
34
|
+
records: SvedocsSearchRecord[];
|
|
35
|
+
accountId?: string;
|
|
36
|
+
apiToken?: string;
|
|
37
|
+
instanceName: string;
|
|
38
|
+
namespace?: string;
|
|
39
|
+
endpoint?: string;
|
|
40
|
+
dryRun?: boolean;
|
|
41
|
+
waitForCompletion?: boolean;
|
|
42
|
+
strategy?: 'append' | 'replace';
|
|
43
|
+
deleteIds?: string[];
|
|
44
|
+
existingIds?: string[];
|
|
45
|
+
batchSize?: number;
|
|
46
|
+
maxRetries?: number;
|
|
47
|
+
retryDelayMs?: number;
|
|
48
|
+
fetch?: typeof fetch;
|
|
49
|
+
}
|
|
50
|
+
export interface CloudflareAiSearchSyncResult {
|
|
51
|
+
provider: 'cloudflare-ai-search';
|
|
52
|
+
instanceName: string;
|
|
53
|
+
endpoint: string;
|
|
54
|
+
dryRun: boolean;
|
|
55
|
+
indexed: number;
|
|
56
|
+
deleted: number;
|
|
57
|
+
failed: number;
|
|
58
|
+
planned: {
|
|
59
|
+
uploadIds: string[];
|
|
60
|
+
deleteIds: string[];
|
|
61
|
+
};
|
|
62
|
+
errors: Array<{
|
|
63
|
+
id: string;
|
|
64
|
+
message: string;
|
|
65
|
+
}>;
|
|
66
|
+
}
|
|
67
|
+
export interface CloudflareAiSearchInstance {
|
|
68
|
+
search(input: CloudflareAiSearchInput): Promise<CloudflareAiSearchOutput>;
|
|
69
|
+
chatCompletions?(input: CloudflareAiSearchChatInput): Promise<CloudflareAiSearchChatOutput | ReadableStream<Uint8Array> | Response>;
|
|
70
|
+
items?: CloudflareAiSearchItemsBinding;
|
|
71
|
+
}
|
|
72
|
+
export interface CloudflareAiSearchItemsBinding {
|
|
73
|
+
upload(input: File | Blob | ArrayBuffer | string, options?: CloudflareAiSearchItemUploadOptions): Promise<unknown>;
|
|
74
|
+
uploadAndPoll?(input: File | Blob | ArrayBuffer | string, options?: CloudflareAiSearchItemUploadOptions): Promise<unknown>;
|
|
75
|
+
delete?(itemId: string): Promise<unknown>;
|
|
76
|
+
get?(itemId: string): Promise<unknown>;
|
|
77
|
+
list?(options?: {
|
|
78
|
+
limit?: number;
|
|
79
|
+
cursor?: string;
|
|
80
|
+
}): Promise<unknown>;
|
|
81
|
+
}
|
|
82
|
+
export interface CloudflareAiSearchItemUploadOptions {
|
|
83
|
+
id?: string;
|
|
84
|
+
metadata?: Record<string, string>;
|
|
85
|
+
contentType?: string;
|
|
86
|
+
filename?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface CloudflareAiSearchMessage {
|
|
89
|
+
role: 'system' | 'developer' | 'user' | 'assistant' | 'tool';
|
|
90
|
+
content: string;
|
|
91
|
+
}
|
|
92
|
+
export interface CloudflareAiSearchInput {
|
|
93
|
+
query?: string;
|
|
94
|
+
messages?: CloudflareAiSearchMessage[];
|
|
95
|
+
ai_search_options?: {
|
|
96
|
+
instance_ids?: string[];
|
|
97
|
+
query_rewrite?: boolean | {
|
|
98
|
+
enabled?: boolean;
|
|
99
|
+
model?: string;
|
|
100
|
+
};
|
|
101
|
+
retrieval?: {
|
|
102
|
+
retrieval_type?: 'vector' | 'keyword' | 'hybrid';
|
|
103
|
+
match_threshold?: number;
|
|
104
|
+
max_num_results?: number;
|
|
105
|
+
filters?: Record<string, unknown>;
|
|
106
|
+
context_expansion?: number;
|
|
107
|
+
fusion_method?: 'rrf' | 'max';
|
|
108
|
+
keyword_match_mode?: string;
|
|
109
|
+
reranking?: {
|
|
110
|
+
enabled?: boolean;
|
|
111
|
+
model?: string;
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
max_num_results?: number;
|
|
116
|
+
}
|
|
117
|
+
export interface CloudflareAiSearchItem {
|
|
118
|
+
id?: string;
|
|
119
|
+
title?: string;
|
|
120
|
+
url?: string;
|
|
121
|
+
content?: string;
|
|
122
|
+
text?: string;
|
|
123
|
+
score?: number;
|
|
124
|
+
metadata?: Record<string, unknown>;
|
|
125
|
+
}
|
|
126
|
+
export interface CloudflareAiSearchChunk {
|
|
127
|
+
id?: string;
|
|
128
|
+
type?: string;
|
|
129
|
+
text?: string;
|
|
130
|
+
content?: string;
|
|
131
|
+
score?: number;
|
|
132
|
+
metadata?: Record<string, unknown>;
|
|
133
|
+
attributes?: Record<string, unknown>;
|
|
134
|
+
item?: {
|
|
135
|
+
id?: string;
|
|
136
|
+
key?: string;
|
|
137
|
+
filename?: string;
|
|
138
|
+
title?: string;
|
|
139
|
+
metadata?: Record<string, unknown>;
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
export interface CloudflareAiSearchOutput {
|
|
143
|
+
response?: string;
|
|
144
|
+
answer?: string;
|
|
145
|
+
data?: CloudflareAiSearchItem[];
|
|
146
|
+
chunks?: CloudflareAiSearchChunk[];
|
|
147
|
+
}
|
|
148
|
+
export interface CloudflareAiSearchChatInput {
|
|
149
|
+
messages: CloudflareAiSearchMessage[];
|
|
150
|
+
ai_search_options?: CloudflareAiSearchInput['ai_search_options'];
|
|
151
|
+
model?: string;
|
|
152
|
+
stream?: boolean;
|
|
153
|
+
}
|
|
154
|
+
export interface CloudflareAiSearchChatOutput extends CloudflareAiSearchOutput {
|
|
155
|
+
choices?: Array<{
|
|
156
|
+
text?: string;
|
|
157
|
+
message?: {
|
|
158
|
+
content?: string;
|
|
159
|
+
};
|
|
160
|
+
}>;
|
|
161
|
+
citations?: Array<{
|
|
162
|
+
title?: string;
|
|
163
|
+
url?: string;
|
|
164
|
+
section?: string;
|
|
165
|
+
}>;
|
|
166
|
+
}
|
|
167
|
+
export interface CloudflareAiSearchNamespace {
|
|
168
|
+
get(instanceName: string): CloudflareAiSearchInstance;
|
|
169
|
+
search?(input: CloudflareAiSearchInput): Promise<CloudflareAiSearchOutput>;
|
|
170
|
+
chatCompletions?(input: CloudflareAiSearchChatInput): Promise<CloudflareAiSearchChatOutput | ReadableStream<Uint8Array> | Response>;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/search/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SearchProvider, SearchQuery } from './types.js';
|
|
2
|
+
export interface TypesenseSearchProviderOptions {
|
|
3
|
+
host: string;
|
|
4
|
+
apiKey: string;
|
|
5
|
+
collection: string | ((query: SearchQuery) => string);
|
|
6
|
+
queryBy?: string | string[];
|
|
7
|
+
filterBy?: string | ((query: SearchQuery) => string | undefined);
|
|
8
|
+
fetch?: typeof fetch;
|
|
9
|
+
}
|
|
10
|
+
export declare function createTypesenseSearchProvider(options: TypesenseSearchProviderOptions): SearchProvider;
|
|
11
|
+
//# sourceMappingURL=typesense.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typesense.d.ts","sourceRoot":"","sources":["../../src/search/typesense.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAgB,MAAM,YAAY,CAAC;AAG5E,MAAM,WAAW,8BAA8B;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,CAAC,CAAC;IACtD,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC;IACjE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AA6BD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,8BAA8B,GAAG,cAAc,CAsBrG"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { matchesSearchScope } from './local.js';
|
|
2
|
+
import { createExcerpt, stringMetadata, stringifyMetadata } from './utils.js';
|
|
3
|
+
export function createTypesenseSearchProvider(options) {
|
|
4
|
+
return {
|
|
5
|
+
name: 'typesense',
|
|
6
|
+
index() {
|
|
7
|
+
// Typesense indexing is commonly handled by a crawler or CI sync script.
|
|
8
|
+
},
|
|
9
|
+
async search(query) {
|
|
10
|
+
const requestFetch = options.fetch ?? fetch;
|
|
11
|
+
const response = await requestFetch(createTypesenseSearchUrl(options, query), {
|
|
12
|
+
headers: {
|
|
13
|
+
'x-typesense-api-key': options.apiKey
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
throw new Error(`Typesense search returned ${response.status}: ${(await response.text()).slice(0, 500)}`);
|
|
18
|
+
}
|
|
19
|
+
const payload = await response.json();
|
|
20
|
+
return (payload.hits ?? [])
|
|
21
|
+
.map((hit, index) => createTypesenseResult(hit, index, query.query))
|
|
22
|
+
.filter((result) => matchesSearchScope({ metadata: result.metadata }, query));
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function createTypesenseSearchUrl(options, query) {
|
|
27
|
+
const collection = typeof options.collection === 'function' ? options.collection(query) : options.collection;
|
|
28
|
+
const base = options.host.replace(/\/$/, '');
|
|
29
|
+
const url = new URL(`${base}/collections/${encodeURIComponent(collection)}/documents/search`);
|
|
30
|
+
url.searchParams.set('q', query.query || '*');
|
|
31
|
+
url.searchParams.set('query_by', Array.isArray(options.queryBy) ? options.queryBy.join(',') : options.queryBy ?? 'title,section,content');
|
|
32
|
+
url.searchParams.set('per_page', String(query.limit ?? 10));
|
|
33
|
+
const filterBy = typeof options.filterBy === 'function' ? options.filterBy(query) : options.filterBy;
|
|
34
|
+
if (filterBy)
|
|
35
|
+
url.searchParams.set('filter_by', filterBy);
|
|
36
|
+
return url.toString();
|
|
37
|
+
}
|
|
38
|
+
function createTypesenseResult(hit, index, query) {
|
|
39
|
+
const document = hit.document ?? {};
|
|
40
|
+
const metadata = normalizeTypesenseMetadata(document);
|
|
41
|
+
const section = stringMetadata(document.section) ?? stringMetadata(metadata.section);
|
|
42
|
+
const content = stringMetadata(document.content) ?? stringMetadata(metadata.content) ?? stringMetadata(document.title) ?? '';
|
|
43
|
+
return {
|
|
44
|
+
id: stringMetadata(document.id) ?? stringMetadata(document.objectID) ?? `typesense:${index}`,
|
|
45
|
+
title: stringMetadata(document.title) ?? stringMetadata(metadata.title) ?? 'Result',
|
|
46
|
+
url: createTypesenseUrl(document, metadata),
|
|
47
|
+
...(section ? { section } : {}),
|
|
48
|
+
excerpt: createExcerpt(content, query),
|
|
49
|
+
score: createTypesenseScore(hit, index),
|
|
50
|
+
metadata
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function createTypesenseUrl(document, metadata) {
|
|
54
|
+
const url = stringMetadata(document.url) ?? stringMetadata(metadata.url) ?? '#';
|
|
55
|
+
const anchor = stringMetadata(document.anchor) ?? stringMetadata(metadata.anchor);
|
|
56
|
+
if (!anchor || url.includes('#'))
|
|
57
|
+
return url;
|
|
58
|
+
return `${url}#${anchor}`;
|
|
59
|
+
}
|
|
60
|
+
function normalizeTypesenseMetadata(document) {
|
|
61
|
+
const metadata = stringifyMetadata({
|
|
62
|
+
...(document.metadata ?? {}),
|
|
63
|
+
locale: document.locale ?? document.metadata?.locale,
|
|
64
|
+
kind: document.kind ?? document.metadata?.kind
|
|
65
|
+
});
|
|
66
|
+
const embedded = stringMetadata(document.svedocs) ?? stringMetadata(document.metadata?.svedocs);
|
|
67
|
+
if (!embedded)
|
|
68
|
+
return metadata;
|
|
69
|
+
try {
|
|
70
|
+
const parsed = JSON.parse(embedded);
|
|
71
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
72
|
+
return metadata;
|
|
73
|
+
return {
|
|
74
|
+
...metadata,
|
|
75
|
+
...stringifyMetadata(parsed)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return metadata;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function createTypesenseScore(hit, index) {
|
|
83
|
+
if (typeof hit.text_match === 'number')
|
|
84
|
+
return hit.text_match;
|
|
85
|
+
const score = hit.text_match_info?.score;
|
|
86
|
+
if (typeof score === 'number')
|
|
87
|
+
return score;
|
|
88
|
+
if (typeof score === 'string' && Number.isFinite(Number(score)))
|
|
89
|
+
return Number(score);
|
|
90
|
+
return 1 / (index + 1);
|
|
91
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function createExcerpt(content: string, query: string): string;
|
|
2
|
+
export declare function normalizeSearchText(value: string): string;
|
|
3
|
+
export declare function tokenizeSearchText(value: string): string[];
|
|
4
|
+
export declare function tokenizeSearchQuery(query: string): string[];
|
|
5
|
+
export declare function stringMetadata(value: unknown): string | undefined;
|
|
6
|
+
export declare function stringifyMetadata(metadata: Record<string, unknown>): Record<string, string>;
|
|
7
|
+
export declare function uniqueStrings(values: string[]): string[];
|
|
8
|
+
export declare function jsonResponse(value: unknown, status?: number): Response;
|
|
9
|
+
export declare function chunkArray<T>(items: T[], size: number): T[][];
|
|
10
|
+
export declare function wait(ms: number): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/search/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAWpE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOzD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAI1D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAE3D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAEjE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAM3F;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAExD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,SAAM,GAAG,QAAQ,CAOnE;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,CAO7D;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9C"}
|