@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
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseCigar = parseCigar;
|
|
4
|
-
exports.flipCigar = flipCigar;
|
|
5
|
-
exports.swapIndelCigar = swapIndelCigar;
|
|
6
1
|
const cigarRegex = new RegExp(/([MIDNSHPX=])/);
|
|
7
|
-
function parseCigar(cigar = '') {
|
|
2
|
+
export function parseCigar(cigar = '') {
|
|
8
3
|
return cigar.split(cigarRegex).slice(0, -1);
|
|
9
4
|
}
|
|
10
|
-
function flipCigar(cigar) {
|
|
5
|
+
export function flipCigar(cigar) {
|
|
11
6
|
const arr = [];
|
|
12
7
|
for (let i = cigar.length - 2; i >= 0; i -= 2) {
|
|
13
8
|
arr.push(cigar[i]);
|
|
@@ -24,6 +19,6 @@ function flipCigar(cigar) {
|
|
|
24
19
|
}
|
|
25
20
|
return arr;
|
|
26
21
|
}
|
|
27
|
-
function swapIndelCigar(cigar) {
|
|
22
|
+
export function swapIndelCigar(cigar) {
|
|
28
23
|
return cigar.replaceAll('D', 'K').replaceAll('I', 'D').replaceAll('K', 'I');
|
|
29
24
|
}
|
|
@@ -1,26 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
exports.createWriteWithBackpressure = createWriteWithBackpressure;
|
|
9
|
-
const fs_1 = __importDefault(require("fs"));
|
|
10
|
-
const readline_1 = __importDefault(require("readline"));
|
|
11
|
-
const zlib_1 = require("zlib");
|
|
12
|
-
function getReadline(filename) {
|
|
13
|
-
const stream = fs_1.default.createReadStream(filename);
|
|
14
|
-
return readline_1.default.createInterface({
|
|
15
|
-
input: /.b?gz$/.exec(filename) ? stream.pipe((0, zlib_1.createGunzip)()) : stream,
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import readline from 'readline';
|
|
3
|
+
import { createGunzip } from 'zlib';
|
|
4
|
+
export function getReadline(filename) {
|
|
5
|
+
const stream = fs.createReadStream(filename);
|
|
6
|
+
return readline.createInterface({
|
|
7
|
+
input: /.b?gz$/.exec(filename) ? stream.pipe(createGunzip()) : stream,
|
|
16
8
|
});
|
|
17
9
|
}
|
|
18
|
-
function getStdReadline() {
|
|
19
|
-
return
|
|
10
|
+
export function getStdReadline() {
|
|
11
|
+
return readline.createInterface({
|
|
20
12
|
input: process.stdin,
|
|
21
13
|
});
|
|
22
14
|
}
|
|
23
|
-
function createWriteWithBackpressure(stream) {
|
|
15
|
+
export function createWriteWithBackpressure(stream) {
|
|
24
16
|
return (data) => {
|
|
25
17
|
// If the stream buffer is full (write returns false), we need to wait for drain
|
|
26
18
|
if (!stream.write(data)) {
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const utils_ts_1 = require("../../utils.js");
|
|
7
|
-
const validators_ts_1 = require("../shared/validators.js");
|
|
8
|
-
async function run(args) {
|
|
1
|
+
import { parseArgs } from 'util';
|
|
2
|
+
import { createPIF, getOutputFilename, spawnSortProcess, waitForProcessClose, } from "./pif-generator.js";
|
|
3
|
+
import { printHelp } from "../../utils.js";
|
|
4
|
+
import { validateFileArgument, validateRequiredCommands, } from "../shared/validators.js";
|
|
5
|
+
export async function run(args) {
|
|
9
6
|
const options = {
|
|
10
7
|
help: {
|
|
11
8
|
type: 'boolean',
|
|
@@ -20,7 +17,7 @@ async function run(args) {
|
|
|
20
17
|
description: 'Create a CSI index for the PIF file instead of TBI',
|
|
21
18
|
},
|
|
22
19
|
};
|
|
23
|
-
const { values: flags, positionals } =
|
|
20
|
+
const { values: flags, positionals } = parseArgs({
|
|
24
21
|
args,
|
|
25
22
|
options,
|
|
26
23
|
allowPositionals: true,
|
|
@@ -32,7 +29,7 @@ async function run(args) {
|
|
|
32
29
|
'$ jbrowse make-pif input.paf --out output.pif.gz # specify output file, creates output.pif.gz.tbi also',
|
|
33
30
|
];
|
|
34
31
|
if (flags.help) {
|
|
35
|
-
|
|
32
|
+
printHelp({
|
|
36
33
|
description,
|
|
37
34
|
examples,
|
|
38
35
|
usage: 'jbrowse make-pif <file> [options]',
|
|
@@ -41,12 +38,12 @@ async function run(args) {
|
|
|
41
38
|
return;
|
|
42
39
|
}
|
|
43
40
|
const file = positionals[0];
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
validateFileArgument(file, 'make-pif', 'paf');
|
|
42
|
+
validateRequiredCommands(['sh', 'sort', 'grep', 'tabix', 'bgzip']);
|
|
46
43
|
const { out, csi = false } = flags;
|
|
47
|
-
const outputFile =
|
|
48
|
-
const child =
|
|
49
|
-
await
|
|
44
|
+
const outputFile = getOutputFilename(file, out);
|
|
45
|
+
const child = spawnSortProcess(outputFile, csi);
|
|
46
|
+
await createPIF(file, child.stdin);
|
|
50
47
|
child.stdin.end();
|
|
51
|
-
await
|
|
48
|
+
await waitForProcessClose(child);
|
|
52
49
|
}
|
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
exports.getOutputFilename = getOutputFilename;
|
|
9
|
-
exports.waitForProcessClose = waitForProcessClose;
|
|
10
|
-
const child_process_1 = require("child_process");
|
|
11
|
-
const path_1 = __importDefault(require("path"));
|
|
12
|
-
const cigar_utils_ts_1 = require("./cigar-utils.js");
|
|
13
|
-
const file_utils_ts_1 = require("./file-utils.js");
|
|
14
|
-
async function createPIF(filename, stream) {
|
|
15
|
-
const rl1 = filename ? (0, file_utils_ts_1.getReadline)(filename) : (0, file_utils_ts_1.getStdReadline)();
|
|
16
|
-
const writeWithBackpressure = (0, file_utils_ts_1.createWriteWithBackpressure)(stream);
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { flipCigar, parseCigar, swapIndelCigar } from "./cigar-utils.js";
|
|
4
|
+
import { createWriteWithBackpressure, getReadline, getStdReadline, } from "./file-utils.js";
|
|
5
|
+
export async function createPIF(filename, stream) {
|
|
6
|
+
const rl1 = filename ? getReadline(filename) : getStdReadline();
|
|
7
|
+
const writeWithBackpressure = createWriteWithBackpressure(stream);
|
|
17
8
|
// Process the file line by line with backpressure handling
|
|
18
9
|
try {
|
|
19
10
|
for await (const line of rl1) {
|
|
@@ -24,8 +15,8 @@ async function createPIF(filename, stream) {
|
|
|
24
15
|
const CIGAR = rest[cigarIdx];
|
|
25
16
|
if (CIGAR) {
|
|
26
17
|
rest[cigarIdx] = `cg:Z:${strand === '-'
|
|
27
|
-
?
|
|
28
|
-
:
|
|
18
|
+
? flipCigar(parseCigar(CIGAR.slice(5))).join('')
|
|
19
|
+
: swapIndelCigar(CIGAR.slice(5))}`;
|
|
29
20
|
}
|
|
30
21
|
// Write the second line and handle backpressure
|
|
31
22
|
await writeWithBackpressure(`${[`q${c1}`, l1, s1, e1, strand, c2, l2, s2, e2, ...rest].join('\t')}\n`);
|
|
@@ -39,7 +30,7 @@ async function createPIF(filename, stream) {
|
|
|
39
30
|
rl1.close();
|
|
40
31
|
}
|
|
41
32
|
}
|
|
42
|
-
function spawnSortProcess(outputFile, useCsi) {
|
|
33
|
+
export function spawnSortProcess(outputFile, useCsi) {
|
|
43
34
|
// Use a more portable approach to avoid E2BIG errors
|
|
44
35
|
const sortCmd = `sort -t"\`printf '\\t'\`" -k1,1 -k3,3n`;
|
|
45
36
|
const bgzipCommand = `bgzip > "${outputFile}"`;
|
|
@@ -49,15 +40,15 @@ function spawnSortProcess(outputFile, useCsi) {
|
|
|
49
40
|
...process.env,
|
|
50
41
|
LC_ALL: 'C',
|
|
51
42
|
};
|
|
52
|
-
return
|
|
43
|
+
return spawn('sh', ['-c', fullCommand], {
|
|
53
44
|
env: minimalEnv,
|
|
54
45
|
stdio: ['pipe', process.stdout, process.stderr],
|
|
55
46
|
});
|
|
56
47
|
}
|
|
57
|
-
function getOutputFilename(file, out) {
|
|
58
|
-
return out || `${
|
|
48
|
+
export function getOutputFilename(file, out) {
|
|
49
|
+
return out || `${path.basename(file || 'output', '.paf')}.pif.gz`;
|
|
59
50
|
}
|
|
60
|
-
async function waitForProcessClose(child) {
|
|
51
|
+
export async function waitForProcessClose(child) {
|
|
61
52
|
return new Promise(resolve => {
|
|
62
53
|
child.on('close', resolve);
|
|
63
54
|
});
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.waitForProcessClose = waitForProcessClose;
|
|
4
|
-
async function waitForProcessClose(child) {
|
|
1
|
+
export async function waitForProcessClose(child) {
|
|
5
2
|
return new Promise((resolve, reject) => {
|
|
6
3
|
child.on('close', code => {
|
|
7
4
|
resolve(code);
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const util_1 = require("util");
|
|
5
|
-
const utils_ts_1 = require("../utils.js");
|
|
6
|
-
async function run(args) {
|
|
1
|
+
import { parseArgs } from 'util';
|
|
2
|
+
import { printHelp, readJsonFile, resolveConfigPath, writeJsonFile, } from "../utils.js";
|
|
3
|
+
export async function run(args) {
|
|
7
4
|
const options = {
|
|
8
5
|
help: {
|
|
9
6
|
type: 'boolean',
|
|
@@ -18,7 +15,7 @@ async function run(args) {
|
|
|
18
15
|
description: 'Synonym for target',
|
|
19
16
|
},
|
|
20
17
|
};
|
|
21
|
-
const { values: flags, positionals } =
|
|
18
|
+
const { values: flags, positionals } = parseArgs({
|
|
22
19
|
args,
|
|
23
20
|
options,
|
|
24
21
|
allowPositionals: true,
|
|
@@ -26,7 +23,7 @@ async function run(args) {
|
|
|
26
23
|
const description = 'Remove a track configuration from a JBrowse 2 configuration. Be aware that this can cause crashes in saved sessions that refer to this track!';
|
|
27
24
|
const examples = ['$ jbrowse remove-track trackId'];
|
|
28
25
|
if (flags.help) {
|
|
29
|
-
|
|
26
|
+
printHelp({
|
|
30
27
|
description,
|
|
31
28
|
examples,
|
|
32
29
|
usage: 'jbrowse remove-track <trackId> [options]',
|
|
@@ -38,8 +35,8 @@ async function run(args) {
|
|
|
38
35
|
if (!trackId) {
|
|
39
36
|
throw new Error('Missing required argument: trackId\nUsage: jbrowse remove-track <trackId> [options]');
|
|
40
37
|
}
|
|
41
|
-
const target = await
|
|
42
|
-
const config = await
|
|
38
|
+
const target = await resolveConfigPath(flags.target, flags.out);
|
|
39
|
+
const config = await readJsonFile(target);
|
|
43
40
|
const originalLength = config.tracks?.length || 0;
|
|
44
41
|
config.tracks = config.tracks?.filter(({ trackId: id }) => id !== trackId);
|
|
45
42
|
const newLength = config.tracks?.length || 0;
|
|
@@ -47,7 +44,7 @@ async function run(args) {
|
|
|
47
44
|
console.log(`No track found with trackId: ${trackId}`);
|
|
48
45
|
}
|
|
49
46
|
else {
|
|
50
|
-
await
|
|
47
|
+
await writeJsonFile(target, config);
|
|
51
48
|
console.log(`Removed track with trackId: ${trackId} from ${target}`);
|
|
52
49
|
}
|
|
53
50
|
}
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.run = run;
|
|
7
|
-
const fs_1 = require("fs");
|
|
8
|
-
const util_1 = require("util");
|
|
9
|
-
const json_parse_better_errors_1 = __importDefault(require("json-parse-better-errors"));
|
|
10
|
-
const utils_ts_1 = require("../utils.js");
|
|
1
|
+
import { promises as fsPromises } from 'fs';
|
|
2
|
+
import { parseArgs } from 'util';
|
|
3
|
+
import parseJSON from 'json-parse-better-errors';
|
|
4
|
+
import { printHelp, readJsonFile, resolveConfigPath, writeJsonFile, } from "../utils.js";
|
|
11
5
|
const description = 'Set a default session with views and tracks';
|
|
12
6
|
const examples = [
|
|
13
7
|
'# set default session for the config.json in your current directory',
|
|
@@ -47,10 +41,10 @@ const options = {
|
|
|
47
41
|
},
|
|
48
42
|
help: { type: 'boolean', short: 'h', description: 'Show help' },
|
|
49
43
|
};
|
|
50
|
-
async function run(args) {
|
|
51
|
-
const { values: runFlags } =
|
|
44
|
+
export async function run(args) {
|
|
45
|
+
const { values: runFlags } = parseArgs({ options, args });
|
|
52
46
|
if (runFlags.help) {
|
|
53
|
-
|
|
47
|
+
printHelp({
|
|
54
48
|
description,
|
|
55
49
|
examples,
|
|
56
50
|
usage: 'jbrowse add-track <track> [options]',
|
|
@@ -59,11 +53,11 @@ async function run(args) {
|
|
|
59
53
|
return;
|
|
60
54
|
}
|
|
61
55
|
const { session, currentSession, delete: deleteDefaultSession } = runFlags;
|
|
62
|
-
const target = await
|
|
63
|
-
const configContents = await
|
|
56
|
+
const target = await resolveConfigPath(runFlags.target, runFlags.out);
|
|
57
|
+
const configContents = await readJsonFile(target);
|
|
64
58
|
if (deleteDefaultSession) {
|
|
65
59
|
configContents.defaultSession = undefined;
|
|
66
|
-
await
|
|
60
|
+
await writeJsonFile(target, configContents);
|
|
67
61
|
}
|
|
68
62
|
else if (currentSession) {
|
|
69
63
|
console.log(`The current default session is ${JSON.stringify(configContents.defaultSession)}`);
|
|
@@ -72,7 +66,7 @@ async function run(args) {
|
|
|
72
66
|
throw new Error('Please provide a --session file');
|
|
73
67
|
}
|
|
74
68
|
else if (session) {
|
|
75
|
-
await
|
|
69
|
+
await writeJsonFile(target, {
|
|
76
70
|
...configContents,
|
|
77
71
|
defaultSession: await readDefaultSessionFile(session),
|
|
78
72
|
});
|
|
@@ -81,7 +75,7 @@ async function run(args) {
|
|
|
81
75
|
async function readDefaultSessionFile(defaultSessionFile) {
|
|
82
76
|
let defaultSessionJson;
|
|
83
77
|
try {
|
|
84
|
-
defaultSessionJson = await
|
|
78
|
+
defaultSessionJson = await fsPromises.readFile(defaultSessionFile, {
|
|
85
79
|
encoding: 'utf8',
|
|
86
80
|
});
|
|
87
81
|
}
|
|
@@ -89,7 +83,7 @@ async function readDefaultSessionFile(defaultSessionFile) {
|
|
|
89
83
|
throw new Error('Could not read the provided file');
|
|
90
84
|
}
|
|
91
85
|
try {
|
|
92
|
-
const session = (
|
|
86
|
+
const session = parseJSON(defaultSessionJson);
|
|
93
87
|
// return top-level "session" if it exists, such as in files created by
|
|
94
88
|
// "File -> Export session"
|
|
95
89
|
return session.session || session;
|
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.findAndUpdateOrAdd = findAndUpdateOrAdd;
|
|
4
|
-
exports.saveConfigAndReport = saveConfigAndReport;
|
|
5
|
-
const utils_ts_1 = require("../../utils.js");
|
|
1
|
+
import { debug, writeJsonFile } from "../../utils.js";
|
|
6
2
|
/**
|
|
7
3
|
* Generic function to find and update or add an item to a config array
|
|
8
4
|
* Returns the updated config and whether an item was overwritten
|
|
9
5
|
*/
|
|
10
|
-
function findAndUpdateOrAdd({ items, newItem, idField, getId, allowOverwrite, itemType, }) {
|
|
6
|
+
export function findAndUpdateOrAdd({ items, newItem, idField, getId, allowOverwrite, itemType, }) {
|
|
11
7
|
const newId = getId(newItem);
|
|
12
8
|
const idx = items.findIndex(item => getId(item) === newId);
|
|
13
9
|
if (idx !== -1) {
|
|
14
|
-
|
|
10
|
+
debug(`Found existing ${itemType} ${newId} in configuration`);
|
|
15
11
|
if (allowOverwrite) {
|
|
16
|
-
|
|
12
|
+
debug(`Overwriting ${itemType} ${newId} in configuration`);
|
|
17
13
|
const updatedItems = [...items];
|
|
18
14
|
updatedItems[idx] = newItem;
|
|
19
15
|
return { updatedItems, wasOverwritten: true };
|
|
@@ -29,9 +25,9 @@ function findAndUpdateOrAdd({ items, newItem, idField, getId, allowOverwrite, it
|
|
|
29
25
|
/**
|
|
30
26
|
* Saves a config file and reports the result to the user
|
|
31
27
|
*/
|
|
32
|
-
async function saveConfigAndReport({ config, target, itemType, itemName, itemId, wasOverwritten, }) {
|
|
33
|
-
|
|
34
|
-
await
|
|
28
|
+
export async function saveConfigAndReport({ config, target, itemType, itemName, itemId, wasOverwritten, }) {
|
|
29
|
+
debug(`Writing configuration to file ${target}`);
|
|
30
|
+
await writeJsonFile(target, config);
|
|
35
31
|
const idPart = itemId ? ` and ${itemType}Id "${itemId}"` : '';
|
|
36
32
|
console.log(`${wasOverwritten ? 'Overwrote' : 'Added'} ${itemType} with name "${itemName}"${idPart} ${wasOverwritten ? 'in' : 'to'} ${target}`);
|
|
37
33
|
}
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.GFF_CONFIG = exports.BED_CONFIG = void 0;
|
|
7
|
-
exports.spawnSortProcess = spawnSortProcess;
|
|
8
|
-
const child_process_1 = require("child_process");
|
|
9
|
-
const tmp_1 = __importDefault(require("tmp"));
|
|
10
|
-
exports.BED_CONFIG = {
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import tmp from 'tmp';
|
|
3
|
+
export const BED_CONFIG = {
|
|
11
4
|
description: 'Helper utility to sort BED files for tabix. Moves all lines starting with # to the top of the file, and sort by refname and start position using unix utilities sort and grep',
|
|
12
5
|
examples: [
|
|
13
6
|
'# sort bed and pipe to bgzip',
|
|
@@ -19,7 +12,7 @@ exports.BED_CONFIG = {
|
|
|
19
12
|
sortColumn: 2,
|
|
20
13
|
fileType: 'bed',
|
|
21
14
|
};
|
|
22
|
-
|
|
15
|
+
export const GFF_CONFIG = {
|
|
23
16
|
description: 'Helper utility to sort GFF files for tabix. Moves all lines starting with # to the top of the file, and sort by refname and start position using unix utilities sort and grep',
|
|
24
17
|
examples: [
|
|
25
18
|
'# sort gff and pipe to bgzip',
|
|
@@ -39,18 +32,18 @@ function getMinimalEnvironment() {
|
|
|
39
32
|
};
|
|
40
33
|
}
|
|
41
34
|
function createSortCommandForStdin(sortColumn) {
|
|
42
|
-
const tmpFile =
|
|
35
|
+
const tmpFile = tmp.fileSync({ prefix: 'jbrowse-sort' }).name;
|
|
43
36
|
const sortCmd = `sort -t"\`printf '\\t'\`" -k1,1 -k${sortColumn},${sortColumn}n`;
|
|
44
37
|
return `cat > ${tmpFile} && (grep "^#" ${tmpFile}; grep -v "^#" ${tmpFile} | ${sortCmd}) && rm -f ${tmpFile}`;
|
|
45
38
|
}
|
|
46
39
|
function createSortCommandForFile(file, sortColumn) {
|
|
47
40
|
return `(grep "^#" "${file}"; grep -v "^#" "${file}" | sort -t"\`printf '\\t'\`" -k1,1 -k${sortColumn},${sortColumn}n)`;
|
|
48
41
|
}
|
|
49
|
-
function spawnSortProcess(file, sortColumn) {
|
|
42
|
+
export function spawnSortProcess(file, sortColumn) {
|
|
50
43
|
const command = file
|
|
51
44
|
? createSortCommandForFile(file, sortColumn)
|
|
52
45
|
: createSortCommandForStdin(sortColumn);
|
|
53
|
-
return
|
|
46
|
+
return spawn('sh', ['-c', command], {
|
|
54
47
|
env: getMinimalEnvironment(),
|
|
55
48
|
stdio: 'inherit',
|
|
56
49
|
});
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.validateFileArgument = validateFileArgument;
|
|
4
|
-
exports.validateRequiredCommands = validateRequiredCommands;
|
|
5
|
-
const command_exists_1 = require("command-exists");
|
|
6
|
-
function validateFileArgument(file, commandName, fileType) {
|
|
1
|
+
import { sync as commandExistsSync } from 'command-exists';
|
|
2
|
+
export function validateFileArgument(file, commandName, fileType) {
|
|
7
3
|
if (!file && process.stdin.isTTY) {
|
|
8
4
|
throw new Error(`Missing required argument: file\n` +
|
|
9
5
|
`Usage: jbrowse ${commandName} <file>\n` +
|
|
10
6
|
` OR pipe data via stdin: cat file.${fileType} | jbrowse ${commandName}`);
|
|
11
7
|
}
|
|
12
8
|
}
|
|
13
|
-
function validateRequiredCommands(requiredCommands) {
|
|
14
|
-
const missingCommands = requiredCommands.filter(cmd => !(
|
|
9
|
+
export function validateRequiredCommands(requiredCommands) {
|
|
10
|
+
const missingCommands = requiredCommands.filter(cmd => !commandExistsSync(cmd));
|
|
15
11
|
if (missingCommands.length > 0) {
|
|
16
12
|
throw new Error(`Unable to run command, requires unix type environment with: ${requiredCommands.join(', ')}`);
|
|
17
13
|
}
|
|
@@ -1,37 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const sort_utils_ts_1 = require("./shared/sort-utils.js");
|
|
8
|
-
const validators_ts_1 = require("./shared/validators.js");
|
|
9
|
-
async function run(args) {
|
|
1
|
+
import { parseArgs } from 'util';
|
|
2
|
+
import { printHelp } from "../utils.js";
|
|
3
|
+
import { waitForProcessClose } from "./process-utils.js";
|
|
4
|
+
import { BED_CONFIG, spawnSortProcess } from "./shared/sort-utils.js";
|
|
5
|
+
import { validateFileArgument, validateRequiredCommands, } from "./shared/validators.js";
|
|
6
|
+
export async function run(args) {
|
|
10
7
|
const options = {
|
|
11
8
|
help: {
|
|
12
9
|
type: 'boolean',
|
|
13
10
|
short: 'h',
|
|
14
11
|
},
|
|
15
12
|
};
|
|
16
|
-
const { values: flags, positionals } =
|
|
13
|
+
const { values: flags, positionals } = parseArgs({
|
|
17
14
|
args,
|
|
18
15
|
options,
|
|
19
16
|
allowPositionals: true,
|
|
20
17
|
});
|
|
21
18
|
if (flags.help) {
|
|
22
|
-
|
|
23
|
-
description:
|
|
24
|
-
examples:
|
|
19
|
+
printHelp({
|
|
20
|
+
description: BED_CONFIG.description,
|
|
21
|
+
examples: BED_CONFIG.examples,
|
|
25
22
|
usage: 'jbrowse sort-bed [file] [options]',
|
|
26
23
|
options,
|
|
27
24
|
});
|
|
28
25
|
return;
|
|
29
26
|
}
|
|
30
27
|
const file = positionals[0];
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const child =
|
|
34
|
-
const exitCode = await
|
|
28
|
+
validateFileArgument(file, 'sort-bed', 'bed');
|
|
29
|
+
validateRequiredCommands(['sh', 'sort', 'grep']);
|
|
30
|
+
const child = spawnSortProcess(file, BED_CONFIG.sortColumn);
|
|
31
|
+
const exitCode = await waitForProcessClose(child);
|
|
35
32
|
if (exitCode !== 0) {
|
|
36
33
|
throw new Error(`Sort process exited with code ${exitCode}`);
|
|
37
34
|
}
|
|
@@ -1,37 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const sort_utils_ts_1 = require("./shared/sort-utils.js");
|
|
8
|
-
const validators_ts_1 = require("./shared/validators.js");
|
|
9
|
-
async function run(args) {
|
|
1
|
+
import { parseArgs } from 'util';
|
|
2
|
+
import { printHelp } from "../utils.js";
|
|
3
|
+
import { waitForProcessClose } from "./process-utils.js";
|
|
4
|
+
import { GFF_CONFIG, spawnSortProcess } from "./shared/sort-utils.js";
|
|
5
|
+
import { validateFileArgument, validateRequiredCommands, } from "./shared/validators.js";
|
|
6
|
+
export async function run(args) {
|
|
10
7
|
const options = {
|
|
11
8
|
help: {
|
|
12
9
|
type: 'boolean',
|
|
13
10
|
short: 'h',
|
|
14
11
|
},
|
|
15
12
|
};
|
|
16
|
-
const { values: flags, positionals } =
|
|
13
|
+
const { values: flags, positionals } = parseArgs({
|
|
17
14
|
args,
|
|
18
15
|
options,
|
|
19
16
|
allowPositionals: true,
|
|
20
17
|
});
|
|
21
18
|
if (flags.help) {
|
|
22
|
-
|
|
23
|
-
description:
|
|
24
|
-
examples:
|
|
19
|
+
printHelp({
|
|
20
|
+
description: GFF_CONFIG.description,
|
|
21
|
+
examples: GFF_CONFIG.examples,
|
|
25
22
|
usage: 'jbrowse sort-gff [file] [options]',
|
|
26
23
|
options,
|
|
27
24
|
});
|
|
28
25
|
return;
|
|
29
26
|
}
|
|
30
27
|
const file = positionals[0];
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const child =
|
|
34
|
-
const exitCode = await
|
|
28
|
+
validateFileArgument(file, 'sort-gff', 'gff');
|
|
29
|
+
validateRequiredCommands(['sh', 'sort', 'grep']);
|
|
30
|
+
const child = spawnSortProcess(file, GFF_CONFIG.sortColumn);
|
|
31
|
+
const exitCode = await waitForProcessClose(child);
|
|
35
32
|
if (exitCode !== 0) {
|
|
36
33
|
throw new Error(`Sort process exited with code ${exitCode}`);
|
|
37
34
|
}
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.getLoc = getLoc;
|
|
4
|
-
exports.createTrixAdapter = createTrixAdapter;
|
|
5
|
-
exports.getAdapterLocation = getAdapterLocation;
|
|
6
|
-
const config_utils_ts_1 = require("./config-utils.js");
|
|
7
|
-
function getLoc(elt) {
|
|
1
|
+
import { sanitizeNameForPath } from "./config-utils.js";
|
|
2
|
+
export function getLoc(elt) {
|
|
8
3
|
return elt.locationType === 'LocalPathLocation' ? elt.localPath : elt.uri;
|
|
9
4
|
}
|
|
10
|
-
function createTrixAdapter(name, assemblyNames, idSuffix = 'index') {
|
|
11
|
-
const safeName =
|
|
5
|
+
export function createTrixAdapter(name, assemblyNames, idSuffix = 'index') {
|
|
6
|
+
const safeName = sanitizeNameForPath(name);
|
|
12
7
|
return {
|
|
13
8
|
type: 'TrixTextSearchAdapter',
|
|
14
9
|
textSearchAdapterId: `${safeName}-${idSuffix}`,
|
|
@@ -33,7 +28,7 @@ const ADAPTER_LOCATION_KEYS = {
|
|
|
33
28
|
VcfAdapter: 'vcfLocation',
|
|
34
29
|
VcfTabixAdapter: 'vcfGzLocation',
|
|
35
30
|
};
|
|
36
|
-
function getAdapterLocation(adapter) {
|
|
31
|
+
export function getAdapterLocation(adapter) {
|
|
37
32
|
const key = ADAPTER_LOCATION_KEYS[adapter?.type ?? ''];
|
|
38
33
|
return key
|
|
39
34
|
? // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const indexing_utils_ts_1 = require("./indexing-utils.js");
|
|
7
|
-
const utils_ts_1 = require("../../utils.js");
|
|
8
|
-
async function aggregateIndex(flags) {
|
|
1
|
+
import { createTrixAdapter } from "./adapter-utils.js";
|
|
2
|
+
import { getAssemblyNames, getTrackConfigs, loadConfigForIndexing, parseCommaSeparatedString, prepareIndexDriverFlags, writeConf, } from "./config-utils.js";
|
|
3
|
+
import { indexDriver } from "./indexing-utils.js";
|
|
4
|
+
import { resolveConfigPath } from "../../utils.js";
|
|
5
|
+
export async function aggregateIndex(flags) {
|
|
9
6
|
const { out, target, tracks, excludeTracks, assemblies, attributes, quiet, force, exclude, dryrun, prefixSize, } = flags;
|
|
10
|
-
const { config, configPath, outLocation } = await
|
|
7
|
+
const { config, configPath, outLocation } = await loadConfigForIndexing(target, out, resolveConfigPath);
|
|
11
8
|
const aggregateTextSearchAdapters = config.aggregateTextSearchAdapters || [];
|
|
12
|
-
const asms =
|
|
9
|
+
const asms = getAssemblyNames(config, assemblies);
|
|
13
10
|
for (const asm of asms) {
|
|
14
|
-
const trackConfigs =
|
|
11
|
+
const trackConfigs = getTrackConfigs(config, parseCommaSeparatedString(tracks), asm, parseCommaSeparatedString(excludeTracks));
|
|
15
12
|
if (!trackConfigs.length) {
|
|
16
13
|
console.log(`Indexing assembly ${asm}...(no tracks found)...`);
|
|
17
14
|
continue;
|
|
@@ -27,14 +24,14 @@ async function aggregateIndex(flags) {
|
|
|
27
24
|
console.log(`Note: ${asm} has already been indexed with this configuration, use --force to overwrite this assembly. Skipping for now`);
|
|
28
25
|
continue;
|
|
29
26
|
}
|
|
30
|
-
await
|
|
27
|
+
await indexDriver({
|
|
31
28
|
trackConfigs,
|
|
32
29
|
outLocation,
|
|
33
30
|
name: asm,
|
|
34
31
|
assemblyNames: [asm],
|
|
35
|
-
...
|
|
32
|
+
...prepareIndexDriverFlags({ attributes, exclude, quiet, prefixSize }),
|
|
36
33
|
});
|
|
37
|
-
const trixConf =
|
|
34
|
+
const trixConf = createTrixAdapter(asm, [asm]);
|
|
38
35
|
if (idx === -1) {
|
|
39
36
|
aggregateTextSearchAdapters.push(trixConf);
|
|
40
37
|
}
|
|
@@ -44,7 +41,7 @@ async function aggregateIndex(flags) {
|
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
43
|
if (!dryrun) {
|
|
47
|
-
|
|
44
|
+
writeConf({
|
|
48
45
|
...config,
|
|
49
46
|
aggregateTextSearchAdapters,
|
|
50
47
|
}, configPath);
|