@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.
- package/CHANGELOG.md +29 -1
- package/LICENSE +1 -1
- package/esm/buffered-transform.d.ts +3 -3
- package/esm/buffered-transform.d.ts.map +1 -1
- package/esm/buffered-transform.js +14 -8
- package/esm/buffered-transform.js.map +1 -1
- package/esm/buffered.d.ts +3 -6
- package/esm/buffered.d.ts.map +1 -1
- package/esm/buffered.js +87 -75
- package/esm/buffered.js.map +1 -1
- package/esm/concat.js +2 -2
- package/esm/concat.js.map +1 -1
- package/esm/consumable.d.ts +15 -10
- package/esm/consumable.d.ts.map +1 -1
- package/esm/consumable.js +82 -86
- package/esm/consumable.js.map +1 -1
- package/esm/duplex.d.ts +2 -2
- package/esm/duplex.d.ts.map +1 -1
- package/esm/duplex.js +2 -6
- package/esm/duplex.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/maybe-consumable-ns.d.ts +16 -0
- package/esm/maybe-consumable-ns.d.ts.map +1 -0
- package/esm/maybe-consumable-ns.js +44 -0
- package/esm/maybe-consumable-ns.js.map +1 -0
- package/esm/maybe-consumable.d.ts +2 -19
- package/esm/maybe-consumable.d.ts.map +1 -1
- package/esm/maybe-consumable.js +1 -61
- package/esm/maybe-consumable.js.map +1 -1
- package/esm/push-readable.d.ts +16 -2
- package/esm/push-readable.d.ts.map +1 -1
- package/esm/push-readable.js +176 -17
- package/esm/push-readable.js.map +1 -1
- package/esm/split-string.d.ts.map +1 -1
- package/esm/split-string.js +19 -14
- package/esm/split-string.js.map +1 -1
- package/esm/stream.d.ts +5 -5
- package/esm/stream.d.ts.map +1 -1
- package/esm/stream.js +54 -5
- package/esm/stream.js.map +1 -1
- package/esm/struct-deserialize.d.ts +3 -4
- package/esm/struct-deserialize.d.ts.map +1 -1
- package/esm/struct-deserialize.js.map +1 -1
- package/esm/struct-serialize.d.ts +2 -2
- package/esm/struct-serialize.d.ts.map +1 -1
- package/esm/struct-serialize.js.map +1 -1
- package/esm/task.d.ts.map +1 -1
- package/esm/task.js +2 -2
- package/esm/task.js.map +1 -1
- package/esm/try-close.d.ts +10 -0
- package/esm/try-close.d.ts.map +1 -0
- package/esm/try-close.js +19 -0
- package/esm/try-close.js.map +1 -0
- package/esm/types.d.ts +3 -3
- package/esm/types.d.ts.map +1 -1
- package/esm/types.js.map +1 -1
- package/esm/wrap-readable.d.ts +5 -4
- package/esm/wrap-readable.d.ts.map +1 -1
- package/esm/wrap-readable.js +14 -9
- package/esm/wrap-readable.js.map +1 -1
- package/esm/wrap-writable.d.ts +2 -2
- package/esm/wrap-writable.d.ts.map +1 -1
- package/esm/wrap-writable.js +4 -6
- package/esm/wrap-writable.js.map +1 -1
- package/package.json +11 -13
- package/src/buffered-transform.ts +21 -11
- package/src/buffered.ts +107 -83
- package/src/concat.ts +2 -2
- package/src/consumable.ts +117 -112
- package/src/duplex.ts +4 -7
- package/src/index.ts +1 -0
- package/src/maybe-consumable-ns.ts +75 -0
- package/src/maybe-consumable.ts +2 -98
- package/src/push-readable.ts +213 -19
- package/src/split-string.ts +22 -21
- package/src/stream.ts +68 -8
- package/src/struct-deserialize.ts +3 -6
- package/src/struct-serialize.ts +3 -3
- package/src/task.ts +2 -2
- package/src/try-close.ts +44 -0
- package/src/types.ts +3 -2
- package/src/wrap-readable.ts +20 -14
- package/src/wrap-writable.ts +6 -9
- package/tsconfig.build.tsbuildinfo +1 -1
- package/CHANGELOG.json +0 -104
package/esm/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,4CAA4C;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAi3B5C,OAAO,EAAE,CAAC"}
|
package/esm/wrap-readable.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MaybePromiseLike } from "@yume-chan/async";
|
|
2
2
|
import type { QueuingStrategy, ReadableStreamDefaultController } from "./stream.js";
|
|
3
3
|
import { ReadableStream } from "./stream.js";
|
|
4
|
-
export type WrapReadableStreamStart<T> = (controller: ReadableStreamDefaultController<T>) =>
|
|
4
|
+
export type WrapReadableStreamStart<T> = (controller: ReadableStreamDefaultController<T>) => MaybePromiseLike<ReadableStream<T>>;
|
|
5
5
|
export interface ReadableStreamWrapper<T> {
|
|
6
6
|
start: WrapReadableStreamStart<T>;
|
|
7
|
-
cancel
|
|
8
|
-
close
|
|
7
|
+
cancel?: (reason?: unknown) => MaybePromiseLike<void>;
|
|
8
|
+
close?: () => MaybePromiseLike<void>;
|
|
9
|
+
error?: (reason?: unknown) => MaybePromiseLike<void>;
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
12
|
* This class has multiple usages:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-readable.d.ts","sourceRoot":"","sources":["../src/wrap-readable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"wrap-readable.d.ts","sourceRoot":"","sources":["../src/wrap-readable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,KAAK,EACR,eAAe,EACf,+BAA+B,EAElC,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI,CACrC,UAAU,EAAE,+BAA+B,CAAC,CAAC,CAAC,KAC7C,gBAAgB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzC,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACpC,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACtD,KAAK,CAAC,EAAE,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,gBAAgB,CAAC,IAAI,CAAC,CAAC;CACxD;AAoBD;;;;;;GAMG;AACH,qBAAa,kBAAkB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;;IACxD,QAAQ,EAAG,cAAc,CAAC,CAAC,CAAC,CAAC;gBAKzB,OAAO,EACD,cAAc,CAAC,CAAC,CAAC,GACjB,uBAAuB,CAAC,CAAC,CAAC,GAC1B,qBAAqB,CAAC,CAAC,CAAC,EAC9B,QAAQ,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC;CA2CpC"}
|
package/esm/wrap-readable.js
CHANGED
|
@@ -25,24 +25,29 @@ export class WrapReadableStream extends ReadableStream {
|
|
|
25
25
|
constructor(wrapper, strategy) {
|
|
26
26
|
super({
|
|
27
27
|
start: async (controller) => {
|
|
28
|
-
|
|
29
|
-
// so
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
await Promise.resolve();
|
|
33
|
-
this.readable = await getWrappedReadableStream(wrapper, controller);
|
|
28
|
+
const readable = await getWrappedReadableStream(wrapper, controller);
|
|
29
|
+
// `start` is called in `super()`, so can't use `this` synchronously.
|
|
30
|
+
// but it's fine after the first `await`
|
|
31
|
+
this.readable = readable;
|
|
34
32
|
this.#reader = this.readable.getReader();
|
|
35
33
|
},
|
|
36
34
|
pull: async (controller) => {
|
|
37
|
-
const
|
|
38
|
-
|
|
35
|
+
const { done, value } = await this.#reader
|
|
36
|
+
.read()
|
|
37
|
+
.catch((e) => {
|
|
38
|
+
if ("error" in wrapper) {
|
|
39
|
+
wrapper.error(e);
|
|
40
|
+
}
|
|
41
|
+
throw e;
|
|
42
|
+
});
|
|
43
|
+
if (done) {
|
|
39
44
|
controller.close();
|
|
40
45
|
if ("close" in wrapper) {
|
|
41
46
|
await wrapper.close?.();
|
|
42
47
|
}
|
|
43
48
|
}
|
|
44
49
|
else {
|
|
45
|
-
controller.enqueue(
|
|
50
|
+
controller.enqueue(value);
|
|
46
51
|
}
|
|
47
52
|
},
|
|
48
53
|
cancel: async (reason) => {
|
package/esm/wrap-readable.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-readable.js","sourceRoot":"","sources":["../src/wrap-readable.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"wrap-readable.js","sourceRoot":"","sources":["../src/wrap-readable.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAa7C,SAAS,wBAAwB,CAC7B,OAG8B,EAC9B,UAA8C;IAE9C,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;SAAM,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QACvC,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC;SAAM,CAAC;QACJ,gDAAgD;QAChD,wEAAwE;QACxE,OAAO,OAAO,CAAC;IACnB,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,kBAAsB,SAAQ,cAAiB;IACxD,QAAQ,CAAqB;IAE7B,OAAO,CAAkC;IAEzC,YACI,OAG8B,EAC9B,QAA6B;QAE7B,KAAK,CACD;YACI,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;gBACxB,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAC3C,OAAO,EACP,UAAU,CACb,CAAC;gBACF,qEAAqE;gBACrE,wCAAwC;gBACxC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;gBACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;YAC7C,CAAC;YACD,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;gBACvB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO;qBACrC,IAAI,EAAE;qBACN,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;oBACT,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;wBACrB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACrB,CAAC;oBACD,MAAM,CAAC,CAAC;gBACZ,CAAC,CAAC,CAAC;gBAEP,IAAI,IAAI,EAAE,CAAC;oBACP,UAAU,CAAC,KAAK,EAAE,CAAC;oBACnB,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;wBACrB,MAAM,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;oBAC5B,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACJ,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC9B,CAAC;YACL,CAAC;YACD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;gBACrB,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBAClC,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;oBACtB,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;gBACnC,CAAC;YACL,CAAC;SACJ,EACD,QAAQ,CACX,CAAC;IACN,CAAC;CACJ"}
|
package/esm/wrap-writable.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MaybePromiseLike } from "@yume-chan/async";
|
|
2
2
|
import type { TransformStream } from "./stream.js";
|
|
3
3
|
import { WritableStream } from "./stream.js";
|
|
4
|
-
export type WrapWritableStreamStart<T> = () =>
|
|
4
|
+
export type WrapWritableStreamStart<T> = () => MaybePromiseLike<WritableStream<T>>;
|
|
5
5
|
export interface WritableStreamWrapper<T> {
|
|
6
6
|
start: WrapWritableStreamStart<T>;
|
|
7
7
|
close?(): void | Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-writable.d.ts","sourceRoot":"","sources":["../src/wrap-writable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"wrap-writable.d.ts","sourceRoot":"","sources":["../src/wrap-writable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,KAAK,EAAE,eAAe,EAA+B,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI,MAAM,gBAAgB,CAC3D,cAAc,CAAC,CAAC,CAAC,CACpB,CAAC;AAEF,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACpC,KAAK,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC;IAClC,KAAK,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAmBD,qBAAa,kBAAkB,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;;IACxD,QAAQ,EAAG,cAAc,CAAC,CAAC,CAAC,CAAC;gBAKzB,KAAK,EACC,cAAc,CAAC,CAAC,CAAC,GACjB,uBAAuB,CAAC,CAAC,CAAC,GAC1B,qBAAqB,CAAC,CAAC,CAAC;IAgClC,kBAAkB,CAAC,CAAC,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC;CAY3D"}
|
package/esm/wrap-writable.js
CHANGED
|
@@ -18,12 +18,10 @@ export class WrapWritableStream extends WritableStream {
|
|
|
18
18
|
constructor(start) {
|
|
19
19
|
super({
|
|
20
20
|
start: async () => {
|
|
21
|
-
|
|
22
|
-
// so
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
await Promise.resolve();
|
|
26
|
-
this.writable = await getWrappedWritableStream(start);
|
|
21
|
+
const writable = await getWrappedWritableStream(start);
|
|
22
|
+
// `start` is called in `super()`, so can't use `this` synchronously.
|
|
23
|
+
// but it's fine after the first `await`
|
|
24
|
+
this.writable = writable;
|
|
27
25
|
this.#writer = this.writable.getWriter();
|
|
28
26
|
},
|
|
29
27
|
write: async (chunk) => {
|
package/esm/wrap-writable.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-writable.js","sourceRoot":"","sources":["../src/wrap-writable.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAW7C,KAAK,UAAU,wBAAwB,CACnC,KAG8B;IAE9B,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;QACnB,OAAO,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;IAC/B,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QACrC,OAAO,MAAM,KAAK,EAAE,CAAC;IACzB,CAAC;SAAM,CAAC;QACJ,gDAAgD;QAChD,wEAAwE;QACxE,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAED,MAAM,OAAO,kBAAsB,SAAQ,cAAiB;IACxD,QAAQ,CAAqB;IAE7B,OAAO,CAAkC;IAEzC,YACI,KAG8B;QAE9B,KAAK,CAAC;YACF,KAAK,EAAE,KAAK,IAAI,EAAE;gBACd,
|
|
1
|
+
{"version":3,"file":"wrap-writable.js","sourceRoot":"","sources":["../src/wrap-writable.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAW7C,KAAK,UAAU,wBAAwB,CACnC,KAG8B;IAE9B,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;QACnB,OAAO,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;IAC/B,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QACrC,OAAO,MAAM,KAAK,EAAE,CAAC;IACzB,CAAC;SAAM,CAAC;QACJ,gDAAgD;QAChD,wEAAwE;QACxE,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAED,MAAM,OAAO,kBAAsB,SAAQ,cAAiB;IACxD,QAAQ,CAAqB;IAE7B,OAAO,CAAkC;IAEzC,YACI,KAG8B;QAE9B,KAAK,CAAC;YACF,KAAK,EAAE,KAAK,IAAI,EAAE;gBACd,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAAC,KAAK,CAAC,CAAC;gBACvD,qEAAqE;gBACrE,wCAAwC;gBACxC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;gBACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;YAC7C,CAAC;YACD,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBACnB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACpC,CAAC;YACD,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;gBACpB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACjC,IAAI,KAAK,KAAK,IAAI,CAAC,QAAQ,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;oBAC9C,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC1B,CAAC;YACL,CAAC;YACD,KAAK,EAAE,KAAK,IAAI,EAAE;gBACd,gCAAgC;gBAChC,0EAA0E;gBAC1E,yEAAyE;gBACzE,uCAAuC;gBACvC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC3B,IAAI,KAAK,KAAK,IAAI,CAAC,QAAQ,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;oBAC9C,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC1B,CAAC;YACL,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;IAED,kBAAkB,CAAI,WAAkC;QACpD,IAAI,OAAsB,CAAC;QAC3B,OAAO,IAAI,kBAAkB,CAAI;YAC7B,KAAK,EAAE,GAAG,EAAE;gBACR,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC5C,OAAO,WAAW,CAAC,QAAQ,CAAC;YAChC,CAAC;YACD,KAAK,CAAC,KAAK;gBACP,MAAM,OAAO,CAAC;YAClB,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;CACJ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yume-chan/stream-extra",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Extensions to Web Streams API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"stream",
|
|
@@ -24,24 +24,22 @@
|
|
|
24
24
|
"type": "module",
|
|
25
25
|
"main": "esm/index.js",
|
|
26
26
|
"types": "esm/index.d.ts",
|
|
27
|
+
"sideEffects": false,
|
|
27
28
|
"dependencies": {
|
|
28
|
-
"@yume-chan/async": "^
|
|
29
|
-
"@yume-chan/struct": "^0.0
|
|
29
|
+
"@yume-chan/async": "^4.0.2",
|
|
30
|
+
"@yume-chan/struct": "^2.0.0"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
|
-
"@
|
|
33
|
+
"@types/node": "^22.13.10",
|
|
34
|
+
"prettier": "^3.5.3",
|
|
35
|
+
"typescript": "^5.8.2",
|
|
33
36
|
"@yume-chan/eslint-config": "^1.0.0",
|
|
34
|
-
"@yume-chan/
|
|
35
|
-
"
|
|
36
|
-
"jest": "^30.0.0-alpha.4",
|
|
37
|
-
"prettier": "^3.3.2",
|
|
38
|
-
"ts-jest": "^29.1.4",
|
|
39
|
-
"typescript": "^5.4.5"
|
|
37
|
+
"@yume-chan/test-runner": "^1.0.0",
|
|
38
|
+
"@yume-chan/tsconfig": "^1.0.0"
|
|
40
39
|
},
|
|
41
40
|
"scripts": {
|
|
42
41
|
"build": "tsc -b tsconfig.build.json",
|
|
43
|
-
"
|
|
44
|
-
"test": "
|
|
45
|
-
"lint": "run-eslint && prettier src/**/*.ts --write --tab-width 4"
|
|
42
|
+
"lint": "run-eslint && prettier src/**/*.ts --write --tab-width 4",
|
|
43
|
+
"test": "run-test"
|
|
46
44
|
}
|
|
47
45
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { MaybePromiseLike } from "@yume-chan/async";
|
|
2
2
|
import { StructEmptyError } from "@yume-chan/struct";
|
|
3
3
|
|
|
4
4
|
import { BufferedReadableStream } from "./buffered.js";
|
|
5
5
|
import type { PushReadableStreamController } from "./push-readable.js";
|
|
6
6
|
import { PushReadableStream } from "./push-readable.js";
|
|
7
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
ReadableWritablePair,
|
|
9
|
+
WritableStreamDefaultController,
|
|
10
|
+
} from "./stream.js";
|
|
8
11
|
import { ReadableStream, WritableStream } from "./stream.js";
|
|
9
12
|
|
|
10
13
|
// TODO: BufferedTransformStream: find better implementation
|
|
@@ -22,14 +25,16 @@ export class BufferedTransformStream<T>
|
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
constructor(
|
|
25
|
-
transform: (stream: BufferedReadableStream) =>
|
|
28
|
+
transform: (stream: BufferedReadableStream) => MaybePromiseLike<T>,
|
|
26
29
|
) {
|
|
27
30
|
// Convert incoming chunks to a `BufferedReadableStream`
|
|
28
|
-
let
|
|
31
|
+
let bufferedStreamController!: PushReadableStreamController<Uint8Array>;
|
|
32
|
+
|
|
33
|
+
let writableStreamController!: WritableStreamDefaultController;
|
|
29
34
|
|
|
30
35
|
const buffered = new BufferedReadableStream(
|
|
31
36
|
new PushReadableStream<Uint8Array>((controller) => {
|
|
32
|
-
|
|
37
|
+
bufferedStreamController = controller;
|
|
33
38
|
}),
|
|
34
39
|
);
|
|
35
40
|
|
|
@@ -50,21 +55,26 @@ export class BufferedTransformStream<T>
|
|
|
50
55
|
}
|
|
51
56
|
},
|
|
52
57
|
cancel: (reason) => {
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
|
|
58
|
+
// If a `ReadableStream` is piping into `#writable`,
|
|
59
|
+
// This will cancel the `ReadableStream` immediately.
|
|
60
|
+
// If upstream is writing using `#writable`'s writer, this will
|
|
61
|
+
// throw errors for any future writes
|
|
62
|
+
return writableStreamController.error(reason);
|
|
56
63
|
},
|
|
57
64
|
});
|
|
58
65
|
|
|
59
66
|
this.#writable = new WritableStream({
|
|
67
|
+
start(controller) {
|
|
68
|
+
writableStreamController = controller;
|
|
69
|
+
},
|
|
60
70
|
async write(chunk) {
|
|
61
|
-
await
|
|
71
|
+
await bufferedStreamController.enqueue(chunk);
|
|
62
72
|
},
|
|
63
73
|
abort() {
|
|
64
|
-
|
|
74
|
+
bufferedStreamController.close();
|
|
65
75
|
},
|
|
66
76
|
close() {
|
|
67
|
-
|
|
77
|
+
bufferedStreamController.close();
|
|
68
78
|
},
|
|
69
79
|
});
|
|
70
80
|
}
|
package/src/buffered.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
import type { MaybePromiseLike } from "@yume-chan/async";
|
|
1
2
|
import type { AsyncExactReadable } from "@yume-chan/struct";
|
|
2
|
-
import { ExactReadableEndedError } from "@yume-chan/struct";
|
|
3
|
+
import { bipedal, ExactReadableEndedError } from "@yume-chan/struct";
|
|
3
4
|
|
|
4
5
|
import { PushReadableStream } from "./push-readable.js";
|
|
5
6
|
import type { ReadableStream, ReadableStreamDefaultReader } from "./stream.js";
|
|
6
|
-
|
|
7
|
-
const NOOP = () => {
|
|
8
|
-
// no-op
|
|
9
|
-
};
|
|
7
|
+
import { tryCancel } from "./try-close.js";
|
|
10
8
|
|
|
11
9
|
export class BufferedReadableStream implements AsyncExactReadable {
|
|
12
10
|
#buffered: Uint8Array | undefined;
|
|
11
|
+
// PERF: `subarray` is slow
|
|
12
|
+
// don't use it until absolutely necessary
|
|
13
13
|
#bufferedOffset = 0;
|
|
14
14
|
#bufferedLength = 0;
|
|
15
15
|
|
|
@@ -26,99 +26,124 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
26
26
|
this.reader = stream.getReader();
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
#readBuffered(length: number) {
|
|
30
|
+
if (!this.#buffered) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const value = this.#buffered.subarray(
|
|
35
|
+
this.#bufferedOffset,
|
|
36
|
+
this.#bufferedOffset + length,
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// PERF: Synchronous path for reading from internal buffer
|
|
40
|
+
if (this.#bufferedLength > length) {
|
|
41
|
+
this.#position += length;
|
|
42
|
+
this.#bufferedOffset += length;
|
|
43
|
+
this.#bufferedLength -= length;
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.#position += this.#bufferedLength;
|
|
48
|
+
this.#buffered = undefined;
|
|
49
|
+
this.#bufferedOffset = 0;
|
|
50
|
+
this.#bufferedLength = 0;
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async #readSource(length: number): Promise<Uint8Array> {
|
|
30
55
|
const { done, value } = await this.reader.read();
|
|
31
56
|
if (done) {
|
|
32
57
|
throw new ExactReadableEndedError();
|
|
33
58
|
}
|
|
59
|
+
|
|
60
|
+
if (value.length > length) {
|
|
61
|
+
this.#buffered = value;
|
|
62
|
+
this.#bufferedOffset = length;
|
|
63
|
+
this.#bufferedLength = value.length - length;
|
|
64
|
+
this.#position += length;
|
|
65
|
+
return value.subarray(0, length);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.#position += value.length;
|
|
34
69
|
return value;
|
|
35
70
|
}
|
|
36
71
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
72
|
+
iterateExactly(
|
|
73
|
+
length: number,
|
|
74
|
+
): Iterator<MaybePromiseLike<Uint8Array>, void, void> {
|
|
75
|
+
let state = this.#buffered ? 0 : 1;
|
|
76
|
+
return {
|
|
77
|
+
next: () => {
|
|
78
|
+
switch (state) {
|
|
79
|
+
case 0: {
|
|
80
|
+
const value = this.#readBuffered(length)!;
|
|
81
|
+
if (value.length === length) {
|
|
82
|
+
state = 2;
|
|
83
|
+
} else {
|
|
84
|
+
length -= value.length;
|
|
85
|
+
state = 1;
|
|
86
|
+
}
|
|
87
|
+
return { done: false, value };
|
|
88
|
+
}
|
|
89
|
+
case 1:
|
|
90
|
+
state = 3;
|
|
91
|
+
return {
|
|
92
|
+
done: false,
|
|
93
|
+
value: this.#readSource(length).then((value) => {
|
|
94
|
+
if (value.length === length) {
|
|
95
|
+
state = 2;
|
|
96
|
+
} else {
|
|
97
|
+
length -= value.length;
|
|
98
|
+
state = 1;
|
|
99
|
+
}
|
|
100
|
+
return value;
|
|
101
|
+
}),
|
|
102
|
+
};
|
|
103
|
+
case 2:
|
|
104
|
+
return { done: true, value: undefined };
|
|
105
|
+
case 3:
|
|
106
|
+
throw new Error(
|
|
107
|
+
"Can't call `next` before previous Promise resolves",
|
|
108
|
+
);
|
|
109
|
+
default:
|
|
110
|
+
throw new Error("unreachable");
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
40
115
|
|
|
116
|
+
readExactly = bipedal(function* (
|
|
117
|
+
this: BufferedReadableStream,
|
|
118
|
+
then,
|
|
119
|
+
length: number,
|
|
120
|
+
) {
|
|
121
|
+
let result: Uint8Array | undefined;
|
|
122
|
+
let index = 0;
|
|
123
|
+
|
|
124
|
+
const initial = this.#readBuffered(length);
|
|
41
125
|
if (initial) {
|
|
126
|
+
if (initial.length === length) {
|
|
127
|
+
return initial;
|
|
128
|
+
}
|
|
129
|
+
|
|
42
130
|
result = new Uint8Array(length);
|
|
43
|
-
result.set(initial);
|
|
44
|
-
index
|
|
131
|
+
result.set(initial, index);
|
|
132
|
+
index += initial.length;
|
|
45
133
|
length -= initial.length;
|
|
46
134
|
} else {
|
|
47
|
-
const array = await this.#readSource();
|
|
48
|
-
if (array.length === length) {
|
|
49
|
-
this.#position += length;
|
|
50
|
-
return array;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (array.length > length) {
|
|
54
|
-
this.#buffered = array;
|
|
55
|
-
this.#bufferedOffset = length;
|
|
56
|
-
this.#bufferedLength = array.length - length;
|
|
57
|
-
this.#position += length;
|
|
58
|
-
return array.subarray(0, length);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
135
|
result = new Uint8Array(length);
|
|
62
|
-
result.set(array);
|
|
63
|
-
index = array.length;
|
|
64
|
-
length -= array.length;
|
|
65
|
-
this.#position += array.length;
|
|
66
136
|
}
|
|
67
137
|
|
|
68
138
|
while (length > 0) {
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return result;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (array.length > length) {
|
|
77
|
-
this.#buffered = array;
|
|
78
|
-
this.#bufferedOffset = length;
|
|
79
|
-
this.#bufferedLength = array.length - length;
|
|
80
|
-
result.set(array.subarray(0, length), index);
|
|
81
|
-
this.#position += length;
|
|
82
|
-
return result;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
result.set(array, index);
|
|
86
|
-
index += array.length;
|
|
87
|
-
length -= array.length;
|
|
88
|
-
this.#position += array.length;
|
|
139
|
+
const value = yield* then(this.#readSource(length));
|
|
140
|
+
result.set(value, index);
|
|
141
|
+
index += value.length;
|
|
142
|
+
length -= value.length;
|
|
89
143
|
}
|
|
90
144
|
|
|
91
145
|
return result;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
*
|
|
96
|
-
* @param length
|
|
97
|
-
* @returns
|
|
98
|
-
*/
|
|
99
|
-
readExactly(length: number): Uint8Array | Promise<Uint8Array> {
|
|
100
|
-
// PERF: Add a synchronous path for reading from internal buffer
|
|
101
|
-
if (this.#buffered) {
|
|
102
|
-
const array = this.#buffered;
|
|
103
|
-
const offset = this.#bufferedOffset;
|
|
104
|
-
if (this.#bufferedLength > length) {
|
|
105
|
-
// PERF: `subarray` is slow
|
|
106
|
-
// don't use it until absolutely necessary
|
|
107
|
-
this.#bufferedOffset += length;
|
|
108
|
-
this.#bufferedLength -= length;
|
|
109
|
-
this.#position += length;
|
|
110
|
-
return array.subarray(offset, offset + length);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
this.#buffered = undefined;
|
|
114
|
-
this.#bufferedLength = 0;
|
|
115
|
-
this.#bufferedOffset = 0;
|
|
116
|
-
this.#position += array.length - offset;
|
|
117
|
-
return this.#readAsync(length, array.subarray(offset));
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return this.#readAsync(length);
|
|
121
|
-
}
|
|
146
|
+
});
|
|
122
147
|
|
|
123
148
|
/**
|
|
124
149
|
* Return a readable stream with unconsumed data (if any) and
|
|
@@ -133,8 +158,7 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
133
158
|
await controller.enqueue(buffered);
|
|
134
159
|
|
|
135
160
|
controller.abortSignal.addEventListener("abort", () => {
|
|
136
|
-
|
|
137
|
-
this.reader.cancel().catch(NOOP);
|
|
161
|
+
void tryCancel(this.reader);
|
|
138
162
|
});
|
|
139
163
|
|
|
140
164
|
// Manually pipe the stream
|
|
@@ -142,9 +166,9 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
142
166
|
const { done, value } = await this.reader.read();
|
|
143
167
|
if (done) {
|
|
144
168
|
return;
|
|
145
|
-
} else {
|
|
146
|
-
await controller.enqueue(value);
|
|
147
169
|
}
|
|
170
|
+
|
|
171
|
+
await controller.enqueue(value);
|
|
148
172
|
}
|
|
149
173
|
});
|
|
150
174
|
} else {
|
package/src/concat.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
-
import {
|
|
2
|
+
import { EmptyUint8Array } from "@yume-chan/struct";
|
|
3
3
|
|
|
4
4
|
import type { ReadableStreamDefaultController } from "./stream.js";
|
|
5
5
|
import { ReadableStream, WritableStream } from "./stream.js";
|
|
@@ -101,7 +101,7 @@ export class ConcatBufferStream {
|
|
|
101
101
|
let offset = 0;
|
|
102
102
|
switch (this.#segments.length) {
|
|
103
103
|
case 0:
|
|
104
|
-
result =
|
|
104
|
+
result = EmptyUint8Array;
|
|
105
105
|
break;
|
|
106
106
|
case 1:
|
|
107
107
|
result = this.#segments[0]!;
|