@paperbits/common
Version:
Paperbits common components.
66 lines (49 loc) • 1.96 kB
text/typescript
import * as lunr from "lunr";
import { SearchResult, SearchResultBuilder } from "@paperbits/common/search";
import { HttpClient } from "@paperbits/common/http";
export interface SearchService {
search(query: string): Promise<SearchResult[]>;
registerSearchResultBuilder(builder: SearchResultBuilder): void;
}
export class StaticSearchService implements SearchService {
private index: lunr.Index;
private searchResultBuilders: SearchResultBuilder[];
constructor(private readonly httpClient: HttpClient) {
this.searchResultBuilders = [];
this.loadIndex();
}
public async loadIndex(): Promise<void> {
try {
const response = await this.httpClient.send({ url: "/search-index.json", method: "GET" });
if (response.statusCode !== 200) {
return;
}
const indexData: any = response.toObject();
this.index = lunr.Index.load(indexData);
}
catch (error) {
console.log(error);
}
}
public async search(query: string): Promise<SearchResult[]> {
const results = [];
if (!this.index || query.length < 2) {
return results;
}
const searchRawResults = this.index.search(query).slice(0, 5);
for (const rawResult of searchRawResults) {
const searchTerm = Object.keys(rawResult.matchData.metadata)[0];
for (const resultBuilder of this.searchResultBuilders) {
const result = await resultBuilder.getSearchResult(rawResult.ref, searchTerm);
if (!result) {
continue;
}
results.push(result)
}
}
return results;
}
public registerSearchResultBuilder(builder: SearchResultBuilder): void {
this.searchResultBuilders.push(builder);
}
}