generic-filehandle2 2.0.18 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -54
- package/dist/blobFile.d.ts +1 -1
- package/dist/blobFile.js +6 -7
- package/dist/blobFile.js.map +1 -1
- package/dist/filehandle.d.ts +3 -11
- package/dist/index.d.ts +0 -1
- package/dist/localFile.d.ts +3 -3
- package/dist/localFile.js +2 -1
- package/dist/localFile.js.map +1 -1
- package/dist/remoteFile.d.ts +2 -1
- package/dist/remoteFile.js +28 -42
- package/dist/remoteFile.js.map +1 -1
- package/esm/blobFile.d.ts +1 -1
- package/esm/blobFile.js +6 -7
- package/esm/blobFile.js.map +1 -1
- package/esm/filehandle.d.ts +3 -11
- package/esm/index.d.ts +0 -1
- package/esm/localFile.d.ts +3 -3
- package/esm/localFile.js +2 -1
- package/esm/localFile.js.map +1 -1
- package/esm/remoteFile.d.ts +2 -1
- package/esm/remoteFile.js +28 -42
- package/esm/remoteFile.js.map +1 -1
- package/package.json +26 -31
- package/src/blobFile.ts +6 -8
- package/src/filehandle.ts +17 -11
- package/src/index.ts +0 -2
- package/src/localFile.ts +8 -3
- package/src/remoteFile.ts +30 -41
package/README.md
CHANGED
|
@@ -11,75 +11,57 @@ HTTP resources, and Blob data in the browser.
|
|
|
11
11
|
```js
|
|
12
12
|
import { LocalFile, RemoteFile, BlobFile } from 'generic-filehandle2'
|
|
13
13
|
|
|
14
|
-
// operate on a local file path
|
|
15
14
|
const local = new LocalFile('/some/file/path/file.txt')
|
|
16
|
-
|
|
17
|
-
// operate on a remote file path
|
|
18
15
|
const remote = new RemoteFile('http://somesite.com/file.txt')
|
|
19
|
-
|
|
20
|
-
// operate on blob objects
|
|
21
16
|
const blobfile = new BlobFile(new Blob([some_data], { type: 'text/plain' }))
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
const buf1 = await remote.read(10, 10)
|
|
25
|
-
// read whole file
|
|
18
|
+
const buf1 = await remote.read(/* length */ 10, /* position */ 10) // range request
|
|
26
19
|
const buf2 = await remote.readFile()
|
|
27
20
|
```
|
|
28
21
|
|
|
29
|
-
Important: under node.js, you should supply a fetch function to the RemoteFile
|
|
30
|
-
constructor
|
|
31
|
-
|
|
32
|
-
```js
|
|
33
|
-
import { RemoteFile } from 'generic-filehandle2'
|
|
34
|
-
import fetch from 'node-fetch'
|
|
35
|
-
const remote = new RemoteFile('http://somesite.com/file.txt', { fetch })
|
|
36
|
-
```
|
|
37
|
-
|
|
38
22
|
## API
|
|
39
23
|
|
|
40
|
-
### `async read(length: number, position: number
|
|
41
|
-
|
|
42
|
-
- length - a length of data to read
|
|
43
|
-
- position - the byte offset in the file to read from
|
|
44
|
-
- opts - optional Options object
|
|
24
|
+
### `async read(length: number, position: number, opts?: Options): Promise<Uint8Array>`
|
|
45
25
|
|
|
46
|
-
|
|
26
|
+
- `length` - number of bytes to read
|
|
27
|
+
- `position` - byte offset to read from
|
|
47
28
|
|
|
48
29
|
### `async readFile(opts?: Options): Promise<Uint8Array | string>`
|
|
49
30
|
|
|
50
|
-
Returns
|
|
51
|
-
|
|
31
|
+
Returns the full file contents as a `Uint8Array`, or as a `string` if
|
|
32
|
+
`opts.encoding` is set.
|
|
52
33
|
|
|
53
|
-
### `async stat()
|
|
34
|
+
### `async stat(): Promise<{ size: number }>`
|
|
54
35
|
|
|
55
|
-
Returns
|
|
56
|
-
is available. At minimum, the `size` of the file will be present.
|
|
36
|
+
Returns an object with the `size` of the file.
|
|
57
37
|
|
|
58
38
|
### Options
|
|
59
39
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
-
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
40
|
+
All entries are optional.
|
|
41
|
+
|
|
42
|
+
- `signal` `<AbortSignal>` - passed to the fetch or file read call
|
|
43
|
+
- `headers` `<Record<string, string>>` - extra HTTP headers for remote requests
|
|
44
|
+
- `overrides` `<Object>` - extra parameters passed to the fetch call
|
|
45
|
+
- `encoding` `<string>` - (`readFile` only) if set to `"utf8"`, returns a string
|
|
46
|
+
instead of `Uint8Array`
|
|
47
|
+
|
|
48
|
+
### Constructor options
|
|
49
|
+
|
|
50
|
+
The `RemoteFile` constructor accepts the same Options above, plus:
|
|
51
|
+
|
|
52
|
+
- `fetch` `<Function>` - custom fetch implementation (defaults to
|
|
53
|
+
`globalThis.fetch`)
|
|
54
|
+
|
|
55
|
+
## See also
|
|
56
|
+
|
|
57
|
+
The original generic-filehandle library:
|
|
58
|
+
https://github.com/GMOD/generic-filehandle
|
|
59
|
+
|
|
60
|
+
## Publishing
|
|
61
|
+
|
|
62
|
+
[Trusted publishing](https://docs.npmjs.com/about-trusted-publishing) via GitHub
|
|
63
|
+
Actions.
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm version patch # or minor/major
|
|
67
|
+
```
|
package/dist/blobFile.d.ts
CHANGED
package/dist/blobFile.js
CHANGED
|
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
* the Dalliance Genome Explorer, which is copyright Thomas Down 2006-2011.
|
|
8
8
|
*/
|
|
9
9
|
class BlobFile {
|
|
10
|
+
blob;
|
|
10
11
|
constructor(blob) {
|
|
11
12
|
this.blob = blob;
|
|
12
13
|
}
|
|
@@ -16,9 +17,7 @@ class BlobFile {
|
|
|
16
17
|
if (!length) {
|
|
17
18
|
return new Uint8Array(0);
|
|
18
19
|
}
|
|
19
|
-
const
|
|
20
|
-
const end = start + length;
|
|
21
|
-
const slice = this.blob.slice(start, end);
|
|
20
|
+
const slice = this.blob.slice(position, position + length);
|
|
22
21
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
23
22
|
return slice.bytes
|
|
24
23
|
? slice.bytes()
|
|
@@ -39,11 +38,11 @@ class BlobFile {
|
|
|
39
38
|
: new Uint8Array(await this.blob.arrayBuffer());
|
|
40
39
|
}
|
|
41
40
|
}
|
|
42
|
-
|
|
43
|
-
return { size: this.blob.size };
|
|
41
|
+
stat() {
|
|
42
|
+
return Promise.resolve({ size: this.blob.size });
|
|
44
43
|
}
|
|
45
|
-
|
|
46
|
-
return;
|
|
44
|
+
close() {
|
|
45
|
+
return Promise.resolve();
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
exports.default = BlobFile;
|
package/dist/blobFile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blobFile.js","sourceRoot":"","sources":["../src/blobFile.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"blobFile.js","sourceRoot":"","sources":["../src/blobFile.ts"],"names":[],"mappings":";;AAOA;;;;;GAKG;AACH,MAAqB,QAAQ;IACnB,IAAI,CAAM;IAElB,YAAmB,IAAU;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEM,KAAK,CAAC,IAAI,CACf,MAAc,EACd,QAAQ,GAAG,CAAC;QAEZ,4EAA4E;QAC5E,sDAAsD;QACtD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAA;QAC1D,uEAAuE;QACvE,OAAO,KAAK,CAAC,KAAK;YAChB,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE;YACf,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;IAC/C,CAAC;IAYM,KAAK,CAAC,QAAQ,CACnB,OAA4C;QAE5C,MAAM,QAAQ,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAA;QAC1E,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;QACzB,CAAC;aAAM,IAAI,QAAQ,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAA;QACtD,CAAC;aAAM,CAAC;YACN,uEAAuE;YACvE,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK;gBACpB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;gBACnB,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;QACnD,CAAC;IACH,CAAC;IAEM,IAAI;QACT,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;IAClD,CAAC;IAEM,KAAK;QACV,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAC1B,CAAC;CACF;AAzDD,2BAyDC"}
|
package/dist/filehandle.d.ts
CHANGED
|
@@ -1,22 +1,14 @@
|
|
|
1
|
+
export type BufferEncoding = 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'utf-16le' | 'ucs2' | 'ucs-2' | 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex';
|
|
1
2
|
export type Fetcher = (input: RequestInfo, init?: RequestInit) => Promise<Response>;
|
|
2
3
|
export interface FilehandleOptions {
|
|
3
|
-
/**
|
|
4
|
-
* optional AbortSignal object for aborting the request
|
|
5
|
-
*/
|
|
6
4
|
signal?: AbortSignal;
|
|
7
|
-
headers?:
|
|
8
|
-
overrides?:
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
overrides?: Omit<RequestInit, 'headers'>;
|
|
9
7
|
encoding?: BufferEncoding;
|
|
10
|
-
/**
|
|
11
|
-
* fetch function to use for HTTP requests. defaults to environment's
|
|
12
|
-
* global fetch. if there is no global fetch, and a fetch function is not provided,
|
|
13
|
-
* throws an error.
|
|
14
|
-
*/
|
|
15
8
|
fetch?: Fetcher;
|
|
16
9
|
}
|
|
17
10
|
export interface Stats {
|
|
18
11
|
size: number;
|
|
19
|
-
[key: string]: any;
|
|
20
12
|
}
|
|
21
13
|
export interface GenericFilehandle {
|
|
22
14
|
read(length: number, position: number, opts?: FilehandleOptions): Promise<Uint8Array<ArrayBuffer>>;
|
package/dist/index.d.ts
CHANGED
package/dist/localFile.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { FilehandleOptions, GenericFilehandle } from './filehandle.ts';
|
|
1
|
+
import type { BufferEncoding, FilehandleOptions, GenericFilehandle, Stats } from './filehandle.ts';
|
|
2
2
|
export default class LocalFile implements GenericFilehandle {
|
|
3
3
|
private filename;
|
|
4
|
-
constructor(source: string
|
|
4
|
+
constructor(source: string);
|
|
5
5
|
read(length: number, position?: number): Promise<Uint8Array<ArrayBuffer>>;
|
|
6
6
|
readFile(): Promise<Uint8Array<ArrayBuffer>>;
|
|
7
7
|
readFile(options: BufferEncoding): Promise<string>;
|
|
@@ -14,6 +14,6 @@ export default class LocalFile implements GenericFilehandle {
|
|
|
14
14
|
readFile<T extends BufferEncoding>(options: Omit<FilehandleOptions, 'encoding'> & {
|
|
15
15
|
encoding: T;
|
|
16
16
|
}): T extends BufferEncoding ? Promise<string> : Promise<Uint8Array<ArrayBuffer>>;
|
|
17
|
-
stat(): Promise<
|
|
17
|
+
stat(): Promise<Stats>;
|
|
18
18
|
close(): Promise<void>;
|
|
19
19
|
}
|
package/dist/localFile.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const promises_1 = require("fs/promises");
|
|
4
4
|
class LocalFile {
|
|
5
|
-
|
|
5
|
+
filename;
|
|
6
|
+
constructor(source) {
|
|
6
7
|
this.filename = source;
|
|
7
8
|
}
|
|
8
9
|
async read(length, position = 0) {
|
package/dist/localFile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localFile.js","sourceRoot":"","sources":["../src/localFile.ts"],"names":[],"mappings":";;AAAA,0CAAkD;
|
|
1
|
+
{"version":3,"file":"localFile.js","sourceRoot":"","sources":["../src/localFile.ts"],"names":[],"mappings":";;AAAA,0CAAkD;AASlD,MAAqB,SAAS;IACpB,QAAQ,CAAQ;IAExB,YAAmB,MAAc;QAC/B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAA;IACxB,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,QAAQ,GAAG,CAAC;QAC5C,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;YACjB,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAA;QAClC,IAAI,EAAE,CAAA;QACN,IAAI,CAAC;YACH,EAAE,GAAG,MAAM,IAAA,eAAI,EAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;YACnC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;YACnD,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAA;QAC9C,CAAC;gBAAS,CAAC;YACT,IAAI,EAAE,EAAE,CAAC;gBACP,IAAI,CAAC;oBACH,MAAM,EAAE,CAAC,KAAK,EAAE,CAAA;gBAClB,CAAC;gBAAC,MAAM,CAAC;oBACP,sEAAsE;oBACtE,oDAAoD;gBACtD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAiBM,KAAK,CAAC,QAAQ,CACnB,OAA4C;QAE5C,OAAO,IAAA,mBAAQ,EAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IACzC,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,OAAO,IAAA,eAAI,EAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC5B,CAAC;IAEM,KAAK,CAAC,KAAK;QAChB,gBAAgB;IAClB,CAAC;CACF;AAzDD,4BAyDC"}
|
package/dist/remoteFile.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { FilehandleOptions, GenericFilehandle, Stats } from './filehandle.ts';
|
|
1
|
+
import type { BufferEncoding, FilehandleOptions, GenericFilehandle, Stats } from './filehandle.ts';
|
|
2
2
|
export default class RemoteFile implements GenericFilehandle {
|
|
3
3
|
protected url: string;
|
|
4
4
|
private _stat?;
|
|
5
5
|
private fetchImplementation;
|
|
6
|
+
private baseHeaders;
|
|
6
7
|
private baseOverrides;
|
|
7
8
|
constructor(source: string, opts?: FilehandleOptions);
|
|
8
9
|
fetch(input: RequestInfo, init: RequestInit | undefined): Promise<Response>;
|
package/dist/remoteFile.js
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
function getMessage(e) {
|
|
4
|
-
const r = typeof e === 'object' &&
|
|
4
|
+
const r = typeof e === 'object' &&
|
|
5
|
+
e !== null &&
|
|
6
|
+
'message' in e &&
|
|
7
|
+
typeof e.message === 'string'
|
|
5
8
|
? e.message
|
|
6
9
|
: `${e}`;
|
|
7
10
|
return r.replace(/\.$/, '');
|
|
8
11
|
}
|
|
9
12
|
class RemoteFile {
|
|
13
|
+
url;
|
|
14
|
+
_stat;
|
|
15
|
+
fetchImplementation;
|
|
16
|
+
baseHeaders;
|
|
17
|
+
baseOverrides;
|
|
10
18
|
constructor(source, opts = {}) {
|
|
11
|
-
this.baseOverrides = {};
|
|
12
19
|
this.url = source;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
this.baseHeaders = opts.headers ?? {};
|
|
21
|
+
this.baseOverrides = opts.overrides ?? {};
|
|
22
|
+
this.fetchImplementation =
|
|
23
|
+
opts.fetch ??
|
|
24
|
+
((input, init) => globalThis.fetch(input, init));
|
|
18
25
|
}
|
|
19
26
|
async fetch(input, init) {
|
|
20
27
|
const wrapError = (e) => new Error(`${getMessage(e)} fetching ${input}`, { cause: e });
|
|
@@ -49,21 +56,15 @@ class RemoteFile {
|
|
|
49
56
|
if (length === 0) {
|
|
50
57
|
return new Uint8Array(0);
|
|
51
58
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
headers.range = `bytes=${position}-${position + length - 1}`;
|
|
55
|
-
}
|
|
56
|
-
else if (length === Infinity && position !== 0) {
|
|
57
|
-
headers.range = `bytes=${position}-`;
|
|
59
|
+
if (Number.isNaN(length) || Number.isNaN(position)) {
|
|
60
|
+
throw new TypeError(`read() called with NaN length or position (length=${length}, position=${position}). The index file may be corrupt.`);
|
|
58
61
|
}
|
|
62
|
+
const { headers = {}, signal, overrides = {} } = opts;
|
|
63
|
+
headers.range = `bytes=${position}-${position + length - 1}`;
|
|
59
64
|
const res = await this.fetch(this.url, {
|
|
60
65
|
...this.baseOverrides,
|
|
61
66
|
...overrides,
|
|
62
|
-
headers: {
|
|
63
|
-
...this.baseOverrides.headers,
|
|
64
|
-
...overrides.headers,
|
|
65
|
-
...headers,
|
|
66
|
-
},
|
|
67
|
+
headers: { ...this.baseHeaders, ...headers },
|
|
67
68
|
method: 'GET',
|
|
68
69
|
redirect: 'follow',
|
|
69
70
|
mode: 'cors',
|
|
@@ -75,7 +76,7 @@ class RemoteFile {
|
|
|
75
76
|
if ((res.status === 200 && position === 0) || res.status === 206) {
|
|
76
77
|
// try to parse out the size of the remote file
|
|
77
78
|
const contentRange = res.headers.get('content-range');
|
|
78
|
-
const sizeMatch = /\/(\d+)$/.exec(contentRange
|
|
79
|
+
const sizeMatch = /\/(\d+)$/.exec(contentRange ?? '');
|
|
79
80
|
if (sizeMatch?.[1]) {
|
|
80
81
|
this._stat = {
|
|
81
82
|
size: parseInt(sizeMatch[1], 10),
|
|
@@ -94,26 +95,13 @@ class RemoteFile {
|
|
|
94
95
|
: `HTTP ${res.status} fetching ${this.url}`);
|
|
95
96
|
}
|
|
96
97
|
async readFile(options = {}) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (typeof options === 'string') {
|
|
100
|
-
encoding = options;
|
|
101
|
-
opts = {};
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
encoding = options.encoding;
|
|
105
|
-
const { encoding: _, ...rest } = options;
|
|
106
|
-
opts = rest;
|
|
107
|
-
}
|
|
98
|
+
const encoding = typeof options === 'string' ? options : options.encoding;
|
|
99
|
+
const opts = typeof options === 'string' ? {} : options;
|
|
108
100
|
const { headers = {}, signal, overrides = {} } = opts;
|
|
109
101
|
const res = await this.fetch(this.url, {
|
|
110
102
|
...this.baseOverrides,
|
|
111
103
|
...overrides,
|
|
112
|
-
headers: {
|
|
113
|
-
...this.baseOverrides.headers,
|
|
114
|
-
...overrides.headers,
|
|
115
|
-
...headers,
|
|
116
|
-
},
|
|
104
|
+
headers: { ...this.baseHeaders, ...headers },
|
|
117
105
|
method: 'GET',
|
|
118
106
|
redirect: 'follow',
|
|
119
107
|
mode: 'cors',
|
|
@@ -136,15 +124,13 @@ class RemoteFile {
|
|
|
136
124
|
async stat() {
|
|
137
125
|
if (!this._stat) {
|
|
138
126
|
await this.read(10, 0);
|
|
139
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
140
|
-
if (!this._stat) {
|
|
141
|
-
throw new Error(`unable to determine size of file at ${this.url}`);
|
|
142
|
-
}
|
|
143
127
|
}
|
|
144
|
-
return
|
|
128
|
+
// Content-Range may not be exposed due to CORS — return size 0 rather
|
|
129
|
+
// than crashing so callers can degrade gracefully.
|
|
130
|
+
return this._stat ?? { size: 0 };
|
|
145
131
|
}
|
|
146
|
-
|
|
147
|
-
return;
|
|
132
|
+
close() {
|
|
133
|
+
return Promise.resolve();
|
|
148
134
|
}
|
|
149
135
|
}
|
|
150
136
|
exports.default = RemoteFile;
|
package/dist/remoteFile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteFile.js","sourceRoot":"","sources":["../src/remoteFile.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"remoteFile.js","sourceRoot":"","sources":["../src/remoteFile.ts"],"names":[],"mappings":"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"}
|
package/esm/blobFile.d.ts
CHANGED
package/esm/blobFile.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* the Dalliance Genome Explorer, which is copyright Thomas Down 2006-2011.
|
|
6
6
|
*/
|
|
7
7
|
export default class BlobFile {
|
|
8
|
+
blob;
|
|
8
9
|
constructor(blob) {
|
|
9
10
|
this.blob = blob;
|
|
10
11
|
}
|
|
@@ -14,9 +15,7 @@ export default class BlobFile {
|
|
|
14
15
|
if (!length) {
|
|
15
16
|
return new Uint8Array(0);
|
|
16
17
|
}
|
|
17
|
-
const
|
|
18
|
-
const end = start + length;
|
|
19
|
-
const slice = this.blob.slice(start, end);
|
|
18
|
+
const slice = this.blob.slice(position, position + length);
|
|
20
19
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
21
20
|
return slice.bytes
|
|
22
21
|
? slice.bytes()
|
|
@@ -37,11 +36,11 @@ export default class BlobFile {
|
|
|
37
36
|
: new Uint8Array(await this.blob.arrayBuffer());
|
|
38
37
|
}
|
|
39
38
|
}
|
|
40
|
-
|
|
41
|
-
return { size: this.blob.size };
|
|
39
|
+
stat() {
|
|
40
|
+
return Promise.resolve({ size: this.blob.size });
|
|
42
41
|
}
|
|
43
|
-
|
|
44
|
-
return;
|
|
42
|
+
close() {
|
|
43
|
+
return Promise.resolve();
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
46
|
//# sourceMappingURL=blobFile.js.map
|
package/esm/blobFile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blobFile.js","sourceRoot":"","sources":["../src/blobFile.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"blobFile.js","sourceRoot":"","sources":["../src/blobFile.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,OAAO,QAAQ;IACnB,IAAI,CAAM;IAElB,YAAmB,IAAU;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEM,KAAK,CAAC,IAAI,CACf,MAAc,EACd,QAAQ,GAAG,CAAC;QAEZ,4EAA4E;QAC5E,sDAAsD;QACtD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAA;QAC1D,uEAAuE;QACvE,OAAO,KAAK,CAAC,KAAK;YAChB,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE;YACf,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;IAC/C,CAAC;IAYM,KAAK,CAAC,QAAQ,CACnB,OAA4C;QAE5C,MAAM,QAAQ,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAA;QAC1E,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;QACzB,CAAC;aAAM,IAAI,QAAQ,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAA;QACtD,CAAC;aAAM,CAAC;YACN,uEAAuE;YACvE,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK;gBACpB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;gBACnB,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;QACnD,CAAC;IACH,CAAC;IAEM,IAAI;QACT,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;IAClD,CAAC;IAEM,KAAK;QACV,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAC1B,CAAC;CACF"}
|
package/esm/filehandle.d.ts
CHANGED
|
@@ -1,22 +1,14 @@
|
|
|
1
|
+
export type BufferEncoding = 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'utf-16le' | 'ucs2' | 'ucs-2' | 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex';
|
|
1
2
|
export type Fetcher = (input: RequestInfo, init?: RequestInit) => Promise<Response>;
|
|
2
3
|
export interface FilehandleOptions {
|
|
3
|
-
/**
|
|
4
|
-
* optional AbortSignal object for aborting the request
|
|
5
|
-
*/
|
|
6
4
|
signal?: AbortSignal;
|
|
7
|
-
headers?:
|
|
8
|
-
overrides?:
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
overrides?: Omit<RequestInit, 'headers'>;
|
|
9
7
|
encoding?: BufferEncoding;
|
|
10
|
-
/**
|
|
11
|
-
* fetch function to use for HTTP requests. defaults to environment's
|
|
12
|
-
* global fetch. if there is no global fetch, and a fetch function is not provided,
|
|
13
|
-
* throws an error.
|
|
14
|
-
*/
|
|
15
8
|
fetch?: Fetcher;
|
|
16
9
|
}
|
|
17
10
|
export interface Stats {
|
|
18
11
|
size: number;
|
|
19
|
-
[key: string]: any;
|
|
20
12
|
}
|
|
21
13
|
export interface GenericFilehandle {
|
|
22
14
|
read(length: number, position: number, opts?: FilehandleOptions): Promise<Uint8Array<ArrayBuffer>>;
|
package/esm/index.d.ts
CHANGED
package/esm/localFile.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { FilehandleOptions, GenericFilehandle } from './filehandle.ts';
|
|
1
|
+
import type { BufferEncoding, FilehandleOptions, GenericFilehandle, Stats } from './filehandle.ts';
|
|
2
2
|
export default class LocalFile implements GenericFilehandle {
|
|
3
3
|
private filename;
|
|
4
|
-
constructor(source: string
|
|
4
|
+
constructor(source: string);
|
|
5
5
|
read(length: number, position?: number): Promise<Uint8Array<ArrayBuffer>>;
|
|
6
6
|
readFile(): Promise<Uint8Array<ArrayBuffer>>;
|
|
7
7
|
readFile(options: BufferEncoding): Promise<string>;
|
|
@@ -14,6 +14,6 @@ export default class LocalFile implements GenericFilehandle {
|
|
|
14
14
|
readFile<T extends BufferEncoding>(options: Omit<FilehandleOptions, 'encoding'> & {
|
|
15
15
|
encoding: T;
|
|
16
16
|
}): T extends BufferEncoding ? Promise<string> : Promise<Uint8Array<ArrayBuffer>>;
|
|
17
|
-
stat(): Promise<
|
|
17
|
+
stat(): Promise<Stats>;
|
|
18
18
|
close(): Promise<void>;
|
|
19
19
|
}
|
package/esm/localFile.js
CHANGED
package/esm/localFile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localFile.js","sourceRoot":"","sources":["../src/localFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"localFile.js","sourceRoot":"","sources":["../src/localFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AASlD,MAAM,CAAC,OAAO,OAAO,SAAS;IACpB,QAAQ,CAAQ;IAExB,YAAmB,MAAc;QAC/B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAA;IACxB,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,QAAQ,GAAG,CAAC;QAC5C,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;YACjB,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAA;QAClC,IAAI,EAAE,CAAA;QACN,IAAI,CAAC;YACH,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;YACnC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;YACnD,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAA;QAC9C,CAAC;gBAAS,CAAC;YACT,IAAI,EAAE,EAAE,CAAC;gBACP,IAAI,CAAC;oBACH,MAAM,EAAE,CAAC,KAAK,EAAE,CAAA;gBAClB,CAAC;gBAAC,MAAM,CAAC;oBACP,sEAAsE;oBACtE,oDAAoD;gBACtD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAiBM,KAAK,CAAC,QAAQ,CACnB,OAA4C;QAE5C,OAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IACzC,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC5B,CAAC;IAEM,KAAK,CAAC,KAAK;QAChB,gBAAgB;IAClB,CAAC;CACF"}
|
package/esm/remoteFile.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { FilehandleOptions, GenericFilehandle, Stats } from './filehandle.ts';
|
|
1
|
+
import type { BufferEncoding, FilehandleOptions, GenericFilehandle, Stats } from './filehandle.ts';
|
|
2
2
|
export default class RemoteFile implements GenericFilehandle {
|
|
3
3
|
protected url: string;
|
|
4
4
|
private _stat?;
|
|
5
5
|
private fetchImplementation;
|
|
6
|
+
private baseHeaders;
|
|
6
7
|
private baseOverrides;
|
|
7
8
|
constructor(source: string, opts?: FilehandleOptions);
|
|
8
9
|
fetch(input: RequestInfo, init: RequestInit | undefined): Promise<Response>;
|
package/esm/remoteFile.js
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
function getMessage(e) {
|
|
2
|
-
const r = typeof e === 'object' &&
|
|
2
|
+
const r = typeof e === 'object' &&
|
|
3
|
+
e !== null &&
|
|
4
|
+
'message' in e &&
|
|
5
|
+
typeof e.message === 'string'
|
|
3
6
|
? e.message
|
|
4
7
|
: `${e}`;
|
|
5
8
|
return r.replace(/\.$/, '');
|
|
6
9
|
}
|
|
7
10
|
export default class RemoteFile {
|
|
11
|
+
url;
|
|
12
|
+
_stat;
|
|
13
|
+
fetchImplementation;
|
|
14
|
+
baseHeaders;
|
|
15
|
+
baseOverrides;
|
|
8
16
|
constructor(source, opts = {}) {
|
|
9
|
-
this.baseOverrides = {};
|
|
10
17
|
this.url = source;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
this.baseHeaders = opts.headers ?? {};
|
|
19
|
+
this.baseOverrides = opts.overrides ?? {};
|
|
20
|
+
this.fetchImplementation =
|
|
21
|
+
opts.fetch ??
|
|
22
|
+
((input, init) => globalThis.fetch(input, init));
|
|
16
23
|
}
|
|
17
24
|
async fetch(input, init) {
|
|
18
25
|
const wrapError = (e) => new Error(`${getMessage(e)} fetching ${input}`, { cause: e });
|
|
@@ -47,21 +54,15 @@ export default class RemoteFile {
|
|
|
47
54
|
if (length === 0) {
|
|
48
55
|
return new Uint8Array(0);
|
|
49
56
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
headers.range = `bytes=${position}-${position + length - 1}`;
|
|
53
|
-
}
|
|
54
|
-
else if (length === Infinity && position !== 0) {
|
|
55
|
-
headers.range = `bytes=${position}-`;
|
|
57
|
+
if (Number.isNaN(length) || Number.isNaN(position)) {
|
|
58
|
+
throw new TypeError(`read() called with NaN length or position (length=${length}, position=${position}). The index file may be corrupt.`);
|
|
56
59
|
}
|
|
60
|
+
const { headers = {}, signal, overrides = {} } = opts;
|
|
61
|
+
headers.range = `bytes=${position}-${position + length - 1}`;
|
|
57
62
|
const res = await this.fetch(this.url, {
|
|
58
63
|
...this.baseOverrides,
|
|
59
64
|
...overrides,
|
|
60
|
-
headers: {
|
|
61
|
-
...this.baseOverrides.headers,
|
|
62
|
-
...overrides.headers,
|
|
63
|
-
...headers,
|
|
64
|
-
},
|
|
65
|
+
headers: { ...this.baseHeaders, ...headers },
|
|
65
66
|
method: 'GET',
|
|
66
67
|
redirect: 'follow',
|
|
67
68
|
mode: 'cors',
|
|
@@ -73,7 +74,7 @@ export default class RemoteFile {
|
|
|
73
74
|
if ((res.status === 200 && position === 0) || res.status === 206) {
|
|
74
75
|
// try to parse out the size of the remote file
|
|
75
76
|
const contentRange = res.headers.get('content-range');
|
|
76
|
-
const sizeMatch = /\/(\d+)$/.exec(contentRange
|
|
77
|
+
const sizeMatch = /\/(\d+)$/.exec(contentRange ?? '');
|
|
77
78
|
if (sizeMatch?.[1]) {
|
|
78
79
|
this._stat = {
|
|
79
80
|
size: parseInt(sizeMatch[1], 10),
|
|
@@ -92,26 +93,13 @@ export default class RemoteFile {
|
|
|
92
93
|
: `HTTP ${res.status} fetching ${this.url}`);
|
|
93
94
|
}
|
|
94
95
|
async readFile(options = {}) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (typeof options === 'string') {
|
|
98
|
-
encoding = options;
|
|
99
|
-
opts = {};
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
encoding = options.encoding;
|
|
103
|
-
const { encoding: _, ...rest } = options;
|
|
104
|
-
opts = rest;
|
|
105
|
-
}
|
|
96
|
+
const encoding = typeof options === 'string' ? options : options.encoding;
|
|
97
|
+
const opts = typeof options === 'string' ? {} : options;
|
|
106
98
|
const { headers = {}, signal, overrides = {} } = opts;
|
|
107
99
|
const res = await this.fetch(this.url, {
|
|
108
100
|
...this.baseOverrides,
|
|
109
101
|
...overrides,
|
|
110
|
-
headers: {
|
|
111
|
-
...this.baseOverrides.headers,
|
|
112
|
-
...overrides.headers,
|
|
113
|
-
...headers,
|
|
114
|
-
},
|
|
102
|
+
headers: { ...this.baseHeaders, ...headers },
|
|
115
103
|
method: 'GET',
|
|
116
104
|
redirect: 'follow',
|
|
117
105
|
mode: 'cors',
|
|
@@ -134,15 +122,13 @@ export default class RemoteFile {
|
|
|
134
122
|
async stat() {
|
|
135
123
|
if (!this._stat) {
|
|
136
124
|
await this.read(10, 0);
|
|
137
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
138
|
-
if (!this._stat) {
|
|
139
|
-
throw new Error(`unable to determine size of file at ${this.url}`);
|
|
140
|
-
}
|
|
141
125
|
}
|
|
142
|
-
return
|
|
126
|
+
// Content-Range may not be exposed due to CORS — return size 0 rather
|
|
127
|
+
// than crashing so callers can degrade gracefully.
|
|
128
|
+
return this._stat ?? { size: 0 };
|
|
143
129
|
}
|
|
144
|
-
|
|
145
|
-
return;
|
|
130
|
+
close() {
|
|
131
|
+
return Promise.resolve();
|
|
146
132
|
}
|
|
147
133
|
}
|
|
148
134
|
//# sourceMappingURL=remoteFile.js.map
|
package/esm/remoteFile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteFile.js","sourceRoot":"","sources":["../src/remoteFile.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"remoteFile.js","sourceRoot":"","sources":["../src/remoteFile.ts"],"names":[],"mappings":"AAQA,SAAS,UAAU,CAAC,CAAU;IAC5B,MAAM,CAAC,GACL,OAAO,CAAC,KAAK,QAAQ;QACrB,CAAC,KAAK,IAAI;QACV,SAAS,IAAI,CAAC;QACd,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ;QAC3B,CAAC,CAAC,CAAC,CAAC,OAAO;QACX,CAAC,CAAC,GAAG,CAAC,EAAE,CAAA;IACZ,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;AAC7B,CAAC;AAED,MAAM,CAAC,OAAO,OAAO,UAAU;IACnB,GAAG,CAAQ;IACb,KAAK,CAAQ;IACb,mBAAmB,CAAS;IAC5B,WAAW,CAAwB;IACnC,aAAa,CAA8B;IAEnD,YAAmB,MAAc,EAAE,OAA0B,EAAE;QAC7D,IAAI,CAAC,GAAG,GAAG,MAAM,CAAA;QACjB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA;QACrC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,SAAS,IAAI,EAAE,CAAA;QACzC,IAAI,CAAC,mBAAmB;YACtB,IAAI,CAAC,KAAK;gBACV,CAAC,CAAC,KAAkB,EAAE,IAAkB,EAAE,EAAE,CAC1C,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;IACpC,CAAC;IAEM,KAAK,CAAC,KAAK,CAChB,KAAkB,EAClB,IAA6B;QAE7B,MAAM,SAAS,GAAG,CAAC,CAAU,EAAE,EAAE,CAC/B,IAAI,KAAK,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,aAAa,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QAE/D,IAAI,QAAQ,CAAA;QACZ,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACxD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;gBACvC,yDAAyD;gBACzD,oEAAoE;gBACpE,iDAAiD;gBACjD,uDAAuD;gBACvD,OAAO,CAAC,IAAI,CACV,kCAAkC,KAAK,2DAA2D,CACnG,CAAA;gBACD,IAAI,CAAC;oBACH,QAAQ,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE;wBAC/C,GAAG,IAAI;wBACP,KAAK,EAAE,QAAQ;qBAChB,CAAC,CAAA;gBACJ,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,MAAM,SAAS,CAAC,CAAC,CAAC,CAAA;gBACpB,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,SAAS,CAAC,CAAC,CAAC,CAAA;YACpB,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAA;IACjB,CAAC;IAEM,KAAK,CAAC,IAAI,CACf,MAAc,EACd,QAAgB,EAChB,OAA0B,EAAE;QAE5B,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;YACjB,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC;QACD,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,SAAS,CACjB,qDAAqD,MAAM,cAAc,QAAQ,mCAAmC,CACrH,CAAA;QACH,CAAC;QACD,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,MAAM,EAAE,SAAS,GAAG,EAAE,EAAE,GAAG,IAAI,CAAA;QACrD,OAAO,CAAC,KAAK,GAAG,SAAS,QAAQ,IAAI,QAAQ,GAAG,MAAM,GAAG,CAAC,EAAE,CAAA;QAC5D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;YACrC,GAAG,IAAI,CAAC,aAAa;YACrB,GAAG,SAAS;YACZ,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,OAAO,EAAE;YAC5C,MAAM,EAAE,KAAK;YACb,QAAQ,EAAE,QAAQ;YAClB,IAAI,EAAE,MAAM;YACZ,MAAM;SACP,CAAC,CAAA;QAEF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,MAAM,aAAa,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;QAC5D,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACjE,+CAA+C;YAC/C,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;YACrD,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAA;YACrD,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnB,IAAI,CAAC,KAAK,GAAG;oBACX,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;iBACjC,CAAA;YACH,CAAC;YAED,uEAAuE;YACvE,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK;gBACvB,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE;gBACnB,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAA;YAC3C,OAAO,OAAO,CAAC,UAAU,IAAI,MAAM;gBACjC,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;QACjC,CAAC;QAED,MAAM,IAAI,KAAK,CACb,GAAG,CAAC,MAAM,KAAK,GAAG;YAChB,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,0CAA0C;YACvD,CAAC,CAAC,QAAQ,GAAG,CAAC,MAAM,aAAa,IAAI,CAAC,GAAG,EAAE,CAC9C,CAAA;IACH,CAAC;IAiBM,KAAK,CAAC,QAAQ,CACnB,UAA8C,EAAE;QAEhD,MAAM,QAAQ,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAA;QACzE,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;QACvD,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE,MAAM,EAAE,SAAS,GAAG,EAAE,EAAE,GAAG,IAAI,CAAA;QACrD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;YACrC,GAAG,IAAI,CAAC,aAAa;YACrB,GAAG,SAAS;YACZ,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,OAAO,EAAE;YAC5C,MAAM,EAAE,KAAK;YACb,QAAQ,EAAE,QAAQ;YAClB,IAAI,EAAE,MAAM;YACZ,MAAM;SACP,CAAC,CAAA;QACF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,MAAM,aAAa,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;QAC5D,CAAC;QACD,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YACxB,OAAO,GAAG,CAAC,IAAI,EAAE,CAAA;QACnB,CAAC;aAAM,IAAI,QAAQ,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAA;QACtD,CAAC;aAAM,CAAC;YACN,uEAAuE;YACvE,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAA;QAC1E,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;QACxB,CAAC;QACD,sEAAsE;QACtE,mDAAmD;QACnD,OAAO,IAAI,CAAC,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAA;IAClC,CAAC;IAEM,KAAK;QACV,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAC1B,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,29 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "generic-filehandle2",
|
|
3
3
|
"description": "uniform interface for accessing binary data from local files, remote HTTP resources, and browser Blob data",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.1.5",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
6
|
+
"main": "dist/index.js",
|
|
7
7
|
"exports": {
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"require": "./dist/index.js"
|
|
15
|
-
}
|
|
8
|
+
"import": "./esm/index.js",
|
|
9
|
+
"require": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/GMOD/generic-filehandle2.git"
|
|
16
14
|
},
|
|
17
|
-
"repository": "GMOD/generic-filehandle2",
|
|
18
15
|
"license": "MIT",
|
|
19
16
|
"author": {
|
|
20
17
|
"name": "Colin Diesh",
|
|
21
18
|
"email": "colin.diesh@gmail.com",
|
|
22
19
|
"url": "https://github.com/cmdcolin"
|
|
23
20
|
},
|
|
24
|
-
"engines": {
|
|
25
|
-
"node": ">=14"
|
|
26
|
-
},
|
|
27
21
|
"files": [
|
|
28
22
|
"dist",
|
|
29
23
|
"esm",
|
|
@@ -31,17 +25,17 @@
|
|
|
31
25
|
],
|
|
32
26
|
"scripts": {
|
|
33
27
|
"test": "vitest",
|
|
34
|
-
"coverage": "yarn test --coverage",
|
|
35
|
-
"lint": "eslint --report-unused-disable-directives --max-warnings 0 src test",
|
|
36
28
|
"clean": "rimraf dist esm",
|
|
37
29
|
"format": "prettier --write .",
|
|
38
|
-
"
|
|
30
|
+
"lint": "eslint --report-unused-disable-directives --max-warnings 0",
|
|
31
|
+
"prebuild": "pnpm clean",
|
|
39
32
|
"build:esm": "tsc --outDir esm",
|
|
40
|
-
"build:es5": "tsc --module commonjs --outDir dist",
|
|
41
|
-
"build": "yarn build:esm && yarn build:es5",
|
|
33
|
+
"build:es5": "tsc --module commonjs --moduleResolution bundler --outDir dist",
|
|
42
34
|
"postbuild:es5": "echo '{\"type\": \"commonjs\"}' > dist/package.json",
|
|
43
|
-
"preversion": "
|
|
44
|
-
"postversion": "git push --follow-tags"
|
|
35
|
+
"preversion": "pnpm lint && pnpm test --run && pnpm build",
|
|
36
|
+
"postversion": "git push --follow-tags",
|
|
37
|
+
"build": "pnpm build:esm && pnpm build:es5",
|
|
38
|
+
"coverage": "pnpm test --coverage"
|
|
45
39
|
},
|
|
46
40
|
"keywords": [
|
|
47
41
|
"bionode",
|
|
@@ -50,19 +44,20 @@
|
|
|
50
44
|
"genomics"
|
|
51
45
|
],
|
|
52
46
|
"devDependencies": {
|
|
53
|
-
"@
|
|
47
|
+
"@eslint/js": "^10.0.1",
|
|
48
|
+
"@types/node": "^25.6.0",
|
|
54
49
|
"@types/range-parser": "^1.2.7",
|
|
55
|
-
"@vitest/coverage-v8": "^4.
|
|
56
|
-
"eslint": "^
|
|
57
|
-
"eslint-plugin-import": "^
|
|
58
|
-
"eslint-plugin-unicorn": "^
|
|
59
|
-
"prettier": "^3.
|
|
50
|
+
"@vitest/coverage-v8": "^4.1.5",
|
|
51
|
+
"eslint": "^10.2.1",
|
|
52
|
+
"eslint-plugin-import-x": "^4.16.2",
|
|
53
|
+
"eslint-plugin-unicorn": "^64.0.0",
|
|
54
|
+
"prettier": "^3.8.3",
|
|
60
55
|
"range-parser": "^1.2.1",
|
|
61
|
-
"rimraf": "^6.
|
|
56
|
+
"rimraf": "^6.1.3",
|
|
62
57
|
"standard-changelog": "^7.0.1",
|
|
63
|
-
"typescript": "^
|
|
64
|
-
"typescript-eslint": "^8.
|
|
65
|
-
"vitest": "^4.
|
|
58
|
+
"typescript": "^6.0.3",
|
|
59
|
+
"typescript-eslint": "^8.59.0",
|
|
60
|
+
"vitest": "^4.1.5"
|
|
66
61
|
},
|
|
67
62
|
"publishConfig": {
|
|
68
63
|
"access": "public"
|
package/src/blobFile.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
BufferEncoding,
|
|
2
3
|
FilehandleOptions,
|
|
3
4
|
GenericFilehandle,
|
|
4
5
|
Stats,
|
|
@@ -27,10 +28,7 @@ export default class BlobFile implements GenericFilehandle {
|
|
|
27
28
|
return new Uint8Array(0)
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
const
|
|
31
|
-
const end = start + length
|
|
32
|
-
|
|
33
|
-
const slice = this.blob.slice(start, end)
|
|
31
|
+
const slice = this.blob.slice(position, position + length)
|
|
34
32
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
35
33
|
return slice.bytes
|
|
36
34
|
? slice.bytes()
|
|
@@ -63,11 +61,11 @@ export default class BlobFile implements GenericFilehandle {
|
|
|
63
61
|
}
|
|
64
62
|
}
|
|
65
63
|
|
|
66
|
-
public
|
|
67
|
-
return { size: this.blob.size }
|
|
64
|
+
public stat(): Promise<Stats> {
|
|
65
|
+
return Promise.resolve({ size: this.blob.size })
|
|
68
66
|
}
|
|
69
67
|
|
|
70
|
-
public
|
|
71
|
-
return
|
|
68
|
+
public close(): Promise<void> {
|
|
69
|
+
return Promise.resolve()
|
|
72
70
|
}
|
|
73
71
|
}
|
package/src/filehandle.ts
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
|
+
// avoids needing to have @types/node as a dependency of the consuming code
|
|
2
|
+
export type BufferEncoding =
|
|
3
|
+
| 'ascii'
|
|
4
|
+
| 'utf8'
|
|
5
|
+
| 'utf-8'
|
|
6
|
+
| 'utf16le'
|
|
7
|
+
| 'utf-16le'
|
|
8
|
+
| 'ucs2'
|
|
9
|
+
| 'ucs-2'
|
|
10
|
+
| 'base64'
|
|
11
|
+
| 'base64url'
|
|
12
|
+
| 'latin1'
|
|
13
|
+
| 'binary'
|
|
14
|
+
| 'hex'
|
|
15
|
+
|
|
1
16
|
export type Fetcher = (
|
|
2
17
|
input: RequestInfo,
|
|
3
18
|
init?: RequestInit,
|
|
4
19
|
) => Promise<Response>
|
|
5
20
|
|
|
6
21
|
export interface FilehandleOptions {
|
|
7
|
-
/**
|
|
8
|
-
* optional AbortSignal object for aborting the request
|
|
9
|
-
*/
|
|
10
22
|
signal?: AbortSignal
|
|
11
|
-
headers?:
|
|
12
|
-
overrides?:
|
|
23
|
+
headers?: Record<string, string>
|
|
24
|
+
overrides?: Omit<RequestInit, 'headers'>
|
|
13
25
|
encoding?: BufferEncoding
|
|
14
|
-
/**
|
|
15
|
-
* fetch function to use for HTTP requests. defaults to environment's
|
|
16
|
-
* global fetch. if there is no global fetch, and a fetch function is not provided,
|
|
17
|
-
* throws an error.
|
|
18
|
-
*/
|
|
19
26
|
fetch?: Fetcher
|
|
20
27
|
}
|
|
21
28
|
|
|
22
29
|
export interface Stats {
|
|
23
30
|
size: number
|
|
24
|
-
[key: string]: any
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
export interface GenericFilehandle {
|
package/src/index.ts
CHANGED
package/src/localFile.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { open, readFile, stat } from 'fs/promises'
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
BufferEncoding,
|
|
5
|
+
FilehandleOptions,
|
|
6
|
+
GenericFilehandle,
|
|
7
|
+
Stats,
|
|
8
|
+
} from './filehandle.ts'
|
|
4
9
|
|
|
5
10
|
export default class LocalFile implements GenericFilehandle {
|
|
6
11
|
private filename: string
|
|
7
12
|
|
|
8
|
-
public constructor(source: string
|
|
13
|
+
public constructor(source: string) {
|
|
9
14
|
this.filename = source
|
|
10
15
|
}
|
|
11
16
|
|
|
@@ -52,7 +57,7 @@ export default class LocalFile implements GenericFilehandle {
|
|
|
52
57
|
return readFile(this.filename, options)
|
|
53
58
|
}
|
|
54
59
|
|
|
55
|
-
public async stat() {
|
|
60
|
+
public async stat(): Promise<Stats> {
|
|
56
61
|
return stat(this.filename)
|
|
57
62
|
}
|
|
58
63
|
|
package/src/remoteFile.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
BufferEncoding,
|
|
2
3
|
Fetcher,
|
|
3
4
|
FilehandleOptions,
|
|
4
5
|
GenericFilehandle,
|
|
@@ -7,8 +8,11 @@ import type {
|
|
|
7
8
|
|
|
8
9
|
function getMessage(e: unknown) {
|
|
9
10
|
const r =
|
|
10
|
-
typeof e === 'object' &&
|
|
11
|
-
|
|
11
|
+
typeof e === 'object' &&
|
|
12
|
+
e !== null &&
|
|
13
|
+
'message' in e &&
|
|
14
|
+
typeof e.message === 'string'
|
|
15
|
+
? e.message
|
|
12
16
|
: `${e}`
|
|
13
17
|
return r.replace(/\.$/, '')
|
|
14
18
|
}
|
|
@@ -17,15 +21,17 @@ export default class RemoteFile implements GenericFilehandle {
|
|
|
17
21
|
protected url: string
|
|
18
22
|
private _stat?: Stats
|
|
19
23
|
private fetchImplementation: Fetcher
|
|
20
|
-
private
|
|
24
|
+
private baseHeaders: Record<string, string>
|
|
25
|
+
private baseOverrides: Omit<RequestInit, 'headers'>
|
|
21
26
|
|
|
22
27
|
public constructor(source: string, opts: FilehandleOptions = {}) {
|
|
23
28
|
this.url = source
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
this.baseHeaders = opts.headers ?? {}
|
|
30
|
+
this.baseOverrides = opts.overrides ?? {}
|
|
31
|
+
this.fetchImplementation =
|
|
32
|
+
opts.fetch ??
|
|
33
|
+
((input: RequestInfo, init?: RequestInit) =>
|
|
34
|
+
globalThis.fetch(input, init))
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
public async fetch(
|
|
@@ -70,20 +76,17 @@ export default class RemoteFile implements GenericFilehandle {
|
|
|
70
76
|
if (length === 0) {
|
|
71
77
|
return new Uint8Array(0)
|
|
72
78
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
headers.range = `bytes=${position}-`
|
|
79
|
+
if (Number.isNaN(length) || Number.isNaN(position)) {
|
|
80
|
+
throw new TypeError(
|
|
81
|
+
`read() called with NaN length or position (length=${length}, position=${position}). The index file may be corrupt.`,
|
|
82
|
+
)
|
|
78
83
|
}
|
|
84
|
+
const { headers = {}, signal, overrides = {} } = opts
|
|
85
|
+
headers.range = `bytes=${position}-${position + length - 1}`
|
|
79
86
|
const res = await this.fetch(this.url, {
|
|
80
87
|
...this.baseOverrides,
|
|
81
88
|
...overrides,
|
|
82
|
-
headers: {
|
|
83
|
-
...this.baseOverrides.headers,
|
|
84
|
-
...overrides.headers,
|
|
85
|
-
...headers,
|
|
86
|
-
},
|
|
89
|
+
headers: { ...this.baseHeaders, ...headers },
|
|
87
90
|
method: 'GET',
|
|
88
91
|
redirect: 'follow',
|
|
89
92
|
mode: 'cors',
|
|
@@ -97,7 +100,7 @@ export default class RemoteFile implements GenericFilehandle {
|
|
|
97
100
|
if ((res.status === 200 && position === 0) || res.status === 206) {
|
|
98
101
|
// try to parse out the size of the remote file
|
|
99
102
|
const contentRange = res.headers.get('content-range')
|
|
100
|
-
const sizeMatch = /\/(\d+)$/.exec(contentRange
|
|
103
|
+
const sizeMatch = /\/(\d+)$/.exec(contentRange ?? '')
|
|
101
104
|
if (sizeMatch?.[1]) {
|
|
102
105
|
this._stat = {
|
|
103
106
|
size: parseInt(sizeMatch[1], 10),
|
|
@@ -138,25 +141,13 @@ export default class RemoteFile implements GenericFilehandle {
|
|
|
138
141
|
public async readFile(
|
|
139
142
|
options: FilehandleOptions | BufferEncoding = {},
|
|
140
143
|
): Promise<Uint8Array<ArrayBuffer> | string> {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (typeof options === 'string') {
|
|
144
|
-
encoding = options
|
|
145
|
-
opts = {}
|
|
146
|
-
} else {
|
|
147
|
-
encoding = options.encoding
|
|
148
|
-
const { encoding: _, ...rest } = options
|
|
149
|
-
opts = rest
|
|
150
|
-
}
|
|
144
|
+
const encoding = typeof options === 'string' ? options : options.encoding
|
|
145
|
+
const opts = typeof options === 'string' ? {} : options
|
|
151
146
|
const { headers = {}, signal, overrides = {} } = opts
|
|
152
147
|
const res = await this.fetch(this.url, {
|
|
153
148
|
...this.baseOverrides,
|
|
154
149
|
...overrides,
|
|
155
|
-
headers: {
|
|
156
|
-
...this.baseOverrides.headers,
|
|
157
|
-
...overrides.headers,
|
|
158
|
-
...headers,
|
|
159
|
-
},
|
|
150
|
+
headers: { ...this.baseHeaders, ...headers },
|
|
160
151
|
method: 'GET',
|
|
161
152
|
redirect: 'follow',
|
|
162
153
|
mode: 'cors',
|
|
@@ -178,15 +169,13 @@ export default class RemoteFile implements GenericFilehandle {
|
|
|
178
169
|
public async stat(): Promise<Stats> {
|
|
179
170
|
if (!this._stat) {
|
|
180
171
|
await this.read(10, 0)
|
|
181
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
182
|
-
if (!this._stat) {
|
|
183
|
-
throw new Error(`unable to determine size of file at ${this.url}`)
|
|
184
|
-
}
|
|
185
172
|
}
|
|
186
|
-
return
|
|
173
|
+
// Content-Range may not be exposed due to CORS — return size 0 rather
|
|
174
|
+
// than crashing so callers can degrade gracefully.
|
|
175
|
+
return this._stat ?? { size: 0 }
|
|
187
176
|
}
|
|
188
177
|
|
|
189
|
-
public
|
|
190
|
-
return
|
|
178
|
+
public close(): Promise<void> {
|
|
179
|
+
return Promise.resolve()
|
|
191
180
|
}
|
|
192
181
|
}
|