Skip to content

Commit c7802b7

Browse files
committed
fixup! fetch orama at run time
1 parent bb693b1 commit c7802b7

9 files changed

Lines changed: 598834 additions & 84 deletions

File tree

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ package-lock.json
1212
apps/site/.next
1313
apps/site/build
1414
apps/site/public/blog-data.json
15-
apps/site/public/orama-db.json
1615
apps/site/next-env.d.ts
1716

1817
# Test Runner

apps/site/components/withSearch.tsx

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,94 @@
11
'use client';
22

33
import SearchBox from '@node-core/ui-components/Common/Search';
4+
import useOrama from '@node-core/ui-components/hooks/useOrama';
5+
import { create, insertMultiple, save } from '@orama/orama';
46
import { useTranslations } from 'next-intl';
57

8+
import { ORAMA_DB_URLS } from '#site/next.constants.mjs';
9+
610
import type { FC } from 'react';
711

12+
/**
13+
* Shape of a single Orama document entry.
14+
* `href` is required (we prefix it); other fields are passthrough.
15+
*/
16+
type OramaDoc = { href: string } & Record<string, unknown>;
17+
18+
/**
19+
* Shape of a serialized Orama database snapshot (from `save()` on the server
20+
* side, fetched as JSON on the client). We only type the parts we touch.
21+
*/
22+
type SerializedOramaDb = {
23+
docs: {
24+
docs: Record<string, OramaDoc>;
25+
};
26+
};
27+
28+
/**
29+
* Each locale/section of the site ships its own prebuilt Orama index, but the
30+
* hrefs inside those indexes are relative to that section's root. When we
31+
* merge multiple indexes into a single client-side DB, we need to re-scope
32+
* those hrefs so clicks route to the correct top-level path.
33+
*/
34+
export const addPrefixToDocs = <T extends SerializedOramaDb>(
35+
db: T,
36+
prefix: string
37+
): T => {
38+
const prefixedDocs: Record<string, OramaDoc> = {};
39+
40+
// Object.entries + Object.fromEntries would also work, but a single pass
41+
// with a plain loop avoids the intermediate array allocations
42+
for (const [id, doc] of Object.entries(db.docs.docs)) {
43+
prefixedDocs[id] = { ...doc, href: `${prefix}${doc.href}` };
44+
}
45+
46+
return {
47+
...db,
48+
docs: { ...db.docs, docs: prefixedDocs },
49+
};
50+
};
51+
852
const WithSearch: FC = () => {
953
const t = useTranslations();
1054

55+
// `useOrama` expects an initializer that returns serialized RawData.
56+
// We build a temporary DB, populate it from every configured index, then
57+
// serialize it so the hook can `load()` it into its own client instance.
58+
const client = useOrama(async () => {
59+
const db = create({
60+
schema: {
61+
title: 'string',
62+
description: 'string',
63+
href: 'string',
64+
siteSection: 'string',
65+
},
66+
});
67+
68+
// Kick off every fetch concurrently — network latency, not CPU, is the
69+
// bottleneck here, so serializing these would waste ~N× round-trip time.
70+
const indexes = await Promise.all(
71+
Object.entries(ORAMA_DB_URLS).map(async ([key, url]) => {
72+
const fetchedDb = (await fetch(url).then(res =>
73+
res.json()
74+
)) as SerializedOramaDb;
75+
return addPrefixToDocs(fetchedDb, `/${key}`);
76+
})
77+
);
78+
79+
for (const index of indexes) {
80+
await insertMultiple(db, Object.values(index.docs.docs) as Array<never>);
81+
}
82+
83+
return save(db);
84+
});
85+
1186
return (
1287
<SearchBox
88+
client={client}
1389
closeShortcutLabel={t('components.search.keyboardShortcuts.close')}
1490
navigateShortcutLabel={t('components.search.keyboardShortcuts.navigate')}
1591
noResultsTitle={t('components.search.noResultsFoundFor')}
16-
path="/orama-db.json"
1792
placeholder={t('components.search.searchPlaceholder')}
1893
selectShortcutLabel={t('components.search.keyboardShortcuts.select')}
1994
/>

apps/site/next.constants.mjs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,11 @@ export const VULNERABILITIES_URL =
169169
*/
170170
export const OPENCOLLECTIVE_MEMBERS_URL =
171171
'https://opencollective.com/nodejs/members/all.json';
172+
173+
/**
174+
* Orama DB URLs for the Learn and API sections of the website
175+
*/
176+
export const ORAMA_DB_URLS = {
177+
learn: 'https://nodejs.org/learn/orama-db.json',
178+
api: 'https://beta.docs.nodejs.org/orama-db.json',
179+
};

apps/site/package.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,16 @@
22
"name": "@node-core/website",
33
"type": "module",
44
"scripts": {
5-
"prebuild": "node --run build:blog-data && node --run build:orama-db",
5+
"prebuild": "node --run build:blog-data",
66
"build": "cross-env NODE_NO_WARNINGS=1 next build",
77
"build:blog-data": "cross-env NODE_NO_WARNINGS=1 node ./scripts/blog-data/index.mjs",
8-
"build:orama-db": "cross-env NODE_NO_WARNINGS=1 node ./scripts/orama/index.mjs",
98
"build:blog-data:watch": "node --watch --watch-path=pages/en/blog ./scripts/blog-data/index.mjs",
109
"cloudflare:build:worker": "OPEN_NEXT_CLOUDFLARE=true opennextjs-cloudflare build",
1110
"cloudflare:deploy": "opennextjs-cloudflare deploy",
1211
"cloudflare:preview": "wrangler dev",
13-
"predeploy": "node --run build:blog-data && node --run build:orama-db",
12+
"predeploy": "node --run build:blog-data",
1413
"deploy": "cross-env NEXT_PUBLIC_STATIC_EXPORT=true node --run build",
15-
"predev": "node --run build:blog-data && node --run build:orama-db",
14+
"predev": "node --run build:blog-data",
1615
"dev": "cross-env NODE_NO_WARNINGS=1 next dev",
1716
"lint": "node --run lint:js && node --run lint:css && node --run lint:md",
1817
"lint:fix": "node --run lint:js:fix && node --run lint:css:fix && node --run lint:md:fix",

0 commit comments

Comments
 (0)