UNPKG

@jbrowse/core

Version:

JBrowse 2 core libraries used by plugins

81 lines (80 loc) 3.11 kB
import uFuzzy from '@leeoniya/ufuzzy'; import { readConfObject } from "../configuration/index.js"; import QuickLRU from "../util/QuickLRU/index.js"; export default class TextSearchManager { pluginManager; adapterCache = new QuickLRU({ maxSize: 15, }); constructor(pluginManager) { this.pluginManager = pluginManager; } clearCache() { this.adapterCache.clear(); } loadTextSearchAdapters(searchScope) { return Promise.all(this.relevantAdapters(searchScope).map(async (conf) => { const adapterId = readConfObject(conf, 'textSearchAdapterId'); const r = this.adapterCache.get(adapterId); if (r) { return r; } else { const adapterType = this.pluginManager.getTextSearchAdapterType(conf.type); const AdapterClass = await adapterType.getAdapterClass(); const adapterInstance = new AdapterClass(conf, undefined, this.pluginManager); this.adapterCache.set(adapterId, adapterInstance); return adapterInstance; } })); } relevantAdapters(searchScope) { const rootModel = this.pluginManager.rootModel; const { aggregateTextSearchAdapters } = rootModel?.jbrowse; const { tracks } = rootModel?.session; const { assemblyName } = searchScope; return [ ...this.getAdaptersWithAssembly(assemblyName, aggregateTextSearchAdapters), ...this.getTrackAdaptersWithAssembly(assemblyName, tracks), ]; } getAdaptersWithAssembly(assemblyName, confs) { return confs.filter(c => readConfObject(c, 'assemblyNames')?.includes(assemblyName)); } getTrackAdaptersWithAssembly(assemblyName, confs) { return confs .filter(conf => readConfObject(conf, [ 'textSearching', 'textSearchAdapter', 'assemblyNames', ])?.includes(assemblyName)) .map(conf => conf.textSearching.textSearchAdapter); } async search(args, searchScope, rankFn) { return this.search2({ args, searchScope, rankFn }); } async search2({ args, searchScope, rankFn, }) { const adapters = await this.loadTextSearchAdapters(searchScope); const results = await Promise.all(adapters.map(a => a.searchIndex(args))); return this.sortResults2({ args, results: results.flat(), rankFn, }); } sortResults2({ results, rankFn, args, }) { const uf = new uFuzzy({}); const haystack = results.map(r => r.getDisplayString()); const needle = args.queryString; const idxs = uf.filter(haystack, needle); const res = []; if (idxs != null && idxs.length > 0) { const info = uf.info(idxs, haystack, needle); const order = uf.sort(info, haystack, needle); for (const element of order) { res.push(results[info.idx[element]]); } } return rankFn(res); } }