@jbrowse/cli 3.5.1 → 3.6.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/README.md +291 -607
- package/bin/run +1 -6
- package/bundle/index.js +4459 -0
- package/dist/base.js +5 -0
- package/dist/bin.js +3 -0
- package/dist/commands/add-assembly.js +143 -0
- package/dist/commands/add-connection.js +177 -0
- package/dist/commands/add-track-json.js +81 -0
- package/dist/commands/add-track-utils/adapter-utils.js +304 -0
- package/dist/commands/add-track-utils/file-operations.js +36 -0
- package/dist/commands/add-track-utils/track-config.js +63 -0
- package/dist/commands/add-track-utils/validators.js +74 -0
- package/dist/commands/add-track.js +193 -0
- package/dist/commands/admin-server-utils.js +238 -0
- package/dist/commands/admin-server.js +51 -0
- package/dist/commands/assembly-utils.js +410 -0
- package/dist/commands/create.js +121 -0
- package/dist/commands/make-pif-utils/cigar-utils.js +29 -0
- package/dist/commands/make-pif-utils/file-utils.js +38 -0
- package/dist/commands/make-pif-utils/pif-generator.js +64 -0
- package/dist/commands/make-pif-utils/validators.js +22 -0
- package/dist/commands/make-pif.js +58 -0
- package/dist/commands/remove-track.js +58 -0
- package/dist/commands/set-default-session.js +104 -0
- package/dist/commands/sort-bed-utils/constants.js +12 -0
- package/dist/commands/sort-bed-utils/process-utils.js +23 -0
- package/dist/commands/sort-bed-utils/sort-utils.js +24 -0
- package/dist/commands/sort-bed-utils/validators.js +22 -0
- package/dist/commands/sort-bed.js +49 -0
- package/dist/commands/sort-gff-utils/constants.js +13 -0
- package/dist/commands/sort-gff-utils/process-utils.js +23 -0
- package/dist/commands/sort-gff-utils/sort-utils.js +55 -0
- package/dist/commands/sort-gff-utils/validators.js +21 -0
- package/dist/commands/sort-gff.js +49 -0
- package/dist/commands/text-index-utils/adapter-utils.js +63 -0
- package/dist/commands/text-index-utils/aggregate.js +87 -0
- package/dist/commands/text-index-utils/config-utils.js +59 -0
- package/dist/commands/text-index-utils/file-list.js +31 -0
- package/dist/commands/text-index-utils/index.js +9 -0
- package/dist/commands/text-index-utils/indexing-utils.js +84 -0
- package/dist/commands/text-index-utils/per-track.js +65 -0
- package/dist/commands/text-index-utils/validators.js +20 -0
- package/dist/commands/text-index.js +113 -0
- package/dist/commands/track-utils.js +85 -0
- package/dist/commands/upgrade.js +122 -0
- package/dist/index.js +119 -0
- package/dist/utils.js +154 -0
- package/package.json +13 -38
- package/bin/dev +0 -17
- package/bin/dev.cmd +0 -3
- package/bin/run.cmd +0 -3
- package/lib/base.js +0 -157
- package/lib/commands/add-assembly.js +0 -491
- package/lib/commands/add-connection.js +0 -170
- package/lib/commands/add-track-json.js +0 -67
- package/lib/commands/add-track.js +0 -564
- package/lib/commands/admin-server.js +0 -153
- package/lib/commands/create.js +0 -111
- package/lib/commands/make-pif.js +0 -116
- package/lib/commands/remove-track.js +0 -37
- package/lib/commands/set-default-session.js +0 -98
- package/lib/commands/sort-bed.js +0 -45
- package/lib/commands/sort-gff.js +0 -45
- package/lib/commands/text-index.js +0 -380
- package/lib/commands/upgrade.js +0 -109
- package/lib/index.js +0 -6
- package/oclif.manifest.json +0 -1169
- /package/{lib → dist}/fetchWithProxy.js +0 -0
- /package/{lib → dist}/types/common.js +0 -0
- /package/{lib → dist}/types/gff3Adapter.js +0 -0
- /package/{lib → dist}/types/vcfAdapter.js +0 -0
- /package/{lib → dist}/util.js +0 -0
package/dist/base.js
ADDED
package/dist/bin.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.run = run;
|
|
4
|
+
const util_1 = require("util");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const assembly_utils_1 = require("./assembly-utils");
|
|
7
|
+
async function run(args) {
|
|
8
|
+
const options = {
|
|
9
|
+
type: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
short: 't',
|
|
12
|
+
description: `type of sequence, by default inferred from sequence file\n\nindexedFasta An index FASTA (e.g. .fa or .fasta) file;\n can optionally specify --faiLocation\n\nbgzipFasta A block-gzipped and indexed FASTA (e.g. .fa.gz or .fasta.gz) file;\n can optionally specify --faiLocation and/or --gziLocation\n\ntwoBit A twoBit (e.g. .2bit) file\n\nchromSizes A chromosome sizes (e.g. .chrom.sizes) file\n\ncustom Either a JSON file location or inline JSON that defines a custom\n sequence adapter; must provide --name if using inline JSON`,
|
|
13
|
+
choices: ['indexedFasta', 'bgzipFasta', 'twoBit', 'chromSizes', 'custom'],
|
|
14
|
+
},
|
|
15
|
+
name: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
short: 'n',
|
|
18
|
+
description: 'Name of the assembly; if not specified, will be guessed using the sequence file name',
|
|
19
|
+
},
|
|
20
|
+
alias: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
short: 'a',
|
|
23
|
+
description: 'An alias for the assembly name (e.g. "hg38" if the name of the assembly is "GRCh38");\ncan be specified multiple times',
|
|
24
|
+
multiple: true,
|
|
25
|
+
},
|
|
26
|
+
displayName: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'The display name to specify for the assembly, e.g. "Homo sapiens (hg38)" while the name can be a shorter identifier like "hg38"',
|
|
29
|
+
},
|
|
30
|
+
faiLocation: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
description: '[default: <fastaLocation>.fai] FASTA index file or URL',
|
|
33
|
+
},
|
|
34
|
+
gziLocation: {
|
|
35
|
+
type: 'string',
|
|
36
|
+
description: '[default: <fastaLocation>.gzi] FASTA gzip index file or URL',
|
|
37
|
+
},
|
|
38
|
+
refNameAliases: {
|
|
39
|
+
type: 'string',
|
|
40
|
+
description: 'Reference sequence name aliases file or URL; assumed to be a tab-separated aliases\nfile unless --refNameAliasesType is specified',
|
|
41
|
+
},
|
|
42
|
+
refNameAliasesType: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
description: 'Type of aliases defined by --refNameAliases; if "custom", --refNameAliases is either\na JSON file location or inline JSON that defines a custom sequence adapter',
|
|
45
|
+
choices: ['aliases', 'custom'],
|
|
46
|
+
dependsOn: ['refNameAliases'],
|
|
47
|
+
},
|
|
48
|
+
refNameColors: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
description: 'A comma-separated list of color strings for the reference sequence names; will cycle\nthrough colors if there are fewer colors than sequences',
|
|
51
|
+
},
|
|
52
|
+
target: {
|
|
53
|
+
type: 'string',
|
|
54
|
+
description: 'path to config file in JB2 installation directory to write out to.\nCreates ./config.json if nonexistent',
|
|
55
|
+
},
|
|
56
|
+
out: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'synonym for target',
|
|
59
|
+
},
|
|
60
|
+
help: {
|
|
61
|
+
type: 'boolean',
|
|
62
|
+
short: 'h',
|
|
63
|
+
description: 'Display help for command',
|
|
64
|
+
},
|
|
65
|
+
load: {
|
|
66
|
+
type: 'string',
|
|
67
|
+
short: 'l',
|
|
68
|
+
description: 'Required flag when using a local file. Choose how to manage the data directory. Copy, symlink, or move the data directory to the JBrowse directory. Or use inPlace to modify the config without doing any file operations',
|
|
69
|
+
choices: ['copy', 'symlink', 'move', 'inPlace'],
|
|
70
|
+
},
|
|
71
|
+
skipCheck: {
|
|
72
|
+
type: 'boolean',
|
|
73
|
+
description: "Don't check whether or not the sequence file or URL exists or if you are in a JBrowse directory",
|
|
74
|
+
},
|
|
75
|
+
overwrite: {
|
|
76
|
+
type: 'boolean',
|
|
77
|
+
description: 'Overwrite existing assembly if one with the same name exists',
|
|
78
|
+
},
|
|
79
|
+
force: {
|
|
80
|
+
type: 'boolean',
|
|
81
|
+
short: 'f',
|
|
82
|
+
description: 'Equivalent to `--skipCheck --overwrite`',
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
const { positionals, values: runFlags } = (0, util_1.parseArgs)({
|
|
86
|
+
args,
|
|
87
|
+
options,
|
|
88
|
+
allowPositionals: true,
|
|
89
|
+
});
|
|
90
|
+
const description = 'Add an assembly to a JBrowse 2 configuration';
|
|
91
|
+
const examples = [
|
|
92
|
+
'# add assembly to installation in current directory. assumes .fai file also exists, and copies GRCh38.fa and GRCh38.fa.fai to current directory',
|
|
93
|
+
'$ jbrowse add-assembly GRCh38.fa --load copy',
|
|
94
|
+
'',
|
|
95
|
+
'# add assembly to a specific jb2 installation path using --out, and copies the .fa and .fa.fai file to /path/to/jb2',
|
|
96
|
+
'$ jbrowse add-assembly GRCh38.fa --out /path/to/jb2/ --load copy',
|
|
97
|
+
'',
|
|
98
|
+
'# force indexedFasta for add-assembly without relying on file extension',
|
|
99
|
+
'$ jbrowse add-assembly GRCh38.xyz --type indexedFasta --load copy',
|
|
100
|
+
'',
|
|
101
|
+
'# add displayName for an assembly',
|
|
102
|
+
'$ jbrowse add-assembly myFile.fa.gz --name hg38 --displayName "Homo sapiens (hg38)"',
|
|
103
|
+
'',
|
|
104
|
+
'# use chrom.sizes file for assembly instead of a fasta file',
|
|
105
|
+
'$ jbrowse add-assembly GRCh38.chrom.sizes --load inPlace',
|
|
106
|
+
'',
|
|
107
|
+
'# add assembly from preconfigured json file, expert option',
|
|
108
|
+
'$ jbrowse add-assembly GRCh38.config.json --load copy',
|
|
109
|
+
'',
|
|
110
|
+
'# add assembly from a 2bit file, also note pointing direct to a URL so no --load flag needed',
|
|
111
|
+
'$ jbrowse add-assembly https://example.com/data/sample.2bit',
|
|
112
|
+
'',
|
|
113
|
+
'# add a bgzip indexed fasta inferred by fa.gz extension. assumes .fa.gz.gzi and .fa.gz.fai files also exists',
|
|
114
|
+
'$ jbrowse add-assembly myfile.fa.gz --load copy',
|
|
115
|
+
];
|
|
116
|
+
if (runFlags.help) {
|
|
117
|
+
(0, utils_1.printHelp)({
|
|
118
|
+
description,
|
|
119
|
+
examples,
|
|
120
|
+
usage: 'jbrowse add-assembly <sequence> [options]',
|
|
121
|
+
options,
|
|
122
|
+
});
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const argsSequence = positionals[0] || '';
|
|
126
|
+
const output = runFlags.target || runFlags.out || '.';
|
|
127
|
+
(0, utils_1.debug)(`Sequence location is: ${argsSequence}`);
|
|
128
|
+
const target = await (0, assembly_utils_1.resolveTargetPath)(output);
|
|
129
|
+
const baseAssembly = await (0, assembly_utils_1.getAssembly)({ runFlags, argsSequence, target });
|
|
130
|
+
const assembly = await (0, assembly_utils_1.enhanceAssembly)(baseAssembly, runFlags);
|
|
131
|
+
const configContents = await (0, assembly_utils_1.loadOrCreateConfig)(target);
|
|
132
|
+
const { config: updatedConfig, wasOverwritten } = await (0, assembly_utils_1.addAssemblyToConfig)({
|
|
133
|
+
config: configContents,
|
|
134
|
+
assembly,
|
|
135
|
+
runFlags,
|
|
136
|
+
});
|
|
137
|
+
await (0, assembly_utils_1.saveConfigAndReport)({
|
|
138
|
+
config: updatedConfig,
|
|
139
|
+
target,
|
|
140
|
+
assembly,
|
|
141
|
+
wasOverwritten,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.run = run;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const util_1 = require("util");
|
|
10
|
+
const json_parse_better_errors_1 = __importDefault(require("json-parse-better-errors"));
|
|
11
|
+
const fetchWithProxy_1 = __importDefault(require("../fetchWithProxy"));
|
|
12
|
+
const utils_1 = require("../utils");
|
|
13
|
+
async function resolveURL(location, check = true) {
|
|
14
|
+
let locationUrl;
|
|
15
|
+
try {
|
|
16
|
+
locationUrl = new URL(location);
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
throw new Error(`The location ${location} provided is not a valid URL`);
|
|
20
|
+
}
|
|
21
|
+
if (check) {
|
|
22
|
+
const response = await (0, fetchWithProxy_1.default)(`${locationUrl}`, { method: 'HEAD' });
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
throw new Error(`HTTP ${response.status} fetching ${locationUrl}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return locationUrl.href;
|
|
28
|
+
}
|
|
29
|
+
function determineConnectionType(url) {
|
|
30
|
+
if (path_1.default.basename(url) === 'hub.txt') {
|
|
31
|
+
return 'UCSCTrackHubConnection';
|
|
32
|
+
}
|
|
33
|
+
if (url.includes('jbrowse/data')) {
|
|
34
|
+
return 'JBrowse1Connection';
|
|
35
|
+
}
|
|
36
|
+
return 'custom';
|
|
37
|
+
}
|
|
38
|
+
async function run(args) {
|
|
39
|
+
const options = {
|
|
40
|
+
help: {
|
|
41
|
+
type: 'boolean',
|
|
42
|
+
short: 'h',
|
|
43
|
+
},
|
|
44
|
+
type: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
short: 't',
|
|
47
|
+
description: 'Type of connection (e.g. JBrowse1Connection, UCSCTrackHubConnection, custom)',
|
|
48
|
+
},
|
|
49
|
+
assemblyNames: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
short: 'a',
|
|
52
|
+
description: 'For UCSC: optional comma separated list of assembly names to filter. For JBrowse1: a single assembly name',
|
|
53
|
+
},
|
|
54
|
+
config: {
|
|
55
|
+
type: 'string',
|
|
56
|
+
short: 'c',
|
|
57
|
+
description: 'Extra config settings to add to connection in JSON object format',
|
|
58
|
+
},
|
|
59
|
+
connectionId: {
|
|
60
|
+
type: 'string',
|
|
61
|
+
description: 'Id for the connection that must be unique to JBrowse',
|
|
62
|
+
},
|
|
63
|
+
name: {
|
|
64
|
+
type: 'string',
|
|
65
|
+
short: 'n',
|
|
66
|
+
description: 'Name of the connection. Defaults to connectionId if not provided',
|
|
67
|
+
},
|
|
68
|
+
target: {
|
|
69
|
+
type: 'string',
|
|
70
|
+
description: 'Path to config file in JB2 installation directory to write out to',
|
|
71
|
+
},
|
|
72
|
+
out: {
|
|
73
|
+
type: 'string',
|
|
74
|
+
description: 'Synonym for target',
|
|
75
|
+
},
|
|
76
|
+
skipCheck: {
|
|
77
|
+
type: 'boolean',
|
|
78
|
+
description: "Don't check whether the data directory URL exists",
|
|
79
|
+
},
|
|
80
|
+
overwrite: {
|
|
81
|
+
type: 'boolean',
|
|
82
|
+
description: 'Overwrites any existing connections if same connection id',
|
|
83
|
+
},
|
|
84
|
+
force: {
|
|
85
|
+
type: 'boolean',
|
|
86
|
+
short: 'f',
|
|
87
|
+
description: 'Equivalent to --skipCheck --overwrite',
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
const { values: flags, positionals } = (0, util_1.parseArgs)({
|
|
91
|
+
args,
|
|
92
|
+
options,
|
|
93
|
+
allowPositionals: true,
|
|
94
|
+
});
|
|
95
|
+
const description = 'Add a connection to a JBrowse 2 configuration';
|
|
96
|
+
const examples = [
|
|
97
|
+
'$ jbrowse add-connection http://mysite.com/jbrowse/data/ -a hg19',
|
|
98
|
+
'$ jbrowse add-connection http://mysite.com/jbrowse/custom_data_folder/ --type JBrowse1Connection -a hg38',
|
|
99
|
+
'$ jbrowse add-connection http://mysite.com/path/to/hub.txt',
|
|
100
|
+
'$ jbrowse add-connection http://mysite.com/path/to/custom_hub_name.txt --type UCSCTrackHubConnection',
|
|
101
|
+
`$ jbrowse add-connection http://mysite.com/path/to/custom --type custom --config '{"uri":{"url":"https://mysite.com/path/to/custom"}, "locationType": "UriLocation"}' -a hg19`,
|
|
102
|
+
'$ jbrowse add-connection https://mysite.com/path/to/hub.txt --connectionId newId --name newName --target /path/to/jb2/installation/config.json',
|
|
103
|
+
];
|
|
104
|
+
if (flags.help) {
|
|
105
|
+
(0, utils_1.printHelp)({
|
|
106
|
+
description,
|
|
107
|
+
examples,
|
|
108
|
+
usage: 'jbrowse add-connection <connectionUrlOrPath> [options]',
|
|
109
|
+
options,
|
|
110
|
+
});
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const connectionUrlOrPath = positionals[0];
|
|
114
|
+
if (!connectionUrlOrPath) {
|
|
115
|
+
console.error('Error: Missing required argument: connectionUrlOrPath');
|
|
116
|
+
console.error('Usage: jbrowse add-connection <connectionUrlOrPath> [options]');
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
const output = flags.target || flags.out || '.';
|
|
120
|
+
const isDir = fs_1.default.lstatSync(output).isDirectory();
|
|
121
|
+
const target = isDir ? `${output}/config.json` : output;
|
|
122
|
+
const { assemblyNames, type, name, config, connectionId, skipCheck, force } = flags;
|
|
123
|
+
const url = await resolveURL(connectionUrlOrPath, !(skipCheck || force));
|
|
124
|
+
const configContents = await (0, utils_1.readJsonFile)(target);
|
|
125
|
+
(0, utils_1.debug)(`Using config file ${target}`);
|
|
126
|
+
if (!configContents.assemblies?.length) {
|
|
127
|
+
throw new Error('No assemblies found. Please add one before adding connections');
|
|
128
|
+
}
|
|
129
|
+
const configType = type || determineConnectionType(url);
|
|
130
|
+
const id = connectionId ||
|
|
131
|
+
[configType, assemblyNames, +Date.now()].filter(f => !!f).join('-');
|
|
132
|
+
const connectionConfig = {
|
|
133
|
+
type: configType,
|
|
134
|
+
name: name || id,
|
|
135
|
+
...(configType === 'UCSCTrackHubConnection'
|
|
136
|
+
? {
|
|
137
|
+
hubTxtLocation: {
|
|
138
|
+
uri: url,
|
|
139
|
+
locationType: 'UriLocation',
|
|
140
|
+
},
|
|
141
|
+
}
|
|
142
|
+
: {}),
|
|
143
|
+
...(configType === 'JBrowse1Connection'
|
|
144
|
+
? {
|
|
145
|
+
dataDirLocation: {
|
|
146
|
+
uri: url,
|
|
147
|
+
locationType: 'UriLocation',
|
|
148
|
+
},
|
|
149
|
+
}
|
|
150
|
+
: {}),
|
|
151
|
+
connectionId: id,
|
|
152
|
+
assemblyNames: assemblyNames
|
|
153
|
+
? assemblyNames.split(',')
|
|
154
|
+
: type === 'JBrowse1Connection'
|
|
155
|
+
? [configContents.assemblies[0]?.name]
|
|
156
|
+
: undefined,
|
|
157
|
+
...(config ? (0, json_parse_better_errors_1.default)(config) : {}),
|
|
158
|
+
};
|
|
159
|
+
if (!configContents.connections) {
|
|
160
|
+
configContents.connections = [];
|
|
161
|
+
}
|
|
162
|
+
const idx = configContents.connections.findIndex(c => c.connectionId === connectionId);
|
|
163
|
+
if (idx !== -1) {
|
|
164
|
+
if (force || flags.overwrite) {
|
|
165
|
+
configContents.connections[idx] = connectionConfig;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
throw new Error(`Cannot add connection with id ${connectionId}, a connection with that id already exists.\nUse --overwrite if you would like to replace the existing connection`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
configContents.connections.push(connectionConfig);
|
|
173
|
+
}
|
|
174
|
+
(0, utils_1.debug)(`Writing configuration to file ${target}`);
|
|
175
|
+
await (0, utils_1.writeJsonFile)(target, configContents);
|
|
176
|
+
console.log(`${idx !== -1 ? 'Overwrote' : 'Added'} connection "${name || id}" ${idx !== -1 ? 'in' : 'to'} ${target}`);
|
|
177
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.run = run;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const util_1 = require("util");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
async function run(args) {
|
|
8
|
+
const options = {
|
|
9
|
+
help: {
|
|
10
|
+
type: 'boolean',
|
|
11
|
+
short: 'h',
|
|
12
|
+
},
|
|
13
|
+
update: {
|
|
14
|
+
type: 'boolean',
|
|
15
|
+
short: 'u',
|
|
16
|
+
description: 'Update the contents of an existing track, matched based on trackId',
|
|
17
|
+
},
|
|
18
|
+
target: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: 'Path to config file in JB2 installation directory to write out to',
|
|
21
|
+
},
|
|
22
|
+
out: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'Synonym for target',
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
const { values: flags, positionals } = (0, util_1.parseArgs)({
|
|
28
|
+
args,
|
|
29
|
+
options,
|
|
30
|
+
allowPositionals: true,
|
|
31
|
+
});
|
|
32
|
+
const description = 'Add a track configuration directly from a JSON hunk to the JBrowse 2 configuration';
|
|
33
|
+
const examples = [
|
|
34
|
+
'$ jbrowse add-track-json track.json',
|
|
35
|
+
'$ jbrowse add-track-json track.json --update',
|
|
36
|
+
];
|
|
37
|
+
if (flags.help) {
|
|
38
|
+
(0, utils_1.printHelp)({
|
|
39
|
+
description,
|
|
40
|
+
examples,
|
|
41
|
+
usage: 'jbrowse add-track-json <track> [options]',
|
|
42
|
+
options,
|
|
43
|
+
});
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const track = positionals[0];
|
|
47
|
+
if (!track) {
|
|
48
|
+
console.error('Error: Missing required argument: track');
|
|
49
|
+
console.error('Usage: jbrowse add-track-json <track> [options]');
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const output = flags.target || flags.out || '.';
|
|
53
|
+
const isDir = (await fs_1.promises.lstat(output)).isDirectory();
|
|
54
|
+
const target = isDir ? `${output}/config.json` : output;
|
|
55
|
+
(0, utils_1.debug)(`Sequence location is: ${track}`);
|
|
56
|
+
const { update } = flags;
|
|
57
|
+
const config = await (0, utils_1.readJsonFile)(target);
|
|
58
|
+
(0, utils_1.debug)(`Found existing config file ${target}`);
|
|
59
|
+
const trackConfig = await (0, utils_1.readInlineOrFileJson)(track);
|
|
60
|
+
if (!config.tracks) {
|
|
61
|
+
config.tracks = [];
|
|
62
|
+
}
|
|
63
|
+
const idx = config.tracks.findIndex(({ trackId }) => trackId === trackConfig.trackId);
|
|
64
|
+
if (idx !== -1) {
|
|
65
|
+
const existing = config.tracks[idx]?.name;
|
|
66
|
+
(0, utils_1.debug)(`Found existing track ${existing} in configuration`);
|
|
67
|
+
if (update) {
|
|
68
|
+
(0, utils_1.debug)(`Overwriting track ${existing} in configuration`);
|
|
69
|
+
config.tracks[idx] = trackConfig;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
throw new Error(`Cannot add track ${trackConfig.name}, a track with that trackId already exists: ${existing}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
config.tracks.push(trackConfig);
|
|
77
|
+
}
|
|
78
|
+
(0, utils_1.debug)(`Writing configuration to file ${target}`);
|
|
79
|
+
await (0, utils_1.writeJsonFile)(target, config);
|
|
80
|
+
console.log(`${idx !== -1 ? 'Overwrote' : 'Added'} track "${trackConfig.name}" ${idx !== -1 ? 'in' : 'to'} ${target}`);
|
|
81
|
+
}
|