svedocs 0.1.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/LICENSE +5 -0
  2. package/README.md +38 -0
  3. package/dist/ai/openai-compatible.d.ts +13 -0
  4. package/dist/ai/openai-compatible.d.ts.map +1 -0
  5. package/dist/ai/openai-compatible.js +92 -0
  6. package/dist/ai/providers.d.ts +19 -0
  7. package/dist/ai/providers.d.ts.map +1 -0
  8. package/dist/ai/providers.js +185 -0
  9. package/dist/ai/rate-limit.d.ts +18 -0
  10. package/dist/ai/rate-limit.d.ts.map +1 -0
  11. package/dist/ai/rate-limit.js +52 -0
  12. package/dist/ai/response.d.ts +4 -0
  13. package/dist/ai/response.d.ts.map +1 -0
  14. package/dist/ai/response.js +151 -0
  15. package/dist/ai/runtime.d.ts +30 -0
  16. package/dist/ai/runtime.d.ts.map +1 -0
  17. package/dist/ai/runtime.js +105 -0
  18. package/dist/ai/types.d.ts +93 -0
  19. package/dist/ai/types.d.ts.map +1 -0
  20. package/dist/ai/types.js +1 -0
  21. package/dist/ai.d.ts +7 -0
  22. package/dist/ai.d.ts.map +1 -0
  23. package/dist/ai.js +6 -0
  24. package/dist/ambient.d.ts +5 -0
  25. package/dist/cloudflare.d.ts +27 -0
  26. package/dist/cloudflare.d.ts.map +1 -0
  27. package/dist/cloudflare.js +146 -0
  28. package/dist/config.d.ts +311 -0
  29. package/dist/config.d.ts.map +1 -0
  30. package/dist/config.js +243 -0
  31. package/dist/core/checks.d.ts +4 -0
  32. package/dist/core/checks.d.ts.map +1 -0
  33. package/dist/core/checks.js +252 -0
  34. package/dist/core/config.d.ts +5 -0
  35. package/dist/core/config.d.ts.map +1 -0
  36. package/dist/core/config.js +182 -0
  37. package/dist/core/content.d.ts +7 -0
  38. package/dist/core/content.d.ts.map +1 -0
  39. package/dist/core/content.js +211 -0
  40. package/dist/core/links.d.ts +8 -0
  41. package/dist/core/links.d.ts.map +1 -0
  42. package/dist/core/links.js +94 -0
  43. package/dist/core/navigation.d.ts +5 -0
  44. package/dist/core/navigation.d.ts.map +1 -0
  45. package/dist/core/navigation.js +144 -0
  46. package/dist/core/search.d.ts +5 -0
  47. package/dist/core/search.d.ts.map +1 -0
  48. package/dist/core/search.js +41 -0
  49. package/dist/core/types.d.ts +269 -0
  50. package/dist/core/types.d.ts.map +1 -0
  51. package/dist/core/types.js +4 -0
  52. package/dist/core/utils.d.ts +12 -0
  53. package/dist/core/utils.d.ts.map +1 -0
  54. package/dist/core/utils.js +52 -0
  55. package/dist/core.d.ts +8 -0
  56. package/dist/core.d.ts.map +1 -0
  57. package/dist/core.js +7 -0
  58. package/dist/index.d.ts +6 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +3 -0
  61. package/dist/mdx/ast.d.ts +32 -0
  62. package/dist/mdx/ast.d.ts.map +1 -0
  63. package/dist/mdx/ast.js +148 -0
  64. package/dist/mdx/code.d.ts +14 -0
  65. package/dist/mdx/code.d.ts.map +1 -0
  66. package/dist/mdx/code.js +315 -0
  67. package/dist/mdx/compile.d.ts +26 -0
  68. package/dist/mdx/compile.d.ts.map +1 -0
  69. package/dist/mdx/compile.js +63 -0
  70. package/dist/mdx/diff.d.ts +5 -0
  71. package/dist/mdx/diff.d.ts.map +1 -0
  72. package/dist/mdx/diff.js +160 -0
  73. package/dist/mdx/utils.d.ts +10 -0
  74. package/dist/mdx/utils.d.ts.map +1 -0
  75. package/dist/mdx/utils.js +64 -0
  76. package/dist/og/image.d.ts +21 -0
  77. package/dist/og/image.d.ts.map +1 -0
  78. package/dist/og/image.js +216 -0
  79. package/dist/og/metadata.d.ts +7 -0
  80. package/dist/og/metadata.d.ts.map +1 -0
  81. package/dist/og/metadata.js +160 -0
  82. package/dist/og/types.d.ts +59 -0
  83. package/dist/og/types.d.ts.map +1 -0
  84. package/dist/og/types.js +1 -0
  85. package/dist/og.d.ts +4 -0
  86. package/dist/og.d.ts.map +1 -0
  87. package/dist/og.js +3 -0
  88. package/dist/search/algolia.d.ts +10 -0
  89. package/dist/search/algolia.d.ts.map +1 -0
  90. package/dist/search/algolia.js +82 -0
  91. package/dist/search/cloudflare-sync.d.ts +5 -0
  92. package/dist/search/cloudflare-sync.d.ts.map +1 -0
  93. package/dist/search/cloudflare-sync.js +169 -0
  94. package/dist/search/cloudflare.d.ts +9 -0
  95. package/dist/search/cloudflare.d.ts.map +1 -0
  96. package/dist/search/cloudflare.js +115 -0
  97. package/dist/search/local.d.ts +9 -0
  98. package/dist/search/local.d.ts.map +1 -0
  99. package/dist/search/local.js +122 -0
  100. package/dist/search/runtime.d.ts +41 -0
  101. package/dist/search/runtime.d.ts.map +1 -0
  102. package/dist/search/runtime.js +151 -0
  103. package/dist/search/types.d.ts +172 -0
  104. package/dist/search/types.d.ts.map +1 -0
  105. package/dist/search/types.js +1 -0
  106. package/dist/search/typesense.d.ts +11 -0
  107. package/dist/search/typesense.d.ts.map +1 -0
  108. package/dist/search/typesense.js +91 -0
  109. package/dist/search/utils.d.ts +10 -0
  110. package/dist/search/utils.d.ts.map +1 -0
  111. package/dist/search/utils.js +55 -0
  112. package/dist/search.d.ts +8 -0
  113. package/dist/search.d.ts.map +1 -0
  114. package/dist/search.js +7 -0
  115. package/dist/svelte.d.ts +24 -0
  116. package/dist/svelte.d.ts.map +1 -0
  117. package/dist/svelte.js +51 -0
  118. package/dist/testing.d.ts +3 -0
  119. package/dist/testing.d.ts.map +1 -0
  120. package/dist/testing.js +23 -0
  121. package/dist/theme/AskAiPanel.svelte +433 -0
  122. package/dist/theme/AskAiPanel.svelte.d.ts +27 -0
  123. package/dist/theme/AskAiPanel.svelte.d.ts.map +1 -0
  124. package/dist/theme/Button.svelte +34 -0
  125. package/dist/theme/Button.svelte.d.ts +41 -0
  126. package/dist/theme/Button.svelte.d.ts.map +1 -0
  127. package/dist/theme/Checkbox.svelte +63 -0
  128. package/dist/theme/Checkbox.svelte.d.ts +45 -0
  129. package/dist/theme/Checkbox.svelte.d.ts.map +1 -0
  130. package/dist/theme/CodeBlock.svelte +6 -0
  131. package/dist/theme/CodeBlock.svelte.d.ts +22 -0
  132. package/dist/theme/CodeBlock.svelte.d.ts.map +1 -0
  133. package/dist/theme/DocPage.svelte +121 -0
  134. package/dist/theme/DocPage.svelte.d.ts +33 -0
  135. package/dist/theme/DocPage.svelte.d.ts.map +1 -0
  136. package/dist/theme/DocsApp.svelte +78 -0
  137. package/dist/theme/DocsApp.svelte.d.ts +63 -0
  138. package/dist/theme/DocsApp.svelte.d.ts.map +1 -0
  139. package/dist/theme/DocsLayout.svelte +167 -0
  140. package/dist/theme/DocsLayout.svelte.d.ts +40 -0
  141. package/dist/theme/DocsLayout.svelte.d.ts.map +1 -0
  142. package/dist/theme/FloatingToolbar.svelte +73 -0
  143. package/dist/theme/FloatingToolbar.svelte.d.ts +22 -0
  144. package/dist/theme/FloatingToolbar.svelte.d.ts.map +1 -0
  145. package/dist/theme/FormField.svelte +41 -0
  146. package/dist/theme/FormField.svelte.d.ts +35 -0
  147. package/dist/theme/FormField.svelte.d.ts.map +1 -0
  148. package/dist/theme/HomePage.svelte +228 -0
  149. package/dist/theme/HomePage.svelte.d.ts +58 -0
  150. package/dist/theme/HomePage.svelte.d.ts.map +1 -0
  151. package/dist/theme/Input.svelte +36 -0
  152. package/dist/theme/Input.svelte.d.ts +34 -0
  153. package/dist/theme/Input.svelte.d.ts.map +1 -0
  154. package/dist/theme/PageLayout.svelte +36 -0
  155. package/dist/theme/PageLayout.svelte.d.ts +31 -0
  156. package/dist/theme/PageLayout.svelte.d.ts.map +1 -0
  157. package/dist/theme/RootLayout.svelte +330 -0
  158. package/dist/theme/RootLayout.svelte.d.ts +40 -0
  159. package/dist/theme/RootLayout.svelte.d.ts.map +1 -0
  160. package/dist/theme/ScopeSwitcher.svelte +103 -0
  161. package/dist/theme/ScopeSwitcher.svelte.d.ts +24 -0
  162. package/dist/theme/ScopeSwitcher.svelte.d.ts.map +1 -0
  163. package/dist/theme/SearchDialog.svelte +253 -0
  164. package/dist/theme/SearchDialog.svelte.d.ts +28 -0
  165. package/dist/theme/SearchDialog.svelte.d.ts.map +1 -0
  166. package/dist/theme/Select.svelte +37 -0
  167. package/dist/theme/Select.svelte.d.ts +42 -0
  168. package/dist/theme/Select.svelte.d.ts.map +1 -0
  169. package/dist/theme/SidebarTree.svelte +136 -0
  170. package/dist/theme/SidebarTree.svelte.d.ts +24 -0
  171. package/dist/theme/SidebarTree.svelte.d.ts.map +1 -0
  172. package/dist/theme/Textarea.svelte +33 -0
  173. package/dist/theme/Textarea.svelte.d.ts +33 -0
  174. package/dist/theme/Textarea.svelte.d.ts.map +1 -0
  175. package/dist/theme/ThemeToggle.svelte +39 -0
  176. package/dist/theme/ThemeToggle.svelte.d.ts +21 -0
  177. package/dist/theme/ThemeToggle.svelte.d.ts.map +1 -0
  178. package/dist/theme/forms.d.ts +4 -0
  179. package/dist/theme/forms.d.ts.map +1 -0
  180. package/dist/theme/forms.js +3 -0
  181. package/dist/theme/index.d.ts +21 -0
  182. package/dist/theme/index.d.ts.map +1 -0
  183. package/dist/theme/index.js +19 -0
  184. package/dist/theme/portal.d.ts +5 -0
  185. package/dist/theme/portal.d.ts.map +1 -0
  186. package/dist/theme/portal.js +19 -0
  187. package/dist/theme/styles.css +3697 -0
  188. package/dist/virtual.d.ts +59 -0
  189. package/dist/vite.d.ts +10 -0
  190. package/dist/vite.d.ts.map +1 -0
  191. package/dist/vite.js +304 -0
  192. package/package.json +118 -0
@@ -0,0 +1,59 @@
1
+ export interface OgImageInput {
2
+ title: string;
3
+ description?: string;
4
+ siteName?: string;
5
+ }
6
+ export type OgRenderer = 'svg' | 'satori';
7
+ export interface OgFont {
8
+ name: string;
9
+ data: ArrayBuffer | Uint8Array;
10
+ weight?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
11
+ style?: 'normal' | 'italic';
12
+ }
13
+ export interface OgTemplateNode {
14
+ type: string;
15
+ props: {
16
+ style?: Record<string, string | number>;
17
+ children?: string | OgTemplateNode | OgTemplateNode[];
18
+ [key: string]: unknown;
19
+ };
20
+ }
21
+ export type OgTemplate = (input: OgImageInput) => OgTemplateNode;
22
+ export interface OgRenderOptions {
23
+ renderer?: OgRenderer;
24
+ fonts?: OgFont[];
25
+ template?: OgTemplate;
26
+ }
27
+ export interface OgImageOptions extends OgRenderOptions {
28
+ format?: 'svg' | 'png';
29
+ }
30
+ export interface SvedocsPageMetadata {
31
+ title: string;
32
+ description: string;
33
+ canonical?: string;
34
+ image?: string;
35
+ openGraph: {
36
+ title: string;
37
+ description: string;
38
+ type: string;
39
+ url?: string;
40
+ image?: string;
41
+ siteName: string;
42
+ author?: string;
43
+ publishedTime?: string;
44
+ updatedTime?: string;
45
+ };
46
+ twitter: {
47
+ card: 'summary' | 'summary_large_image';
48
+ title: string;
49
+ description: string;
50
+ image?: string;
51
+ };
52
+ jsonLd: Record<string, unknown>;
53
+ }
54
+ export interface SvedocsPageAlternate {
55
+ lang: string;
56
+ href: string;
57
+ locale?: string;
58
+ }
59
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/og/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE1C,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC;IAC/B,MAAM,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC7D,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE;QACL,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;QACxC,QAAQ,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,cAAc,EAAE,CAAC;QACtD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;CACH;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,cAAc,CAAC;AAEjE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,WAAW,cAAe,SAAQ,eAAe;IACrD,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,EAAE;QACT,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACJ,OAAO,EAAE;QACP,IAAI,EAAE,SAAS,GAAG,qBAAqB,CAAC;QACxC,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1 @@
1
+ export {};
package/dist/og.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './og/types.js';
2
+ export * from './og/metadata.js';
3
+ export * from './og/image.js';
4
+ //# sourceMappingURL=og.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"og.d.ts","sourceRoot":"","sources":["../src/og.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC"}
package/dist/og.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './og/types.js';
2
+ export * from './og/metadata.js';
3
+ export * from './og/image.js';
@@ -0,0 +1,10 @@
1
+ import type { SearchProvider, SearchQuery } from './types.js';
2
+ export interface AlgoliaSearchProviderOptions {
3
+ appId: string;
4
+ apiKey: string;
5
+ indexName: string;
6
+ filters?: string | ((query: SearchQuery) => string | undefined);
7
+ fetch?: typeof fetch;
8
+ }
9
+ export declare function createAlgoliaSearchProvider(options: AlgoliaSearchProviderOptions): SearchProvider;
10
+ //# sourceMappingURL=algolia.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"algolia.d.ts","sourceRoot":"","sources":["../../src/search/algolia.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAgB,MAAM,YAAY,CAAC;AAG5E,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC;IAChE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAyBD,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,4BAA4B,GAAG,cAAc,CAgCjG"}
@@ -0,0 +1,82 @@
1
+ import { matchesSearchScope } from './local.js';
2
+ import { createExcerpt, stringMetadata, stringifyMetadata } from './utils.js';
3
+ export function createAlgoliaSearchProvider(options) {
4
+ return {
5
+ name: 'algolia',
6
+ index() {
7
+ // Algolia indexing is usually handled by DocSearch crawlers or user CI.
8
+ },
9
+ async search(query) {
10
+ const requestFetch = options.fetch ?? fetch;
11
+ const filters = createAlgoliaFilters(options, query);
12
+ const response = await requestFetch(createAlgoliaQueryEndpoint(options), {
13
+ method: 'POST',
14
+ headers: {
15
+ 'content-type': 'application/json',
16
+ 'x-algolia-application-id': options.appId,
17
+ 'x-algolia-api-key': options.apiKey
18
+ },
19
+ body: JSON.stringify({
20
+ query: query.query,
21
+ hitsPerPage: query.limit ?? 10,
22
+ ...(filters ? { filters } : {}),
23
+ attributesToSnippet: ['content:30']
24
+ })
25
+ });
26
+ if (!response.ok) {
27
+ throw new Error(`Algolia search returned ${response.status}: ${(await response.text()).slice(0, 500)}`);
28
+ }
29
+ const payload = await response.json();
30
+ return (payload.hits ?? [])
31
+ .map((hit, index) => createAlgoliaResult(hit, index, query.query))
32
+ .filter((result) => matchesSearchScope({ metadata: result.metadata }, query));
33
+ }
34
+ };
35
+ }
36
+ function createAlgoliaQueryEndpoint(options) {
37
+ return `https://${encodeURIComponent(options.appId)}-dsn.algolia.net/1/indexes/${encodeURIComponent(options.indexName)}/query`;
38
+ }
39
+ function createAlgoliaFilters(options, query) {
40
+ return typeof options.filters === 'function' ? options.filters(query) : options.filters;
41
+ }
42
+ function createAlgoliaResult(hit, index, query) {
43
+ const metadata = stringifyMetadata({
44
+ ...(hit.metadata ?? {}),
45
+ locale: hit.locale ?? hit.metadata?.locale,
46
+ kind: hit.kind ?? hit.metadata?.kind
47
+ });
48
+ const hierarchyTitle = readHierarchy(hit.hierarchy, ['lvl0', 'lvl1', 'lvl2']);
49
+ const title = hit.title ?? hierarchyTitle ?? 'Result';
50
+ const section = hit.section ?? readHierarchy(hit.hierarchy, ['lvl6', 'lvl5', 'lvl4', 'lvl3', 'lvl2', 'lvl1']);
51
+ const content = stripHtml(readSnippet(hit) ?? hit.content ?? title);
52
+ return {
53
+ id: hit.objectID ?? `algolia:${index}`,
54
+ title,
55
+ url: createAlgoliaUrl(hit),
56
+ ...(section && section !== title ? { section } : {}),
57
+ excerpt: createExcerpt(content, query),
58
+ score: 1 / (index + 1),
59
+ metadata
60
+ };
61
+ }
62
+ function createAlgoliaUrl(hit) {
63
+ const url = hit.url ?? '#';
64
+ if (!hit.anchor || url.includes('#'))
65
+ return url;
66
+ return `${url}#${hit.anchor}`;
67
+ }
68
+ function readSnippet(hit) {
69
+ return stringMetadata(hit._snippetResult?.content?.value)
70
+ ?? stringMetadata(hit._highlightResult?.content?.value);
71
+ }
72
+ function readHierarchy(hierarchy, keys) {
73
+ for (const key of keys) {
74
+ const value = stringMetadata(hierarchy?.[key]);
75
+ if (value)
76
+ return stripHtml(value);
77
+ }
78
+ return undefined;
79
+ }
80
+ function stripHtml(value) {
81
+ return value.replace(/<[^>]+>/g, '').replace(/&nbsp;/g, ' ').trim();
82
+ }
@@ -0,0 +1,5 @@
1
+ import type { SvedocsSearchRecord } from '../core.js';
2
+ import type { CloudflareAiSearchSyncDocument, CloudflareAiSearchSyncOptions, CloudflareAiSearchSyncResult } from './types.js';
3
+ export declare function createCloudflareAiSearchDocuments(records: SvedocsSearchRecord[]): CloudflareAiSearchSyncDocument[];
4
+ export declare function syncCloudflareAiSearchIndex(options: CloudflareAiSearchSyncOptions): Promise<CloudflareAiSearchSyncResult>;
5
+ //# sourceMappingURL=cloudflare-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare-sync.d.ts","sourceRoot":"","sources":["../../src/search/cloudflare-sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EACV,8BAA8B,EAC9B,6BAA6B,EAC7B,4BAA4B,EAC7B,MAAM,YAAY,CAAC;AAGpB,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,8BAA8B,EAAE,CAwBlH;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,4BAA4B,CAAC,CAgEvC"}
@@ -0,0 +1,169 @@
1
+ import { chunkArray, stringifyMetadata, uniqueStrings, wait } from './utils.js';
2
+ export function createCloudflareAiSearchDocuments(records) {
3
+ return records.map((record) => ({
4
+ id: record.id,
5
+ title: record.section ? `${record.title}: ${record.section}` : record.title,
6
+ url: record.url,
7
+ content: [
8
+ `# ${record.section ? `${record.title}: ${record.section}` : record.title}`,
9
+ '',
10
+ `URL: ${record.url}`,
11
+ '',
12
+ record.content
13
+ ].join('\n'),
14
+ metadata: stringifyMetadata({
15
+ svedocs: JSON.stringify({
16
+ id: record.id,
17
+ pageId: record.pageId,
18
+ title: record.title,
19
+ section: record.section ?? '',
20
+ url: record.url
21
+ }),
22
+ locale: record.metadata.locale,
23
+ kind: record.metadata.kind
24
+ })
25
+ }));
26
+ }
27
+ export async function syncCloudflareAiSearchIndex(options) {
28
+ const endpoint = options.endpoint ?? createCloudflareAiSearchItemsEndpoint(options);
29
+ const dryRun = options.dryRun ?? (!options.accountId || !options.apiToken);
30
+ const documents = createCloudflareAiSearchDocuments(options.records);
31
+ const uploadIds = documents.map((document) => document.id);
32
+ const deleteIds = createCloudflareDeletePlan(options, uploadIds);
33
+ const result = {
34
+ provider: 'cloudflare-ai-search',
35
+ instanceName: options.instanceName,
36
+ endpoint,
37
+ dryRun,
38
+ indexed: dryRun ? documents.length : 0,
39
+ deleted: dryRun ? deleteIds.length : 0,
40
+ failed: 0,
41
+ planned: {
42
+ uploadIds,
43
+ deleteIds
44
+ },
45
+ errors: []
46
+ };
47
+ if (dryRun)
48
+ return result;
49
+ if (!options.apiToken) {
50
+ throw new Error('CLOUDFLARE_API_TOKEN is required to index Cloudflare AI Search.');
51
+ }
52
+ const requestFetch = options.fetch ?? fetch;
53
+ const batchSize = options.batchSize ?? 10;
54
+ const maxRetries = options.maxRetries ?? 2;
55
+ const retryDelayMs = options.retryDelayMs ?? 250;
56
+ await processBatches(deleteIds, batchSize, async (itemId) => {
57
+ try {
58
+ await withRetry(() => deleteCloudflareAiSearchItem(endpoint, itemId, options.apiToken, requestFetch), {
59
+ maxRetries,
60
+ retryDelayMs
61
+ });
62
+ result.deleted += 1;
63
+ }
64
+ catch (error) {
65
+ result.failed += 1;
66
+ result.errors.push({
67
+ id: itemId,
68
+ message: error instanceof Error ? error.message : 'Cloudflare AI Search delete failed.'
69
+ });
70
+ }
71
+ });
72
+ await processBatches(documents, batchSize, async (document) => {
73
+ try {
74
+ await withRetry(() => uploadCloudflareAiSearchDocument(endpoint, document, options, requestFetch), {
75
+ maxRetries,
76
+ retryDelayMs
77
+ });
78
+ result.indexed += 1;
79
+ }
80
+ catch (error) {
81
+ result.failed += 1;
82
+ result.errors.push({
83
+ id: document.id,
84
+ message: error instanceof Error ? error.message : 'Cloudflare AI Search upload failed.'
85
+ });
86
+ }
87
+ });
88
+ return result;
89
+ }
90
+ function createCloudflareAiSearchItemsEndpoint(options) {
91
+ if (!options.accountId)
92
+ return 'https://api.cloudflare.com/client/v4/accounts/<account_id>/ai-search/instances/<instance_name>/items';
93
+ const account = encodeURIComponent(options.accountId);
94
+ const instance = encodeURIComponent(options.instanceName);
95
+ if (options.namespace) {
96
+ return `https://api.cloudflare.com/client/v4/accounts/${account}/ai-search/namespaces/${encodeURIComponent(options.namespace)}/instances/${instance}/items`;
97
+ }
98
+ return `https://api.cloudflare.com/client/v4/accounts/${account}/ai-search/instances/${instance}/items`;
99
+ }
100
+ function createCloudflareAiSearchItemEndpoint(itemsEndpoint, itemId) {
101
+ return `${itemsEndpoint.replace(/\/$/, '')}/${encodeURIComponent(itemId)}`;
102
+ }
103
+ function createCloudflareDeletePlan(options, uploadIds) {
104
+ const explicitDeletes = options.deleteIds ?? [];
105
+ if (options.strategy !== 'replace')
106
+ return uniqueStrings(explicitDeletes);
107
+ const uploadSet = new Set(uploadIds);
108
+ return uniqueStrings([
109
+ ...explicitDeletes,
110
+ ...(options.existingIds ?? []).filter((itemId) => !uploadSet.has(itemId))
111
+ ]);
112
+ }
113
+ function createCloudflareItemFilename(document) {
114
+ const safe = document.id.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-|-$/g, '') || 'svedocs-page';
115
+ return `${safe.slice(0, 124)}.md`;
116
+ }
117
+ async function deleteCloudflareAiSearchItem(endpoint, itemId, apiToken, requestFetch) {
118
+ const response = await requestFetch(createCloudflareAiSearchItemEndpoint(endpoint, itemId), {
119
+ method: 'DELETE',
120
+ headers: {
121
+ authorization: `Bearer ${apiToken}`
122
+ }
123
+ });
124
+ if (!response.ok) {
125
+ throw new Error(await createCloudflareApiErrorMessage(response, 'delete'));
126
+ }
127
+ }
128
+ async function uploadCloudflareAiSearchDocument(endpoint, document, options, requestFetch) {
129
+ const form = new FormData();
130
+ form.append('file', new Blob([document.content], { type: 'text/markdown' }), createCloudflareItemFilename(document));
131
+ form.append('metadata', JSON.stringify(document.metadata));
132
+ if (typeof options.waitForCompletion === 'boolean') {
133
+ form.append('wait_for_completion', String(options.waitForCompletion));
134
+ }
135
+ const response = await requestFetch(endpoint, {
136
+ method: 'POST',
137
+ headers: {
138
+ authorization: `Bearer ${options.apiToken}`
139
+ },
140
+ body: form
141
+ });
142
+ if (!response.ok) {
143
+ throw new Error(await createCloudflareApiErrorMessage(response, 'upload'));
144
+ }
145
+ }
146
+ async function createCloudflareApiErrorMessage(response, action) {
147
+ const body = await response.text().catch(() => '');
148
+ return `Cloudflare AI Search ${action} returned ${response.status}${body ? `: ${body.slice(0, 500)}` : ''}`;
149
+ }
150
+ async function processBatches(items, batchSize, handler) {
151
+ for (const batch of chunkArray(items, batchSize)) {
152
+ await Promise.all(batch.map((item) => handler(item)));
153
+ }
154
+ }
155
+ async function withRetry(action, options) {
156
+ let attempt = 0;
157
+ while (true) {
158
+ try {
159
+ await action();
160
+ return;
161
+ }
162
+ catch (error) {
163
+ if (attempt >= options.maxRetries)
164
+ throw error;
165
+ attempt += 1;
166
+ await wait(options.retryDelayMs * attempt);
167
+ }
168
+ }
169
+ }
@@ -0,0 +1,9 @@
1
+ import type { CloudflareAiSearchInput, CloudflareAiSearchInstance, CloudflareAiSearchOutput, CloudflareAiSearchNamespace, SearchResult, SearchProvider } from './types.js';
2
+ export declare function createCloudflareAiSearchProvider(input: {
3
+ binding: CloudflareAiSearchInstance | CloudflareAiSearchNamespace;
4
+ instanceName?: string;
5
+ }): SearchProvider;
6
+ export declare function runCloudflareAiSearch(binding: CloudflareAiSearchInstance | CloudflareAiSearchNamespace, instanceName: string | undefined, input: CloudflareAiSearchInput): Promise<CloudflareAiSearchOutput>;
7
+ export declare function normalizeCloudflareAiSearchResults(result: CloudflareAiSearchOutput, query: string): SearchResult[];
8
+ export declare function resolveAiSearchInstance(binding: CloudflareAiSearchInstance | CloudflareAiSearchNamespace, instanceName?: string): CloudflareAiSearchInstance;
9
+ //# sourceMappingURL=cloudflare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../src/search/cloudflare.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,uBAAuB,EACvB,0BAA0B,EAE1B,wBAAwB,EACxB,2BAA2B,EAC3B,YAAY,EACZ,cAAc,EACf,MAAM,YAAY,CAAC;AAIpB,wBAAgB,gCAAgC,CAAC,KAAK,EAAE;IACtD,OAAO,EAAE,0BAA0B,GAAG,2BAA2B,CAAC;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,cAAc,CA0BjB;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,0BAA0B,GAAG,2BAA2B,EACjE,YAAY,oBAAY,EACxB,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,wBAAwB,CAAC,CASnC;AAED,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,wBAAwB,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE,CAKlH;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,0BAA0B,GAAG,2BAA2B,EACjE,YAAY,SAAY,GACvB,0BAA0B,CAE5B"}
@@ -0,0 +1,115 @@
1
+ import { matchesSearchScope } from './local.js';
2
+ import { createExcerpt, stringMetadata, stringifyMetadata } from './utils.js';
3
+ export function createCloudflareAiSearchProvider(input) {
4
+ return {
5
+ name: 'cloudflare-ai-search',
6
+ index() {
7
+ // Cloudflare AI Search indexing is intentionally handled by CLI/provider sync.
8
+ },
9
+ async search(query) {
10
+ const maxResults = query.limit ?? 10;
11
+ const result = await runCloudflareAiSearch(input.binding, input.instanceName, {
12
+ messages: [
13
+ {
14
+ role: 'user',
15
+ content: query.query
16
+ }
17
+ ],
18
+ ai_search_options: {
19
+ retrieval: {
20
+ retrieval_type: 'hybrid',
21
+ max_num_results: maxResults
22
+ }
23
+ }
24
+ });
25
+ return normalizeCloudflareAiSearchResults(result, query.query)
26
+ .filter((record) => matchesSearchScope({ metadata: record.metadata }, query));
27
+ }
28
+ };
29
+ }
30
+ export async function runCloudflareAiSearch(binding, instanceName = 'svedocs', input) {
31
+ const instance = resolveAiSearchInstance(binding, instanceName);
32
+ const aiSearchOptions = createAiSearchOptions(input);
33
+ const messages = input.messages;
34
+ return instance.search({
35
+ ...(messages ? { messages } : {}),
36
+ ...(!messages && input.query ? { query: input.query } : {}),
37
+ ...(aiSearchOptions ? { ai_search_options: aiSearchOptions } : {})
38
+ });
39
+ }
40
+ export function normalizeCloudflareAiSearchResults(result, query) {
41
+ if (result.data?.length) {
42
+ return result.data.map((item, index) => createResultFromItem(item, index, query, result.response ?? result.answer));
43
+ }
44
+ return (result.chunks ?? []).map((chunk, index) => createResultFromChunk(chunk, index, query, result.response ?? result.answer));
45
+ }
46
+ export function resolveAiSearchInstance(binding, instanceName = 'svedocs') {
47
+ return 'get' in binding ? binding.get(instanceName) : binding;
48
+ }
49
+ function mergeRetrieval(options, retrieval) {
50
+ return {
51
+ ...(options ?? {}),
52
+ retrieval: {
53
+ ...(options?.retrieval ?? {}),
54
+ ...retrieval
55
+ }
56
+ };
57
+ }
58
+ function createAiSearchOptions(input) {
59
+ const retrieval = typeof input.max_num_results === 'number' ? { max_num_results: input.max_num_results } : {};
60
+ return input.ai_search_options || Object.keys(retrieval).length > 0
61
+ ? mergeRetrieval(input.ai_search_options, retrieval)
62
+ : undefined;
63
+ }
64
+ function createResultFromItem(item, index, query, fallbackContent = '') {
65
+ const metadata = normalizeCloudflareMetadata(item.metadata ?? {});
66
+ const section = stringMetadata(metadata.section);
67
+ return {
68
+ id: item.id ?? `cloudflare:${index}`,
69
+ title: item.title ?? stringMetadata(metadata.title) ?? 'Result',
70
+ url: item.url ?? stringMetadata(metadata.url) ?? '#',
71
+ ...(section ? { section } : {}),
72
+ excerpt: createExcerpt(item.content ?? item.text ?? fallbackContent, query),
73
+ score: typeof item.score === 'number' ? item.score : 1 / (index + 1),
74
+ metadata
75
+ };
76
+ }
77
+ function createResultFromChunk(chunk, index, query, fallbackContent = '') {
78
+ const metadata = normalizeCloudflareMetadata({
79
+ ...(chunk.attributes ?? {}),
80
+ ...(chunk.metadata ?? {}),
81
+ ...(chunk.item?.metadata ?? {})
82
+ });
83
+ const section = stringMetadata(metadata.section);
84
+ return {
85
+ id: chunk.id ?? stringMetadata(chunk.item?.id) ?? stringMetadata(chunk.item?.key) ?? `cloudflare:${index}`,
86
+ title: stringMetadata(metadata.title) ??
87
+ stringMetadata(chunk.item?.title) ??
88
+ stringMetadata(chunk.item?.filename) ??
89
+ stringMetadata(chunk.item?.key) ??
90
+ 'Result',
91
+ url: stringMetadata(metadata.url) ?? stringMetadata(metadata.source_url) ?? '#',
92
+ ...(section ? { section } : {}),
93
+ excerpt: createExcerpt(chunk.text ?? chunk.content ?? stringMetadata(metadata.content) ?? fallbackContent, query),
94
+ score: typeof chunk.score === 'number' ? chunk.score : 1 / (index + 1),
95
+ metadata
96
+ };
97
+ }
98
+ function normalizeCloudflareMetadata(metadata) {
99
+ const stringified = stringifyMetadata(metadata);
100
+ const embedded = stringMetadata(metadata.svedocs);
101
+ if (!embedded)
102
+ return stringified;
103
+ try {
104
+ const parsed = JSON.parse(embedded);
105
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
106
+ return stringified;
107
+ return {
108
+ ...stringified,
109
+ ...stringifyMetadata(parsed)
110
+ };
111
+ }
112
+ catch {
113
+ return stringified;
114
+ }
115
+ }
@@ -0,0 +1,9 @@
1
+ import type { SvedocsSearchRecord } from '../core.js';
2
+ import type { SearchProvider, SearchQuery, SearchResult, SearchScope } from './types.js';
3
+ export declare function createLocalSearchProvider(records?: SvedocsSearchRecord[]): SearchProvider;
4
+ export declare const localSearchProvider: SearchProvider;
5
+ export declare function searchRecords(records: SvedocsSearchRecord[], input: SearchQuery): SearchResult[];
6
+ export declare function filterSearchRecords(records: SvedocsSearchRecord[], scope?: SearchScope): SvedocsSearchRecord[];
7
+ export declare function matchesSearchScope(record: SvedocsSearchRecord, scope?: SearchScope): boolean;
8
+ export declare function createSearchResponse(records: SvedocsSearchRecord[], request: Request): Promise<Response>;
9
+ //# sourceMappingURL=local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/search/local.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAoBzF,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,mBAAmB,EAAO,GAAG,cAAc,CAW7F;AAED,eAAO,MAAM,mBAAmB,gBAA8B,CAAC;AAE/D,wBAAgB,aAAa,CAAC,OAAO,EAAE,mBAAmB,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,YAAY,EAAE,CAkChG;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,mBAAmB,EAAE,EAC9B,KAAK,GAAE,WAAgB,GACtB,mBAAmB,EAAE,CAEvB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,EAAE,KAAK,GAAE,WAAgB,GAAG,OAAO,CAGhG;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAa9G"}
@@ -0,0 +1,122 @@
1
+ import MiniSearch from 'minisearch';
2
+ import { createExcerpt, jsonResponse, normalizeSearchText } from './utils.js';
3
+ const miniSearchCache = new WeakMap();
4
+ export function createLocalSearchProvider(records = []) {
5
+ let indexed = records;
6
+ return {
7
+ name: 'local-json',
8
+ index(nextRecords) {
9
+ indexed = nextRecords;
10
+ },
11
+ search(input) {
12
+ return searchRecords(indexed, input);
13
+ }
14
+ };
15
+ }
16
+ export const localSearchProvider = createLocalSearchProvider();
17
+ export function searchRecords(records, input) {
18
+ const query = normalizeSearchText(input.query);
19
+ if (!query)
20
+ return [];
21
+ const entry = getMiniSearchIndex(records);
22
+ const scoped = entry.index.search(input.query, {
23
+ prefix: true,
24
+ fuzzy: (term) => term.length > 4 ? 0.18 : false,
25
+ combineWith: 'AND',
26
+ boost: {
27
+ title: 5,
28
+ section: 4,
29
+ url: 1.5,
30
+ metadataText: 0.8,
31
+ content: 1
32
+ }
33
+ });
34
+ return scoped
35
+ .map((hit) => {
36
+ const record = entry.recordsById.get(hit.id);
37
+ return record ? { record, score: Number(hit.score.toFixed(4)) } : undefined;
38
+ })
39
+ .filter((item) => Boolean(item))
40
+ .filter((item) => matchesSearchScope(item.record, input))
41
+ .slice(0, input.limit ?? 10)
42
+ .map(({ record, score }) => ({
43
+ id: record.id,
44
+ title: record.title,
45
+ url: record.url,
46
+ ...(record.section ? { section: record.section } : {}),
47
+ excerpt: createExcerpt(record.content, input.query),
48
+ score,
49
+ metadata: record.metadata
50
+ }));
51
+ }
52
+ export function filterSearchRecords(records, scope = {}) {
53
+ return records.filter((record) => matchesSearchScope(record, scope));
54
+ }
55
+ export function matchesSearchScope(record, scope = {}) {
56
+ return matchesMetadata(record.metadata.locale, scope.locale)
57
+ && matchesMetadata(record.metadata.kind, scope.kind);
58
+ }
59
+ export async function createSearchResponse(records, request) {
60
+ const url = new URL(request.url);
61
+ const query = url.searchParams.get('q') ?? url.searchParams.get('query') ?? '';
62
+ const limit = clampLimit(Number(url.searchParams.get('limit') ?? 10));
63
+ const locale = readScopeParam(url, 'locale');
64
+ const kind = readScopeParam(url, 'kind');
65
+ const results = searchRecords(records, {
66
+ query,
67
+ limit,
68
+ ...(locale ? { locale } : {}),
69
+ ...(kind ? { kind } : {})
70
+ });
71
+ return jsonResponse({ query, results });
72
+ }
73
+ function getMiniSearchIndex(records) {
74
+ const cached = miniSearchCache.get(records);
75
+ if (cached)
76
+ return cached;
77
+ const documents = records.map(toMiniSearchDocument);
78
+ const index = new MiniSearch({
79
+ fields: ['title', 'section', 'url', 'content', 'metadataText'],
80
+ storeFields: ['id', 'title', 'section', 'url', 'content', 'metadata'],
81
+ idField: 'id',
82
+ searchOptions: {
83
+ prefix: true,
84
+ fuzzy: 0.18
85
+ },
86
+ processTerm: (term) => normalizeSearchText(term)
87
+ });
88
+ index.addAll(documents);
89
+ const entry = {
90
+ index,
91
+ recordsById: new Map(records.map((record) => [record.id, record]))
92
+ };
93
+ miniSearchCache.set(records, entry);
94
+ return entry;
95
+ }
96
+ function toMiniSearchDocument(record) {
97
+ return {
98
+ id: record.id,
99
+ title: record.title,
100
+ section: record.section ?? '',
101
+ url: record.url,
102
+ content: record.content,
103
+ metadataText: Object.values(record.metadata).flat().join(' '),
104
+ metadata: record.metadata
105
+ };
106
+ }
107
+ function matchesMetadata(value, expected) {
108
+ if (!expected)
109
+ return true;
110
+ if (Array.isArray(value))
111
+ return value.some((item) => String(item) === expected);
112
+ return value === expected;
113
+ }
114
+ function readScopeParam(url, key) {
115
+ const value = url.searchParams.get(key);
116
+ return value?.trim() || undefined;
117
+ }
118
+ function clampLimit(value) {
119
+ if (!Number.isFinite(value))
120
+ return 10;
121
+ return Math.min(50, Math.max(1, Math.floor(value)));
122
+ }
@@ -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