@jbrowse/cli 3.6.5 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/bin/run +0 -0
- package/bundle/index.js +2280 -2722
- package/dist/bin.js +2 -2
- package/dist/commands/{add-assembly.js → add-assembly/index.js} +10 -10
- package/dist/commands/{assembly-utils.js → add-assembly/utils.js} +69 -105
- package/dist/commands/add-connection.js +11 -16
- package/dist/commands/add-track-json.js +26 -31
- package/dist/commands/add-track-utils/track-config.js +3 -15
- package/dist/commands/add-track-utils/validators.js +4 -9
- package/dist/commands/add-track.js +23 -25
- package/dist/commands/admin-server/index.js +100 -0
- package/dist/commands/{admin-server-utils.js → admin-server/utils.js} +7 -58
- package/dist/commands/create.js +8 -8
- package/dist/commands/{make-pif.js → make-pif/index.js} +11 -17
- package/dist/commands/{make-pif-utils → make-pif}/pif-generator.js +6 -6
- package/dist/commands/{sort-bed-utils/process-utils.js → process-utils.js} +0 -10
- package/dist/commands/remove-track.js +6 -11
- package/dist/commands/set-default-session.js +8 -12
- package/dist/commands/shared/config-operations.js +37 -0
- package/dist/commands/shared/sort-utils.js +57 -0
- package/dist/commands/shared/validators.js +18 -0
- package/dist/commands/sort-bed.js +13 -24
- package/dist/commands/sort-gff.js +13 -24
- package/dist/commands/text-index/adapter-utils.js +43 -0
- package/dist/commands/text-index/aggregate.js +52 -0
- package/dist/commands/{text-index.js → text-index/command.js} +13 -6
- package/dist/commands/text-index/config-utils.js +134 -0
- package/dist/commands/{text-index-utils → text-index}/file-list.js +12 -15
- package/dist/commands/text-index/index.js +11 -0
- package/dist/commands/{text-index-utils → text-index}/indexing-utils.js +30 -20
- package/dist/commands/text-index/per-track.js +54 -0
- package/dist/commands/track-utils.js +33 -33
- package/dist/commands/upgrade.js +8 -8
- package/dist/index.js +39 -27
- package/dist/types/common.js +9 -8
- package/dist/types/gff3Adapter.js +17 -48
- package/dist/types/streamUtils.js +66 -0
- package/dist/types/vcfAdapter.js +17 -54
- package/dist/util.js +14 -7
- package/dist/utils.js +10 -5
- package/package.json +14 -16
- package/dist/commands/admin-server.js +0 -55
- package/dist/commands/make-pif-utils/validators.js +0 -22
- package/dist/commands/sort-bed-utils/constants.js +0 -12
- package/dist/commands/sort-bed-utils/sort-utils.js +0 -24
- package/dist/commands/sort-bed-utils/validators.js +0 -22
- package/dist/commands/sort-gff-utils/constants.js +0 -13
- package/dist/commands/sort-gff-utils/process-utils.js +0 -23
- package/dist/commands/sort-gff-utils/sort-utils.js +0 -55
- package/dist/commands/sort-gff-utils/validators.js +0 -21
- package/dist/commands/text-index-utils/adapter-utils.js +0 -63
- package/dist/commands/text-index-utils/aggregate.js +0 -87
- package/dist/commands/text-index-utils/config-utils.js +0 -59
- package/dist/commands/text-index-utils/index.js +0 -9
- package/dist/commands/text-index-utils/per-track.js +0 -65
- /package/dist/commands/{make-pif-utils → make-pif}/cigar-utils.js +0 -0
- /package/dist/commands/{make-pif-utils → make-pif}/file-utils.js +0 -0
- /package/dist/commands/{text-index-utils → text-index}/validators.js +0 -0
|
@@ -6,11 +6,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.run = run;
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
8
|
const util_1 = require("util");
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
9
|
+
const utils_ts_1 = require("../utils.js");
|
|
10
|
+
const adapter_utils_ts_1 = require("./add-track-utils/adapter-utils.js");
|
|
11
|
+
const track_config_ts_1 = require("./add-track-utils/track-config.js");
|
|
12
|
+
const validators_ts_1 = require("./add-track-utils/validators.js");
|
|
13
|
+
const track_utils_ts_1 = require("./track-utils.js");
|
|
14
14
|
async function run(args) {
|
|
15
15
|
const options = {
|
|
16
16
|
help: {
|
|
@@ -122,7 +122,7 @@ async function run(args) {
|
|
|
122
122
|
'$ jbrowse add-track /url/relative/path.bam --load inPlace',
|
|
123
123
|
];
|
|
124
124
|
if (flags.help) {
|
|
125
|
-
(0,
|
|
125
|
+
(0, utils_ts_1.printHelp)({
|
|
126
126
|
description,
|
|
127
127
|
examples,
|
|
128
128
|
usage: 'jbrowse add-track <track> [options]',
|
|
@@ -130,50 +130,48 @@ async function run(args) {
|
|
|
130
130
|
});
|
|
131
131
|
return;
|
|
132
132
|
}
|
|
133
|
-
(0,
|
|
133
|
+
(0, validators_ts_1.validateLoadOption)(flags.load);
|
|
134
134
|
const track = positionals[0];
|
|
135
|
-
(0,
|
|
136
|
-
const { config,
|
|
137
|
-
const
|
|
138
|
-
const targetConfigPath = (0, track_utils_1.resolveTrackConfigPath)(output);
|
|
135
|
+
(0, validators_ts_1.validateTrackArg)(track);
|
|
136
|
+
const { config, force, overwrite, category, description: trackDescription, load, subDir = '', target, protocol = 'uri', out, indexFile: index, bed1, bed2, } = flags;
|
|
137
|
+
const targetConfigPath = await (0, utils_ts_1.resolveConfigPath)(target, out);
|
|
139
138
|
const configDir = path_1.default.dirname(targetConfigPath);
|
|
140
|
-
(0,
|
|
139
|
+
(0, validators_ts_1.createTargetDirectory)(configDir, subDir);
|
|
141
140
|
const location = track;
|
|
142
|
-
const mapLoc = (p) => (0,
|
|
143
|
-
let adapter = (0,
|
|
141
|
+
const mapLoc = (p) => (0, track_config_ts_1.mapLocationForFiles)(p, load, subDir);
|
|
142
|
+
let adapter = (0, adapter_utils_ts_1.guessAdapter)({
|
|
144
143
|
protocol,
|
|
145
144
|
location: mapLoc(location),
|
|
146
145
|
index: index ? mapLoc(index) : undefined,
|
|
147
146
|
bed1: bed1 ? mapLoc(bed1) : undefined,
|
|
148
147
|
bed2: bed2 ? mapLoc(bed2) : undefined,
|
|
149
148
|
});
|
|
150
|
-
adapter = (0,
|
|
151
|
-
(0,
|
|
152
|
-
(0,
|
|
153
|
-
const configContents = await (0,
|
|
154
|
-
(0,
|
|
155
|
-
const trackParams = (0,
|
|
149
|
+
adapter = (0, track_config_ts_1.addSyntenyAssemblyNames)(adapter, flags.assemblyNames);
|
|
150
|
+
(0, validators_ts_1.validateLoadAndLocation)(location, load);
|
|
151
|
+
(0, validators_ts_1.validateAdapterType)(adapter.type);
|
|
152
|
+
const configContents = await (0, track_utils_ts_1.loadTrackConfig)(targetConfigPath);
|
|
153
|
+
(0, validators_ts_1.validateAssemblies)(configContents, flags.assemblyNames);
|
|
154
|
+
const trackParams = (0, track_utils_ts_1.buildTrackParams)({
|
|
156
155
|
flags,
|
|
157
156
|
location,
|
|
158
157
|
adapter,
|
|
159
158
|
configContents,
|
|
160
159
|
});
|
|
161
|
-
const trackConfig = (0,
|
|
160
|
+
const trackConfig = (0, track_utils_ts_1.createTrackConfiguration)({
|
|
162
161
|
location,
|
|
163
162
|
trackParams,
|
|
164
163
|
flags: { category, description: trackDescription, config },
|
|
165
164
|
adapter,
|
|
166
165
|
configContents,
|
|
167
|
-
skipCheck,
|
|
168
166
|
});
|
|
169
|
-
const { updatedConfig, wasOverwritten } = (0,
|
|
167
|
+
const { updatedConfig, wasOverwritten } = (0, track_utils_ts_1.addTrackToConfig)({
|
|
170
168
|
configContents,
|
|
171
169
|
trackConfig,
|
|
172
170
|
trackId: trackParams.trackId,
|
|
173
171
|
force,
|
|
174
172
|
overwrite,
|
|
175
173
|
});
|
|
176
|
-
await (0,
|
|
174
|
+
await (0, track_utils_ts_1.processTrackFiles)({
|
|
177
175
|
location,
|
|
178
176
|
index,
|
|
179
177
|
bed1,
|
|
@@ -183,7 +181,7 @@ async function run(args) {
|
|
|
183
181
|
subDir,
|
|
184
182
|
force,
|
|
185
183
|
});
|
|
186
|
-
await (0,
|
|
184
|
+
await (0, track_utils_ts_1.saveTrackConfigAndReport)({
|
|
187
185
|
config: updatedConfig,
|
|
188
186
|
targetConfigPath,
|
|
189
187
|
name: trackParams.name,
|
|
@@ -0,0 +1,100 @@
|
|
|
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 os_1 = __importDefault(require("os"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const util_1 = require("util");
|
|
11
|
+
const cors_1 = __importDefault(require("cors"));
|
|
12
|
+
const express_1 = __importDefault(require("express"));
|
|
13
|
+
const utils_ts_1 = require("./utils.js");
|
|
14
|
+
const utils_ts_2 = require("../../utils.js");
|
|
15
|
+
async function run(args) {
|
|
16
|
+
const options = {
|
|
17
|
+
help: {
|
|
18
|
+
type: 'boolean',
|
|
19
|
+
short: 'h',
|
|
20
|
+
},
|
|
21
|
+
port: {
|
|
22
|
+
type: 'string',
|
|
23
|
+
short: 'p',
|
|
24
|
+
description: 'Specified port to start the server on (default: 9090)',
|
|
25
|
+
},
|
|
26
|
+
root: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'Path to the root of the JB2 installation',
|
|
29
|
+
},
|
|
30
|
+
bodySizeLimit: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
description: 'Size limit of the update message (default: 25mb)',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
const { values: flags } = (0, util_1.parseArgs)({
|
|
36
|
+
args,
|
|
37
|
+
options,
|
|
38
|
+
allowPositionals: true,
|
|
39
|
+
});
|
|
40
|
+
const description = 'Start up a small admin server for JBrowse configuration';
|
|
41
|
+
const examples = ['$ jbrowse admin-server', '$ jbrowse admin-server -p 8888'];
|
|
42
|
+
if (flags.help) {
|
|
43
|
+
(0, utils_ts_2.printHelp)({
|
|
44
|
+
description,
|
|
45
|
+
examples,
|
|
46
|
+
usage: 'jbrowse admin-server [options]',
|
|
47
|
+
options,
|
|
48
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const { root, bodySizeLimit = '25mb' } = flags;
|
|
52
|
+
const { outFile, baseDir } = await (0, utils_ts_1.setupConfigFile)({ root });
|
|
53
|
+
// Parse and validate port
|
|
54
|
+
const port = (0, utils_ts_1.parsePort)({ portStr: flags.port });
|
|
55
|
+
// Set up the Express server
|
|
56
|
+
// const { app, key, keyPath, serverRef } = setupServer({
|
|
57
|
+
// baseDir,
|
|
58
|
+
// outFile,
|
|
59
|
+
// bodySizeLimit,
|
|
60
|
+
// })
|
|
61
|
+
const app = (0, express_1.default)();
|
|
62
|
+
// Configure middleware
|
|
63
|
+
app.use(express_1.default.static(baseDir));
|
|
64
|
+
app.use((0, cors_1.default)());
|
|
65
|
+
app.use(express_1.default.json({ limit: bodySizeLimit }));
|
|
66
|
+
// Add error handling middleware
|
|
67
|
+
app.use((err, _req, res, next) => {
|
|
68
|
+
if (err) {
|
|
69
|
+
console.error('Server error:', err);
|
|
70
|
+
res.status(500).setHeader('Content-Type', 'text/plain');
|
|
71
|
+
res.send('Internal Server Error');
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
next();
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
// Generate admin key and store it
|
|
78
|
+
const key = (0, utils_ts_1.generateKey)();
|
|
79
|
+
const keyPath = path_1.default.join(os_1.default.tmpdir(), `jbrowse-admin-${key}`);
|
|
80
|
+
try {
|
|
81
|
+
fs_1.default.writeFileSync(keyPath, key);
|
|
82
|
+
(0, utils_ts_2.debug)(`Admin key stored at ${keyPath}`);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.error(`Failed to write admin key to ${keyPath}:`, error.message);
|
|
86
|
+
// Continue anyway, as this is not critical
|
|
87
|
+
}
|
|
88
|
+
// Create server reference for shutdown route
|
|
89
|
+
const serverRef = { current: null };
|
|
90
|
+
// Set up routes
|
|
91
|
+
(0, utils_ts_1.setupRoutes)({
|
|
92
|
+
app,
|
|
93
|
+
baseDir,
|
|
94
|
+
outFile,
|
|
95
|
+
key,
|
|
96
|
+
serverRef,
|
|
97
|
+
});
|
|
98
|
+
// Start the server and set up shutdown handlers
|
|
99
|
+
(0, utils_ts_1.startServer)({ app, port, key, outFile, keyPath, serverRef });
|
|
100
|
+
}
|
|
@@ -8,15 +8,12 @@ exports.parsePort = parsePort;
|
|
|
8
8
|
exports.generateKey = generateKey;
|
|
9
9
|
exports.setupConfigFile = setupConfigFile;
|
|
10
10
|
exports.setupRoutes = setupRoutes;
|
|
11
|
-
exports.setupServer = setupServer;
|
|
12
11
|
exports.startServer = startServer;
|
|
13
12
|
const crypto_1 = __importDefault(require("crypto"));
|
|
14
13
|
const fs_1 = __importDefault(require("fs"));
|
|
15
|
-
const os_1 = __importDefault(require("os"));
|
|
16
14
|
const path_1 = __importDefault(require("path"));
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const utils_1 = require("../utils");
|
|
15
|
+
const utils_ts_1 = require("../../utils.js");
|
|
16
|
+
const utils_ts_2 = require("../add-assembly/utils.js");
|
|
20
17
|
/**
|
|
21
18
|
* Validates if a port number is in the valid range
|
|
22
19
|
*/
|
|
@@ -46,24 +43,14 @@ function generateKey() {
|
|
|
46
43
|
* Sets up the configuration file
|
|
47
44
|
*/
|
|
48
45
|
async function setupConfigFile({ root = '.', } = {}) {
|
|
49
|
-
const
|
|
50
|
-
const isDir = fs_1.default.lstatSync(output).isDirectory();
|
|
51
|
-
const outFile = isDir ? `${output}/config.json` : output;
|
|
46
|
+
const outFile = await (0, utils_ts_1.resolveConfigPath)(root);
|
|
52
47
|
const baseDir = path_1.default.dirname(outFile);
|
|
53
48
|
if (fs_1.default.existsSync(outFile)) {
|
|
54
|
-
(0,
|
|
49
|
+
(0, utils_ts_1.debug)(`Found existing config file ${outFile}`);
|
|
55
50
|
}
|
|
56
51
|
else {
|
|
57
|
-
(0,
|
|
58
|
-
await (0,
|
|
59
|
-
assemblies: [],
|
|
60
|
-
configuration: {},
|
|
61
|
-
connections: [],
|
|
62
|
-
defaultSession: {
|
|
63
|
-
name: 'New Session',
|
|
64
|
-
},
|
|
65
|
-
tracks: [],
|
|
66
|
-
});
|
|
52
|
+
(0, utils_ts_1.debug)(`Creating config file ${outFile}`);
|
|
53
|
+
await (0, utils_ts_1.writeJsonFile)(outFile, (0, utils_ts_2.createDefaultConfig)());
|
|
67
54
|
}
|
|
68
55
|
return { outFile, baseDir };
|
|
69
56
|
}
|
|
@@ -176,44 +163,6 @@ function setupRoutes({ app, baseDir, outFile, key, serverRef, }) {
|
|
|
176
163
|
});
|
|
177
164
|
});
|
|
178
165
|
}
|
|
179
|
-
/**
|
|
180
|
-
* Sets up the Express server with routes
|
|
181
|
-
*/
|
|
182
|
-
function setupServer({ baseDir, outFile, bodySizeLimit, }) {
|
|
183
|
-
// Create Express application
|
|
184
|
-
const app = (0, express_1.default)();
|
|
185
|
-
// Configure middleware
|
|
186
|
-
app.use(express_1.default.static(baseDir));
|
|
187
|
-
app.use((0, cors_1.default)());
|
|
188
|
-
app.use(express_1.default.json({ limit: bodySizeLimit }));
|
|
189
|
-
// Add error handling middleware
|
|
190
|
-
app.use((err, _req, res, next) => {
|
|
191
|
-
if (err) {
|
|
192
|
-
console.error('Server error:', err);
|
|
193
|
-
res.status(500).setHeader('Content-Type', 'text/plain');
|
|
194
|
-
res.send('Internal Server Error');
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
next();
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
// Generate admin key and store it
|
|
201
|
-
const key = generateKey();
|
|
202
|
-
const keyPath = path_1.default.join(os_1.default.tmpdir(), `jbrowse-admin-${key}`);
|
|
203
|
-
try {
|
|
204
|
-
fs_1.default.writeFileSync(keyPath, key);
|
|
205
|
-
(0, utils_1.debug)(`Admin key stored at ${keyPath}`);
|
|
206
|
-
}
|
|
207
|
-
catch (error) {
|
|
208
|
-
console.error(`Failed to write admin key to ${keyPath}:`, error.message);
|
|
209
|
-
// Continue anyway, as this is not critical
|
|
210
|
-
}
|
|
211
|
-
// Create server reference for shutdown route
|
|
212
|
-
const serverRef = { current: null };
|
|
213
|
-
// Set up routes
|
|
214
|
-
setupRoutes({ app, baseDir, outFile, key, serverRef });
|
|
215
|
-
return { app, key, keyPath, serverRef };
|
|
216
|
-
}
|
|
217
166
|
/**
|
|
218
167
|
* Starts the server and sets up shutdown handlers
|
|
219
168
|
*/
|
|
@@ -246,7 +195,7 @@ function startServer({ app, port, key, outFile, keyPath, serverRef, }) {
|
|
|
246
195
|
// Clean up admin key file
|
|
247
196
|
try {
|
|
248
197
|
fs_1.default.unlinkSync(keyPath);
|
|
249
|
-
(0,
|
|
198
|
+
(0, utils_ts_1.debug)(`Removed admin key file: ${keyPath}`);
|
|
250
199
|
}
|
|
251
200
|
catch (error) {
|
|
252
201
|
// Ignore errors when cleaning up
|
package/dist/commands/create.js
CHANGED
|
@@ -7,8 +7,8 @@ exports.run = run;
|
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
const util_1 = require("util");
|
|
9
9
|
const decompress_1 = __importDefault(require("decompress"));
|
|
10
|
-
const
|
|
11
|
-
const
|
|
10
|
+
const fetchWithProxy_ts_1 = __importDefault(require("../fetchWithProxy.js"));
|
|
11
|
+
const utils_ts_1 = require("../utils.js");
|
|
12
12
|
const fsPromises = fs_1.default.promises;
|
|
13
13
|
const description = 'Downloads and installs the latest JBrowse 2 release';
|
|
14
14
|
const examples = [
|
|
@@ -69,7 +69,7 @@ async function run(args) {
|
|
|
69
69
|
args,
|
|
70
70
|
});
|
|
71
71
|
if (runFlags.help) {
|
|
72
|
-
(0,
|
|
72
|
+
(0, utils_ts_1.printHelp)({
|
|
73
73
|
description,
|
|
74
74
|
examples,
|
|
75
75
|
usage: 'jbrowse create [localPath] [options]',
|
|
@@ -86,7 +86,7 @@ async function run(args) {
|
|
|
86
86
|
}
|
|
87
87
|
const { force, url, listVersions, tag, branch, nightly } = runFlags;
|
|
88
88
|
if (listVersions) {
|
|
89
|
-
const versions = (await (0,
|
|
89
|
+
const versions = (await (0, utils_ts_1.fetchGithubVersions)()).map(version => version.tag_name);
|
|
90
90
|
console.log(`All JBrowse versions:\n${versions.join('\n')}`);
|
|
91
91
|
process.exit(0);
|
|
92
92
|
}
|
|
@@ -96,11 +96,11 @@ async function run(args) {
|
|
|
96
96
|
await checkPath(argsPath);
|
|
97
97
|
}
|
|
98
98
|
const locationUrl = url ||
|
|
99
|
-
(nightly ? await (0,
|
|
100
|
-
(branch ? await (0,
|
|
101
|
-
(tag ? await (0,
|
|
99
|
+
(nightly ? await (0, utils_ts_1.getBranch)('main') : '') ||
|
|
100
|
+
(branch ? await (0, utils_ts_1.getBranch)(branch) : '') ||
|
|
101
|
+
(tag ? await (0, utils_ts_1.getTag)(tag) : await (0, utils_ts_1.getLatest)());
|
|
102
102
|
console.log(`Fetching ${locationUrl}...`);
|
|
103
|
-
const response = await (0,
|
|
103
|
+
const response = await (0, fetchWithProxy_ts_1.default)(locationUrl);
|
|
104
104
|
if (!response.ok) {
|
|
105
105
|
throw new Error(`HTTP ${response.status} fetching ${locationUrl}: ${response.statusText}`);
|
|
106
106
|
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.run = run;
|
|
4
4
|
const util_1 = require("util");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
5
|
+
const pif_generator_ts_1 = require("./pif-generator.js");
|
|
6
|
+
const utils_ts_1 = require("../../utils.js");
|
|
7
|
+
const validators_ts_1 = require("../shared/validators.js");
|
|
8
8
|
async function run(args) {
|
|
9
9
|
const options = {
|
|
10
10
|
help: {
|
|
@@ -32,7 +32,7 @@ async function run(args) {
|
|
|
32
32
|
'$ jbrowse make-pif input.paf --out output.pif.gz # specify output file, creates output.pif.gz.tbi also',
|
|
33
33
|
];
|
|
34
34
|
if (flags.help) {
|
|
35
|
-
(0,
|
|
35
|
+
(0, utils_ts_1.printHelp)({
|
|
36
36
|
description,
|
|
37
37
|
examples,
|
|
38
38
|
usage: 'jbrowse make-pif <file> [options]',
|
|
@@ -41,18 +41,12 @@ async function run(args) {
|
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
43
|
const file = positionals[0];
|
|
44
|
-
(0,
|
|
45
|
-
(0,
|
|
44
|
+
(0, validators_ts_1.validateFileArgument)(file, 'make-pif', 'paf');
|
|
45
|
+
(0, validators_ts_1.validateRequiredCommands)(['sh', 'sort', 'grep', 'tabix', 'bgzip']);
|
|
46
46
|
const { out, csi = false } = flags;
|
|
47
|
-
const outputFile = (0,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
await (0, pif_generator_1.waitForProcessClose)(child);
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
console.error('Error during PIF creation:', error);
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
47
|
+
const outputFile = (0, pif_generator_ts_1.getOutputFilename)(file, out);
|
|
48
|
+
const child = (0, pif_generator_ts_1.spawnSortProcess)(outputFile, csi);
|
|
49
|
+
await (0, pif_generator_ts_1.createPIF)(file, child.stdin);
|
|
50
|
+
child.stdin.end();
|
|
51
|
+
await (0, pif_generator_ts_1.waitForProcessClose)(child);
|
|
58
52
|
}
|
|
@@ -9,11 +9,11 @@ exports.getOutputFilename = getOutputFilename;
|
|
|
9
9
|
exports.waitForProcessClose = waitForProcessClose;
|
|
10
10
|
const child_process_1 = require("child_process");
|
|
11
11
|
const path_1 = __importDefault(require("path"));
|
|
12
|
-
const
|
|
13
|
-
const
|
|
12
|
+
const cigar_utils_ts_1 = require("./cigar-utils.js");
|
|
13
|
+
const file_utils_ts_1 = require("./file-utils.js");
|
|
14
14
|
async function createPIF(filename, stream) {
|
|
15
|
-
const rl1 = filename ? (0,
|
|
16
|
-
const writeWithBackpressure = (0,
|
|
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);
|
|
17
17
|
// Process the file line by line with backpressure handling
|
|
18
18
|
try {
|
|
19
19
|
for await (const line of rl1) {
|
|
@@ -24,8 +24,8 @@ async function createPIF(filename, stream) {
|
|
|
24
24
|
const CIGAR = rest[cigarIdx];
|
|
25
25
|
if (CIGAR) {
|
|
26
26
|
rest[cigarIdx] = `cg:Z:${strand === '-'
|
|
27
|
-
? (0,
|
|
28
|
-
: (0,
|
|
27
|
+
? (0, cigar_utils_ts_1.flipCigar)((0, cigar_utils_ts_1.parseCigar)(CIGAR.slice(5))).join('')
|
|
28
|
+
: (0, cigar_utils_ts_1.swapIndelCigar)(CIGAR.slice(5))}`;
|
|
29
29
|
}
|
|
30
30
|
// Write the second line and handle backpressure
|
|
31
31
|
await writeWithBackpressure(`${[`q${c1}`, l1, s1, e1, strand, c2, l2, s2, e2, ...rest].join('\t')}\n`);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.waitForProcessClose = waitForProcessClose;
|
|
4
|
-
exports.handleProcessError = handleProcessError;
|
|
5
4
|
async function waitForProcessClose(child) {
|
|
6
5
|
return new Promise((resolve, reject) => {
|
|
7
6
|
child.on('close', code => {
|
|
@@ -12,12 +11,3 @@ async function waitForProcessClose(child) {
|
|
|
12
11
|
});
|
|
13
12
|
});
|
|
14
13
|
}
|
|
15
|
-
function handleProcessError(error) {
|
|
16
|
-
if (error instanceof Error) {
|
|
17
|
-
console.error(`Process error: ${error.message}`);
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
console.error('Unknown process error:', error);
|
|
21
|
-
}
|
|
22
|
-
process.exit(1);
|
|
23
|
-
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.run = run;
|
|
4
|
-
const fs_1 = require("fs");
|
|
5
4
|
const util_1 = require("util");
|
|
6
|
-
const
|
|
5
|
+
const utils_ts_1 = require("../utils.js");
|
|
7
6
|
async function run(args) {
|
|
8
7
|
const options = {
|
|
9
8
|
help: {
|
|
@@ -27,7 +26,7 @@ async function run(args) {
|
|
|
27
26
|
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!';
|
|
28
27
|
const examples = ['$ jbrowse remove-track trackId'];
|
|
29
28
|
if (flags.help) {
|
|
30
|
-
(0,
|
|
29
|
+
(0, utils_ts_1.printHelp)({
|
|
31
30
|
description,
|
|
32
31
|
examples,
|
|
33
32
|
usage: 'jbrowse remove-track <trackId> [options]',
|
|
@@ -37,14 +36,10 @@ async function run(args) {
|
|
|
37
36
|
}
|
|
38
37
|
const trackId = positionals[0];
|
|
39
38
|
if (!trackId) {
|
|
40
|
-
|
|
41
|
-
console.error('Usage: jbrowse remove-track <trackId> [options]');
|
|
42
|
-
process.exit(1);
|
|
39
|
+
throw new Error('Missing required argument: trackId\nUsage: jbrowse remove-track <trackId> [options]');
|
|
43
40
|
}
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const target = isDir ? `${output}/config.json` : output;
|
|
47
|
-
const config = await (0, utils_1.readJsonFile)(target);
|
|
41
|
+
const target = await (0, utils_ts_1.resolveConfigPath)(flags.target, flags.out);
|
|
42
|
+
const config = await (0, utils_ts_1.readJsonFile)(target);
|
|
48
43
|
const originalLength = config.tracks?.length || 0;
|
|
49
44
|
config.tracks = config.tracks?.filter(({ trackId: id }) => id !== trackId);
|
|
50
45
|
const newLength = config.tracks?.length || 0;
|
|
@@ -52,7 +47,7 @@ async function run(args) {
|
|
|
52
47
|
console.log(`No track found with trackId: ${trackId}`);
|
|
53
48
|
}
|
|
54
49
|
else {
|
|
55
|
-
await (0,
|
|
50
|
+
await (0, utils_ts_1.writeJsonFile)(target, config);
|
|
56
51
|
console.log(`Removed track with trackId: ${trackId} from ${target}`);
|
|
57
52
|
}
|
|
58
53
|
}
|
|
@@ -4,11 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.run = run;
|
|
7
|
-
const fs_1 =
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
8
|
const util_1 = require("util");
|
|
9
9
|
const json_parse_better_errors_1 = __importDefault(require("json-parse-better-errors"));
|
|
10
|
-
const
|
|
11
|
-
const fsPromises = fs_1.default.promises;
|
|
10
|
+
const utils_ts_1 = require("../utils.js");
|
|
12
11
|
const description = 'Set a default session with views and tracks';
|
|
13
12
|
const examples = [
|
|
14
13
|
'# set default session for the config.json in your current directory',
|
|
@@ -51,7 +50,7 @@ const options = {
|
|
|
51
50
|
async function run(args) {
|
|
52
51
|
const { values: runFlags } = (0, util_1.parseArgs)({ options, args });
|
|
53
52
|
if (runFlags.help) {
|
|
54
|
-
(0,
|
|
53
|
+
(0, utils_ts_1.printHelp)({
|
|
55
54
|
description,
|
|
56
55
|
examples,
|
|
57
56
|
usage: 'jbrowse add-track <track> [options]',
|
|
@@ -60,23 +59,20 @@ async function run(args) {
|
|
|
60
59
|
return;
|
|
61
60
|
}
|
|
62
61
|
const { session, currentSession, delete: deleteDefaultSession } = runFlags;
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
const target = isDir ? `${output}/config.json` : output;
|
|
66
|
-
const configContents = await (0, utils_1.readJsonFile)(target);
|
|
62
|
+
const target = await (0, utils_ts_1.resolveConfigPath)(runFlags.target, runFlags.out);
|
|
63
|
+
const configContents = await (0, utils_ts_1.readJsonFile)(target);
|
|
67
64
|
if (deleteDefaultSession) {
|
|
68
65
|
configContents.defaultSession = undefined;
|
|
69
|
-
await (0,
|
|
66
|
+
await (0, utils_ts_1.writeJsonFile)(target, configContents);
|
|
70
67
|
}
|
|
71
68
|
else if (currentSession) {
|
|
72
69
|
console.log(`The current default session is ${JSON.stringify(configContents.defaultSession)}`);
|
|
73
|
-
process.exit();
|
|
74
70
|
}
|
|
75
71
|
else if (!session) {
|
|
76
72
|
throw new Error('Please provide a --session file');
|
|
77
73
|
}
|
|
78
74
|
else if (session) {
|
|
79
|
-
await (0,
|
|
75
|
+
await (0, utils_ts_1.writeJsonFile)(target, {
|
|
80
76
|
...configContents,
|
|
81
77
|
defaultSession: await readDefaultSessionFile(session),
|
|
82
78
|
});
|
|
@@ -85,7 +81,7 @@ async function run(args) {
|
|
|
85
81
|
async function readDefaultSessionFile(defaultSessionFile) {
|
|
86
82
|
let defaultSessionJson;
|
|
87
83
|
try {
|
|
88
|
-
defaultSessionJson = await
|
|
84
|
+
defaultSessionJson = await fs_1.promises.readFile(defaultSessionFile, {
|
|
89
85
|
encoding: 'utf8',
|
|
90
86
|
});
|
|
91
87
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findAndUpdateOrAdd = findAndUpdateOrAdd;
|
|
4
|
+
exports.saveConfigAndReport = saveConfigAndReport;
|
|
5
|
+
const utils_ts_1 = require("../../utils.js");
|
|
6
|
+
/**
|
|
7
|
+
* Generic function to find and update or add an item to a config array
|
|
8
|
+
* Returns the updated config and whether an item was overwritten
|
|
9
|
+
*/
|
|
10
|
+
function findAndUpdateOrAdd({ items, newItem, idField, getId, allowOverwrite, itemType, }) {
|
|
11
|
+
const newId = getId(newItem);
|
|
12
|
+
const idx = items.findIndex(item => getId(item) === newId);
|
|
13
|
+
if (idx !== -1) {
|
|
14
|
+
(0, utils_ts_1.debug)(`Found existing ${itemType} ${newId} in configuration`);
|
|
15
|
+
if (allowOverwrite) {
|
|
16
|
+
(0, utils_ts_1.debug)(`Overwriting ${itemType} ${newId} in configuration`);
|
|
17
|
+
const updatedItems = [...items];
|
|
18
|
+
updatedItems[idx] = newItem;
|
|
19
|
+
return { updatedItems, wasOverwritten: true };
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
throw new Error(`Cannot add ${itemType} with ${idField} ${newId}, a ${itemType} with that ${idField} already exists`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return { updatedItems: [...items, newItem], wasOverwritten: false };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Saves a config file and reports the result to the user
|
|
31
|
+
*/
|
|
32
|
+
async function saveConfigAndReport({ config, target, itemType, itemName, itemId, wasOverwritten, }) {
|
|
33
|
+
(0, utils_ts_1.debug)(`Writing configuration to file ${target}`);
|
|
34
|
+
await (0, utils_ts_1.writeJsonFile)(target, config);
|
|
35
|
+
const idPart = itemId ? ` and ${itemType}Id "${itemId}"` : '';
|
|
36
|
+
console.log(`${wasOverwritten ? 'Overwrote' : 'Added'} ${itemType} with name "${itemName}"${idPart} ${wasOverwritten ? 'in' : 'to'} ${target}`);
|
|
37
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
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.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 = {
|
|
11
|
+
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
|
+
examples: [
|
|
13
|
+
'# sort bed and pipe to bgzip',
|
|
14
|
+
'$ jbrowse sort-bed input.bed | bgzip > sorted.bed.gz',
|
|
15
|
+
'$ tabix sorted.bed.gz',
|
|
16
|
+
'',
|
|
17
|
+
'# OR pipe data via stdin: cat file.bed | jbrowse sort-bed | bgzip > sorted.bed.gz',
|
|
18
|
+
],
|
|
19
|
+
sortColumn: 2,
|
|
20
|
+
fileType: 'bed',
|
|
21
|
+
};
|
|
22
|
+
exports.GFF_CONFIG = {
|
|
23
|
+
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
|
+
examples: [
|
|
25
|
+
'# sort gff and pipe to bgzip',
|
|
26
|
+
'$ jbrowse sort-gff input.gff | bgzip > sorted.gff.gz',
|
|
27
|
+
'$ tabix sorted.gff.gz',
|
|
28
|
+
'',
|
|
29
|
+
'# sort gff from stdin',
|
|
30
|
+
'$ cat input.gff | jbrowse sort-gff | bgzip > sorted.gff.gz',
|
|
31
|
+
],
|
|
32
|
+
sortColumn: 4,
|
|
33
|
+
fileType: 'gff',
|
|
34
|
+
};
|
|
35
|
+
function getMinimalEnvironment() {
|
|
36
|
+
return {
|
|
37
|
+
...process.env,
|
|
38
|
+
LC_ALL: 'C',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function createSortCommandForStdin(sortColumn) {
|
|
42
|
+
const tmpFile = tmp_1.default.fileSync({ prefix: 'jbrowse-sort' }).name;
|
|
43
|
+
const sortCmd = `sort -t"\`printf '\\t'\`" -k1,1 -k${sortColumn},${sortColumn}n`;
|
|
44
|
+
return `cat > ${tmpFile} && (grep "^#" ${tmpFile}; grep -v "^#" ${tmpFile} | ${sortCmd}) && rm -f ${tmpFile}`;
|
|
45
|
+
}
|
|
46
|
+
function createSortCommandForFile(file, sortColumn) {
|
|
47
|
+
return `(grep "^#" "${file}"; grep -v "^#" "${file}" | sort -t"\`printf '\\t'\`" -k1,1 -k${sortColumn},${sortColumn}n)`;
|
|
48
|
+
}
|
|
49
|
+
function spawnSortProcess(file, sortColumn) {
|
|
50
|
+
const command = file
|
|
51
|
+
? createSortCommandForFile(file, sortColumn)
|
|
52
|
+
: createSortCommandForStdin(sortColumn);
|
|
53
|
+
return (0, child_process_1.spawn)('sh', ['-c', command], {
|
|
54
|
+
env: getMinimalEnvironment(),
|
|
55
|
+
stdio: 'inherit',
|
|
56
|
+
});
|
|
57
|
+
}
|