@jbrowse/cli 3.6.0 → 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/bin/run +1 -1
- 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/fetchWithProxy.js +12 -0
- package/dist/index.js +119 -0
- package/dist/types/common.js +128 -0
- package/dist/types/gff3Adapter.js +73 -0
- package/dist/types/vcfAdapter.js +76 -0
- package/dist/util.js +35 -0
- package/dist/utils.js +154 -0
- package/package.json +3 -3
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.adapterTypesToTrackTypeMap = void 0;
|
|
4
|
+
exports.makeLocationProtocol = makeLocationProtocol;
|
|
5
|
+
exports.guessFileNames = guessFileNames;
|
|
6
|
+
exports.guessAdapter = guessAdapter;
|
|
7
|
+
exports.guessTrackType = guessTrackType;
|
|
8
|
+
function makeLocationProtocol(protocol) {
|
|
9
|
+
return (location) => {
|
|
10
|
+
if (protocol === 'uri') {
|
|
11
|
+
return {
|
|
12
|
+
uri: location,
|
|
13
|
+
locationType: 'UriLocation',
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (protocol === 'localPath') {
|
|
17
|
+
return {
|
|
18
|
+
localPath: location,
|
|
19
|
+
locationType: 'LocalPathLocation',
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
throw new Error(`invalid protocol ${protocol}`);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function guessFileNames({ location, index, bed1, bed2, }) {
|
|
26
|
+
if (/\.anchors(.simple)?$/i.test(location)) {
|
|
27
|
+
return {
|
|
28
|
+
file: location,
|
|
29
|
+
bed1: bed1,
|
|
30
|
+
bed2: bed2,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
else if (/\.bam$/i.test(location)) {
|
|
34
|
+
return {
|
|
35
|
+
file: location,
|
|
36
|
+
index: index || `${location}.bai`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
else if (/\.cram$/i.test(location)) {
|
|
40
|
+
return {
|
|
41
|
+
file: location,
|
|
42
|
+
index: index || `${location}.crai`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
else if (/\.gff3?\.b?gz$/i.test(location) ||
|
|
46
|
+
/\.vcf\.b?gz$/i.test(location) ||
|
|
47
|
+
/\.bed\.b?gz$/i.test(location) ||
|
|
48
|
+
/\.pif\.b?gz$/i.test(location)) {
|
|
49
|
+
return {
|
|
50
|
+
file: location,
|
|
51
|
+
index: index || `${location}.tbi`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
else if (/\.(fa|fasta|fas|fna|mfa)$/i.test(location)) {
|
|
55
|
+
return {
|
|
56
|
+
file: location,
|
|
57
|
+
index: index || `${location}.fai`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
else if (/\.(fa|fasta|fas|fna|mfa)\.b?gz$/i.test(location)) {
|
|
61
|
+
return {
|
|
62
|
+
file: location,
|
|
63
|
+
index: `${location}.fai`,
|
|
64
|
+
index2: `${location}.gzi`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
else if (/\.2bit$/i.test(location) ||
|
|
68
|
+
/\.bedpe(\.gz)?$/i.test(location) ||
|
|
69
|
+
/\/trackData.jsonz?$/i.test(location) ||
|
|
70
|
+
/\/sparql$/i.test(location) ||
|
|
71
|
+
/\.out(\.gz)?$/i.test(location) ||
|
|
72
|
+
/\.paf(\.gz)?$/i.test(location) ||
|
|
73
|
+
/\.delta(\.gz)?$/i.test(location) ||
|
|
74
|
+
/\.bed?$/i.test(location) ||
|
|
75
|
+
/\.(bw|bigwig)$/i.test(location) ||
|
|
76
|
+
/\.(bb|bigbed)$/i.test(location) ||
|
|
77
|
+
/\.vcf$/i.test(location) ||
|
|
78
|
+
/\.gtf?$/i.test(location) ||
|
|
79
|
+
/\.gff3?$/i.test(location) ||
|
|
80
|
+
/\.chain(\.gz)?$/i.test(location) ||
|
|
81
|
+
/\.hic$/i.test(location)) {
|
|
82
|
+
return {
|
|
83
|
+
file: location,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {};
|
|
87
|
+
}
|
|
88
|
+
function guessAdapter({ location, protocol, index, bed1, bed2, }) {
|
|
89
|
+
const makeLocation = makeLocationProtocol(protocol);
|
|
90
|
+
if (/\.bam$/i.test(location)) {
|
|
91
|
+
return {
|
|
92
|
+
type: 'BamAdapter',
|
|
93
|
+
bamLocation: makeLocation(location),
|
|
94
|
+
index: {
|
|
95
|
+
location: makeLocation(index || `${location}.bai`),
|
|
96
|
+
indexType: index?.toUpperCase().endsWith('CSI') ? 'CSI' : 'BAI',
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
else if (/\.cram$/i.test(location)) {
|
|
101
|
+
return {
|
|
102
|
+
type: 'CramAdapter',
|
|
103
|
+
cramLocation: makeLocation(location),
|
|
104
|
+
craiLocation: makeLocation(`${location}.crai`),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
else if (/\.gff3?$/i.test(location)) {
|
|
108
|
+
return {
|
|
109
|
+
type: 'Gff3Adapter',
|
|
110
|
+
gffLocation: makeLocation(location),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
else if (/\.gff3?\.b?gz$/i.test(location)) {
|
|
114
|
+
return {
|
|
115
|
+
type: 'Gff3TabixAdapter',
|
|
116
|
+
gffGzLocation: makeLocation(location),
|
|
117
|
+
index: {
|
|
118
|
+
location: makeLocation(index || `${location}.tbi`),
|
|
119
|
+
indexType: index?.toUpperCase().endsWith('CSI') ? 'CSI' : 'TBI',
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
else if (/\.gtf?$/i.test(location)) {
|
|
124
|
+
return {
|
|
125
|
+
type: 'GtfAdapter',
|
|
126
|
+
gtfLocation: makeLocation(location),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
else if (/\.vcf$/i.test(location)) {
|
|
130
|
+
return {
|
|
131
|
+
type: 'VcfAdapter',
|
|
132
|
+
vcfLocation: makeLocation(location),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
else if (/\.vcf\.b?gz$/i.test(location)) {
|
|
136
|
+
return {
|
|
137
|
+
type: 'VcfTabixAdapter',
|
|
138
|
+
vcfGzLocation: makeLocation(location),
|
|
139
|
+
index: {
|
|
140
|
+
location: makeLocation(index || `${location}.tbi`),
|
|
141
|
+
indexType: index?.toUpperCase().endsWith('CSI') ? 'CSI' : 'TBI',
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
else if (/\.vcf\.idx$/i.test(location)) {
|
|
146
|
+
return {
|
|
147
|
+
type: 'UNSUPPORTED',
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
else if (/\.bedpe(.gz)?$/i.test(location)) {
|
|
151
|
+
return {
|
|
152
|
+
type: 'BedpeAdapter',
|
|
153
|
+
bedpeLocation: makeLocation(location),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
else if (/\.bed$/i.test(location)) {
|
|
157
|
+
return {
|
|
158
|
+
type: 'BedAdapter',
|
|
159
|
+
bedLocation: makeLocation(location),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
else if (/\.pif\.b?gz$/i.test(location)) {
|
|
163
|
+
return {
|
|
164
|
+
type: 'PairwiseIndexedPAFAdapter',
|
|
165
|
+
pifGzLocation: makeLocation(location),
|
|
166
|
+
index: {
|
|
167
|
+
location: makeLocation(index || `${location}.tbi`),
|
|
168
|
+
indexType: index?.toUpperCase().endsWith('CSI') ? 'CSI' : 'TBI',
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
else if (/\.bed\.b?gz$/i.test(location)) {
|
|
173
|
+
return {
|
|
174
|
+
type: 'BedTabixAdapter',
|
|
175
|
+
bedGzLocation: makeLocation(location),
|
|
176
|
+
index: {
|
|
177
|
+
location: makeLocation(index || `${location}.tbi`),
|
|
178
|
+
indexType: index?.toUpperCase().endsWith('CSI') ? 'CSI' : 'TBI',
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
else if (/\.(bb|bigbed)$/i.test(location)) {
|
|
183
|
+
return {
|
|
184
|
+
type: 'BigBedAdapter',
|
|
185
|
+
bigBedLocation: makeLocation(location),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
else if (/\.(bw|bigwig)$/i.test(location)) {
|
|
189
|
+
return {
|
|
190
|
+
type: 'BigWigAdapter',
|
|
191
|
+
bigWigLocation: makeLocation(location),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
else if (/\.(fa|fasta|fna|mfa)$/i.test(location)) {
|
|
195
|
+
return {
|
|
196
|
+
type: 'IndexedFastaAdapter',
|
|
197
|
+
fastaLocation: makeLocation(location),
|
|
198
|
+
faiLocation: makeLocation(index || `${location}.fai`),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
else if (/\.(fa|fasta|fna|mfa)\.b?gz$/i.test(location)) {
|
|
202
|
+
return {
|
|
203
|
+
type: 'BgzipFastaAdapter',
|
|
204
|
+
fastaLocation: makeLocation(location),
|
|
205
|
+
faiLocation: makeLocation(`${location}.fai`),
|
|
206
|
+
gziLocation: makeLocation(`${location}.gzi`),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
else if (/\.2bit$/i.test(location)) {
|
|
210
|
+
return {
|
|
211
|
+
type: 'TwoBitAdapter',
|
|
212
|
+
twoBitLocation: makeLocation(location),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
else if (/\.sizes$/i.test(location)) {
|
|
216
|
+
return {
|
|
217
|
+
type: 'UNSUPPORTED',
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
else if (/\/trackData.jsonz?$/i.test(location)) {
|
|
221
|
+
return {
|
|
222
|
+
type: 'NCListAdapter',
|
|
223
|
+
rootUrlTemplate: makeLocation(location),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
else if (/\/sparql$/i.test(location)) {
|
|
227
|
+
return {
|
|
228
|
+
type: 'SPARQLAdapter',
|
|
229
|
+
endpoint: location,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
else if (/\.hic$/i.test(location)) {
|
|
233
|
+
return {
|
|
234
|
+
type: 'HicAdapter',
|
|
235
|
+
hicLocation: makeLocation(location),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
else if (/\.paf(.gz)?$/i.test(location)) {
|
|
239
|
+
return {
|
|
240
|
+
type: 'PAFAdapter',
|
|
241
|
+
pafLocation: makeLocation(location),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
else if (/\.out(.gz)?$/i.test(location)) {
|
|
245
|
+
return {
|
|
246
|
+
type: 'MashMapAdapter',
|
|
247
|
+
outLocation: makeLocation(location),
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
else if (/\.chain(.gz)?$/i.test(location)) {
|
|
251
|
+
return {
|
|
252
|
+
type: 'ChainAdapter',
|
|
253
|
+
chainLocation: makeLocation(location),
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
else if (/\.delta(.gz)?$/i.test(location)) {
|
|
257
|
+
return {
|
|
258
|
+
type: 'DeltaAdapter',
|
|
259
|
+
deltaLocation: makeLocation(location),
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
else if (/\.anchors(.gz)?$/i.test(location)) {
|
|
263
|
+
return {
|
|
264
|
+
type: 'MCScanAnchorsAdapter',
|
|
265
|
+
mcscanAnchorsLocation: makeLocation(location),
|
|
266
|
+
bed1Location: bed1 ? makeLocation(bed1) : undefined,
|
|
267
|
+
bed2Location: bed2 ? makeLocation(bed2) : undefined,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
else if (/\.anchors.simple(.gz)?$/i.test(location)) {
|
|
271
|
+
return {
|
|
272
|
+
type: 'MCScanSimpleAnchorsAdapter',
|
|
273
|
+
mcscanSimpleAnchorsLocation: makeLocation(location),
|
|
274
|
+
bed1Location: bed1 ? makeLocation(bed1) : undefined,
|
|
275
|
+
bed2Location: bed2 ? makeLocation(bed2) : undefined,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
type: 'UNKNOWN',
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
exports.adapterTypesToTrackTypeMap = {
|
|
283
|
+
BamAdapter: 'AlignmentsTrack',
|
|
284
|
+
CramAdapter: 'AlignmentsTrack',
|
|
285
|
+
BgzipFastaAdapter: 'ReferenceSequenceTrack',
|
|
286
|
+
BigWigAdapter: 'QuantitativeTrack',
|
|
287
|
+
IndexedFastaAdapter: 'ReferenceSequenceTrack',
|
|
288
|
+
TwoBitAdapter: 'ReferenceSequenceTrack',
|
|
289
|
+
VcfTabixAdapter: 'VariantTrack',
|
|
290
|
+
VcfAdapter: 'VariantTrack',
|
|
291
|
+
BedpeAdapter: 'VariantTrack',
|
|
292
|
+
BedAdapter: 'FeatureTrack',
|
|
293
|
+
HicAdapter: 'HicTrack',
|
|
294
|
+
PAFAdapter: 'SyntenyTrack',
|
|
295
|
+
DeltaAdapter: 'SyntenyTrack',
|
|
296
|
+
ChainAdapter: 'SyntenyTrack',
|
|
297
|
+
MashMapAdapter: 'SyntenyTrack',
|
|
298
|
+
PairwiseIndexedPAFAdapter: 'SyntenyTrack',
|
|
299
|
+
MCScanAnchorsAdapter: 'SyntenyTrack',
|
|
300
|
+
MCScanSimpleAnchorsAdapter: 'SyntenyTrack',
|
|
301
|
+
};
|
|
302
|
+
function guessTrackType(adapterType) {
|
|
303
|
+
return exports.adapterTypesToTrackTypeMap[adapterType] || 'FeatureTrack';
|
|
304
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
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.loadFile = loadFile;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const { copyFile, rename, symlink, unlink } = fs_1.default.promises;
|
|
10
|
+
const { COPYFILE_EXCL } = fs_1.default.constants;
|
|
11
|
+
async function loadFile({ src, destDir, mode, subDir = '', force = false, }) {
|
|
12
|
+
if (mode === 'inPlace') {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const dest = path_1.default.join(destDir, subDir, path_1.default.basename(src));
|
|
16
|
+
if (force) {
|
|
17
|
+
try {
|
|
18
|
+
await unlink(dest);
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
if (e.code !== 'ENOENT') {
|
|
22
|
+
throw e;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (mode === 'copy') {
|
|
27
|
+
return copyFile(src, dest, force ? 0 : COPYFILE_EXCL);
|
|
28
|
+
}
|
|
29
|
+
if (mode === 'move') {
|
|
30
|
+
return rename(src, dest);
|
|
31
|
+
}
|
|
32
|
+
if (mode === 'symlink') {
|
|
33
|
+
return symlink(path_1.default.resolve(src), dest);
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
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.mapLocationForFiles = mapLocationForFiles;
|
|
7
|
+
exports.buildTrackConfig = buildTrackConfig;
|
|
8
|
+
exports.addSyntenyAssemblyNames = addSyntenyAssemblyNames;
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const json_parse_better_errors_1 = __importDefault(require("json-parse-better-errors"));
|
|
11
|
+
const validators_1 = require("./validators");
|
|
12
|
+
const SYNTENY_ADAPTERS = new Set([
|
|
13
|
+
'PAFAdapter',
|
|
14
|
+
'PairwiseIndexedPAFAdapter',
|
|
15
|
+
'DeltaAdapter',
|
|
16
|
+
'ChainAdapter',
|
|
17
|
+
'MashMapAdapter',
|
|
18
|
+
'MCScanAnchorsAdapter',
|
|
19
|
+
'MCScanSimpleAnchorsAdapter',
|
|
20
|
+
]);
|
|
21
|
+
function mapLocationForFiles(p, load, subDir) {
|
|
22
|
+
return !p || (0, validators_1.isUrl)(p) || load === 'inPlace'
|
|
23
|
+
? p
|
|
24
|
+
: path_1.default.join(subDir || '', path_1.default.basename(p));
|
|
25
|
+
}
|
|
26
|
+
function buildTrackConfig({ location, trackType, trackId, name, assemblyNames, category, description, config, adapter, configContents, skipCheck, }) {
|
|
27
|
+
const configObj = config ? (0, json_parse_better_errors_1.default)(config) : {};
|
|
28
|
+
const finalTrackId = trackId || path_1.default.basename(location, path_1.default.extname(location));
|
|
29
|
+
const finalName = name || finalTrackId;
|
|
30
|
+
const finalAssemblyNames = assemblyNames || configContents.assemblies?.[0]?.name || '';
|
|
31
|
+
const trackConfig = {
|
|
32
|
+
type: trackType,
|
|
33
|
+
trackId: finalTrackId,
|
|
34
|
+
name: finalName,
|
|
35
|
+
adapter,
|
|
36
|
+
category: category?.split(',').map(c => c.trim()),
|
|
37
|
+
assemblyNames: finalAssemblyNames.split(',').map(a => a.trim()),
|
|
38
|
+
description,
|
|
39
|
+
...configObj,
|
|
40
|
+
};
|
|
41
|
+
// Special handling for AlignmentsTrack
|
|
42
|
+
if (trackType === 'AlignmentsTrack') {
|
|
43
|
+
const assembly = configContents.assemblies?.find(asm => asm.name === finalAssemblyNames);
|
|
44
|
+
if (assembly) {
|
|
45
|
+
// @ts-expect-error
|
|
46
|
+
trackConfig.adapter.sequenceAdapter = assembly.sequence.adapter;
|
|
47
|
+
}
|
|
48
|
+
else if (!skipCheck) {
|
|
49
|
+
console.error(`Error: Failed to find assemblyName ${finalAssemblyNames}`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return trackConfig;
|
|
54
|
+
}
|
|
55
|
+
function addSyntenyAssemblyNames(adapter, assemblyNames) {
|
|
56
|
+
if (SYNTENY_ADAPTERS.has(adapter.type)) {
|
|
57
|
+
return {
|
|
58
|
+
...adapter,
|
|
59
|
+
assemblyNames: assemblyNames?.split(',').map(a => a.trim()),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return adapter;
|
|
63
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
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.isUrl = void 0;
|
|
7
|
+
exports.validateLoadOption = validateLoadOption;
|
|
8
|
+
exports.validateTrackArg = validateTrackArg;
|
|
9
|
+
exports.validateLoadAndLocation = validateLoadAndLocation;
|
|
10
|
+
exports.validateAdapterType = validateAdapterType;
|
|
11
|
+
exports.validateAssemblies = validateAssemblies;
|
|
12
|
+
exports.validateTrackId = validateTrackId;
|
|
13
|
+
exports.createTargetDirectory = createTargetDirectory;
|
|
14
|
+
const fs_1 = __importDefault(require("fs"));
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const isUrl = (loc) => loc?.match(/^https?:\/\//);
|
|
17
|
+
exports.isUrl = isUrl;
|
|
18
|
+
function validateLoadOption(load) {
|
|
19
|
+
if (load && !['copy', 'symlink', 'move', 'inPlace'].includes(load)) {
|
|
20
|
+
throw new Error('Error: --load must be one of: copy, symlink, move, inPlace');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function validateTrackArg(track) {
|
|
24
|
+
if (!track) {
|
|
25
|
+
console.error('Missing 1 required arg:');
|
|
26
|
+
console.error('track Track file or URL');
|
|
27
|
+
console.error('See more help with --help');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function validateLoadAndLocation(location, load) {
|
|
32
|
+
if (isUrl(location) && load) {
|
|
33
|
+
throw new Error('The --load flag is used for local files only, but a URL was provided');
|
|
34
|
+
}
|
|
35
|
+
else if (!isUrl(location) && !load) {
|
|
36
|
+
throw new Error(`The --load flag should be used if a local file is used, example --load
|
|
37
|
+
copy to copy the file into the config directory. Options for load are
|
|
38
|
+
copy/move/symlink/inPlace (inPlace for no file operations)`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function validateAdapterType(adapterType) {
|
|
42
|
+
if (adapterType === 'UNKNOWN') {
|
|
43
|
+
throw new Error('Track type is not recognized');
|
|
44
|
+
}
|
|
45
|
+
if (adapterType === 'UNSUPPORTED') {
|
|
46
|
+
throw new Error('Track type is not supported');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function validateAssemblies(configContents, assemblyNames) {
|
|
50
|
+
if (!configContents.assemblies?.length) {
|
|
51
|
+
throw new Error('No assemblies found. Please add one before adding tracks');
|
|
52
|
+
}
|
|
53
|
+
if (configContents.assemblies.length > 1 && !assemblyNames) {
|
|
54
|
+
throw new Error('Too many assemblies, cannot default to one. Please specify the assembly with the --assemblyNames flag');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function validateTrackId(configContents, trackId, force, overwrite) {
|
|
58
|
+
if (!configContents.tracks) {
|
|
59
|
+
configContents.tracks = [];
|
|
60
|
+
}
|
|
61
|
+
const idx = configContents.tracks.findIndex(c => c.trackId === trackId);
|
|
62
|
+
if (idx !== -1 && !force && !overwrite) {
|
|
63
|
+
throw new Error(`Cannot add track with id ${trackId}, a track with that id already exists (use --force to override)`);
|
|
64
|
+
}
|
|
65
|
+
return idx;
|
|
66
|
+
}
|
|
67
|
+
function createTargetDirectory(configDir, subDir) {
|
|
68
|
+
if (subDir) {
|
|
69
|
+
const dir = path_1.default.join(configDir, subDir);
|
|
70
|
+
if (!fs_1.default.existsSync(dir)) {
|
|
71
|
+
fs_1.default.mkdirSync(dir);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
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 path_1 = __importDefault(require("path"));
|
|
8
|
+
const util_1 = require("util");
|
|
9
|
+
const utils_1 = require("../utils");
|
|
10
|
+
const adapter_utils_1 = require("./add-track-utils/adapter-utils");
|
|
11
|
+
const track_config_1 = require("./add-track-utils/track-config");
|
|
12
|
+
const validators_1 = require("./add-track-utils/validators");
|
|
13
|
+
const track_utils_1 = require("./track-utils");
|
|
14
|
+
async function run(args) {
|
|
15
|
+
const options = {
|
|
16
|
+
help: {
|
|
17
|
+
type: 'boolean',
|
|
18
|
+
short: 'h',
|
|
19
|
+
},
|
|
20
|
+
trackType: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
short: 't',
|
|
23
|
+
description: 'Type of track, by default inferred from track file',
|
|
24
|
+
},
|
|
25
|
+
name: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
short: 'n',
|
|
28
|
+
description: 'Name of the track. Will be defaulted to the trackId if none specified',
|
|
29
|
+
},
|
|
30
|
+
indexFile: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
description: 'Optional index file for the track',
|
|
33
|
+
},
|
|
34
|
+
description: {
|
|
35
|
+
type: 'string',
|
|
36
|
+
short: 'd',
|
|
37
|
+
description: 'Optional description of the track',
|
|
38
|
+
},
|
|
39
|
+
assemblyNames: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
short: 'a',
|
|
42
|
+
description: 'Assembly name or names for track as comma separated string',
|
|
43
|
+
},
|
|
44
|
+
category: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
description: 'Optional comma separated string of categories to group tracks',
|
|
47
|
+
},
|
|
48
|
+
config: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
description: 'Any extra config settings to add to a track',
|
|
51
|
+
},
|
|
52
|
+
target: {
|
|
53
|
+
type: 'string',
|
|
54
|
+
description: 'Path to config file in JB2 installation to write out to',
|
|
55
|
+
},
|
|
56
|
+
out: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'Synonym for target',
|
|
59
|
+
},
|
|
60
|
+
subDir: {
|
|
61
|
+
type: 'string',
|
|
62
|
+
description: 'When using --load a file, output to a subdirectory of the target dir',
|
|
63
|
+
},
|
|
64
|
+
trackId: {
|
|
65
|
+
type: 'string',
|
|
66
|
+
description: 'trackId for the track, by default inferred from filename',
|
|
67
|
+
},
|
|
68
|
+
load: {
|
|
69
|
+
type: 'string',
|
|
70
|
+
short: 'l',
|
|
71
|
+
description: 'How to manage the track (copy, symlink, move, inPlace)',
|
|
72
|
+
},
|
|
73
|
+
skipCheck: {
|
|
74
|
+
type: 'boolean',
|
|
75
|
+
description: 'Skip check for whether file or URL exists',
|
|
76
|
+
},
|
|
77
|
+
overwrite: {
|
|
78
|
+
type: 'boolean',
|
|
79
|
+
description: 'Overwrites existing track if it shares the same trackId',
|
|
80
|
+
},
|
|
81
|
+
force: {
|
|
82
|
+
type: 'boolean',
|
|
83
|
+
short: 'f',
|
|
84
|
+
description: 'Equivalent to --skipCheck --overwrite',
|
|
85
|
+
},
|
|
86
|
+
protocol: {
|
|
87
|
+
type: 'string',
|
|
88
|
+
description: 'Force protocol to a specific value',
|
|
89
|
+
},
|
|
90
|
+
bed1: {
|
|
91
|
+
type: 'string',
|
|
92
|
+
description: 'Used only for mcscan anchors/simpleAnchors types',
|
|
93
|
+
},
|
|
94
|
+
bed2: {
|
|
95
|
+
type: 'string',
|
|
96
|
+
description: 'Used only for mcscan anchors/simpleAnchors types',
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
const { values: flags, positionals } = (0, util_1.parseArgs)({
|
|
100
|
+
args,
|
|
101
|
+
options,
|
|
102
|
+
allowPositionals: true,
|
|
103
|
+
});
|
|
104
|
+
const description = 'Add a track to a JBrowse 2 configuration';
|
|
105
|
+
const examples = [
|
|
106
|
+
'# copy /path/to/my.bam and /path/to/my.bam.bai to current directory and adds track to config.json',
|
|
107
|
+
'$ jbrowse add-track /path/to/my.bam --load copy',
|
|
108
|
+
'',
|
|
109
|
+
'# copy my.bam and my.bam.bai to /path/to/jb2/bam and adds track entry to /path/to/jb2/bam/config.json',
|
|
110
|
+
'$ jbrowse add-track my.bam --load copy --out /path/to/jb2 --subDir bam',
|
|
111
|
+
'',
|
|
112
|
+
'# same as above, but specify path to bai file. needed for if the bai file does not have the extension .bam.bai',
|
|
113
|
+
'$ jbrowse add-track my.bam --indexFile my.bai --load copy',
|
|
114
|
+
'',
|
|
115
|
+
'# creates symlink for /path/to/my.bam and adds track to config.json',
|
|
116
|
+
'$ jbrowse add-track /path/to/my.bam --load symlink',
|
|
117
|
+
'',
|
|
118
|
+
'# add track from URL to config.json, no --load flag needed',
|
|
119
|
+
'$ jbrowse add-track https://mywebsite.com/my.bam',
|
|
120
|
+
'',
|
|
121
|
+
'# --load inPlace adds a track without doing file operations',
|
|
122
|
+
'$ jbrowse add-track /url/relative/path.bam --load inPlace',
|
|
123
|
+
];
|
|
124
|
+
if (flags.help) {
|
|
125
|
+
(0, utils_1.printHelp)({
|
|
126
|
+
description,
|
|
127
|
+
examples,
|
|
128
|
+
usage: 'jbrowse add-track <track> [options]',
|
|
129
|
+
options,
|
|
130
|
+
});
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
(0, validators_1.validateLoadOption)(flags.load);
|
|
134
|
+
const track = positionals[0];
|
|
135
|
+
(0, validators_1.validateTrackArg)(track);
|
|
136
|
+
const { config, skipCheck, force, overwrite, category, description: trackDescription, load, subDir = '', target, protocol = 'uri', out, indexFile: index, bed1, bed2, } = flags;
|
|
137
|
+
const output = target || out || '.';
|
|
138
|
+
const targetConfigPath = (0, track_utils_1.resolveTrackConfigPath)(output);
|
|
139
|
+
const configDir = path_1.default.dirname(targetConfigPath);
|
|
140
|
+
(0, validators_1.createTargetDirectory)(configDir, subDir);
|
|
141
|
+
const location = track;
|
|
142
|
+
const mapLoc = (p) => (0, track_config_1.mapLocationForFiles)(p, load, subDir);
|
|
143
|
+
let adapter = (0, adapter_utils_1.guessAdapter)({
|
|
144
|
+
protocol,
|
|
145
|
+
location: mapLoc(location),
|
|
146
|
+
index: index ? mapLoc(index) : undefined,
|
|
147
|
+
bed1: bed1 ? mapLoc(bed1) : undefined,
|
|
148
|
+
bed2: bed2 ? mapLoc(bed2) : undefined,
|
|
149
|
+
});
|
|
150
|
+
adapter = (0, track_config_1.addSyntenyAssemblyNames)(adapter, flags.assemblyNames);
|
|
151
|
+
(0, validators_1.validateLoadAndLocation)(location, load);
|
|
152
|
+
(0, validators_1.validateAdapterType)(adapter.type);
|
|
153
|
+
const configContents = await (0, track_utils_1.loadTrackConfig)(targetConfigPath);
|
|
154
|
+
(0, validators_1.validateAssemblies)(configContents, flags.assemblyNames);
|
|
155
|
+
const trackParams = (0, track_utils_1.buildTrackParams)({
|
|
156
|
+
flags,
|
|
157
|
+
location,
|
|
158
|
+
adapter,
|
|
159
|
+
configContents,
|
|
160
|
+
});
|
|
161
|
+
const trackConfig = (0, track_utils_1.createTrackConfiguration)({
|
|
162
|
+
location,
|
|
163
|
+
trackParams,
|
|
164
|
+
flags: { category, description: trackDescription, config },
|
|
165
|
+
adapter,
|
|
166
|
+
configContents,
|
|
167
|
+
skipCheck,
|
|
168
|
+
});
|
|
169
|
+
const { updatedConfig, wasOverwritten } = (0, track_utils_1.addTrackToConfig)({
|
|
170
|
+
configContents,
|
|
171
|
+
trackConfig,
|
|
172
|
+
trackId: trackParams.trackId,
|
|
173
|
+
force,
|
|
174
|
+
overwrite,
|
|
175
|
+
});
|
|
176
|
+
await (0, track_utils_1.processTrackFiles)({
|
|
177
|
+
location,
|
|
178
|
+
index,
|
|
179
|
+
bed1,
|
|
180
|
+
bed2,
|
|
181
|
+
load,
|
|
182
|
+
configDir,
|
|
183
|
+
subDir,
|
|
184
|
+
force,
|
|
185
|
+
});
|
|
186
|
+
await (0, track_utils_1.saveTrackConfigAndReport)({
|
|
187
|
+
config: updatedConfig,
|
|
188
|
+
targetConfigPath,
|
|
189
|
+
name: trackParams.name,
|
|
190
|
+
trackId: trackParams.trackId,
|
|
191
|
+
wasOverwritten,
|
|
192
|
+
});
|
|
193
|
+
}
|