@loaders.gl/polyfills 4.0.0-beta.1 → 4.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/buffer/btoa.node.d.ts.map +1 -0
- package/dist/buffer/btoa.node.js.map +1 -0
- package/dist/buffer/to-array-buffer.node.d.ts.map +1 -0
- package/dist/buffer/to-array-buffer.node.js.map +1 -0
- package/dist/crypto/node-hash.d.ts +28 -0
- package/dist/crypto/node-hash.d.ts.map +1 -0
- package/dist/crypto/node-hash.js +56 -0
- package/dist/crypto/node-hash.js.map +1 -0
- package/dist/dist.dev.js +43 -0
- package/dist/{node/fetch/utils/decode-data-uri.node.d.ts → fetch/decode-data-uri.d.ts} +1 -1
- package/dist/fetch/decode-data-uri.d.ts.map +1 -0
- package/dist/{esm/node/fetch/utils/decode-data-uri.node.js → fetch/decode-data-uri.js} +3 -3
- package/dist/fetch/decode-data-uri.js.map +1 -0
- package/dist/{node/fetch/fetch.node.d.ts → fetch/fetch-polyfill.d.ts} +2 -2
- package/dist/fetch/fetch-polyfill.d.ts.map +1 -0
- package/dist/{esm/node/fetch/fetch.node.js → fetch/fetch-polyfill.js} +4 -4
- package/dist/fetch/fetch-polyfill.js.map +1 -0
- package/dist/{node/fetch/headers.node.d.ts → fetch/headers-polyfill.d.ts} +1 -1
- package/dist/{node/fetch/headers.node.d.ts.map → fetch/headers-polyfill.d.ts.map} +1 -1
- package/dist/{esm/node/fetch/headers.node.js → fetch/headers-polyfill.js} +3 -4
- package/dist/fetch/headers-polyfill.js.map +1 -0
- package/dist/{node/fetch/response.node.d.ts → fetch/response-polyfill.d.ts} +2 -2
- package/dist/{node/fetch/response.node.d.ts.map → fetch/response-polyfill.d.ts.map} +1 -1
- package/dist/{esm/node/fetch/response.node.js → fetch/response-polyfill.js} +14 -15
- package/dist/fetch/response-polyfill.js.map +1 -0
- package/dist/file/blob-stream-controller.d.ts.map +1 -0
- package/dist/{esm/node/file → file}/blob-stream-controller.js +3 -4
- package/dist/file/blob-stream-controller.js.map +1 -0
- package/dist/file/blob-stream.d.ts.map +1 -0
- package/dist/{esm/node/file → file}/blob-stream.js +3 -4
- package/dist/file/blob-stream.js.map +1 -0
- package/dist/file/blob.d.ts.map +1 -0
- package/dist/{esm/node/file → file}/blob.js +4 -5
- package/dist/file/blob.js.map +1 -0
- package/dist/file/file-reader.d.ts.map +1 -0
- package/dist/file/file-reader.js +59 -0
- package/dist/file/file-reader.js.map +1 -0
- package/dist/{node/file → file}/file.d.ts +1 -2
- package/dist/file/file.d.ts.map +1 -0
- package/dist/{esm/node/file → file}/file.js +4 -6
- package/dist/file/file.js.map +1 -0
- package/dist/file/install-blob-polyfills.d.ts +9 -0
- package/dist/file/install-blob-polyfills.d.ts.map +1 -0
- package/dist/file/install-blob-polyfills.js +9 -0
- package/dist/file/install-blob-polyfills.js.map +1 -0
- package/dist/file/install-file-polyfills.d.ts +3 -0
- package/dist/file/install-file-polyfills.d.ts.map +1 -0
- package/dist/file/install-file-polyfills.js +13 -0
- package/dist/file/install-file-polyfills.js.map +1 -0
- package/dist/file/readable-stream.d.ts.map +1 -0
- package/dist/{esm/node/file → file}/readable-stream.js +1 -1
- package/dist/file/readable-stream.js.map +1 -0
- package/dist/filesystems/fetch-node.d.ts +8 -0
- package/dist/filesystems/fetch-node.d.ts.map +1 -0
- package/dist/filesystems/fetch-node.js +77 -0
- package/dist/filesystems/fetch-node.js.map +1 -0
- package/dist/filesystems/node-file.d.ts +13 -0
- package/dist/filesystems/node-file.d.ts.map +1 -0
- package/dist/filesystems/node-file.js +72 -0
- package/dist/filesystems/node-file.js.map +1 -0
- package/dist/filesystems/node-filesystem.d.ts +19 -0
- package/dist/filesystems/node-filesystem.d.ts.map +1 -0
- package/dist/filesystems/node-filesystem.js +40 -0
- package/dist/filesystems/node-filesystem.js.map +1 -0
- package/dist/{node/fetch/utils → filesystems}/stream-utils.node.d.ts +8 -1
- package/dist/filesystems/stream-utils.node.d.ts.map +1 -0
- package/dist/{esm/node/fetch/utils → filesystems}/stream-utils.node.js +24 -2
- package/dist/filesystems/stream-utils.node.js.map +1 -0
- package/dist/images/encode-image.node.d.ts.map +1 -0
- package/dist/{esm/node/images → images}/encode-image.node.js +1 -1
- package/dist/images/encode-image.node.js.map +1 -0
- package/dist/images/parse-image.node.d.ts.map +1 -0
- package/dist/images/parse-image.node.js.map +1 -0
- package/dist/index.browser.d.ts +4 -0
- package/dist/index.browser.d.ts.map +1 -0
- package/dist/index.browser.js +6 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.cjs +33 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/libs/encoding-indexes-asian.js +2 -0
- package/dist/libs/encoding-indexes-asian.js.map +1 -0
- package/dist/streams/make-node-stream.d.ts +11 -0
- package/dist/streams/make-node-stream.d.ts.map +1 -0
- package/dist/streams/make-node-stream.js +56 -0
- package/dist/streams/make-node-stream.js.map +1 -0
- package/dist/text-encoder/encoding-indexes.d.ts.map +1 -0
- package/dist/{esm/lib → text-encoder}/encoding-indexes.js.map +1 -1
- package/dist/{lib/encoding.d.ts → text-encoder/text-encoder.d.ts} +1 -1
- package/dist/text-encoder/text-encoder.d.ts.map +1 -0
- package/dist/{esm/lib/encoding.js → text-encoder/text-encoder.js} +7 -7
- package/dist/text-encoder/text-encoder.js.map +1 -0
- package/dist/utils/assert.js +6 -0
- package/dist/utils/assert.js.map +1 -0
- package/dist/utils/is-browser.d.ts +2 -0
- package/dist/utils/is-browser.d.ts.map +1 -0
- package/dist/utils/is-browser.js +2 -0
- package/dist/utils/is-browser.js.map +1 -0
- package/package.json +20 -70
- package/src/crypto/node-hash.ts +71 -0
- package/src/{node/fetch/fetch.node.ts → fetch/fetch-polyfill.ts} +3 -3
- package/src/{node/fetch/response.node.ts → fetch/response-polyfill.ts} +6 -6
- package/src/{node/file → file}/file.ts +1 -2
- package/src/file/install-blob-polyfills.ts +13 -0
- package/src/file/install-file-polyfills.ts +20 -0
- package/src/{node/file → file}/readable-stream.ts +1 -1
- package/src/filesystems/fetch-node.ts +96 -0
- package/src/filesystems/node-file.ts +137 -0
- package/src/filesystems/node-filesystem.ts +52 -0
- package/src/{node/fetch/utils → filesystems}/stream-utils.node.ts +42 -3
- package/src/index.browser.ts +10 -0
- package/src/index.ts +76 -50
- package/src/streams/make-node-stream.ts +74 -0
- package/src/{lib/encoding.ts → text-encoder/text-encoder.ts} +7 -7
- package/src/utils/is-browser.ts +6 -0
- package/dist/bundle.d.ts +0 -2
- package/dist/bundle.d.ts.map +0 -1
- package/dist/dist.min.js +0 -1792
- package/dist/es5/bundle.js +0 -6
- package/dist/es5/bundle.js.map +0 -1
- package/dist/es5/index.js +0 -72
- package/dist/es5/index.js.map +0 -1
- package/dist/es5/lib/encoding-indexes.js +0 -37
- package/dist/es5/lib/encoding-indexes.js.map +0 -1
- package/dist/es5/lib/encoding.js +0 -1214
- package/dist/es5/lib/encoding.js.map +0 -1
- package/dist/es5/libs/encoding-indexes-asian.js +0 -13
- package/dist/es5/node/buffer/btoa.node.js +0 -14
- package/dist/es5/node/buffer/btoa.node.js.map +0 -1
- package/dist/es5/node/buffer/to-array-buffer.node.js +0 -14
- package/dist/es5/node/buffer/to-array-buffer.node.js.map +0 -1
- package/dist/es5/node/fetch/fetch.node.js +0 -193
- package/dist/es5/node/fetch/fetch.node.js.map +0 -1
- package/dist/es5/node/fetch/headers.node.js +0 -151
- package/dist/es5/node/fetch/headers.node.js.map +0 -1
- package/dist/es5/node/fetch/response.node.js +0 -182
- package/dist/es5/node/fetch/response.node.js.map +0 -1
- package/dist/es5/node/fetch/utils/decode-data-uri.node.js +0 -58
- package/dist/es5/node/fetch/utils/decode-data-uri.node.js.map +0 -1
- package/dist/es5/node/fetch/utils/stream-utils.node.js +0 -92
- package/dist/es5/node/fetch/utils/stream-utils.node.js.map +0 -1
- package/dist/es5/node/file/blob-stream-controller.js +0 -90
- package/dist/es5/node/file/blob-stream-controller.js.map +0 -1
- package/dist/es5/node/file/blob-stream.js +0 -64
- package/dist/es5/node/file/blob-stream.js.map +0 -1
- package/dist/es5/node/file/blob.js +0 -212
- package/dist/es5/node/file/blob.js.map +0 -1
- package/dist/es5/node/file/file-reader.js +0 -153
- package/dist/es5/node/file/file-reader.js.map +0 -1
- package/dist/es5/node/file/file.js +0 -44
- package/dist/es5/node/file/file.js.map +0 -1
- package/dist/es5/node/file/install-file-polyfills.js +0 -22
- package/dist/es5/node/file/install-file-polyfills.js.map +0 -1
- package/dist/es5/node/file/readable-stream.js +0 -27
- package/dist/es5/node/file/readable-stream.js.map +0 -1
- package/dist/es5/node/images/encode-image.node.js +0 -30
- package/dist/es5/node/images/encode-image.node.js.map +0 -1
- package/dist/es5/node/images/parse-image.node.js +0 -64
- package/dist/es5/node/images/parse-image.node.js.map +0 -1
- package/dist/es5/promise/all-settled.js +0 -28
- package/dist/es5/promise/all-settled.js.map +0 -1
- package/dist/es5/utils/assert.js +0 -12
- package/dist/es5/utils/assert.js.map +0 -1
- package/dist/es5/utils/globals.js +0 -18
- package/dist/es5/utils/globals.js.map +0 -1
- package/dist/esm/bundle.js +0 -4
- package/dist/esm/bundle.js.map +0 -1
- package/dist/esm/index.js +0 -46
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/lib/encoding.js.map +0 -1
- package/dist/esm/libs/encoding-indexes-asian.js +0 -13
- package/dist/esm/node/buffer/btoa.node.js.map +0 -1
- package/dist/esm/node/buffer/to-array-buffer.node.js.map +0 -1
- package/dist/esm/node/fetch/fetch.node.js.map +0 -1
- package/dist/esm/node/fetch/headers.node.js.map +0 -1
- package/dist/esm/node/fetch/response.node.js.map +0 -1
- package/dist/esm/node/fetch/utils/decode-data-uri.node.js.map +0 -1
- package/dist/esm/node/fetch/utils/stream-utils.node.js.map +0 -1
- package/dist/esm/node/file/blob-stream-controller.js.map +0 -1
- package/dist/esm/node/file/blob-stream.js.map +0 -1
- package/dist/esm/node/file/blob.js.map +0 -1
- package/dist/esm/node/file/file-reader.js +0 -60
- package/dist/esm/node/file/file-reader.js.map +0 -1
- package/dist/esm/node/file/file.js.map +0 -1
- package/dist/esm/node/file/install-file-polyfills.js +0 -16
- package/dist/esm/node/file/install-file-polyfills.js.map +0 -1
- package/dist/esm/node/file/readable-stream.js.map +0 -1
- package/dist/esm/node/images/encode-image.node.js.map +0 -1
- package/dist/esm/node/images/parse-image.node.js.map +0 -1
- package/dist/esm/promise/all-settled.js +0 -19
- package/dist/esm/promise/all-settled.js.map +0 -1
- package/dist/esm/utils/assert.js +0 -6
- package/dist/esm/utils/assert.js.map +0 -1
- package/dist/esm/utils/globals.js +0 -9
- package/dist/esm/utils/globals.js.map +0 -1
- package/dist/lib/encoding-indexes.d.ts.map +0 -1
- package/dist/lib/encoding.d.ts.map +0 -1
- package/dist/node/buffer/btoa.node.d.ts.map +0 -1
- package/dist/node/buffer/to-array-buffer.node.d.ts.map +0 -1
- package/dist/node/fetch/fetch.node.d.ts.map +0 -1
- package/dist/node/fetch/utils/decode-data-uri.node.d.ts.map +0 -1
- package/dist/node/fetch/utils/stream-utils.node.d.ts.map +0 -1
- package/dist/node/file/blob-stream-controller.d.ts.map +0 -1
- package/dist/node/file/blob-stream.d.ts.map +0 -1
- package/dist/node/file/blob.d.ts.map +0 -1
- package/dist/node/file/file-reader.d.ts.map +0 -1
- package/dist/node/file/file.d.ts.map +0 -1
- package/dist/node/file/install-file-polyfills.d.ts +0 -2
- package/dist/node/file/install-file-polyfills.d.ts.map +0 -1
- package/dist/node/file/readable-stream.d.ts.map +0 -1
- package/dist/node/images/encode-image.node.d.ts.map +0 -1
- package/dist/node/images/parse-image.node.d.ts.map +0 -1
- package/dist/promise/all-settled.d.ts +0 -10
- package/dist/promise/all-settled.d.ts.map +0 -1
- package/dist/utils/globals.d.ts +0 -4
- package/dist/utils/globals.d.ts.map +0 -1
- package/src/bundle.ts +0 -4
- package/src/node/file/install-file-polyfills.ts +0 -27
- package/src/promise/all-settled.ts +0 -21
- package/src/utils/globals.ts +0 -37
- /package/dist/{node/buffer → buffer}/btoa.node.d.ts +0 -0
- /package/dist/{esm/node/buffer → buffer}/btoa.node.js +0 -0
- /package/dist/{node/buffer → buffer}/to-array-buffer.node.d.ts +0 -0
- /package/dist/{esm/node/buffer → buffer}/to-array-buffer.node.js +0 -0
- /package/dist/{node/file → file}/blob-stream-controller.d.ts +0 -0
- /package/dist/{node/file → file}/blob-stream.d.ts +0 -0
- /package/dist/{node/file → file}/blob.d.ts +0 -0
- /package/dist/{node/file → file}/file-reader.d.ts +0 -0
- /package/dist/{node/file → file}/readable-stream.d.ts +0 -0
- /package/dist/{node/images → images}/encode-image.node.d.ts +0 -0
- /package/dist/{node/images → images}/parse-image.node.d.ts +0 -0
- /package/dist/{esm/node/images → images}/parse-image.node.js +0 -0
- /package/dist/{lib → text-encoder}/encoding-indexes.d.ts +0 -0
- /package/dist/{esm/lib → text-encoder}/encoding-indexes.js +0 -0
- /package/src/{node/buffer → buffer}/btoa.node.ts +0 -0
- /package/src/{node/buffer → buffer}/to-array-buffer.node.ts +0 -0
- /package/src/{node/fetch/utils/decode-data-uri.node.ts → fetch/decode-data-uri.ts} +0 -0
- /package/src/{node/fetch/headers.node.ts → fetch/headers-polyfill.ts} +0 -0
- /package/src/{node/file → file}/blob-stream-controller.ts +0 -0
- /package/src/{node/file → file}/blob-stream.ts +0 -0
- /package/src/{node/file → file}/blob.ts +0 -0
- /package/src/{node/file → file}/file-reader.ts +0 -0
- /package/src/{node/images → images}/encode-image.node.ts +0 -0
- /package/src/{node/images → images}/parse-image.node.ts +0 -0
- /package/src/{lib → text-encoder}/encoding-indexes.ts +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// loaders.gl, MIT license
|
|
2
2
|
|
|
3
|
-
import {assert} from '
|
|
4
|
-
import {decompressReadStream, concatenateReadStream} from '
|
|
5
|
-
import {Headers} from './headers
|
|
3
|
+
import {assert} from '../utils/assert';
|
|
4
|
+
import {decompressReadStream, concatenateReadStream} from '../filesystems/stream-utils.node';
|
|
5
|
+
import {Headers} from './headers-polyfill';
|
|
6
6
|
|
|
7
7
|
const isBoolean = (x) => typeof x === 'boolean';
|
|
8
8
|
const isFunction = (x) => typeof x === 'function';
|
|
@@ -20,7 +20,7 @@ const isReadableNodeStream = (x) =>
|
|
|
20
20
|
*
|
|
21
21
|
* See https://developer.mozilla.org/en-US/docs/Web/API/Response
|
|
22
22
|
*/
|
|
23
|
-
import
|
|
23
|
+
import * as stream from 'stream';
|
|
24
24
|
|
|
25
25
|
export class Response {
|
|
26
26
|
readonly ok: boolean;
|
|
@@ -53,9 +53,9 @@ export class Response {
|
|
|
53
53
|
if (isReadableNodeStream(body)) {
|
|
54
54
|
this._body = decompressReadStream(body, headers);
|
|
55
55
|
} else if (typeof body === 'string') {
|
|
56
|
-
this._body = Readable.from([new TextEncoder().encode(body)]);
|
|
56
|
+
this._body = stream.Readable.from([new TextEncoder().encode(body)]);
|
|
57
57
|
} else {
|
|
58
|
-
this._body = Readable.from([body || new ArrayBuffer(0)]);
|
|
58
|
+
this._body = stream.Readable.from([body || new ArrayBuffer(0)]);
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
// Forked from @gozala's web-file under MIT license https://github.com/Gozala/web-file
|
|
2
|
-
import {BlobPolyfill} from './blob';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Forked from @gozala's web-file under MIT license
|
|
6
5
|
* @see https://github.com/Gozala/web-file
|
|
7
6
|
*/
|
|
8
7
|
// @ts-ignore
|
|
9
|
-
export class FilePolyfill extends
|
|
8
|
+
export class FilePolyfill extends globalThis.Blob {
|
|
10
9
|
// implements File {
|
|
11
10
|
// public API
|
|
12
11
|
/** The name of the file referenced by the File object. */
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// import {ReadableStreamPolyfill} from './readable-stream';
|
|
2
|
+
import {BlobPolyfill} from './blob';
|
|
3
|
+
|
|
4
|
+
export function instalBlobPolyfills() {
|
|
5
|
+
if (typeof Blob === 'undefined' && !globalThis.Blob) {
|
|
6
|
+
// @ts-ignore;
|
|
7
|
+
globalThis.Blob = BlobPolyfill;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return globalThis.Blob;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const Blob_ = instalBlobPolyfills();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// import {ReadableStreamPolyfill} from './readable-stream';
|
|
2
|
+
import {FileReaderPolyfill} from './file-reader';
|
|
3
|
+
import {FilePolyfill} from './file';
|
|
4
|
+
|
|
5
|
+
export function installFilePolyfills() {
|
|
6
|
+
if (typeof FileReader === 'undefined' && !globalThis.FileReader) {
|
|
7
|
+
// @ts-ignore;
|
|
8
|
+
globalThis.FileReader = FileReaderPolyfill;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Install minimal Node.js File polyfill
|
|
12
|
+
if (typeof File === 'undefined' && !globalThis.File) {
|
|
13
|
+
// @ts-ignore;
|
|
14
|
+
globalThis.File = FilePolyfill;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return global;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const File_ = installFilePolyfills();
|
|
@@ -2,7 +2,7 @@ import {ReadableStream as WSPReadableStream} from 'web-streams-polyfill';
|
|
|
2
2
|
|
|
3
3
|
// Want a polyfill, but please don't install it
|
|
4
4
|
// @ts-ignore
|
|
5
|
-
delete
|
|
5
|
+
delete globalThis.ReadableStream;
|
|
6
6
|
|
|
7
7
|
// @ts-ignore
|
|
8
8
|
export class ReadableStreamPolyfill<T> extends WSPReadableStream<T> implements ReadableStream {}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// loaders.gl, MIT license
|
|
2
|
+
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import {Readable} from 'stream';
|
|
5
|
+
import {resolvePath} from '@loaders.gl/loader-utils';
|
|
6
|
+
import {decompressReadStream} from './stream-utils.node';
|
|
7
|
+
|
|
8
|
+
const isBoolean = (x) => typeof x === 'boolean';
|
|
9
|
+
const isFunction = (x) => typeof x === 'function';
|
|
10
|
+
const isObject = (x) => x !== null && typeof x === 'object';
|
|
11
|
+
const isReadableNodeStream = (x) =>
|
|
12
|
+
isObject(x) && isFunction(x.read) && isFunction(x.pipe) && isBoolean(x.readable);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Enables
|
|
16
|
+
* @param url
|
|
17
|
+
* @param options
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
// eslint-disable-next-line max-statements
|
|
21
|
+
export async function fetchNode(url: string, options?: RequestInit): Promise<Response> {
|
|
22
|
+
// Support `file://` protocol
|
|
23
|
+
const FILE_PROTOCOL_REGEX = /^file:\/\//;
|
|
24
|
+
url.replace(FILE_PROTOCOL_REGEX, '/');
|
|
25
|
+
|
|
26
|
+
// Remove any query parameters, as they have no meaning
|
|
27
|
+
let noqueryUrl = url.split('?')[0];
|
|
28
|
+
noqueryUrl = resolvePath(noqueryUrl);
|
|
29
|
+
|
|
30
|
+
const responseHeaders = new Headers();
|
|
31
|
+
// Automatically decompress gzipped files with .gz extension
|
|
32
|
+
if (url.endsWith('.gz')) {
|
|
33
|
+
// url = url.slice(0, -3);
|
|
34
|
+
responseHeaders['content-encoding'] = 'gzip';
|
|
35
|
+
}
|
|
36
|
+
if (url.endsWith('.br')) {
|
|
37
|
+
// url = url.slice(0, -3);
|
|
38
|
+
responseHeaders['content-encoding'] = 'br';
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
// Now open the stream
|
|
43
|
+
const body = await new Promise<fs.ReadStream>((resolve, reject) => {
|
|
44
|
+
// @ts-ignore
|
|
45
|
+
const stream = fs.createReadStream(noqueryUrl, {encoding: null});
|
|
46
|
+
stream.once('readable', () => resolve(stream));
|
|
47
|
+
stream.on('error', (error) => reject(error));
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
let bodyStream: Readable = body;
|
|
51
|
+
|
|
52
|
+
// Check for content-encoding and create a decompression stream
|
|
53
|
+
if (isReadableNodeStream(body)) {
|
|
54
|
+
bodyStream = decompressReadStream(body, responseHeaders);
|
|
55
|
+
} else if (typeof body === 'string') {
|
|
56
|
+
bodyStream = Readable.from([new TextEncoder().encode(body)]);
|
|
57
|
+
} else {
|
|
58
|
+
bodyStream = Readable.from([body || new ArrayBuffer(0)]);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const status = 200;
|
|
62
|
+
const statusText = 'OK';
|
|
63
|
+
const headers = getHeadersForFile(noqueryUrl);
|
|
64
|
+
// @ts-expect-error
|
|
65
|
+
const response = new Response(bodyStream, {headers, status, statusText});
|
|
66
|
+
Object.defineProperty(response, 'url', {value: url});
|
|
67
|
+
return response;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
// console.error(error);
|
|
70
|
+
const errorMessage = (error as Error).message;
|
|
71
|
+
const status = 400;
|
|
72
|
+
const statusText = errorMessage;
|
|
73
|
+
const headers = {};
|
|
74
|
+
const response = new Response(errorMessage, {headers, status, statusText});
|
|
75
|
+
Object.defineProperty(response, 'url', {value: url});
|
|
76
|
+
return response;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function getHeadersForFile(noqueryUrl: string): Headers {
|
|
81
|
+
const headers = {};
|
|
82
|
+
|
|
83
|
+
// Fix up content length if we can for best progress experience
|
|
84
|
+
if (!headers['content-length']) {
|
|
85
|
+
const stats = fs.statSync(noqueryUrl);
|
|
86
|
+
headers['content-length'] = stats.size;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Automatically decompress gzipped files with .gz extension
|
|
90
|
+
if (noqueryUrl.endsWith('.gz')) {
|
|
91
|
+
noqueryUrl = noqueryUrl.slice(0, -3);
|
|
92
|
+
headers['content-encoding'] = 'gzip';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return new Headers(headers);
|
|
96
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type {ReadableFile, WritableFile, Stat} from '@loaders.gl/loader-utils';
|
|
2
|
+
import {resolvePath} from '@loaders.gl/loader-utils';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
|
|
5
|
+
export class NodeFile implements ReadableFile, WritableFile {
|
|
6
|
+
handle: number;
|
|
7
|
+
size: number;
|
|
8
|
+
bigsize: bigint;
|
|
9
|
+
url: string;
|
|
10
|
+
|
|
11
|
+
constructor(path: string, flags: 'r' | 'w' | 'wx', mode?: number) {
|
|
12
|
+
path = resolvePath(path);
|
|
13
|
+
this.handle = fs.openSync(path, flags, mode);
|
|
14
|
+
const stats = fs.fstatSync(this.handle, {bigint: true});
|
|
15
|
+
this.size = Number(stats.size);
|
|
16
|
+
this.bigsize = stats.size;
|
|
17
|
+
this.url = path;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async close(): Promise<void> {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
fs.close(this.handle, (err) => (err ? reject(err) : resolve()));
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async stat(): Promise<Stat> {
|
|
27
|
+
return await new Promise((resolve, reject) =>
|
|
28
|
+
fs.fstat(this.handle, {bigint: true}, (err, info) => {
|
|
29
|
+
const stats: Stat = {
|
|
30
|
+
size: Number(info.size),
|
|
31
|
+
bigsize: info.size,
|
|
32
|
+
isDirectory: info.isDirectory()
|
|
33
|
+
};
|
|
34
|
+
if (err) {
|
|
35
|
+
reject(err);
|
|
36
|
+
} else {
|
|
37
|
+
resolve(stats);
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async read(offset: number | bigint, length: number): Promise<ArrayBuffer> {
|
|
44
|
+
const arrayBuffer = new ArrayBuffer(length);
|
|
45
|
+
let bigOffset = BigInt(offset);
|
|
46
|
+
|
|
47
|
+
let totalBytesRead = 0;
|
|
48
|
+
const uint8Array = new Uint8Array(arrayBuffer);
|
|
49
|
+
|
|
50
|
+
let position;
|
|
51
|
+
// Read in loop until we get required number of bytes
|
|
52
|
+
while (length > 0) {
|
|
53
|
+
const bytesRead = await readBytes(this.handle, uint8Array, 0, length, bigOffset);
|
|
54
|
+
|
|
55
|
+
// Check if end of file reached
|
|
56
|
+
if (bytesRead === 0) {
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
totalBytesRead += bytesRead;
|
|
61
|
+
bigOffset += BigInt(bytesRead);
|
|
62
|
+
length -= bytesRead;
|
|
63
|
+
|
|
64
|
+
// Advance position unless we are using built-in position advancement
|
|
65
|
+
if (position !== undefined) {
|
|
66
|
+
position += bytesRead;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return totalBytesRead < length ? arrayBuffer.slice(0, totalBytesRead) : arrayBuffer;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async write(
|
|
73
|
+
arrayBuffer: ArrayBuffer,
|
|
74
|
+
offset: number | bigint = 0,
|
|
75
|
+
length: number = arrayBuffer.byteLength
|
|
76
|
+
): Promise<number> {
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
// TODO - Node.js doesn't offer write with bigint offsets???
|
|
79
|
+
const nOffset = Number(offset);
|
|
80
|
+
const uint8Array = new Uint8Array(arrayBuffer, Number(offset), length);
|
|
81
|
+
fs.write(this.handle, uint8Array, 0, length, nOffset, (err, bytesWritten) =>
|
|
82
|
+
err ? reject(err) : resolve(bytesWritten)
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function readBytes(
|
|
89
|
+
fd: number,
|
|
90
|
+
uint8Array: Uint8Array,
|
|
91
|
+
offset: number,
|
|
92
|
+
length: number,
|
|
93
|
+
position: number | bigint | null
|
|
94
|
+
): Promise<number> {
|
|
95
|
+
return await new Promise<number>((resolve, reject) =>
|
|
96
|
+
fs.read(fd, uint8Array, offset, length, position, (err, bytesRead) =>
|
|
97
|
+
err ? reject(err) : resolve(bytesRead)
|
|
98
|
+
)
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// TODO - implement streaming write
|
|
103
|
+
/*
|
|
104
|
+
export interface WriteStreamOptions {
|
|
105
|
+
flags?: string;
|
|
106
|
+
encoding?: 'utf8';
|
|
107
|
+
fd?: number;
|
|
108
|
+
mode?: number;
|
|
109
|
+
autoClose?: boolean;
|
|
110
|
+
start?: number;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export class NodeStreamWritableFile implements WritableFile {
|
|
114
|
+
outputStream: fs.WriteStream | Writable;
|
|
115
|
+
|
|
116
|
+
constructor(pathOrStream: string | Writable, options?: WriteStreamOptions) {
|
|
117
|
+
this.outputStream =
|
|
118
|
+
typeof pathOrStream === 'string' ? fs.createWriteStream(pathOrStream, options) : pathOrStream;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async write(buffer: ArrayBuffer): Promise<void> {
|
|
122
|
+
return new Promise((resolve, reject) => {
|
|
123
|
+
const uint8Array = new Uint8Array(buffer);
|
|
124
|
+
this.outputStream.write(uint8Array, (err) => (err ? reject(err) : resolve()));
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async close(): Promise<void> {
|
|
129
|
+
if (this.outputStream instanceof fs.WriteStream) {
|
|
130
|
+
return new Promise((resolve, reject) => {
|
|
131
|
+
const stream = this.outputStream as fs.WriteStream;
|
|
132
|
+
stream.close((err) => (err ? reject(err) : resolve()));
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
*/
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// loaders.gl, MIT license
|
|
2
|
+
|
|
3
|
+
import {Stat, RandomAccessFileSystem} from '@loaders.gl/loader-utils';
|
|
4
|
+
import fsPromise from 'fs/promises';
|
|
5
|
+
import {NodeFile} from './node-file';
|
|
6
|
+
import {fetchNode} from './fetch-node';
|
|
7
|
+
|
|
8
|
+
// import {fetchFile} from "../fetch/fetch-file"
|
|
9
|
+
// import {selectLoader} from "../api/select-loader";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* FileSystem pass-through for Node.js
|
|
13
|
+
* Compatible with BrowserFileSystem.
|
|
14
|
+
* @param options
|
|
15
|
+
*/
|
|
16
|
+
export class NodeFileSystem implements RandomAccessFileSystem {
|
|
17
|
+
readable: boolean = true;
|
|
18
|
+
writable: boolean = true;
|
|
19
|
+
|
|
20
|
+
// implements FileSystem
|
|
21
|
+
constructor() {}
|
|
22
|
+
|
|
23
|
+
async readdir(dirname = '.', options?: {}): Promise<any[]> {
|
|
24
|
+
return await fsPromise.readdir(dirname, options);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async stat(path: string): Promise<Stat> {
|
|
28
|
+
const info = await fsPromise.stat(path, {bigint: true});
|
|
29
|
+
return {
|
|
30
|
+
size: Number(info.size),
|
|
31
|
+
bigsize: info.size,
|
|
32
|
+
isDirectory: info.isDirectory()
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async unlink(path: string): Promise<void> {
|
|
37
|
+
return await fsPromise.unlink(path);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async fetch(path: string, options: RequestInit): Promise<Response> {
|
|
41
|
+
return await fetchNode(path, options);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// implements IRandomAccessFileSystem
|
|
45
|
+
async openReadableFile(path: string, flags: 'r' = 'r'): Promise<NodeFile> {
|
|
46
|
+
return new NodeFile(path, flags);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async openWritableFile(path: string, flags: 'w' | 'wx' = 'w', mode?: any): Promise<NodeFile> {
|
|
50
|
+
return new NodeFile(path, flags, mode);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
// loaders.gl, MIT license
|
|
2
2
|
|
|
3
3
|
import zlib from 'zlib';
|
|
4
|
+
import {Readable} from 'stream';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
const isArrayBuffer = (x) => x && x instanceof ArrayBuffer;
|
|
7
|
+
const isBuffer = (x) => x && x instanceof Buffer;
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
*
|
|
9
11
|
*/
|
|
10
|
-
export function decompressReadStream(readStream, headers) {
|
|
11
|
-
switch (headers
|
|
12
|
+
export function decompressReadStream(readStream: Readable, headers?: Headers) {
|
|
13
|
+
switch (headers?.get('content-encoding')) {
|
|
12
14
|
case 'br':
|
|
13
15
|
return readStream.pipe(zlib.createBrotliDecompress());
|
|
14
16
|
case 'gzip':
|
|
@@ -77,3 +79,40 @@ export function concatenateArrayBuffers(sources: (ArrayBuffer | Uint8Array)[]):
|
|
|
77
79
|
// We work with ArrayBuffers, discard the typed array wrapper
|
|
78
80
|
return result.buffer;
|
|
79
81
|
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @param data
|
|
85
|
+
* @todo Duplicate of core
|
|
86
|
+
*/
|
|
87
|
+
export function toArrayBuffer(data: unknown): ArrayBuffer {
|
|
88
|
+
if (isArrayBuffer(data)) {
|
|
89
|
+
return data as ArrayBuffer;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// TODO - per docs we should just be able to call buffer.buffer, but there are issues
|
|
93
|
+
if (isBuffer(data)) {
|
|
94
|
+
// @ts-expect-error
|
|
95
|
+
const typedArray = new Uint8Array(data);
|
|
96
|
+
return typedArray.buffer;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Careful - Node Buffers will look like ArrayBuffers (keep after isBuffer)
|
|
100
|
+
if (ArrayBuffer.isView(data)) {
|
|
101
|
+
return data.buffer;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (typeof data === 'string') {
|
|
105
|
+
const text = data;
|
|
106
|
+
const uint8Array = new TextEncoder().encode(text);
|
|
107
|
+
return uint8Array.buffer;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// HACK to support Blob polyfill
|
|
111
|
+
// @ts-expect-error
|
|
112
|
+
if (data && typeof data === 'object' && data._toArrayBuffer) {
|
|
113
|
+
// @ts-expect-error
|
|
114
|
+
return data._toArrayBuffer();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
throw new Error(`toArrayBuffer(${JSON.stringify(data, null, 2).slice(10)})`);
|
|
118
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// loaders.gl, MIT License
|
|
2
|
+
|
|
3
|
+
export function installFilePolyfills() {}
|
|
4
|
+
|
|
5
|
+
// Dummy export to avoid import errors in browser tests
|
|
6
|
+
export const NodeFileSystem = null;
|
|
7
|
+
|
|
8
|
+
export function fetchNode(path: string, options: RequestInit): Promise<Response> {
|
|
9
|
+
throw new Error('fetchNode not available in browser');
|
|
10
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,82 +1,108 @@
|
|
|
1
1
|
/* eslint-disable dot-notation */
|
|
2
|
-
import {isBrowser
|
|
2
|
+
import {isBrowser} from './utils/is-browser';
|
|
3
3
|
|
|
4
|
-
import {TextDecoder, TextEncoder} from './
|
|
5
|
-
import {allSettled} from './promise/all-settled';
|
|
4
|
+
import {TextDecoder, TextEncoder} from './text-encoder/text-encoder';
|
|
6
5
|
|
|
7
6
|
// Node specific
|
|
8
|
-
import
|
|
7
|
+
import {atob, btoa} from './buffer/btoa.node';
|
|
9
8
|
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {fetchNode as fetchNode} from './node/fetch/fetch.node';
|
|
9
|
+
import {encodeImageNode} from './images/encode-image.node';
|
|
10
|
+
import {parseImageNode, NODE_FORMAT_SUPPORT} from './images/parse-image.node';
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
import {
|
|
12
|
+
// FILESYSTEM POLYFILLS
|
|
13
|
+
import {NodeFile} from './filesystems/node-file';
|
|
14
|
+
import {NodeFileSystem} from './filesystems/node-filesystem';
|
|
15
|
+
import {fetchNode} from './filesystems/fetch-node';
|
|
16
16
|
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
export
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
// NODE VERSION
|
|
18
|
+
import {versions} from 'node:process';
|
|
19
|
+
export const nodeVersion = parseInt(versions.node.split('.')[0]);
|
|
20
|
+
|
|
21
|
+
// STREAM POLYFILLS
|
|
22
|
+
import {makeNodeStream} from './streams/make-node-stream';
|
|
23
|
+
|
|
24
|
+
// BLOB AND FILE POLYFILLS
|
|
25
|
+
export {Blob_ as Blob} from './file/install-blob-polyfills';
|
|
26
|
+
export {File_ as File} from './file/install-file-polyfills';
|
|
27
|
+
|
|
28
|
+
if (isBrowser) {
|
|
29
|
+
// eslint-disable-next-line no-console
|
|
30
|
+
console.error(
|
|
31
|
+
'loaders.gl: The @loaders.gl/polyfills should only be used in Node.js environments'
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
globalThis.loaders = globalThis.loaders || {};
|
|
36
|
+
|
|
37
|
+
// STREAM POLYFILLS
|
|
38
|
+
export {makeNodeStream} from './streams/make-node-stream';
|
|
39
|
+
globalThis.loaders.makeNodeStream = makeNodeStream;
|
|
40
|
+
|
|
41
|
+
// FILESYSTEM POLYFILLS
|
|
42
|
+
globalThis.loaders.NodeFile = NodeFile;
|
|
43
|
+
globalThis.loaders.NodeFileSystem = NodeFileSystem;
|
|
44
|
+
globalThis.loaders.fetchNode = fetchNode;
|
|
22
45
|
|
|
23
46
|
// POLYFILLS: TextEncoder, TextDecoder
|
|
24
47
|
// - Recent Node versions have these classes but virtually no encodings unless special build.
|
|
25
48
|
// - Browser: Edge, IE11 do not have these
|
|
26
49
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
50
|
+
if (!globalThis.TextEncoder) {
|
|
51
|
+
// @ts-expect-error
|
|
52
|
+
globalThis.TextEncoder = TextEncoder;
|
|
30
53
|
}
|
|
31
54
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
55
|
+
if (!globalThis.TextDecoder) {
|
|
56
|
+
// @ts-expect-error
|
|
57
|
+
globalThis.TextDecoder = TextDecoder;
|
|
35
58
|
}
|
|
36
59
|
|
|
37
60
|
// POLYFILLS: btoa, atob
|
|
38
61
|
// - Node: Yes
|
|
39
62
|
// - Browser: No
|
|
40
63
|
|
|
41
|
-
if (!
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
if (!isBrowser && !('btoa' in global) && base64.btoa) {
|
|
45
|
-
global['btoa'] = base64.btoa;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// DEPRECATED POLYFILL:
|
|
49
|
-
// - Node v18+: No, not needed
|
|
50
|
-
// - Node v16 and lower: Yes
|
|
51
|
-
// - Browsers (evergreen): Not needed.
|
|
52
|
-
// - IE11: No. This polyfill is node only, install external polyfill
|
|
53
|
-
|
|
54
|
-
if (!isBrowser && !('Headers' in global) && HeadersNode) {
|
|
55
|
-
global['Headers'] = HeadersNode;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (!isBrowser && !('Response' in global) && ResponseNode) {
|
|
59
|
-
global['Response'] = ResponseNode;
|
|
64
|
+
if (!('atob' in globalThis) && atob) {
|
|
65
|
+
globalThis['atob'] = atob;
|
|
60
66
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
global['fetch'] = fetchNode;
|
|
67
|
+
if (!('btoa' in globalThis) && btoa) {
|
|
68
|
+
globalThis['btoa'] = btoa;
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
// NODE IMAGE FUNCTIONS:
|
|
67
72
|
// These are not official polyfills but used by the @loaders.gl/images module if installed
|
|
68
73
|
// TODO - is there an appropriate Image API we could polyfill using an adapter?
|
|
69
74
|
|
|
70
|
-
if (!
|
|
71
|
-
|
|
75
|
+
if (!('_encodeImageNode' in globalThis) && encodeImageNode) {
|
|
76
|
+
globalThis['_encodeImageNode'] = encodeImageNode;
|
|
72
77
|
}
|
|
73
78
|
|
|
74
|
-
if (!
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
if (!('_parseImageNode' in globalThis) && parseImageNode) {
|
|
80
|
+
globalThis['_parseImageNode'] = parseImageNode;
|
|
81
|
+
globalThis['_imageFormatsNode'] = NODE_FORMAT_SUPPORT;
|
|
77
82
|
}
|
|
78
83
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
// DEPRECATED POLYFILL:
|
|
85
|
+
// - Node v18+: No, not needed
|
|
86
|
+
// - Node v16 and lower: Yes
|
|
87
|
+
// - Browsers (evergreen): Not needed.
|
|
88
|
+
// - IE11: No. This polyfill is node only, install external polyfill
|
|
89
|
+
import {Headers as HeadersNode} from './fetch/headers-polyfill';
|
|
90
|
+
import {Response as ResponseNode} from './fetch/response-polyfill';
|
|
91
|
+
import {fetchNode as fetchNodePolyfill} from './fetch/fetch-polyfill';
|
|
92
|
+
|
|
93
|
+
if (nodeVersion < 18) {
|
|
94
|
+
if (!('Headers' in globalThis) && HeadersNode) {
|
|
95
|
+
// @ts-ignore
|
|
96
|
+
globalThis.Headers = HeadersNode;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!('Response' in globalThis) && ResponseNode) {
|
|
100
|
+
// @ts-ignore
|
|
101
|
+
globalThis.Response = ResponseNode;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!('fetch' in globalThis) && fetchNodePolyfill) {
|
|
105
|
+
// @ts-ignore
|
|
106
|
+
globalThis.fetch = fetchNodePolyfill;
|
|
107
|
+
}
|
|
82
108
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type {ReadableOptions} from 'stream';
|
|
2
|
+
import * as Stream from 'stream';
|
|
3
|
+
|
|
4
|
+
class _Readable {}
|
|
5
|
+
|
|
6
|
+
type ReadableType = Stream.Readable | _Readable;
|
|
7
|
+
const Readable = Stream.Readable || _Readable;
|
|
8
|
+
|
|
9
|
+
export type MakeStreamOptions = ReadableOptions;
|
|
10
|
+
|
|
11
|
+
/** Builds a node stream from an iterator */
|
|
12
|
+
export function makeNodeStream<ArrayBuffer>(
|
|
13
|
+
source: Iterable<ArrayBuffer> | AsyncIterable<ArrayBuffer>,
|
|
14
|
+
options?: ReadableOptions
|
|
15
|
+
): ReadableType {
|
|
16
|
+
// @ts-ignore AsyncGenerator
|
|
17
|
+
const iterator = source[Symbol.asyncIterator]
|
|
18
|
+
? // @ts-ignore AsyncGenerator
|
|
19
|
+
source[Symbol.asyncIterator]()
|
|
20
|
+
: // @ts-ignore AsyncGenerator
|
|
21
|
+
source[Symbol.iterator]();
|
|
22
|
+
return new AsyncIterableReadable(iterator, options);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class AsyncIterableReadable extends Readable {
|
|
26
|
+
private _pulling: boolean;
|
|
27
|
+
private _bytesMode: boolean;
|
|
28
|
+
private _iterator: AsyncIterator<ArrayBuffer>;
|
|
29
|
+
|
|
30
|
+
constructor(it: AsyncIterator<ArrayBuffer>, options?: ReadableOptions) {
|
|
31
|
+
super(options);
|
|
32
|
+
this._iterator = it;
|
|
33
|
+
this._pulling = false;
|
|
34
|
+
this._bytesMode = !options || !options.objectMode;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async _read(size: number): Promise<void> {
|
|
38
|
+
if (!this._pulling) {
|
|
39
|
+
this._pulling = true;
|
|
40
|
+
this._pulling = await this._pull(size, this._iterator);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async _destroy(error: Error | null, cb: (e: Error | null) => void): Promise<void> {
|
|
45
|
+
if (!this._iterator) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (error) {
|
|
49
|
+
await this._iterator?.throw?.(error);
|
|
50
|
+
} else {
|
|
51
|
+
await this._iterator?.return?.(error);
|
|
52
|
+
}
|
|
53
|
+
cb?.(null);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// eslint-disable-next-line complexity
|
|
57
|
+
private async _pull(size: number, it: AsyncIterator<ArrayBuffer>): Promise<boolean> {
|
|
58
|
+
const bm = this._bytesMode;
|
|
59
|
+
let r: IteratorResult<ArrayBuffer> | null = null;
|
|
60
|
+
// while (this.readable && !(r = await it.next(bm ? size : null)).done) {
|
|
61
|
+
while (this.readable && !(r = await it.next()).done) {
|
|
62
|
+
if (size !== null) {
|
|
63
|
+
size -= bm && ArrayBuffer.isView(r.value) ? r.value.byteLength : 1;
|
|
64
|
+
}
|
|
65
|
+
if (!this.push(new Uint8Array(r.value)) || size <= 0) {
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if ((r?.done || !this.readable) && (this.push(null) || true)) {
|
|
70
|
+
it?.return?.();
|
|
71
|
+
}
|
|
72
|
+
return !this.readable;
|
|
73
|
+
}
|
|
74
|
+
}
|