strtok3 10.2.2 → 10.3.1

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 CHANGED
@@ -361,15 +361,7 @@ import { ReadableWebToNodeStream } from 'readable-web-to-node-stream';
361
361
 
362
362
  ## Dependencies
363
363
 
364
- The diagram below illustrates the primary dependencies of `strtok3`:
365
-
366
- ```mermaid
367
- graph TD;
368
- S(strtok3)-->P(peek-readable)
369
- S(strtok3)-->TO("@tokenizer/token")
370
- ```
371
-
372
- - [peek-readable](https://github.com/Borewit/peek-readable): Manages reading operations with peeking capabilities, allowing data to be previewed without advancing the read pointer.
364
+ Dependencies:
373
365
  - [@tokenizer/token](https://github.com/Borewit/tokenizer-token): Provides token definitions and utilities used by `strtok3` for interpreting binary data.
374
366
 
375
367
  ## Licence
@@ -1,4 +1,4 @@
1
- import { EndOfStreamError } from 'peek-readable';
1
+ import { EndOfStreamError } from './stream/index.js';
2
2
  /**
3
3
  * Core tokenizer
4
4
  */
@@ -0,0 +1,29 @@
1
+ import type { ITokenizerOptions, IReadChunkOptions, IRandomAccessFileInfo, IRandomAccessTokenizer } from './types.js';
2
+ import { AbstractTokenizer } from './AbstractTokenizer.js';
3
+ export declare class BlobTokenizer extends AbstractTokenizer implements IRandomAccessTokenizer {
4
+ private blob;
5
+ fileInfo: IRandomAccessFileInfo;
6
+ /**
7
+ * Construct BufferTokenizer
8
+ * @param blob - Uint8Array to tokenize
9
+ * @param options Tokenizer options
10
+ */
11
+ constructor(blob: Blob, options?: ITokenizerOptions);
12
+ /**
13
+ * Read buffer from tokenizer
14
+ * @param uint8Array - Uint8Array to tokenize
15
+ * @param options - Read behaviour options
16
+ * @returns {Promise<number>}
17
+ */
18
+ readBuffer(uint8Array: Uint8Array, options?: IReadChunkOptions): Promise<number>;
19
+ /**
20
+ * Peek (read ahead) buffer from tokenizer
21
+ * @param buffer
22
+ * @param options - Read behaviour options
23
+ * @returns {Promise<number>}
24
+ */
25
+ peekBuffer(buffer: Uint8Array, options?: IReadChunkOptions): Promise<number>;
26
+ close(): Promise<void>;
27
+ supportsRandomAccess(): boolean;
28
+ setPosition(position: number): void;
29
+ }
@@ -0,0 +1,53 @@
1
+ import { EndOfStreamError } from './stream/index.js';
2
+ import { AbstractTokenizer } from './AbstractTokenizer.js';
3
+ export class BlobTokenizer extends AbstractTokenizer {
4
+ /**
5
+ * Construct BufferTokenizer
6
+ * @param blob - Uint8Array to tokenize
7
+ * @param options Tokenizer options
8
+ */
9
+ constructor(blob, options) {
10
+ super(options);
11
+ this.blob = blob;
12
+ this.fileInfo = { ...options?.fileInfo ?? {}, ...{ size: blob.size, mimeType: blob.type } };
13
+ }
14
+ /**
15
+ * Read buffer from tokenizer
16
+ * @param uint8Array - Uint8Array to tokenize
17
+ * @param options - Read behaviour options
18
+ * @returns {Promise<number>}
19
+ */
20
+ async readBuffer(uint8Array, options) {
21
+ if (options?.position) {
22
+ this.position = options.position;
23
+ }
24
+ const bytesRead = await this.peekBuffer(uint8Array, options);
25
+ this.position += bytesRead;
26
+ return bytesRead;
27
+ }
28
+ /**
29
+ * Peek (read ahead) buffer from tokenizer
30
+ * @param buffer
31
+ * @param options - Read behaviour options
32
+ * @returns {Promise<number>}
33
+ */
34
+ async peekBuffer(buffer, options) {
35
+ const normOptions = this.normalizeOptions(buffer, options);
36
+ const bytes2read = Math.min(this.blob.size - normOptions.position, normOptions.length);
37
+ if ((!normOptions.mayBeLess) && bytes2read < normOptions.length) {
38
+ throw new EndOfStreamError();
39
+ }
40
+ const arrayBuffer = await this.blob.slice(normOptions.position, normOptions.position + bytes2read).arrayBuffer();
41
+ buffer.set(new Uint8Array(arrayBuffer));
42
+ return bytes2read;
43
+ }
44
+ close() {
45
+ return super.close();
46
+ }
47
+ supportsRandomAccess() {
48
+ return true;
49
+ }
50
+ setPosition(position) {
51
+ this.position = position;
52
+ }
53
+ }
@@ -1,4 +1,4 @@
1
- import { EndOfStreamError } from 'peek-readable';
1
+ import { EndOfStreamError } from './stream/index.js';
2
2
  import { AbstractTokenizer } from './AbstractTokenizer.js';
3
3
  export class BufferTokenizer extends AbstractTokenizer {
4
4
  /**
@@ -1,5 +1,5 @@
1
1
  import { AbstractTokenizer } from './AbstractTokenizer.js';
2
- import { EndOfStreamError } from 'peek-readable';
2
+ import { EndOfStreamError } from './stream/index.js';
3
3
  import { open as fsOpen } from 'node:fs/promises';
4
4
  export class FileTokenizer extends AbstractTokenizer {
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { AbstractTokenizer } from './AbstractTokenizer.js';
2
- import { type IStreamReader } from 'peek-readable';
2
+ import { type IStreamReader } from './stream/index.js';
3
3
  import type { IFileInfo, IReadChunkOptions, ITokenizerOptions } from './types.js';
4
4
  export declare class ReadStreamTokenizer extends AbstractTokenizer {
5
5
  private streamReader;
@@ -1,5 +1,5 @@
1
1
  import { AbstractTokenizer } from './AbstractTokenizer.js';
2
- import { EndOfStreamError } from 'peek-readable';
2
+ import { EndOfStreamError } from './stream/index.js';
3
3
  const maxBufferSize = 256000;
4
4
  export class ReadStreamTokenizer extends AbstractTokenizer {
5
5
  /**
package/lib/core.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import type { Readable } from 'node:stream';
2
- import { type AnyWebByteStream } from 'peek-readable';
2
+ import { type AnyWebByteStream } from './stream/index.js';
3
3
  import { ReadStreamTokenizer } from './ReadStreamTokenizer.js';
4
4
  import { BufferTokenizer } from './BufferTokenizer.js';
5
5
  import type { ITokenizerOptions } from './types.js';
6
- export { EndOfStreamError, AbortError, type AnyWebByteStream } from 'peek-readable';
6
+ import { BlobTokenizer } from './BlobTokenizer.js';
7
+ export { EndOfStreamError, AbortError, type AnyWebByteStream } from './stream/index.js';
7
8
  export type { ITokenizer, IRandomAccessTokenizer, IFileInfo, IRandomAccessFileInfo, ITokenizerOptions, IReadChunkOptions, OnClose } from './types.js';
8
9
  export type { IToken, IGetToken } from '@tokenizer/token';
9
10
  export { AbstractTokenizer } from './AbstractTokenizer.js';
@@ -30,3 +31,10 @@ export declare function fromWebStream(webStream: AnyWebByteStream, options?: ITo
30
31
  * @returns BufferTokenizer
31
32
  */
32
33
  export declare function fromBuffer(uint8Array: Uint8Array, options?: ITokenizerOptions): BufferTokenizer;
34
+ /**
35
+ * Construct ReadStreamTokenizer from given Blob.
36
+ * @param blob - Uint8Array to tokenize
37
+ * @param options - Tokenizer options
38
+ * @returns BufferTokenizer
39
+ */
40
+ export declare function fromBlob(blob: Blob, options?: ITokenizerOptions): BlobTokenizer;
package/lib/core.js CHANGED
@@ -1,7 +1,8 @@
1
- import { StreamReader, makeWebStreamReader } from 'peek-readable';
1
+ import { StreamReader, makeWebStreamReader } from './stream/index.js';
2
2
  import { ReadStreamTokenizer } from './ReadStreamTokenizer.js';
3
3
  import { BufferTokenizer } from './BufferTokenizer.js';
4
- export { EndOfStreamError, AbortError } from 'peek-readable';
4
+ import { BlobTokenizer } from './BlobTokenizer.js';
5
+ export { EndOfStreamError, AbortError } from './stream/index.js';
5
6
  export { AbstractTokenizer } from './AbstractTokenizer.js';
6
7
  /**
7
8
  * Construct ReadStreamTokenizer from given Stream.
@@ -50,3 +51,12 @@ export function fromWebStream(webStream, options) {
50
51
  export function fromBuffer(uint8Array, options) {
51
52
  return new BufferTokenizer(uint8Array, options);
52
53
  }
54
+ /**
55
+ * Construct ReadStreamTokenizer from given Blob.
56
+ * @param blob - Uint8Array to tokenize
57
+ * @param options - Tokenizer options
58
+ * @returns BufferTokenizer
59
+ */
60
+ export function fromBlob(blob, options) {
61
+ return new BlobTokenizer(blob, options);
62
+ }
@@ -0,0 +1,54 @@
1
+ export interface IStreamReader {
2
+ /**
3
+ * Peak ahead (peek) from stream. Subsequent read or peeks will return the same data.
4
+ * @param uint8Array - Uint8Array (or Buffer) to store data read from stream in
5
+ * @param mayBeLess - Allow the read to complete, without the buffer being fully filled (length may be smaller)
6
+ * @returns Number of bytes peeked. If `maybeLess` is set, this shall be the `uint8Array.length`.
7
+ */
8
+ peek(uint8Array: Uint8Array, mayBeLess?: boolean): Promise<number>;
9
+ /**
10
+ * Read from stream the stream.
11
+ * @param uint8Array - Uint8Array (or Buffer) to store data read from stream in
12
+ * @param mayBeLess - Allow the read to complete, without the buffer being fully filled (length may be smaller)
13
+ * @returns Number of actually bytes read. If `maybeLess` is set, this shall be the `uint8Array.length`.
14
+ */
15
+ read(uint8Array: Uint8Array, mayBeLess?: boolean): Promise<number>;
16
+ close(): Promise<void>;
17
+ /**
18
+ * Abort any active asynchronous operation are active, abort those before they may have completed.
19
+ */
20
+ abort(): Promise<void>;
21
+ }
22
+ export declare abstract class AbstractStreamReader implements IStreamReader {
23
+ protected endOfStream: boolean;
24
+ protected interrupted: boolean;
25
+ /**
26
+ * Store peeked data
27
+ * @type {Array}
28
+ */
29
+ protected peekQueue: Uint8Array[];
30
+ peek(uint8Array: Uint8Array, mayBeLess?: boolean): Promise<number>;
31
+ read(buffer: Uint8Array, mayBeLess?: boolean): Promise<number>;
32
+ /**
33
+ * Read chunk from stream
34
+ * @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
35
+ * @returns Number of bytes read
36
+ */
37
+ protected readFromPeekBuffer(buffer: Uint8Array): number;
38
+ readRemainderFromStream(buffer: Uint8Array, mayBeLess: boolean): Promise<number>;
39
+ /**
40
+ * Read from stream
41
+ * @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
42
+ * @param mayBeLess - If true, may fill the buffer partially
43
+ * @protected Bytes read
44
+ */
45
+ protected abstract readFromStream(buffer: Uint8Array, mayBeLess: boolean): Promise<number>;
46
+ /**
47
+ * abort synchronous operations
48
+ */
49
+ abstract close(): Promise<void>;
50
+ /**
51
+ * Abort any active asynchronous operation are active, abort those before they may have completed.
52
+ */
53
+ abstract abort(): Promise<void>;
54
+ }
@@ -0,0 +1,71 @@
1
+ import { EndOfStreamError, AbortError } from "./Errors.js";
2
+ export class AbstractStreamReader {
3
+ constructor() {
4
+ this.endOfStream = false;
5
+ this.interrupted = false;
6
+ /**
7
+ * Store peeked data
8
+ * @type {Array}
9
+ */
10
+ this.peekQueue = [];
11
+ }
12
+ async peek(uint8Array, mayBeLess = false) {
13
+ const bytesRead = await this.read(uint8Array, mayBeLess);
14
+ this.peekQueue.push(uint8Array.subarray(0, bytesRead)); // Put read data back to peek buffer
15
+ return bytesRead;
16
+ }
17
+ async read(buffer, mayBeLess = false) {
18
+ if (buffer.length === 0) {
19
+ return 0;
20
+ }
21
+ let bytesRead = this.readFromPeekBuffer(buffer);
22
+ if (!this.endOfStream) {
23
+ bytesRead += await this.readRemainderFromStream(buffer.subarray(bytesRead), mayBeLess);
24
+ }
25
+ if (bytesRead === 0 && !mayBeLess) {
26
+ throw new EndOfStreamError();
27
+ }
28
+ return bytesRead;
29
+ }
30
+ /**
31
+ * Read chunk from stream
32
+ * @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
33
+ * @returns Number of bytes read
34
+ */
35
+ readFromPeekBuffer(buffer) {
36
+ let remaining = buffer.length;
37
+ let bytesRead = 0;
38
+ // consume peeked data first
39
+ while (this.peekQueue.length > 0 && remaining > 0) {
40
+ const peekData = this.peekQueue.pop(); // Front of queue
41
+ if (!peekData)
42
+ throw new Error('peekData should be defined');
43
+ const lenCopy = Math.min(peekData.length, remaining);
44
+ buffer.set(peekData.subarray(0, lenCopy), bytesRead);
45
+ bytesRead += lenCopy;
46
+ remaining -= lenCopy;
47
+ if (lenCopy < peekData.length) {
48
+ // remainder back to queue
49
+ this.peekQueue.push(peekData.subarray(lenCopy));
50
+ }
51
+ }
52
+ return bytesRead;
53
+ }
54
+ async readRemainderFromStream(buffer, mayBeLess) {
55
+ let bytesRead = 0;
56
+ // Continue reading from stream if required
57
+ while (bytesRead < buffer.length && !this.endOfStream) {
58
+ if (this.interrupted) {
59
+ throw new AbortError();
60
+ }
61
+ const chunkLen = await this.readFromStream(buffer.subarray(bytesRead), mayBeLess);
62
+ if (chunkLen === 0)
63
+ break;
64
+ bytesRead += chunkLen;
65
+ }
66
+ if (!mayBeLess && bytesRead < buffer.length) {
67
+ throw new EndOfStreamError();
68
+ }
69
+ return bytesRead;
70
+ }
71
+ }
@@ -0,0 +1,6 @@
1
+ export declare class Deferred<T> {
2
+ promise: Promise<T>;
3
+ resolve: (value: T) => void;
4
+ reject: (reason: Error) => void;
5
+ constructor();
6
+ }
@@ -0,0 +1,10 @@
1
+ export class Deferred {
2
+ constructor() {
3
+ this.resolve = () => null;
4
+ this.reject = () => null;
5
+ this.promise = new Promise((resolve, reject) => {
6
+ this.reject = reject;
7
+ this.resolve = resolve;
8
+ });
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ export declare const defaultMessages = "End-Of-Stream";
2
+ /**
3
+ * Thrown on read operation of the end of file or stream has been reached
4
+ */
5
+ export declare class EndOfStreamError extends Error {
6
+ constructor();
7
+ }
8
+ export declare class AbortError extends Error {
9
+ constructor(message?: string);
10
+ }
@@ -0,0 +1,16 @@
1
+ export const defaultMessages = 'End-Of-Stream';
2
+ /**
3
+ * Thrown on read operation of the end of file or stream has been reached
4
+ */
5
+ export class EndOfStreamError extends Error {
6
+ constructor() {
7
+ super(defaultMessages);
8
+ this.name = "EndOfStreamError";
9
+ }
10
+ }
11
+ export class AbortError extends Error {
12
+ constructor(message = "The operation was aborted") {
13
+ super(message);
14
+ this.name = "AbortError";
15
+ }
16
+ }
@@ -0,0 +1,29 @@
1
+ import type { Readable } from 'node:stream';
2
+ import { AbstractStreamReader } from "./AbstractStreamReader.js";
3
+ /**
4
+ * Node.js Readable Stream Reader
5
+ * Ref: https://nodejs.org/api/stream.html#readable-streams
6
+ */
7
+ export declare class StreamReader extends AbstractStreamReader {
8
+ private s;
9
+ /**
10
+ * Deferred used for postponed read request (as not data is yet available to read)
11
+ */
12
+ private deferred;
13
+ constructor(s: Readable);
14
+ /**
15
+ * Read chunk from stream
16
+ * @param buffer Target Uint8Array (or Buffer) to store data read from stream in
17
+ * @param mayBeLess - If true, may fill the buffer partially
18
+ * @returns Number of bytes read
19
+ */
20
+ protected readFromStream(buffer: Uint8Array, mayBeLess: boolean): Promise<number>;
21
+ /**
22
+ * Process deferred read request
23
+ * @param request Deferred read request
24
+ */
25
+ private readDeferred;
26
+ private reject;
27
+ abort(): Promise<void>;
28
+ close(): Promise<void>;
29
+ }
@@ -0,0 +1,83 @@
1
+ import { AbortError, } from './Errors.js';
2
+ import { Deferred } from './Deferred.js';
3
+ import { AbstractStreamReader } from "./AbstractStreamReader.js";
4
+ /**
5
+ * Node.js Readable Stream Reader
6
+ * Ref: https://nodejs.org/api/stream.html#readable-streams
7
+ */
8
+ export class StreamReader extends AbstractStreamReader {
9
+ constructor(s) {
10
+ super();
11
+ this.s = s;
12
+ /**
13
+ * Deferred used for postponed read request (as not data is yet available to read)
14
+ */
15
+ this.deferred = null;
16
+ if (!s.read || !s.once) {
17
+ throw new Error('Expected an instance of stream.Readable');
18
+ }
19
+ this.s.once('end', () => {
20
+ this.endOfStream = true;
21
+ if (this.deferred) {
22
+ this.deferred.resolve(0);
23
+ }
24
+ });
25
+ this.s.once('error', err => this.reject(err));
26
+ this.s.once('close', () => this.abort());
27
+ }
28
+ /**
29
+ * Read chunk from stream
30
+ * @param buffer Target Uint8Array (or Buffer) to store data read from stream in
31
+ * @param mayBeLess - If true, may fill the buffer partially
32
+ * @returns Number of bytes read
33
+ */
34
+ async readFromStream(buffer, mayBeLess) {
35
+ if (buffer.length === 0)
36
+ return 0;
37
+ const readBuffer = this.s.read(buffer.length);
38
+ if (readBuffer) {
39
+ buffer.set(readBuffer);
40
+ return readBuffer.length;
41
+ }
42
+ const request = {
43
+ buffer,
44
+ mayBeLess,
45
+ deferred: new Deferred()
46
+ };
47
+ this.deferred = request.deferred;
48
+ this.s.once('readable', () => {
49
+ this.readDeferred(request);
50
+ });
51
+ return request.deferred.promise;
52
+ }
53
+ /**
54
+ * Process deferred read request
55
+ * @param request Deferred read request
56
+ */
57
+ readDeferred(request) {
58
+ const readBuffer = this.s.read(request.buffer.length);
59
+ if (readBuffer) {
60
+ request.buffer.set(readBuffer);
61
+ request.deferred.resolve(readBuffer.length);
62
+ this.deferred = null;
63
+ }
64
+ else {
65
+ this.s.once('readable', () => {
66
+ this.readDeferred(request);
67
+ });
68
+ }
69
+ }
70
+ reject(err) {
71
+ this.interrupted = true;
72
+ if (this.deferred) {
73
+ this.deferred.reject(err);
74
+ this.deferred = null;
75
+ }
76
+ }
77
+ async abort() {
78
+ this.reject(new AbortError());
79
+ }
80
+ async close() {
81
+ return this.abort();
82
+ }
83
+ }
@@ -0,0 +1,14 @@
1
+ import { WebStreamReader } from './WebStreamReader.js';
2
+ /**
3
+ * Read from a WebStream using a BYOB reader
4
+ * Reference: https://nodejs.org/api/webstreams.html#class-readablestreambyobreader
5
+ */
6
+ export declare class WebStreamByobReader extends WebStreamReader {
7
+ /**
8
+ * Read from stream
9
+ * @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
10
+ * @param mayBeLess - If true, may fill the buffer partially
11
+ * @protected Bytes read
12
+ */
13
+ protected readFromStream(buffer: Uint8Array, mayBeLess: boolean): Promise<number>;
14
+ }
@@ -0,0 +1,27 @@
1
+ import { WebStreamReader } from './WebStreamReader.js';
2
+ /**
3
+ * Read from a WebStream using a BYOB reader
4
+ * Reference: https://nodejs.org/api/webstreams.html#class-readablestreambyobreader
5
+ */
6
+ export class WebStreamByobReader extends WebStreamReader {
7
+ /**
8
+ * Read from stream
9
+ * @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
10
+ * @param mayBeLess - If true, may fill the buffer partially
11
+ * @protected Bytes read
12
+ */
13
+ async readFromStream(buffer, mayBeLess) {
14
+ if (buffer.length === 0)
15
+ return 0;
16
+ // @ts-ignore
17
+ const result = await this.reader.read(new Uint8Array(buffer.length), { min: mayBeLess ? undefined : buffer.length });
18
+ if (result.done) {
19
+ this.endOfStream = result.done;
20
+ }
21
+ if (result.value) {
22
+ buffer.set(result.value);
23
+ return result.value.length;
24
+ }
25
+ return 0;
26
+ }
27
+ }
@@ -0,0 +1,19 @@
1
+ import { AbstractStreamReader } from "./AbstractStreamReader.js";
2
+ export declare class WebStreamDefaultReader extends AbstractStreamReader {
3
+ private reader;
4
+ private buffer;
5
+ constructor(reader: ReadableStreamDefaultReader<Uint8Array>);
6
+ /**
7
+ * Copy chunk to target, and store the remainder in this.buffer
8
+ */
9
+ private writeChunk;
10
+ /**
11
+ * Read from stream
12
+ * @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
13
+ * @param mayBeLess - If true, may fill the buffer partially
14
+ * @protected Bytes read
15
+ */
16
+ protected readFromStream(buffer: Uint8Array, mayBeLess: boolean): Promise<number>;
17
+ abort(): Promise<void>;
18
+ close(): Promise<void>;
19
+ }
@@ -0,0 +1,62 @@
1
+ import { EndOfStreamError } from './Errors.js';
2
+ import { AbstractStreamReader } from "./AbstractStreamReader.js";
3
+ export class WebStreamDefaultReader extends AbstractStreamReader {
4
+ constructor(reader) {
5
+ super();
6
+ this.reader = reader;
7
+ this.buffer = null; // Internal buffer to store excess data
8
+ }
9
+ /**
10
+ * Copy chunk to target, and store the remainder in this.buffer
11
+ */
12
+ writeChunk(target, chunk) {
13
+ const written = Math.min(chunk.length, target.length);
14
+ target.set(chunk.subarray(0, written));
15
+ // Adjust the remainder of the buffer
16
+ if (written < chunk.length) {
17
+ this.buffer = chunk.subarray(written);
18
+ }
19
+ else {
20
+ this.buffer = null;
21
+ }
22
+ return written;
23
+ }
24
+ /**
25
+ * Read from stream
26
+ * @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
27
+ * @param mayBeLess - If true, may fill the buffer partially
28
+ * @protected Bytes read
29
+ */
30
+ async readFromStream(buffer, mayBeLess) {
31
+ if (buffer.length === 0)
32
+ return 0;
33
+ let totalBytesRead = 0;
34
+ // Serve from the internal buffer first
35
+ if (this.buffer) {
36
+ totalBytesRead += this.writeChunk(buffer, this.buffer);
37
+ }
38
+ // Continue reading from the stream if more data is needed
39
+ while (totalBytesRead < buffer.length && !this.endOfStream) {
40
+ const result = await this.reader.read();
41
+ if (result.done) {
42
+ this.endOfStream = true;
43
+ break;
44
+ }
45
+ if (result.value) {
46
+ totalBytesRead += this.writeChunk(buffer.subarray(totalBytesRead), result.value);
47
+ }
48
+ }
49
+ if (!mayBeLess && totalBytesRead === 0 && this.endOfStream) {
50
+ throw new EndOfStreamError();
51
+ }
52
+ return totalBytesRead;
53
+ }
54
+ abort() {
55
+ this.interrupted = true;
56
+ return this.reader.cancel();
57
+ }
58
+ async close() {
59
+ await this.abort();
60
+ this.reader.releaseLock();
61
+ }
62
+ }
@@ -0,0 +1,14 @@
1
+ import { AbstractStreamReader } from "./AbstractStreamReader.js";
2
+ export declare abstract class WebStreamReader extends AbstractStreamReader {
3
+ protected reader: ReadableStreamDefaultReader | ReadableStreamBYOBReader;
4
+ constructor(reader: ReadableStreamDefaultReader | ReadableStreamBYOBReader);
5
+ /**
6
+ * Read from stream
7
+ * @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
8
+ * @param mayBeLess - If true, may fill the buffer partially
9
+ * @protected Bytes read
10
+ */
11
+ protected abstract readFromStream(buffer: Uint8Array, mayBeLess: boolean): Promise<number>;
12
+ abort(): Promise<void>;
13
+ close(): Promise<void>;
14
+ }
@@ -0,0 +1,13 @@
1
+ import { AbstractStreamReader } from "./AbstractStreamReader.js";
2
+ export class WebStreamReader extends AbstractStreamReader {
3
+ constructor(reader) {
4
+ super();
5
+ this.reader = reader;
6
+ }
7
+ async abort() {
8
+ return this.close();
9
+ }
10
+ async close() {
11
+ this.reader.releaseLock();
12
+ }
13
+ }
@@ -0,0 +1,5 @@
1
+ import type { ReadableStream as NodeReadableStream } from 'node:stream/web';
2
+ import { WebStreamByobReader } from './WebStreamByobReader.js';
3
+ import { WebStreamDefaultReader } from './WebStreamDefaultReader.js';
4
+ export type AnyWebByteStream = NodeReadableStream<Uint8Array> | ReadableStream<Uint8Array>;
5
+ export declare function makeWebStreamReader(stream: AnyWebByteStream): WebStreamByobReader | WebStreamDefaultReader;
@@ -0,0 +1,19 @@
1
+ import { WebStreamByobReader } from './WebStreamByobReader.js';
2
+ import { WebStreamDefaultReader } from './WebStreamDefaultReader.js';
3
+ export function makeWebStreamReader(stream) {
4
+ try {
5
+ const reader = stream.getReader({ mode: "byob" });
6
+ if (reader instanceof ReadableStreamDefaultReader) {
7
+ // Fallback to default reader in case `mode: byob` is ignored
8
+ return new WebStreamDefaultReader(reader);
9
+ }
10
+ return new WebStreamByobReader(reader);
11
+ }
12
+ catch (error) {
13
+ if (error instanceof TypeError) {
14
+ // Fallback to default reader in case `mode: byob` rejected by a `TypeError`
15
+ return new WebStreamDefaultReader(stream.getReader());
16
+ }
17
+ throw error;
18
+ }
19
+ }
@@ -0,0 +1,6 @@
1
+ export { AbortError, EndOfStreamError } from './Errors.js';
2
+ export { StreamReader } from './StreamReader.js';
3
+ export { WebStreamByobReader } from './WebStreamByobReader.js';
4
+ export { WebStreamDefaultReader } from './WebStreamDefaultReader.js';
5
+ export type { IStreamReader } from './AbstractStreamReader.js';
6
+ export { type AnyWebByteStream, makeWebStreamReader } from './WebStreamReaderFactory.js';
@@ -0,0 +1,5 @@
1
+ export { AbortError, EndOfStreamError } from './Errors.js';
2
+ export { StreamReader } from './StreamReader.js';
3
+ export { WebStreamByobReader } from './WebStreamByobReader.js';
4
+ export { WebStreamDefaultReader } from './WebStreamDefaultReader.js';
5
+ export { makeWebStreamReader } from './WebStreamReaderFactory.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strtok3",
3
- "version": "10.2.2",
3
+ "version": "10.3.1",
4
4
  "description": "A promise based streaming tokenizer",
5
5
  "author": {
6
6
  "name": "Borewit",
@@ -17,9 +17,9 @@
17
17
  "compile": "yarn run compile-src && yarn run compile-test",
18
18
  "build": "yarn run clean && yarn run compile",
19
19
  "eslint": "eslint lib test",
20
- "lint-md": "remark -u preset-lint-recommended .",
21
- "lint-ts": "biome check",
22
- "lint": "yarn run lint-md && yarn run lint-ts",
20
+ "lint:md": "remark -u preset-lint-recommended .",
21
+ "lint:ts": "biome check",
22
+ "lint": "yarn run lint:md && yarn run lint:ts",
23
23
  "fix": "yarn run biome lint --write",
24
24
  "test": "mocha",
25
25
  "bun:test": "bun run --bun test",
@@ -52,27 +52,26 @@
52
52
  "url": "https://github.com/Borewit/strtok3/issues"
53
53
  },
54
54
  "dependencies": {
55
- "@tokenizer/token": "^0.3.0",
56
- "peek-readable": "^7.0.0"
55
+ "@tokenizer/token": "^0.3.0"
57
56
  },
58
57
  "devDependencies": {
59
58
  "@biomejs/biome": "^1.9.4",
60
- "@types/chai": "^5.0.1",
61
- "@types/chai-as-promised": "^8.0.1",
59
+ "@types/chai": "^5.2.2",
60
+ "@types/chai-as-promised": "^8.0.2",
62
61
  "@types/debug": "^4.1.12",
63
62
  "@types/mocha": "^10.0.10",
64
- "@types/node": "^22.13.8",
63
+ "@types/node": "^22.15.21",
65
64
  "c8": "^10.1.3",
66
65
  "chai": "^5.2.0",
67
66
  "chai-as-promised": "^8.0.1",
68
67
  "del-cli": "^6.0.0",
69
- "mocha": "^11.1.0",
68
+ "mocha": "^11.5.0",
70
69
  "node-readable-to-web-readable-stream": "^0.4.2",
71
70
  "remark-cli": "^12.0.1",
72
71
  "remark-preset-lint-recommended": "^7.0.1",
73
72
  "token-types": "^6.0.0",
74
73
  "ts-node": "^10.9.2",
75
- "typescript": "^5.8.2",
74
+ "typescript": "^5.8.3",
76
75
  "uint8array-extras": "^1.4.0"
77
76
  },
78
77
  "keywords": [
@@ -89,5 +88,5 @@
89
88
  "stream",
90
89
  "streaming"
91
90
  ],
92
- "packageManager": "yarn@4.6.0"
91
+ "packageManager": "yarn@4.9.1"
93
92
  }