@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.
Files changed (59) hide show
  1. package/README.md +4 -0
  2. package/bin/run +0 -0
  3. package/bundle/index.js +2280 -2722
  4. package/dist/bin.js +2 -2
  5. package/dist/commands/{add-assembly.js → add-assembly/index.js} +10 -10
  6. package/dist/commands/{assembly-utils.js → add-assembly/utils.js} +69 -105
  7. package/dist/commands/add-connection.js +11 -16
  8. package/dist/commands/add-track-json.js +26 -31
  9. package/dist/commands/add-track-utils/track-config.js +3 -15
  10. package/dist/commands/add-track-utils/validators.js +4 -9
  11. package/dist/commands/add-track.js +23 -25
  12. package/dist/commands/admin-server/index.js +100 -0
  13. package/dist/commands/{admin-server-utils.js → admin-server/utils.js} +7 -58
  14. package/dist/commands/create.js +8 -8
  15. package/dist/commands/{make-pif.js → make-pif/index.js} +11 -17
  16. package/dist/commands/{make-pif-utils → make-pif}/pif-generator.js +6 -6
  17. package/dist/commands/{sort-bed-utils/process-utils.js → process-utils.js} +0 -10
  18. package/dist/commands/remove-track.js +6 -11
  19. package/dist/commands/set-default-session.js +8 -12
  20. package/dist/commands/shared/config-operations.js +37 -0
  21. package/dist/commands/shared/sort-utils.js +57 -0
  22. package/dist/commands/shared/validators.js +18 -0
  23. package/dist/commands/sort-bed.js +13 -24
  24. package/dist/commands/sort-gff.js +13 -24
  25. package/dist/commands/text-index/adapter-utils.js +43 -0
  26. package/dist/commands/text-index/aggregate.js +52 -0
  27. package/dist/commands/{text-index.js → text-index/command.js} +13 -6
  28. package/dist/commands/text-index/config-utils.js +134 -0
  29. package/dist/commands/{text-index-utils → text-index}/file-list.js +12 -15
  30. package/dist/commands/text-index/index.js +11 -0
  31. package/dist/commands/{text-index-utils → text-index}/indexing-utils.js +30 -20
  32. package/dist/commands/text-index/per-track.js +54 -0
  33. package/dist/commands/track-utils.js +33 -33
  34. package/dist/commands/upgrade.js +8 -8
  35. package/dist/index.js +39 -27
  36. package/dist/types/common.js +9 -8
  37. package/dist/types/gff3Adapter.js +17 -48
  38. package/dist/types/streamUtils.js +66 -0
  39. package/dist/types/vcfAdapter.js +17 -54
  40. package/dist/util.js +14 -7
  41. package/dist/utils.js +10 -5
  42. package/package.json +14 -16
  43. package/dist/commands/admin-server.js +0 -55
  44. package/dist/commands/make-pif-utils/validators.js +0 -22
  45. package/dist/commands/sort-bed-utils/constants.js +0 -12
  46. package/dist/commands/sort-bed-utils/sort-utils.js +0 -24
  47. package/dist/commands/sort-bed-utils/validators.js +0 -22
  48. package/dist/commands/sort-gff-utils/constants.js +0 -13
  49. package/dist/commands/sort-gff-utils/process-utils.js +0 -23
  50. package/dist/commands/sort-gff-utils/sort-utils.js +0 -55
  51. package/dist/commands/sort-gff-utils/validators.js +0 -21
  52. package/dist/commands/text-index-utils/adapter-utils.js +0 -63
  53. package/dist/commands/text-index-utils/aggregate.js +0 -87
  54. package/dist/commands/text-index-utils/config-utils.js +0 -59
  55. package/dist/commands/text-index-utils/index.js +0 -9
  56. package/dist/commands/text-index-utils/per-track.js +0 -65
  57. /package/dist/commands/{make-pif-utils → make-pif}/cigar-utils.js +0 -0
  58. /package/dist/commands/{make-pif-utils → make-pif}/file-utils.js +0 -0
  59. /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 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");
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, utils_1.printHelp)({
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, validators_1.validateLoadOption)(flags.load);
133
+ (0, validators_ts_1.validateLoadOption)(flags.load);
134
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);
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, validators_1.createTargetDirectory)(configDir, subDir);
139
+ (0, validators_ts_1.createTargetDirectory)(configDir, subDir);
141
140
  const location = track;
142
- const mapLoc = (p) => (0, track_config_1.mapLocationForFiles)(p, load, subDir);
143
- let adapter = (0, adapter_utils_1.guessAdapter)({
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, 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)({
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, track_utils_1.createTrackConfiguration)({
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, track_utils_1.addTrackToConfig)({
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, track_utils_1.processTrackFiles)({
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, track_utils_1.saveTrackConfigAndReport)({
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 cors_1 = __importDefault(require("cors"));
18
- const express_1 = __importDefault(require("express"));
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 output = root;
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, utils_1.debug)(`Found existing config file ${outFile}`);
49
+ (0, utils_ts_1.debug)(`Found existing config file ${outFile}`);
55
50
  }
56
51
  else {
57
- (0, utils_1.debug)(`Creating config file ${outFile}`);
58
- await (0, utils_1.writeJsonFile)(outFile, {
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, utils_1.debug)(`Removed admin key file: ${keyPath}`);
198
+ (0, utils_ts_1.debug)(`Removed admin key file: ${keyPath}`);
250
199
  }
251
200
  catch (error) {
252
201
  // Ignore errors when cleaning up
@@ -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 fetchWithProxy_1 = __importDefault(require("../fetchWithProxy"));
11
- const utils_1 = require("../utils");
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, utils_1.printHelp)({
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, utils_1.fetchGithubVersions)()).map(version => version.tag_name);
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, utils_1.getBranch)('main') : '') ||
100
- (branch ? await (0, utils_1.getBranch)(branch) : '') ||
101
- (tag ? await (0, utils_1.getTag)(tag) : await (0, utils_1.getLatest)());
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, fetchWithProxy_1.default)(locationUrl);
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 utils_1 = require("../utils");
6
- const pif_generator_1 = require("./make-pif-utils/pif-generator");
7
- const validators_1 = require("./make-pif-utils/validators");
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, utils_1.printHelp)({
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, validators_1.validateFileArgument)(file);
45
- (0, validators_1.validateRequiredCommands)();
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, pif_generator_1.getOutputFilename)(file, out);
48
- try {
49
- const child = (0, pif_generator_1.spawnSortProcess)(outputFile, csi);
50
- await (0, pif_generator_1.createPIF)(file, child.stdin);
51
- child.stdin.end();
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 cigar_utils_1 = require("./cigar-utils");
13
- const file_utils_1 = require("./file-utils");
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, file_utils_1.getReadline)(filename) : (0, file_utils_1.getStdReadline)();
16
- const writeWithBackpressure = (0, file_utils_1.createWriteWithBackpressure)(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);
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, cigar_utils_1.flipCigar)((0, cigar_utils_1.parseCigar)(CIGAR.slice(5))).join('')
28
- : (0, cigar_utils_1.swapIndelCigar)(CIGAR.slice(5))}`;
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 utils_1 = require("../utils");
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, utils_1.printHelp)({
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
- console.error('Error: Missing required argument: trackId');
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 output = flags.target || flags.out || '.';
45
- const isDir = (await fs_1.promises.lstat(output)).isDirectory();
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, utils_1.writeJsonFile)(target, config);
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 = __importDefault(require("fs"));
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 utils_1 = require("../utils");
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, utils_1.printHelp)({
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 output = runFlags.target || runFlags.out || '.';
64
- const isDir = (await fsPromises.lstat(output)).isDirectory();
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, utils_1.writeJsonFile)(target, configContents);
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, utils_1.writeJsonFile)(target, {
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 fsPromises.readFile(defaultSessionFile, {
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
+ }