@jbrowse/cli 1.4.4 → 1.5.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.
@@ -2,9 +2,11 @@ import { flags } from '@oclif/command';
2
2
  import JBrowseCommand from '../base';
3
3
  interface UriLocation {
4
4
  uri: string;
5
+ locationType: 'UriLocation';
5
6
  }
6
7
  interface LocalPathLocation {
7
8
  localPath: string;
9
+ locationType: 'LocalPathLocation';
8
10
  }
9
11
  export default class AddTrack extends JBrowseCommand {
10
12
  target: string;
@@ -40,21 +42,17 @@ export default class AddTrack extends JBrowseCommand {
40
42
  index: string;
41
43
  index2?: undefined;
42
44
  } | {
43
- file?: undefined;
45
+ file: string;
44
46
  index?: undefined;
45
47
  index2?: undefined;
46
48
  } | {
47
- file: string;
48
- index: undefined;
49
+ file?: undefined;
50
+ index?: undefined;
49
51
  index2?: undefined;
50
52
  } | {
51
53
  file: string;
52
54
  index: string;
53
55
  index2: string;
54
- } | {
55
- file: string;
56
- index?: undefined;
57
- index2?: undefined;
58
56
  };
59
57
  guessAdapter(fileName: string, protocol: string, index?: string): {
60
58
  type: string;
@@ -65,7 +63,9 @@ export default class AddTrack extends JBrowseCommand {
65
63
  };
66
64
  cramLocation?: undefined;
67
65
  craiLocation?: undefined;
66
+ gffLocation?: undefined;
68
67
  gffGzLocation?: undefined;
68
+ gtfLocation?: undefined;
69
69
  vcfLocation?: undefined;
70
70
  vcfGzLocation?: undefined;
71
71
  bedGzLocation?: undefined;
@@ -85,7 +85,9 @@ export default class AddTrack extends JBrowseCommand {
85
85
  craiLocation: UriLocation | LocalPathLocation;
86
86
  bamLocation?: undefined;
87
87
  index?: undefined;
88
+ gffLocation?: undefined;
88
89
  gffGzLocation?: undefined;
90
+ gtfLocation?: undefined;
89
91
  vcfLocation?: undefined;
90
92
  vcfGzLocation?: undefined;
91
93
  bedGzLocation?: undefined;
@@ -101,11 +103,13 @@ export default class AddTrack extends JBrowseCommand {
101
103
  pafLocation?: undefined;
102
104
  } | {
103
105
  type: string;
106
+ gffLocation: UriLocation | LocalPathLocation;
104
107
  bamLocation?: undefined;
105
108
  index?: undefined;
106
109
  cramLocation?: undefined;
107
110
  craiLocation?: undefined;
108
111
  gffGzLocation?: undefined;
112
+ gtfLocation?: undefined;
109
113
  vcfLocation?: undefined;
110
114
  vcfGzLocation?: undefined;
111
115
  bedGzLocation?: undefined;
@@ -129,6 +133,30 @@ export default class AddTrack extends JBrowseCommand {
129
133
  bamLocation?: undefined;
130
134
  cramLocation?: undefined;
131
135
  craiLocation?: undefined;
136
+ gffLocation?: undefined;
137
+ gtfLocation?: undefined;
138
+ vcfLocation?: undefined;
139
+ vcfGzLocation?: undefined;
140
+ bedGzLocation?: undefined;
141
+ bigBedLocation?: undefined;
142
+ bigWigLocation?: undefined;
143
+ fastaLocation?: undefined;
144
+ faiLocation?: undefined;
145
+ gziLocation?: undefined;
146
+ twoBitLocation?: undefined;
147
+ rootUrlTemplate?: undefined;
148
+ endpoint?: undefined;
149
+ hicLocation?: undefined;
150
+ pafLocation?: undefined;
151
+ } | {
152
+ type: string;
153
+ gtfLocation: UriLocation | LocalPathLocation;
154
+ bamLocation?: undefined;
155
+ index?: undefined;
156
+ cramLocation?: undefined;
157
+ craiLocation?: undefined;
158
+ gffLocation?: undefined;
159
+ gffGzLocation?: undefined;
132
160
  vcfLocation?: undefined;
133
161
  vcfGzLocation?: undefined;
134
162
  bedGzLocation?: undefined;
@@ -149,7 +177,9 @@ export default class AddTrack extends JBrowseCommand {
149
177
  index?: undefined;
150
178
  cramLocation?: undefined;
151
179
  craiLocation?: undefined;
180
+ gffLocation?: undefined;
152
181
  gffGzLocation?: undefined;
182
+ gtfLocation?: undefined;
153
183
  vcfGzLocation?: undefined;
154
184
  bedGzLocation?: undefined;
155
185
  bigBedLocation?: undefined;
@@ -172,8 +202,32 @@ export default class AddTrack extends JBrowseCommand {
172
202
  bamLocation?: undefined;
173
203
  cramLocation?: undefined;
174
204
  craiLocation?: undefined;
205
+ gffLocation?: undefined;
206
+ gffGzLocation?: undefined;
207
+ gtfLocation?: undefined;
208
+ vcfLocation?: undefined;
209
+ bedGzLocation?: undefined;
210
+ bigBedLocation?: undefined;
211
+ bigWigLocation?: undefined;
212
+ fastaLocation?: undefined;
213
+ faiLocation?: undefined;
214
+ gziLocation?: undefined;
215
+ twoBitLocation?: undefined;
216
+ rootUrlTemplate?: undefined;
217
+ endpoint?: undefined;
218
+ hicLocation?: undefined;
219
+ pafLocation?: undefined;
220
+ } | {
221
+ type: string;
222
+ bamLocation?: undefined;
223
+ index?: undefined;
224
+ cramLocation?: undefined;
225
+ craiLocation?: undefined;
226
+ gffLocation?: undefined;
175
227
  gffGzLocation?: undefined;
228
+ gtfLocation?: undefined;
176
229
  vcfLocation?: undefined;
230
+ vcfGzLocation?: undefined;
177
231
  bedGzLocation?: undefined;
178
232
  bigBedLocation?: undefined;
179
233
  bigWigLocation?: undefined;
@@ -195,7 +249,9 @@ export default class AddTrack extends JBrowseCommand {
195
249
  bamLocation?: undefined;
196
250
  cramLocation?: undefined;
197
251
  craiLocation?: undefined;
252
+ gffLocation?: undefined;
198
253
  gffGzLocation?: undefined;
254
+ gtfLocation?: undefined;
199
255
  vcfLocation?: undefined;
200
256
  vcfGzLocation?: undefined;
201
257
  bigBedLocation?: undefined;
@@ -215,7 +271,9 @@ export default class AddTrack extends JBrowseCommand {
215
271
  index?: undefined;
216
272
  cramLocation?: undefined;
217
273
  craiLocation?: undefined;
274
+ gffLocation?: undefined;
218
275
  gffGzLocation?: undefined;
276
+ gtfLocation?: undefined;
219
277
  vcfLocation?: undefined;
220
278
  vcfGzLocation?: undefined;
221
279
  bedGzLocation?: undefined;
@@ -235,7 +293,9 @@ export default class AddTrack extends JBrowseCommand {
235
293
  index?: undefined;
236
294
  cramLocation?: undefined;
237
295
  craiLocation?: undefined;
296
+ gffLocation?: undefined;
238
297
  gffGzLocation?: undefined;
298
+ gtfLocation?: undefined;
239
299
  vcfLocation?: undefined;
240
300
  vcfGzLocation?: undefined;
241
301
  bedGzLocation?: undefined;
@@ -256,7 +316,9 @@ export default class AddTrack extends JBrowseCommand {
256
316
  index?: undefined;
257
317
  cramLocation?: undefined;
258
318
  craiLocation?: undefined;
319
+ gffLocation?: undefined;
259
320
  gffGzLocation?: undefined;
321
+ gtfLocation?: undefined;
260
322
  vcfLocation?: undefined;
261
323
  vcfGzLocation?: undefined;
262
324
  bedGzLocation?: undefined;
@@ -277,7 +339,9 @@ export default class AddTrack extends JBrowseCommand {
277
339
  index?: undefined;
278
340
  cramLocation?: undefined;
279
341
  craiLocation?: undefined;
342
+ gffLocation?: undefined;
280
343
  gffGzLocation?: undefined;
344
+ gtfLocation?: undefined;
281
345
  vcfLocation?: undefined;
282
346
  vcfGzLocation?: undefined;
283
347
  bedGzLocation?: undefined;
@@ -295,7 +359,9 @@ export default class AddTrack extends JBrowseCommand {
295
359
  index?: undefined;
296
360
  cramLocation?: undefined;
297
361
  craiLocation?: undefined;
362
+ gffLocation?: undefined;
298
363
  gffGzLocation?: undefined;
364
+ gtfLocation?: undefined;
299
365
  vcfLocation?: undefined;
300
366
  vcfGzLocation?: undefined;
301
367
  bedGzLocation?: undefined;
@@ -315,7 +381,9 @@ export default class AddTrack extends JBrowseCommand {
315
381
  index?: undefined;
316
382
  cramLocation?: undefined;
317
383
  craiLocation?: undefined;
384
+ gffLocation?: undefined;
318
385
  gffGzLocation?: undefined;
386
+ gtfLocation?: undefined;
319
387
  vcfLocation?: undefined;
320
388
  vcfGzLocation?: undefined;
321
389
  bedGzLocation?: undefined;
@@ -335,7 +403,9 @@ export default class AddTrack extends JBrowseCommand {
335
403
  index?: undefined;
336
404
  cramLocation?: undefined;
337
405
  craiLocation?: undefined;
406
+ gffLocation?: undefined;
338
407
  gffGzLocation?: undefined;
408
+ gtfLocation?: undefined;
339
409
  vcfLocation?: undefined;
340
410
  vcfGzLocation?: undefined;
341
411
  bedGzLocation?: undefined;
@@ -355,7 +425,9 @@ export default class AddTrack extends JBrowseCommand {
355
425
  index?: undefined;
356
426
  cramLocation?: undefined;
357
427
  craiLocation?: undefined;
428
+ gffLocation?: undefined;
358
429
  gffGzLocation?: undefined;
430
+ gtfLocation?: undefined;
359
431
  vcfLocation?: undefined;
360
432
  vcfGzLocation?: undefined;
361
433
  bedGzLocation?: undefined;
@@ -375,7 +447,9 @@ export default class AddTrack extends JBrowseCommand {
375
447
  index?: undefined;
376
448
  cramLocation?: undefined;
377
449
  craiLocation?: undefined;
450
+ gffLocation?: undefined;
378
451
  gffGzLocation?: undefined;
452
+ gtfLocation?: undefined;
379
453
  vcfLocation?: undefined;
380
454
  vcfGzLocation?: undefined;
381
455
  bedGzLocation?: undefined;
@@ -2,18 +2,20 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const command_1 = require("@oclif/command");
5
- const fs_1 = tslib_1.__importDefault(require("fs"));
6
- const path_1 = tslib_1.__importDefault(require("path"));
7
- const json_parse_better_errors_1 = tslib_1.__importDefault(require("json-parse-better-errors"));
8
- const base_1 = tslib_1.__importDefault(require("../base"));
9
- const fsPromises = fs_1.default.promises;
5
+ const fs_1 = (0, tslib_1.__importDefault)(require("fs"));
6
+ const path_1 = (0, tslib_1.__importDefault)(require("path"));
7
+ const json_parse_better_errors_1 = (0, tslib_1.__importDefault)(require("json-parse-better-errors"));
8
+ const base_1 = (0, tslib_1.__importDefault)(require("../base"));
9
+ const { copyFile, rename, symlink, lstat, unlink } = fs_1.default.promises;
10
+ const { COPYFILE_EXCL } = fs_1.default.constants;
11
+ const isUrl = (loc) => loc === null || loc === void 0 ? void 0 : loc.match(/^https?:\/\//);
10
12
  class AddTrack extends base_1.default {
11
13
  async run() {
12
14
  const { args: runArgs, flags: runFlags } = this.parse(AddTrack);
13
15
  const { track: argsTrack } = runArgs;
14
16
  const { config, skipCheck, force, overwrite, category, description, load, subDir, target, protocol, out, indexFile: index, } = runFlags;
15
17
  const output = target || out || '.';
16
- const isDir = (await fsPromises.lstat(output)).isDirectory();
18
+ const isDir = (await lstat(output)).isDirectory();
17
19
  this.target = isDir ? `${output}/config.json` : output;
18
20
  let { trackType, trackId, name, assemblyNames } = runFlags;
19
21
  const configDirectory = path_1.default.dirname(this.target);
@@ -27,7 +29,6 @@ class AddTrack extends base_1.default {
27
29
  }
28
30
  }
29
31
  const location = argsTrack;
30
- const isUrl = (loc) => loc === null || loc === void 0 ? void 0 : loc.match(/^https?:\/\//);
31
32
  const inPlace = load === 'inPlace';
32
33
  const useIndex = isUrl(index) || inPlace || index;
33
34
  const effectiveLocation = isUrl(location) || inPlace
@@ -76,13 +77,11 @@ class AddTrack extends base_1.default {
76
77
  this.debug(`Type is: ${trackType}`);
77
78
  this.debug(`Track is :${trackId}`);
78
79
  this.debug(`Assembly name(s) is :${assemblyNames}`);
79
- const configObj = config ? json_parse_better_errors_1.default(config) : {};
80
+ const configObj = config ? (0, json_parse_better_errors_1.default)(config) : {};
80
81
  const trackConfig = Object.assign({ type: trackType, trackId,
81
- name, category: category ? category.split(',').map(c => c.trim()) : undefined, assemblyNames: assemblyNames.split(',').map(a => a.trim()), adapter }, configObj);
82
+ name,
83
+ adapter, category: category === null || category === void 0 ? void 0 : category.split(',').map(c => c.trim()), assemblyNames: assemblyNames.split(',').map(a => a.trim()), description }, configObj);
82
84
  this.debug(`Track location: ${location}, index: ${adapter ? adapter.index : ''}`);
83
- if (description) {
84
- trackConfig.description = description;
85
- }
86
85
  // any special track modifications go here
87
86
  switch (trackType) {
88
87
  case 'AlignmentsTrack': {
@@ -113,56 +112,27 @@ class AddTrack extends base_1.default {
113
112
  else {
114
113
  configContents.tracks.push(trackConfig);
115
114
  }
116
- // copy/symlinks/moves the track into the jbrowse installation directory
117
- const filePaths = Object.values(this.guessFileNames(location, index)).filter(f => !!f);
118
- const destinationFn = (dir, file) => path_1.default.join(dir, subDir, path_1.default.basename(file));
119
- switch (load) {
120
- case 'copy': {
121
- await Promise.all(filePaths.map(async (filePath) => {
122
- const dest = destinationFn(configDirectory, filePath);
123
- try {
124
- if (force && fs_1.default.existsSync(dest)) {
125
- await fsPromises.unlink(dest);
126
- }
127
- }
128
- catch (e) {
129
- this.error(e);
130
- }
131
- return fsPromises.copyFile(filePath, dest, fs_1.default.constants.COPYFILE_EXCL);
132
- }));
133
- break;
134
- }
135
- case 'symlink': {
136
- await Promise.all(filePaths.map(async (filePath) => {
137
- const dest = destinationFn(configDirectory, filePath);
138
- try {
139
- if (force && fs_1.default.existsSync(dest)) {
140
- await fsPromises.unlink(dest);
141
- }
142
- }
143
- catch (e) {
144
- this.error(e);
145
- }
146
- return fsPromises.symlink(filePath, dest);
147
- }));
148
- break;
115
+ const filePaths = Object.values(this.guessFileNames(location, index)).filter((f) => !!f);
116
+ // get path of destination, and remove file at that path if it exists and
117
+ // force is set
118
+ const destinationFn = async (dir, file) => {
119
+ const dest = path_1.default.join(dir, subDir, path_1.default.basename(file));
120
+ if (force && fs_1.default.existsSync(dest)) {
121
+ await unlink(dest);
149
122
  }
150
- case 'move': {
151
- await Promise.all(filePaths.map(async (filePath) => {
152
- const dest = destinationFn(configDirectory, filePath);
153
- try {
154
- if (force && fs_1.default.existsSync(dest)) {
155
- await fsPromises.unlink(dest);
156
- }
157
- }
158
- catch (e) {
159
- this.error(e);
160
- }
161
- return fsPromises.rename(filePath, dest);
162
- }));
163
- break;
123
+ return dest;
124
+ };
125
+ const callbacks = {
126
+ copy: (src, dest) => copyFile(src, dest, COPYFILE_EXCL),
127
+ move: (src, dest) => rename(src, dest),
128
+ symlink: (src, dest) => symlink(src, dest),
129
+ };
130
+ await Promise.all(filePaths.map(async (src) => {
131
+ const dest = await destinationFn(configDirectory, src);
132
+ if (load === 'copy' || load === 'move' || load === 'symlink') {
133
+ return callbacks[load](src, dest);
164
134
  }
165
- }
135
+ }));
166
136
  this.debug(`Writing configuration to file ${this.target}`);
167
137
  await this.writeJsonFile(this.target, configContents);
168
138
  this.log(`${idx !== -1 ? 'Overwrote' : 'Added'} track "${name}" ${idx !== -1 ? 'in' : 'to'} ${this.target}`);
@@ -177,28 +147,34 @@ class AddTrack extends base_1.default {
177
147
  if (/\.cram$/i.test(fileName)) {
178
148
  return {
179
149
  file: fileName,
180
- index: `${fileName}.crai`,
150
+ index: index || `${fileName}.crai`,
181
151
  };
182
152
  }
183
153
  if (/\.gff3?$/i.test(fileName)) {
184
- return {};
154
+ return {
155
+ file: fileName,
156
+ };
185
157
  }
186
158
  if (/\.gff3?\.b?gz$/i.test(fileName)) {
187
159
  return {
188
160
  file: fileName,
189
- index: `${fileName}.tbi`,
161
+ index: index || `${fileName}.tbi`,
190
162
  };
191
163
  }
192
164
  if (/\.gtf?$/i.test(fileName)) {
193
- return {};
165
+ return {
166
+ file: fileName,
167
+ };
194
168
  }
195
169
  if (/\.vcf$/i.test(fileName)) {
196
- return {};
170
+ return {
171
+ file: fileName,
172
+ };
197
173
  }
198
174
  if (/\.vcf\.b?gz$/i.test(fileName)) {
199
175
  return {
200
176
  file: fileName,
201
- index: `${fileName}.tbi`,
177
+ index: index || `${fileName}.tbi`,
202
178
  };
203
179
  }
204
180
  if (/\.vcf\.idx$/i.test(fileName)) {
@@ -219,13 +195,11 @@ class AddTrack extends base_1.default {
219
195
  if (/\.(bb|bigbed)$/i.test(fileName)) {
220
196
  return {
221
197
  file: fileName,
222
- index: undefined,
223
198
  };
224
199
  }
225
200
  if (/\.(bw|bigwig)$/i.test(fileName)) {
226
201
  return {
227
202
  file: fileName,
228
- index: undefined,
229
203
  };
230
204
  }
231
205
  if (/\.(fa|fasta|fas|fna|mfa)$/i.test(fileName)) {
@@ -275,10 +249,13 @@ class AddTrack extends base_1.default {
275
249
  guessAdapter(fileName, protocol, index) {
276
250
  function makeLocation(location) {
277
251
  if (protocol === 'uri') {
278
- return { uri: location };
252
+ return { uri: location, locationType: 'UriLocation' };
279
253
  }
280
254
  if (protocol === 'localPath') {
281
- return { localPath: location };
255
+ return {
256
+ localPath: location,
257
+ locationType: 'LocalPathLocation',
258
+ };
282
259
  }
283
260
  throw new Error(`invalid protocol ${protocol}`);
284
261
  }
@@ -301,7 +278,8 @@ class AddTrack extends base_1.default {
301
278
  }
302
279
  if (/\.gff3?$/i.test(fileName)) {
303
280
  return {
304
- type: 'UNSUPPORTED',
281
+ type: 'Gff3Adapter',
282
+ gffLocation: makeLocation(fileName),
305
283
  };
306
284
  }
307
285
  if (/\.gff3?\.b?gz$/i.test(fileName)) {
@@ -316,7 +294,8 @@ class AddTrack extends base_1.default {
316
294
  }
317
295
  if (/\.gtf?$/i.test(fileName)) {
318
296
  return {
319
- type: 'UNSUPPORTED',
297
+ type: 'GtfAdapter',
298
+ gtfLocation: makeLocation(fileName),
320
299
  };
321
300
  }
322
301
  if (/\.vcf$/i.test(fileName)) {
@@ -439,18 +418,23 @@ class AddTrack extends base_1.default {
439
418
  exports.default = AddTrack;
440
419
  AddTrack.description = 'Add a track to a JBrowse 2 configuration';
441
420
  AddTrack.examples = [
442
- `# --load copy copies my.bam and my.bam.bai to current directory and adds track to config.json`,
443
- '$ jbrowse add-track /path/to/my.bam --load copy\n',
444
- `# same as above, but specify path to bai file`,
445
- '$ jbrowse add-track /path/to/my.bam --indexFile /path/to/my.bai --load copy\n',
446
- `# --load symlink creates symlink in /path/to/jb2/ directory for this file, and adds track to config.json`,
447
- '$ jbrowse add-track /path/to/my.bam --target /path/to/jb2/config.json --load symlink\n',
448
- `# no --load flag to add literal URL for this track to config.json`,
449
- '$ jbrowse add-track https://mywebsite.com/my.bam\n',
450
- `# --load move to move the file `,
451
- `$ jbrowse add-track /path/to/my.bam --name 'New Track' --load move\n`,
452
- `# --load inPlace puts /url/relative/path.bam in the config without performing any file operations`,
453
- `$ jbrowse add-track /url/relative/path.bam --trackId AlignmentsTrack1 --load url --overwrite`,
421
+ '# copy /path/to/my.bam and /path/to/my.bam.bai to current directory and adds track to config.json',
422
+ '$ jbrowse add-track /path/to/my.bam --load copy',
423
+ '',
424
+ '# copy my.bam and my.bam.bai to /path/to/jb2/bam and adds track entry to /path/to/jb2/bam/config.json',
425
+ '$ jbrowse add-track my.bam --load copy --out /path/to/jb2 --subDir bam',
426
+ '',
427
+ `# same as above, but specify path to bai file. needed for if the bai file does not have the extension .bam.bai`,
428
+ '$ jbrowse add-track my.bam --indexFile my.bai --load copy',
429
+ '',
430
+ '# creates symlink for /path/to/my.bam and adds track to config.json',
431
+ '$ jbrowse add-track /path/to/my.bam --load symlink',
432
+ '',
433
+ '# add track from URL to config.json, no --load flag needed',
434
+ '$ jbrowse add-track https://mywebsite.com/my.bam',
435
+ '',
436
+ '# --load inPlace adds a track without doing file operations',
437
+ '$ jbrowse add-track /url/relative/path.bam --load inPlace',
454
438
  ];
455
439
  AddTrack.args = [
456
440
  {
@@ -1,14 +1,12 @@
1
1
  import { flags } from '@oclif/command';
2
2
  import JBrowseCommand from '../base';
3
3
  export default class AdminServer extends JBrowseCommand {
4
- private target;
5
4
  static description: string;
6
5
  static examples: string[];
7
6
  static flags: {
8
7
  port: flags.IOptionFlag<string | undefined>;
9
8
  target: flags.IOptionFlag<string | undefined>;
10
9
  out: flags.IOptionFlag<string | undefined>;
11
- skipCheck: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
12
10
  help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
13
11
  };
14
12
  run(): Promise<void>;
@@ -2,15 +2,15 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const command_1 = require("@oclif/command");
5
- const fs_1 = tslib_1.__importDefault(require("fs"));
6
- const crypto_1 = tslib_1.__importDefault(require("crypto"));
7
- const boxen_1 = tslib_1.__importDefault(require("boxen"));
8
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
9
- const os_1 = tslib_1.__importDefault(require("os"));
10
- const express_1 = tslib_1.__importDefault(require("express"));
11
- const cors_1 = tslib_1.__importDefault(require("cors"));
12
- const base_1 = tslib_1.__importDefault(require("../base"));
13
- const fsPromises = fs_1.default.promises;
5
+ const path_1 = (0, tslib_1.__importDefault)(require("path"));
6
+ const fs_1 = (0, tslib_1.__importDefault)(require("fs"));
7
+ const crypto_1 = (0, tslib_1.__importDefault)(require("crypto"));
8
+ const boxen_1 = (0, tslib_1.__importDefault)(require("boxen"));
9
+ const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
10
+ const os_1 = (0, tslib_1.__importDefault)(require("os"));
11
+ const express_1 = (0, tslib_1.__importDefault)(require("express"));
12
+ const cors_1 = (0, tslib_1.__importDefault)(require("cors"));
13
+ const base_1 = (0, tslib_1.__importDefault)(require("../base"));
14
14
  function isValidPort(port) {
15
15
  return port > 0 && port < 65535;
16
16
  }
@@ -21,25 +21,25 @@ function generateKey() {
21
21
  class AdminServer extends base_1.default {
22
22
  async run() {
23
23
  const { flags: runFlags } = this.parse(AdminServer);
24
- const output = runFlags.target || runFlags.out || '.';
25
- const isDir = (await fsPromises.lstat(output)).isDirectory();
26
- this.target = isDir ? `${output}/config.json` : output;
27
- // check if the config file exists, if none exists write default
28
- const defaultConfig = {
29
- assemblies: [],
30
- configuration: {},
31
- connections: [],
32
- defaultSession: {
33
- name: 'New Session',
34
- },
35
- tracks: [],
36
- };
37
- if (fs_1.default.existsSync(this.target)) {
38
- this.debug(`Found existing config file ${this.target}`);
24
+ const { target, out } = runFlags;
25
+ const output = target || out || '.';
26
+ const isDir = fs_1.default.lstatSync(output).isDirectory();
27
+ const outFile = isDir ? `${output}/config.json` : output;
28
+ const baseDir = path_1.default.dirname(outFile);
29
+ if (fs_1.default.existsSync(outFile)) {
30
+ this.debug(`Found existing config file ${outFile}`);
39
31
  }
40
32
  else {
41
- this.debug(`Creating config file ${this.target}`);
42
- await this.writeJsonFile('./config.json', defaultConfig);
33
+ this.debug(`Creating config file ${outFile}`);
34
+ await this.writeJsonFile('./config.json', {
35
+ assemblies: [],
36
+ configuration: {},
37
+ connections: [],
38
+ defaultSession: {
39
+ name: 'New Session',
40
+ },
41
+ tracks: [],
42
+ });
43
43
  }
44
44
  // start server with admin key in URL query string
45
45
  let port = 9090;
@@ -51,21 +51,28 @@ class AdminServer extends base_1.default {
51
51
  port = parseInt(runFlags.port, 10);
52
52
  }
53
53
  }
54
- const app = express_1.default();
54
+ const app = (0, express_1.default)();
55
55
  app.use(express_1.default.static('.'));
56
- app.use(cors_1.default());
56
+ app.use((0, cors_1.default)());
57
57
  // POST route to save config
58
58
  app.use(express_1.default.json());
59
59
  app.post('/updateConfig', async (req, res) => {
60
- this.debug('Req body: ', req.body);
61
- if (req.body.adminKey === adminKey) {
60
+ if (adminKey === req.body.adminKey) {
62
61
  this.debug('Admin key matches');
63
62
  try {
64
- await this.writeJsonFile(this.target, req.body.config);
63
+ // use directory traversal prevention
64
+ // https://nodejs.org/en/knowledge/file-system/security/introduction/#preventing-directory-traversal
65
+ const filename = req.body.configPath
66
+ ? path_1.default.join(baseDir, req.body.configPath)
67
+ : outFile;
68
+ if (filename.indexOf(baseDir) !== 0) {
69
+ throw new Error(`Cannot perform directory traversal outside of ${baseDir}`);
70
+ }
71
+ await this.writeJsonFile(filename, req.body.config);
65
72
  res.send('Config written to disk');
66
73
  }
67
- catch (_a) {
68
- res.status(500).send('Could not write config file');
74
+ catch (e) {
75
+ res.status(500).send(`Could not write config file ${e}`);
69
76
  }
70
77
  }
71
78
  else {
@@ -110,7 +117,7 @@ class AdminServer extends base_1.default {
110
117
  if (networkAddress) {
111
118
  message += `\n${chalk_1.default.bold('- On Your Network:')} ${networkAddress}`;
112
119
  }
113
- this.log(boxen_1.default(message, { padding: 1, borderColor: 'blue', margin: 1 }));
120
+ this.log((0, boxen_1.default)(message, { padding: 1, borderColor: 'blue', margin: 1 }));
114
121
  this.log(`If you are running yarn start you can launch http://localhost:3000?adminKey=${adminKey}&adminServer=http://localhost:${port}/updateConfig`);
115
122
  }
116
123
  }
@@ -128,9 +135,6 @@ AdminServer.flags = {
128
135
  out: command_1.flags.string({
129
136
  description: 'synonym for target',
130
137
  }),
131
- skipCheck: command_1.flags.boolean({
132
- description: "Don't check whether or not you are in a JBrowse directory",
133
- }),
134
138
  help: command_1.flags.help({ char: 'h' }),
135
139
  };
136
140
  function getNetworkAddress() {
@@ -19,5 +19,5 @@ export default class Create extends JBrowseCommand {
19
19
  };
20
20
  run(): Promise<void>;
21
21
  checkPath(userPath: string): Promise<void>;
22
- catch(error: any): Promise<void>;
22
+ catch(error: unknown): Promise<void>;
23
23
  }