@jbrowse/core
Version:
JBrowse 2 core libraries used by plugins
81 lines (80 loc) • 3.11 kB
JavaScript
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);
}
}