@yume-chan/stream-extra 0.0.24 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/LICENSE +1 -1
  3. package/esm/buffered-transform.d.ts +3 -3
  4. package/esm/buffered-transform.d.ts.map +1 -1
  5. package/esm/buffered-transform.js +14 -8
  6. package/esm/buffered-transform.js.map +1 -1
  7. package/esm/buffered.d.ts +3 -6
  8. package/esm/buffered.d.ts.map +1 -1
  9. package/esm/buffered.js +87 -75
  10. package/esm/buffered.js.map +1 -1
  11. package/esm/concat.js +2 -2
  12. package/esm/concat.js.map +1 -1
  13. package/esm/consumable.d.ts +15 -10
  14. package/esm/consumable.d.ts.map +1 -1
  15. package/esm/consumable.js +82 -86
  16. package/esm/consumable.js.map +1 -1
  17. package/esm/duplex.d.ts +2 -2
  18. package/esm/duplex.d.ts.map +1 -1
  19. package/esm/duplex.js +2 -6
  20. package/esm/duplex.js.map +1 -1
  21. package/esm/index.d.ts +1 -0
  22. package/esm/index.d.ts.map +1 -1
  23. package/esm/index.js +1 -0
  24. package/esm/index.js.map +1 -1
  25. package/esm/maybe-consumable-ns.d.ts +16 -0
  26. package/esm/maybe-consumable-ns.d.ts.map +1 -0
  27. package/esm/maybe-consumable-ns.js +44 -0
  28. package/esm/maybe-consumable-ns.js.map +1 -0
  29. package/esm/maybe-consumable.d.ts +2 -19
  30. package/esm/maybe-consumable.d.ts.map +1 -1
  31. package/esm/maybe-consumable.js +1 -61
  32. package/esm/maybe-consumable.js.map +1 -1
  33. package/esm/push-readable.d.ts +16 -2
  34. package/esm/push-readable.d.ts.map +1 -1
  35. package/esm/push-readable.js +176 -17
  36. package/esm/push-readable.js.map +1 -1
  37. package/esm/split-string.d.ts.map +1 -1
  38. package/esm/split-string.js +19 -14
  39. package/esm/split-string.js.map +1 -1
  40. package/esm/stream.d.ts +5 -5
  41. package/esm/stream.d.ts.map +1 -1
  42. package/esm/stream.js +54 -5
  43. package/esm/stream.js.map +1 -1
  44. package/esm/struct-deserialize.d.ts +3 -4
  45. package/esm/struct-deserialize.d.ts.map +1 -1
  46. package/esm/struct-deserialize.js.map +1 -1
  47. package/esm/struct-serialize.d.ts +2 -2
  48. package/esm/struct-serialize.d.ts.map +1 -1
  49. package/esm/struct-serialize.js.map +1 -1
  50. package/esm/task.d.ts.map +1 -1
  51. package/esm/task.js +2 -2
  52. package/esm/task.js.map +1 -1
  53. package/esm/try-close.d.ts +10 -0
  54. package/esm/try-close.d.ts.map +1 -0
  55. package/esm/try-close.js +19 -0
  56. package/esm/try-close.js.map +1 -0
  57. package/esm/types.d.ts +3 -3
  58. package/esm/types.d.ts.map +1 -1
  59. package/esm/types.js.map +1 -1
  60. package/esm/wrap-readable.d.ts +5 -4
  61. package/esm/wrap-readable.d.ts.map +1 -1
  62. package/esm/wrap-readable.js +14 -9
  63. package/esm/wrap-readable.js.map +1 -1
  64. package/esm/wrap-writable.d.ts +2 -2
  65. package/esm/wrap-writable.d.ts.map +1 -1
  66. package/esm/wrap-writable.js +4 -6
  67. package/esm/wrap-writable.js.map +1 -1
  68. package/package.json +11 -13
  69. package/src/buffered-transform.ts +21 -11
  70. package/src/buffered.ts +107 -83
  71. package/src/concat.ts +2 -2
  72. package/src/consumable.ts +117 -112
  73. package/src/duplex.ts +4 -7
  74. package/src/index.ts +1 -0
  75. package/src/maybe-consumable-ns.ts +75 -0
  76. package/src/maybe-consumable.ts +2 -98
  77. package/src/push-readable.ts +213 -19
  78. package/src/split-string.ts +22 -21
  79. package/src/stream.ts +68 -8
  80. package/src/struct-deserialize.ts +3 -6
  81. package/src/struct-serialize.ts +3 -3
  82. package/src/task.ts +2 -2
  83. package/src/try-close.ts +44 -0
  84. package/src/types.ts +3 -2
  85. package/src/wrap-readable.ts +20 -14
  86. package/src/wrap-writable.ts +6 -9
  87. package/tsconfig.build.tsbuildinfo +1 -1
  88. package/CHANGELOG.json +0 -104
package/src/consumable.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { PromiseResolver } from "@yume-chan/async";
1
+ import { PromiseResolver, isPromiseLike } from "@yume-chan/async";
2
2
 
3
3
  import type {
4
4
  QueuingStrategy,
@@ -12,11 +12,123 @@ import {
12
12
  import type { Task } from "./task.js";
13
13
  import { createTask } from "./task.js";
14
14
 
15
- function isPromiseLike(value: unknown): value is PromiseLike<unknown> {
16
- return typeof value === "object" && value !== null && "then" in value;
15
+ // Workaround https://github.com/evanw/esbuild/issues/3923
16
+ class WritableStream<in T> extends NativeWritableStream<Consumable<T>> {
17
+ static async write<T>(
18
+ writer: WritableStreamDefaultWriter<Consumable<T>>,
19
+ value: T,
20
+ ) {
21
+ const consumable = new Consumable(value);
22
+ await writer.write(consumable);
23
+ await consumable.consumed;
24
+ }
25
+
26
+ constructor(
27
+ sink: Consumable.WritableStreamSink<T>,
28
+ strategy?: QueuingStrategy<T>,
29
+ ) {
30
+ let wrappedStrategy: QueuingStrategy<Consumable<T>> | undefined;
31
+ if (strategy) {
32
+ wrappedStrategy = {};
33
+ if ("highWaterMark" in strategy) {
34
+ wrappedStrategy.highWaterMark = strategy.highWaterMark;
35
+ }
36
+ if ("size" in strategy) {
37
+ wrappedStrategy.size = (chunk) => {
38
+ return strategy.size!(
39
+ chunk instanceof Consumable ? chunk.value : chunk,
40
+ );
41
+ };
42
+ }
43
+ }
44
+
45
+ super(
46
+ {
47
+ start(controller) {
48
+ return sink.start?.(controller);
49
+ },
50
+ async write(chunk, controller) {
51
+ await chunk.tryConsume((chunk) =>
52
+ sink.write?.(chunk, controller),
53
+ );
54
+ },
55
+ abort(reason) {
56
+ return sink.abort?.(reason);
57
+ },
58
+ close() {
59
+ return sink.close?.();
60
+ },
61
+ },
62
+ wrappedStrategy,
63
+ );
64
+ }
65
+ }
66
+
67
+ class ReadableStream<T> extends NativeReadableStream<Consumable<T>> {
68
+ static async enqueue<T>(
69
+ controller: { enqueue: (chunk: Consumable<T>) => void },
70
+ chunk: T,
71
+ ) {
72
+ const output = new Consumable(chunk);
73
+ controller.enqueue(output);
74
+ await output.consumed;
75
+ }
76
+
77
+ constructor(
78
+ source: Consumable.ReadableStreamSource<T>,
79
+ strategy?: QueuingStrategy<T>,
80
+ ) {
81
+ let wrappedController:
82
+ | Consumable.ReadableStreamController<T>
83
+ | undefined;
84
+
85
+ let wrappedStrategy: QueuingStrategy<Consumable<T>> | undefined;
86
+ if (strategy) {
87
+ wrappedStrategy = {};
88
+ if ("highWaterMark" in strategy) {
89
+ wrappedStrategy.highWaterMark = strategy.highWaterMark;
90
+ }
91
+ if ("size" in strategy) {
92
+ wrappedStrategy.size = (chunk) => {
93
+ return strategy.size!(chunk.value);
94
+ };
95
+ }
96
+ }
97
+
98
+ super(
99
+ {
100
+ async start(controller) {
101
+ wrappedController = {
102
+ async enqueue(chunk) {
103
+ await ReadableStream.enqueue(controller, chunk);
104
+ },
105
+ close() {
106
+ controller.close();
107
+ },
108
+ error(reason) {
109
+ controller.error(reason);
110
+ },
111
+ };
112
+
113
+ await source.start?.(wrappedController);
114
+ },
115
+ async pull() {
116
+ await source.pull?.(wrappedController!);
117
+ },
118
+ async cancel(reason) {
119
+ await source.cancel?.(reason);
120
+ },
121
+ },
122
+ wrappedStrategy,
123
+ );
124
+ }
17
125
  }
18
126
 
19
127
  export class Consumable<T> {
128
+ static readonly WritableStream = WritableStream;
129
+
130
+ static readonly ReadableStream = ReadableStream;
131
+
20
132
  readonly #task: Task;
21
133
  readonly #resolver: PromiseResolver<void>;
22
134
 
@@ -76,58 +188,7 @@ export namespace Consumable {
76
188
  close?(): void | PromiseLike<void>;
77
189
  }
78
190
 
79
- export class WritableStream<in T> extends NativeWritableStream<
80
- Consumable<T>
81
- > {
82
- static async write<T>(
83
- writer: WritableStreamDefaultWriter<Consumable<T>>,
84
- value: T,
85
- ) {
86
- const consumable = new Consumable(value);
87
- await writer.write(consumable);
88
- await consumable.consumed;
89
- }
90
-
91
- constructor(
92
- sink: WritableStreamSink<T>,
93
- strategy?: QueuingStrategy<T>,
94
- ) {
95
- let wrappedStrategy: QueuingStrategy<Consumable<T>> | undefined;
96
- if (strategy) {
97
- wrappedStrategy = {};
98
- if ("highWaterMark" in strategy) {
99
- wrappedStrategy.highWaterMark = strategy.highWaterMark;
100
- }
101
- if ("size" in strategy) {
102
- wrappedStrategy.size = (chunk) => {
103
- return strategy.size!(
104
- chunk instanceof Consumable ? chunk.value : chunk,
105
- );
106
- };
107
- }
108
- }
109
-
110
- super(
111
- {
112
- start(controller) {
113
- return sink.start?.(controller);
114
- },
115
- async write(chunk, controller) {
116
- await chunk.tryConsume((chunk) =>
117
- sink.write?.(chunk, controller),
118
- );
119
- },
120
- abort(reason) {
121
- return sink.abort?.(reason);
122
- },
123
- close() {
124
- return sink.close?.();
125
- },
126
- },
127
- wrappedStrategy,
128
- );
129
- }
130
- }
191
+ export type WritableStream<in T> = typeof Consumable.WritableStream<T>;
131
192
 
132
193
  export interface ReadableStreamController<T> {
133
194
  enqueue(chunk: T): Promise<void>;
@@ -145,61 +206,5 @@ export namespace Consumable {
145
206
  cancel?(reason: unknown): void | PromiseLike<void>;
146
207
  }
147
208
 
148
- export class ReadableStream<T> extends NativeReadableStream<Consumable<T>> {
149
- static async enqueue<T>(
150
- controller: { enqueue: (chunk: Consumable<T>) => void },
151
- chunk: T,
152
- ) {
153
- const output = new Consumable(chunk);
154
- controller.enqueue(output);
155
- await output.consumed;
156
- }
157
-
158
- constructor(
159
- source: ReadableStreamSource<T>,
160
- strategy?: QueuingStrategy<T>,
161
- ) {
162
- let wrappedController: ReadableStreamController<T> | undefined;
163
-
164
- let wrappedStrategy: QueuingStrategy<Consumable<T>> | undefined;
165
- if (strategy) {
166
- wrappedStrategy = {};
167
- if ("highWaterMark" in strategy) {
168
- wrappedStrategy.highWaterMark = strategy.highWaterMark;
169
- }
170
- if ("size" in strategy) {
171
- wrappedStrategy.size = (chunk) => {
172
- return strategy.size!(chunk.value);
173
- };
174
- }
175
- }
176
-
177
- super(
178
- {
179
- async start(controller) {
180
- wrappedController = {
181
- async enqueue(chunk) {
182
- await ReadableStream.enqueue(controller, chunk);
183
- },
184
- close() {
185
- controller.close();
186
- },
187
- error(reason) {
188
- controller.error(reason);
189
- },
190
- };
191
-
192
- await source.start?.(wrappedController);
193
- },
194
- async pull() {
195
- await source.pull?.(wrappedController!);
196
- },
197
- async cancel(reason) {
198
- await source.cancel?.(reason);
199
- },
200
- },
201
- wrappedStrategy,
202
- );
203
- }
204
- }
209
+ export type ReadableStream<T> = typeof Consumable.ReadableStream<T>;
205
210
  }
package/src/duplex.ts CHANGED
@@ -1,5 +1,5 @@
1
+ import type { MaybePromiseLike } from "@yume-chan/async";
1
2
  import { PromiseResolver } from "@yume-chan/async";
2
- import type { ValueOrPromise } from "@yume-chan/struct";
3
3
 
4
4
  import type {
5
5
  QueuingStrategy,
@@ -8,6 +8,7 @@ import type {
8
8
  WritableStreamDefaultWriter,
9
9
  } from "./stream.js";
10
10
  import { WritableStream } from "./stream.js";
11
+ import { tryClose } from "./try-close.js";
11
12
  import { WrapReadableStream } from "./wrap-readable.js";
12
13
 
13
14
  const NOOP = () => {
@@ -27,7 +28,7 @@ export interface DuplexStreamFactoryOptions {
27
28
  * `DuplexStreamFactory#dispose` yourself, you can return `false`
28
29
  * (or a `Promise` that resolves to `false`) to disable the automatic call.
29
30
  */
30
- close?: (() => ValueOrPromise<boolean | void>) | undefined;
31
+ close?: (() => MaybePromiseLike<boolean | void>) | undefined;
31
32
 
32
33
  /**
33
34
  * Callback when any `ReadableStream` is closed (the other peer doesn't produce any more data),
@@ -134,11 +135,7 @@ export class DuplexStreamFactory<R, W> {
134
135
  this.#closed.resolve();
135
136
 
136
137
  for (const controller of this.#readableControllers) {
137
- try {
138
- controller.close();
139
- } catch {
140
- // ignore
141
- }
138
+ tryClose(controller);
142
139
  }
143
140
 
144
141
  await this.#options.dispose?.();
package/src/index.ts CHANGED
@@ -14,5 +14,6 @@ export * from "./stream.js";
14
14
  export * from "./struct-deserialize.js";
15
15
  export * from "./struct-serialize.js";
16
16
  export * from "./task.js";
17
+ export * from "./try-close.js";
17
18
  export * from "./wrap-readable.js";
18
19
  export * from "./wrap-writable.js";
@@ -0,0 +1,75 @@
1
+ import { Consumable } from "./consumable.js";
2
+ import type { MaybeConsumable } from "./maybe-consumable.js";
3
+ import type {
4
+ QueuingStrategy,
5
+ WritableStreamDefaultController,
6
+ } from "./stream.js";
7
+ import { WritableStream as NativeWritableStream } from "./stream.js";
8
+
9
+ export function getValue<T>(value: MaybeConsumable<T>): T {
10
+ return value instanceof Consumable ? value.value : value;
11
+ }
12
+
13
+ export function tryConsume<T, R>(
14
+ value: T,
15
+ callback: (value: T extends Consumable<infer U> ? U : T) => R,
16
+ ): R {
17
+ if (value instanceof Consumable) {
18
+ return value.tryConsume(callback);
19
+ } else {
20
+ return callback(value as never);
21
+ }
22
+ }
23
+
24
+ export interface WritableStreamSink<in T> {
25
+ start?(
26
+ controller: WritableStreamDefaultController,
27
+ ): void | PromiseLike<void>;
28
+ write?(
29
+ chunk: T,
30
+ controller: WritableStreamDefaultController,
31
+ ): void | PromiseLike<void>;
32
+ abort?(reason: unknown): void | PromiseLike<void>;
33
+ close?(): void | PromiseLike<void>;
34
+ }
35
+
36
+ export class WritableStream<in T> extends NativeWritableStream<
37
+ MaybeConsumable<T>
38
+ > {
39
+ constructor(sink: WritableStreamSink<T>, strategy?: QueuingStrategy<T>) {
40
+ let wrappedStrategy: QueuingStrategy<MaybeConsumable<T>> | undefined;
41
+ if (strategy) {
42
+ wrappedStrategy = {};
43
+ if ("highWaterMark" in strategy) {
44
+ wrappedStrategy.highWaterMark = strategy.highWaterMark;
45
+ }
46
+ if ("size" in strategy) {
47
+ wrappedStrategy.size = (chunk) => {
48
+ return strategy.size!(
49
+ chunk instanceof Consumable ? chunk.value : chunk,
50
+ );
51
+ };
52
+ }
53
+ }
54
+
55
+ super(
56
+ {
57
+ start(controller) {
58
+ return sink.start?.(controller);
59
+ },
60
+ async write(chunk, controller) {
61
+ await tryConsume(chunk, (chunk) =>
62
+ sink.write?.(chunk as T, controller),
63
+ );
64
+ },
65
+ abort(reason) {
66
+ return sink.abort?.(reason);
67
+ },
68
+ close() {
69
+ return sink.close?.();
70
+ },
71
+ },
72
+ wrappedStrategy,
73
+ );
74
+ }
75
+ }
@@ -1,101 +1,5 @@
1
- import { Consumable } from "./consumable.js";
2
- import type {
3
- QueuingStrategy,
4
- WritableStreamDefaultController,
5
- } from "./stream.js";
6
- import {
7
- WritableStream as NativeWritableStream,
8
- TransformStream,
9
- } from "./stream.js";
1
+ import type { Consumable } from "./consumable.js";
10
2
 
11
3
  export type MaybeConsumable<T> = T | Consumable<T>;
12
4
 
13
- export namespace MaybeConsumable {
14
- export function getValue<T>(value: MaybeConsumable<T>): T {
15
- return value instanceof Consumable ? value.value : value;
16
- }
17
-
18
- export function tryConsume<T, R>(
19
- value: T,
20
- callback: (value: T extends Consumable<infer U> ? U : T) => R,
21
- ): R {
22
- if (value instanceof Consumable) {
23
- return value.tryConsume(callback);
24
- } else {
25
- return callback(value as never);
26
- }
27
- }
28
-
29
- export class UnwrapStream<T> extends TransformStream<
30
- MaybeConsumable<T>,
31
- T
32
- > {
33
- constructor() {
34
- super({
35
- transform(chunk, controller) {
36
- MaybeConsumable.tryConsume(chunk, (chunk) => {
37
- controller.enqueue(chunk as T);
38
- });
39
- },
40
- });
41
- }
42
- }
43
-
44
- export interface WritableStreamSink<in T> {
45
- start?(
46
- controller: WritableStreamDefaultController,
47
- ): void | PromiseLike<void>;
48
- write?(
49
- chunk: T,
50
- controller: WritableStreamDefaultController,
51
- ): void | PromiseLike<void>;
52
- abort?(reason: unknown): void | PromiseLike<void>;
53
- close?(): void | PromiseLike<void>;
54
- }
55
-
56
- export class WritableStream<in T> extends NativeWritableStream<
57
- MaybeConsumable<T>
58
- > {
59
- constructor(
60
- sink: WritableStreamSink<T>,
61
- strategy?: QueuingStrategy<T>,
62
- ) {
63
- let wrappedStrategy:
64
- | QueuingStrategy<MaybeConsumable<T>>
65
- | undefined;
66
- if (strategy) {
67
- wrappedStrategy = {};
68
- if ("highWaterMark" in strategy) {
69
- wrappedStrategy.highWaterMark = strategy.highWaterMark;
70
- }
71
- if ("size" in strategy) {
72
- wrappedStrategy.size = (chunk) => {
73
- return strategy.size!(
74
- chunk instanceof Consumable ? chunk.value : chunk,
75
- );
76
- };
77
- }
78
- }
79
-
80
- super(
81
- {
82
- start(controller) {
83
- return sink.start?.(controller);
84
- },
85
- async write(chunk, controller) {
86
- await MaybeConsumable.tryConsume(chunk, (chunk) =>
87
- sink.write?.(chunk as T, controller),
88
- );
89
- },
90
- abort(reason) {
91
- return sink.abort?.(reason);
92
- },
93
- close() {
94
- return sink.close?.();
95
- },
96
- },
97
- wrappedStrategy,
98
- );
99
- }
100
- }
101
- }
5
+ export * as MaybeConsumable from "./maybe-consumable-ns.js";