diff --git a/packages/lyra/src/lyra.ts b/packages/lyra/src/lyra.ts index e84dbeaeb..896623678 100644 --- a/packages/lyra/src/lyra.ts +++ b/packages/lyra/src/lyra.ts @@ -21,7 +21,10 @@ export type LyraProperties< defaultLanguage?: Language; }; -export type LyraDocs = Map; +export type LyraDocs = Map< + string, + ResolveSchema +>; export type SearchParams = { term: string; @@ -34,25 +37,29 @@ export type SearchParams = { type LyraIndex = Map; -type QueueDocParams = { +type QueueDocParams = { id: string; - doc: object; + doc: ResolveSchema; language: Language; }; -type SearchResult = Promise<{ +type SearchResult = Promise<{ count: number; - hits: object[]; + hits: RetrievedDoc[]; elapsed: string; }>; +type RetrievedDoc = ResolveSchema & { + id: string; +}; + export class Lyra { private defaultLanguage: Language = "english"; private schema: TSchema; - private docs: LyraDocs = new Map(); + private docs: LyraDocs = new Map(); private index: LyraIndex = new Map(); - private queue: queueAsPromised = fastq.promise( + private queue: queueAsPromised> = fastq.promise( this, this._insert, 1 @@ -91,11 +98,13 @@ export class Lyra { async search( params: SearchParams, language: Language = this.defaultLanguage - ): SearchResult { + ): SearchResult { const tokens = tokenize(params.term, language).values(); const indices = this.getIndices(params.properties); const { limit = 10, offset = 0, exact = false } = params; - const results: object[] = new Array({ length: limit }); + const results: RetrievedDoc[] = Array.from({ + length: limit, + }); let totalResults = 0; const timeStart = getNanosecondsTime(); @@ -129,7 +138,7 @@ export class Lyra { break; } - const fullDoc = this.docs.get(id); + const fullDoc = this.docs.get(id)!; results[i] = { id, ...fullDoc }; i++; } @@ -233,7 +242,11 @@ export class Lyra { return { id }; } - private async _insert({ doc, id, language }: QueueDocParams): Promise { + private async _insert({ + doc, + id, + language, + }: QueueDocParams): Promise { const index = this.index; this.docs.set(id, doc); @@ -260,10 +273,10 @@ export class Lyra { } private async checkInsertDocSchema( - doc: QueueDocParams["doc"] + doc: QueueDocParams["doc"] ): Promise { function recursiveCheck( - newDoc: QueueDocParams["doc"], + newDoc: QueueDocParams["doc"], schema: PropertiesSchema ): boolean { for (const key in newDoc) { diff --git a/packages/lyra/tests/lyra.test.ts b/packages/lyra/tests/lyra.test.ts index e5613dd09..65c2cf8f5 100644 --- a/packages/lyra/tests/lyra.test.ts +++ b/packages/lyra/tests/lyra.test.ts @@ -103,7 +103,7 @@ describe("lyra", () => { expect(ex1Insert.id).toBeDefined(); expect(ex1Search.count).toBe(1); expect(ex1Search.elapsed).toBeDefined(); - expect((ex1Search.hits[0] as any).example).toBe("The quick, brown, fox"); + expect(ex1Search.hits[0].example).toBe("The quick, brown, fox"); }); it("should correctly paginate results", async () => { @@ -126,17 +126,17 @@ describe("lyra", () => { const search4 = await db.search({ term: "f", limit: 2, offset: 2 }); expect(search1.count).toBe(4); - expect((search1.hits[0] as any).animal).toBe("Quick brown fox"); + expect(search1.hits[0].animal).toBe("Quick brown fox"); expect(search2.count).toBe(4); - expect((search2.hits[0] as any).animal).toBe("Fast chicken"); + expect(search2.hits[0].animal).toBe("Fast chicken"); expect(search3.count).toBe(4); - expect((search3.hits[0] as any).animal).toBe("Fabolous ducks"); + expect(search3.hits[0].animal).toBe("Fabolous ducks"); expect(search4.count).toBe(4); - expect((search4.hits[0] as any).animal).toBe("Fabolous ducks"); - expect((search4.hits[1] as any).animal).toBe("Fantastic horse"); + expect(search4.hits[0].animal).toBe("Fabolous ducks"); + expect(search4.hits[1].animal).toBe("Fantastic horse"); }); it("Should throw an error when searching in non-existing indices", async () => { @@ -187,11 +187,11 @@ describe("lyra", () => { expect(res).toBeTruthy(); expect(searchResult.count).toBe(1); - expect((searchResult.hits[0] as any).author).toBe("Oscar Wilde"); - expect((searchResult.hits[0] as any).quote).toBe( + expect(searchResult.hits[0].author).toBe("Oscar Wilde"); + expect(searchResult.hits[0].quote).toBe( "To live is the rarest thing in the world. Most people exist, that is all." ); - expect((searchResult.hits[0] as any).id).toBe(id2); + expect(searchResult.hits[0].id).toBe(id2); }); it("Should preserve identical docs after deletion", async () => { @@ -231,18 +231,18 @@ describe("lyra", () => { expect(res).toBeTruthy(); expect(searchResult.count).toBe(1); - expect((searchResult.hits[0] as any).author).toBe("Oscar Wilde"); - expect((searchResult.hits[0] as any).quote).toBe( + expect(searchResult.hits[0].author).toBe("Oscar Wilde"); + expect(searchResult.hits[0].quote).toBe( "Be yourself; everyone else is already taken." ); - expect((searchResult.hits[0] as any).id).toBe(id2); + expect(searchResult.hits[0].id).toBe(id2); expect(searchResult2.count).toBe(1); - expect((searchResult2.hits[0] as any).author).toBe("Oscar Wilde"); - expect((searchResult2.hits[0] as any).quote).toBe( + expect(searchResult2.hits[0].author).toBe("Oscar Wilde"); + expect(searchResult2.hits[0].quote).toBe( "Be yourself; everyone else is already taken." ); - expect((searchResult2.hits[0] as any).id).toBe(id2); + expect(searchResult2.hits[0].id).toBe(id2); }); it("Should be able to insert documens with non-searchable fields", async () => { @@ -274,7 +274,7 @@ describe("lyra", () => { }); expect(search.count).toBe(1); - expect((search.hits[0] as any).author).toBe("Frank Zappa"); + expect(search.hits[0].author).toBe("Frank Zappa"); }); it("Should exact match", async () => { @@ -303,10 +303,10 @@ describe("lyra", () => { }); expect(exactSearch.count).toBe(1); - expect((exactSearch.hits[0] as any).quote).toBe( + expect(exactSearch.hits[0].quote).toBe( "Be yourself; everyone else is already taken." ); - expect((exactSearch.hits[0] as any).author).toBe("Oscar Wilde"); + expect(exactSearch.hits[0].author).toBe("Oscar Wilde"); }); it("Shouldn't tolerate typos", async () => {