@jbrowse/plugin-legacy-jbrowse 4.3.0 → 5.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/JBrowse1Connection/configSchema.d.ts +42 -18
- package/esm/JBrowse1Connection/configSchema.js +29 -3
- package/esm/JBrowse1Connection/get-value.d.ts +1 -10
- package/esm/JBrowse1Connection/get-value.js +9 -82
- package/esm/JBrowse1Connection/index.js +2 -2
- package/esm/JBrowse1Connection/jb1ConfigLoad.d.ts +9 -36
- package/esm/JBrowse1Connection/jb1ConfigLoad.js +72 -241
- package/esm/JBrowse1Connection/jb1ConfigParse.d.ts +6 -3
- package/esm/JBrowse1Connection/jb1ConfigParse.js +25 -250
- package/esm/JBrowse1Connection/jb1ToJb2.d.ts +8 -3
- package/esm/JBrowse1Connection/jb1ToJb2.js +124 -368
- package/esm/JBrowse1Connection/model.d.ts +57 -50
- package/esm/JBrowse1Connection/model.js +23 -9
- package/esm/JBrowse1Connection/set-value.d.ts +1 -0
- package/esm/JBrowse1Connection/set-value.js +14 -0
- package/esm/JBrowse1Connection/types.d.ts +4 -57
- package/esm/JBrowse1Connection/util.d.ts +13 -8
- package/esm/JBrowse1Connection/util.js +15 -80
- package/esm/JBrowse1TextSearchAdapter/HttpMap.d.ts +34 -7
- package/esm/JBrowse1TextSearchAdapter/HttpMap.js +49 -24
- package/esm/JBrowse1TextSearchAdapter/JBrowse1TextSearchAdapter.d.ts +5 -5
- package/esm/JBrowse1TextSearchAdapter/JBrowse1TextSearchAdapter.js +21 -22
- package/esm/JBrowse1TextSearchAdapter/configSchema.d.ts +42 -14
- package/esm/JBrowse1TextSearchAdapter/configSchema.js +31 -1
- package/esm/JBrowse1TextSearchAdapter/index.js +2 -2
- package/esm/NCListAdapter/NCListAdapter.d.ts +11 -1
- package/esm/NCListAdapter/NCListAdapter.js +12 -3
- package/esm/NCListAdapter/NCListFeature.d.ts +34 -3
- package/esm/NCListAdapter/NCListFeature.js +22 -8
- package/esm/NCListAdapter/configSchema.d.ts +35 -9
- package/esm/NCListAdapter/configSchema.js +26 -1
- package/esm/NCListAdapter/index.js +2 -2
- package/esm/index.js +3 -5
- package/package.json +9 -12
- package/esm/GuessNCList/index.d.ts +0 -2
- package/esm/GuessNCList/index.js +0 -15
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { ConfigurationReference, getConf } from '@jbrowse/core/configuration';
|
|
2
2
|
import { BaseConnectionModelFactory } from '@jbrowse/core/pluggableElementTypes/models';
|
|
3
3
|
import { getSession } from '@jbrowse/core/util';
|
|
4
|
-
import { types } from '@jbrowse/mobx-state-tree';
|
|
5
|
-
import configSchema from
|
|
4
|
+
import { isAlive, types } from '@jbrowse/mobx-state-tree';
|
|
5
|
+
import configSchema from './configSchema.js';
|
|
6
|
+
/**
|
|
7
|
+
* #stateModel JBrowse1Connection
|
|
8
|
+
* Connection that imports tracks from a legacy JBrowse 1 data directory,
|
|
9
|
+
* composed on the base connection model.
|
|
10
|
+
*/
|
|
6
11
|
export default function stateModelFactory(pluginManager) {
|
|
7
12
|
return types
|
|
8
13
|
.compose('JBrowse1Connection', BaseConnectionModelFactory(pluginManager), types.model({
|
|
@@ -14,18 +19,27 @@ export default function stateModelFactory(pluginManager) {
|
|
|
14
19
|
const session = getSession(self);
|
|
15
20
|
try {
|
|
16
21
|
const dataDirLocation = getConf(self, 'dataDirLocation');
|
|
17
|
-
const { fetchJb1 } = await import(
|
|
18
|
-
const { convertTrackConfig } = await import(
|
|
22
|
+
const { fetchJb1 } = await import('./jb1ConfigLoad.js');
|
|
23
|
+
const { convertTrackConfig } = await import('./jb1ToJb2.js');
|
|
19
24
|
const config = await fetchJb1(dataDirLocation);
|
|
20
25
|
const assemblyName = getConf(self, 'assemblyNames')[0];
|
|
21
26
|
if (!assemblyName) {
|
|
22
27
|
throw new Error('assembly name required for JBrowse 1 connection');
|
|
23
28
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
// a JBrowse 1 sequence store describes the assembly, which the
|
|
30
|
+
// connection is given rather than supplying. Its ReferenceSequenceTrack
|
|
31
|
+
// schema declares neither assemblyNames nor category, so passing one
|
|
32
|
+
// through would stamp two slots JBrowse ignores onto a second copy of
|
|
33
|
+
// a sequence the assembly already has
|
|
34
|
+
const jb2Tracks = config.tracks
|
|
35
|
+
.map(jb1Track => convertTrackConfig(jb1Track, config.dataRoot || ''))
|
|
36
|
+
.filter(conf => conf.type !== 'ReferenceSequenceTrack')
|
|
37
|
+
.map(conf => ({ ...conf, assemblyNames: [assemblyName] }));
|
|
38
|
+
// the node can be destroyed during the awaits above (e.g. a React
|
|
39
|
+
// StrictMode double-mount disposes the first rootModel)
|
|
40
|
+
if (isAlive(self)) {
|
|
41
|
+
self.setTrackConfs(jb2Tracks);
|
|
42
|
+
}
|
|
29
43
|
}
|
|
30
44
|
catch (error) {
|
|
31
45
|
console.error(error);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function setValue(target: Record<string, unknown>, path: string, value: unknown): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// minimal nested setter, replaces the `set-value` dependency. Splits the dot
|
|
2
|
+
// path and creates intermediate objects as needed, mirroring ./get-value.ts
|
|
3
|
+
export default function setValue(target, path, value) {
|
|
4
|
+
const segs = path.split('.');
|
|
5
|
+
const last = segs.pop();
|
|
6
|
+
let obj = target;
|
|
7
|
+
for (const seg of segs) {
|
|
8
|
+
if (typeof obj[seg] !== 'object' || obj[seg] === null) {
|
|
9
|
+
obj[seg] = {};
|
|
10
|
+
}
|
|
11
|
+
obj = obj[seg];
|
|
12
|
+
}
|
|
13
|
+
obj[last] = value;
|
|
14
|
+
}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
export interface ProtoTrack {
|
|
2
|
-
|
|
3
|
-
baseUrl?: string;
|
|
2
|
+
[key: string]: unknown;
|
|
4
3
|
category?: string;
|
|
5
|
-
config?:
|
|
6
|
-
dataRoot?: string;
|
|
4
|
+
config?: ProtoTrack;
|
|
7
5
|
features?: Feature[];
|
|
8
|
-
histograms?: Track;
|
|
9
|
-
index?: number;
|
|
10
6
|
key?: string;
|
|
11
7
|
label?: string;
|
|
12
8
|
metadata?: Metadata;
|
|
13
|
-
store?: Store | string;
|
|
14
9
|
storeClass?: string;
|
|
15
10
|
type?: string;
|
|
16
11
|
urlTemplate?: string;
|
|
@@ -20,7 +15,6 @@ export interface ProtoTrack {
|
|
|
20
15
|
csiUrlTemplate?: string;
|
|
21
16
|
faiUrlTemplate?: string;
|
|
22
17
|
gziUrlTemplate?: string;
|
|
23
|
-
useAsRefSeqStore?: boolean;
|
|
24
18
|
}
|
|
25
19
|
export interface Track extends ProtoTrack {
|
|
26
20
|
label: string;
|
|
@@ -36,56 +30,9 @@ export interface Feature {
|
|
|
36
30
|
end: number;
|
|
37
31
|
name?: string;
|
|
38
32
|
}
|
|
39
|
-
export interface Source {
|
|
40
|
-
url: string;
|
|
41
|
-
name?: string;
|
|
42
|
-
type?: string;
|
|
43
|
-
}
|
|
44
|
-
export interface TrackMetadata {
|
|
45
|
-
sources?: string | Source | (string | Source)[] | Record<string, Source>;
|
|
46
|
-
}
|
|
47
|
-
export interface Store extends ProtoTrack {
|
|
48
|
-
name?: string;
|
|
49
|
-
}
|
|
50
|
-
export interface Names {
|
|
51
|
-
baseUrl?: string;
|
|
52
|
-
}
|
|
53
|
-
export interface RefSeq {
|
|
54
|
-
name: string;
|
|
55
|
-
length: number;
|
|
56
|
-
end: number;
|
|
57
|
-
start: number;
|
|
58
|
-
}
|
|
59
|
-
export interface RefSeqs {
|
|
60
|
-
url?: string;
|
|
61
|
-
data?: RefSeq[];
|
|
62
|
-
}
|
|
63
|
-
export interface Include {
|
|
64
|
-
url: string;
|
|
65
|
-
cacheBuster?: boolean;
|
|
66
|
-
format?: string;
|
|
67
|
-
version?: number;
|
|
68
|
-
}
|
|
69
33
|
export interface Config {
|
|
70
|
-
|
|
71
|
-
cacheBuster?: boolean;
|
|
34
|
+
[key: string]: unknown;
|
|
72
35
|
dataRoot?: string;
|
|
73
|
-
include?: string[];
|
|
74
|
-
names?: Record<string, string>;
|
|
75
|
-
nameUrl?: string;
|
|
76
|
-
refSeqs?: string | RefSeqs;
|
|
77
|
-
sourceUrl?: string;
|
|
78
|
-
stores?: Record<string, Store>;
|
|
79
|
-
trackMetadata?: TrackMetadata;
|
|
36
|
+
include?: string | string[];
|
|
80
37
|
tracks?: Track | Track[] | Record<string, Track | ProtoTrack>;
|
|
81
38
|
}
|
|
82
|
-
export interface UriLocation {
|
|
83
|
-
uri: string;
|
|
84
|
-
baseUri?: string;
|
|
85
|
-
locationType: 'UriLocation';
|
|
86
|
-
}
|
|
87
|
-
export interface LocalPathLocation {
|
|
88
|
-
localPath: string;
|
|
89
|
-
locationType: 'LocalPathLocation';
|
|
90
|
-
}
|
|
91
|
-
export type JBLocation = UriLocation | LocalPathLocation;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function isTrack(arg:
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import type { Track } from './types.ts';
|
|
2
|
+
export declare function isTrack(arg: unknown): arg is Track;
|
|
3
|
+
/**
|
|
4
|
+
* replace variables in a template string with values
|
|
5
|
+
*
|
|
6
|
+
* @param template - String with variable names in curly brackets
|
|
7
|
+
* e.g., `http://foo/{bar}?arg={baz.foo}`
|
|
8
|
+
* @param fillWith - object with attribute-value mappings
|
|
9
|
+
* e.g., `{ 'bar': 'someurl', 'baz': { 'foo': 42 } }`
|
|
10
|
+
* @returns the template string with variables in fillWith replaced
|
|
11
|
+
* e.g., 'htp://foo/someurl?arg=valueforbaz'
|
|
12
|
+
*/
|
|
13
|
+
export declare function fillTemplate(template: string, fillWith: Record<string, unknown>): string;
|
|
@@ -1,86 +1,21 @@
|
|
|
1
|
-
import getValue from
|
|
1
|
+
import getValue from './get-value.js';
|
|
2
2
|
export function isTrack(arg) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export function isSource(arg) {
|
|
6
|
-
return arg?.url && typeof arg.url === 'string';
|
|
7
|
-
}
|
|
8
|
-
export function deepUpdate(a, b) {
|
|
9
|
-
for (const prop of Object.keys(b)) {
|
|
10
|
-
if (prop === '__proto__' ||
|
|
11
|
-
prop === 'constructor' ||
|
|
12
|
-
prop === 'prototype') {
|
|
13
|
-
continue;
|
|
14
|
-
}
|
|
15
|
-
if (prop in a &&
|
|
16
|
-
typeof b[prop] === 'object' &&
|
|
17
|
-
typeof a[prop] === 'object') {
|
|
18
|
-
deepUpdate(a[prop], b[prop]);
|
|
19
|
-
}
|
|
20
|
-
else if (a[prop] === undefined || b[prop] !== undefined) {
|
|
21
|
-
a[prop] = b[prop];
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return a;
|
|
3
|
+
const a = arg;
|
|
4
|
+
return !!a?.label && typeof a.label === 'string';
|
|
25
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* replace variables in a template string with values
|
|
8
|
+
*
|
|
9
|
+
* @param template - String with variable names in curly brackets
|
|
10
|
+
* e.g., `http://foo/{bar}?arg={baz.foo}`
|
|
11
|
+
* @param fillWith - object with attribute-value mappings
|
|
12
|
+
* e.g., `{ 'bar': 'someurl', 'baz': { 'foo': 42 } }`
|
|
13
|
+
* @returns the template string with variables in fillWith replaced
|
|
14
|
+
* e.g., 'htp://foo/someurl?arg=valueforbaz'
|
|
15
|
+
*/
|
|
26
16
|
export function fillTemplate(template, fillWith) {
|
|
27
17
|
return template.replaceAll(/{([\s\w.]+)}/g, (match, varName) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (fill !== undefined) {
|
|
31
|
-
return typeof fill === 'function' ? fill(varName) : fill;
|
|
32
|
-
}
|
|
33
|
-
if (fillWith.callback) {
|
|
34
|
-
const v = fillWith.callback.call(this, varName);
|
|
35
|
-
if (v !== undefined) {
|
|
36
|
-
return v;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return match;
|
|
18
|
+
const fill = getValue(fillWith, varName.replaceAll(/\s+/g, ''));
|
|
19
|
+
return fill === undefined ? match : `${fill}`;
|
|
40
20
|
});
|
|
41
21
|
}
|
|
42
|
-
export function structuredClone(src) {
|
|
43
|
-
if (!src ||
|
|
44
|
-
typeof src !== 'object' ||
|
|
45
|
-
Object.prototype.toString.call(src) === '[object Function]') {
|
|
46
|
-
return src;
|
|
47
|
-
}
|
|
48
|
-
if (src.nodeType && 'cloneNode' in src) {
|
|
49
|
-
return src.cloneNode(true);
|
|
50
|
-
}
|
|
51
|
-
if (src instanceof Date) {
|
|
52
|
-
return new Date(src);
|
|
53
|
-
}
|
|
54
|
-
if (src instanceof RegExp) {
|
|
55
|
-
return new RegExp(src);
|
|
56
|
-
}
|
|
57
|
-
let r;
|
|
58
|
-
if (Array.isArray(src)) {
|
|
59
|
-
r = [];
|
|
60
|
-
for (let i = 0, l = src.length; i < l; ++i) {
|
|
61
|
-
if (i in src) {
|
|
62
|
-
r[i] = structuredClone(src[i]);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
r = src.constructor ? new src.constructor() : {};
|
|
68
|
-
}
|
|
69
|
-
return mixin(r, src, a => structuredClone(a));
|
|
70
|
-
}
|
|
71
|
-
function mixin(dest, source, copyFunc) {
|
|
72
|
-
const empty = {};
|
|
73
|
-
for (const name in source) {
|
|
74
|
-
if (name === '__proto__' ||
|
|
75
|
-
name === 'constructor' ||
|
|
76
|
-
name === 'prototype') {
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
const s = source[name];
|
|
80
|
-
if (!(name in dest) ||
|
|
81
|
-
(dest[name] !== s && (!(name in empty) || empty[name] !== s))) {
|
|
82
|
-
dest[name] = copyFunc ? copyFunc(s) : s;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return dest;
|
|
86
|
-
}
|
|
@@ -1,19 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper class allows reading names index generated in JBrowse1
|
|
3
|
+
* Adapted from https://github.com/GMOD/jbrowse/blob/master/src/JBrowse/Store/Hash.js
|
|
4
|
+
*/
|
|
5
|
+
interface Meta {
|
|
6
|
+
hashHexCharacters: number;
|
|
7
|
+
compress: number;
|
|
8
|
+
tracks: string[];
|
|
9
|
+
}
|
|
1
10
|
export default class HttpMap {
|
|
2
11
|
url: string;
|
|
12
|
+
private metaPromise;
|
|
3
13
|
constructor(args: {
|
|
4
14
|
url: string;
|
|
5
15
|
});
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}>;
|
|
16
|
+
/**
|
|
17
|
+
* loads meta.json file from names directory and reads number of hash_bits used
|
|
18
|
+
*/
|
|
19
|
+
readMeta(): Promise<Meta>;
|
|
11
20
|
getHashHexCharacters(): Promise<number>;
|
|
12
|
-
getCompress(): Promise<
|
|
13
|
-
getTrackNames(): Promise<
|
|
21
|
+
getCompress(): Promise<number>;
|
|
22
|
+
getTrackNames(): Promise<string[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Returns contents of a bucket given a key
|
|
25
|
+
* @param key - string
|
|
26
|
+
*/
|
|
14
27
|
get(key: string): Promise<any>;
|
|
28
|
+
/**
|
|
29
|
+
* Returns a bucket given a key
|
|
30
|
+
* @param key - string
|
|
31
|
+
*/
|
|
15
32
|
getBucket(key: string): Promise<any>;
|
|
33
|
+
/**
|
|
34
|
+
* Loads a file using the url and provided id.
|
|
35
|
+
* Returns response object with contents of the file
|
|
36
|
+
* @param id - string
|
|
37
|
+
*/
|
|
16
38
|
loadFile(id: string): Promise<any>;
|
|
39
|
+
/**
|
|
40
|
+
* Returns the corresponding path of the file given a hex string
|
|
41
|
+
* @param hex - hex string
|
|
42
|
+
*/
|
|
17
43
|
hexToDirPath(hex: string): Promise<string>;
|
|
18
44
|
hash(data: string): string;
|
|
19
45
|
}
|
|
46
|
+
export {};
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper class allows reading names index generated in JBrowse1
|
|
3
|
+
* Adapted from https://github.com/GMOD/jbrowse/blob/master/src/JBrowse/Store/Hash.js
|
|
4
|
+
*/
|
|
1
5
|
const crcTable = new Uint32Array(256);
|
|
2
6
|
for (let i = 0; i < 256; i++) {
|
|
3
7
|
let c = i;
|
|
@@ -15,36 +19,54 @@ function crc32(str) {
|
|
|
15
19
|
}
|
|
16
20
|
export default class HttpMap {
|
|
17
21
|
url;
|
|
22
|
+
metaPromise;
|
|
18
23
|
constructor(args) {
|
|
19
24
|
this.url = args.url.endsWith('/') ? args.url : `${args.url}/`;
|
|
20
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* loads meta.json file from names directory and reads number of hash_bits used
|
|
28
|
+
*/
|
|
21
29
|
async readMeta() {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
if (!this.metaPromise) {
|
|
31
|
+
this.metaPromise = this.loadFile('meta.json').then(meta => ({
|
|
32
|
+
hashHexCharacters: Math.ceil(meta.hash_bits / 4),
|
|
33
|
+
compress: meta.compress,
|
|
34
|
+
tracks: meta.track_names,
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
return this.metaPromise;
|
|
26
38
|
}
|
|
27
39
|
async getHashHexCharacters() {
|
|
28
|
-
|
|
29
|
-
return meta.hashHexCharacters;
|
|
40
|
+
return (await this.readMeta()).hashHexCharacters;
|
|
30
41
|
}
|
|
31
42
|
async getCompress() {
|
|
32
|
-
|
|
33
|
-
return meta.compress;
|
|
43
|
+
return (await this.readMeta()).compress;
|
|
34
44
|
}
|
|
35
45
|
async getTrackNames() {
|
|
36
|
-
|
|
37
|
-
return meta.tracks;
|
|
46
|
+
return (await this.readMeta()).tracks;
|
|
38
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Returns contents of a bucket given a key
|
|
50
|
+
* @param key - string
|
|
51
|
+
*/
|
|
39
52
|
async get(key) {
|
|
40
53
|
const bucket = await this.getBucket(key);
|
|
41
54
|
return bucket[key];
|
|
42
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns a bucket given a key
|
|
58
|
+
* @param key - string
|
|
59
|
+
*/
|
|
43
60
|
async getBucket(key) {
|
|
44
61
|
const bucketIdent = this.hash(key);
|
|
45
62
|
const hexToDirPath = await this.hexToDirPath(bucketIdent);
|
|
46
63
|
return this.loadFile(hexToDirPath);
|
|
47
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Loads a file using the url and provided id.
|
|
67
|
+
* Returns response object with contents of the file
|
|
68
|
+
* @param id - string
|
|
69
|
+
*/
|
|
48
70
|
async loadFile(id) {
|
|
49
71
|
const response = await fetch(`${this.url}${id}`);
|
|
50
72
|
if (!response.ok) {
|
|
@@ -52,23 +74,26 @@ export default class HttpMap {
|
|
|
52
74
|
}
|
|
53
75
|
return response.json();
|
|
54
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Returns the corresponding path of the file given a hex string
|
|
79
|
+
* @param hex - hex string
|
|
80
|
+
*/
|
|
55
81
|
async hexToDirPath(hex) {
|
|
56
|
-
const hashHexCharacters = await this.
|
|
57
|
-
if (hashHexCharacters) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return `${dirpath.join('/')}.json${compress ? 'z' : ''}`;
|
|
82
|
+
const { hashHexCharacters, compress } = await this.readMeta();
|
|
83
|
+
if (!hashHexCharacters) {
|
|
84
|
+
return '';
|
|
85
|
+
}
|
|
86
|
+
while (hex.length < 8) {
|
|
87
|
+
hex = `0${hex}`;
|
|
88
|
+
}
|
|
89
|
+
hex = hex.slice(8 - hashHexCharacters);
|
|
90
|
+
const dirpath = [];
|
|
91
|
+
for (let i = 0; i < hex.length; i += 3) {
|
|
92
|
+
dirpath.push(hex.slice(i, i + 3));
|
|
68
93
|
}
|
|
69
|
-
return ''
|
|
94
|
+
return `${dirpath.join('/')}.json${compress ? 'z' : ''}`;
|
|
70
95
|
}
|
|
71
96
|
hash(data) {
|
|
72
|
-
return crc32(data).toString(16).toLowerCase()
|
|
97
|
+
return crc32(data).toString(16).toLowerCase();
|
|
73
98
|
}
|
|
74
99
|
}
|
|
@@ -5,22 +5,22 @@ import type PluginManager from '@jbrowse/core/PluginManager';
|
|
|
5
5
|
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
6
6
|
import type { BaseTextSearchAdapter, BaseTextSearchArgs } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
7
7
|
import type { getSubAdapterType } from '@jbrowse/core/data_adapters/dataAdapterCache';
|
|
8
|
-
export interface TooManyHits {
|
|
9
|
-
name: string;
|
|
10
|
-
hitLimit: number;
|
|
11
|
-
}
|
|
12
8
|
interface SearchResults {
|
|
13
9
|
prefix: ({
|
|
14
10
|
name: string;
|
|
15
11
|
} | string)[];
|
|
16
12
|
exact: [string, number, string, string, number, number][];
|
|
17
13
|
}
|
|
18
|
-
export type NamesIndexRecord = string | (string | number)[];
|
|
19
14
|
type IndexFile = Record<string, SearchResults>;
|
|
20
15
|
export default class JBrowse1TextSearchAdapter extends BaseAdapter implements BaseTextSearchAdapter {
|
|
21
16
|
httpMap: HttpMap;
|
|
22
17
|
tracksNames?: string[];
|
|
23
18
|
constructor(config: AnyConfigurationModel, getSubAdapter?: getSubAdapterType, pluginManager?: PluginManager);
|
|
19
|
+
/**
|
|
20
|
+
* Returns the contents of the file containing the query if it exists
|
|
21
|
+
* else it returns empty
|
|
22
|
+
* @param query - string query
|
|
23
|
+
*/
|
|
24
24
|
loadIndexFile(query: string): Promise<IndexFile>;
|
|
25
25
|
searchIndex(args: BaseTextSearchArgs): Promise<BaseResult[]>;
|
|
26
26
|
formatResults(results: SearchResults, tracks: string[], searchType?: string): BaseResult[];
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import BaseResult from '@jbrowse/core/TextSearch/BaseResults';
|
|
2
2
|
import { readConfObject } from '@jbrowse/core/configuration';
|
|
3
3
|
import { BaseAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
4
|
-
import HttpMap from
|
|
4
|
+
import HttpMap from './HttpMap.js';
|
|
5
|
+
// Uses index built by generate-names.pl
|
|
5
6
|
export default class JBrowse1TextSearchAdapter extends BaseAdapter {
|
|
6
7
|
httpMap;
|
|
7
8
|
tracksNames;
|
|
@@ -13,17 +14,21 @@ export default class JBrowse1TextSearchAdapter extends BaseAdapter {
|
|
|
13
14
|
url: baseUri ? new URL(uri, baseUri).href : uri,
|
|
14
15
|
});
|
|
15
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Returns the contents of the file containing the query if it exists
|
|
19
|
+
* else it returns empty
|
|
20
|
+
* @param query - string query
|
|
21
|
+
*/
|
|
16
22
|
async loadIndexFile(query) {
|
|
17
23
|
return this.httpMap.getBucket(query);
|
|
18
24
|
}
|
|
19
25
|
async searchIndex(args) {
|
|
20
26
|
const { searchType, queryString } = args;
|
|
21
|
-
const tracks = this.tracksNames
|
|
27
|
+
const tracks = this.tracksNames ?? (await this.httpMap.getTrackNames());
|
|
22
28
|
const str = queryString.toLowerCase();
|
|
23
29
|
const entries = await this.loadIndexFile(str);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
: [];
|
|
30
|
+
const results = entries[str];
|
|
31
|
+
return results ? this.formatResults(results, tracks, searchType) : [];
|
|
27
32
|
}
|
|
28
33
|
formatResults(results, tracks, searchType) {
|
|
29
34
|
return [
|
|
@@ -31,24 +36,18 @@ export default class JBrowse1TextSearchAdapter extends BaseAdapter {
|
|
|
31
36
|
? []
|
|
32
37
|
: results.prefix.map(result => new BaseResult({
|
|
33
38
|
label: typeof result === 'object' ? result.name : result,
|
|
34
|
-
matchedAttribute: 'name',
|
|
35
|
-
matchedObject: { result: result },
|
|
36
39
|
}))),
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
matchedObject: result,
|
|
49
|
-
trackId: tracks[trackIndex],
|
|
50
|
-
});
|
|
51
|
-
}),
|
|
40
|
+
// the bucket is keyed by the query, so everything in its `exact` list
|
|
41
|
+
// matched it exactly — which is what lets a caller ask once rather than
|
|
42
|
+
// asking for exact hits and then for all of them
|
|
43
|
+
...results.exact.map(([name, trackIndex, , refName, start, end]) => new BaseResult({
|
|
44
|
+
locString: `${refName || name}:${start}-${end}`,
|
|
45
|
+
label: name,
|
|
46
|
+
trackId: tracks[trackIndex],
|
|
47
|
+
exact: true,
|
|
48
|
+
})),
|
|
49
|
+
// the index encodes an overflow bucket as a pseudo-hit; it is a message,
|
|
50
|
+
// not a navigable location
|
|
52
51
|
].filter(result => result.getLabel() !== 'too many matches');
|
|
53
52
|
}
|
|
54
53
|
}
|
|
@@ -1,21 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #config JBrowse1TextSearchAdapter
|
|
3
|
+
* #trackType TextSearchAdapter
|
|
4
|
+
* #fileFormat textsearch | JBrowse 1 names index | From JBrowse 1 `generate-names.pl`
|
|
5
|
+
* note: metadata about tracks and assemblies covered by text search adapter
|
|
6
|
+
*
|
|
7
|
+
* #example
|
|
8
|
+
* An entry in `aggregateTextSearchAdapters`, pointing at the `names/`
|
|
9
|
+
* directory JBrowse 1's `generate-names.pl` wrote — so an existing instance's
|
|
10
|
+
* search index is reused rather than rebuilt with `jbrowse text-index`:
|
|
11
|
+
* ```js
|
|
12
|
+
* {
|
|
13
|
+
* type: 'JBrowse1TextSearchAdapter',
|
|
14
|
+
* textSearchAdapterId: 'jbrowse1-names',
|
|
15
|
+
* namesIndexLocation: { uri: 'https://example.com/jbrowse1/data/names/' },
|
|
16
|
+
* assemblyNames: ['hg19'],
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
1
20
|
declare const _default: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
21
|
+
/**
|
|
22
|
+
* #slot
|
|
23
|
+
*/
|
|
24
|
+
readonly namesIndexLocation: {
|
|
25
|
+
readonly type: "fileLocation";
|
|
26
|
+
readonly defaultValue: {
|
|
27
|
+
readonly uri: "/volvox/names";
|
|
28
|
+
readonly locationType: "UriLocation";
|
|
7
29
|
};
|
|
8
|
-
description:
|
|
30
|
+
readonly description: "the location of the JBrowse1 names index data directory";
|
|
9
31
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
32
|
+
/**
|
|
33
|
+
* #slot
|
|
34
|
+
*/
|
|
35
|
+
readonly tracks: {
|
|
36
|
+
readonly type: "stringArray";
|
|
37
|
+
readonly defaultValue: readonly [];
|
|
38
|
+
readonly description: "List of tracks covered by text search adapter";
|
|
14
39
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
40
|
+
/**
|
|
41
|
+
* #slot
|
|
42
|
+
*/
|
|
43
|
+
readonly assemblyNames: {
|
|
44
|
+
readonly type: "stringArray";
|
|
45
|
+
readonly defaultValue: readonly [];
|
|
46
|
+
readonly description: "List of assemblies covered by text search adapter";
|
|
19
47
|
};
|
|
20
48
|
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "textSearchAdapterId">>;
|
|
21
49
|
export default _default;
|
|
@@ -1,16 +1,43 @@
|
|
|
1
1
|
import { ConfigurationSchema } from '@jbrowse/core/configuration';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* #config JBrowse1TextSearchAdapter
|
|
4
|
+
* #trackType TextSearchAdapter
|
|
5
|
+
* #fileFormat textsearch | JBrowse 1 names index | From JBrowse 1 `generate-names.pl`
|
|
6
|
+
* note: metadata about tracks and assemblies covered by text search adapter
|
|
7
|
+
*
|
|
8
|
+
* #example
|
|
9
|
+
* An entry in `aggregateTextSearchAdapters`, pointing at the `names/`
|
|
10
|
+
* directory JBrowse 1's `generate-names.pl` wrote — so an existing instance's
|
|
11
|
+
* search index is reused rather than rebuilt with `jbrowse text-index`:
|
|
12
|
+
* ```js
|
|
13
|
+
* {
|
|
14
|
+
* type: 'JBrowse1TextSearchAdapter',
|
|
15
|
+
* textSearchAdapterId: 'jbrowse1-names',
|
|
16
|
+
* namesIndexLocation: { uri: 'https://example.com/jbrowse1/data/names/' },
|
|
17
|
+
* assemblyNames: ['hg19'],
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
3
21
|
export default ConfigurationSchema('JBrowse1TextSearchAdapter', {
|
|
22
|
+
/**
|
|
23
|
+
* #slot
|
|
24
|
+
*/
|
|
4
25
|
namesIndexLocation: {
|
|
5
26
|
type: 'fileLocation',
|
|
6
27
|
defaultValue: { uri: '/volvox/names', locationType: 'UriLocation' },
|
|
7
28
|
description: 'the location of the JBrowse1 names index data directory',
|
|
8
29
|
},
|
|
30
|
+
/**
|
|
31
|
+
* #slot
|
|
32
|
+
*/
|
|
9
33
|
tracks: {
|
|
10
34
|
type: 'stringArray',
|
|
11
35
|
defaultValue: [],
|
|
12
36
|
description: 'List of tracks covered by text search adapter',
|
|
13
37
|
},
|
|
38
|
+
/**
|
|
39
|
+
* #slot
|
|
40
|
+
*/
|
|
14
41
|
assemblyNames: {
|
|
15
42
|
type: 'stringArray',
|
|
16
43
|
defaultValue: [],
|
|
@@ -18,5 +45,8 @@ export default ConfigurationSchema('JBrowse1TextSearchAdapter', {
|
|
|
18
45
|
},
|
|
19
46
|
}, {
|
|
20
47
|
explicitlyTyped: true,
|
|
48
|
+
/**
|
|
49
|
+
* #identifier
|
|
50
|
+
*/
|
|
21
51
|
explicitIdentifier: 'textSearchAdapterId',
|
|
22
52
|
});
|