From 735e0bf52ecacec046670a7e0b231dca7f8cf3ef Mon Sep 17 00:00:00 2001 From: iCrawl Date: Fri, 16 Sep 2022 23:04:05 +0200 Subject: [PATCH] feat: search --- packages/scripts/src/generateIndex.ts | 5 +- packages/website/package.json | 2 +- packages/website/src/components/Cmdk.tsx | 162 ++++++++---------- .../website/src/components/SidebarLayout.tsx | 2 +- packages/website/src/util/search.ts | 6 + yarn.lock | 18 +- 6 files changed, 98 insertions(+), 97 deletions(-) create mode 100644 packages/website/src/util/search.ts diff --git a/packages/scripts/src/generateIndex.ts b/packages/scripts/src/generateIndex.ts index 07938abb9..94e44140b 100644 --- a/packages/scripts/src/generateIndex.ts +++ b/packages/scripts/src/generateIndex.ts @@ -29,6 +29,7 @@ export interface MemberJSON { } export const PACKAGES = ['builders', 'collection', 'proxy', 'rest', 'voice', 'ws']; +let idx = 0; export function createApiModel(data: any) { const model = new ApiModel(); @@ -96,7 +97,7 @@ function tryResolveSummaryText(item: ApiDeclaredItem): string | null { } export function visitNodes(item: ApiItem, tag: string) { - const members: MemberJSON[] = []; + const members: (MemberJSON & { id: number })[] = []; for (const member of item.members) { if (!(member instanceof ApiDeclaredItem)) { @@ -112,6 +113,7 @@ export function visitNodes(item: ApiItem, tag: string) { } members.push({ + id: idx++, name: member.displayName, kind: member.kind, summary: tryResolveSummaryText(member) ?? '', @@ -153,6 +155,7 @@ export async function generateAllIndicies() { // await generateIndex(model, pkg, version); // } + idx = 0; const model = createApiModel(data); await generateIndex(model, pkg); } diff --git a/packages/website/package.json b/packages/website/package.json index 5b8b25930..ea67a5016 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -42,12 +42,12 @@ "dependencies": { "@discordjs/api-extractor-utils": "workspace:^", "@discordjs/scripts": "workspace:^", - "@lyrasearch/lyra": "^0.2.3", "@microsoft/api-extractor-model": "7.24.0", "@microsoft/tsdoc": "0.14.1", "@vscode/codicons": "^0.0.32", "ariakit": "^2.0.0-next.41", "cmdk": "^0.1.20", + "meilisearch": "^0.27.0", "next": "^12.3.0", "next-mdx-remote": "^4.1.0", "next-progress": "^2.2.0", diff --git a/packages/website/src/components/Cmdk.tsx b/packages/website/src/components/Cmdk.tsx index a1dd8020a..a2cb3db43 100644 --- a/packages/website/src/components/Cmdk.tsx +++ b/packages/website/src/components/Cmdk.tsx @@ -1,5 +1,4 @@ -// import { insertBatch, search as searchDb } from '@lyrasearch/lyra'; -// import type { ApiItemKind } from '@microsoft/api-extractor-model'; +import type { ApiItemKind } from '@microsoft/api-extractor-model'; import { Dialog, useDialogState } from 'ariakit/dialog'; import { Command } from 'cmdk'; import { useRouter } from 'next/router'; @@ -7,65 +6,59 @@ import { useEffect, useMemo, useState } from 'react'; import { VscArrowRight, VscPackage, - // VscSymbolClass, - // VscSymbolEnum, - // VscSymbolField, - // VscSymbolInterface, - // VscSymbolMethod, - // VscSymbolProperty, - // VscSymbolVariable, + VscSymbolClass, + VscSymbolEnum, + VscSymbolField, + VscSymbolInterface, + VscSymbolMethod, + VscSymbolProperty, + VscSymbolVariable, VscVersions, } from 'react-icons/vsc'; import { useKey } from 'react-use'; import useSWR from 'swr'; import { PACKAGES } from '~/util/constants'; import { fetcher } from '~/util/fetcher'; +import { client } from '~/util/search'; -// function resolveIcon(item: keyof ApiItemKind) { -// switch (item) { -// case 'Class': -// return ; -// case 'Enum': -// return ; -// case 'Interface': -// return ; -// case 'Property': -// return ; -// case 'TypeAlias': -// return ; -// case 'Variables': -// return ; -// default: -// return ; -// } -// } +function resolveIcon(item: keyof ApiItemKind) { + switch (item) { + case 'Class': + return ; + case 'Enum': + return ; + case 'Interface': + return ; + case 'Property': + return ; + case 'TypeAlias': + return ; + case 'Variables': + return ; + default: + return ; + } +} -// const searchIndex: any[] = []; - -export function CmdkDialog() { +export function CmdkDialog({ currentPackageName }: { currentPackageName?: string | undefined }) { const router = useRouter(); const dialog = useDialogState(); const [search, setSearch] = useState(''); const [page, setPage] = useState(''); const [packageName, setPackageName] = useState(''); - // const [searchResults, setSearchResults] = useState([]); + const [searchResults, setSearchResults] = useState([]); const { data: versions, isValidating } = useSWR( packageName ? `https://docs.discordjs.dev/api/info?package=${packageName}` : null, fetcher, ); - // const { data: searchIndex } = useSWR( - // packageName ? `http://localhost:3000/searchIndex/${packageName}-main-index.json` : null, - // fetcher, - // ); - const packageCommandItems = useMemo( () => PACKAGES.map((pkg) => ( { setPackageName(pkg); setPage('version'); @@ -92,7 +85,7 @@ export function CmdkDialog() { ?.map((version) => ( { void router.push(`/docs/packages/${packageName}/${version}`); dialog.setOpen(false); @@ -114,34 +107,35 @@ export function CmdkDialog() { [packageName], ); - // const searchResultItems = useMemo( - // () => - // searchResults?.map((item) => ( - // { - // void router.push(item.path); - // dialog.setOpen(false); - // }} - // > - //
- //
- //
- // {resolveIcon(item.kind)} - //
- //

{item.name}

- // {item.summary} - //
- //
- //
- // - //
- //
- // )) ?? [], - // // eslint-disable-next-line react-hooks/exhaustive-deps - // [searchResults], - // ); + const searchResultItems = useMemo( + () => + searchResults?.map((item) => ( + { + void router.push(item.path); + dialog.setOpen(false); + }} + > +
+
+
+ {resolveIcon(item.kind)} +
+

{item.name}

+ {item.summary} + {item.path} +
+
+
+ +
+
+ )) ?? [], + // eslint-disable-next-line react-hooks/exhaustive-deps + [searchResults], + ); useKey((event) => event.key === 'k' && event.metaKey, dialog.toggle, { event: 'keydown' }, []); useKey( @@ -158,27 +152,23 @@ export function CmdkDialog() { } }, [dialog.open]); - // useEffect(() => { - // if (searchIndex?.length) { - // void insertBatch(db, searchIndex); - // } - // // eslint-disable-next-line react-hooks/exhaustive-deps - // }, [searchIndex]); + useEffect(() => { + const searchDoc = async (searchString: string) => { + const res = await client.index(`${currentPackageName}-main`).search(searchString, { limit: 5 }); + setSearchResults(res.hits); + }; - // useEffect(() => { - // if (search) { - // const results = searchDb(db, { - // term: search, - // properties: ['name', 'kind', 'summary'], - // }); - // setSearchResults(results.hits); - // } - // // eslint-disable-next-line react-hooks/exhaustive-deps - // }, [search]); + if (search && currentPackageName) { + void searchDoc(search); + } else { + setSearchResults([]); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [search]); return ( - + ) : null} - {page /* || search */ ? null : packageCommandItems} + {page || search ? null : packageCommandItems} - {page === 'version' /* && !search */ ? versionCommandItems : null} + {page === 'version' && !search ? versionCommandItems : null} - {/* {search && !page ? searchResultItems : null} */} + {search ? searchResultItems : null} diff --git a/packages/website/src/components/SidebarLayout.tsx b/packages/website/src/components/SidebarLayout.tsx index 70a57ee3e..765df0c48 100644 --- a/packages/website/src/components/SidebarLayout.tsx +++ b/packages/website/src/components/SidebarLayout.tsx @@ -307,7 +307,7 @@ export function SidebarLayout({ - + ); } diff --git a/packages/website/src/util/search.ts b/packages/website/src/util/search.ts new file mode 100644 index 000000000..5d86ba4d4 --- /dev/null +++ b/packages/website/src/util/search.ts @@ -0,0 +1,6 @@ +import MeiliSearch from 'meilisearch'; + +export const client = new MeiliSearch({ + host: 'https://search.discordjs.dev', + apiKey: 'b51923c6abb574b1e97be9a03dc6414b6c69fb0c5696d0ef01a82b0f77d223db', +}); diff --git a/yarn.lock b/yarn.lock index 6494fe4a0..62e548eab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2123,7 +2123,6 @@ __metadata: dependencies: "@discordjs/api-extractor-utils": "workspace:^" "@discordjs/scripts": "workspace:^" - "@lyrasearch/lyra": ^0.2.3 "@microsoft/api-extractor-model": 7.24.0 "@microsoft/tsdoc": 0.14.1 "@testing-library/react": ^13.4.0 @@ -2142,6 +2141,7 @@ __metadata: eslint: ^8.23.0 eslint-config-neon: ^0.1.33 happy-dom: ^6.0.4 + meilisearch: ^0.27.0 next: ^12.3.0 next-mdx-remote: ^4.1.0 next-progress: ^2.2.0 @@ -2708,13 +2708,6 @@ __metadata: languageName: node linkType: hard -"@lyrasearch/lyra@npm:^0.2.3": - version: 0.2.3 - resolution: "@lyrasearch/lyra@npm:0.2.3" - checksum: 5fde21ef623222657255fb9f592c16fcfc1f5e81fc0bf48a7c196aee9fcdc857c3cedb9ffbc55654778d6822c4c48c1ea76701a117719007d83d7e9017a24933 - languageName: node - linkType: hard - "@mapbox/node-pre-gyp@npm:^1.0.5": version: 1.0.9 resolution: "@mapbox/node-pre-gyp@npm:1.0.9" @@ -12171,6 +12164,15 @@ __metadata: languageName: node linkType: hard +"meilisearch@npm:^0.27.0": + version: 0.27.0 + resolution: "meilisearch@npm:0.27.0" + dependencies: + cross-fetch: ^3.1.5 + checksum: 78c1a667f4dc95f2a77f1a2d929d8ad25e090544abfb3d8ad44ace19e9c16f4b5a18bd74ebd0f1c33f72381732f7d31531090130fd0844460b0380bd2c875358 + languageName: node + linkType: hard + "meow@npm:^8.0.0": version: 8.1.2 resolution: "meow@npm:8.1.2"