From fd3952ba93cb7901fb439ccdd46191644d85cf0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Rodrigues?= Date: Wed, 2 Oct 2019 21:37:05 +0100 Subject: [PATCH] [elasticlunr] new typings (#38717) --- types/elasticlunr/elasticlunr-tests.ts | 149 ++++++++++ types/elasticlunr/index.d.ts | 384 +++++++++++++++++++++++++ types/elasticlunr/tsconfig.json | 16 ++ types/elasticlunr/tslint.json | 1 + 4 files changed, 550 insertions(+) create mode 100644 types/elasticlunr/elasticlunr-tests.ts create mode 100644 types/elasticlunr/index.d.ts create mode 100644 types/elasticlunr/tsconfig.json create mode 100644 types/elasticlunr/tslint.json diff --git a/types/elasticlunr/elasticlunr-tests.ts b/types/elasticlunr/elasticlunr-tests.ts new file mode 100644 index 0000000000..3c12c1d46b --- /dev/null +++ b/types/elasticlunr/elasticlunr-tests.ts @@ -0,0 +1,149 @@ +import elasticlunr = require('elasticlunr'); + +function assertType(value: T): T { + return value; +} + +interface TestDocument { + id: string; + field: string; +} + +elasticlunr(); + +elasticlunr(function() { + this.addField('field'); + this.setRef('id'); + this.saveDocument(true); +}); + +const index = elasticlunr(ctx => { + ctx.addField('field'); + ctx.setRef('id'); + ctx.saveDocument(true); +}); + +const testDoc: TestDocument = { id: '1', field: 'ok' }; + +// Index + +index.addDoc(testDoc); +index.addDoc(testDoc, true); + +index.addField('field'); + +index.coordNorm({ doc: 1 }, { doc: ['token'] }, 1); + +index.fieldSearch(['ok'], 'field', { field: { boost: 10 } }); +index.fieldSearch(['ok'], 'field', { field: { boost: 10, bool: 'OR' } }); +index.fieldSearch(['ok'], 'field', { field: { boost: 10, bool: 'AND' } }); +index.fieldSearch(['ok'], 'field', { field: { boost: 10, expand: true } }); + +index.fieldSearchStats({ doc: ['ok'] }, 'ok', { doc: testDoc }); + +index.getFields(); + +index.idf('term', 'field'); + +index.mergeScores({ doc: 1 }, { doc: 1 }, 'AND'); +index.mergeScores({ doc: 1 }, { doc: 1 }, 'OR'); + +index.off('add', () => {}); +index.off('update', () => {}); +index.off('remove', () => {}); + +index.on('add', () => {}); +index.on('update', () => {}); +index.on('remove', () => {}); +index.on('add', 'update', () => {}); +index.on('add', 'update', 'remove', () => {}); + +index.removeDoc(testDoc); +index.removeDoc(testDoc, true); + +index.removeDocByRef('1'); +index.removeDocByRef('1', true); + +index.saveDocument(true); + +assertType(index.search('query')); +index.search('query', { + fields: { + field: { boost: 2 }, + }, +}); + +index.toJSON(); + +index.updateDoc(testDoc); +index.updateDoc(testDoc, true); + +index.use(() => {}); +index.use(() => {}, 1); + +elasticlunr.Index.load({ + version: 'version', + fields: ['field'], + ref: 'id', + documentStore: new elasticlunr.DocumentStore().toJSON(), + pipeline: ['trimmer', 'stopWordFilter', 'stemmer'], + index: { + field: { df: 1, docs: {} }, + }, +}); + +// Pipeline + +index.pipeline.add(() => ''); + +index.pipeline.after(() => '', () => ''); + +index.pipeline.before(() => '', () => ''); + +assertType(index.pipeline.get()); + +index.pipeline.remove(() => ''); + +assertType(index.pipeline.run([''])); + +assertType(index.pipeline.toJSON()); + +assertType(elasticlunr.Pipeline.load(index.pipeline.toJSON())); + +elasticlunr.Pipeline.registerFunction(() => '', 'fn'); +elasticlunr.Pipeline.getRegisteredFunction('fn'); +elasticlunr.Pipeline.warnIfFunctionNotRegistered(() => ''); + +// DocumentStore + +index.documentStore.addDoc('1', { id: '1', field: '1' }); + +index.documentStore.addFieldLength('1', 'field', 1); + +index.documentStore.getDoc('1'); + +index.documentStore.getFieldLength('1', 'field'); + +index.documentStore.hasDoc('1'); + +index.documentStore.isDocStored(); + +index.documentStore.removeDoc('1'); + +index.documentStore.toJSON(); + +index.documentStore.updateFieldLength('1', 'field', 1); + +elasticlunr.DocumentStore.load(index.documentStore.toJSON()); + +// EventEmitter + +index.eventEmitter.addListener('add', () => {}); + +index.eventEmitter.removeListener('add', () => {}); + +index.eventEmitter.hasHandler('add'); + +index.eventEmitter.emit('add'); + +index.eventEmitter.emit('add', 1, 2, 3); diff --git a/types/elasticlunr/index.d.ts b/types/elasticlunr/index.d.ts new file mode 100644 index 0000000000..ed8b6da09d --- /dev/null +++ b/types/elasticlunr/index.d.ts @@ -0,0 +1,384 @@ +// Type definitions for elasticlunr 0.9 +// Project: http://weixsong.github.io +// Definitions by: Luis Rodrigues +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.1 + +export = elasticlunr; + +declare function elasticlunr( + config?: (this: elasticlunr.Index, idx: elasticlunr.Index) => void, +): elasticlunr.Index; + +declare namespace elasticlunr { + class Configuration { + constructor(config: string, fields: Array); + + addAllFields2UserConfig(bool: Bool, expand: boolean, fields: Array): void; + + buildDefaultConfig(fields: Array): void; + + buildUserConfig(config: SearchConfig, fields: Array): void; + + get(): SearchConfig; + + reset(): void; + } + + type DocumentReference = string | number; + + class DocumentStore { + constructor(save?: boolean); + + addDoc(docRef: DocumentReference, doc: T): void; + + addFieldLength(docRef: DocumentReference, fieldName: keyof T, length: number): void; + + getDoc(docRef: DocumentReference): T; + + getFieldLength(docRef: DocumentReference, fieldName: keyof T): number; + + hasDoc(docRef: DocumentReference): boolean; + + isDocStored(): boolean; + + removeDoc(docRef: DocumentReference): void; + + toJSON(): SerialisedDocumentStore; + + updateFieldLength(docRef: DocumentReference, fieldName: keyof T, length: number): void; + + static load(serialisedData: SerialisedDocumentStore): DocumentStore; + } + + type EventType = 'add' | 'update' | 'remove'; + type EventHandler = (...args: any[]) => void; + + class EventEmitter { + constructor(); + + addListener(e1: EventType, fn: EventHandler): void; + addListener(e1: EventType, e2: EventType, fn: EventHandler): void; + addListener(e1: EventType, e2: EventType, e3: EventType, fn: EventHandler): void; + + emit(name: EventType, ...args: any[]): void; + + hasHandler(name: EventType): boolean; + + removeListener(name: EventType, fn: EventHandler): void; + } + + interface SearchScores { + [key: string]: number; + } + + interface SearchResults { + ref: string; + score: number; + } + + interface IndexTokens { + [key: string]: string[]; + } + + interface IndexDocuments { + [key: string]: T; + } + + type Bool = 'OR' | 'AND'; + + type FieldSearchConfig = { + [K in keyof T]?: { + bool?: Bool; + boost?: number; + expand?: boolean; + }; + }; + + interface SearchConfig { + fields?: FieldSearchConfig; + } + + interface SerialisedInvertedIndex { + root: InvertedIndexNode; + } + + interface SerialisedDocumentStore { + docInfo: { + [docRef: string]: { + [field in keyof T]: number; + }; + }; + docs: { + [docRef: string]: T; + }; + } + + interface SerialisedIndexData { + version: string; + fields: Array; + ref: keyof T; + pipeline: SerialisedPipeline; + documentStore: SerialisedDocumentStore; + index: { [K in keyof T]?: InvertedIndexNode }; + } + + class Index { + constructor(); + + documentStore: DocumentStore; + + eventEmitter: EventEmitter; + + index: { [K in keyof T]?: InvertedIndexNode }; + + pipeline: Pipeline; + + addDoc(doc: T, emitEvent?: boolean): void; + + addField(fieldName: keyof T): Index; + + coordNorm(scores: SearchScores, docTokens: IndexTokens, n: number): SearchScores; + + fieldSearch(queryTokens: string[], fieldName: keyof T, config: FieldSearchConfig): SearchScores; + + fieldSearchStats(docTokens: IndexTokens, token: string, docs: IndexDocuments): void; + + getFields(): Array; + + idf(term: string, field: keyof T): number; + + mergeScores(accumScores: SearchScores | null, scores: SearchScores, op: 'AND' | 'OR'): SearchScores; + + off(name: EventType, fn: EventHandler): void; + + on(e1: EventType, fn: EventHandler): void; + on(e1: EventType, e2: EventType, fn: EventHandler): void; + on(e1: EventType, e2: EventType, e3: EventType, fn: EventHandler): void; + + removeDoc(doc: T, emitEvent?: boolean): void; + + removeDocByRef(docRef: DocumentReference, emitEvent?: boolean): void; + + saveDocument(save: boolean): Index; + + search(query: string, userConfig?: SearchConfig): SearchResults[]; + + setRef(refName: keyof T): Index; + + toJSON(): SerialisedIndexData; + + updateDoc(doc: T, emitEvent?: boolean): void; + + use(plugin: (...args: any[]) => any, ...args: any[]): void; + + static load(serialisedData: SerialisedIndexData): Index; + } + + interface TokenInfo { + ref: number | string; + tf: number; + } + + interface InvertedIndexCharNode { + a?: InvertedIndexNode; + b?: InvertedIndexNode; + c?: InvertedIndexNode; + d?: InvertedIndexNode; + e?: InvertedIndexNode; + f?: InvertedIndexNode; + g?: InvertedIndexNode; + h?: InvertedIndexNode; + i?: InvertedIndexNode; + j?: InvertedIndexNode; + k?: InvertedIndexNode; + l?: InvertedIndexNode; + m?: InvertedIndexNode; + n?: InvertedIndexNode; + o?: InvertedIndexNode; + p?: InvertedIndexNode; + q?: InvertedIndexNode; + r?: InvertedIndexNode; + s?: InvertedIndexNode; + t?: InvertedIndexNode; + u?: InvertedIndexNode; + v?: InvertedIndexNode; + w?: InvertedIndexNode; + x?: InvertedIndexNode; + y?: InvertedIndexNode; + z?: InvertedIndexNode; + } + + interface InvertedIndexDocs { + [key: string]: { + tf?: number; + }; + } + + type InvertedIndexNode = InvertedIndexCharNode & { + df: number; + docs: InvertedIndexDocs; + }; + + class InvertedIndex { + constructor(); + + addToken(token: string, tokenInfo: TokenInfo, root?: InvertedIndexNode): void; + + expandToken(token: string, memo?: string[], root?: InvertedIndexNode): string[]; + + getDocFreq(token: string): number; + + getDocs(token: string): InvertedIndexDocs; + + getNode(token: string): InvertedIndexNode; + + getTermFrequency(token: string, docRef: string | number): number; + + hasToken(token: string): boolean; + + removeToken(token: string, ref: number | string): void; + + toJSON(): SerialisedInvertedIndex; + + static load(serialisedData: SerialisedInvertedIndex): InvertedIndex; + } + + type SerialisedPipeline = string[]; + + type PipelineFunction = (token: string, i: number, tokens: string[]) => string | undefined | null | void; + + class Pipeline { + constructor(); + + add(...functions: PipelineFunction[]): void; + + after(existingFn: PipelineFunction, newFn: PipelineFunction): void; + + before(existingFn: PipelineFunction, newFn: PipelineFunction): void; + + get(): PipelineFunction[]; + + remove(fn: PipelineFunction): void; + + reset(): void; + + run(tokens: string[]): string[]; + + toJSON(): SerialisedPipeline; + + static getRegisteredFunction(label: string): PipelineFunction; + + static load(serialised: SerialisedPipeline): Pipeline; + + static registerFunction(fn: PipelineFunction, label: string): void; + + static warnIfFunctionNotRegistered(fn: PipelineFunction): void; + } + + class SortedSet { + constructor(); + + add(...args: any[]): void; + + clone(): SortedSet; + + forEach(fn: (element: T, index: number, collection: T[]) => void, ctx: {}): void; + + indexOf(elem: {}): number; + + intersect(otherSet: SortedSet): SortedSet; + + locationFor(elem: T): number; + + map(fn: (element: T, index: number, collection: T[]) => T, ctx?: {}): T[]; + + toArray(): T[]; + + toJSON(): T[]; + + union(otherSet: SortedSet): SortedSet; + + static load(serialisedData: T[]): SortedSet; + } + + const defaultStopWords: { + [key: string]: boolean; + }; + + const version: string; + + function addStopWords(words: string[]): void; + + function clearStopWords(): void; + + function resetStopWords(): void; + + function stemmer(w: string): string; + + function stopWordFilter(token: string): string; + + function tokenizer(str?: string): string[]; + + function trimmer(token: string): string; + + namespace Pipeline { + namespace registeredFunctions { + function stemmer(w: string): string; + + function stopWordFilter(token: string): string; + + function trimmer(token: string): string; + + namespace stemmer { + const label: string; + } + + namespace stopWordFilter { + const label: string; + + const stopWords: { + [key: string]: boolean; + }; + } + + namespace trimmer { + const label: string; + } + } + } + + namespace stemmer { + const label: string; + } + + namespace stopWordFilter { + const label: string; + + const stopWords: { + [key: string]: boolean; + }; + } + + namespace tokenizer { + const defaultSeperator: RegExp; + + const seperator: RegExp; + + function getSeperator(): RegExp; + + function resetSeperator(): void; + + function setSeperator(sep: RegExp): void; + } + + namespace trimmer { + const label: string; + } + + namespace utils { + function toString(obj: {}): string; + + function warn(message: string): void; + } +} diff --git a/types/elasticlunr/tsconfig.json b/types/elasticlunr/tsconfig.json new file mode 100644 index 0000000000..8ec9b7f258 --- /dev/null +++ b/types/elasticlunr/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es6"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "baseUrl": "../", + "typeRoots": ["../"], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": ["index.d.ts", "elasticlunr-tests.ts"] +} diff --git a/types/elasticlunr/tslint.json b/types/elasticlunr/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/elasticlunr/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }