@jbrowse/cli 2.13.1 → 2.15.0
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/README.md +13 -13
- package/lib/base.js +9 -9
- package/lib/commands/add-assembly.js +7 -3
- package/lib/commands/add-connection.js +11 -18
- package/lib/commands/add-track-json.js +3 -3
- package/lib/commands/add-track.js +26 -25
- package/lib/commands/admin-server.js +2 -2
- package/lib/commands/create.js +1 -1
- package/lib/commands/make-pif.js +4 -4
- package/lib/commands/remove-track.js +1 -1
- package/lib/commands/set-default-session.js +2 -2
- package/lib/commands/sort-gff.js +1 -1
- package/lib/commands/text-index.js +21 -17
- package/lib/commands/upgrade.js +6 -5
- package/lib/types/common.js +5 -6
- package/lib/types/gff3Adapter.js +5 -3
- package/lib/types/vcfAdapter.js +2 -2
- package/lib/util.js +8 -7
- package/oclif.manifest.json +1 -1
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -205,7 +205,7 @@ EXAMPLES
|
|
|
205
205
|
```
|
|
206
206
|
|
|
207
207
|
_See code:
|
|
208
|
-
[src/commands/add-assembly.ts](https://github.com/GMOD/jbrowse-components/blob/v2.
|
|
208
|
+
[src/commands/add-assembly.ts](https://github.com/GMOD/jbrowse-components/blob/v2.15.0/products/jbrowse-cli/src/commands/add-assembly.ts)_
|
|
209
209
|
|
|
210
210
|
## `jbrowse add-connection CONNECTIONURLORPATH`
|
|
211
211
|
|
|
@@ -256,7 +256,7 @@ EXAMPLES
|
|
|
256
256
|
```
|
|
257
257
|
|
|
258
258
|
_See code:
|
|
259
|
-
[src/commands/add-connection.ts](https://github.com/GMOD/jbrowse-components/blob/v2.
|
|
259
|
+
[src/commands/add-connection.ts](https://github.com/GMOD/jbrowse-components/blob/v2.15.0/products/jbrowse-cli/src/commands/add-connection.ts)_
|
|
260
260
|
|
|
261
261
|
## `jbrowse add-track TRACK`
|
|
262
262
|
|
|
@@ -337,7 +337,7 @@ EXAMPLES
|
|
|
337
337
|
```
|
|
338
338
|
|
|
339
339
|
_See code:
|
|
340
|
-
[src/commands/add-track.ts](https://github.com/GMOD/jbrowse-components/blob/v2.
|
|
340
|
+
[src/commands/add-track.ts](https://github.com/GMOD/jbrowse-components/blob/v2.15.0/products/jbrowse-cli/src/commands/add-track.ts)_
|
|
341
341
|
|
|
342
342
|
## `jbrowse add-track-json TRACK`
|
|
343
343
|
|
|
@@ -367,7 +367,7 @@ EXAMPLES
|
|
|
367
367
|
```
|
|
368
368
|
|
|
369
369
|
_See code:
|
|
370
|
-
[src/commands/add-track-json.ts](https://github.com/GMOD/jbrowse-components/blob/v2.
|
|
370
|
+
[src/commands/add-track-json.ts](https://github.com/GMOD/jbrowse-components/blob/v2.15.0/products/jbrowse-cli/src/commands/add-track-json.ts)_
|
|
371
371
|
|
|
372
372
|
## `jbrowse admin-server`
|
|
373
373
|
|
|
@@ -399,7 +399,7 @@ EXAMPLES
|
|
|
399
399
|
```
|
|
400
400
|
|
|
401
401
|
_See code:
|
|
402
|
-
[src/commands/admin-server.ts](https://github.com/GMOD/jbrowse-components/blob/v2.
|
|
402
|
+
[src/commands/admin-server.ts](https://github.com/GMOD/jbrowse-components/blob/v2.15.0/products/jbrowse-cli/src/commands/admin-server.ts)_
|
|
403
403
|
|
|
404
404
|
## `jbrowse create LOCALPATH`
|
|
405
405
|
|
|
@@ -456,7 +456,7 @@ EXAMPLES
|
|
|
456
456
|
```
|
|
457
457
|
|
|
458
458
|
_See code:
|
|
459
|
-
[src/commands/create.ts](https://github.com/GMOD/jbrowse-components/blob/v2.
|
|
459
|
+
[src/commands/create.ts](https://github.com/GMOD/jbrowse-components/blob/v2.15.0/products/jbrowse-cli/src/commands/create.ts)_
|
|
460
460
|
|
|
461
461
|
## `jbrowse help [COMMAND]`
|
|
462
462
|
|
|
@@ -477,7 +477,7 @@ DESCRIPTION
|
|
|
477
477
|
```
|
|
478
478
|
|
|
479
479
|
_See code:
|
|
480
|
-
[@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.
|
|
480
|
+
[@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.10/src/commands/help.ts)_
|
|
481
481
|
|
|
482
482
|
## `jbrowse make-pif FILE`
|
|
483
483
|
|
|
@@ -507,7 +507,7 @@ EXAMPLES
|
|
|
507
507
|
```
|
|
508
508
|
|
|
509
509
|
_See code:
|
|
510
|
-
[src/commands/make-pif.ts](https://github.com/GMOD/jbrowse-components/blob/v2.
|
|
510
|
+
[src/commands/make-pif.ts](https://github.com/GMOD/jbrowse-components/blob/v2.15.0/products/jbrowse-cli/src/commands/make-pif.ts)_
|
|
511
511
|
|
|
512
512
|
## `jbrowse remove-track TRACK`
|
|
513
513
|
|
|
@@ -535,7 +535,7 @@ EXAMPLES
|
|
|
535
535
|
```
|
|
536
536
|
|
|
537
537
|
_See code:
|
|
538
|
-
[src/commands/remove-track.ts](https://github.com/GMOD/jbrowse-components/blob/v2.
|
|
538
|
+
[src/commands/remove-track.ts](https://github.com/GMOD/jbrowse-components/blob/v2.15.0/products/jbrowse-cli/src/commands/remove-track.ts)_
|
|
539
539
|
|
|
540
540
|
## `jbrowse set-default-session`
|
|
541
541
|
|
|
@@ -577,7 +577,7 @@ EXAMPLES
|
|
|
577
577
|
```
|
|
578
578
|
|
|
579
579
|
_See code:
|
|
580
|
-
[src/commands/set-default-session.ts](https://github.com/GMOD/jbrowse-components/blob/v2.
|
|
580
|
+
[src/commands/set-default-session.ts](https://github.com/GMOD/jbrowse-components/blob/v2.15.0/products/jbrowse-cli/src/commands/set-default-session.ts)_
|
|
581
581
|
|
|
582
582
|
## `jbrowse sort-gff FILE`
|
|
583
583
|
|
|
@@ -608,7 +608,7 @@ EXAMPLES
|
|
|
608
608
|
```
|
|
609
609
|
|
|
610
610
|
_See code:
|
|
611
|
-
[src/commands/sort-gff.ts](https://github.com/GMOD/jbrowse-components/blob/v2.
|
|
611
|
+
[src/commands/sort-gff.ts](https://github.com/GMOD/jbrowse-components/blob/v2.15.0/products/jbrowse-cli/src/commands/sort-gff.ts)_
|
|
612
612
|
|
|
613
613
|
## `jbrowse text-index`
|
|
614
614
|
|
|
@@ -675,7 +675,7 @@ EXAMPLES
|
|
|
675
675
|
```
|
|
676
676
|
|
|
677
677
|
_See code:
|
|
678
|
-
[src/commands/text-index.ts](https://github.com/GMOD/jbrowse-components/blob/v2.
|
|
678
|
+
[src/commands/text-index.ts](https://github.com/GMOD/jbrowse-components/blob/v2.15.0/products/jbrowse-cli/src/commands/text-index.ts)_
|
|
679
679
|
|
|
680
680
|
## `jbrowse upgrade [LOCALPATH]`
|
|
681
681
|
|
|
@@ -738,7 +738,7 @@ EXAMPLES
|
|
|
738
738
|
```
|
|
739
739
|
|
|
740
740
|
_See code:
|
|
741
|
-
[src/commands/upgrade.ts](https://github.com/GMOD/jbrowse-components/blob/v2.
|
|
741
|
+
[src/commands/upgrade.ts](https://github.com/GMOD/jbrowse-components/blob/v2.15.0/products/jbrowse-cli/src/commands/upgrade.ts)_
|
|
742
742
|
|
|
743
743
|
<!-- commandsstop -->
|
|
744
744
|
|
package/lib/base.js
CHANGED
|
@@ -42,7 +42,6 @@ class JBrowseCommand extends core_1.Command {
|
|
|
42
42
|
}
|
|
43
43
|
return result;
|
|
44
44
|
}
|
|
45
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
45
|
async writeJsonFile(location, contents) {
|
|
47
46
|
this.debug(`Writing JSON file to ${process.cwd()} ${location}`);
|
|
48
47
|
return fs_1.promises.writeFile(location, JSON.stringify(contents, null, 2));
|
|
@@ -105,11 +104,11 @@ class JBrowseCommand extends core_1.Command {
|
|
|
105
104
|
}
|
|
106
105
|
async getLatest() {
|
|
107
106
|
for await (const versions of this.fetchVersions()) {
|
|
108
|
-
// if a release was just uploaded, or an erroneous build was made
|
|
109
|
-
//
|
|
107
|
+
// if a release was just uploaded, or an erroneous build was made then it
|
|
108
|
+
// might have no build asset
|
|
110
109
|
const nonprereleases = versions
|
|
111
|
-
.filter(release => release.prerelease
|
|
112
|
-
.filter(release => release.assets
|
|
110
|
+
.filter(release => !release.prerelease)
|
|
111
|
+
.filter(release => release.assets?.length);
|
|
113
112
|
if (nonprereleases.length > 0) {
|
|
114
113
|
// @ts-expect-error
|
|
115
114
|
const file = nonprereleases[0].assets.find(f => f.name.includes('jbrowse-web'))?.browser_download_url;
|
|
@@ -125,22 +124,23 @@ class JBrowseCommand extends core_1.Command {
|
|
|
125
124
|
let page = 1;
|
|
126
125
|
let result;
|
|
127
126
|
do {
|
|
128
|
-
const
|
|
127
|
+
const url = `https://api.github.com/repos/GMOD/jbrowse-components/releases?page=${page}`;
|
|
128
|
+
const response = await (0, fetchWithProxy_1.default)(url);
|
|
129
129
|
if (response.ok) {
|
|
130
130
|
result = (await response.json());
|
|
131
131
|
yield result.filter(release => release.tag_name.startsWith('v'));
|
|
132
132
|
page++;
|
|
133
133
|
}
|
|
134
134
|
else {
|
|
135
|
-
throw new Error(
|
|
135
|
+
throw new Error(`HTTP ${response.status} fetching ${url}`);
|
|
136
136
|
}
|
|
137
|
-
} while (result
|
|
137
|
+
} while (result.length);
|
|
138
138
|
}
|
|
139
139
|
async getTag(tag) {
|
|
140
140
|
const response = await (0, fetchWithProxy_1.default)(`https://api.github.com/repos/GMOD/jbrowse-components/releases/tags/${tag}`);
|
|
141
141
|
if (response.ok) {
|
|
142
142
|
const result = (await response.json());
|
|
143
|
-
const file = result
|
|
143
|
+
const file = result.assets?.find(f => f.name.includes('jbrowse-web'))?.browser_download_url;
|
|
144
144
|
if (!file) {
|
|
145
145
|
this.error('Could not find version specified. Use --listVersions to see all available versions', { exit: 90 });
|
|
146
146
|
}
|
|
@@ -23,10 +23,10 @@ class AddAssembly extends base_1.default {
|
|
|
23
23
|
const { args: runArgs, flags: runFlags } = await this.parse(AddAssembly);
|
|
24
24
|
const { sequence: argsSequence } = runArgs;
|
|
25
25
|
if (this.needLoadData(argsSequence) && !runFlags.load) {
|
|
26
|
-
this.error(
|
|
26
|
+
this.error('Please specify the loading operation for this file with --load copy|symlink|move|inPlace', { exit: 110 });
|
|
27
27
|
}
|
|
28
28
|
else if (!this.needLoadData(argsSequence) && runFlags.load) {
|
|
29
|
-
this.error(
|
|
29
|
+
this.error('URL detected with --load flag. Please rerun the function without the --load flag', { exit: 120 });
|
|
30
30
|
}
|
|
31
31
|
let { name } = runFlags;
|
|
32
32
|
let { type } = runFlags;
|
|
@@ -192,7 +192,11 @@ class AddAssembly extends base_1.default {
|
|
|
192
192
|
}
|
|
193
193
|
async run() {
|
|
194
194
|
// https://stackoverflow.com/a/35008327/2129219
|
|
195
|
-
const exists = (s) => new Promise(r =>
|
|
195
|
+
const exists = (s) => new Promise(r => {
|
|
196
|
+
fs_1.default.access(s, fs_1.default.constants.F_OK, e => {
|
|
197
|
+
r(!e);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
196
200
|
const { args: runArgs, flags: runFlags } = await this.parse(AddAssembly);
|
|
197
201
|
const output = runFlags.target || runFlags.out || '.';
|
|
198
202
|
if (!(await exists(output))) {
|
|
@@ -82,26 +82,19 @@ class AddConnection extends base_1.default {
|
|
|
82
82
|
catch (error) {
|
|
83
83
|
this.error('The location provided is not a valid URL', { exit: 160 });
|
|
84
84
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
response = await (0, fetchWithProxy_1.default)(locationUrl, { method: 'HEAD' });
|
|
91
|
-
}
|
|
92
|
-
if (!response || response.ok) {
|
|
93
|
-
return locationUrl.href;
|
|
85
|
+
try {
|
|
86
|
+
if (check) {
|
|
87
|
+
const response = await (0, fetchWithProxy_1.default)(`${locationUrl}`, { method: 'HEAD' });
|
|
88
|
+
if (!response.ok) {
|
|
89
|
+
this.error(`Response returned with code ${response.status}`);
|
|
94
90
|
}
|
|
95
|
-
this.error(`Response returned with code ${response.status}`);
|
|
96
|
-
}
|
|
97
|
-
catch (error) {
|
|
98
|
-
// ignore
|
|
99
|
-
this.error(`Unable to fetch from URL, ${error}`, { exit: 170 });
|
|
100
91
|
}
|
|
92
|
+
return locationUrl.href;
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
// ignore
|
|
96
|
+
this.error(`Unable to fetch from URL, ${error}`, { exit: 170 });
|
|
101
97
|
}
|
|
102
|
-
return this.error(`Could not resolve to a URL: "${location}"`, {
|
|
103
|
-
exit: 180,
|
|
104
|
-
});
|
|
105
98
|
}
|
|
106
99
|
determineConnectionType(url) {
|
|
107
100
|
if (path_1.default.basename(url) === 'hub.txt') {
|
|
@@ -134,7 +127,7 @@ AddConnection.examples = [
|
|
|
134
127
|
AddConnection.args = {
|
|
135
128
|
connectionUrlOrPath: core_1.Args.string({
|
|
136
129
|
required: true,
|
|
137
|
-
description:
|
|
130
|
+
description: 'URL of data directory\nFor hub file, usually called hub.txt\nFor JBrowse 1, location of JB1 data directory similar to http://mysite.com/jbrowse/data/ ',
|
|
138
131
|
}),
|
|
139
132
|
};
|
|
140
133
|
AddConnection.flags = {
|
|
@@ -23,7 +23,7 @@ class AddTrackJson extends base_1.default {
|
|
|
23
23
|
}
|
|
24
24
|
const idx = config.tracks.findIndex(({ trackId }) => trackId === track.trackId);
|
|
25
25
|
if (idx !== -1) {
|
|
26
|
-
const existing = config.tracks[idx]
|
|
26
|
+
const existing = config.tracks[idx]?.name;
|
|
27
27
|
this.debug(`Found existing track ${existing} in configuration`);
|
|
28
28
|
if (update) {
|
|
29
29
|
this.debug(`Overwriting track ${existing} in configuration`);
|
|
@@ -49,13 +49,13 @@ AddTrackJson.examples = [
|
|
|
49
49
|
AddTrackJson.args = {
|
|
50
50
|
track: core_1.Args.string({
|
|
51
51
|
required: true,
|
|
52
|
-
description:
|
|
52
|
+
description: 'track JSON file or command line arg blob',
|
|
53
53
|
}),
|
|
54
54
|
};
|
|
55
55
|
AddTrackJson.flags = {
|
|
56
56
|
update: core_1.Flags.boolean({
|
|
57
57
|
char: 'u',
|
|
58
|
-
description:
|
|
58
|
+
description: 'update the contents of an existing track, matched based on trackId',
|
|
59
59
|
}),
|
|
60
60
|
target: core_1.Flags.string({
|
|
61
61
|
description: 'path to config file in JB2 installation directory to write out to.\nCreates ./config.json if nonexistent',
|
|
@@ -129,7 +129,7 @@ class AddTrack extends base_1.default {
|
|
|
129
129
|
trackType = trackType || this.guessTrackType(adapter.type);
|
|
130
130
|
trackId = trackId || path_1.default.basename(location, path_1.default.extname(location));
|
|
131
131
|
name = name || trackId;
|
|
132
|
-
assemblyNames = assemblyNames || configContents.assemblies[0]
|
|
132
|
+
assemblyNames = assemblyNames || configContents.assemblies[0]?.name || '';
|
|
133
133
|
const configObj = config ? (0, json_parse_better_errors_1.default)(config) : {};
|
|
134
134
|
const trackConfig = {
|
|
135
135
|
type: trackType,
|
|
@@ -145,6 +145,7 @@ class AddTrack extends base_1.default {
|
|
|
145
145
|
if (trackType === 'AlignmentsTrack') {
|
|
146
146
|
const assembly = configContents.assemblies.find(asm => asm.name === assemblyNames);
|
|
147
147
|
if (assembly) {
|
|
148
|
+
// @ts-expect-error
|
|
148
149
|
trackConfig.adapter.sequenceAdapter = assembly.sequence.adapter;
|
|
149
150
|
}
|
|
150
151
|
else if (!skipCheck) {
|
|
@@ -445,27 +446,7 @@ class AddTrack extends base_1.default {
|
|
|
445
446
|
};
|
|
446
447
|
}
|
|
447
448
|
guessTrackType(adapterType) {
|
|
448
|
-
|
|
449
|
-
BamAdapter: 'AlignmentsTrack',
|
|
450
|
-
CramAdapter: 'AlignmentsTrack',
|
|
451
|
-
BgzipFastaAdapter: 'ReferenceSequenceTrack',
|
|
452
|
-
BigWigAdapter: 'QuantitativeTrack',
|
|
453
|
-
IndexedFastaAdapter: 'ReferenceSequenceTrack',
|
|
454
|
-
TwoBitAdapter: 'ReferenceSequenceTrack',
|
|
455
|
-
VcfTabixAdapter: 'VariantTrack',
|
|
456
|
-
VcfAdapter: 'VariantTrack',
|
|
457
|
-
BedpeAdapter: 'VariantTrack',
|
|
458
|
-
BedAdapter: 'FeatureTrack',
|
|
459
|
-
HicAdapter: 'HicTrack',
|
|
460
|
-
PAFAdapter: 'SyntenyTrack',
|
|
461
|
-
DeltaAdapter: 'SyntenyTrack',
|
|
462
|
-
ChainAdapter: 'SyntenyTrack',
|
|
463
|
-
MashMapAdapter: 'SyntenyTrack',
|
|
464
|
-
PairwiseIndexedPAFAdapter: 'SyntenyTrack',
|
|
465
|
-
MCScanAnchorsAdapter: 'SyntenyTrack',
|
|
466
|
-
MCScanSimpleAnchorsAdapter: 'SyntenyTrack',
|
|
467
|
-
};
|
|
468
|
-
return known[adapterType] || 'FeatureTrack';
|
|
449
|
+
return adapterTypesToTrackTypeMap[adapterType] || 'FeatureTrack';
|
|
469
450
|
}
|
|
470
451
|
}
|
|
471
452
|
AddTrack.description = 'Add a track to a JBrowse 2 configuration';
|
|
@@ -476,7 +457,7 @@ AddTrack.examples = [
|
|
|
476
457
|
'# copy my.bam and my.bam.bai to /path/to/jb2/bam and adds track entry to /path/to/jb2/bam/config.json',
|
|
477
458
|
'$ jbrowse add-track my.bam --load copy --out /path/to/jb2 --subDir bam',
|
|
478
459
|
'',
|
|
479
|
-
|
|
460
|
+
'# same as above, but specify path to bai file. needed for if the bai file does not have the extension .bam.bai',
|
|
480
461
|
'$ jbrowse add-track my.bam --indexFile my.bai --load copy',
|
|
481
462
|
'',
|
|
482
463
|
'# creates symlink for /path/to/my.bam and adds track to config.json',
|
|
@@ -491,13 +472,13 @@ AddTrack.examples = [
|
|
|
491
472
|
AddTrack.args = {
|
|
492
473
|
track: core_1.Args.string({
|
|
493
474
|
required: true,
|
|
494
|
-
description:
|
|
475
|
+
description: 'Track file or URL',
|
|
495
476
|
}),
|
|
496
477
|
};
|
|
497
478
|
AddTrack.flags = {
|
|
498
479
|
trackType: core_1.Flags.string({
|
|
499
480
|
char: 't',
|
|
500
|
-
description:
|
|
481
|
+
description: 'Type of track, by default inferred from track file',
|
|
501
482
|
}),
|
|
502
483
|
name: core_1.Flags.string({
|
|
503
484
|
char: 'n',
|
|
@@ -561,3 +542,23 @@ AddTrack.flags = {
|
|
|
561
542
|
}),
|
|
562
543
|
};
|
|
563
544
|
exports.default = AddTrack;
|
|
545
|
+
const adapterTypesToTrackTypeMap = {
|
|
546
|
+
BamAdapter: 'AlignmentsTrack',
|
|
547
|
+
CramAdapter: 'AlignmentsTrack',
|
|
548
|
+
BgzipFastaAdapter: 'ReferenceSequenceTrack',
|
|
549
|
+
BigWigAdapter: 'QuantitativeTrack',
|
|
550
|
+
IndexedFastaAdapter: 'ReferenceSequenceTrack',
|
|
551
|
+
TwoBitAdapter: 'ReferenceSequenceTrack',
|
|
552
|
+
VcfTabixAdapter: 'VariantTrack',
|
|
553
|
+
VcfAdapter: 'VariantTrack',
|
|
554
|
+
BedpeAdapter: 'VariantTrack',
|
|
555
|
+
BedAdapter: 'FeatureTrack',
|
|
556
|
+
HicAdapter: 'HicTrack',
|
|
557
|
+
PAFAdapter: 'SyntenyTrack',
|
|
558
|
+
DeltaAdapter: 'SyntenyTrack',
|
|
559
|
+
ChainAdapter: 'SyntenyTrack',
|
|
560
|
+
MashMapAdapter: 'SyntenyTrack',
|
|
561
|
+
PairwiseIndexedPAFAdapter: 'SyntenyTrack',
|
|
562
|
+
MCScanAnchorsAdapter: 'SyntenyTrack',
|
|
563
|
+
MCScanSimpleAnchorsAdapter: 'SyntenyTrack',
|
|
564
|
+
};
|
|
@@ -46,11 +46,11 @@ class AdminServer extends base_1.default {
|
|
|
46
46
|
// start server with admin key in URL query string
|
|
47
47
|
let port = 9090;
|
|
48
48
|
if (runFlags.port) {
|
|
49
|
-
if (!isValidPort(parseInt(runFlags.port, 10))) {
|
|
49
|
+
if (!isValidPort(Number.parseInt(runFlags.port, 10))) {
|
|
50
50
|
this.error(`${runFlags.port} is not a valid port`);
|
|
51
51
|
}
|
|
52
52
|
else {
|
|
53
|
-
port = parseInt(runFlags.port, 10);
|
|
53
|
+
port = Number.parseInt(runFlags.port, 10);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
const app = (0, express_1.default)();
|
package/lib/commands/create.js
CHANGED
package/lib/commands/make-pif.js
CHANGED
|
@@ -18,7 +18,7 @@ const cigarRegex = new RegExp(/([MIDNSHPX=])/);
|
|
|
18
18
|
function getReadline(filename) {
|
|
19
19
|
const stream = fs_1.default.createReadStream(filename);
|
|
20
20
|
return readline_1.default.createInterface({
|
|
21
|
-
input:
|
|
21
|
+
input: /.b?gz$/.exec(filename) ? stream.pipe((0, zlib_1.createGunzip)()) : stream,
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
24
|
function getStdReadline() {
|
|
@@ -53,7 +53,7 @@ async function createPIF(filename, stream) {
|
|
|
53
53
|
const rl1 = filename ? getReadline(filename) : getStdReadline();
|
|
54
54
|
for await (const line of rl1) {
|
|
55
55
|
const [c1, l1, s1, e1, strand, c2, l2, s2, e2, ...rest] = line.split('\t');
|
|
56
|
-
stream.write([`t${c2}`, l2, s2, e2, strand, c1, l1, s1, e1, ...rest].join('\t')
|
|
56
|
+
stream.write(`${[`t${c2}`, l2, s2, e2, strand, c1, l1, s1, e1, ...rest].join('\t')}\n`);
|
|
57
57
|
const cigarIdx = rest.findIndex(f => f.startsWith('cg:Z'));
|
|
58
58
|
const CIGAR = rest[cigarIdx];
|
|
59
59
|
if (CIGAR) {
|
|
@@ -61,7 +61,7 @@ async function createPIF(filename, stream) {
|
|
|
61
61
|
? flipCigar(parseCigar(CIGAR.slice(5))).join('')
|
|
62
62
|
: swapIndelCigar(CIGAR.slice(5))}`;
|
|
63
63
|
}
|
|
64
|
-
stream.write([`q${c1}`, l1, s1, e1, strand, c2, l2, s2, e2, ...rest].join('\t')
|
|
64
|
+
stream.write(`${[`q${c1}`, l1, s1, e1, strand, c2, l2, s2, e2, ...rest].join('\t')}\n`);
|
|
65
65
|
}
|
|
66
66
|
rl1.close();
|
|
67
67
|
}
|
|
@@ -110,7 +110,7 @@ MakePIF.flags = {
|
|
|
110
110
|
MakePIF.args = {
|
|
111
111
|
file: core_1.Args.string({
|
|
112
112
|
required: true,
|
|
113
|
-
description:
|
|
113
|
+
description: 'PAF file as input',
|
|
114
114
|
}),
|
|
115
115
|
};
|
|
116
116
|
exports.default = MakePIF;
|
|
@@ -23,7 +23,7 @@ RemoveTrackJson.examples = ['$ jbrowse remove-track-json trackId'];
|
|
|
23
23
|
RemoveTrackJson.args = {
|
|
24
24
|
track: core_1.Args.string({
|
|
25
25
|
required: true,
|
|
26
|
-
description:
|
|
26
|
+
description: 'track JSON file or command line arg blob',
|
|
27
27
|
}),
|
|
28
28
|
};
|
|
29
29
|
RemoveTrackJson.flags = {
|
|
@@ -17,7 +17,7 @@ class SetDefaultSession extends base_1.default {
|
|
|
17
17
|
this.target = isDir ? `${output}/config.json` : output;
|
|
18
18
|
const configContents = await this.readJsonFile(this.target);
|
|
19
19
|
if (deleteDefaultSession) {
|
|
20
|
-
|
|
20
|
+
configContents.defaultSession = undefined;
|
|
21
21
|
await this.writeJsonFile(this.target, configContents);
|
|
22
22
|
}
|
|
23
23
|
else if (currentSession) {
|
|
@@ -25,7 +25,7 @@ class SetDefaultSession extends base_1.default {
|
|
|
25
25
|
this.exit();
|
|
26
26
|
}
|
|
27
27
|
else if (!session) {
|
|
28
|
-
this.error(
|
|
28
|
+
this.error('Please provide a --session file', { exit: 120 });
|
|
29
29
|
}
|
|
30
30
|
else if (session) {
|
|
31
31
|
await this.writeJsonFile(this.target, {
|
package/lib/commands/sort-gff.js
CHANGED
|
@@ -53,21 +53,21 @@ class TextIndex extends base_1.default {
|
|
|
53
53
|
const asms = assemblies?.split(',') ||
|
|
54
54
|
config.assemblies?.map(a => a.name) ||
|
|
55
55
|
(config.assembly ? [config.assembly.name] : []);
|
|
56
|
-
if (!asms
|
|
56
|
+
if (!asms.length) {
|
|
57
57
|
throw new Error('No assemblies found');
|
|
58
58
|
}
|
|
59
59
|
for (const asm of asms) {
|
|
60
60
|
const trackConfigs = await this.getTrackConfigs(confPath, tracks?.split(','), asm);
|
|
61
61
|
if (!trackConfigs.length) {
|
|
62
|
-
this.log(
|
|
62
|
+
this.log(`Indexing assembly ${asm}...(no tracks found)...`);
|
|
63
63
|
continue;
|
|
64
64
|
}
|
|
65
|
-
this.log(
|
|
65
|
+
this.log(`Indexing assembly ${asm}...`);
|
|
66
66
|
if (dryrun) {
|
|
67
|
-
this.log(trackConfigs.map(e => `${e.trackId}\t${e.adapter
|
|
67
|
+
this.log(trackConfigs.map(e => `${e.trackId}\t${e.adapter?.type}`).join('\n'));
|
|
68
68
|
}
|
|
69
69
|
else {
|
|
70
|
-
const id = asm
|
|
70
|
+
const id = `${asm}-index`;
|
|
71
71
|
const idx = aggregateTextSearchAdapters.findIndex(x => x.textSearchAdapterId === id);
|
|
72
72
|
if (idx !== -1 && !force) {
|
|
73
73
|
this.log(`Note: ${asm} has already been indexed with this configuration, use --force to overwrite this assembly. Skipping for now`);
|
|
@@ -133,7 +133,7 @@ class TextIndex extends base_1.default {
|
|
|
133
133
|
}
|
|
134
134
|
const confs = await this.getTrackConfigs(confFilePath, tracks?.split(','));
|
|
135
135
|
if (!confs.length) {
|
|
136
|
-
throw new Error(
|
|
136
|
+
throw new Error('Tracks not found in config.json, please add track configurations before indexing.');
|
|
137
137
|
}
|
|
138
138
|
for (const trackConfig of confs) {
|
|
139
139
|
const { textSearching, trackId, assemblyNames } = trackConfig;
|
|
@@ -141,7 +141,7 @@ class TextIndex extends base_1.default {
|
|
|
141
141
|
this.log(`Note: ${trackId} has already been indexed with this configuration, use --force to overwrite this track. Skipping for now`);
|
|
142
142
|
continue;
|
|
143
143
|
}
|
|
144
|
-
this.log(
|
|
144
|
+
this.log(`Indexing track ${trackId}...`);
|
|
145
145
|
await this.indexDriver({
|
|
146
146
|
trackConfigs: [trackConfig],
|
|
147
147
|
attributes: attributes.split(','),
|
|
@@ -162,7 +162,7 @@ class TextIndex extends base_1.default {
|
|
|
162
162
|
...textSearching,
|
|
163
163
|
textSearchAdapter: {
|
|
164
164
|
type: 'TrixTextSearchAdapter',
|
|
165
|
-
textSearchAdapterId: trackId
|
|
165
|
+
textSearchAdapterId: `${trackId}-index`,
|
|
166
166
|
ixFilePath: {
|
|
167
167
|
uri: `trix/${trackId}.ix`,
|
|
168
168
|
locationType: 'UriLocation',
|
|
@@ -200,7 +200,7 @@ class TextIndex extends base_1.default {
|
|
|
200
200
|
}
|
|
201
201
|
const trackConfigs = file
|
|
202
202
|
.map(file => (0, common_1.guessAdapterFromFileName)(file))
|
|
203
|
-
.filter(fileConfig => (0, common_1.supported)(fileConfig.adapter
|
|
203
|
+
.filter(fileConfig => (0, common_1.supported)(fileConfig.adapter?.type));
|
|
204
204
|
if (fileId?.length) {
|
|
205
205
|
for (let i = 0; i < fileId.length; i++) {
|
|
206
206
|
trackConfigs[i].trackId = fileId[i];
|
|
@@ -226,7 +226,7 @@ class TextIndex extends base_1.default {
|
|
|
226
226
|
quiet,
|
|
227
227
|
typesToExclude,
|
|
228
228
|
}));
|
|
229
|
-
|
|
229
|
+
await this.runIxIxx({
|
|
230
230
|
readStream,
|
|
231
231
|
outLocation,
|
|
232
232
|
name,
|
|
@@ -240,27 +240,30 @@ class TextIndex extends base_1.default {
|
|
|
240
240
|
typesToExclude,
|
|
241
241
|
assemblyNames,
|
|
242
242
|
});
|
|
243
|
-
return ixIxxStream;
|
|
244
243
|
}
|
|
245
244
|
async *indexFiles({ trackConfigs, attributes, outLocation, quiet, typesToExclude, }) {
|
|
246
245
|
for (const config of trackConfigs) {
|
|
247
246
|
const { adapter, textSearching } = config;
|
|
248
|
-
const { type } = adapter;
|
|
247
|
+
const { type } = adapter || {};
|
|
249
248
|
const { indexingFeatureTypesToExclude = typesToExclude, indexingAttributes = attributes, } = textSearching || {};
|
|
250
249
|
let loc;
|
|
251
250
|
if (type === 'Gff3TabixAdapter') {
|
|
251
|
+
// @ts-expect-error
|
|
252
252
|
loc = adapter.gffGzLocation;
|
|
253
253
|
}
|
|
254
254
|
else if (type === 'Gff3Adapter') {
|
|
255
|
+
// @ts-expect-error
|
|
255
256
|
loc = adapter.gffLocation;
|
|
256
257
|
}
|
|
257
258
|
else if (type === 'VcfAdapter') {
|
|
259
|
+
// @ts-expect-error
|
|
258
260
|
loc = adapter.vcfLocation;
|
|
259
261
|
}
|
|
260
262
|
else if (type === 'VcfTabixAdapter') {
|
|
263
|
+
// @ts-expect-error
|
|
261
264
|
loc = adapter.vcfGzLocation;
|
|
262
265
|
}
|
|
263
|
-
|
|
266
|
+
else {
|
|
264
267
|
return;
|
|
265
268
|
}
|
|
266
269
|
if (type === 'Gff3TabixAdapter' || type === 'Gff3Adapter') {
|
|
@@ -273,6 +276,7 @@ class TextIndex extends base_1.default {
|
|
|
273
276
|
quiet,
|
|
274
277
|
});
|
|
275
278
|
}
|
|
279
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
276
280
|
else if (type === 'VcfTabixAdapter' || type === 'VcfAdapter') {
|
|
277
281
|
yield* (0, vcfAdapter_1.indexVcf)({
|
|
278
282
|
config,
|
|
@@ -285,15 +289,15 @@ class TextIndex extends base_1.default {
|
|
|
285
289
|
}
|
|
286
290
|
}
|
|
287
291
|
}
|
|
288
|
-
runIxIxx({ readStream, outLocation, name, prefixSize, }) {
|
|
289
|
-
|
|
292
|
+
async runIxIxx({ readStream, outLocation, name, prefixSize, }) {
|
|
293
|
+
await (0, ixixx_1.ixIxxStream)(readStream, path_1.default.join(outLocation, 'trix', `${name}.ix`), path_1.default.join(outLocation, 'trix', `${name}.ixx`), prefixSize);
|
|
290
294
|
}
|
|
291
295
|
async getTrackConfigs(configPath, trackIds, assemblyName) {
|
|
292
296
|
const { tracks } = readConf(configPath);
|
|
293
297
|
if (!tracks) {
|
|
294
298
|
return [];
|
|
295
299
|
}
|
|
296
|
-
const trackIdsToIndex = trackIds || tracks
|
|
300
|
+
const trackIdsToIndex = trackIds || tracks.map(track => track.trackId);
|
|
297
301
|
return trackIdsToIndex
|
|
298
302
|
.map(trackId => {
|
|
299
303
|
const currentTrack = tracks.find(t => trackId === t.trackId);
|
|
@@ -326,7 +330,7 @@ TextIndex.examples = [
|
|
|
326
330
|
TextIndex.flags = {
|
|
327
331
|
help: core_1.Flags.help({ char: 'h' }),
|
|
328
332
|
tracks: core_1.Flags.string({
|
|
329
|
-
description:
|
|
333
|
+
description: 'Specific tracks to index, formatted as comma separated trackIds. If unspecified, indexes all available tracks',
|
|
330
334
|
}),
|
|
331
335
|
target: core_1.Flags.string({
|
|
332
336
|
description: 'Path to config file in JB2 installation directory to read from.',
|
package/lib/commands/upgrade.js
CHANGED
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const core_1 = require("@oclif/core");
|
|
7
|
-
const rimraf_1 = require("rimraf");
|
|
8
7
|
const fs_1 = __importDefault(require("fs"));
|
|
9
8
|
const path_1 = __importDefault(require("path"));
|
|
10
9
|
const decompress_1 = __importDefault(require("decompress"));
|
|
@@ -22,7 +21,7 @@ class Upgrade extends base_1.default {
|
|
|
22
21
|
}
|
|
23
22
|
this.debug(`Want to upgrade at: ${argsPath}`);
|
|
24
23
|
if (!argsPath) {
|
|
25
|
-
this.error(
|
|
24
|
+
this.error('No directory supplied', { exit: 100 });
|
|
26
25
|
}
|
|
27
26
|
if (!fs_1.default.existsSync(path_1.default.join(argsPath, 'manifest.json'))) {
|
|
28
27
|
this.error(`No manifest.json found in this directory, are you sure it is an
|
|
@@ -44,10 +43,12 @@ class Upgrade extends base_1.default {
|
|
|
44
43
|
this.error('The URL provided does not seem to be a JBrowse installation URL');
|
|
45
44
|
}
|
|
46
45
|
if (clean) {
|
|
47
|
-
|
|
46
|
+
fs_1.default.rmSync(path_1.default.join(argsPath, 'static'), { recursive: true, force: true });
|
|
48
47
|
fs_1.default.readdirSync(argsPath)
|
|
49
48
|
.filter(f => f.includes('worker.js'))
|
|
50
|
-
.forEach(f =>
|
|
49
|
+
.forEach(f => {
|
|
50
|
+
fs_1.default.unlinkSync(path_1.default.join(argsPath, f));
|
|
51
|
+
});
|
|
51
52
|
}
|
|
52
53
|
await (0, decompress_1.default)(Buffer.from(await response.arrayBuffer()), argsPath);
|
|
53
54
|
this.log(`Unpacked ${locationUrl} at ${argsPath}`);
|
|
@@ -76,7 +77,7 @@ Upgrade.examples = [
|
|
|
76
77
|
Upgrade.args = {
|
|
77
78
|
localPath: core_1.Args.string({
|
|
78
79
|
required: false,
|
|
79
|
-
description:
|
|
80
|
+
description: 'Location where JBrowse 2 is installed',
|
|
80
81
|
default: '.',
|
|
81
82
|
}),
|
|
82
83
|
};
|
package/lib/types/common.js
CHANGED
|
@@ -12,11 +12,11 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
12
12
|
const path_1 = __importDefault(require("path"));
|
|
13
13
|
const fetchWithProxy_1 = __importDefault(require("../fetchWithProxy"));
|
|
14
14
|
async function createRemoteStream(urlIn) {
|
|
15
|
-
const
|
|
16
|
-
if (!
|
|
17
|
-
throw new Error(`Failed to fetch ${urlIn} status ${
|
|
15
|
+
const res = await (0, fetchWithProxy_1.default)(urlIn);
|
|
16
|
+
if (!res.ok) {
|
|
17
|
+
throw new Error(`Failed to fetch ${urlIn} status ${res.status} ${await res.text()}`);
|
|
18
18
|
}
|
|
19
|
-
return
|
|
19
|
+
return res;
|
|
20
20
|
}
|
|
21
21
|
function isURL(FileName) {
|
|
22
22
|
let url;
|
|
@@ -44,7 +44,6 @@ function makeLocation(location, protocol) {
|
|
|
44
44
|
throw new Error(`invalid protocol ${protocol}`);
|
|
45
45
|
}
|
|
46
46
|
function guessAdapterFromFileName(filePath) {
|
|
47
|
-
// const uri = isURL(filePath) ? filePath : path.resolve(filePath)
|
|
48
47
|
const protocol = isURL(filePath) ? 'uri' : 'localPath';
|
|
49
48
|
const name = path_1.default.basename(filePath);
|
|
50
49
|
if (/\.vcf\.b?gz$/i.test(filePath)) {
|
|
@@ -106,7 +105,7 @@ function guessAdapterFromFileName(filePath) {
|
|
|
106
105
|
throw new Error(`Unsupported file type ${filePath}`);
|
|
107
106
|
}
|
|
108
107
|
}
|
|
109
|
-
function supported(type) {
|
|
108
|
+
function supported(type = '') {
|
|
110
109
|
return [
|
|
111
110
|
'Gff3TabixAdapter',
|
|
112
111
|
'VcfTabixAdapter',
|
package/lib/types/gff3Adapter.js
CHANGED
|
@@ -13,7 +13,7 @@ async function* indexGff3({ config, attributesToIndex, inLocation, outLocation,
|
|
|
13
13
|
// progress bar code was aided by blog post at
|
|
14
14
|
// https://webomnizz.com/download-a-file-with-progressbar-using-node-js/
|
|
15
15
|
const progressBar = new cli_progress_1.SingleBar({
|
|
16
|
-
format:
|
|
16
|
+
format: `{bar} ${trackId} {percentage}% | ETA: {eta}s`,
|
|
17
17
|
etaBuffer: 2000,
|
|
18
18
|
}, cli_progress_1.Presets.shades_classic);
|
|
19
19
|
let receivedBytes = 0;
|
|
@@ -28,7 +28,7 @@ async function* indexGff3({ config, attributesToIndex, inLocation, outLocation,
|
|
|
28
28
|
});
|
|
29
29
|
const rl = readline_1.default.createInterface({
|
|
30
30
|
// @ts-expect-error
|
|
31
|
-
input:
|
|
31
|
+
input: /.b?gz$/.exec(inLocation) ? stream.pipe((0, zlib_1.createGunzip)()) : stream,
|
|
32
32
|
});
|
|
33
33
|
for await (const line of rl) {
|
|
34
34
|
if (!line.trim()) {
|
|
@@ -52,7 +52,9 @@ async function* indexGff3({ config, attributesToIndex, inLocation, outLocation,
|
|
|
52
52
|
.map(f => f.split('='))
|
|
53
53
|
.map(([key, val]) => [
|
|
54
54
|
key.trim(),
|
|
55
|
-
|
|
55
|
+
val
|
|
56
|
+
? (0, util_1.decodeURIComponentNoThrow)(val).trim().split(',').join(' ')
|
|
57
|
+
: undefined,
|
|
56
58
|
]));
|
|
57
59
|
const attrs = attributesToIndex
|
|
58
60
|
.map(attr => col9attrs[attr])
|
package/lib/types/vcfAdapter.js
CHANGED
|
@@ -13,7 +13,7 @@ async function* indexVcf({ config, attributesToIndex, inLocation, outLocation, q
|
|
|
13
13
|
// progress bar code was aided by blog post at
|
|
14
14
|
// https://webomnizz.com/download-a-file-with-progressbar-using-node-js/
|
|
15
15
|
const progressBar = new cli_progress_1.SingleBar({
|
|
16
|
-
format:
|
|
16
|
+
format: `{bar} ${trackId} {percentage}% | ETA: {eta}s`,
|
|
17
17
|
etaBuffer: 2000,
|
|
18
18
|
}, cli_progress_1.Presets.shades_classic);
|
|
19
19
|
let receivedBytes = 0;
|
|
@@ -26,7 +26,7 @@ async function* indexVcf({ config, attributesToIndex, inLocation, outLocation, q
|
|
|
26
26
|
receivedBytes += chunk.length;
|
|
27
27
|
progressBar.update(receivedBytes);
|
|
28
28
|
});
|
|
29
|
-
const gzStream =
|
|
29
|
+
const gzStream = /.b?gz$/.exec(inLocation)
|
|
30
30
|
? // @ts-expect-error
|
|
31
31
|
stream.pipe((0, zlib_1.createGunzip)())
|
|
32
32
|
: stream;
|
package/lib/util.js
CHANGED
|
@@ -9,19 +9,20 @@ const common_1 = require("./types/common");
|
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
11
|
async function getLocalOrRemoteStream(uri, out) {
|
|
12
|
-
let stream;
|
|
13
|
-
let totalBytes = 0;
|
|
14
12
|
if ((0, common_1.isURL)(uri)) {
|
|
15
13
|
const result = await (0, common_1.createRemoteStream)(uri);
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
return {
|
|
15
|
+
totalBytes: +(result.headers.get('Content-Length') || 0),
|
|
16
|
+
stream: result.body,
|
|
17
|
+
};
|
|
18
18
|
}
|
|
19
19
|
else {
|
|
20
20
|
const filename = path_1.default.isAbsolute(uri) ? uri : path_1.default.join(out, uri);
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
return {
|
|
22
|
+
totalBytes: fs_1.default.statSync(filename).size,
|
|
23
|
+
stream: fs_1.default.createReadStream(filename),
|
|
24
|
+
};
|
|
23
25
|
}
|
|
24
|
-
return { totalBytes, stream };
|
|
25
26
|
}
|
|
26
27
|
function decodeURIComponentNoThrow(uri) {
|
|
27
28
|
try {
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.15.0",
|
|
4
4
|
"description": "A command line tool for working with JBrowse 2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -57,7 +57,6 @@
|
|
|
57
57
|
"ixixx": "^2.0.1",
|
|
58
58
|
"json-parse-better-errors": "^1.0.2",
|
|
59
59
|
"node-fetch-native": "^1.6.4",
|
|
60
|
-
"rimraf": "^5.0.0",
|
|
61
60
|
"tslib": "^2.3.1"
|
|
62
61
|
},
|
|
63
62
|
"devDependencies": {
|
|
@@ -74,5 +73,5 @@
|
|
|
74
73
|
"publishConfig": {
|
|
75
74
|
"access": "public"
|
|
76
75
|
},
|
|
77
|
-
"gitHead": "
|
|
76
|
+
"gitHead": "87eeb1fbf8311dbf88d5e75b5a265f03beffdda8"
|
|
78
77
|
}
|