@jbrowse/cli 2.4.0 → 2.4.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.
@@ -10,12 +10,29 @@ const json_parse_better_errors_1 = __importDefault(require("json-parse-better-er
10
10
  const base_1 = __importDefault(require("../base"));
11
11
  const { copyFile, rename, symlink } = fs_1.default.promises;
12
12
  const { COPYFILE_EXCL } = fs_1.default.constants;
13
+ function makeLocationProtocol(protocol) {
14
+ return (location) => {
15
+ if (protocol === 'uri') {
16
+ return {
17
+ uri: location,
18
+ locationType: 'UriLocation',
19
+ };
20
+ }
21
+ if (protocol === 'localPath') {
22
+ return {
23
+ localPath: location,
24
+ locationType: 'LocalPathLocation',
25
+ };
26
+ }
27
+ throw new Error(`invalid protocol ${protocol}`);
28
+ };
29
+ }
13
30
  const isUrl = (loc) => loc === null || loc === void 0 ? void 0 : loc.match(/^https?:\/\//);
14
31
  class AddTrack extends base_1.default {
15
32
  async run() {
16
33
  const { args: runArgs, flags: runFlags } = this.parse(AddTrack);
17
34
  const { track: argsTrack } = runArgs;
18
- const { config, skipCheck, force, overwrite, category, description, load, subDir, target, protocol, out, indexFile: index, } = runFlags;
35
+ const { config, skipCheck, force, overwrite, category, description, load, subDir, target, protocol, out, indexFile: index, bed1, bed2, } = runFlags;
19
36
  const output = target || out || '.';
20
37
  const isDir = fs_1.default.lstatSync(output).isDirectory();
21
38
  this.target = isDir ? `${output}/config.json` : output;
@@ -31,19 +48,27 @@ class AddTrack extends base_1.default {
31
48
  }
32
49
  }
33
50
  const location = argsTrack;
34
- const inPlace = load === 'inPlace';
35
- const useIndex = isUrl(index) || inPlace || index;
36
- const effectiveLocation = isUrl(location) || inPlace
37
- ? location
38
- : path_1.default.join(subDir, path_1.default.basename(location));
39
- const effectiveIndexLocation = !index || isUrl(index) || inPlace
40
- ? index
41
- : path_1.default.join(subDir, path_1.default.basename(index));
42
- const adapter = useIndex
43
- ? this.guessAdapter(effectiveLocation, protocol, effectiveIndexLocation)
44
- : this.guessAdapter(effectiveLocation, protocol);
45
- if (adapter.type === 'PAFAdapter') {
46
- // @ts-ignore
51
+ const mapLoc = (p) => {
52
+ return !p || isUrl(p) || load === 'inPlace'
53
+ ? p
54
+ : path_1.default.join(subDir, path_1.default.basename(p));
55
+ };
56
+ const adapter = this.guessAdapter({
57
+ protocol,
58
+ location: mapLoc(location),
59
+ index: index ? mapLoc(index) : undefined,
60
+ bed1: bed1 ? mapLoc(bed1) : undefined,
61
+ bed2: bed2 ? mapLoc(bed2) : undefined,
62
+ });
63
+ if ([
64
+ 'PAFAdapter',
65
+ 'DeltaAdapter',
66
+ 'ChainAdapter',
67
+ 'MashMapAdapter',
68
+ 'MCScanAnchorsAdapter',
69
+ 'MCScanSimpleAnchorsAdapter',
70
+ ].includes(adapter.type)) {
71
+ // @ts-expect-error
47
72
  adapter.assemblyNames = assemblyNames.split(',').map(a => a.trim());
48
73
  }
49
74
  if (isUrl(location) && load) {
@@ -75,26 +100,18 @@ class AddTrack extends base_1.default {
75
100
  trackId = trackId || path_1.default.basename(location, path_1.default.extname(location));
76
101
  name = name || trackId;
77
102
  assemblyNames = assemblyNames || configContents.assemblies[0].name;
78
- this.debug(`Name is: ${name}`);
79
- this.debug(`Type is: ${trackType}`);
80
- this.debug(`Track is :${trackId}`);
81
- this.debug(`Assembly name(s) is :${assemblyNames}`);
82
103
  const configObj = config ? (0, json_parse_better_errors_1.default)(config) : {};
83
104
  const trackConfig = Object.assign({ type: trackType, trackId,
84
105
  name,
85
106
  adapter, category: category === null || category === void 0 ? void 0 : category.split(',').map(c => c.trim()), assemblyNames: assemblyNames.split(',').map(a => a.trim()), description }, configObj);
86
- this.debug(`Track location: ${location}, index: ${adapter ? adapter.index : ''}`);
87
107
  // any special track modifications go here
88
- switch (trackType) {
89
- case 'AlignmentsTrack': {
90
- const assembly = configContents.assemblies.find(asm => asm.name === assemblyNames);
91
- if (assembly) {
92
- trackConfig.adapter.sequenceAdapter = assembly.sequence.adapter;
93
- }
94
- else if (!skipCheck) {
95
- this.error(`Failed to find assemblyName ${assemblyNames}`);
96
- }
97
- break;
108
+ if (trackType === 'AlignmentsTrack') {
109
+ const assembly = configContents.assemblies.find(asm => asm.name === assemblyNames);
110
+ if (assembly) {
111
+ trackConfig.adapter.sequenceAdapter = assembly.sequence.adapter;
112
+ }
113
+ else if (!skipCheck) {
114
+ this.error(`Failed to find assemblyName ${assemblyNames}`);
98
115
  }
99
116
  }
100
117
  if (!configContents.tracks) {
@@ -139,276 +156,252 @@ class AddTrack extends base_1.default {
139
156
  /* do nothing */
140
157
  },
141
158
  };
142
- await Promise.all(Object.values(this.guessFileNames(location, index))
159
+ await Promise.all(Object.values(this.guessFileNames({ location, index, bed1, bed2 }))
143
160
  .filter(f => !!f)
144
161
  .map(src => callbacks[loadType](src, destinationFn(configDirectory, src))));
145
162
  this.debug(`Writing configuration to file ${this.target}`);
146
163
  await this.writeJsonFile(this.target, configContents);
147
164
  this.log(`${idx !== -1 ? 'Overwrote' : 'Added'} track with name "${name}" and trackId "${trackId}" ${idx !== -1 ? 'in' : 'to'} ${this.target}`);
148
165
  }
149
- guessFileNames(fileName, index) {
150
- if (/\.bam$/i.test(fileName)) {
151
- return {
152
- file: fileName,
153
- index: index || `${fileName}.bai`,
154
- };
155
- }
156
- if (/\.cram$/i.test(fileName)) {
166
+ guessFileNames({ location, index, bed1, bed2, }) {
167
+ if (/\.anchors(.simple)?$/i.test(location)) {
157
168
  return {
158
- file: fileName,
159
- index: index || `${fileName}.crai`,
169
+ file: location,
170
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
171
+ bed1: bed1,
172
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
173
+ bed2: bed2,
160
174
  };
161
175
  }
162
- if (/\.gff3?$/i.test(fileName)) {
176
+ if (/\.bam$/i.test(location)) {
163
177
  return {
164
- file: fileName,
178
+ file: location,
179
+ index: index || `${location}.bai`,
165
180
  };
166
181
  }
167
- if (/\.gff3?\.b?gz$/i.test(fileName)) {
182
+ if (/\.cram$/i.test(location)) {
168
183
  return {
169
- file: fileName,
170
- index: index || `${fileName}.tbi`,
184
+ file: location,
185
+ index: index || `${location}.crai`,
171
186
  };
172
187
  }
173
- if (/\.gtf?$/i.test(fileName)) {
188
+ if (/\.gff3?\.b?gz$/i.test(location) ||
189
+ /\.vcf\.b?gz$/i.test(location) ||
190
+ /\.bed\.b?gz$/i.test(location)) {
174
191
  return {
175
- file: fileName,
192
+ file: location,
193
+ index: index || `${location}.tbi`,
176
194
  };
177
195
  }
178
- if (/\.vcf$/i.test(fileName)) {
196
+ if (/\.(fa|fasta|fas|fna|mfa)$/i.test(location)) {
179
197
  return {
180
- file: fileName,
198
+ file: location,
199
+ index: index || `${location}.fai`,
181
200
  };
182
201
  }
183
- if (/\.vcf\.b?gz$/i.test(fileName)) {
202
+ if (/\.(fa|fasta|fas|fna|mfa)\.b?gz$/i.test(location)) {
184
203
  return {
185
- file: fileName,
186
- index: index || `${fileName}.tbi`,
204
+ file: location,
205
+ index: `${location}.fai`,
206
+ index2: `${location}.gzi`,
187
207
  };
188
208
  }
189
- if (/\.vcf\.idx$/i.test(fileName)) {
190
- return {};
191
- }
192
- if (/\.bed$/i.test(fileName)) {
193
- return {};
194
- }
195
- if (/\.bed\.b?gz$/i.test(fileName)) {
209
+ if (/\.2bit$/i.test(location) ||
210
+ /\/trackData.jsonz?$/i.test(location) ||
211
+ /\/sparql$/i.test(location) ||
212
+ /\.out(.gz)?$/i.test(location) ||
213
+ /\.paf(.gz)?$/i.test(location) ||
214
+ /\.delta(.gz)?$/i.test(location) ||
215
+ /\.(bw|bigwig)$/i.test(location) ||
216
+ /\.(bb|bigbed)$/i.test(location) ||
217
+ /\.vcf$/i.test(location) ||
218
+ /\.gtf?$/i.test(location) ||
219
+ /\.gff3?$/i.test(location) ||
220
+ /\.chain(.gz)?$/i.test(location)) {
196
221
  return {
197
- file: fileName,
198
- index: index || `${fileName}.tbi`,
199
- };
200
- }
201
- if (/\.bed\.idx$/i.test(fileName)) {
202
- return {};
203
- }
204
- if (/\.(bb|bigbed)$/i.test(fileName)) {
205
- return {
206
- file: fileName,
207
- };
208
- }
209
- if (/\.(bw|bigwig)$/i.test(fileName)) {
210
- return {
211
- file: fileName,
212
- };
213
- }
214
- if (/\.(fa|fasta|fas|fna|mfa)$/i.test(fileName)) {
215
- return {
216
- file: fileName,
217
- index: index || `${fileName}.fai`,
218
- };
219
- }
220
- if (/\.(fa|fasta|fas|fna|mfa)\.b?gz$/i.test(fileName)) {
221
- return {
222
- file: fileName,
223
- index: `${fileName}.fai`,
224
- index2: `${fileName}.gzi`,
225
- };
226
- }
227
- if (/\.2bit$/i.test(fileName)) {
228
- return {
229
- file: fileName,
230
- };
231
- }
232
- if (/\.sizes$/i.test(fileName)) {
233
- return {};
234
- }
235
- if (/\/trackData.jsonz?$/i.test(fileName)) {
236
- return {
237
- file: fileName,
238
- };
239
- }
240
- if (/\/sparql$/i.test(fileName)) {
241
- return {
242
- file: fileName,
243
- };
244
- }
245
- if (/\.hic$/i.test(fileName)) {
246
- return {
247
- file: fileName,
248
- };
249
- }
250
- if (/\.paf$/i.test(fileName)) {
251
- return {
252
- file: fileName,
222
+ file: location,
253
223
  };
254
224
  }
255
225
  return {};
256
226
  }
257
227
  // find way to import this instead of having to paste it
258
- guessAdapter(fileName, protocol, index) {
259
- function makeLocation(location) {
260
- if (protocol === 'uri') {
261
- return { uri: location, locationType: 'UriLocation' };
262
- }
263
- if (protocol === 'localPath') {
264
- return {
265
- localPath: location,
266
- locationType: 'LocalPathLocation',
267
- };
268
- }
269
- throw new Error(`invalid protocol ${protocol}`);
270
- }
271
- if (/\.bam$/i.test(fileName)) {
228
+ guessAdapter({ location, protocol, index, bed1, bed2, }) {
229
+ const makeLocation = makeLocationProtocol(protocol);
230
+ if (/\.bam$/i.test(location)) {
272
231
  return {
273
232
  type: 'BamAdapter',
274
- bamLocation: makeLocation(fileName),
233
+ bamLocation: makeLocation(location),
275
234
  index: {
276
- location: makeLocation(index || `${fileName}.bai`),
277
- indexType: index && index.toUpperCase().endsWith('CSI') ? 'CSI' : 'BAI',
235
+ location: makeLocation(index || `${location}.bai`),
236
+ indexType: (index === null || index === void 0 ? void 0 : index.toUpperCase().endsWith('CSI')) ? 'CSI' : 'BAI',
278
237
  },
279
238
  };
280
239
  }
281
- if (/\.cram$/i.test(fileName)) {
240
+ if (/\.cram$/i.test(location)) {
282
241
  return {
283
242
  type: 'CramAdapter',
284
- cramLocation: makeLocation(fileName),
285
- craiLocation: makeLocation(`${fileName}.crai`),
243
+ cramLocation: makeLocation(location),
244
+ craiLocation: makeLocation(`${location}.crai`),
286
245
  };
287
246
  }
288
- if (/\.gff3?$/i.test(fileName)) {
247
+ if (/\.gff3?$/i.test(location)) {
289
248
  return {
290
249
  type: 'Gff3Adapter',
291
- gffLocation: makeLocation(fileName),
250
+ gffLocation: makeLocation(location),
292
251
  };
293
252
  }
294
- if (/\.gff3?\.b?gz$/i.test(fileName)) {
253
+ if (/\.gff3?\.b?gz$/i.test(location)) {
295
254
  return {
296
255
  type: 'Gff3TabixAdapter',
297
- gffGzLocation: makeLocation(fileName),
256
+ gffGzLocation: makeLocation(location),
298
257
  index: {
299
- location: makeLocation(index || `${fileName}.tbi`),
300
- indexType: index && index.toUpperCase().endsWith('CSI') ? 'CSI' : 'TBI',
258
+ location: makeLocation(index || `${location}.tbi`),
259
+ indexType: (index === null || index === void 0 ? void 0 : index.toUpperCase().endsWith('CSI')) ? 'CSI' : 'TBI',
301
260
  },
302
261
  };
303
262
  }
304
- if (/\.gtf?$/i.test(fileName)) {
263
+ if (/\.gtf?$/i.test(location)) {
305
264
  return {
306
265
  type: 'GtfAdapter',
307
- gtfLocation: makeLocation(fileName),
266
+ gtfLocation: makeLocation(location),
308
267
  };
309
268
  }
310
- if (/\.vcf$/i.test(fileName)) {
269
+ if (/\.vcf$/i.test(location)) {
311
270
  return {
312
271
  type: 'VcfAdapter',
313
- vcfLocation: makeLocation(fileName),
272
+ vcfLocation: makeLocation(location),
314
273
  };
315
274
  }
316
- if (/\.vcf\.b?gz$/i.test(fileName)) {
275
+ if (/\.vcf\.b?gz$/i.test(location)) {
317
276
  return {
318
277
  type: 'VcfTabixAdapter',
319
- vcfGzLocation: makeLocation(fileName),
278
+ vcfGzLocation: makeLocation(location),
320
279
  index: {
321
- location: makeLocation(index || `${fileName}.tbi`),
322
- indexType: index && index.toUpperCase().endsWith('CSI') ? 'CSI' : 'TBI',
280
+ location: makeLocation(index || `${location}.tbi`),
281
+ indexType: (index === null || index === void 0 ? void 0 : index.toUpperCase().endsWith('CSI')) ? 'CSI' : 'TBI',
323
282
  },
324
283
  };
325
284
  }
326
- if (/\.vcf\.idx$/i.test(fileName)) {
285
+ if (/\.vcf\.idx$/i.test(location)) {
327
286
  return {
328
287
  type: 'UNSUPPORTED',
329
288
  };
330
289
  }
331
- if (/\.bed$/i.test(fileName)) {
290
+ if (/\.bed$/i.test(location)) {
332
291
  return {
333
292
  type: 'UNSUPPORTED',
334
293
  };
335
294
  }
336
- if (/\.bed\.b?gz$/i.test(fileName)) {
295
+ if (/\.bed\.b?gz$/i.test(location)) {
337
296
  return {
338
297
  type: 'BedTabixAdapter',
339
- bedGzLocation: makeLocation(fileName),
298
+ bedGzLocation: makeLocation(location),
340
299
  index: {
341
- location: makeLocation(index || `${fileName}.tbi`),
342
- indexType: index && index.toUpperCase().endsWith('CSI') ? 'CSI' : 'TBI',
300
+ location: makeLocation(index || `${location}.tbi`),
301
+ indexType: (index === null || index === void 0 ? void 0 : index.toUpperCase().endsWith('CSI')) ? 'CSI' : 'TBI',
343
302
  },
344
303
  };
345
304
  }
346
- if (/\.bed$/i.test(fileName)) {
305
+ if (/\.bed$/i.test(location)) {
347
306
  return {
348
307
  type: 'BedAdapter',
349
- bedLocation: makeLocation(fileName),
308
+ bedLocation: makeLocation(location),
350
309
  };
351
310
  }
352
- if (/\.(bb|bigbed)$/i.test(fileName)) {
311
+ if (/\.(bb|bigbed)$/i.test(location)) {
353
312
  return {
354
313
  type: 'BigBedAdapter',
355
- bigBedLocation: makeLocation(fileName),
314
+ bigBedLocation: makeLocation(location),
356
315
  };
357
316
  }
358
- if (/\.(bw|bigwig)$/i.test(fileName)) {
317
+ if (/\.(bw|bigwig)$/i.test(location)) {
359
318
  return {
360
319
  type: 'BigWigAdapter',
361
- bigWigLocation: makeLocation(fileName),
320
+ bigWigLocation: makeLocation(location),
362
321
  };
363
322
  }
364
- if (/\.(fa|fasta|fna|mfa)$/i.test(fileName)) {
323
+ if (/\.(fa|fasta|fna|mfa)$/i.test(location)) {
365
324
  return {
366
325
  type: 'IndexedFastaAdapter',
367
- fastaLocation: makeLocation(fileName),
368
- faiLocation: makeLocation(index || `${fileName}.fai`),
326
+ fastaLocation: makeLocation(location),
327
+ faiLocation: makeLocation(index || `${location}.fai`),
369
328
  };
370
329
  }
371
- if (/\.(fa|fasta|fna|mfa)\.b?gz$/i.test(fileName)) {
330
+ if (/\.(fa|fasta|fna|mfa)\.b?gz$/i.test(location)) {
372
331
  return {
373
332
  type: 'BgzipFastaAdapter',
374
- fastaLocation: makeLocation(fileName),
375
- faiLocation: makeLocation(`${fileName}.fai`),
376
- gziLocation: makeLocation(`${fileName}.gzi`),
333
+ fastaLocation: makeLocation(location),
334
+ faiLocation: makeLocation(`${location}.fai`),
335
+ gziLocation: makeLocation(`${location}.gzi`),
377
336
  };
378
337
  }
379
- if (/\.2bit$/i.test(fileName)) {
338
+ if (/\.2bit$/i.test(location)) {
380
339
  return {
381
340
  type: 'TwoBitAdapter',
382
- twoBitLocation: makeLocation(fileName),
341
+ twoBitLocation: makeLocation(location),
383
342
  };
384
343
  }
385
- if (/\.sizes$/i.test(fileName)) {
344
+ if (/\.sizes$/i.test(location)) {
386
345
  return {
387
346
  type: 'UNSUPPORTED',
388
347
  };
389
348
  }
390
- if (/\/trackData.jsonz?$/i.test(fileName)) {
349
+ if (/\/trackData.jsonz?$/i.test(location)) {
391
350
  return {
392
351
  type: 'NCListAdapter',
393
- rootUrlTemplate: makeLocation(fileName),
352
+ rootUrlTemplate: makeLocation(location),
394
353
  };
395
354
  }
396
- if (/\/sparql$/i.test(fileName)) {
355
+ if (/\/sparql$/i.test(location)) {
397
356
  return {
398
357
  type: 'SPARQLAdapter',
399
- endpoint: fileName,
358
+ endpoint: location,
400
359
  };
401
360
  }
402
- if (/\.hic/i.test(fileName)) {
361
+ if (/\.hic$/i.test(location)) {
403
362
  return {
404
363
  type: 'HicAdapter',
405
- hicLocation: makeLocation(fileName),
364
+ hicLocation: makeLocation(location),
406
365
  };
407
366
  }
408
- if (/\.paf/i.test(fileName)) {
367
+ if (/\.paf(.gz)?$/i.test(location)) {
409
368
  return {
410
369
  type: 'PAFAdapter',
411
- pafLocation: makeLocation(fileName),
370
+ pafLocation: makeLocation(location),
371
+ };
372
+ }
373
+ if (/\.out(.gz)?$/i.test(location)) {
374
+ return {
375
+ type: 'MashMapAdapter',
376
+ outLocation: makeLocation(location),
377
+ };
378
+ }
379
+ if (/\.chain(.gz)?$/i.test(location)) {
380
+ return {
381
+ type: 'ChainAdapter',
382
+ chainLocation: makeLocation(location),
383
+ };
384
+ }
385
+ if (/\.delta(.gz)?$/i.test(location)) {
386
+ return {
387
+ type: 'DeltaAdapter',
388
+ deltaLocation: makeLocation(location),
389
+ };
390
+ }
391
+ if (/\.anchors(.gz)?$/i.test(location)) {
392
+ return {
393
+ type: 'MCScanAnchorsAdapter',
394
+ mcscanAnchorsLocation: makeLocation(location),
395
+ bed1Location: bed1 ? makeLocation(bed1) : undefined,
396
+ bed2Location: bed2 ? makeLocation(bed2) : undefined,
397
+ };
398
+ }
399
+ if (/\.anchors.simple(.gz)?$/i.test(location)) {
400
+ return {
401
+ type: 'MCScanSimpleAnchorsAdapter',
402
+ mcscanSimpleAnchorsLocation: makeLocation(location),
403
+ bed1Location: bed1 ? makeLocation(bed1) : undefined,
404
+ bed2Location: bed2 ? makeLocation(bed2) : undefined,
412
405
  };
413
406
  }
414
407
  return {
@@ -427,6 +420,11 @@ class AddTrack extends base_1.default {
427
420
  VcfAdapter: 'VariantTrack',
428
421
  HicAdapter: 'HicTrack',
429
422
  PAFAdapter: 'SyntenyTrack',
423
+ DeltaAdapter: 'SyntenyTrack',
424
+ ChainAdapter: 'SyntenyTrack',
425
+ MashMapAdapter: 'SyntenyTrack',
426
+ MCScanAnchorsAdapter: 'SyntenyTrack',
427
+ MCScanSimpleAnchorsAdapter: 'SyntenyTrack',
430
428
  };
431
429
  return known[adapterType] || 'FeatureTrack';
432
430
  }
@@ -518,4 +516,10 @@ AddTrack.flags = {
518
516
  description: 'Force protocol to a specific value',
519
517
  default: 'uri',
520
518
  }),
519
+ bed1: command_1.flags.string({
520
+ description: 'Used only for mcscan anchors/simpleAnchors types',
521
+ }),
522
+ bed2: command_1.flags.string({
523
+ description: 'Used only for mcscan anchors/simpleAnchors types',
524
+ }),
521
525
  };
@@ -50,7 +50,7 @@ class Create extends base_1.default {
50
50
  }
51
51
  }
52
52
  async catch(error) {
53
- // @ts-ignore
53
+ // @ts-expect-error
54
54
  if (error.parse && error.parse.output.flags.listVersions) {
55
55
  const versions = (await this.fetchGithubVersions()).map(version => version.tag_name);
56
56
  this.log(`All JBrowse versions:\n${versions.join('\n')}`);
@@ -75,7 +75,7 @@ function indexVcf({ config, attributesToIndex, inLocation, outLocation, quiet, }
75
75
  val ? decodeURIComponent(val).trim().split(',').join(' ') : undefined,
76
76
  ]));
77
77
  const end = fields.END;
78
- const locStr = `${ref}:${pos}..${end ? end : +pos + 1}`;
78
+ const locStr = `${ref}:${pos}..${end || +pos + 1}`;
79
79
  if (id === '.') {
80
80
  continue;
81
81
  }