@jbrowse/text-indexing 2.13.1 → 2.15.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.
@@ -1,11 +1,11 @@
1
1
  import { Track, indexType } from './util';
2
2
  export declare function indexTracks(args: {
3
3
  tracks: Track[];
4
- outLocation?: string;
4
+ outDir?: string;
5
5
  signal?: AbortSignal;
6
- attributes?: string[];
7
- assemblies?: string[];
8
- exclude?: string[];
6
+ attributesToIndex?: string[];
7
+ assemblyNames?: string[];
8
+ featureTypesToExclude?: string[];
9
9
  indexType?: indexType;
10
10
  statusCallback: (message: string) => void;
11
11
  }): Promise<never[]>;
@@ -13,17 +13,32 @@ const common_1 = require("./types/common");
13
13
  const ixixx_1 = require("ixixx");
14
14
  const util_1 = require("@jbrowse/core/util");
15
15
  async function indexTracks(args) {
16
- const { tracks, outLocation, attributes, exclude, assemblies, indexType, statusCallback, signal, } = args;
16
+ const { tracks, outDir, attributesToIndex, featureTypesToExclude, assemblyNames, indexType, statusCallback, signal, } = args;
17
17
  const idxType = indexType || 'perTrack';
18
18
  (0, util_1.checkAbortSignal)(signal);
19
19
  await (idxType === 'perTrack'
20
- ? perTrackIndex(tracks, statusCallback, outLocation, attributes, exclude, signal)
21
- : aggregateIndex(tracks, statusCallback, outLocation, attributes, assemblies, exclude, signal));
20
+ ? perTrackIndex({
21
+ tracks,
22
+ statusCallback,
23
+ outDir,
24
+ attributesToIndex,
25
+ featureTypesToExclude,
26
+ signal,
27
+ })
28
+ : aggregateIndex({
29
+ tracks,
30
+ statusCallback,
31
+ outDir,
32
+ attributesToIndex,
33
+ assemblyNames,
34
+ featureTypesToExclude,
35
+ signal,
36
+ }));
22
37
  (0, util_1.checkAbortSignal)(signal);
23
38
  return [];
24
39
  }
25
- async function perTrackIndex(tracks, statusCallback, outLocation, attributes, exclude, signal) {
26
- const outFlag = outLocation || '.';
40
+ async function perTrackIndex({ tracks, statusCallback, outDir: paramOutDir, attributesToIndex = ['Name', 'ID'], featureTypesToExclude = ['exon', 'CDS'], signal, }) {
41
+ const outFlag = paramOutDir || '.';
27
42
  const isDir = fs_1.default.lstatSync(outFlag).isDirectory();
28
43
  const confFilePath = isDir ? path_1.default.join(outFlag, 'config.json') : outFlag;
29
44
  const outDir = path_1.default.dirname(confFilePath);
@@ -32,22 +47,24 @@ async function perTrackIndex(tracks, statusCallback, outLocation, attributes, ex
32
47
  fs_1.default.mkdirSync(trixDir);
33
48
  }
34
49
  // default settings
35
- const attrs = attributes || ['Name', 'ID'];
36
- const excludeTypes = exclude || ['exon', 'CDS'];
37
- const force = true;
38
50
  const supportedTracks = tracks.filter(track => { var _a; return (0, util_1.isSupportedIndexingAdapter)((_a = track.adapter) === null || _a === void 0 ? void 0 : _a.type); });
39
51
  for (const trackConfig of supportedTracks) {
40
- const { textSearching, trackId, assemblyNames } = trackConfig;
52
+ const { trackId, assemblyNames } = trackConfig;
41
53
  const id = `${trackId}-index`;
42
- if ((textSearching === null || textSearching === void 0 ? void 0 : textSearching.textSearchAdapter) && !force) {
43
- console.warn(`Note: ${trackId} has already been indexed with this configuration, use --force to overwrite this track. Skipping for now`);
44
- continue;
45
- }
46
- await indexDriver([trackConfig], outDir, attrs, id, true, excludeTypes, assemblyNames, statusCallback, signal);
54
+ await indexDriver({
55
+ tracks: [trackConfig],
56
+ outDir,
57
+ attributesToIndex,
58
+ name: id,
59
+ featureTypesToExclude,
60
+ assemblyNames,
61
+ statusCallback,
62
+ signal,
63
+ });
47
64
  }
48
65
  }
49
- async function aggregateIndex(tracks, statusCallback, outLocation, attributes, assemblies, exclude, signal) {
50
- const outFlag = outLocation || '.';
66
+ async function aggregateIndex({ tracks, statusCallback, outDir: paramOutDir, attributesToIndex = ['Name', 'ID'], featureTypesToExclude = ['exon', 'CDS'], signal, assemblyNames, }) {
67
+ const outFlag = paramOutDir || '.';
51
68
  const isDir = fs_1.default.lstatSync(outFlag).isDirectory();
52
69
  const confFilePath = isDir ? path_1.default.join(outFlag, 'config.json') : outFlag;
53
70
  const outDir = path_1.default.dirname(confFilePath);
@@ -55,70 +72,92 @@ async function aggregateIndex(tracks, statusCallback, outLocation, attributes, a
55
72
  if (!fs_1.default.existsSync(trixDir)) {
56
73
  fs_1.default.mkdirSync(trixDir);
57
74
  }
58
- if (!assemblies) {
75
+ if (!assemblyNames) {
59
76
  throw new Error('No assemblies passed. Assmeblies required for aggregate indexes');
60
77
  }
61
- for (const asm of assemblies) {
62
- // console.log('Indexing assembly ' + asm + '...')
63
- const id = asm + '-index';
64
- // default settings
65
- const attrs = attributes || ['Name', 'ID'];
66
- const excludeTypes = exclude || ['exon', 'CDS'];
67
- // const force = true
68
- const quiet = true;
69
- // supported tracks for given assembly
78
+ for (const asm of assemblyNames) {
79
+ const id = `${asm}-index`;
70
80
  const supportedTracks = tracks
71
81
  .filter(track => { var _a; return (0, util_1.isSupportedIndexingAdapter)((_a = track.adapter) === null || _a === void 0 ? void 0 : _a.type); })
72
82
  .filter(track => (asm ? track.assemblyNames.includes(asm) : true));
73
- await indexDriver(supportedTracks, outDir, attrs, id, quiet, excludeTypes, [asm], statusCallback, signal);
83
+ await indexDriver({
84
+ tracks: supportedTracks,
85
+ outDir: outDir,
86
+ attributesToIndex,
87
+ name: id,
88
+ featureTypesToExclude,
89
+ assemblyNames: [asm],
90
+ statusCallback,
91
+ signal,
92
+ });
74
93
  }
75
94
  }
76
- async function indexDriver(tracks, idxLocation, attributes, name, quiet, exclude, assemblyNames, statusCallback, signal) {
77
- const readable = stream_1.Readable.from(indexFiles(tracks, attributes, idxLocation, quiet, exclude, statusCallback, signal));
95
+ async function indexDriver({ tracks, outDir, attributesToIndex, name, featureTypesToExclude, assemblyNames, statusCallback, signal, }) {
96
+ const readable = stream_1.Readable.from(indexFiles({
97
+ tracks,
98
+ attributesToIndex,
99
+ outDir,
100
+ featureTypesToExclude,
101
+ statusCallback,
102
+ signal,
103
+ }));
78
104
  statusCallback('Indexing files.');
79
- const ixIxxStream = await runIxIxx(readable, idxLocation, name);
105
+ await runIxIxx(readable, outDir, name);
80
106
  (0, util_1.checkAbortSignal)(signal);
81
107
  await (0, common_1.generateMeta)({
82
108
  configs: tracks,
83
- attributes,
84
- outDir: idxLocation,
109
+ attributesToIndex,
110
+ outDir,
85
111
  name,
86
- exclude,
112
+ featureTypesToExclude,
87
113
  assemblyNames,
88
114
  });
89
115
  (0, util_1.checkAbortSignal)(signal);
90
- return ixIxxStream;
91
116
  }
92
- async function* indexFiles(tracks, attributes, outLocation, quiet, typesToExclude, statusCallback, signal) {
117
+ async function* indexFiles({ tracks, attributesToIndex: idx1, outDir, featureTypesToExclude: edx1, statusCallback, }) {
93
118
  for (const track of tracks) {
94
119
  const { adapter, textSearching } = track;
95
- const { type } = adapter;
96
- const { indexingFeatureTypesToExclude: types = typesToExclude, indexingAttributes: attrs = attributes, } = textSearching || {};
97
- // currently only supporting GFF3Tabix and VCFTabix
98
- switch (type) {
99
- case 'Gff3TabixAdapter': {
100
- yield* (0, gff3Adapter_1.indexGff3)(track, attrs, getLoc('gffGzLocation', track), outLocation, types, quiet, statusCallback, signal);
101
- break;
102
- }
103
- case 'Gff3Adapter': {
104
- yield* (0, gff3Adapter_1.indexGff3)(track, attrs, getLoc('gffLocation', track), outLocation, types, quiet, statusCallback, signal);
105
- break;
106
- }
107
- case 'VcfTabixAdapter': {
108
- yield* (0, vcfAdapter_1.indexVcf)(track, attrs, getLoc('vcfGzLocation', track), outLocation, types, quiet, statusCallback, signal);
109
- break;
110
- }
111
- case 'VcfAdapter': {
112
- yield* (0, vcfAdapter_1.indexVcf)(track, attrs, getLoc('vcfLocation', track), outLocation, types, quiet, statusCallback, signal);
113
- break;
114
- }
115
- // No default
120
+ const { type } = adapter || {};
121
+ const { indexingFeatureTypesToExclude: featureTypesToExclude = edx1, indexingAttributes: attributesToIndex = idx1, } = textSearching || {};
122
+ let myTotalBytes;
123
+ if (type === 'Gff3TabixAdapter' || type === 'Gff3Adapter') {
124
+ yield* (0, gff3Adapter_1.indexGff3)({
125
+ config: track,
126
+ attributesToIndex,
127
+ inLocation: getLoc('gffGzLocation', track),
128
+ outDir,
129
+ featureTypesToExclude,
130
+ onStart: totalBytes => {
131
+ myTotalBytes = totalBytes;
132
+ },
133
+ onUpdate: progressBytes => {
134
+ statusCallback(`${progressBytes}/${myTotalBytes}`);
135
+ },
136
+ });
137
+ }
138
+ else if (type === 'VcfTabixAdapter' || type === 'VcfAdapter') {
139
+ yield* (0, vcfAdapter_1.indexVcf)({
140
+ config: track,
141
+ attributesToIndex,
142
+ inLocation: getLoc('vcfGzLocation', track),
143
+ outDir,
144
+ onStart: totalBytes => {
145
+ myTotalBytes = totalBytes;
146
+ },
147
+ onUpdate: progressBytes => {
148
+ statusCallback(`${progressBytes}/${myTotalBytes}`);
149
+ },
150
+ });
116
151
  }
117
152
  }
118
153
  return;
119
154
  }
120
155
  function getLoc(attr, config) {
121
- const elt = config.adapter[attr];
156
+ var _a;
157
+ const elt = (_a = config.adapter) === null || _a === void 0 ? void 0 : _a[attr];
158
+ if (!elt) {
159
+ throw new Error('none');
160
+ }
122
161
  return elt.uri || elt.localPath;
123
162
  }
124
163
  function runIxIxx(readStream, idxLocation, name) {
package/dist/index.d.ts CHANGED
@@ -1,2 +1,5 @@
1
1
  export * from './util';
2
+ export * from './types/common';
2
3
  export { indexTracks } from './TextIndexing';
4
+ export { indexGff3 } from './types/gff3Adapter';
5
+ export { indexVcf } from './types/vcfAdapter';
package/dist/index.js CHANGED
@@ -14,7 +14,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.indexTracks = void 0;
17
+ exports.indexVcf = exports.indexGff3 = exports.indexTracks = void 0;
18
18
  __exportStar(require("./util"), exports);
19
+ __exportStar(require("./types/common"), exports);
19
20
  var TextIndexing_1 = require("./TextIndexing");
20
21
  Object.defineProperty(exports, "indexTracks", { enumerable: true, get: function () { return TextIndexing_1.indexTracks; } });
22
+ var gff3Adapter_1 = require("./types/gff3Adapter");
23
+ Object.defineProperty(exports, "indexGff3", { enumerable: true, get: function () { return gff3Adapter_1.indexGff3; } });
24
+ var vcfAdapter_1 = require("./types/vcfAdapter");
25
+ Object.defineProperty(exports, "indexVcf", { enumerable: true, get: function () { return vcfAdapter_1.indexVcf; } });
@@ -5,23 +5,21 @@ export declare function createRemoteStream(urlIn: string): Promise<fetch.Respons
5
5
  export declare function isURL(FileName: string): boolean;
6
6
  export declare function getLocalOrRemoteStream(uri: string, out: string): Promise<{
7
7
  totalBytes: number;
8
- stream: NodeJS.ReadableStream | fs.ReadStream;
8
+ stream: NodeJS.ReadableStream;
9
+ } | {
10
+ totalBytes: number;
11
+ stream: fs.ReadStream;
9
12
  }>;
10
13
  export declare function makeLocation(location: string, protocol: string): UriLocation | LocalPathLocation;
11
14
  export declare function guessAdapterFromFileName(filePath: string): Track;
12
15
  /**
13
16
  * Generates metadata of index given a filename (trackId or assembly)
14
- * @param name - assembly name or trackId
15
- * @param attributes - attributes indexed
16
- * @param include - feature types included from index
17
- * @param exclude - feature types excluded from index
18
- * @param configs - list of track
19
17
  */
20
- export declare function generateMeta({ configs, attributes, outDir, name, exclude, assemblyNames, }: {
18
+ export declare function generateMeta({ configs, attributesToIndex, outDir, name, featureTypesToExclude, assemblyNames, }: {
21
19
  configs: Track[];
22
- attributes: string[];
20
+ attributesToIndex: string[];
23
21
  outDir: string;
24
22
  name: string;
25
- exclude: string[];
23
+ featureTypesToExclude: string[];
26
24
  assemblyNames: string[];
27
25
  }): Promise<void>;
@@ -12,15 +12,14 @@ exports.generateMeta = generateMeta;
12
12
  const fs_1 = __importDefault(require("fs"));
13
13
  const node_fetch_1 = __importDefault(require("node-fetch"));
14
14
  const path_1 = __importDefault(require("path"));
15
- // Method for handing off the parsing of a gff3 file URL.
16
- // Calls the proper parser depending on if it is gzipped or not.
17
- // Returns a @gmod/gff stream.
15
+ // Method for handing off the parsing of a gff3 file URL. Calls the proper
16
+ // parser depending on if it is gzipped or not. Returns a @gmod/gff stream.
18
17
  async function createRemoteStream(urlIn) {
19
- const response = await (0, node_fetch_1.default)(urlIn);
20
- if (!response.ok) {
21
- throw new Error(`Failed to fetch ${urlIn} status ${response.status} ${response.statusText}`);
18
+ const res = await (0, node_fetch_1.default)(urlIn);
19
+ if (!res.ok) {
20
+ throw new Error(`Failed to fetch ${urlIn} status ${res.status} ${await res.text()}`);
22
21
  }
23
- return response;
22
+ return res;
24
23
  }
25
24
  // Checks if the passed in string is a valid URL.
26
25
  // Returns a boolean.
@@ -35,20 +34,20 @@ function isURL(FileName) {
35
34
  return url.protocol === 'http:' || url.protocol === 'https:';
36
35
  }
37
36
  async function getLocalOrRemoteStream(uri, out) {
38
- var _a;
39
- let stream;
40
- let totalBytes = 0;
41
37
  if (isURL(uri)) {
42
38
  const result = await createRemoteStream(uri);
43
- totalBytes = +(((_a = result.headers) === null || _a === void 0 ? void 0 : _a.get('Content-Length')) || 0);
44
- stream = result.body;
39
+ return {
40
+ totalBytes: +(result.headers.get('Content-Length') || 0),
41
+ stream: result.body,
42
+ };
45
43
  }
46
44
  else {
47
45
  const filename = path_1.default.isAbsolute(uri) ? uri : path_1.default.join(out, uri);
48
- totalBytes = fs_1.default.statSync(filename).size;
49
- stream = fs_1.default.createReadStream(filename);
46
+ return {
47
+ totalBytes: fs_1.default.statSync(filename).size,
48
+ stream: fs_1.default.createReadStream(filename),
49
+ };
50
50
  }
51
- return { totalBytes, stream };
52
51
  }
53
52
  function makeLocation(location, protocol) {
54
53
  if (protocol === 'uri') {
@@ -127,27 +126,20 @@ function guessAdapterFromFileName(filePath) {
127
126
  }
128
127
  /**
129
128
  * Generates metadata of index given a filename (trackId or assembly)
130
- * @param name - assembly name or trackId
131
- * @param attributes - attributes indexed
132
- * @param include - feature types included from index
133
- * @param exclude - feature types excluded from index
134
- * @param configs - list of track
135
129
  */
136
- async function generateMeta({ configs, attributes, outDir, name, exclude, assemblyNames, }) {
137
- const tracks = configs.map(config => {
138
- const { trackId, textSearching, adapter } = config;
139
- const includeExclude = (textSearching === null || textSearching === void 0 ? void 0 : textSearching.indexingFeatureTypesToExclude) || exclude;
140
- const metaAttrs = (textSearching === null || textSearching === void 0 ? void 0 : textSearching.indexingAttributes) || attributes;
141
- return {
142
- trackId: trackId,
143
- attributesIndexed: metaAttrs,
144
- excludedTypes: includeExclude,
145
- adapterConf: adapter,
146
- };
147
- });
130
+ async function generateMeta({ configs, attributesToIndex, outDir, name, featureTypesToExclude, assemblyNames, }) {
148
131
  fs_1.default.writeFileSync(path_1.default.join(outDir, 'trix', `${name}_meta.json`), JSON.stringify({
149
132
  dateCreated: new Date().toISOString(),
150
- tracks,
133
+ tracks: configs.map(config => {
134
+ const { trackId, textSearching, adapter } = config;
135
+ return {
136
+ trackId,
137
+ attributesIndexed: (textSearching === null || textSearching === void 0 ? void 0 : textSearching.indexingAttributes) || attributesToIndex,
138
+ excludedTypes: (textSearching === null || textSearching === void 0 ? void 0 : textSearching.indexingFeatureTypesToExclude) ||
139
+ featureTypesToExclude,
140
+ adapterConf: adapter,
141
+ };
142
+ }),
151
143
  assemblyNames,
152
144
  }, null, 2));
153
145
  }
@@ -1,2 +1,11 @@
1
- import { Track } from '../util';
2
- export declare function indexGff3(config: Track, attributes: string[], inLocation: string, outLocation: string, typesToExclude: string[], quiet: boolean, statusCallback: (message: string) => void, signal?: AbortSignal): AsyncGenerator<string, void, unknown>;
1
+ export declare function indexGff3({ config, attributesToIndex, inLocation, outDir, featureTypesToExclude, onStart, onUpdate, }: {
2
+ config: {
3
+ trackId: string;
4
+ };
5
+ attributesToIndex: string[];
6
+ inLocation: string;
7
+ outDir: string;
8
+ featureTypesToExclude: string[];
9
+ onStart: (totalBytes: number) => void;
10
+ onUpdate: (progressBytes: number) => void;
11
+ }): AsyncGenerator<string, void, unknown>;
@@ -6,24 +6,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.indexGff3 = indexGff3;
7
7
  const zlib_1 = require("zlib");
8
8
  const readline_1 = __importDefault(require("readline"));
9
+ // locals
9
10
  const util_1 = require("../util");
10
11
  const common_1 = require("./common");
11
- const util_2 = require("@jbrowse/core/util");
12
- async function* indexGff3(config, attributes, inLocation, outLocation, typesToExclude, quiet, statusCallback, signal) {
12
+ async function* indexGff3({ config, attributesToIndex, inLocation, outDir, featureTypesToExclude, onStart, onUpdate, }) {
13
13
  const { trackId } = config;
14
14
  let receivedBytes = 0;
15
- const { totalBytes, stream } = await (0, common_1.getLocalOrRemoteStream)(inLocation, outLocation);
15
+ const { totalBytes, stream } = await (0, common_1.getLocalOrRemoteStream)(inLocation, outDir);
16
+ onStart(totalBytes);
16
17
  stream.on('data', chunk => {
17
18
  receivedBytes += chunk.length;
18
- // send an update?
19
- const progress = Math.round((receivedBytes / totalBytes) * 100);
20
- statusCallback(`${progress}`);
19
+ onUpdate(receivedBytes);
21
20
  });
22
21
  const rl = readline_1.default.createInterface({
23
- input: inLocation.match(/.b?gz$/) ? stream.pipe((0, zlib_1.createGunzip)()) : stream,
22
+ input: /.b?gz$/.exec(inLocation) ? stream.pipe((0, zlib_1.createGunzip)()) : stream,
24
23
  });
25
24
  for await (const line of rl) {
26
- if (line.startsWith('#')) {
25
+ if (!line.trim()) {
26
+ continue;
27
+ }
28
+ else if (line.startsWith('#')) {
27
29
  continue;
28
30
  }
29
31
  else if (line.startsWith('>')) {
@@ -31,7 +33,7 @@ async function* indexGff3(config, attributes, inLocation, outLocation, typesToEx
31
33
  }
32
34
  const [seq_id, , type, start, end, , , , col9] = line.split('\t');
33
35
  const locStr = `${seq_id}:${start}..${end}`;
34
- if (!typesToExclude.includes(type)) {
36
+ if (!featureTypesToExclude.includes(type)) {
35
37
  // turns gff3 attrs into a map, and converts the arrays into space
36
38
  // separated strings
37
39
  const col9attrs = Object.fromEntries(col9
@@ -41,9 +43,11 @@ async function* indexGff3(config, attributes, inLocation, outLocation, typesToEx
41
43
  .map(f => f.split('='))
42
44
  .map(([key, val]) => [
43
45
  key.trim(),
44
- (0, util_1.decodeURIComponentNoThrow)(val).trim().split(',').join(' '),
46
+ val
47
+ ? (0, util_1.decodeURIComponentNoThrow)(val).trim().split(',').join(' ')
48
+ : undefined,
45
49
  ]));
46
- const attrs = attributes
50
+ const attrs = attributesToIndex
47
51
  .map(attr => col9attrs[attr])
48
52
  .filter((f) => !!f);
49
53
  if (attrs.length) {
@@ -52,11 +56,8 @@ async function* indexGff3(config, attributes, inLocation, outLocation, typesToEx
52
56
  encodeURIComponent(trackId),
53
57
  ...attrs.map(a => encodeURIComponent(a)),
54
58
  ]).replaceAll(',', '|');
55
- // Check abort signal
56
- (0, util_2.checkAbortSignal)(signal);
57
59
  yield `${record} ${[...new Set(attrs)].join(' ')}\n`;
58
60
  }
59
61
  }
60
62
  }
61
- // console.log('done')
62
63
  }
@@ -1,2 +1,8 @@
1
- import { Track } from '../util';
2
- export declare function indexVcf(config: Track, attributesToIndex: string[], inLocation: string, outLocation: string, typesToExclude: string[], quiet: boolean, statusCallback: (message: string) => void, signal?: AbortSignal): AsyncGenerator<string, void, unknown>;
1
+ export declare function indexVcf({ config, attributesToIndex, inLocation, outDir, onStart, onUpdate, }: {
2
+ config: any;
3
+ attributesToIndex: string[];
4
+ inLocation: string;
5
+ outDir: string;
6
+ onStart: (totalBytes: number) => void;
7
+ onUpdate: (progressBytes: number) => void;
8
+ }): AsyncGenerator<string, void, unknown>;
@@ -6,19 +6,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.indexVcf = indexVcf;
7
7
  const zlib_1 = require("zlib");
8
8
  const readline_1 = __importDefault(require("readline"));
9
+ // locals
9
10
  const util_1 = require("../util");
10
11
  const common_1 = require("./common");
11
- const util_2 = require("@jbrowse/core/util");
12
- async function* indexVcf(config, attributesToIndex, inLocation, outLocation, typesToExclude, quiet, statusCallback, signal) {
12
+ async function* indexVcf({ config, attributesToIndex, inLocation, outDir, onStart, onUpdate, }) {
13
13
  const { trackId } = config;
14
14
  let receivedBytes = 0;
15
- const { totalBytes, stream } = await (0, common_1.getLocalOrRemoteStream)(inLocation, outLocation);
15
+ const { totalBytes, stream } = await (0, common_1.getLocalOrRemoteStream)(inLocation, outDir);
16
+ onStart(totalBytes);
16
17
  stream.on('data', chunk => {
17
18
  receivedBytes += chunk.length;
18
- const progress = Math.round((receivedBytes / totalBytes) * 100);
19
- statusCallback(`${progress}`);
19
+ onUpdate(receivedBytes);
20
20
  });
21
- const gzStream = inLocation.match(/.b?gz$/)
21
+ const gzStream = /.b?gz$/.exec(inLocation)
22
22
  ? stream.pipe((0, zlib_1.createGunzip)())
23
23
  : stream;
24
24
  const rl = readline_1.default.createInterface({
@@ -30,7 +30,7 @@ async function* indexVcf(config, attributesToIndex, inLocation, outLocation, typ
30
30
  }
31
31
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
32
32
  const [ref, pos, id, _ref, _alt, _qual, _filter, info] = line.split('\t');
33
- // turns vcf info attrs into a map, and converts the arrays into space
33
+ // turns gff3 attrs into a map, and converts the arrays into space
34
34
  // separated strings
35
35
  const fields = Object.fromEntries(info
36
36
  .split(';')
@@ -60,8 +60,6 @@ async function* indexVcf(config, attributesToIndex, inLocation, outLocation, typ
60
60
  encodeURIComponent(id || ''),
61
61
  ...infoAttrs.map(a => encodeURIComponent(a || '')),
62
62
  ]).replaceAll(',', '|');
63
- // Check abort signal
64
- (0, util_2.checkAbortSignal)(signal);
65
63
  yield `${record} ${[...new Set(attrs)].join(' ')}\n`;
66
64
  }
67
65
  }
package/dist/util.d.ts CHANGED
@@ -50,27 +50,37 @@ export interface Sequence {
50
50
  trackId: string;
51
51
  adapter: IndexedFastaAdapter | BgzipFastaAdapter | TwoBitAdapter | ChromeSizesAdapter | CustomSequenceAdapter;
52
52
  }
53
+ type Loc = UriLocation | LocalPathLocation;
53
54
  export interface Gff3TabixAdapter {
54
55
  type: 'Gff3TabixAdapter';
55
- gffGzLocation: UriLocation | LocalPathLocation;
56
+ gffGzLocation: Loc;
56
57
  }
57
58
  export interface Gff3Adapter {
58
59
  type: 'Gff3Adapter';
59
- gffLocation: UriLocation | LocalPathLocation;
60
+ gffLocation: Loc;
60
61
  }
61
62
  export interface GtfAdapter {
62
63
  type: 'GtfAdapter';
63
- gtfLocation: UriLocation | LocalPathLocation;
64
+ gtfLocation: Loc;
64
65
  }
65
66
  export interface VcfTabixAdapter {
66
67
  type: 'VcfTabixAdapter';
67
- vcfGzLocation: UriLocation | LocalPathLocation;
68
+ vcfGzLocation: Loc;
68
69
  }
69
70
  export interface VcfAdapter {
70
71
  type: 'VcfAdapter';
71
- vcfLocation: UriLocation | LocalPathLocation;
72
+ vcfLocation: Loc;
73
+ }
74
+ export interface Track {
75
+ adapter?: {
76
+ type: string;
77
+ [key: string]: unknown;
78
+ };
79
+ textSearching?: TextSearching;
80
+ name: string;
81
+ assemblyNames: string[];
82
+ trackId: string;
72
83
  }
73
- export type Track = Record<string, any>;
74
84
  export interface TextSearching {
75
85
  indexingFeatureTypesToExclude?: string[];
76
86
  indexingAttributes?: string[];
@@ -87,10 +97,10 @@ export interface TrixTextSearchAdapter {
87
97
  export interface Config {
88
98
  assemblies?: Assembly[];
89
99
  assembly?: Assembly;
90
- configuration?: {};
100
+ configuration?: Record<string, unknown>;
91
101
  aggregateTextSearchAdapters?: TrixTextSearchAdapter[];
92
102
  connections?: unknown[];
93
- defaultSession?: {};
103
+ defaultSession?: Record<string, unknown>;
94
104
  tracks?: Track[];
95
105
  }
96
106
  export type indexType = 'aggregate' | 'perTrack';
@@ -114,3 +124,4 @@ export declare function createTextSearchConf(name: string, trackIds: string[], a
114
124
  };
115
125
  export declare function findTrackConfigsToIndex(tracks: Track[], trackIds: string[], assemblyName?: string): Track[];
116
126
  export declare function decodeURIComponentNoThrow(uri: string): string;
127
+ export {};
@@ -1,11 +1,11 @@
1
1
  import { Track, indexType } from './util';
2
2
  export declare function indexTracks(args: {
3
3
  tracks: Track[];
4
- outLocation?: string;
4
+ outDir?: string;
5
5
  signal?: AbortSignal;
6
- attributes?: string[];
7
- assemblies?: string[];
8
- exclude?: string[];
6
+ attributesToIndex?: string[];
7
+ assemblyNames?: string[];
8
+ featureTypesToExclude?: string[];
9
9
  indexType?: indexType;
10
10
  statusCallback: (message: string) => void;
11
11
  }): Promise<never[]>;
@@ -7,17 +7,32 @@ import { generateMeta } from './types/common';
7
7
  import { ixIxxStream } from 'ixixx';
8
8
  import { checkAbortSignal, isSupportedIndexingAdapter, } from '@jbrowse/core/util';
9
9
  export async function indexTracks(args) {
10
- const { tracks, outLocation, attributes, exclude, assemblies, indexType, statusCallback, signal, } = args;
10
+ const { tracks, outDir, attributesToIndex, featureTypesToExclude, assemblyNames, indexType, statusCallback, signal, } = args;
11
11
  const idxType = indexType || 'perTrack';
12
12
  checkAbortSignal(signal);
13
13
  await (idxType === 'perTrack'
14
- ? perTrackIndex(tracks, statusCallback, outLocation, attributes, exclude, signal)
15
- : aggregateIndex(tracks, statusCallback, outLocation, attributes, assemblies, exclude, signal));
14
+ ? perTrackIndex({
15
+ tracks,
16
+ statusCallback,
17
+ outDir,
18
+ attributesToIndex,
19
+ featureTypesToExclude,
20
+ signal,
21
+ })
22
+ : aggregateIndex({
23
+ tracks,
24
+ statusCallback,
25
+ outDir,
26
+ attributesToIndex,
27
+ assemblyNames,
28
+ featureTypesToExclude,
29
+ signal,
30
+ }));
16
31
  checkAbortSignal(signal);
17
32
  return [];
18
33
  }
19
- async function perTrackIndex(tracks, statusCallback, outLocation, attributes, exclude, signal) {
20
- const outFlag = outLocation || '.';
34
+ async function perTrackIndex({ tracks, statusCallback, outDir: paramOutDir, attributesToIndex = ['Name', 'ID'], featureTypesToExclude = ['exon', 'CDS'], signal, }) {
35
+ const outFlag = paramOutDir || '.';
21
36
  const isDir = fs.lstatSync(outFlag).isDirectory();
22
37
  const confFilePath = isDir ? path.join(outFlag, 'config.json') : outFlag;
23
38
  const outDir = path.dirname(confFilePath);
@@ -26,22 +41,24 @@ async function perTrackIndex(tracks, statusCallback, outLocation, attributes, ex
26
41
  fs.mkdirSync(trixDir);
27
42
  }
28
43
  // default settings
29
- const attrs = attributes || ['Name', 'ID'];
30
- const excludeTypes = exclude || ['exon', 'CDS'];
31
- const force = true;
32
44
  const supportedTracks = tracks.filter(track => { var _a; return isSupportedIndexingAdapter((_a = track.adapter) === null || _a === void 0 ? void 0 : _a.type); });
33
45
  for (const trackConfig of supportedTracks) {
34
- const { textSearching, trackId, assemblyNames } = trackConfig;
46
+ const { trackId, assemblyNames } = trackConfig;
35
47
  const id = `${trackId}-index`;
36
- if ((textSearching === null || textSearching === void 0 ? void 0 : textSearching.textSearchAdapter) && !force) {
37
- console.warn(`Note: ${trackId} has already been indexed with this configuration, use --force to overwrite this track. Skipping for now`);
38
- continue;
39
- }
40
- await indexDriver([trackConfig], outDir, attrs, id, true, excludeTypes, assemblyNames, statusCallback, signal);
48
+ await indexDriver({
49
+ tracks: [trackConfig],
50
+ outDir,
51
+ attributesToIndex,
52
+ name: id,
53
+ featureTypesToExclude,
54
+ assemblyNames,
55
+ statusCallback,
56
+ signal,
57
+ });
41
58
  }
42
59
  }
43
- async function aggregateIndex(tracks, statusCallback, outLocation, attributes, assemblies, exclude, signal) {
44
- const outFlag = outLocation || '.';
60
+ async function aggregateIndex({ tracks, statusCallback, outDir: paramOutDir, attributesToIndex = ['Name', 'ID'], featureTypesToExclude = ['exon', 'CDS'], signal, assemblyNames, }) {
61
+ const outFlag = paramOutDir || '.';
45
62
  const isDir = fs.lstatSync(outFlag).isDirectory();
46
63
  const confFilePath = isDir ? path.join(outFlag, 'config.json') : outFlag;
47
64
  const outDir = path.dirname(confFilePath);
@@ -49,70 +66,92 @@ async function aggregateIndex(tracks, statusCallback, outLocation, attributes, a
49
66
  if (!fs.existsSync(trixDir)) {
50
67
  fs.mkdirSync(trixDir);
51
68
  }
52
- if (!assemblies) {
69
+ if (!assemblyNames) {
53
70
  throw new Error('No assemblies passed. Assmeblies required for aggregate indexes');
54
71
  }
55
- for (const asm of assemblies) {
56
- // console.log('Indexing assembly ' + asm + '...')
57
- const id = asm + '-index';
58
- // default settings
59
- const attrs = attributes || ['Name', 'ID'];
60
- const excludeTypes = exclude || ['exon', 'CDS'];
61
- // const force = true
62
- const quiet = true;
63
- // supported tracks for given assembly
72
+ for (const asm of assemblyNames) {
73
+ const id = `${asm}-index`;
64
74
  const supportedTracks = tracks
65
75
  .filter(track => { var _a; return isSupportedIndexingAdapter((_a = track.adapter) === null || _a === void 0 ? void 0 : _a.type); })
66
76
  .filter(track => (asm ? track.assemblyNames.includes(asm) : true));
67
- await indexDriver(supportedTracks, outDir, attrs, id, quiet, excludeTypes, [asm], statusCallback, signal);
77
+ await indexDriver({
78
+ tracks: supportedTracks,
79
+ outDir: outDir,
80
+ attributesToIndex,
81
+ name: id,
82
+ featureTypesToExclude,
83
+ assemblyNames: [asm],
84
+ statusCallback,
85
+ signal,
86
+ });
68
87
  }
69
88
  }
70
- async function indexDriver(tracks, idxLocation, attributes, name, quiet, exclude, assemblyNames, statusCallback, signal) {
71
- const readable = Readable.from(indexFiles(tracks, attributes, idxLocation, quiet, exclude, statusCallback, signal));
89
+ async function indexDriver({ tracks, outDir, attributesToIndex, name, featureTypesToExclude, assemblyNames, statusCallback, signal, }) {
90
+ const readable = Readable.from(indexFiles({
91
+ tracks,
92
+ attributesToIndex,
93
+ outDir,
94
+ featureTypesToExclude,
95
+ statusCallback,
96
+ signal,
97
+ }));
72
98
  statusCallback('Indexing files.');
73
- const ixIxxStream = await runIxIxx(readable, idxLocation, name);
99
+ await runIxIxx(readable, outDir, name);
74
100
  checkAbortSignal(signal);
75
101
  await generateMeta({
76
102
  configs: tracks,
77
- attributes,
78
- outDir: idxLocation,
103
+ attributesToIndex,
104
+ outDir,
79
105
  name,
80
- exclude,
106
+ featureTypesToExclude,
81
107
  assemblyNames,
82
108
  });
83
109
  checkAbortSignal(signal);
84
- return ixIxxStream;
85
110
  }
86
- async function* indexFiles(tracks, attributes, outLocation, quiet, typesToExclude, statusCallback, signal) {
111
+ async function* indexFiles({ tracks, attributesToIndex: idx1, outDir, featureTypesToExclude: edx1, statusCallback, }) {
87
112
  for (const track of tracks) {
88
113
  const { adapter, textSearching } = track;
89
- const { type } = adapter;
90
- const { indexingFeatureTypesToExclude: types = typesToExclude, indexingAttributes: attrs = attributes, } = textSearching || {};
91
- // currently only supporting GFF3Tabix and VCFTabix
92
- switch (type) {
93
- case 'Gff3TabixAdapter': {
94
- yield* indexGff3(track, attrs, getLoc('gffGzLocation', track), outLocation, types, quiet, statusCallback, signal);
95
- break;
96
- }
97
- case 'Gff3Adapter': {
98
- yield* indexGff3(track, attrs, getLoc('gffLocation', track), outLocation, types, quiet, statusCallback, signal);
99
- break;
100
- }
101
- case 'VcfTabixAdapter': {
102
- yield* indexVcf(track, attrs, getLoc('vcfGzLocation', track), outLocation, types, quiet, statusCallback, signal);
103
- break;
104
- }
105
- case 'VcfAdapter': {
106
- yield* indexVcf(track, attrs, getLoc('vcfLocation', track), outLocation, types, quiet, statusCallback, signal);
107
- break;
108
- }
109
- // No default
114
+ const { type } = adapter || {};
115
+ const { indexingFeatureTypesToExclude: featureTypesToExclude = edx1, indexingAttributes: attributesToIndex = idx1, } = textSearching || {};
116
+ let myTotalBytes;
117
+ if (type === 'Gff3TabixAdapter' || type === 'Gff3Adapter') {
118
+ yield* indexGff3({
119
+ config: track,
120
+ attributesToIndex,
121
+ inLocation: getLoc('gffGzLocation', track),
122
+ outDir,
123
+ featureTypesToExclude,
124
+ onStart: totalBytes => {
125
+ myTotalBytes = totalBytes;
126
+ },
127
+ onUpdate: progressBytes => {
128
+ statusCallback(`${progressBytes}/${myTotalBytes}`);
129
+ },
130
+ });
131
+ }
132
+ else if (type === 'VcfTabixAdapter' || type === 'VcfAdapter') {
133
+ yield* indexVcf({
134
+ config: track,
135
+ attributesToIndex,
136
+ inLocation: getLoc('vcfGzLocation', track),
137
+ outDir,
138
+ onStart: totalBytes => {
139
+ myTotalBytes = totalBytes;
140
+ },
141
+ onUpdate: progressBytes => {
142
+ statusCallback(`${progressBytes}/${myTotalBytes}`);
143
+ },
144
+ });
110
145
  }
111
146
  }
112
147
  return;
113
148
  }
114
149
  function getLoc(attr, config) {
115
- const elt = config.adapter[attr];
150
+ var _a;
151
+ const elt = (_a = config.adapter) === null || _a === void 0 ? void 0 : _a[attr];
152
+ if (!elt) {
153
+ throw new Error('none');
154
+ }
116
155
  return elt.uri || elt.localPath;
117
156
  }
118
157
  function runIxIxx(readStream, idxLocation, name) {
package/esm/index.d.ts CHANGED
@@ -1,2 +1,5 @@
1
1
  export * from './util';
2
+ export * from './types/common';
2
3
  export { indexTracks } from './TextIndexing';
4
+ export { indexGff3 } from './types/gff3Adapter';
5
+ export { indexVcf } from './types/vcfAdapter';
package/esm/index.js CHANGED
@@ -1,2 +1,5 @@
1
1
  export * from './util';
2
+ export * from './types/common';
2
3
  export { indexTracks } from './TextIndexing';
4
+ export { indexGff3 } from './types/gff3Adapter';
5
+ export { indexVcf } from './types/vcfAdapter';
@@ -5,23 +5,21 @@ export declare function createRemoteStream(urlIn: string): Promise<fetch.Respons
5
5
  export declare function isURL(FileName: string): boolean;
6
6
  export declare function getLocalOrRemoteStream(uri: string, out: string): Promise<{
7
7
  totalBytes: number;
8
- stream: NodeJS.ReadableStream | fs.ReadStream;
8
+ stream: NodeJS.ReadableStream;
9
+ } | {
10
+ totalBytes: number;
11
+ stream: fs.ReadStream;
9
12
  }>;
10
13
  export declare function makeLocation(location: string, protocol: string): UriLocation | LocalPathLocation;
11
14
  export declare function guessAdapterFromFileName(filePath: string): Track;
12
15
  /**
13
16
  * Generates metadata of index given a filename (trackId or assembly)
14
- * @param name - assembly name or trackId
15
- * @param attributes - attributes indexed
16
- * @param include - feature types included from index
17
- * @param exclude - feature types excluded from index
18
- * @param configs - list of track
19
17
  */
20
- export declare function generateMeta({ configs, attributes, outDir, name, exclude, assemblyNames, }: {
18
+ export declare function generateMeta({ configs, attributesToIndex, outDir, name, featureTypesToExclude, assemblyNames, }: {
21
19
  configs: Track[];
22
- attributes: string[];
20
+ attributesToIndex: string[];
23
21
  outDir: string;
24
22
  name: string;
25
- exclude: string[];
23
+ featureTypesToExclude: string[];
26
24
  assemblyNames: string[];
27
25
  }): Promise<void>;
@@ -1,15 +1,14 @@
1
1
  import fs from 'fs';
2
2
  import fetch from 'node-fetch';
3
3
  import path from 'path';
4
- // Method for handing off the parsing of a gff3 file URL.
5
- // Calls the proper parser depending on if it is gzipped or not.
6
- // Returns a @gmod/gff stream.
4
+ // Method for handing off the parsing of a gff3 file URL. Calls the proper
5
+ // parser depending on if it is gzipped or not. Returns a @gmod/gff stream.
7
6
  export async function createRemoteStream(urlIn) {
8
- const response = await fetch(urlIn);
9
- if (!response.ok) {
10
- throw new Error(`Failed to fetch ${urlIn} status ${response.status} ${response.statusText}`);
7
+ const res = await fetch(urlIn);
8
+ if (!res.ok) {
9
+ throw new Error(`Failed to fetch ${urlIn} status ${res.status} ${await res.text()}`);
11
10
  }
12
- return response;
11
+ return res;
13
12
  }
14
13
  // Checks if the passed in string is a valid URL.
15
14
  // Returns a boolean.
@@ -24,20 +23,20 @@ export function isURL(FileName) {
24
23
  return url.protocol === 'http:' || url.protocol === 'https:';
25
24
  }
26
25
  export async function getLocalOrRemoteStream(uri, out) {
27
- var _a;
28
- let stream;
29
- let totalBytes = 0;
30
26
  if (isURL(uri)) {
31
27
  const result = await createRemoteStream(uri);
32
- totalBytes = +(((_a = result.headers) === null || _a === void 0 ? void 0 : _a.get('Content-Length')) || 0);
33
- stream = result.body;
28
+ return {
29
+ totalBytes: +(result.headers.get('Content-Length') || 0),
30
+ stream: result.body,
31
+ };
34
32
  }
35
33
  else {
36
34
  const filename = path.isAbsolute(uri) ? uri : path.join(out, uri);
37
- totalBytes = fs.statSync(filename).size;
38
- stream = fs.createReadStream(filename);
35
+ return {
36
+ totalBytes: fs.statSync(filename).size,
37
+ stream: fs.createReadStream(filename),
38
+ };
39
39
  }
40
- return { totalBytes, stream };
41
40
  }
42
41
  export function makeLocation(location, protocol) {
43
42
  if (protocol === 'uri') {
@@ -116,27 +115,20 @@ export function guessAdapterFromFileName(filePath) {
116
115
  }
117
116
  /**
118
117
  * Generates metadata of index given a filename (trackId or assembly)
119
- * @param name - assembly name or trackId
120
- * @param attributes - attributes indexed
121
- * @param include - feature types included from index
122
- * @param exclude - feature types excluded from index
123
- * @param configs - list of track
124
118
  */
125
- export async function generateMeta({ configs, attributes, outDir, name, exclude, assemblyNames, }) {
126
- const tracks = configs.map(config => {
127
- const { trackId, textSearching, adapter } = config;
128
- const includeExclude = (textSearching === null || textSearching === void 0 ? void 0 : textSearching.indexingFeatureTypesToExclude) || exclude;
129
- const metaAttrs = (textSearching === null || textSearching === void 0 ? void 0 : textSearching.indexingAttributes) || attributes;
130
- return {
131
- trackId: trackId,
132
- attributesIndexed: metaAttrs,
133
- excludedTypes: includeExclude,
134
- adapterConf: adapter,
135
- };
136
- });
119
+ export async function generateMeta({ configs, attributesToIndex, outDir, name, featureTypesToExclude, assemblyNames, }) {
137
120
  fs.writeFileSync(path.join(outDir, 'trix', `${name}_meta.json`), JSON.stringify({
138
121
  dateCreated: new Date().toISOString(),
139
- tracks,
122
+ tracks: configs.map(config => {
123
+ const { trackId, textSearching, adapter } = config;
124
+ return {
125
+ trackId,
126
+ attributesIndexed: (textSearching === null || textSearching === void 0 ? void 0 : textSearching.indexingAttributes) || attributesToIndex,
127
+ excludedTypes: (textSearching === null || textSearching === void 0 ? void 0 : textSearching.indexingFeatureTypesToExclude) ||
128
+ featureTypesToExclude,
129
+ adapterConf: adapter,
130
+ };
131
+ }),
140
132
  assemblyNames,
141
133
  }, null, 2));
142
134
  }
@@ -1,2 +1,11 @@
1
- import { Track } from '../util';
2
- export declare function indexGff3(config: Track, attributes: string[], inLocation: string, outLocation: string, typesToExclude: string[], quiet: boolean, statusCallback: (message: string) => void, signal?: AbortSignal): AsyncGenerator<string, void, unknown>;
1
+ export declare function indexGff3({ config, attributesToIndex, inLocation, outDir, featureTypesToExclude, onStart, onUpdate, }: {
2
+ config: {
3
+ trackId: string;
4
+ };
5
+ attributesToIndex: string[];
6
+ inLocation: string;
7
+ outDir: string;
8
+ featureTypesToExclude: string[];
9
+ onStart: (totalBytes: number) => void;
10
+ onUpdate: (progressBytes: number) => void;
11
+ }): AsyncGenerator<string, void, unknown>;
@@ -1,23 +1,25 @@
1
1
  import { createGunzip } from 'zlib';
2
2
  import readline from 'readline';
3
+ // locals
3
4
  import { decodeURIComponentNoThrow } from '../util';
4
5
  import { getLocalOrRemoteStream } from './common';
5
- import { checkAbortSignal } from '@jbrowse/core/util';
6
- export async function* indexGff3(config, attributes, inLocation, outLocation, typesToExclude, quiet, statusCallback, signal) {
6
+ export async function* indexGff3({ config, attributesToIndex, inLocation, outDir, featureTypesToExclude, onStart, onUpdate, }) {
7
7
  const { trackId } = config;
8
8
  let receivedBytes = 0;
9
- const { totalBytes, stream } = await getLocalOrRemoteStream(inLocation, outLocation);
9
+ const { totalBytes, stream } = await getLocalOrRemoteStream(inLocation, outDir);
10
+ onStart(totalBytes);
10
11
  stream.on('data', chunk => {
11
12
  receivedBytes += chunk.length;
12
- // send an update?
13
- const progress = Math.round((receivedBytes / totalBytes) * 100);
14
- statusCallback(`${progress}`);
13
+ onUpdate(receivedBytes);
15
14
  });
16
15
  const rl = readline.createInterface({
17
- input: inLocation.match(/.b?gz$/) ? stream.pipe(createGunzip()) : stream,
16
+ input: /.b?gz$/.exec(inLocation) ? stream.pipe(createGunzip()) : stream,
18
17
  });
19
18
  for await (const line of rl) {
20
- if (line.startsWith('#')) {
19
+ if (!line.trim()) {
20
+ continue;
21
+ }
22
+ else if (line.startsWith('#')) {
21
23
  continue;
22
24
  }
23
25
  else if (line.startsWith('>')) {
@@ -25,7 +27,7 @@ export async function* indexGff3(config, attributes, inLocation, outLocation, ty
25
27
  }
26
28
  const [seq_id, , type, start, end, , , , col9] = line.split('\t');
27
29
  const locStr = `${seq_id}:${start}..${end}`;
28
- if (!typesToExclude.includes(type)) {
30
+ if (!featureTypesToExclude.includes(type)) {
29
31
  // turns gff3 attrs into a map, and converts the arrays into space
30
32
  // separated strings
31
33
  const col9attrs = Object.fromEntries(col9
@@ -35,9 +37,11 @@ export async function* indexGff3(config, attributes, inLocation, outLocation, ty
35
37
  .map(f => f.split('='))
36
38
  .map(([key, val]) => [
37
39
  key.trim(),
38
- decodeURIComponentNoThrow(val).trim().split(',').join(' '),
40
+ val
41
+ ? decodeURIComponentNoThrow(val).trim().split(',').join(' ')
42
+ : undefined,
39
43
  ]));
40
- const attrs = attributes
44
+ const attrs = attributesToIndex
41
45
  .map(attr => col9attrs[attr])
42
46
  .filter((f) => !!f);
43
47
  if (attrs.length) {
@@ -46,11 +50,8 @@ export async function* indexGff3(config, attributes, inLocation, outLocation, ty
46
50
  encodeURIComponent(trackId),
47
51
  ...attrs.map(a => encodeURIComponent(a)),
48
52
  ]).replaceAll(',', '|');
49
- // Check abort signal
50
- checkAbortSignal(signal);
51
53
  yield `${record} ${[...new Set(attrs)].join(' ')}\n`;
52
54
  }
53
55
  }
54
56
  }
55
- // console.log('done')
56
57
  }
@@ -1,2 +1,8 @@
1
- import { Track } from '../util';
2
- export declare function indexVcf(config: Track, attributesToIndex: string[], inLocation: string, outLocation: string, typesToExclude: string[], quiet: boolean, statusCallback: (message: string) => void, signal?: AbortSignal): AsyncGenerator<string, void, unknown>;
1
+ export declare function indexVcf({ config, attributesToIndex, inLocation, outDir, onStart, onUpdate, }: {
2
+ config: any;
3
+ attributesToIndex: string[];
4
+ inLocation: string;
5
+ outDir: string;
6
+ onStart: (totalBytes: number) => void;
7
+ onUpdate: (progressBytes: number) => void;
8
+ }): AsyncGenerator<string, void, unknown>;
@@ -1,18 +1,18 @@
1
1
  import { createGunzip } from 'zlib';
2
2
  import readline from 'readline';
3
+ // locals
3
4
  import { decodeURIComponentNoThrow } from '../util';
4
5
  import { getLocalOrRemoteStream } from './common';
5
- import { checkAbortSignal } from '@jbrowse/core/util';
6
- export async function* indexVcf(config, attributesToIndex, inLocation, outLocation, typesToExclude, quiet, statusCallback, signal) {
6
+ export async function* indexVcf({ config, attributesToIndex, inLocation, outDir, onStart, onUpdate, }) {
7
7
  const { trackId } = config;
8
8
  let receivedBytes = 0;
9
- const { totalBytes, stream } = await getLocalOrRemoteStream(inLocation, outLocation);
9
+ const { totalBytes, stream } = await getLocalOrRemoteStream(inLocation, outDir);
10
+ onStart(totalBytes);
10
11
  stream.on('data', chunk => {
11
12
  receivedBytes += chunk.length;
12
- const progress = Math.round((receivedBytes / totalBytes) * 100);
13
- statusCallback(`${progress}`);
13
+ onUpdate(receivedBytes);
14
14
  });
15
- const gzStream = inLocation.match(/.b?gz$/)
15
+ const gzStream = /.b?gz$/.exec(inLocation)
16
16
  ? stream.pipe(createGunzip())
17
17
  : stream;
18
18
  const rl = readline.createInterface({
@@ -24,7 +24,7 @@ export async function* indexVcf(config, attributesToIndex, inLocation, outLocati
24
24
  }
25
25
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
26
  const [ref, pos, id, _ref, _alt, _qual, _filter, info] = line.split('\t');
27
- // turns vcf info attrs into a map, and converts the arrays into space
27
+ // turns gff3 attrs into a map, and converts the arrays into space
28
28
  // separated strings
29
29
  const fields = Object.fromEntries(info
30
30
  .split(';')
@@ -54,8 +54,6 @@ export async function* indexVcf(config, attributesToIndex, inLocation, outLocati
54
54
  encodeURIComponent(id || ''),
55
55
  ...infoAttrs.map(a => encodeURIComponent(a || '')),
56
56
  ]).replaceAll(',', '|');
57
- // Check abort signal
58
- checkAbortSignal(signal);
59
57
  yield `${record} ${[...new Set(attrs)].join(' ')}\n`;
60
58
  }
61
59
  }
package/esm/util.d.ts CHANGED
@@ -50,27 +50,37 @@ export interface Sequence {
50
50
  trackId: string;
51
51
  adapter: IndexedFastaAdapter | BgzipFastaAdapter | TwoBitAdapter | ChromeSizesAdapter | CustomSequenceAdapter;
52
52
  }
53
+ type Loc = UriLocation | LocalPathLocation;
53
54
  export interface Gff3TabixAdapter {
54
55
  type: 'Gff3TabixAdapter';
55
- gffGzLocation: UriLocation | LocalPathLocation;
56
+ gffGzLocation: Loc;
56
57
  }
57
58
  export interface Gff3Adapter {
58
59
  type: 'Gff3Adapter';
59
- gffLocation: UriLocation | LocalPathLocation;
60
+ gffLocation: Loc;
60
61
  }
61
62
  export interface GtfAdapter {
62
63
  type: 'GtfAdapter';
63
- gtfLocation: UriLocation | LocalPathLocation;
64
+ gtfLocation: Loc;
64
65
  }
65
66
  export interface VcfTabixAdapter {
66
67
  type: 'VcfTabixAdapter';
67
- vcfGzLocation: UriLocation | LocalPathLocation;
68
+ vcfGzLocation: Loc;
68
69
  }
69
70
  export interface VcfAdapter {
70
71
  type: 'VcfAdapter';
71
- vcfLocation: UriLocation | LocalPathLocation;
72
+ vcfLocation: Loc;
73
+ }
74
+ export interface Track {
75
+ adapter?: {
76
+ type: string;
77
+ [key: string]: unknown;
78
+ };
79
+ textSearching?: TextSearching;
80
+ name: string;
81
+ assemblyNames: string[];
82
+ trackId: string;
72
83
  }
73
- export type Track = Record<string, any>;
74
84
  export interface TextSearching {
75
85
  indexingFeatureTypesToExclude?: string[];
76
86
  indexingAttributes?: string[];
@@ -87,10 +97,10 @@ export interface TrixTextSearchAdapter {
87
97
  export interface Config {
88
98
  assemblies?: Assembly[];
89
99
  assembly?: Assembly;
90
- configuration?: {};
100
+ configuration?: Record<string, unknown>;
91
101
  aggregateTextSearchAdapters?: TrixTextSearchAdapter[];
92
102
  connections?: unknown[];
93
- defaultSession?: {};
103
+ defaultSession?: Record<string, unknown>;
94
104
  tracks?: Track[];
95
105
  }
96
106
  export type indexType = 'aggregate' | 'perTrack';
@@ -114,3 +124,4 @@ export declare function createTextSearchConf(name: string, trackIds: string[], a
114
124
  };
115
125
  export declare function findTrackConfigsToIndex(tracks: Track[], trackIds: string[], assemblyName?: string): Track[];
116
126
  export declare function decodeURIComponentNoThrow(uri: string): string;
127
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/text-indexing",
3
- "version": "2.13.1",
3
+ "version": "2.15.0",
4
4
  "description": "JBrowse 2 text indexing for desktop",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -32,7 +32,7 @@
32
32
  "build:esm": "tsc --build tsconfig.build.esm.json",
33
33
  "build:commonjs": "tsc --build tsconfig.build.commonjs.json",
34
34
  "build": "npm run build:esm && npm run build:commonjs",
35
- "test": "cd ../..; jest packages/text-indexing",
35
+ "test": "cd ../..; jest --passWithNoTests packages/text-indexing",
36
36
  "clean": "rimraf dist esm *.tsbuildinfo",
37
37
  "prebuild": "yarn clean",
38
38
  "prepack": "yarn build && yarn useDist",
@@ -42,6 +42,7 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "@babel/runtime": "^7.16.3",
45
+ "@jbrowse/core": "^2.15.0",
45
46
  "ixixx": "^2.0.1",
46
47
  "node-fetch": "^2.6.0",
47
48
  "sanitize-filename": "^1.6.3"
@@ -57,5 +58,5 @@
57
58
  "publishConfig": {
58
59
  "access": "public"
59
60
  },
60
- "gitHead": "fcebca71cc1d066654603e1a9accfa6c6d4f764d"
61
+ "gitHead": "87eeb1fbf8311dbf88d5e75b5a265f03beffdda8"
61
62
  }