@gmod/bam 8.11.1 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/htsget.d.ts +7 -6
- package/dist/htsget.js +21 -10
- package/dist/htsget.js.map +1 -1
- package/esm/htsget.d.ts +7 -6
- package/esm/htsget.js +21 -10
- package/esm/htsget.js.map +1 -1
- package/package.json +1 -1
- package/src/htsget.ts +28 -26
package/dist/htsget.d.ts
CHANGED
|
@@ -12,12 +12,13 @@ export default class HtsgetFile<T extends BamRecordLike = BamRecord> extends Bam
|
|
|
12
12
|
baseUrl: string;
|
|
13
13
|
recordClass?: BamRecordClass<T>;
|
|
14
14
|
/**
|
|
15
|
-
* fetch implementation
|
|
16
|
-
* <token>` header can be added for
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
15
|
+
* fetch implementation for the **ticket request**, so an `Authorization:
|
|
16
|
+
* Bearer <token>` header can be added for endpoints that require one.
|
|
17
|
+
*
|
|
18
|
+
* The data blocks a ticket names are NOT fetched with it — they can point
|
|
19
|
+
* at any host, and the spec forbids sending the API's token to them. A
|
|
20
|
+
* block needing authorization carries it in the ticket's own `headers`
|
|
21
|
+
* field for that url, which is applied regardless.
|
|
21
22
|
*/
|
|
22
23
|
fetch?: Fetcher;
|
|
23
24
|
/**
|
package/dist/htsget.js
CHANGED
|
@@ -56,19 +56,28 @@ async function fetchOk(fetchFn, url, opts) {
|
|
|
56
56
|
}
|
|
57
57
|
return res;
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Data blocks are fetched with the global fetch, never with the ticket fetcher.
|
|
61
|
+
* The spec is explicit ("HTTPS data block URLs", rule 6): a block url must
|
|
62
|
+
* carry whatever credential it needs itself, in the url or in its own `headers`,
|
|
63
|
+
* and the client "must not send the bearer token used for the API, if any, to
|
|
64
|
+
* the data block endpoint, unless copied in the required `headers`". A ticket
|
|
65
|
+
* can name any host, so honouring that is the difference between one endpoint's
|
|
66
|
+
* token going to that endpoint and it going wherever a ticket points.
|
|
67
|
+
*/
|
|
68
|
+
async function fetchChunk({ url, headers }, opts) {
|
|
60
69
|
// pass base64 data URLs straight to fetch; otherwise apply headers (minus
|
|
61
70
|
// referer, which isn't a permitted client-set header).
|
|
62
71
|
// https://stackoverflow.com/a/54123275/2129219
|
|
63
72
|
const { referer: _referer, ...rest } = headers ?? {};
|
|
64
73
|
const res = url.startsWith('data:')
|
|
65
|
-
? await fetchOk(
|
|
66
|
-
: await fetchOk(
|
|
74
|
+
? await fetchOk(fetch, url)
|
|
75
|
+
: await fetchOk(fetch, url, { ...opts, headers: rest });
|
|
67
76
|
return new Uint8Array(await res.arrayBuffer());
|
|
68
77
|
}
|
|
69
|
-
async function fetchAndConcat(
|
|
78
|
+
async function fetchAndConcat(arr, opts) {
|
|
70
79
|
// Pipeline unzip after each fetch so decompression overlaps later fetches.
|
|
71
|
-
return (0, util_ts_1.concatUint8Array)(await Promise.all(arr.map(async (c) => (0, bgzf_filehandle_1.unzip)(await fetchChunk(
|
|
80
|
+
return (0, util_ts_1.concatUint8Array)(await Promise.all(arr.map(async (c) => (0, bgzf_filehandle_1.unzip)(await fetchChunk(c, opts)))));
|
|
72
81
|
}
|
|
73
82
|
class HtsgetFile extends bamFile_ts_1.default {
|
|
74
83
|
baseUrl;
|
|
@@ -91,12 +100,14 @@ class HtsgetFile extends bamFile_ts_1.default {
|
|
|
91
100
|
* concatenated, which per the spec is a complete BAM stream.
|
|
92
101
|
*/
|
|
93
102
|
async fetchTicket(query, opts) {
|
|
94
|
-
|
|
103
|
+
// Exactly one slash between the two. An id may contain "/" and the spec's
|
|
104
|
+
// own examples start with one ("/byStudy/PRJEB4019"), while an endpoint is
|
|
105
|
+
// as often written with a trailing slash as without; concatenating raw
|
|
106
|
+
// produced "//" for either.
|
|
107
|
+
const url = `${this.baseUrl.replace(/\/+$/, '')}/${this.trackId.replace(/^\/+/, '')}?${query}`;
|
|
95
108
|
const res = await fetchOk(this.fetchFn, url, { signal: opts?.signal });
|
|
96
109
|
const ticket = await res.json();
|
|
97
|
-
return fetchAndConcat(
|
|
98
|
-
signal: opts?.signal,
|
|
99
|
-
});
|
|
110
|
+
return fetchAndConcat(ticket.htsget.urls, { signal: opts?.signal });
|
|
100
111
|
}
|
|
101
112
|
async getRecordsForRange(chr, min, max, opts) {
|
|
102
113
|
await this.getHeader(opts);
|
|
@@ -104,7 +115,7 @@ class HtsgetFile extends bamFile_ts_1.default {
|
|
|
104
115
|
if (chrId === undefined) {
|
|
105
116
|
return [];
|
|
106
117
|
}
|
|
107
|
-
const uncba = await this.fetchTicket(`referenceName=${chr}&start=${min}&end=${max}&format=BAM`, opts);
|
|
118
|
+
const uncba = await this.fetchTicket(`referenceName=${encodeURIComponent(chr)}&start=${min}&end=${max}&format=BAM`, opts);
|
|
108
119
|
const zero = new virtualOffset_ts_1.VirtualOffset(0, 0);
|
|
109
120
|
const records = this.readBamFeatures(uncba.subarray(recordsOffset(uncba)), [], [], new chunk_ts_1.default(zero, zero, 0));
|
|
110
121
|
const result = (0, util_ts_1.appendInRange)(records, chrId, min, max);
|
package/dist/htsget.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htsget.js","sourceRoot":"","sources":["../src/htsget.ts"],"names":[],"mappings":";;;;;AAAA,2DAA6C;AAE7C,8DAAkC;AAClC,0DAA8B;AAC9B,uCAKkB;AAClB,yDAAkD;AA2BlD,kEAAkE;AAClE,+EAA+E;AAC/E,iFAAiF;AACjF,SAAS,kBAAkB,CAAC,IAAY;IACtC,IAAI,MAAmC,CAAA;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,yCAAyC;IAC3C,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,EAAE,MAAM,CAAA;IAC1B,OAAO,GAAG,EAAE,KAAK,KAAK,SAAS;QAC7B,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,GAAG,CAAC,OAAO,KAAK,SAAS;YACzB,CAAC,CAAC,GAAG,CAAC,KAAK;YACX,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,OAAO,EAAE,CAAA;AACtC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,aAAa,CAAC,KAAiB;IACtC,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAC3B,KAAK,CAAC,MAAM,EACZ,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,UAAU,CACjB,CAAA;IACD,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,mBAAS,EAAE,CAAC;QACrE,OAAO,CAAC,CAAA;IACV,CAAC;IACD,MAAM,IAAI,GAAG,IAAA,sBAAY,EAAC,KAAK,EAAE,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACxE,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAA;AACjB,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,OAAgB,EAAE,GAAW,EAAE,IAAkB;IACtE,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IACpC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,QAAQ,GAAG,CAAC,MAAM,aAAa,GAAG,KAAK,kBAAkB,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAC9E,CAAA;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,KAAK,UAAU,UAAU,
|
|
1
|
+
{"version":3,"file":"htsget.js","sourceRoot":"","sources":["../src/htsget.ts"],"names":[],"mappings":"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"}
|
package/esm/htsget.d.ts
CHANGED
|
@@ -12,12 +12,13 @@ export default class HtsgetFile<T extends BamRecordLike = BamRecord> extends Bam
|
|
|
12
12
|
baseUrl: string;
|
|
13
13
|
recordClass?: BamRecordClass<T>;
|
|
14
14
|
/**
|
|
15
|
-
* fetch implementation
|
|
16
|
-
* <token>` header can be added for
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
15
|
+
* fetch implementation for the **ticket request**, so an `Authorization:
|
|
16
|
+
* Bearer <token>` header can be added for endpoints that require one.
|
|
17
|
+
*
|
|
18
|
+
* The data blocks a ticket names are NOT fetched with it — they can point
|
|
19
|
+
* at any host, and the spec forbids sending the API's token to them. A
|
|
20
|
+
* block needing authorization carries it in the ticket's own `headers`
|
|
21
|
+
* field for that url, which is applied regardless.
|
|
21
22
|
*/
|
|
22
23
|
fetch?: Fetcher;
|
|
23
24
|
/**
|
package/esm/htsget.js
CHANGED
|
@@ -51,19 +51,28 @@ async function fetchOk(fetchFn, url, opts) {
|
|
|
51
51
|
}
|
|
52
52
|
return res;
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Data blocks are fetched with the global fetch, never with the ticket fetcher.
|
|
56
|
+
* The spec is explicit ("HTTPS data block URLs", rule 6): a block url must
|
|
57
|
+
* carry whatever credential it needs itself, in the url or in its own `headers`,
|
|
58
|
+
* and the client "must not send the bearer token used for the API, if any, to
|
|
59
|
+
* the data block endpoint, unless copied in the required `headers`". A ticket
|
|
60
|
+
* can name any host, so honouring that is the difference between one endpoint's
|
|
61
|
+
* token going to that endpoint and it going wherever a ticket points.
|
|
62
|
+
*/
|
|
63
|
+
async function fetchChunk({ url, headers }, opts) {
|
|
55
64
|
// pass base64 data URLs straight to fetch; otherwise apply headers (minus
|
|
56
65
|
// referer, which isn't a permitted client-set header).
|
|
57
66
|
// https://stackoverflow.com/a/54123275/2129219
|
|
58
67
|
const { referer: _referer, ...rest } = headers ?? {};
|
|
59
68
|
const res = url.startsWith('data:')
|
|
60
|
-
? await fetchOk(
|
|
61
|
-
: await fetchOk(
|
|
69
|
+
? await fetchOk(fetch, url)
|
|
70
|
+
: await fetchOk(fetch, url, { ...opts, headers: rest });
|
|
62
71
|
return new Uint8Array(await res.arrayBuffer());
|
|
63
72
|
}
|
|
64
|
-
async function fetchAndConcat(
|
|
73
|
+
async function fetchAndConcat(arr, opts) {
|
|
65
74
|
// Pipeline unzip after each fetch so decompression overlaps later fetches.
|
|
66
|
-
return concatUint8Array(await Promise.all(arr.map(async (c) => unzip(await fetchChunk(
|
|
75
|
+
return concatUint8Array(await Promise.all(arr.map(async (c) => unzip(await fetchChunk(c, opts)))));
|
|
67
76
|
}
|
|
68
77
|
export default class HtsgetFile extends BamFile {
|
|
69
78
|
baseUrl;
|
|
@@ -86,12 +95,14 @@ export default class HtsgetFile extends BamFile {
|
|
|
86
95
|
* concatenated, which per the spec is a complete BAM stream.
|
|
87
96
|
*/
|
|
88
97
|
async fetchTicket(query, opts) {
|
|
89
|
-
|
|
98
|
+
// Exactly one slash between the two. An id may contain "/" and the spec's
|
|
99
|
+
// own examples start with one ("/byStudy/PRJEB4019"), while an endpoint is
|
|
100
|
+
// as often written with a trailing slash as without; concatenating raw
|
|
101
|
+
// produced "//" for either.
|
|
102
|
+
const url = `${this.baseUrl.replace(/\/+$/, '')}/${this.trackId.replace(/^\/+/, '')}?${query}`;
|
|
90
103
|
const res = await fetchOk(this.fetchFn, url, { signal: opts?.signal });
|
|
91
104
|
const ticket = await res.json();
|
|
92
|
-
return fetchAndConcat(
|
|
93
|
-
signal: opts?.signal,
|
|
94
|
-
});
|
|
105
|
+
return fetchAndConcat(ticket.htsget.urls, { signal: opts?.signal });
|
|
95
106
|
}
|
|
96
107
|
async getRecordsForRange(chr, min, max, opts) {
|
|
97
108
|
await this.getHeader(opts);
|
|
@@ -99,7 +110,7 @@ export default class HtsgetFile extends BamFile {
|
|
|
99
110
|
if (chrId === undefined) {
|
|
100
111
|
return [];
|
|
101
112
|
}
|
|
102
|
-
const uncba = await this.fetchTicket(`referenceName=${chr}&start=${min}&end=${max}&format=BAM`, opts);
|
|
113
|
+
const uncba = await this.fetchTicket(`referenceName=${encodeURIComponent(chr)}&start=${min}&end=${max}&format=BAM`, opts);
|
|
103
114
|
const zero = new VirtualOffset(0, 0);
|
|
104
115
|
const records = this.readBamFeatures(uncba.subarray(recordsOffset(uncba)), [], [], new Chunk(zero, zero, 0));
|
|
105
116
|
const result = appendInRange(records, chrId, min, max);
|
package/esm/htsget.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htsget.js","sourceRoot":"","sources":["../src/htsget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAE7C,OAAO,OAAO,MAAM,cAAc,CAAA;AAClC,OAAO,KAAK,MAAM,YAAY,CAAA;AAC9B,OAAO,EACL,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,YAAY,GACb,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AA2BlD,kEAAkE;AAClE,+EAA+E;AAC/E,iFAAiF;AACjF,SAAS,kBAAkB,CAAC,IAAY;IACtC,IAAI,MAAmC,CAAA;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,yCAAyC;IAC3C,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,EAAE,MAAM,CAAA;IAC1B,OAAO,GAAG,EAAE,KAAK,KAAK,SAAS;QAC7B,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,GAAG,CAAC,OAAO,KAAK,SAAS;YACzB,CAAC,CAAC,GAAG,CAAC,KAAK;YACX,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,OAAO,EAAE,CAAA;AACtC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,aAAa,CAAC,KAAiB;IACtC,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAC3B,KAAK,CAAC,MAAM,EACZ,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,UAAU,CACjB,CAAA;IACD,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QACrE,OAAO,CAAC,CAAA;IACV,CAAC;IACD,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACxE,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAA;AACjB,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,OAAgB,EAAE,GAAW,EAAE,IAAkB;IACtE,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IACpC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,QAAQ,GAAG,CAAC,MAAM,aAAa,GAAG,KAAK,kBAAkB,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAC9E,CAAA;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,KAAK,UAAU,UAAU,
|
|
1
|
+
{"version":3,"file":"htsget.js","sourceRoot":"","sources":["../src/htsget.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/htsget.ts
CHANGED
|
@@ -91,31 +91,30 @@ async function fetchOk(fetchFn: Fetcher, url: string, opts?: RequestInit) {
|
|
|
91
91
|
return res
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Data blocks are fetched with the global fetch, never with the ticket fetcher.
|
|
96
|
+
* The spec is explicit ("HTTPS data block URLs", rule 6): a block url must
|
|
97
|
+
* carry whatever credential it needs itself, in the url or in its own `headers`,
|
|
98
|
+
* and the client "must not send the bearer token used for the API, if any, to
|
|
99
|
+
* the data block endpoint, unless copied in the required `headers`". A ticket
|
|
100
|
+
* can name any host, so honouring that is the difference between one endpoint's
|
|
101
|
+
* token going to that endpoint and it going wherever a ticket points.
|
|
102
|
+
*/
|
|
103
|
+
async function fetchChunk({ url, headers }: HtsgetChunk, opts?: RequestInit) {
|
|
99
104
|
// pass base64 data URLs straight to fetch; otherwise apply headers (minus
|
|
100
105
|
// referer, which isn't a permitted client-set header).
|
|
101
106
|
// https://stackoverflow.com/a/54123275/2129219
|
|
102
107
|
const { referer: _referer, ...rest } = headers ?? {}
|
|
103
108
|
const res = url.startsWith('data:')
|
|
104
|
-
? await fetchOk(
|
|
105
|
-
: await fetchOk(
|
|
109
|
+
? await fetchOk(fetch, url)
|
|
110
|
+
: await fetchOk(fetch, url, { ...opts, headers: rest })
|
|
106
111
|
return new Uint8Array(await res.arrayBuffer())
|
|
107
112
|
}
|
|
108
113
|
|
|
109
|
-
async function fetchAndConcat(
|
|
110
|
-
fetchFn: Fetcher,
|
|
111
|
-
arr: HtsgetChunk[],
|
|
112
|
-
opts?: RequestInit,
|
|
113
|
-
) {
|
|
114
|
+
async function fetchAndConcat(arr: HtsgetChunk[], opts?: RequestInit) {
|
|
114
115
|
// Pipeline unzip after each fetch so decompression overlaps later fetches.
|
|
115
116
|
return concatUint8Array(
|
|
116
|
-
await Promise.all(
|
|
117
|
-
arr.map(async c => unzip(await fetchChunk(fetchFn, c, opts))),
|
|
118
|
-
),
|
|
117
|
+
await Promise.all(arr.map(async c => unzip(await fetchChunk(c, opts)))),
|
|
119
118
|
)
|
|
120
119
|
}
|
|
121
120
|
|
|
@@ -133,12 +132,13 @@ export default class HtsgetFile<
|
|
|
133
132
|
baseUrl: string
|
|
134
133
|
recordClass?: BamRecordClass<T>
|
|
135
134
|
/**
|
|
136
|
-
* fetch implementation
|
|
137
|
-
* <token>` header can be added for
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
135
|
+
* fetch implementation for the **ticket request**, so an `Authorization:
|
|
136
|
+
* Bearer <token>` header can be added for endpoints that require one.
|
|
137
|
+
*
|
|
138
|
+
* The data blocks a ticket names are NOT fetched with it — they can point
|
|
139
|
+
* at any host, and the spec forbids sending the API's token to them. A
|
|
140
|
+
* block needing authorization carries it in the ticket's own `headers`
|
|
141
|
+
* field for that url, which is applied regardless.
|
|
142
142
|
*/
|
|
143
143
|
fetch?: Fetcher
|
|
144
144
|
/**
|
|
@@ -179,12 +179,14 @@ export default class HtsgetFile<
|
|
|
179
179
|
* concatenated, which per the spec is a complete BAM stream.
|
|
180
180
|
*/
|
|
181
181
|
private async fetchTicket(query: string, opts?: BaseOpts) {
|
|
182
|
-
|
|
182
|
+
// Exactly one slash between the two. An id may contain "/" and the spec's
|
|
183
|
+
// own examples start with one ("/byStudy/PRJEB4019"), while an endpoint is
|
|
184
|
+
// as often written with a trailing slash as without; concatenating raw
|
|
185
|
+
// produced "//" for either.
|
|
186
|
+
const url = `${this.baseUrl.replace(/\/+$/, '')}/${this.trackId.replace(/^\/+/, '')}?${query}`
|
|
183
187
|
const res = await fetchOk(this.fetchFn, url, { signal: opts?.signal })
|
|
184
188
|
const ticket: HtsgetTicket = await res.json()
|
|
185
|
-
return fetchAndConcat(
|
|
186
|
-
signal: opts?.signal,
|
|
187
|
-
})
|
|
189
|
+
return fetchAndConcat(ticket.htsget.urls, { signal: opts?.signal })
|
|
188
190
|
}
|
|
189
191
|
|
|
190
192
|
async getRecordsForRange(
|
|
@@ -199,7 +201,7 @@ export default class HtsgetFile<
|
|
|
199
201
|
return []
|
|
200
202
|
}
|
|
201
203
|
const uncba = await this.fetchTicket(
|
|
202
|
-
`referenceName=${chr}&start=${min}&end=${max}&format=BAM`,
|
|
204
|
+
`referenceName=${encodeURIComponent(chr)}&start=${min}&end=${max}&format=BAM`,
|
|
203
205
|
opts,
|
|
204
206
|
)
|
|
205
207
|
const zero = new VirtualOffset(0, 0)
|