import { editDistance } from "./distance"; import { foldText, splitWords, tokenize } from "./fold"; /** One searchable string; `weight` scales its matches (label 1, keyword 0.75, context 0.4). */ export type LauncherSearchField = { /** Field identifier, reported back in `LauncherTokenMatch.field`. */ name: string; /** String to match, compared without case or accents. */ text: string; /** Scales this field's matches; defaults to 1. */ weight?: number; }; /** Anything searchable: an id plus its weighted fields, in the order results should tie-break. */ export type LauncherSearchDocument = { /** Identifier returned on the matching hit. */ id: string; /** Fields searched; each query token scores against its best field. */ fields: readonly LauncherSearchField[]; }; /** How a query token matched a field, strongest first. */ export type LauncherMatchKind = "exact" | "prefix" | "word" | "word-prefix" | "initialism" | "substring" | "fuzzy" | "subsequence"; /** The field that gave a query token its best score. */ export type LauncherTokenMatch = { /** The query token this entry explains. */ token: string; /** `name` of the field that scored best for the token. */ field: string; /** Text of that field. */ text: string; /** How the token matched that field. */ kind: LauncherMatchKind; }; /** A ranked document: `index` is its input position, `synonym` the expansion used. */ export type LauncherSearchHit = { /** `id` of the matching document. */ id: string; /** Position of the document in the list that was indexed. */ index: number; /** Relevance, including any `boosts`; higher ranks first. */ score: number; /** Best match for each query token. */ matches: LauncherTokenMatch[]; /** The synonym expansion that produced the hit; absent when the literal query matched. */ synonym?: string; }; /** Term -> equivalent phrases, matched both ways: `{ pf: ["provident fund"] }`. */ export type LauncherSynonyms = Readonly>; /** Ranking knobs; `boosts` adds points per document id to documents that already match. */ export type LauncherSearchOptions = { /** Equivalent terms expanded in both directions. */ synonyms?: LauncherSynonyms; /** Points added per document id to documents that already match; never adds a non-match. */ boosts?: Readonly>; /** Typo tolerance; defaults to true. */ fuzzy?: boolean; /** Drops hits under this share of the best score; 0 keeps all. */ relativeCutoff?: number; /** Maximum hits returned; unlimited when omitted. */ limit?: number; }; type IndexedField = { name: string; text: string; weight: number; folded: string; compact: string; words: string[]; starts: number[]; initials: string; mask: number; letterWords: readonly (readonly string[])[] | null; }; type IndexedDocument = { id: string; index: number; fields: IndexedField[]; mask: number; }; /** Pre-folded documents; build once with `createIndex`, query many times. */ export type LauncherSearchIndex = { /** Number of indexed documents. */ readonly size: number; /** Pre-folded records; internal shape, pass the index to the engine rather than reading it. */ readonly documents: readonly IndexedDocument[]; }; export declare const createSearchIndex: (documents: readonly LauncherSearchDocument[]) => LauncherSearchIndex; type CompileOptions = Pick; export declare const searchIndex: (index: LauncherSearchIndex, query: string, options?: LauncherSearchOptions) => LauncherSearchHit[]; export declare const searchDocuments: (documents: readonly LauncherSearchDocument[], query: string, options?: LauncherSearchOptions) => LauncherSearchHit[]; /** Boolean test over one row's texts; an empty query matches every row. */ export type LauncherMatcher = (...texts: ReadonlyArray) => boolean; /** Compiles `query` once; every query word must hit some text of the row. */ export declare const createMatcher: (query: string, options?: CompileOptions) => LauncherMatcher; /** One-off form of `createMatcher`: does `query` match the row made of `texts`? */ export declare const matchesQuery: (query: string, ...texts: ReadonlyArray) => boolean; /** Character ranges of `text` a query matched, in original-text offsets, merged and sorted. */ export declare const highlightRanges: (text: string, query: string, options?: Pick) => Array<[number, number]>; /** Additive ranking points from usage: pinned flat, frequent and recent decaying by position. */ export declare const usageBoosts: (usage: { pinnedIds?: readonly string[]; frequentIds?: readonly string[]; recentIds?: readonly string[]; }) => Record; export { editDistance, foldText, splitWords, tokenize };