@jbrowse/plugin-legacy-jbrowse 1.4.1 → 1.5.2
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/dist/JBrowse1Connection/jb1ToJb2.d.ts +1 -0
- package/dist/JBrowse1Connection/types.d.ts +2 -0
- package/dist/JBrowse1TextSeachAdapter/HttpMap.d.ts +1 -15
- package/dist/JBrowse1TextSeachAdapter/JBrowse1TextSearchAdapter.d.ts +12 -8
- package/dist/NCListAdapter/NCListAdapter.d.ts +3 -1
- package/dist/plugin-legacy-jbrowse.cjs.development.js +334 -398
- package/dist/plugin-legacy-jbrowse.cjs.development.js.map +1 -1
- package/dist/plugin-legacy-jbrowse.cjs.production.min.js +1 -1
- package/dist/plugin-legacy-jbrowse.cjs.production.min.js.map +1 -1
- package/dist/plugin-legacy-jbrowse.esm.js +336 -399
- package/dist/plugin-legacy-jbrowse.esm.js.map +1 -1
- package/package.json +5 -3
- package/src/JBrowse1Connection/configSchema.ts +4 -1
- package/src/JBrowse1Connection/jb1ConfigLoad.ts +24 -27
- package/src/JBrowse1Connection/jb1ConfigParse.ts +10 -12
- package/src/JBrowse1Connection/jb1ToJb2.ts +93 -43
- package/src/JBrowse1Connection/types.ts +2 -0
- package/src/JBrowse1TextSeachAdapter/HttpMap.test.ts +8 -20
- package/src/JBrowse1TextSeachAdapter/HttpMap.ts +17 -75
- package/src/JBrowse1TextSeachAdapter/JBrowse1TextSearchAdapter.test.ts +2 -4
- package/src/JBrowse1TextSeachAdapter/JBrowse1TextSearchAdapter.ts +42 -58
- package/src/JBrowse1TextSeachAdapter/configSchema.ts +2 -2
- package/src/NCListAdapter/NCListAdapter.test.ts +4 -1
- package/src/NCListAdapter/NCListAdapter.ts +15 -8
- package/src/NCListAdapter/configSchema.ts +4 -1
- package/src/__snapshots__/index.test.js.snap +3 -0
- package/src/index.test.js +1 -0
- package/src/index.ts +23 -0
- package/dist/JBrowse1TextSeachAdapter/Crc32.d.ts +0 -19
- package/src/JBrowse1TextSeachAdapter/Crc32.test.ts +0 -21
- package/src/JBrowse1TextSeachAdapter/Crc32.ts +0 -77
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-legacy-jbrowse",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"description": "JBrowse 2 plugin for connecting to and reading JBrowse 1 data",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -36,8 +36,10 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@gmod/nclist": "^0.1.1",
|
|
39
|
+
"buffer-crc32": "^0.2.13",
|
|
40
|
+
"generic-filehandle": "^2.2.2",
|
|
39
41
|
"get-value": "^3.0.1",
|
|
40
|
-
"set-value": "^
|
|
42
|
+
"set-value": "^4.0.1"
|
|
41
43
|
},
|
|
42
44
|
"peerDependencies": {
|
|
43
45
|
"@jbrowse/core": "^1.0.0",
|
|
@@ -47,5 +49,5 @@
|
|
|
47
49
|
"publishConfig": {
|
|
48
50
|
"access": "public"
|
|
49
51
|
},
|
|
50
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "94fdfbc34787ab8f12a87e00038da74b247b42fa"
|
|
51
53
|
}
|
|
@@ -6,7 +6,10 @@ export default ConfigurationSchema(
|
|
|
6
6
|
{
|
|
7
7
|
dataDirLocation: {
|
|
8
8
|
type: 'fileLocation',
|
|
9
|
-
defaultValue: {
|
|
9
|
+
defaultValue: {
|
|
10
|
+
uri: 'http://mysite.com/jbrowse/data/',
|
|
11
|
+
locationType: 'UriLocation',
|
|
12
|
+
},
|
|
10
13
|
description:
|
|
11
14
|
'the location of the JBrowse 1 data directory, often something like http://mysite.com/jbrowse/data/',
|
|
12
15
|
},
|
|
@@ -21,11 +21,11 @@ function isLocalPathLocation(
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export async function fetchJb1(
|
|
24
|
-
dataRoot: JBLocation = { uri: '' },
|
|
24
|
+
dataRoot: JBLocation = { uri: '', locationType: 'UriLocation' },
|
|
25
25
|
baseConfig: Config = {
|
|
26
26
|
include: ['{dataRoot}/trackList.json', '{dataRoot}/tracks.conf'],
|
|
27
27
|
},
|
|
28
|
-
baseConfigRoot: JBLocation = { uri: '' },
|
|
28
|
+
baseConfigRoot: JBLocation = { uri: '', locationType: 'UriLocation' },
|
|
29
29
|
): Promise<Config> {
|
|
30
30
|
const protocol = 'uri' in dataRoot ? 'uri' : 'localPath'
|
|
31
31
|
const dataRootReg = JSON.parse(JSON.stringify(dataRoot))
|
|
@@ -224,15 +224,14 @@ async function loadIncludes(inputConfig: Config): Promise<Config> {
|
|
|
224
224
|
)
|
|
225
225
|
delete config.include
|
|
226
226
|
|
|
227
|
-
const loads = includes.map(
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
)
|
|
227
|
+
const loads = includes.map(async (include): Promise<Config> => {
|
|
228
|
+
include.cacheBuster = inputConfig.cacheBuster
|
|
229
|
+
const includedData = await fetchConfigFile({
|
|
230
|
+
uri: new URL(include.url, sourceUrl).href,
|
|
231
|
+
locationType: 'UriLocation',
|
|
232
|
+
})
|
|
233
|
+
return loadRecur(includedData, newUpstreamConf)
|
|
234
|
+
})
|
|
236
235
|
const includedDataObjects = await Promise.all(loads)
|
|
237
236
|
includedDataObjects.forEach((includedData): void => {
|
|
238
237
|
config = mergeConfigs(config, includedData) || config
|
|
@@ -255,23 +254,21 @@ function regularizeIncludes(
|
|
|
255
254
|
includes = [includes]
|
|
256
255
|
}
|
|
257
256
|
|
|
258
|
-
return includes.map(
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
257
|
+
return includes.map((include): Include => {
|
|
258
|
+
// coerce bare strings in the includes to URLs
|
|
259
|
+
if (typeof include === 'string') {
|
|
260
|
+
include = { url: include }
|
|
261
|
+
}
|
|
264
262
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
)
|
|
263
|
+
// set defaults for format and version
|
|
264
|
+
if (!('format' in include)) {
|
|
265
|
+
include.format = include.url.endsWith('.conf') ? 'conf' : 'JB_json'
|
|
266
|
+
}
|
|
267
|
+
if (include.format === 'JB_json' && !('version' in include)) {
|
|
268
|
+
include.version = 1
|
|
269
|
+
}
|
|
270
|
+
return include
|
|
271
|
+
})
|
|
275
272
|
}
|
|
276
273
|
|
|
277
274
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -208,19 +208,17 @@ export function regularizeConf(conf: Config, url: string): Config {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
// coerce any string source defs to be URLs, and try to detect their types
|
|
211
|
-
meta.sources = meta.sources.map(
|
|
212
|
-
(sourceDef
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
newSourceDef.type = typeMatch[1].toLowerCase()
|
|
218
|
-
}
|
|
219
|
-
return newSourceDef
|
|
211
|
+
meta.sources = meta.sources.map((sourceDef: string | Source): Source => {
|
|
212
|
+
if (typeof sourceDef === 'string') {
|
|
213
|
+
const newSourceDef: Source = { url: sourceDef }
|
|
214
|
+
const typeMatch = sourceDef.match(/\.(\w+)$/)
|
|
215
|
+
if (typeMatch) {
|
|
216
|
+
newSourceDef.type = typeMatch[1].toLowerCase()
|
|
220
217
|
}
|
|
221
|
-
return
|
|
222
|
-
}
|
|
223
|
-
|
|
218
|
+
return newSourceDef
|
|
219
|
+
}
|
|
220
|
+
return sourceDef
|
|
221
|
+
})
|
|
224
222
|
}
|
|
225
223
|
|
|
226
224
|
conf.sourceUrl = conf.sourceUrl || url
|
|
@@ -51,6 +51,7 @@ interface Jb2Location {
|
|
|
51
51
|
uri?: string
|
|
52
52
|
localPath?: string
|
|
53
53
|
blobId?: string
|
|
54
|
+
locationType?: string
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
export function convertTrackConfig(
|
|
@@ -102,19 +103,27 @@ export function convertTrackConfig(
|
|
|
102
103
|
if (storeClass === 'JBrowse/Store/SeqFeature/BAM') {
|
|
103
104
|
const adapter: Jb2Adapter = {
|
|
104
105
|
type: 'BamAdapter',
|
|
105
|
-
bamLocation: { uri: urlTemplate },
|
|
106
|
+
bamLocation: { uri: urlTemplate, locationType: 'UriLocation' },
|
|
106
107
|
}
|
|
107
108
|
if (jb1TrackConfig.baiUrlTemplate) {
|
|
108
109
|
adapter.index = {
|
|
109
|
-
location: {
|
|
110
|
+
location: {
|
|
111
|
+
uri: resolveUrlTemplate(jb1TrackConfig.baiUrlTemplate),
|
|
112
|
+
locationType: 'UriLocation',
|
|
113
|
+
},
|
|
110
114
|
}
|
|
111
115
|
} else if (jb1TrackConfig.csiUrlTemplate) {
|
|
112
116
|
adapter.index = {
|
|
113
|
-
location: {
|
|
117
|
+
location: {
|
|
118
|
+
uri: resolveUrlTemplate(jb1TrackConfig.csiUrlTemplate),
|
|
119
|
+
locationType: 'UriLocation',
|
|
120
|
+
},
|
|
114
121
|
indexType: 'CSI',
|
|
115
122
|
}
|
|
116
123
|
} else {
|
|
117
|
-
adapter.index = {
|
|
124
|
+
adapter.index = {
|
|
125
|
+
location: { uri: `${urlTemplate}.bai`, locationType: 'UriLocation' },
|
|
126
|
+
}
|
|
118
127
|
}
|
|
119
128
|
return {
|
|
120
129
|
...jb2TrackConfig,
|
|
@@ -125,15 +134,19 @@ export function convertTrackConfig(
|
|
|
125
134
|
if (storeClass === 'JBrowse/Store/SeqFeature/CRAM') {
|
|
126
135
|
const adapter: Jb2Adapter = {
|
|
127
136
|
type: 'CramAdapter',
|
|
128
|
-
cramLocation: { uri: urlTemplate },
|
|
137
|
+
cramLocation: { uri: urlTemplate, locationType: 'UriLocation' },
|
|
129
138
|
sequenceAdapter,
|
|
130
139
|
}
|
|
131
140
|
if (jb1TrackConfig.craiUrlTemplate) {
|
|
132
141
|
adapter.craiLocation = {
|
|
133
142
|
uri: resolveUrlTemplate(jb1TrackConfig.craiUrlTemplate),
|
|
143
|
+
locationType: 'UriLocation',
|
|
134
144
|
}
|
|
135
145
|
} else {
|
|
136
|
-
adapter.craiLocation = {
|
|
146
|
+
adapter.craiLocation = {
|
|
147
|
+
uri: `${urlTemplate}.crai`,
|
|
148
|
+
locationType: 'UriLocation',
|
|
149
|
+
}
|
|
137
150
|
}
|
|
138
151
|
return {
|
|
139
152
|
...jb2TrackConfig,
|
|
@@ -147,7 +160,7 @@ export function convertTrackConfig(
|
|
|
147
160
|
type: 'FeatureTrack',
|
|
148
161
|
adapter: {
|
|
149
162
|
type: 'NCListAdapter',
|
|
150
|
-
rootUrlTemplate: { uri: urlTemplate },
|
|
163
|
+
rootUrlTemplate: { uri: urlTemplate, locationType: 'UriLocation' },
|
|
151
164
|
},
|
|
152
165
|
}
|
|
153
166
|
}
|
|
@@ -168,26 +181,34 @@ export function convertTrackConfig(
|
|
|
168
181
|
type: 'QuantitativeTrack',
|
|
169
182
|
adapter: {
|
|
170
183
|
type: 'BigWigAdapter',
|
|
171
|
-
bigWigLocation: { uri: urlTemplate },
|
|
184
|
+
bigWigLocation: { uri: urlTemplate, locationType: 'UriLocation' },
|
|
172
185
|
},
|
|
173
186
|
}
|
|
174
187
|
}
|
|
175
188
|
if (storeClass === 'JBrowse/Store/SeqFeature/VCFTabix') {
|
|
176
189
|
const adapter: Jb2Adapter = {
|
|
177
190
|
type: 'VcfTabixAdapter',
|
|
178
|
-
vcfGzLocation: { uri: urlTemplate },
|
|
191
|
+
vcfGzLocation: { uri: urlTemplate, locationType: 'UriLocation' },
|
|
179
192
|
}
|
|
180
193
|
if (jb1TrackConfig.tbiUrlTemplate) {
|
|
181
194
|
adapter.index = {
|
|
182
|
-
location: {
|
|
195
|
+
location: {
|
|
196
|
+
uri: resolveUrlTemplate(jb1TrackConfig.tbiUrlTemplate),
|
|
197
|
+
locationType: 'UriLocation',
|
|
198
|
+
},
|
|
183
199
|
}
|
|
184
200
|
} else if (jb1TrackConfig.csiUrlTemplate) {
|
|
185
201
|
adapter.index = {
|
|
186
|
-
location: {
|
|
202
|
+
location: {
|
|
203
|
+
uri: resolveUrlTemplate(jb1TrackConfig.csiUrlTemplate),
|
|
204
|
+
locationType: 'UriLocation',
|
|
205
|
+
},
|
|
187
206
|
indexType: 'CSI',
|
|
188
207
|
}
|
|
189
208
|
} else {
|
|
190
|
-
adapter.index = {
|
|
209
|
+
adapter.index = {
|
|
210
|
+
location: { uri: `${urlTemplate}.tbi`, locationType: 'UriLocation' },
|
|
211
|
+
}
|
|
191
212
|
}
|
|
192
213
|
return {
|
|
193
214
|
...jb2TrackConfig,
|
|
@@ -215,26 +236,34 @@ export function convertTrackConfig(
|
|
|
215
236
|
type: 'FeatureTrack',
|
|
216
237
|
adapter: {
|
|
217
238
|
type: 'BigBedAdapter',
|
|
218
|
-
bigBedLocation: { uri: urlTemplate },
|
|
239
|
+
bigBedLocation: { uri: urlTemplate, locationType: 'UriLocation' },
|
|
219
240
|
},
|
|
220
241
|
}
|
|
221
242
|
}
|
|
222
243
|
if (storeClass === 'JBrowse/Store/SeqFeature/GFF3Tabix') {
|
|
223
244
|
const adapter: Jb2Adapter = {
|
|
224
245
|
type: 'Gff3TabixAdapter',
|
|
225
|
-
gffGzLocation: { uri: urlTemplate },
|
|
246
|
+
gffGzLocation: { uri: urlTemplate, locationType: 'UriLocation' },
|
|
226
247
|
}
|
|
227
248
|
if (jb1TrackConfig.tbiUrlTemplate) {
|
|
228
249
|
adapter.index = {
|
|
229
|
-
location: {
|
|
250
|
+
location: {
|
|
251
|
+
uri: resolveUrlTemplate(jb1TrackConfig.tbiUrlTemplate),
|
|
252
|
+
locationType: 'UriLocation',
|
|
253
|
+
},
|
|
230
254
|
}
|
|
231
255
|
} else if (jb1TrackConfig.csiUrlTemplate) {
|
|
232
256
|
adapter.index = {
|
|
233
|
-
location: {
|
|
257
|
+
location: {
|
|
258
|
+
uri: resolveUrlTemplate(jb1TrackConfig.csiUrlTemplate),
|
|
259
|
+
locationType: 'UriLocation',
|
|
260
|
+
},
|
|
234
261
|
indexType: 'CSI',
|
|
235
262
|
}
|
|
236
263
|
} else {
|
|
237
|
-
adapter.index = {
|
|
264
|
+
adapter.index = {
|
|
265
|
+
location: { uri: `${urlTemplate}.tbi`, locationType: 'UriLocation' },
|
|
266
|
+
}
|
|
238
267
|
}
|
|
239
268
|
return {
|
|
240
269
|
...jb2TrackConfig,
|
|
@@ -252,19 +281,27 @@ export function convertTrackConfig(
|
|
|
252
281
|
if (storeClass === 'JBrowse/Store/SeqFeature/BEDTabix') {
|
|
253
282
|
const adapter: Jb2Adapter = {
|
|
254
283
|
type: 'BedTabixAdapter',
|
|
255
|
-
bedGzLocation: { uri: urlTemplate },
|
|
284
|
+
bedGzLocation: { uri: urlTemplate, locationType: 'UriLocation' },
|
|
256
285
|
}
|
|
257
286
|
if (jb1TrackConfig.tbiUrlTemplate) {
|
|
258
287
|
adapter.index = {
|
|
259
|
-
location: {
|
|
288
|
+
location: {
|
|
289
|
+
uri: resolveUrlTemplate(jb1TrackConfig.tbiUrlTemplate),
|
|
290
|
+
locationType: 'UriLocation',
|
|
291
|
+
},
|
|
260
292
|
}
|
|
261
293
|
} else if (jb1TrackConfig.csiUrlTemplate) {
|
|
262
294
|
adapter.index = {
|
|
263
|
-
location: {
|
|
295
|
+
location: {
|
|
296
|
+
uri: resolveUrlTemplate(jb1TrackConfig.csiUrlTemplate),
|
|
297
|
+
locationType: 'UriLocation',
|
|
298
|
+
},
|
|
264
299
|
indexType: 'CSI',
|
|
265
300
|
}
|
|
266
301
|
} else {
|
|
267
|
-
adapter.index = {
|
|
302
|
+
adapter.index = {
|
|
303
|
+
location: { uri: `${urlTemplate}.tbi`, locationType: 'UriLocation' },
|
|
304
|
+
}
|
|
268
305
|
}
|
|
269
306
|
return {
|
|
270
307
|
...jb2TrackConfig,
|
|
@@ -299,14 +336,18 @@ export function convertTrackConfig(
|
|
|
299
336
|
if (storeClass === 'JBrowse/Store/SeqFeature/IndexedFasta') {
|
|
300
337
|
const adapter: Jb2Adapter = {
|
|
301
338
|
type: 'IndexedFastaAdapter',
|
|
302
|
-
fastaLocation: { uri: urlTemplate },
|
|
339
|
+
fastaLocation: { uri: urlTemplate, locationType: 'UriLocation' },
|
|
303
340
|
}
|
|
304
341
|
if (jb1TrackConfig.faiUrlTemplate) {
|
|
305
342
|
adapter.faiLocation = {
|
|
306
343
|
uri: resolveUrlTemplate(jb1TrackConfig.faiUrlTemplate),
|
|
344
|
+
locationType: 'UriLocation',
|
|
307
345
|
}
|
|
308
346
|
} else {
|
|
309
|
-
adapter.faiLocation = {
|
|
347
|
+
adapter.faiLocation = {
|
|
348
|
+
uri: `${urlTemplate}.fai`,
|
|
349
|
+
locationType: 'UriLocation',
|
|
350
|
+
}
|
|
310
351
|
}
|
|
311
352
|
return {
|
|
312
353
|
...jb2TrackConfig,
|
|
@@ -317,21 +358,29 @@ export function convertTrackConfig(
|
|
|
317
358
|
if (storeClass === 'JBrowse/Store/SeqFeature/BgzipIndexedFasta') {
|
|
318
359
|
const adapter: Jb2Adapter = {
|
|
319
360
|
type: 'BgzipFastaAdapter',
|
|
320
|
-
fastaLocation: { uri: urlTemplate },
|
|
361
|
+
fastaLocation: { uri: urlTemplate, locationType: 'UriLocation' },
|
|
321
362
|
}
|
|
322
363
|
if (jb1TrackConfig.faiUrlTemplate) {
|
|
323
364
|
adapter.faiLocation = {
|
|
324
365
|
uri: resolveUrlTemplate(jb1TrackConfig.faiUrlTemplate),
|
|
366
|
+
locationType: 'UriLocation',
|
|
325
367
|
}
|
|
326
368
|
} else {
|
|
327
|
-
adapter.faiLocation = {
|
|
369
|
+
adapter.faiLocation = {
|
|
370
|
+
uri: `${urlTemplate}.fai`,
|
|
371
|
+
locationType: 'UriLocation',
|
|
372
|
+
}
|
|
328
373
|
}
|
|
329
374
|
if (jb1TrackConfig.gziUrlTemplate) {
|
|
330
375
|
adapter.gziLocation = {
|
|
331
376
|
uri: resolveUrlTemplate(jb1TrackConfig.gziUrlTemplate),
|
|
377
|
+
locationType: 'UriLocation',
|
|
332
378
|
}
|
|
333
379
|
} else {
|
|
334
|
-
adapter.gziLocation = {
|
|
380
|
+
adapter.gziLocation = {
|
|
381
|
+
uri: `${urlTemplate}.gzi`,
|
|
382
|
+
locationType: 'UriLocation',
|
|
383
|
+
}
|
|
335
384
|
}
|
|
336
385
|
return {
|
|
337
386
|
...jb2TrackConfig,
|
|
@@ -345,7 +394,7 @@ export function convertTrackConfig(
|
|
|
345
394
|
type: 'ReferenceSequenceTrack',
|
|
346
395
|
adapter: {
|
|
347
396
|
type: 'TwoBitAdapter',
|
|
348
|
-
twoBitLocation: { uri: urlTemplate },
|
|
397
|
+
twoBitLocation: { uri: urlTemplate, locationType: 'UriLocation' },
|
|
349
398
|
},
|
|
350
399
|
}
|
|
351
400
|
}
|
|
@@ -353,9 +402,9 @@ export function convertTrackConfig(
|
|
|
353
402
|
|
|
354
403
|
// If we don't recogize the store class, make a best effort to guess by file type
|
|
355
404
|
jb2TrackConfig.adapter = guessAdapter(
|
|
356
|
-
{ uri: urlTemplate },
|
|
405
|
+
{ uri: urlTemplate, locationType: 'UriLocation' },
|
|
357
406
|
undefined,
|
|
358
|
-
|
|
407
|
+
urlTemplate,
|
|
359
408
|
)
|
|
360
409
|
if (!jb2TrackConfig.adapter) {
|
|
361
410
|
throw new Error('Could not determine adapter')
|
|
@@ -394,16 +443,14 @@ function generateFromConfigTrackConfig(
|
|
|
394
443
|
jb2TrackConfig: Jb2Track,
|
|
395
444
|
): Jb2Track {
|
|
396
445
|
const jb1Features = jb1TrackConfig.features || []
|
|
397
|
-
const jb2Features = jb1Features.map(
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
},
|
|
406
|
-
)
|
|
446
|
+
const jb2Features = jb1Features.map((feature): Jb2Feature => {
|
|
447
|
+
const jb2Feature: Jb2Feature = JSON.parse(JSON.stringify(feature))
|
|
448
|
+
jb2Feature.refName = feature.seq_id
|
|
449
|
+
jb2Feature.uniqueId = `${feature.seq_id}:${feature.start}-${feature.end}:${
|
|
450
|
+
feature.name || ''
|
|
451
|
+
}`
|
|
452
|
+
return jb2Feature
|
|
453
|
+
})
|
|
407
454
|
jb2TrackConfig.adapter = {
|
|
408
455
|
type: 'FromConfigAdapter',
|
|
409
456
|
features: jb2Features,
|
|
@@ -429,16 +476,18 @@ export async function createRefSeqsAdapter(
|
|
|
429
476
|
type: 'IndexedFastaAdapter',
|
|
430
477
|
fastaLocation: {
|
|
431
478
|
uri: refSeqs.url.slice(0, -4),
|
|
479
|
+
locationType: 'UriLocation',
|
|
432
480
|
},
|
|
433
481
|
faiLocation: {
|
|
434
482
|
uri: refSeqs.url,
|
|
483
|
+
locationType: 'UriLocation',
|
|
435
484
|
},
|
|
436
485
|
}
|
|
437
486
|
}
|
|
438
487
|
if (refSeqs.url.match(/.2bit$/)) {
|
|
439
488
|
return {
|
|
440
489
|
type: 'TwoBitAdapter',
|
|
441
|
-
twoBitLocation: { uri: refSeqs.url },
|
|
490
|
+
twoBitLocation: { uri: refSeqs.url, locationType: 'UriLocation' },
|
|
442
491
|
}
|
|
443
492
|
}
|
|
444
493
|
if (refSeqs.url.match(/.fa$/)) {
|
|
@@ -447,9 +496,10 @@ export async function createRefSeqsAdapter(
|
|
|
447
496
|
if (refSeqs.url.match(/.sizes/)) {
|
|
448
497
|
throw new Error('chromosome SIZES adapter not available')
|
|
449
498
|
}
|
|
450
|
-
const refSeqsJson = await openLocation({
|
|
451
|
-
|
|
452
|
-
|
|
499
|
+
const refSeqsJson = await openLocation({
|
|
500
|
+
uri: refSeqs.url,
|
|
501
|
+
locationType: 'UriLocation',
|
|
502
|
+
}).readFile('utf8')
|
|
453
503
|
const refSeqsData: RefSeq[] = JSON.parse(refSeqsJson as string)
|
|
454
504
|
return refSeqAdapterFromConfig(refSeqsData)
|
|
455
505
|
}
|
|
@@ -94,10 +94,12 @@ export interface Config {
|
|
|
94
94
|
export interface UriLocation {
|
|
95
95
|
uri: string
|
|
96
96
|
baseUri?: string
|
|
97
|
+
locationType: 'UriLocation'
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
export interface LocalPathLocation {
|
|
100
101
|
localPath: string
|
|
102
|
+
locationType: 'LocalPathLocation'
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
export type JBLocation = UriLocation | LocalPathLocation
|
|
@@ -22,19 +22,13 @@ describe('test JBrowse1 hash implementation', () => {
|
|
|
22
22
|
spy.mockImplementation(mockFetch as any)
|
|
23
23
|
const hashMap = new HttpMap({
|
|
24
24
|
url: rootTemplate,
|
|
25
|
-
isElectron: false,
|
|
26
25
|
})
|
|
27
|
-
|
|
28
|
-
'Access-Control-Allow-Origin': '*',
|
|
29
|
-
'Content-Type': 'application/json',
|
|
30
|
-
}
|
|
26
|
+
|
|
31
27
|
await hashMap.getBucket('apple')
|
|
32
|
-
|
|
33
|
-
headers,
|
|
34
|
-
})
|
|
28
|
+
|
|
35
29
|
// test compress and hash hex characters are set after initial search
|
|
36
|
-
expect(hashMap.
|
|
37
|
-
expect(hashMap.
|
|
30
|
+
expect(await hashMap.getHashHexCharacters()).toBe(1)
|
|
31
|
+
expect(await hashMap.getCompress()).toBe(0)
|
|
38
32
|
})
|
|
39
33
|
test('get bucket contents', async () => {
|
|
40
34
|
function mockFetch(url: string): Promise<Response> {
|
|
@@ -59,18 +53,12 @@ describe('test JBrowse1 hash implementation', () => {
|
|
|
59
53
|
spy.mockImplementation(mockFetch as any)
|
|
60
54
|
const hashMap = new HttpMap({
|
|
61
55
|
url: rootTemplate,
|
|
62
|
-
isElectron: false,
|
|
63
56
|
})
|
|
64
|
-
|
|
65
|
-
'Access-Control-Allow-Origin': '*',
|
|
66
|
-
'Content-Type': 'application/json',
|
|
67
|
-
}
|
|
57
|
+
|
|
68
58
|
await hashMap.getBucket('apple')
|
|
69
|
-
expect(spy).
|
|
70
|
-
|
|
71
|
-
})
|
|
72
|
-
expect(spy).toHaveBeenLastCalledWith(`${rootTemplate}/0.json`, { headers })
|
|
59
|
+
expect(spy).toHaveBeenLastCalledWith(`${rootTemplate}/0.json`)
|
|
60
|
+
|
|
73
61
|
await hashMap.getBucket('apple3')
|
|
74
|
-
expect(spy).toHaveBeenLastCalledWith(`${rootTemplate}/f.json
|
|
62
|
+
expect(spy).toHaveBeenLastCalledWith(`${rootTemplate}/f.json`)
|
|
75
63
|
})
|
|
76
64
|
})
|
|
@@ -1,75 +1,38 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
1
|
/*
|
|
3
2
|
* Helper class allows reading names index generated in JBrowse1
|
|
4
3
|
* Adapted from https://github.com/GMOD/jbrowse/blob/master/src/JBrowse/Store/Hash.js
|
|
5
4
|
*/
|
|
6
|
-
import
|
|
5
|
+
import crc32 from 'buffer-crc32'
|
|
7
6
|
|
|
8
7
|
export default class HttpMap {
|
|
9
8
|
url: string
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
hash_hex_characters?: number
|
|
14
|
-
|
|
15
|
-
compress?: number
|
|
16
|
-
|
|
17
|
-
tracks?: string[]
|
|
18
|
-
|
|
19
|
-
constructor(args: { url: string; isElectron: boolean }) {
|
|
10
|
+
constructor(args: { url: string }) {
|
|
20
11
|
// make sure url has a trailing slash
|
|
21
12
|
this.url = /\/$/.test(args.url) ? args.url : `${args.url}/`
|
|
22
|
-
|
|
23
|
-
this.isElectron = args.isElectron
|
|
24
13
|
}
|
|
25
14
|
|
|
26
15
|
/**
|
|
27
16
|
* loads meta.json file from names directory and reads number of hash_bits used
|
|
28
17
|
*/
|
|
29
18
|
async readMeta() {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
this.compress = compress
|
|
35
|
-
const hashHexCharacters = Math.ceil(meta.hash_bits / 4)
|
|
36
|
-
this.hash_hex_characters = hashHexCharacters
|
|
37
|
-
this.tracks = tracks
|
|
38
|
-
return { hashHexCharacters, compress, tracks }
|
|
39
|
-
}
|
|
40
|
-
throw new Error('Error parsing meta.json')
|
|
41
|
-
|
|
42
|
-
// const { compress } = meta
|
|
43
|
-
// this.compress = compress
|
|
44
|
-
// const hashHexCharacters = Math.ceil(meta.hash_bits / 4)
|
|
45
|
-
// this.hash_hex_characters = hashHexCharacters
|
|
46
|
-
} catch (err) {
|
|
47
|
-
// throw Error(err)
|
|
48
|
-
console.warn(`Error: ${err}`)
|
|
49
|
-
}
|
|
50
|
-
return {}
|
|
19
|
+
const meta = await this.loadFile('meta.json')
|
|
20
|
+
const { compress, track_names: tracks } = meta
|
|
21
|
+
const hashHexCharacters = Math.ceil(meta.hash_bits / 4)
|
|
22
|
+
return { hashHexCharacters, compress, tracks }
|
|
51
23
|
}
|
|
52
24
|
|
|
53
25
|
async getHashHexCharacters() {
|
|
54
|
-
if (this.hash_hex_characters) {
|
|
55
|
-
return this.hash_hex_characters
|
|
56
|
-
}
|
|
57
26
|
const meta = await this.readMeta()
|
|
58
27
|
return meta.hashHexCharacters
|
|
59
28
|
}
|
|
60
29
|
|
|
61
30
|
async getCompress() {
|
|
62
|
-
if (this.compress) {
|
|
63
|
-
return this.compress
|
|
64
|
-
}
|
|
65
31
|
const meta = await this.readMeta()
|
|
66
32
|
return meta.compress
|
|
67
33
|
}
|
|
68
34
|
|
|
69
35
|
async getTrackNames() {
|
|
70
|
-
if (this.tracks) {
|
|
71
|
-
return this.tracks
|
|
72
|
-
}
|
|
73
36
|
const meta = await this.readMeta()
|
|
74
37
|
return meta.tracks
|
|
75
38
|
}
|
|
@@ -79,7 +42,7 @@ export default class HttpMap {
|
|
|
79
42
|
* @param key - string
|
|
80
43
|
*/
|
|
81
44
|
async get(key: string) {
|
|
82
|
-
const bucket
|
|
45
|
+
const bucket = await this.getBucket(key)
|
|
83
46
|
return bucket[key]
|
|
84
47
|
}
|
|
85
48
|
|
|
@@ -89,17 +52,8 @@ export default class HttpMap {
|
|
|
89
52
|
*/
|
|
90
53
|
async getBucket(key: string) {
|
|
91
54
|
const bucketIdent = this.hash(key)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const value = await this.loadFile(hexToDirPath)
|
|
95
|
-
return value
|
|
96
|
-
} catch (err) {
|
|
97
|
-
if (this.isElectron || err.status === 404) {
|
|
98
|
-
// 404 is expected if the name is not in the store
|
|
99
|
-
return {}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return {}
|
|
55
|
+
const hexToDirPath = await this.hexToDirPath(bucketIdent)
|
|
56
|
+
return this.loadFile(hexToDirPath)
|
|
103
57
|
}
|
|
104
58
|
|
|
105
59
|
/**
|
|
@@ -108,21 +62,11 @@ export default class HttpMap {
|
|
|
108
62
|
* @param id - string
|
|
109
63
|
*/
|
|
110
64
|
async loadFile(id: string) {
|
|
111
|
-
const response = await fetch(`${this.url}${id}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
'Access-Control-Allow-Origin': '*',
|
|
115
|
-
},
|
|
116
|
-
})
|
|
117
|
-
try {
|
|
118
|
-
const data = await response.json()
|
|
119
|
-
return data
|
|
120
|
-
} catch (err) {
|
|
121
|
-
// handle error
|
|
122
|
-
// throw Error(err)
|
|
123
|
-
console.warn(`Error: ${err}`)
|
|
65
|
+
const response = await fetch(`${this.url}${id}`)
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
throw new Error(`HTTP ${response.status} ${response.statusText}`)
|
|
124
68
|
}
|
|
125
|
-
return
|
|
69
|
+
return response.json()
|
|
126
70
|
}
|
|
127
71
|
|
|
128
72
|
/**
|
|
@@ -147,12 +91,10 @@ export default class HttpMap {
|
|
|
147
91
|
return ''
|
|
148
92
|
}
|
|
149
93
|
|
|
150
|
-
/**
|
|
151
|
-
* Returns crc32 hash given a string.
|
|
152
|
-
* (Note: this is using JBrowse1 implementation of crc32.)
|
|
153
|
-
* @param data - string
|
|
154
|
-
*/
|
|
155
94
|
hash(data: string) {
|
|
156
|
-
return crc32(
|
|
95
|
+
return crc32(Buffer.from(data))
|
|
96
|
+
.toString('hex')
|
|
97
|
+
.toLowerCase()
|
|
98
|
+
.replace('-', 'n')
|
|
157
99
|
}
|
|
158
100
|
}
|