unikvs 0.0.12 → 0.0.13

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 (82) hide show
  1. package/README.md +2 -2
  2. package/dist/index.d.ts +1553 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +4032 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +34 -34
  7. package/src/_contexts.ts +1089 -0
  8. package/src/_logger.ts +5 -3
  9. package/src/_middleware.ts +207 -0
  10. package/src/_pipeline-graph.helpers.ts +183 -0
  11. package/src/_pipeline-graph.ts +1307 -0
  12. package/src/_pipeline-graph.types.ts +303 -0
  13. package/src/_pipeline-leaf-resolver.ts +70 -0
  14. package/src/_plugin-lifecycle.ts +201 -0
  15. package/src/_storage.ts +169 -115
  16. package/src/_streams.schemas.ts +21 -0
  17. package/src/_streams.ts +32 -6
  18. package/src/_to-value-stream.ts +22 -11
  19. package/src/_types.ts +237 -0
  20. package/src/_unikvs-branch.ts +94 -0
  21. package/src/_unikvs.schemas.ts +451 -0
  22. package/src/_valibot.ts +17 -6
  23. package/src/_value-schemas.ts +36 -206
  24. package/src/_value-validation.ts +57 -0
  25. package/src/errors.ts +391 -148
  26. package/src/index.ts +46 -25
  27. package/src/{value-stream.types.ts → types.ts} +1 -1
  28. package/src/unikvs-branch.ts +445 -0
  29. package/src/unikvs-builder.ts +706 -0
  30. package/src/unikvs.ts +1423 -1007
  31. package/src/unikvs.types.ts +194 -0
  32. package/src/value-schemas.ts +98 -0
  33. package/dist/src/_logger.d.ts +0 -3
  34. package/dist/src/_logger.d.ts.map +0 -1
  35. package/dist/src/_logger.js +0 -3
  36. package/dist/src/_merge-variables.d.ts +0 -13
  37. package/dist/src/_merge-variables.d.ts.map +0 -1
  38. package/dist/src/_merge-variables.js +0 -12
  39. package/dist/src/_storage.d.ts +0 -18
  40. package/dist/src/_storage.d.ts.map +0 -1
  41. package/dist/src/_storage.js +0 -103
  42. package/dist/src/_streams.d.ts +0 -20
  43. package/dist/src/_streams.d.ts.map +0 -1
  44. package/dist/src/_streams.js +0 -36
  45. package/dist/src/_to-value-stream.d.ts +0 -12
  46. package/dist/src/_to-value-stream.d.ts.map +0 -1
  47. package/dist/src/_to-value-stream.js +0 -102
  48. package/dist/src/_transformer.d.ts +0 -13
  49. package/dist/src/_transformer.d.ts.map +0 -1
  50. package/dist/src/_transformer.js +0 -60
  51. package/dist/src/_valibot.d.ts +0 -15
  52. package/dist/src/_valibot.d.ts.map +0 -1
  53. package/dist/src/_valibot.js +0 -23
  54. package/dist/src/_value-schemas.d.ts +0 -179
  55. package/dist/src/_value-schemas.d.ts.map +0 -1
  56. package/dist/src/_value-schemas.js +0 -150
  57. package/dist/src/errors.d.ts +0 -306
  58. package/dist/src/errors.d.ts.map +0 -1
  59. package/dist/src/errors.js +0 -234
  60. package/dist/src/index.d.ts +0 -10
  61. package/dist/src/index.d.ts.map +0 -1
  62. package/dist/src/index.js +0 -3
  63. package/dist/src/unikvs-config.d.ts +0 -174
  64. package/dist/src/unikvs-config.d.ts.map +0 -1
  65. package/dist/src/unikvs-config.js +0 -100
  66. package/dist/src/unikvs.d.ts +0 -272
  67. package/dist/src/unikvs.d.ts.map +0 -1
  68. package/dist/src/unikvs.js +0 -928
  69. package/dist/src/utils.types.d.ts +0 -5
  70. package/dist/src/utils.types.d.ts.map +0 -1
  71. package/dist/src/utils.types.js +0 -1
  72. package/dist/src/value-stream.types.d.ts +0 -10
  73. package/dist/src/value-stream.types.d.ts.map +0 -1
  74. package/dist/src/value-stream.types.js +0 -1
  75. package/dist/src/variables.types.d.ts +0 -11
  76. package/dist/src/variables.types.d.ts.map +0 -1
  77. package/dist/src/variables.types.js +0 -1
  78. package/src/_merge-variables.ts +0 -19
  79. package/src/_transformer.ts +0 -89
  80. package/src/unikvs-config.ts +0 -401
  81. package/src/utils.types.ts +0 -4
  82. package/src/variables.types.ts +0 -13
package/src/_storage.ts CHANGED
@@ -1,13 +1,10 @@
1
- import type {
2
- Variables,
3
- IStorage,
4
- ErrorBase,
5
- IReadableStream,
6
- IWritableStream,
7
- } from "@unikvs/core";
8
-
9
- import { isReadableStream, isWritableStream } from "./_streams.js";
10
- import * as v from "./_valibot.js";
1
+ import type { IStorage, IReadableStream, IWritableStream } from "@unikvs/core";
2
+ import { asyncmux } from "asyncmux";
3
+ import { callFnOnce } from "call-fn-once";
4
+
5
+ import { PluginLifecycle } from "./_plugin-lifecycle.js";
6
+ import { ReadableStreamSchema, WritableStreamSchema } from "./_streams.schemas.js";
7
+ import { parseOutput } from "./_valibot.js";
11
8
  import {
12
9
  type PluginOperationAggregateError,
13
10
  StorageIsNotOpenError,
@@ -16,166 +13,223 @@ import {
16
13
  } from "./errors.js";
17
14
 
18
15
  /**
19
- * `ReadableStream` のインターフェースを満たすかを検証するためのスキーマです。
16
+ * 同じオブジェクトに対して同じ `UniKvsStorage` インスタンスを返すためのメモです。
20
17
  */
21
- const ReadableStreamSchema = v.custom<IReadableStream>(
22
- isReadableStream,
23
- "Expected a ReadableStream",
24
- );
18
+ const instances = /* #__PURE__ */ new WeakMap<IStorage, UniKvsStorage>();
25
19
 
26
20
  /**
27
- * `WritableStream` のインターフェースを満たすかを検証するためのスキーマです。
21
+ * `IStorage` を `UniKvs` 内部から扱うためのラッパーです。
22
+ *
23
+ * ストレージを安全に使うための検証などの処理が集約されています。
28
24
  */
29
- const WritableStreamSchema = v.custom<IWritableStream>(
30
- isWritableStream,
31
- "Expected a WritableStream",
32
- );
33
-
34
25
  export default class UniKvsStorage {
35
- private readonly io: IStorage;
36
-
37
- private managed: boolean;
38
-
39
- public constructor(io: IStorage) {
40
- this.io = io;
41
- this.managed = false;
26
+ /**
27
+ * ラップするストレージです。
28
+ */
29
+ readonly #io: IStorage;
30
+
31
+ /**
32
+ * 参照カウントと実 `close` の再試行を管理します。
33
+ */
34
+ readonly #lifecycle: PluginLifecycle<IStorage.OpenContext, IStorage.CloseContext>;
35
+
36
+ /**
37
+ * ストレージの名前です。
38
+ */
39
+ public readonly name: string;
40
+
41
+ private constructor(storage: IStorage) {
42
+ this.#io = storage;
43
+ this.#lifecycle = new PluginLifecycle(storage);
44
+ this.name = storage.name;
42
45
  }
43
46
 
44
- public async open(vars: Variables, signal: AbortSignal): Promise<void> {
45
- if (typeof this.io.open !== "function") {
46
- return;
47
- }
47
+ /**
48
+ * `IStorage` から `UniKvs` 内部から扱うためのストレージを作成します。
49
+ *
50
+ * @param storage 元となるストレージです。
51
+ *
52
+ * @returns 検証などの機能が集約されたストレージです。
53
+ */
54
+ public static from(storage: IStorage): UniKvsStorage {
55
+ return callFnOnce(instances, storage, () => new UniKvsStorage(storage));
56
+ }
48
57
 
49
- if (!this.io.isOpen) {
50
- this.managed = true;
51
- await this.io.open({ vars, signal });
52
- }
58
+ /**
59
+ * ストレージを開きます。
60
+ *
61
+ * @param c オープンコンテキストです。
62
+ */
63
+ @asyncmux
64
+ public async open(c: IStorage.OpenContext): Promise<void> {
65
+ await this.#lifecycle.open(c);
53
66
  }
54
67
 
55
- public async close(vars: Variables, signal: AbortSignal): Promise<void> {
56
- if (typeof this.io.close !== "function") {
57
- return;
58
- }
68
+ /**
69
+ * ストレージを閉じます。
70
+ *
71
+ * @param c クローズコンテキストです。
72
+ */
73
+ @asyncmux
74
+ public async close(c: IStorage.CloseContext): Promise<void> {
75
+ await this.#lifecycle.close(c);
76
+ }
59
77
 
60
- if (this.io.isOpen && this.managed) {
61
- await this.io.close({ vars, signal });
62
- }
78
+ /**
79
+ * 失敗した実 `close` だけを再試行します。
80
+ *
81
+ * @param c クローズコンテキストです。
82
+ */
83
+ @asyncmux
84
+ public async retryClose(c: IStorage.CloseContext): Promise<void> {
85
+ await this.#lifecycle.retryClose(c);
63
86
  }
64
87
 
65
- public async write(
66
- vars: Variables,
67
- signal: AbortSignal,
68
- key: IStorage.Key,
69
- data: unknown,
70
- ): Promise<void> {
71
- if (!this.io.isOpen) {
72
- throw new StorageIsNotOpenError({ name: this.io.name });
88
+ /**
89
+ * データを書き込みます。
90
+ *
91
+ * @param c 書き込みコンテキストです。
92
+ * @param data 書き込むデータです。
93
+ */
94
+ public async write(c: IStorage.WriteContext, data: unknown): Promise<void> {
95
+ if (!this.#io.isOpen) {
96
+ throw new StorageIsNotOpenError({ name: this.name });
73
97
  }
74
98
 
75
- await this.io.write({ key, data, vars, signal });
99
+ await this.#io.write(c, data);
76
100
  }
77
101
 
78
- public async read(vars: Variables, signal: AbortSignal, key: IStorage.Key): Promise<unknown> {
79
- if (!this.io.isOpen) {
80
- throw new StorageIsNotOpenError({ name: this.io.name });
102
+ /**
103
+ * データを読み取ります。
104
+ *
105
+ * @param c 読み取りコンテキストです。
106
+ *
107
+ * @returns 読み取ったデータを返します。
108
+ */
109
+ public async read(c: IStorage.ReadContext): Promise<unknown> {
110
+ if (!this.#io.isOpen) {
111
+ throw new StorageIsNotOpenError({ name: this.name });
81
112
  }
82
113
 
83
- const output = await this.io.read({ key, vars, signal });
84
-
85
- return output;
114
+ return await this.#io.read(c);
86
115
  }
87
116
 
88
- public async exists(vars: Variables, signal: AbortSignal, key: IStorage.Key): Promise<boolean> {
89
- if (!this.io.isOpen) {
90
- throw new StorageIsNotOpenError({ name: this.io.name });
117
+ /**
118
+ * データの存在を確認します。
119
+ *
120
+ * @param c 存在確認コンテキストです。
121
+ *
122
+ * @returns 存在する場合は `true` を返します。
123
+ */
124
+ public async exists(c: IStorage.ExistsContext): Promise<boolean> {
125
+ if (!this.#io.isOpen) {
126
+ throw new StorageIsNotOpenError({ name: this.name });
91
127
  }
92
128
 
93
- const output = await this.io.exists({ key, vars, signal });
94
- const parsed = Boolean(output);
129
+ const output = await this.#io.exists(c);
95
130
 
96
- return parsed;
131
+ return output;
97
132
  }
98
133
 
99
- public async delete(vars: Variables, signal: AbortSignal, key: IStorage.Key): Promise<void> {
100
- if (!this.io.isOpen) {
101
- throw new StorageIsNotOpenError({ name: this.io.name });
134
+ /**
135
+ * データを削除します。
136
+ *
137
+ * @param c 削除コンテキストです。
138
+ */
139
+ public async delete(c: IStorage.DeleteContext): Promise<void> {
140
+ if (!this.#io.isOpen) {
141
+ throw new StorageIsNotOpenError({ name: this.name });
102
142
  }
103
143
 
104
- await this.io.delete({ key, vars, signal });
144
+ await this.#io.delete(c);
105
145
  }
106
146
 
107
- public async clear(vars: Variables, signal: AbortSignal): Promise<void> {
108
- if (!this.io.isOpen) {
109
- throw new StorageIsNotOpenError({ name: this.io.name });
147
+ /**
148
+ * データをすべて削除します。
149
+ *
150
+ * @param c クリアコンテキストです。
151
+ */
152
+ public async clear(c: IStorage.ClearContext): Promise<void> {
153
+ if (!this.#io.isOpen) {
154
+ throw new StorageIsNotOpenError({ name: this.name });
110
155
  }
111
156
 
112
- await this.io.clear({ vars, signal });
157
+ await this.#io.clear(c);
113
158
  }
114
159
 
115
- public async getReadable(
116
- vars: Variables,
117
- signal: AbortSignal,
118
- key: IStorage.Key,
119
- ): Promise<IReadableStream> {
120
- if (!this.io.isOpen) {
121
- throw new StorageIsNotOpenError({ name: this.io.name });
160
+ /**
161
+ * 読み取り用のストリームを取得します。
162
+ *
163
+ * @param c ストリーム取得コンテキストです。
164
+ *
165
+ * @returns 読み取り用のストリームを返します。
166
+ */
167
+ public async getReadable(c: IStorage.GetReadableContext): Promise<IReadableStream> {
168
+ if (!this.#io.isOpen) {
169
+ throw new StorageIsNotOpenError({ name: this.name });
122
170
  }
123
171
 
124
- if (typeof this.io.getReadable !== "function") {
125
- throw new ReadableStreamNotSupportedError({ name: this.io.name });
172
+ if (this.#io.getReadable === undefined) {
173
+ throw new ReadableStreamNotSupportedError({ name: this.name });
126
174
  }
127
175
 
128
- const output = await this.io.getReadable({ key, vars, signal });
129
- const parsed = v.parseOutput(ReadableStreamSchema, output);
176
+ const output = await this.#io.getReadable(c);
130
177
 
131
- return parsed;
178
+ return parseOutput(ReadableStreamSchema, output);
132
179
  }
133
180
 
134
- public async getWritable(
135
- vars: Variables,
136
- signal: AbortSignal,
137
- key: IStorage.Key,
138
- ): Promise<IWritableStream> {
139
- if (!this.io.isOpen) {
140
- throw new StorageIsNotOpenError({ name: this.io.name });
181
+ /**
182
+ * 書き込み用のストリームを取得します。
183
+ *
184
+ * @param c ストリーム取得コンテキストです。
185
+ *
186
+ * @returns 書き込み用のストリームを返します。
187
+ */
188
+ public async getWritable(c: IStorage.GetWritableContext): Promise<IWritableStream> {
189
+ if (!this.#io.isOpen) {
190
+ throw new StorageIsNotOpenError({ name: this.name });
141
191
  }
142
192
 
143
- if (typeof this.io.getWritable !== "function") {
144
- throw new WritableStreamNotSupportedError({ name: this.io.name });
193
+ if (this.#io.getWritable === undefined) {
194
+ throw new WritableStreamNotSupportedError({ name: this.name });
145
195
  }
146
196
 
147
- const output = await this.io.getWritable({ key, vars, signal });
148
- const parsed = v.parseOutput(WritableStreamSchema, output);
197
+ const output = await this.#io.getWritable(c);
149
198
 
150
- return parsed;
199
+ return parseOutput(WritableStreamSchema, output);
151
200
  }
152
201
 
202
+ /**
203
+ * 他のストレージへの書き込み失敗を通知します。
204
+ *
205
+ * @param c 書き込み失敗通知コンテキストです。
206
+ * @param err 集約エラーです。
207
+ */
153
208
  public async onOtherWriteError(
154
- vars: Variables,
155
- signal: AbortSignal,
156
- key: IStorage.Key,
209
+ c: IStorage.OtherWriteErrorHandlerContext,
157
210
  err: PluginOperationAggregateError,
158
211
  ): Promise<void> {
159
- if (!this.io.isOpen) {
160
- throw new StorageIsNotOpenError({ name: this.io.name });
212
+ if (!this.#io.isOpen) {
213
+ throw new StorageIsNotOpenError({ name: this.name });
161
214
  }
162
215
 
163
- if (typeof this.io.onOtherWriteError !== "function") {
216
+ if (this.#io.onOtherWriteError === undefined) {
164
217
  return;
165
218
  }
166
219
 
167
- await this.io.onOtherWriteError({
168
- key,
169
- error: err as ErrorBase<{
170
- readonly plugin: "storage";
171
- readonly action: "write";
172
- readonly errors: readonly {
173
- readonly plugin: "storage";
174
- readonly reason: unknown;
175
- }[];
176
- }>,
177
- signal,
178
- vars,
179
- });
220
+ await this.#io.onOtherWriteError(c, [
221
+ {
222
+ errors: (
223
+ err.meta.errors as readonly {
224
+ readonly plugin: "storage";
225
+ readonly reason: unknown;
226
+ }[]
227
+ ).map((error) => ({
228
+ plugin: "storage" as const,
229
+ reason: error.reason,
230
+ })),
231
+ plugin: "storage",
232
+ },
233
+ ]);
180
234
  }
181
235
  }
@@ -0,0 +1,21 @@
1
+ import type { IReadableStream, IWritableStream } from "@unikvs/core";
2
+ import type { CustomIssue, CustomSchema, ErrorMessage } from "valibot";
3
+
4
+ import { isReadableStream, isWritableStream } from "./_streams.js";
5
+ import { custom } from "./_valibot.js";
6
+
7
+ /**
8
+ * `ReadableStream` のインターフェースを満たすかを検証するためのスキーマです。
9
+ */
10
+ export const ReadableStreamSchema: CustomSchema<
11
+ IReadableStream,
12
+ ErrorMessage<CustomIssue> | undefined
13
+ > = custom<IReadableStream>(isReadableStream, "Expected a ReadableStream");
14
+
15
+ /**
16
+ * `WritableStream` のインターフェースを満たすかを検証するためのスキーマです。
17
+ */
18
+ export const WritableStreamSchema: CustomSchema<
19
+ IWritableStream,
20
+ ErrorMessage<CustomIssue> | undefined
21
+ > = custom<IWritableStream>(isWritableStream, "Expected a WritableStream");
package/src/_streams.ts CHANGED
@@ -6,6 +6,7 @@ import type { IReadableStream, IWritableStream } from "@unikvs/core";
6
6
  * ランタイムによっては `ReadableStream` クラスを継承せずに同じインターフェースを備えたオブジェクトが存在するため、`instanceof` ではなく必要なメソッドの有無で判定します。
7
7
  *
8
8
  * @param input 判定する値です。
9
+ *
9
10
  * @returns `ReadableStream` のインターフェースを満たす場合は `true` を返します。
10
11
  */
11
12
  export function isReadableStream(input: unknown): input is IReadableStream {
@@ -16,11 +17,11 @@ export function isReadableStream(input: unknown): input is IReadableStream {
16
17
  const stream = input as Partial<IReadableStream>;
17
18
 
18
19
  return (
19
- typeof stream.getReader === "function" &&
20
- typeof stream.pipeThrough === "function" &&
21
- typeof stream.pipeTo === "function" &&
22
20
  typeof stream.tee === "function" &&
23
- typeof stream.cancel === "function"
21
+ typeof stream.cancel === "function" &&
22
+ typeof stream.pipeTo === "function" &&
23
+ typeof stream.getReader === "function" &&
24
+ typeof stream.pipeThrough === "function"
24
25
  );
25
26
  }
26
27
 
@@ -30,6 +31,7 @@ export function isReadableStream(input: unknown): input is IReadableStream {
30
31
  * ランタイムによっては `WritableStream` クラスを継承せずに同じインターフェースを備えたオブジェクトが存在するため、`instanceof` ではなく必要なメソッドの有無で判定します。
31
32
  *
32
33
  * @param input 判定する値です。
34
+ *
33
35
  * @returns `WritableStream` のインターフェースを満たす場合は `true` を返します。
34
36
  */
35
37
  export function isWritableStream(input: unknown): input is IWritableStream {
@@ -40,8 +42,32 @@ export function isWritableStream(input: unknown): input is IWritableStream {
40
42
  const stream = input as Partial<IWritableStream>;
41
43
 
42
44
  return (
43
- typeof stream.getWriter === "function" &&
44
45
  typeof stream.abort === "function" &&
45
- typeof stream.close === "function"
46
+ typeof stream.close === "function" &&
47
+ typeof stream.getWriter === "function"
48
+ );
49
+ }
50
+
51
+ /**
52
+ * ストリームの重複を除いてキャンセルします。
53
+ *
54
+ * 個々のキャンセルに失敗しても無視し、元の例外を優先して伝えます。
55
+ *
56
+ * @param streams キャンセルするストリームです。
57
+ * @param reason キャンセル理由です。
58
+ */
59
+ export async function cancelStreams(
60
+ streams: Iterable<IReadableStream>,
61
+ reason: unknown,
62
+ ): Promise<void> {
63
+ // 同じ参照は 1 回だけキャンセルします。
64
+ await Promise.all(
65
+ [...new Set(streams)].map(async (stream) => {
66
+ try {
67
+ await stream.cancel(reason);
68
+ } catch {
69
+ // キャンセルに失敗しても元の例外の伝播を優先します。
70
+ }
71
+ }),
46
72
  );
47
73
  }
@@ -1,27 +1,33 @@
1
1
  import type { IReadableStream } from "@unikvs/core";
2
2
  import { callAsyncableFnOnce } from "call-fn-once";
3
3
 
4
- import logger from "./_logger.js";
5
- import type { ValueStream } from "./value-stream.types.js";
4
+ import { logger } from "./_logger.js";
5
+ import type { IValueStream } from "./types.js";
6
6
 
7
7
  /**
8
- * 与えられた `IReadableStream` を `ValueStream` に変換します。
8
+ * 与えられた `IReadableStream` を `IValueStream` に変換します。
9
9
  *
10
10
  * @template T ストリームが保持する値の型です。
11
+ *
11
12
  * @param readableStream 変換対象となる `IReadableStream` インスタンスです。
12
13
  * @param onAsyncDispose ストリーム破棄時の処理です。
14
+ * @param onBeforeDispose ソースストリームをキャンセルする前に呼ばれる処理です。
15
+ *
13
16
  * @returns 非同期イテレーターが付与された `ValueStream` インスタンスを返します。
14
17
  */
15
18
  export default function toValueStream<T>(
16
19
  readableStream: IReadableStream<T>,
17
20
  onAsyncDispose: () => Promise<void>,
18
- ): ValueStream<T> {
21
+ onBeforeDispose?: () => void,
22
+ ): IValueStream<T> {
19
23
  const cacheMap = new Map();
20
24
  const reader = readableStream.getReader();
21
25
 
22
26
  async function disposeValueStream(): Promise<void> {
23
27
  await callAsyncableFnOnce(cacheMap, "dispose", async () => {
24
28
  try {
29
+ // ソースストリームのキャンセルが他の分岐の解放を待つ場合、先に分岐を中断しないと破棄が停止します。
30
+ onBeforeDispose?.();
25
31
  await reader.cancel();
26
32
  } catch (ex) {
27
33
  logger.error`Failed to cancel the source stream: ${ex}`;
@@ -33,9 +39,10 @@ export default function toValueStream<T>(
33
39
 
34
40
  // cancel・エラー・早期 break であっても dispose されるように、readable 側のキャンセルを直接フックしたストリームを返します。
35
41
  const valueStream = new ReadableStream<T>({
36
- async pull(controller) {
42
+ async pull(controller): Promise<void> {
37
43
  try {
38
44
  const { done, value } = await reader.read();
45
+
39
46
  if (done) {
40
47
  // ストリームが正常に完了したことも dispose 対象とし、完了を通知する前に破棄を完了させます。
41
48
  await disposeValueStream();
@@ -46,12 +53,14 @@ export default function toValueStream<T>(
46
53
  } catch (ex) {
47
54
  // ソースエラー時も dispose (ロック解放など) を行わないと、ストリームを放棄した consumer に対してキーの I/O ロックがリークします。
48
55
  // dispose 自体が失敗しても元の例外の伝播を壊さないように、失敗はログに残すだけにします。
49
- await disposeValueStream().catch((e) => logger.error`Failed to dispose value stream: ${e}`);
56
+ await disposeValueStream().catch((disposeError) => {
57
+ logger.error`Failed to dispose value stream: ${disposeError}`;
58
+ });
50
59
  controller.error(ex);
51
60
  }
52
61
  },
53
62
 
54
- async cancel() {
63
+ async cancel(): Promise<void> {
55
64
  await disposeValueStream();
56
65
  },
57
66
  });
@@ -59,7 +68,7 @@ export default function toValueStream<T>(
59
68
  const stream = Object.assign(
60
69
  valueStream,
61
70
 
62
- // AsyncDisposable
71
+ // AsyncDisposable。
63
72
  {
64
73
  [Symbol.asyncDispose]: disposeValueStream,
65
74
  },
@@ -69,14 +78,16 @@ export default function toValueStream<T>(
69
78
  dispose: disposeValueStream,
70
79
  },
71
80
 
72
- // AsyncIterable<T, void, unknown>
81
+ // AsyncIterable<T, void, unknown>。
73
82
  {
74
83
  async *[Symbol.asyncIterator](this: ReadableStream<T>) {
75
84
  const r = this.getReader();
85
+
76
86
  try {
77
87
  // ストリームが終了するまでループを回し、チャンクを読み取ります。
78
88
  while (true) {
79
89
  const { done, value } = await r.read();
90
+
80
91
  if (done) {
81
92
  break;
82
93
  }
@@ -87,8 +98,8 @@ export default function toValueStream<T>(
87
98
  // エラーが発生した場合は、リーダーのキャンセルを試みます。
88
99
  try {
89
100
  await r.cancel(ex);
90
- } catch (ex) {
91
- logger.error`Failed to cancel reader: ${ex}`;
101
+ } catch (cancelError) {
102
+ logger.error`Failed to cancel reader: ${cancelError}`;
92
103
  }
93
104
 
94
105
  throw ex;