@jbrowse/cli 4.0.4 → 4.1.3
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 +269 -111
- package/bin/run +2 -1
- package/bundle/index.js +289 -538
- package/dist/base.js +1 -2
- package/dist/bin.js +2 -4
- package/dist/cliFetch.js +3 -0
- package/dist/commands/add-assembly/index.js +19 -22
- package/dist/commands/add-assembly/utils.js +75 -92
- package/dist/commands/add-connection.js +16 -22
- package/dist/commands/add-track-json.js +13 -16
- package/dist/commands/add-track-utils/adapter-utils.js +6 -13
- package/dist/commands/add-track-utils/file-operations.js +8 -14
- package/dist/commands/add-track-utils/track-config.js +10 -18
- package/dist/commands/add-track-utils/validators.js +15 -27
- package/dist/commands/add-track.js +27 -33
- package/dist/commands/admin-server/index.js +24 -30
- package/dist/commands/admin-server/utils.js +27 -38
- package/dist/commands/create.js +16 -22
- package/dist/commands/make-pif/cigar-utils.js +3 -8
- package/dist/commands/make-pif/file-utils.js +10 -18
- package/dist/commands/make-pif/index.js +13 -16
- package/dist/commands/make-pif/pif-generator.js +14 -23
- package/dist/commands/process-utils.js +1 -4
- package/dist/commands/remove-track.js +8 -11
- package/dist/commands/set-default-session.js +13 -19
- package/dist/commands/shared/config-operations.js +7 -11
- package/dist/commands/shared/sort-utils.js +7 -14
- package/dist/commands/shared/validators.js +4 -8
- package/dist/commands/sort-bed.js +14 -17
- package/dist/commands/sort-gff.js +14 -17
- package/dist/commands/text-index/adapter-utils.js +5 -10
- package/dist/commands/text-index/aggregate.js +12 -15
- package/dist/commands/text-index/command.js +9 -12
- package/dist/commands/text-index/config-utils.js +24 -38
- package/dist/commands/text-index/file-list.js +11 -17
- package/dist/commands/text-index/index.js +4 -11
- package/dist/commands/text-index/indexing-utils.js +59 -43
- package/dist/commands/text-index/per-track.js +13 -16
- package/dist/commands/text-index/validators.js +3 -8
- package/dist/commands/track-utils.js +22 -33
- package/dist/commands/upgrade.js +20 -26
- package/dist/index.js +31 -39
- package/dist/types/common.js +5 -107
- package/dist/util.js +13 -20
- package/dist/utils.js +82 -58
- package/dist/version.js +1 -0
- package/package.json +7 -6
- package/dist/fetchWithProxy.js +0 -12
- package/dist/types/gff3Adapter.js +0 -42
- package/dist/types/streamUtils.js +0 -66
- package/dist/types/vcfAdapter.js +0 -39
package/dist/base.js
CHANGED
package/dist/bin.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const index_ts_1 = require("./index.js");
|
|
5
|
-
(0, index_ts_1.main)(process.argv.slice(2)).catch((e) => {
|
|
2
|
+
import { main } from "./index.js";
|
|
3
|
+
main(process.argv.slice(2)).catch((e) => {
|
|
6
4
|
console.error(e);
|
|
7
5
|
});
|
package/dist/cliFetch.js
ADDED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const utils_ts_1 = require("./utils.js");
|
|
6
|
-
const utils_ts_2 = require("../../utils.js");
|
|
7
|
-
async function run(args) {
|
|
1
|
+
import { parseArgs } from 'util';
|
|
2
|
+
import { addAssemblyToConfig, enhanceAssembly, getAssembly, loadOrCreateConfig, resolveTargetPath, saveConfigAndReport, } from "./utils.js";
|
|
3
|
+
import { debug, printHelp } from "../../utils.js";
|
|
4
|
+
export async function run(args) {
|
|
8
5
|
const options = {
|
|
9
6
|
type: {
|
|
10
7
|
type: 'string',
|
|
11
8
|
short: 't',
|
|
12
|
-
description: `type of sequence, by default inferred from sequence file\n\nindexedFasta
|
|
9
|
+
description: `type of sequence, by default inferred from sequence file\n\nindexedFasta - An index FASTA (e.g. .fa or .fasta) file; can optionally specify --faiLocation\n\nbgzipFasta - A block-gzipped and indexed FASTA (e.g. .fa.gz or .fasta.gz) file; 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 sequence adapter; must provide --name if using inline JSON`,
|
|
13
10
|
choices: ['indexedFasta', 'bgzipFasta', 'twoBit', 'chromSizes', 'custom'],
|
|
14
11
|
},
|
|
15
12
|
name: {
|
|
@@ -20,7 +17,7 @@ async function run(args) {
|
|
|
20
17
|
alias: {
|
|
21
18
|
type: 'string',
|
|
22
19
|
short: 'a',
|
|
23
|
-
description: 'An alias for the assembly name (e.g. "hg38" if the name of the assembly is "GRCh38")
|
|
20
|
+
description: 'An alias for the assembly name (e.g. "hg38" if the name of the assembly is "GRCh38"); can be specified multiple times',
|
|
24
21
|
multiple: true,
|
|
25
22
|
},
|
|
26
23
|
displayName: {
|
|
@@ -37,21 +34,21 @@ async function run(args) {
|
|
|
37
34
|
},
|
|
38
35
|
refNameAliases: {
|
|
39
36
|
type: 'string',
|
|
40
|
-
description: 'Reference sequence name aliases file or URL; assumed to be a tab-separated aliases
|
|
37
|
+
description: 'Reference sequence name aliases file or URL; assumed to be a tab-separated aliases file unless --refNameAliasesType is specified',
|
|
41
38
|
},
|
|
42
39
|
refNameAliasesType: {
|
|
43
40
|
type: 'string',
|
|
44
|
-
description: 'Type of aliases defined by --refNameAliases; if "custom", --refNameAliases is either
|
|
41
|
+
description: 'Type of aliases defined by --refNameAliases; if "custom", --refNameAliases is either a JSON file location or inline JSON that defines a custom sequence adapter',
|
|
45
42
|
choices: ['aliases', 'custom'],
|
|
46
43
|
dependsOn: ['refNameAliases'],
|
|
47
44
|
},
|
|
48
45
|
refNameColors: {
|
|
49
46
|
type: 'string',
|
|
50
|
-
description: 'A comma-separated list of color strings for the reference sequence names; will cycle
|
|
47
|
+
description: 'A comma-separated list of color strings for the reference sequence names; will cycle through colors if there are fewer colors than sequences',
|
|
51
48
|
},
|
|
52
49
|
target: {
|
|
53
50
|
type: 'string',
|
|
54
|
-
description: 'path to config file in JB2 installation directory to write out to
|
|
51
|
+
description: 'path to config file in JB2 installation directory to write out to. Creates ./config.json if nonexistent',
|
|
55
52
|
},
|
|
56
53
|
out: {
|
|
57
54
|
type: 'string',
|
|
@@ -82,7 +79,7 @@ async function run(args) {
|
|
|
82
79
|
description: 'Equivalent to `--skipCheck --overwrite`',
|
|
83
80
|
},
|
|
84
81
|
};
|
|
85
|
-
const { positionals, values: runFlags } =
|
|
82
|
+
const { positionals, values: runFlags } = parseArgs({
|
|
86
83
|
args,
|
|
87
84
|
options,
|
|
88
85
|
allowPositionals: true,
|
|
@@ -114,7 +111,7 @@ async function run(args) {
|
|
|
114
111
|
'$ jbrowse add-assembly myfile.fa.gz --load copy',
|
|
115
112
|
];
|
|
116
113
|
if (runFlags.help) {
|
|
117
|
-
|
|
114
|
+
printHelp({
|
|
118
115
|
description,
|
|
119
116
|
examples,
|
|
120
117
|
usage: 'jbrowse add-assembly <sequence> [options]',
|
|
@@ -124,17 +121,17 @@ async function run(args) {
|
|
|
124
121
|
}
|
|
125
122
|
const argsSequence = positionals[0] || '';
|
|
126
123
|
const output = runFlags.target || runFlags.out || '.';
|
|
127
|
-
|
|
128
|
-
const target = await
|
|
129
|
-
const baseAssembly = await
|
|
130
|
-
const assembly = await
|
|
131
|
-
const configContents = await
|
|
132
|
-
const { config: updatedConfig, wasOverwritten } = await
|
|
124
|
+
debug(`Sequence location is: ${argsSequence}`);
|
|
125
|
+
const target = await resolveTargetPath(output);
|
|
126
|
+
const baseAssembly = await getAssembly({ runFlags, argsSequence, target });
|
|
127
|
+
const assembly = await enhanceAssembly(baseAssembly, runFlags);
|
|
128
|
+
const configContents = await loadOrCreateConfig(target);
|
|
129
|
+
const { config: updatedConfig, wasOverwritten } = await addAssemblyToConfig({
|
|
133
130
|
config: configContents,
|
|
134
131
|
assembly,
|
|
135
132
|
runFlags,
|
|
136
133
|
});
|
|
137
|
-
await
|
|
134
|
+
await saveConfigAndReport({
|
|
138
135
|
config: updatedConfig,
|
|
139
136
|
target,
|
|
140
137
|
assembly,
|
|
@@ -1,27 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
exports.needLoadData = needLoadData;
|
|
9
|
-
exports.loadData = loadData;
|
|
10
|
-
exports.getAssembly = getAssembly;
|
|
11
|
-
exports.exists = exists;
|
|
12
|
-
exports.resolveTargetPath = resolveTargetPath;
|
|
13
|
-
exports.enhanceAssembly = enhanceAssembly;
|
|
14
|
-
exports.createDefaultConfig = createDefaultConfig;
|
|
15
|
-
exports.loadOrCreateConfig = loadOrCreateConfig;
|
|
16
|
-
exports.addAssemblyToConfig = addAssemblyToConfig;
|
|
17
|
-
exports.saveConfigAndReport = saveConfigAndReport;
|
|
18
|
-
const fs_1 = __importDefault(require("fs"));
|
|
19
|
-
const path_1 = __importDefault(require("path"));
|
|
20
|
-
const common_ts_1 = require("../../types/common.js");
|
|
21
|
-
const utils_ts_1 = require("../../utils.js");
|
|
22
|
-
const config_operations_ts_1 = require("../shared/config-operations.js");
|
|
23
|
-
const { rename, copyFile, symlink } = fs_1.default.promises;
|
|
24
|
-
function isValidJSON(string) {
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { isURL } from "../../types/common.js";
|
|
4
|
+
import { debug, readInlineOrFileJson, readJsonFile, resolveFileLocation, } from "../../utils.js";
|
|
5
|
+
import { findAndUpdateOrAdd, saveConfigAndReport as saveConfigAndReportBase, } from "../shared/config-operations.js";
|
|
6
|
+
const { rename, copyFile, symlink } = fs.promises;
|
|
7
|
+
export function isValidJSON(string) {
|
|
25
8
|
try {
|
|
26
9
|
JSON.parse(string);
|
|
27
10
|
return true;
|
|
@@ -30,7 +13,7 @@ function isValidJSON(string) {
|
|
|
30
13
|
return false;
|
|
31
14
|
}
|
|
32
15
|
}
|
|
33
|
-
function guessSequenceType(sequence) {
|
|
16
|
+
export function guessSequenceType(sequence) {
|
|
34
17
|
if (sequence.endsWith('.fa') ||
|
|
35
18
|
sequence.endsWith('.fna') ||
|
|
36
19
|
sequence.endsWith('.fasta')) {
|
|
@@ -55,31 +38,31 @@ function guessSequenceType(sequence) {
|
|
|
55
38
|
}
|
|
56
39
|
throw new Error('Could not determine sequence type automatically, add --type to specify it');
|
|
57
40
|
}
|
|
58
|
-
function needLoadData(location) {
|
|
59
|
-
return !
|
|
41
|
+
export function needLoadData(location) {
|
|
42
|
+
return !isURL(location);
|
|
60
43
|
}
|
|
61
|
-
async function loadData({ load, filePaths, destination, }) {
|
|
62
|
-
if (
|
|
44
|
+
export async function loadData({ load, filePaths, destination, }) {
|
|
45
|
+
if (isURL(filePaths[0])) {
|
|
63
46
|
return false;
|
|
64
47
|
}
|
|
65
48
|
if (load === 'inPlace') {
|
|
66
49
|
return false;
|
|
67
50
|
}
|
|
68
|
-
const destDir =
|
|
51
|
+
const destDir = path.dirname(destination);
|
|
69
52
|
const validPaths = filePaths.filter(f => !!f);
|
|
70
53
|
const operations = {
|
|
71
54
|
copy: copyFile,
|
|
72
|
-
symlink: (src, dest) => symlink(
|
|
55
|
+
symlink: (src, dest) => symlink(path.resolve(src), dest),
|
|
73
56
|
move: rename,
|
|
74
57
|
};
|
|
75
58
|
const operation = operations[load];
|
|
76
59
|
if (operation) {
|
|
77
|
-
await Promise.all(validPaths.map(filePath => operation(filePath,
|
|
60
|
+
await Promise.all(validPaths.map(filePath => operation(filePath, path.join(destDir, path.basename(filePath)))));
|
|
78
61
|
return true;
|
|
79
62
|
}
|
|
80
63
|
return false;
|
|
81
64
|
}
|
|
82
|
-
async function getAssembly({ runFlags, argsSequence, target, }) {
|
|
65
|
+
export async function getAssembly({ runFlags, argsSequence, target, }) {
|
|
83
66
|
let sequence;
|
|
84
67
|
if (needLoadData(argsSequence) && !runFlags.load) {
|
|
85
68
|
throw new Error('Please specify the loading operation for this file with --load copy|symlink|move|inPlace');
|
|
@@ -90,25 +73,25 @@ async function getAssembly({ runFlags, argsSequence, target, }) {
|
|
|
90
73
|
let { name } = runFlags;
|
|
91
74
|
let { type } = runFlags;
|
|
92
75
|
if (type) {
|
|
93
|
-
|
|
76
|
+
debug(`Type is: ${type}`);
|
|
94
77
|
}
|
|
95
78
|
else {
|
|
96
79
|
type = guessSequenceType(argsSequence);
|
|
97
|
-
|
|
80
|
+
debug(`No type specified, guessing type: ${type}`);
|
|
98
81
|
}
|
|
99
82
|
if (name) {
|
|
100
|
-
|
|
83
|
+
debug(`Name is: ${name}`);
|
|
101
84
|
}
|
|
102
85
|
switch (type) {
|
|
103
86
|
case 'indexedFasta': {
|
|
104
87
|
const { skipCheck, force, load, faiLocation } = runFlags;
|
|
105
|
-
let sequenceLocation = await
|
|
106
|
-
|
|
107
|
-
let indexLocation = await
|
|
108
|
-
|
|
88
|
+
let sequenceLocation = await resolveFileLocation(argsSequence, !(skipCheck || force), load === 'inPlace');
|
|
89
|
+
debug(`FASTA location resolved to: ${sequenceLocation}`);
|
|
90
|
+
let indexLocation = await resolveFileLocation(faiLocation || `${argsSequence}.fai`, !(skipCheck || force), load === 'inPlace');
|
|
91
|
+
debug(`FASTA index location resolved to: ${indexLocation}`);
|
|
109
92
|
if (!name) {
|
|
110
|
-
name =
|
|
111
|
-
|
|
93
|
+
name = path.basename(sequenceLocation, sequenceLocation.endsWith('.fasta') ? '.fasta' : '.fa');
|
|
94
|
+
debug(`Guessing name: ${name}`);
|
|
112
95
|
}
|
|
113
96
|
const loaded = load
|
|
114
97
|
? await loadData({
|
|
@@ -118,8 +101,8 @@ async function getAssembly({ runFlags, argsSequence, target, }) {
|
|
|
118
101
|
})
|
|
119
102
|
: false;
|
|
120
103
|
if (loaded) {
|
|
121
|
-
sequenceLocation =
|
|
122
|
-
indexLocation =
|
|
104
|
+
sequenceLocation = path.basename(sequenceLocation);
|
|
105
|
+
indexLocation = path.basename(indexLocation);
|
|
123
106
|
}
|
|
124
107
|
sequence = {
|
|
125
108
|
type: 'ReferenceSequenceTrack',
|
|
@@ -136,15 +119,15 @@ async function getAssembly({ runFlags, argsSequence, target, }) {
|
|
|
136
119
|
break;
|
|
137
120
|
}
|
|
138
121
|
case 'bgzipFasta': {
|
|
139
|
-
let sequenceLocation = await
|
|
140
|
-
|
|
141
|
-
let indexLocation = await
|
|
142
|
-
|
|
143
|
-
let bgzipIndexLocation = await
|
|
144
|
-
|
|
122
|
+
let sequenceLocation = await resolveFileLocation(argsSequence, !(runFlags.skipCheck || runFlags.force), runFlags.load === 'inPlace');
|
|
123
|
+
debug(`compressed FASTA location resolved to: ${sequenceLocation}`);
|
|
124
|
+
let indexLocation = await resolveFileLocation(runFlags.faiLocation || `${sequenceLocation}.fai`, !(runFlags.skipCheck || runFlags.force), runFlags.load === 'inPlace');
|
|
125
|
+
debug(`compressed FASTA index location resolved to: ${indexLocation}`);
|
|
126
|
+
let bgzipIndexLocation = await resolveFileLocation(runFlags.gziLocation || `${sequenceLocation}.gzi`, !(runFlags.skipCheck || runFlags.force), runFlags.load === 'inPlace');
|
|
127
|
+
debug(`bgzip index location resolved to: ${bgzipIndexLocation}`);
|
|
145
128
|
if (!name) {
|
|
146
|
-
name =
|
|
147
|
-
|
|
129
|
+
name = path.basename(sequenceLocation, sequenceLocation.endsWith('.fasta.gz') ? '.fasta.gz' : '.fa.gz');
|
|
130
|
+
debug(`Guessing name: ${name}`);
|
|
148
131
|
}
|
|
149
132
|
const loaded = runFlags.load
|
|
150
133
|
? await loadData({
|
|
@@ -154,9 +137,9 @@ async function getAssembly({ runFlags, argsSequence, target, }) {
|
|
|
154
137
|
})
|
|
155
138
|
: false;
|
|
156
139
|
if (loaded) {
|
|
157
|
-
sequenceLocation =
|
|
158
|
-
indexLocation =
|
|
159
|
-
bgzipIndexLocation =
|
|
140
|
+
sequenceLocation = path.basename(sequenceLocation);
|
|
141
|
+
indexLocation = path.basename(indexLocation);
|
|
142
|
+
bgzipIndexLocation = path.basename(bgzipIndexLocation);
|
|
160
143
|
}
|
|
161
144
|
sequence = {
|
|
162
145
|
type: 'ReferenceSequenceTrack',
|
|
@@ -177,11 +160,11 @@ async function getAssembly({ runFlags, argsSequence, target, }) {
|
|
|
177
160
|
break;
|
|
178
161
|
}
|
|
179
162
|
case 'twoBit': {
|
|
180
|
-
let sequenceLocation = await
|
|
181
|
-
|
|
163
|
+
let sequenceLocation = await resolveFileLocation(argsSequence, !(runFlags.skipCheck || runFlags.force), runFlags.load === 'inPlace');
|
|
164
|
+
debug(`2bit location resolved to: ${sequenceLocation}`);
|
|
182
165
|
if (!name) {
|
|
183
|
-
name =
|
|
184
|
-
|
|
166
|
+
name = path.basename(sequenceLocation, '.2bit');
|
|
167
|
+
debug(`Guessing name: ${name}`);
|
|
185
168
|
}
|
|
186
169
|
const loaded = runFlags.load
|
|
187
170
|
? await loadData({
|
|
@@ -191,7 +174,7 @@ async function getAssembly({ runFlags, argsSequence, target, }) {
|
|
|
191
174
|
})
|
|
192
175
|
: false;
|
|
193
176
|
if (loaded) {
|
|
194
|
-
sequenceLocation =
|
|
177
|
+
sequenceLocation = path.basename(sequenceLocation);
|
|
195
178
|
}
|
|
196
179
|
sequence = {
|
|
197
180
|
type: 'ReferenceSequenceTrack',
|
|
@@ -207,11 +190,11 @@ async function getAssembly({ runFlags, argsSequence, target, }) {
|
|
|
207
190
|
break;
|
|
208
191
|
}
|
|
209
192
|
case 'chromSizes': {
|
|
210
|
-
let sequenceLocation = await
|
|
211
|
-
|
|
193
|
+
let sequenceLocation = await resolveFileLocation(argsSequence, !(runFlags.skipCheck || runFlags.force), runFlags.load === 'inPlace');
|
|
194
|
+
debug(`chrom.sizes location resolved to: ${sequenceLocation}`);
|
|
212
195
|
if (!name) {
|
|
213
|
-
name =
|
|
214
|
-
|
|
196
|
+
name = path.basename(sequenceLocation, '.chrom.sizes');
|
|
197
|
+
debug(`Guessing name: ${name}`);
|
|
215
198
|
}
|
|
216
199
|
const loaded = runFlags.load
|
|
217
200
|
? await loadData({
|
|
@@ -221,7 +204,7 @@ async function getAssembly({ runFlags, argsSequence, target, }) {
|
|
|
221
204
|
})
|
|
222
205
|
: false;
|
|
223
206
|
if (loaded) {
|
|
224
|
-
sequenceLocation =
|
|
207
|
+
sequenceLocation = path.basename(sequenceLocation);
|
|
225
208
|
}
|
|
226
209
|
sequence = {
|
|
227
210
|
type: 'ReferenceSequenceTrack',
|
|
@@ -237,16 +220,16 @@ async function getAssembly({ runFlags, argsSequence, target, }) {
|
|
|
237
220
|
break;
|
|
238
221
|
}
|
|
239
222
|
case 'custom': {
|
|
240
|
-
const adapter = await
|
|
241
|
-
|
|
223
|
+
const adapter = await readInlineOrFileJson(argsSequence);
|
|
224
|
+
debug(`Custom adapter: ${JSON.stringify(adapter)}`);
|
|
242
225
|
if (!name) {
|
|
243
226
|
if (isValidJSON(argsSequence)) {
|
|
244
227
|
throw new Error('Must provide --name when using custom inline JSON sequence');
|
|
245
228
|
}
|
|
246
229
|
else {
|
|
247
|
-
name =
|
|
230
|
+
name = path.basename(argsSequence, '.json');
|
|
248
231
|
}
|
|
249
|
-
|
|
232
|
+
debug(`Guessing name: ${name}`);
|
|
250
233
|
}
|
|
251
234
|
if (!('type' in adapter)) {
|
|
252
235
|
throw new Error(`No "type" specified in sequence adapter "${JSON.stringify(adapter)}"`);
|
|
@@ -261,31 +244,31 @@ async function getAssembly({ runFlags, argsSequence, target, }) {
|
|
|
261
244
|
}
|
|
262
245
|
return { name, sequence };
|
|
263
246
|
}
|
|
264
|
-
async function exists(s) {
|
|
247
|
+
export async function exists(s) {
|
|
265
248
|
try {
|
|
266
|
-
await
|
|
249
|
+
await fs.promises.access(s, fs.constants.F_OK);
|
|
267
250
|
return true;
|
|
268
251
|
}
|
|
269
252
|
catch {
|
|
270
253
|
return false;
|
|
271
254
|
}
|
|
272
255
|
}
|
|
273
|
-
async function resolveTargetPath(output) {
|
|
256
|
+
export async function resolveTargetPath(output) {
|
|
274
257
|
if (!(await exists(output))) {
|
|
275
|
-
const dir = output.endsWith('.json') ?
|
|
276
|
-
await
|
|
258
|
+
const dir = output.endsWith('.json') ? path.dirname(output) : output;
|
|
259
|
+
await fs.promises.mkdir(dir, { recursive: true });
|
|
277
260
|
}
|
|
278
261
|
let isDir = false;
|
|
279
262
|
try {
|
|
280
|
-
isDir =
|
|
263
|
+
isDir = fs.statSync(output).isDirectory();
|
|
281
264
|
}
|
|
282
265
|
catch (e) { }
|
|
283
|
-
return isDir ?
|
|
266
|
+
return isDir ? path.join(output, 'config.json') : output;
|
|
284
267
|
}
|
|
285
|
-
async function enhanceAssembly(assembly, runFlags) {
|
|
268
|
+
export async function enhanceAssembly(assembly, runFlags) {
|
|
286
269
|
const enhancedAssembly = { ...assembly };
|
|
287
270
|
if (runFlags.alias?.length) {
|
|
288
|
-
|
|
271
|
+
debug(`Adding assembly aliases: ${runFlags.alias}`);
|
|
289
272
|
enhancedAssembly.aliases = runFlags.alias;
|
|
290
273
|
}
|
|
291
274
|
if (runFlags.refNameColors) {
|
|
@@ -296,18 +279,18 @@ async function enhanceAssembly(assembly, runFlags) {
|
|
|
296
279
|
if (runFlags.refNameAliases) {
|
|
297
280
|
if (runFlags.refNameAliasesType &&
|
|
298
281
|
runFlags.refNameAliasesType === 'custom') {
|
|
299
|
-
const refNameAliasesConfig = await
|
|
282
|
+
const refNameAliasesConfig = await readInlineOrFileJson(runFlags.refNameAliases);
|
|
300
283
|
if (!refNameAliasesConfig.type) {
|
|
301
284
|
throw new Error(`No "type" specified in refNameAliases adapter "${JSON.stringify(refNameAliasesConfig)}"`);
|
|
302
285
|
}
|
|
303
|
-
|
|
286
|
+
debug(`Adding custom refNameAliases config: ${JSON.stringify(refNameAliasesConfig)}`);
|
|
304
287
|
enhancedAssembly.refNameAliases = {
|
|
305
288
|
adapter: refNameAliasesConfig,
|
|
306
289
|
};
|
|
307
290
|
}
|
|
308
291
|
else {
|
|
309
|
-
const refNameAliasesLocation = await
|
|
310
|
-
|
|
292
|
+
const refNameAliasesLocation = await resolveFileLocation(runFlags.refNameAliases, !(runFlags.skipCheck || runFlags.force), runFlags.load === 'inPlace');
|
|
293
|
+
debug(`refName aliases file location resolved to: ${refNameAliasesLocation}`);
|
|
311
294
|
enhancedAssembly.refNameAliases = {
|
|
312
295
|
adapter: {
|
|
313
296
|
type: 'RefNameAliasAdapter',
|
|
@@ -324,7 +307,7 @@ async function enhanceAssembly(assembly, runFlags) {
|
|
|
324
307
|
}
|
|
325
308
|
return enhancedAssembly;
|
|
326
309
|
}
|
|
327
|
-
function createDefaultConfig() {
|
|
310
|
+
export function createDefaultConfig() {
|
|
328
311
|
return {
|
|
329
312
|
assemblies: [],
|
|
330
313
|
configuration: {},
|
|
@@ -335,22 +318,22 @@ function createDefaultConfig() {
|
|
|
335
318
|
tracks: [],
|
|
336
319
|
};
|
|
337
320
|
}
|
|
338
|
-
async function loadOrCreateConfig(target) {
|
|
321
|
+
export async function loadOrCreateConfig(target) {
|
|
339
322
|
const defaultConfig = createDefaultConfig();
|
|
340
|
-
if (
|
|
341
|
-
|
|
323
|
+
if (fs.existsSync(target)) {
|
|
324
|
+
debug(`Found existing config file ${target}`);
|
|
342
325
|
return {
|
|
343
326
|
...defaultConfig,
|
|
344
|
-
...(await
|
|
327
|
+
...(await readJsonFile(target)),
|
|
345
328
|
};
|
|
346
329
|
}
|
|
347
330
|
else {
|
|
348
|
-
|
|
331
|
+
debug(`Creating config file ${target}`);
|
|
349
332
|
return { ...defaultConfig };
|
|
350
333
|
}
|
|
351
334
|
}
|
|
352
|
-
async function addAssemblyToConfig({ config, assembly, runFlags, }) {
|
|
353
|
-
const { updatedItems, wasOverwritten } =
|
|
335
|
+
export async function addAssemblyToConfig({ config, assembly, runFlags, }) {
|
|
336
|
+
const { updatedItems, wasOverwritten } = findAndUpdateOrAdd({
|
|
354
337
|
items: config.assemblies || [],
|
|
355
338
|
newItem: assembly,
|
|
356
339
|
idField: 'name',
|
|
@@ -363,8 +346,8 @@ async function addAssemblyToConfig({ config, assembly, runFlags, }) {
|
|
|
363
346
|
wasOverwritten,
|
|
364
347
|
};
|
|
365
348
|
}
|
|
366
|
-
async function saveConfigAndReport({ config, target, assembly, wasOverwritten, }) {
|
|
367
|
-
await (
|
|
349
|
+
export async function saveConfigAndReport({ config, target, assembly, wasOverwritten, }) {
|
|
350
|
+
await saveConfigAndReportBase({
|
|
368
351
|
config,
|
|
369
352
|
target,
|
|
370
353
|
itemType: 'assembly',
|
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
exports.run = run;
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const util_1 = require("util");
|
|
9
|
-
const json_parse_better_errors_1 = __importDefault(require("json-parse-better-errors"));
|
|
10
|
-
const fetchWithProxy_ts_1 = __importDefault(require("../fetchWithProxy.js"));
|
|
11
|
-
const utils_ts_1 = require("../utils.js");
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { parseArgs } from 'util';
|
|
3
|
+
import parseJSON from 'json-parse-better-errors';
|
|
4
|
+
import fetch from "../cliFetch.js";
|
|
5
|
+
import { debug, printHelp, readJsonFile, resolveConfigPath, writeJsonFile, } from "../utils.js";
|
|
12
6
|
async function resolveURL(location, check = true) {
|
|
13
7
|
let locationUrl;
|
|
14
8
|
try {
|
|
@@ -18,7 +12,7 @@ async function resolveURL(location, check = true) {
|
|
|
18
12
|
throw new Error(`The location ${location} provided is not a valid URL`);
|
|
19
13
|
}
|
|
20
14
|
if (check) {
|
|
21
|
-
const response = await (
|
|
15
|
+
const response = await fetch(`${locationUrl}`, { method: 'HEAD' });
|
|
22
16
|
if (!response.ok) {
|
|
23
17
|
throw new Error(`HTTP ${response.status} fetching ${locationUrl}`);
|
|
24
18
|
}
|
|
@@ -26,7 +20,7 @@ async function resolveURL(location, check = true) {
|
|
|
26
20
|
return locationUrl.href;
|
|
27
21
|
}
|
|
28
22
|
function determineConnectionType(url) {
|
|
29
|
-
if (
|
|
23
|
+
if (path.basename(url) === 'hub.txt') {
|
|
30
24
|
return 'UCSCTrackHubConnection';
|
|
31
25
|
}
|
|
32
26
|
if (url.includes('jbrowse/data')) {
|
|
@@ -34,7 +28,7 @@ function determineConnectionType(url) {
|
|
|
34
28
|
}
|
|
35
29
|
return 'custom';
|
|
36
30
|
}
|
|
37
|
-
async function run(args) {
|
|
31
|
+
export async function run(args) {
|
|
38
32
|
const options = {
|
|
39
33
|
help: {
|
|
40
34
|
type: 'boolean',
|
|
@@ -86,7 +80,7 @@ async function run(args) {
|
|
|
86
80
|
description: 'Equivalent to --skipCheck --overwrite',
|
|
87
81
|
},
|
|
88
82
|
};
|
|
89
|
-
const { values: flags, positionals } =
|
|
83
|
+
const { values: flags, positionals } = parseArgs({
|
|
90
84
|
args,
|
|
91
85
|
options,
|
|
92
86
|
allowPositionals: true,
|
|
@@ -101,7 +95,7 @@ async function run(args) {
|
|
|
101
95
|
'$ jbrowse add-connection https://mysite.com/path/to/hub.txt --connectionId newId --name newName --target /path/to/jb2/installation/config.json',
|
|
102
96
|
];
|
|
103
97
|
if (flags.help) {
|
|
104
|
-
|
|
98
|
+
printHelp({
|
|
105
99
|
description,
|
|
106
100
|
examples,
|
|
107
101
|
usage: 'jbrowse add-connection <connectionUrlOrPath> [options]',
|
|
@@ -113,11 +107,11 @@ async function run(args) {
|
|
|
113
107
|
if (!connectionUrlOrPath) {
|
|
114
108
|
throw new Error('Missing required argument: connectionUrlOrPath\nUsage: jbrowse add-connection <connectionUrlOrPath> [options]');
|
|
115
109
|
}
|
|
116
|
-
const target = await
|
|
110
|
+
const target = await resolveConfigPath(flags.target, flags.out);
|
|
117
111
|
const { assemblyNames, type, name, config, connectionId, skipCheck, force } = flags;
|
|
118
112
|
const url = await resolveURL(connectionUrlOrPath, !(skipCheck || force));
|
|
119
|
-
const configContents = await
|
|
120
|
-
|
|
113
|
+
const configContents = await readJsonFile(target);
|
|
114
|
+
debug(`Using config file ${target}`);
|
|
121
115
|
if (!configContents.assemblies?.length) {
|
|
122
116
|
throw new Error('No assemblies found. Please add one before adding connections');
|
|
123
117
|
}
|
|
@@ -149,7 +143,7 @@ async function run(args) {
|
|
|
149
143
|
: type === 'JBrowse1Connection'
|
|
150
144
|
? [configContents.assemblies[0]?.name]
|
|
151
145
|
: undefined,
|
|
152
|
-
...(config ? (
|
|
146
|
+
...(config ? parseJSON(config) : {}),
|
|
153
147
|
};
|
|
154
148
|
if (!configContents.connections) {
|
|
155
149
|
configContents.connections = [];
|
|
@@ -166,7 +160,7 @@ async function run(args) {
|
|
|
166
160
|
else {
|
|
167
161
|
configContents.connections.push(connectionConfig);
|
|
168
162
|
}
|
|
169
|
-
|
|
170
|
-
await
|
|
163
|
+
debug(`Writing configuration to file ${target}`);
|
|
164
|
+
await writeJsonFile(target, configContents);
|
|
171
165
|
console.log(`${idx !== -1 ? 'Overwrote' : 'Added'} connection "${name || id}" ${idx !== -1 ? 'in' : 'to'} ${target}`);
|
|
172
166
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const utils_ts_1 = require("../utils.js");
|
|
6
|
-
const config_operations_ts_1 = require("./shared/config-operations.js");
|
|
7
|
-
async function run(args) {
|
|
1
|
+
import { parseArgs } from 'util';
|
|
2
|
+
import { debug, printHelp, readInlineOrFileJson, readJsonFile, resolveConfigPath, } from "../utils.js";
|
|
3
|
+
import { findAndUpdateOrAdd, saveConfigAndReport, } from "./shared/config-operations.js";
|
|
4
|
+
export async function run(args) {
|
|
8
5
|
const options = {
|
|
9
6
|
help: {
|
|
10
7
|
type: 'boolean',
|
|
@@ -24,7 +21,7 @@ async function run(args) {
|
|
|
24
21
|
description: 'Synonym for target',
|
|
25
22
|
},
|
|
26
23
|
};
|
|
27
|
-
const { values: flags, positionals } =
|
|
24
|
+
const { values: flags, positionals } = parseArgs({
|
|
28
25
|
args,
|
|
29
26
|
options,
|
|
30
27
|
allowPositionals: true,
|
|
@@ -35,7 +32,7 @@ async function run(args) {
|
|
|
35
32
|
'$ jbrowse add-track-json track.json --update',
|
|
36
33
|
];
|
|
37
34
|
if (flags.help) {
|
|
38
|
-
|
|
35
|
+
printHelp({
|
|
39
36
|
description,
|
|
40
37
|
examples,
|
|
41
38
|
usage: 'jbrowse add-track-json <track> [options]',
|
|
@@ -47,16 +44,16 @@ async function run(args) {
|
|
|
47
44
|
if (!track) {
|
|
48
45
|
throw new Error('Missing required argument: track\nUsage: jbrowse add-track-json <track> [options]');
|
|
49
46
|
}
|
|
50
|
-
const target = await
|
|
51
|
-
|
|
47
|
+
const target = await resolveConfigPath(flags.target, flags.out);
|
|
48
|
+
debug(`Sequence location is: ${track}`);
|
|
52
49
|
const { update } = flags;
|
|
53
|
-
const config = await
|
|
54
|
-
|
|
55
|
-
const trackConfig = await
|
|
50
|
+
const config = await readJsonFile(target);
|
|
51
|
+
debug(`Found existing config file ${target}`);
|
|
52
|
+
const trackConfig = await readInlineOrFileJson(track);
|
|
56
53
|
if (!config.tracks) {
|
|
57
54
|
config.tracks = [];
|
|
58
55
|
}
|
|
59
|
-
const { updatedItems, wasOverwritten } =
|
|
56
|
+
const { updatedItems, wasOverwritten } = findAndUpdateOrAdd({
|
|
60
57
|
items: config.tracks,
|
|
61
58
|
newItem: trackConfig,
|
|
62
59
|
idField: 'trackId',
|
|
@@ -65,7 +62,7 @@ async function run(args) {
|
|
|
65
62
|
itemType: 'track',
|
|
66
63
|
});
|
|
67
64
|
config.tracks = updatedItems;
|
|
68
|
-
await
|
|
65
|
+
await saveConfigAndReport({
|
|
69
66
|
config,
|
|
70
67
|
target,
|
|
71
68
|
itemType: 'track',
|