@yume-chan/stream-extra 0.0.19 → 0.0.21

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.
Files changed (79) hide show
  1. package/CHANGELOG.json +60 -33
  2. package/CHANGELOG.md +17 -1
  3. package/esm/buffered-transform.d.ts +1 -2
  4. package/esm/buffered-transform.d.ts.map +1 -1
  5. package/esm/buffered-transform.js +10 -9
  6. package/esm/buffered-transform.js.map +1 -1
  7. package/esm/buffered.d.ts +4 -11
  8. package/esm/buffered.d.ts.map +1 -1
  9. package/esm/buffered.js +40 -36
  10. package/esm/buffered.js.map +1 -1
  11. package/esm/concat.d.ts +35 -0
  12. package/esm/concat.d.ts.map +1 -0
  13. package/esm/concat.js +128 -0
  14. package/esm/concat.js.map +1 -0
  15. package/esm/consumable.d.ts +1 -2
  16. package/esm/consumable.d.ts.map +1 -1
  17. package/esm/consumable.js +9 -9
  18. package/esm/consumable.js.map +1 -1
  19. package/esm/distribution.d.ts +1 -4
  20. package/esm/distribution.d.ts.map +1 -1
  21. package/esm/distribution.js +29 -29
  22. package/esm/distribution.js.map +1 -1
  23. package/esm/duplex.d.ts +1 -5
  24. package/esm/duplex.d.ts.map +1 -1
  25. package/esm/duplex.js +21 -19
  26. package/esm/duplex.js.map +1 -1
  27. package/esm/index.d.ts +1 -1
  28. package/esm/index.d.ts.map +1 -1
  29. package/esm/index.js +1 -1
  30. package/esm/index.js.map +1 -1
  31. package/esm/push-readable.d.ts.map +1 -1
  32. package/esm/push-readable.js +11 -6
  33. package/esm/push-readable.js.map +1 -1
  34. package/esm/split-string.d.ts.map +1 -1
  35. package/esm/split-string.js.map +1 -1
  36. package/esm/stream.js +0 -14
  37. package/esm/stream.js.map +1 -1
  38. package/esm/struct-deserialize.d.ts.map +1 -1
  39. package/esm/struct-deserialize.js.map +1 -1
  40. package/esm/wrap-readable.d.ts +1 -1
  41. package/esm/wrap-readable.d.ts.map +1 -1
  42. package/esm/wrap-readable.js +4 -4
  43. package/esm/wrap-readable.js.map +1 -1
  44. package/esm/wrap-writable.d.ts +1 -1
  45. package/esm/wrap-writable.d.ts.map +1 -1
  46. package/esm/wrap-writable.js +5 -5
  47. package/esm/wrap-writable.js.map +1 -1
  48. package/package.json +8 -8
  49. package/src/buffered-transform.ts +14 -16
  50. package/src/buffered.ts +48 -42
  51. package/src/concat.ts +160 -0
  52. package/src/consumable.ts +38 -37
  53. package/src/decode-utf8.ts +1 -1
  54. package/src/distribution.ts +35 -35
  55. package/src/duplex.ts +28 -26
  56. package/src/index.ts +1 -1
  57. package/src/pipe-from.ts +1 -1
  58. package/src/push-readable.ts +15 -11
  59. package/src/split-string.ts +2 -2
  60. package/src/stream.ts +0 -13
  61. package/src/struct-deserialize.ts +2 -2
  62. package/src/struct-serialize.ts +1 -1
  63. package/src/wrap-readable.ts +10 -10
  64. package/src/wrap-writable.ts +10 -10
  65. package/tsconfig.build.json +6 -1
  66. package/tsconfig.build.tsbuildinfo +1 -1
  67. package/esm/chunk.d.ts +0 -8
  68. package/esm/chunk.d.ts.map +0 -1
  69. package/esm/chunk.js +0 -56
  70. package/esm/chunk.js.map +0 -1
  71. package/esm/gather-string.d.ts +0 -7
  72. package/esm/gather-string.d.ts.map +0 -1
  73. package/esm/gather-string.js +0 -16
  74. package/esm/gather-string.js.map +0 -1
  75. package/esm/trace.d.ts +0 -16
  76. package/esm/trace.d.ts.map +0 -1
  77. package/esm/trace.js +0 -131
  78. package/esm/trace.js.map +0 -1
  79. package/src/gather-string.ts +0 -17
@@ -4,16 +4,16 @@ import { ConsumableTransformStream } from "./consumable.js";
4
4
  * Splits or combines buffers to specified size.
5
5
  */
6
6
  export class BufferCombiner {
7
- private _capacity: number;
8
- private readonly _buffer: Uint8Array;
9
- private _offset: number;
10
- private _available: number;
7
+ #capacity: number;
8
+ readonly #buffer: Uint8Array;
9
+ #offset: number;
10
+ #available: number;
11
11
 
12
- public constructor(size: number) {
13
- this._capacity = size;
14
- this._buffer = new Uint8Array(size);
15
- this._offset = 0;
16
- this._available = size;
12
+ constructor(size: number) {
13
+ this.#capacity = size;
14
+ this.#buffer = new Uint8Array(size);
15
+ this.#offset = 0;
16
+ this.#available = size;
17
17
  }
18
18
 
19
19
  /**
@@ -23,56 +23,56 @@ export class BufferCombiner {
23
23
  * A generator that yields buffers of specified size.
24
24
  * It may yield the same buffer multiple times, consume the data before calling `next`.
25
25
  */
26
- public *push(data: Uint8Array): Generator<Uint8Array, void, void> {
26
+ *push(data: Uint8Array): Generator<Uint8Array, void, void> {
27
27
  let offset = 0;
28
28
  let available = data.byteLength;
29
29
 
30
- if (this._offset !== 0) {
31
- if (available >= this._available) {
32
- this._buffer.set(
33
- data.subarray(0, this._available),
34
- this._offset
30
+ if (this.#offset !== 0) {
31
+ if (available >= this.#available) {
32
+ this.#buffer.set(
33
+ data.subarray(0, this.#available),
34
+ this.#offset,
35
35
  );
36
- offset += this._available;
37
- available -= this._available;
36
+ offset += this.#available;
37
+ available -= this.#available;
38
38
 
39
- yield this._buffer;
40
- this._offset = 0;
41
- this._available = this._capacity;
39
+ yield this.#buffer;
40
+ this.#offset = 0;
41
+ this.#available = this.#capacity;
42
42
 
43
43
  if (available === 0) {
44
44
  return;
45
45
  }
46
46
  } else {
47
- this._buffer.set(data, this._offset);
48
- this._offset += available;
49
- this._available -= available;
47
+ this.#buffer.set(data, this.#offset);
48
+ this.#offset += available;
49
+ this.#available -= available;
50
50
  return;
51
51
  }
52
52
  }
53
53
 
54
- while (available >= this._capacity) {
55
- const end = offset + this._capacity;
54
+ while (available >= this.#capacity) {
55
+ const end = offset + this.#capacity;
56
56
  yield data.subarray(offset, end);
57
57
  offset = end;
58
- available -= this._capacity;
58
+ available -= this.#capacity;
59
59
  }
60
60
 
61
61
  if (available > 0) {
62
- this._buffer.set(data.subarray(offset), this._offset);
63
- this._offset += available;
64
- this._available -= available;
62
+ this.#buffer.set(data.subarray(offset), this.#offset);
63
+ this.#offset += available;
64
+ this.#available -= available;
65
65
  }
66
66
  }
67
67
 
68
- public flush(): Uint8Array | undefined {
69
- if (this._offset === 0) {
68
+ flush(): Uint8Array | undefined {
69
+ if (this.#offset === 0) {
70
70
  return undefined;
71
71
  }
72
72
 
73
- const output = this._buffer.subarray(0, this._offset);
74
- this._offset = 0;
75
- this._available = this._capacity;
73
+ const output = this.#buffer.subarray(0, this.#offset);
74
+ this.#offset = 0;
75
+ this.#available = this.#capacity;
76
76
  return output;
77
77
  }
78
78
  }
@@ -81,7 +81,7 @@ export class DistributionStream extends ConsumableTransformStream<
81
81
  Uint8Array,
82
82
  Uint8Array
83
83
  > {
84
- public constructor(size: number, combine = false) {
84
+ constructor(size: number, combine = false) {
85
85
  const combiner = combine ? new BufferCombiner(size) : undefined;
86
86
  super({
87
87
  async transform(chunk, controller) {
package/src/duplex.ts CHANGED
@@ -46,29 +46,29 @@ export interface DuplexStreamFactoryOptions {
46
46
  * when any of them is closed, all other streams will be closed as well.
47
47
  */
48
48
  export class DuplexStreamFactory<R, W> {
49
- private readableControllers: ReadableStreamDefaultController<R>[] = [];
50
- private writers: WritableStreamDefaultWriter<W>[] = [];
49
+ #readableControllers: ReadableStreamDefaultController<R>[] = [];
50
+ #writers: WritableStreamDefaultWriter<W>[] = [];
51
51
 
52
- private _writableClosed = false;
53
- public get writableClosed() {
54
- return this._writableClosed;
52
+ #writableClosed = false;
53
+ get writableClosed() {
54
+ return this.#writableClosed;
55
55
  }
56
56
 
57
- private _closed = new PromiseResolver<void>();
58
- public get closed() {
59
- return this._closed.promise;
57
+ #closed = new PromiseResolver<void>();
58
+ get closed() {
59
+ return this.#closed.promise;
60
60
  }
61
61
 
62
- private options: DuplexStreamFactoryOptions;
62
+ readonly #options: DuplexStreamFactoryOptions;
63
63
 
64
- public constructor(options?: DuplexStreamFactoryOptions) {
65
- this.options = options ?? {};
64
+ constructor(options?: DuplexStreamFactoryOptions) {
65
+ this.#options = options ?? {};
66
66
  }
67
67
 
68
- public wrapReadable(readable: ReadableStream<R>): WrapReadableStream<R> {
68
+ wrapReadable(readable: ReadableStream<R>): WrapReadableStream<R> {
69
69
  return new WrapReadableStream<R>({
70
70
  start: (controller) => {
71
- this.readableControllers.push(controller);
71
+ this.#readableControllers.push(controller);
72
72
  return readable;
73
73
  },
74
74
  cancel: async () => {
@@ -82,9 +82,9 @@ export class DuplexStreamFactory<R, W> {
82
82
  });
83
83
  }
84
84
 
85
- public createWritable(stream: WritableStream<W>): WritableStream<W> {
85
+ createWritable(stream: WritableStream<W>): WritableStream<W> {
86
86
  const writer = stream.getWriter();
87
- this.writers.push(writer);
87
+ this.#writers.push(writer);
88
88
 
89
89
  // `WritableStream` has no way to tell if the remote peer has closed the connection.
90
90
  // So it only triggers `close`.
@@ -97,34 +97,36 @@ export class DuplexStreamFactory<R, W> {
97
97
  await this.close();
98
98
  },
99
99
  close: async () => {
100
+ // NOOP: the writer is already closed
100
101
  await writer.close().catch(NOOP);
101
102
  await this.close();
102
103
  },
103
104
  });
104
105
  }
105
106
 
106
- public async close() {
107
- if (this._writableClosed) {
107
+ async close() {
108
+ if (this.#writableClosed) {
108
109
  return;
109
110
  }
110
- this._writableClosed = true;
111
+ this.#writableClosed = true;
111
112
 
112
113
  // Call `close` first, so it can still write data to `WritableStream`s.
113
- if ((await this.options.close?.()) !== false) {
114
+ if ((await this.#options.close?.()) !== false) {
114
115
  // `close` can return `false` to disable automatic `dispose`.
115
116
  await this.dispose();
116
117
  }
117
118
 
118
- for (const writer of this.writers) {
119
- await writer.close().catch(NOOP);
119
+ for (const writer of this.#writers) {
120
+ // NOOP: the writer is already closed
121
+ writer.close().catch(NOOP);
120
122
  }
121
123
  }
122
124
 
123
- public async dispose() {
124
- this._writableClosed = true;
125
- this._closed.resolve();
125
+ async dispose() {
126
+ this.#writableClosed = true;
127
+ this.#closed.resolve();
126
128
 
127
- for (const controller of this.readableControllers) {
129
+ for (const controller of this.#readableControllers) {
128
130
  try {
129
131
  controller.close();
130
132
  } catch {
@@ -132,6 +134,6 @@ export class DuplexStreamFactory<R, W> {
132
134
  }
133
135
  }
134
136
 
135
- await this.options.dispose?.();
137
+ await this.#options.dispose?.();
136
138
  }
137
139
  }
package/src/index.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  export * from "./buffered-transform.js";
2
2
  export * from "./buffered.js";
3
+ export * from "./concat.js";
3
4
  export * from "./consumable.js";
4
5
  export * from "./decode-utf8.js";
5
6
  export * from "./distribution.js";
6
7
  export * from "./duplex.js";
7
- export * from "./gather-string.js";
8
8
  export * from "./inspect.js";
9
9
  export * from "./pipe-from.js";
10
10
  export * from "./push-readable.js";
package/src/pipe-from.ts CHANGED
@@ -12,7 +12,7 @@ import { WritableStream } from "./stream.js";
12
12
  */
13
13
  export function pipeFrom<W, T>(
14
14
  writable: WritableStream<W>,
15
- pair: ReadableWritablePair<W, T>
15
+ pair: ReadableWritablePair<W, T>,
16
16
  ) {
17
17
  const writer = pair.writable.getWriter();
18
18
  const pipe = pair.readable.pipeTo(writable);
@@ -14,7 +14,7 @@ export interface PushReadableStreamController<T> {
14
14
  }
15
15
 
16
16
  export type PushReadableStreamSource<T> = (
17
- controller: PushReadableStreamController<T>
17
+ controller: PushReadableStreamController<T>,
18
18
  ) => void | Promise<void>;
19
19
 
20
20
  export class PushReadableStream<T> extends ReadableStream<T> {
@@ -25,24 +25,24 @@ export class PushReadableStream<T> extends ReadableStream<T> {
25
25
  * when the `Promise` is resolved, and be errored when the `Promise` is rejected.
26
26
  * @param strategy
27
27
  */
28
- public constructor(
28
+ constructor(
29
29
  source: PushReadableStreamSource<T>,
30
- strategy?: QueuingStrategy<T>
30
+ strategy?: QueuingStrategy<T>,
31
31
  ) {
32
32
  let waterMarkLow: PromiseResolver<void> | undefined;
33
- const canceled = new AbortController();
33
+ const abortController = new AbortController();
34
34
 
35
35
  super(
36
36
  {
37
37
  start: (controller) => {
38
38
  const result = source({
39
- abortSignal: canceled.signal,
39
+ abortSignal: abortController.signal,
40
40
  async enqueue(chunk) {
41
- if (canceled.signal.aborted) {
41
+ if (abortController.signal.aborted) {
42
42
  // If the stream is already cancelled,
43
43
  // throw immediately.
44
44
  throw (
45
- canceled.signal.reason ??
45
+ abortController.signal.reason ??
46
46
  new Error("Aborted")
47
47
  );
48
48
  }
@@ -71,11 +71,15 @@ export class PushReadableStream<T> extends ReadableStream<T> {
71
71
  if (result && "then" in result) {
72
72
  result.then(
73
73
  () => {
74
- controller.close();
74
+ try {
75
+ controller.close();
76
+ } catch (e) {
77
+ // controller already closed
78
+ }
75
79
  },
76
80
  (e) => {
77
81
  controller.error(e);
78
- }
82
+ },
79
83
  );
80
84
  }
81
85
  },
@@ -83,11 +87,11 @@ export class PushReadableStream<T> extends ReadableStream<T> {
83
87
  waterMarkLow?.resolve();
84
88
  },
85
89
  cancel: (reason) => {
86
- canceled.abort(reason);
90
+ abortController.abort(reason);
87
91
  waterMarkLow?.reject(reason);
88
92
  },
89
93
  },
90
- strategy
94
+ strategy,
91
95
  );
92
96
  }
93
97
  }
@@ -2,7 +2,7 @@ import { TransformStream } from "./stream.js";
2
2
 
3
3
  function* split(
4
4
  input: string,
5
- separator: string
5
+ separator: string,
6
6
  ): Generator<string, void, void> {
7
7
  let start = 0;
8
8
 
@@ -20,7 +20,7 @@ function* split(
20
20
  }
21
21
 
22
22
  export class SplitStringStream extends TransformStream<string, string> {
23
- public constructor(separator: string) {
23
+ constructor(separator: string) {
24
24
  super({
25
25
  transform(chunk, controller) {
26
26
  for (const part of split(chunk, separator)) {
package/src/stream.ts CHANGED
@@ -45,20 +45,7 @@ export type TransformStream<I = any, O = any> = TransformStreamPolyfill<I, O>;
45
45
  export let TransformStream = TransformStreamPolyfill;
46
46
 
47
47
  if (GLOBAL.ReadableStream && GLOBAL.WritableStream && GLOBAL.TransformStream) {
48
- // Use browser native implementation
49
48
  ReadableStream = GLOBAL.ReadableStream;
50
49
  WritableStream = GLOBAL.WritableStream;
51
50
  TransformStream = GLOBAL.TransformStream;
52
- } else {
53
- // TODO: enable loading Node.js stream implementation when bundler supports Top Level Await
54
- // try {
55
- // // Use Node.js native implementation
56
- // const MODULE_NAME = "node:stream/web";
57
- // const StreamWeb = (await import(MODULE_NAME)) as GlobalExtension;
58
- // ReadableStream = StreamWeb.ReadableStream;
59
- // WritableStream = StreamWeb.WritableStream;
60
- // TransformStream = StreamWeb.TransformStream;
61
- // } catch {
62
- // // ignore
63
- // }
64
51
  }
@@ -4,9 +4,9 @@ import type { StructValueType } from "@yume-chan/struct";
4
4
  import { BufferedTransformStream } from "./buffered-transform.js";
5
5
 
6
6
  export class StructDeserializeStream<
7
- T extends Struct<any, any, any, any>
7
+ T extends Struct<any, any, any, any>,
8
8
  > extends BufferedTransformStream<StructValueType<T>> {
9
- public constructor(struct: T) {
9
+ constructor(struct: T) {
10
10
  super((stream) => {
11
11
  return struct.deserialize(stream);
12
12
  });
@@ -3,7 +3,7 @@ import type Struct from "@yume-chan/struct";
3
3
  import { TransformStream } from "./stream.js";
4
4
 
5
5
  export class StructSerializeStream<
6
- T extends Struct<any, any, any, any>
6
+ T extends Struct<any, any, any, any>,
7
7
  > extends TransformStream<T["TInit"], Uint8Array> {
8
8
  constructor(struct: T) {
9
9
  super({
@@ -7,7 +7,7 @@ import type {
7
7
  import { ReadableStream } from "./stream.js";
8
8
 
9
9
  export type WrapReadableStreamStart<T> = (
10
- controller: ReadableStreamDefaultController<T>
10
+ controller: ReadableStreamDefaultController<T>,
11
11
  ) => ValueOrPromise<ReadableStream<T>>;
12
12
 
13
13
  export interface ReadableStreamWrapper<T> {
@@ -21,7 +21,7 @@ function getWrappedReadableStream<T>(
21
21
  | ReadableStream<T>
22
22
  | WrapReadableStreamStart<T>
23
23
  | ReadableStreamWrapper<T>,
24
- controller: ReadableStreamDefaultController<T>
24
+ controller: ReadableStreamDefaultController<T>,
25
25
  ) {
26
26
  if ("start" in wrapper) {
27
27
  return wrapper.start(controller);
@@ -42,15 +42,15 @@ function getWrappedReadableStream<T>(
42
42
  * 3. Convert native `ReadableStream`s to polyfilled ones so they can `pipe` between.
43
43
  */
44
44
  export class WrapReadableStream<T> extends ReadableStream<T> {
45
- public readable!: ReadableStream<T>;
45
+ readable!: ReadableStream<T>;
46
46
 
47
- private reader!: ReadableStreamDefaultReader<T>;
47
+ #reader!: ReadableStreamDefaultReader<T>;
48
48
 
49
- public constructor(
49
+ constructor(
50
50
  wrapper:
51
51
  | ReadableStream<T>
52
52
  | WrapReadableStreamStart<T>
53
- | ReadableStreamWrapper<T>
53
+ | ReadableStreamWrapper<T>,
54
54
  ) {
55
55
  super({
56
56
  start: async (controller) => {
@@ -62,18 +62,18 @@ export class WrapReadableStream<T> extends ReadableStream<T> {
62
62
 
63
63
  this.readable = await getWrappedReadableStream(
64
64
  wrapper,
65
- controller
65
+ controller,
66
66
  );
67
- this.reader = this.readable.getReader();
67
+ this.#reader = this.readable.getReader();
68
68
  },
69
69
  cancel: async (reason) => {
70
- await this.reader.cancel(reason);
70
+ await this.#reader.cancel(reason);
71
71
  if ("cancel" in wrapper) {
72
72
  await wrapper.cancel?.(reason);
73
73
  }
74
74
  },
75
75
  pull: async (controller) => {
76
- const result = await this.reader.read();
76
+ const result = await this.#reader.read();
77
77
  if (result.done) {
78
78
  controller.close();
79
79
  if ("close" in wrapper) {
@@ -16,7 +16,7 @@ async function getWrappedWritableStream<T>(
16
16
  wrapper:
17
17
  | WritableStream<T>
18
18
  | WrapWritableStreamStart<T>
19
- | WritableStreamWrapper<T>
19
+ | WritableStreamWrapper<T>,
20
20
  ) {
21
21
  if ("start" in wrapper) {
22
22
  return await wrapper.start();
@@ -30,15 +30,15 @@ async function getWrappedWritableStream<T>(
30
30
  }
31
31
 
32
32
  export class WrapWritableStream<T> extends WritableStream<T> {
33
- public writable!: WritableStream<T>;
33
+ writable!: WritableStream<T>;
34
34
 
35
- private writer!: WritableStreamDefaultWriter<T>;
35
+ #writer!: WritableStreamDefaultWriter<T>;
36
36
 
37
- public constructor(
37
+ constructor(
38
38
  wrapper:
39
39
  | WritableStream<T>
40
40
  | WrapWritableStreamStart<T>
41
- | WritableStreamWrapper<T>
41
+ | WritableStreamWrapper<T>,
42
42
  ) {
43
43
  super({
44
44
  start: async () => {
@@ -49,13 +49,13 @@ export class WrapWritableStream<T> extends WritableStream<T> {
49
49
  await Promise.resolve();
50
50
 
51
51
  this.writable = await getWrappedWritableStream(wrapper);
52
- this.writer = this.writable.getWriter();
52
+ this.#writer = this.writable.getWriter();
53
53
  },
54
54
  write: async (chunk) => {
55
- await this.writer.write(chunk);
55
+ await this.#writer.write(chunk);
56
56
  },
57
57
  abort: async (reason) => {
58
- await this.writer.abort(reason);
58
+ await this.#writer.abort(reason);
59
59
  if ("close" in wrapper) {
60
60
  await wrapper.close?.();
61
61
  }
@@ -65,7 +65,7 @@ export class WrapWritableStream<T> extends WritableStream<T> {
65
65
  // Usually the inner stream is a logical sub-stream over the outer stream,
66
66
  // closing the outer stream first will make the inner stream incapable of
67
67
  // sending data in its `close` handler.
68
- await this.writer.close();
68
+ await this.#writer.close();
69
69
  if ("close" in wrapper) {
70
70
  await wrapper.close?.();
71
71
  }
@@ -73,7 +73,7 @@ export class WrapWritableStream<T> extends WritableStream<T> {
73
73
  });
74
74
  }
75
75
 
76
- public bePipedThroughFrom<U>(transformer: TransformStream<U, T>) {
76
+ bePipedThroughFrom<U>(transformer: TransformStream<U, T>) {
77
77
  let promise: Promise<void>;
78
78
  return new WrapWritableStream<U>({
79
79
  start: () => {
@@ -1,3 +1,8 @@
1
1
  {
2
- "extends": "./node_modules/@yume-chan/tsconfig/tsconfig.base.json"
2
+ "extends": "./node_modules/@yume-chan/tsconfig/tsconfig.base.json",
3
+ "references": [
4
+ {
5
+ "path": "../struct/tsconfig.build.json"
6
+ }
7
+ ]
3
8
  }