-
Notifications
You must be signed in to change notification settings - Fork 6.5k
Expand file tree
/
Copy pathwithSearch.tsx
More file actions
109 lines (88 loc) · 2.67 KB
/
withSearch.tsx
File metadata and controls
109 lines (88 loc) · 2.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
'use client';
import SearchBox from '@node-core/ui-components/Common/Search';
import { create, insertMultiple, search } from '@orama/orama';
import { useTranslations } from 'next-intl';
import { useMemo } from 'react';
import { ORAMA_DB_URLS } from '#site/next.constants.mjs';
import type { OramaCloud } from '@orama/core';
import type { AnyOrama } from '@orama/orama';
import type { FC } from 'react';
type OramaDoc = { href: string } & Record<string, unknown>;
type SerializedOramaDb = {
docs: {
docs: Record<string, OramaDoc>;
};
};
type OramaUrls = typeof ORAMA_DB_URLS;
type OramaClient = {
client: OramaCloud;
warmup: () => Promise<void>;
};
export const addPrefixToDocs = <T extends SerializedOramaDb>(
db: T,
prefix: string
): T => {
const prefixedDocs: Record<string, OramaDoc> = {};
for (const [id, doc] of Object.entries(db.docs.docs)) {
prefixedDocs[id] = { ...doc, href: `${prefix}${doc.href}` };
}
return {
...db,
docs: { ...db.docs, docs: prefixedDocs },
};
};
const loadOrama = async (
db: AnyOrama,
urls: OramaUrls = ORAMA_DB_URLS
): Promise<void> => {
const indexes = await Promise.all(
Object.entries(urls).map(async ([key, url]) => {
const response = await fetch(url);
const fetchedDb = (await response.json()) as SerializedOramaDb;
return addPrefixToDocs(fetchedDb, key);
})
);
for (const index of indexes) {
await insertMultiple(db, Object.values(index.docs.docs) as Array<never>);
}
};
export const createOramaClient = (
urls: OramaUrls = ORAMA_DB_URLS
): OramaClient => {
const db = create({
schema: {
title: 'string',
description: 'string',
href: 'string',
siteSection: 'string',
},
});
let loadPromise: Promise<void> | null = null;
const warmup = () => (loadPromise ??= loadOrama(db, urls));
// @ts-expect-error We are overriding a method, an error is expected.
db.search = async options => {
await warmup();
return search(db, options);
};
return {
client: db as unknown as OramaCloud,
warmup,
};
};
export const useOrama = () => useMemo(() => createOramaClient(), []);
const WithSearch: FC = () => {
const t = useTranslations();
const { client, warmup } = useOrama();
return (
<SearchBox
client={client}
onWarmup={warmup}
closeShortcutLabel={t('components.search.keyboardShortcuts.close')}
navigateShortcutLabel={t('components.search.keyboardShortcuts.navigate')}
noResultsTitle={t('components.search.noResultsFoundFor')}
placeholder={t('components.search.searchPlaceholder')}
selectShortcutLabel={t('components.search.keyboardShortcuts.select')}
/>
);
};
export default WithSearch;