unikvs 0.0.9 → 0.0.12
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 +3 -0
- package/dist/src/_logger.d.ts.map +1 -1
- package/dist/src/_merge-variables.d.ts +13 -0
- package/dist/src/_merge-variables.d.ts.map +1 -0
- package/dist/src/_merge-variables.js +12 -0
- package/dist/src/_storage.d.ts +11 -11
- package/dist/src/_storage.d.ts.map +1 -1
- package/dist/src/_storage.js +31 -22
- package/dist/src/_streams.d.ts +20 -0
- package/dist/src/_streams.d.ts.map +1 -0
- package/dist/src/_streams.js +36 -0
- package/dist/src/_to-value-stream.d.ts.map +1 -1
- package/dist/src/_to-value-stream.js +44 -6
- package/dist/src/_transformer.d.ts +7 -7
- package/dist/src/_transformer.d.ts.map +1 -1
- package/dist/src/_transformer.js +12 -12
- package/dist/src/_valibot.d.ts +6 -7
- package/dist/src/_valibot.d.ts.map +1 -1
- package/dist/src/_valibot.js +1 -1
- package/dist/src/_value-schemas.d.ts +179 -0
- package/dist/src/_value-schemas.d.ts.map +1 -0
- package/dist/src/_value-schemas.js +150 -0
- package/dist/src/errors.d.ts +218 -27
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +102 -47
- package/dist/src/index.d.ts +3 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/unikvs-config.d.ts +58 -139
- package/dist/src/unikvs-config.d.ts.map +1 -1
- package/dist/src/unikvs-config.js +41 -46
- package/dist/src/unikvs.d.ts +86 -161
- package/dist/src/unikvs.d.ts.map +1 -1
- package/dist/src/unikvs.js +374 -171
- package/dist/src/utils.types.d.ts +1 -3
- package/dist/src/utils.types.d.ts.map +1 -1
- package/dist/src/value-stream.types.d.ts +5 -6
- package/dist/src/value-stream.types.d.ts.map +1 -1
- package/dist/src/variables.types.d.ts +11 -0
- package/dist/src/variables.types.d.ts.map +1 -0
- package/package.json +26 -25
- package/src/_merge-variables.ts +19 -0
- package/src/_storage.ts +47 -24
- package/src/_streams.ts +47 -0
- package/src/_to-value-stream.ts +47 -8
- package/src/_transformer.ts +13 -13
- package/src/_valibot.ts +8 -6
- package/src/_value-schemas.ts +362 -0
- package/src/errors.ts +280 -68
- package/src/index.ts +2 -3
- package/src/unikvs-config.ts +142 -167
- package/src/unikvs.ts +523 -285
- package/src/utils.types.ts +1 -3
- package/src/value-stream.types.ts +5 -6
- package/src/variables.types.ts +13 -0
- package/dist/src/_merge-context.d.ts +0 -13
- package/dist/src/_merge-context.d.ts.map +0 -1
- package/dist/src/_merge-context.js +0 -12
- package/dist/src/context.types.d.ts +0 -17
- package/dist/src/context.types.d.ts.map +0 -1
- package/src/_merge-context.ts +0 -19
- package/src/context.types.ts +0 -19
- /package/dist/src/{context.types.js → variables.types.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.types.d.ts","sourceRoot":"","sources":["../../src/utils.types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"utils.types.d.ts","sourceRoot":"","sources":["../../src/utils.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* `ReadableStream` を拡張しており、標準的なストリーム操作に加えて非同期イテレーターによる反復処理をサポートします。
|
|
5
|
-
*
|
|
6
|
-
* @template T ストリームを流れるデータの型です。
|
|
2
|
+
* [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#value-stream)
|
|
7
3
|
*/
|
|
8
4
|
export interface ValueStream<T = any> extends Omit<ReadableStream, keyof AsyncDisposable | keyof AsyncIterable<unknown>>, AsyncDisposable, AsyncIterable<T, void, unknown> {
|
|
9
|
-
|
|
5
|
+
/**
|
|
6
|
+
* [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#value-stream)
|
|
7
|
+
*/
|
|
8
|
+
dispose: (this: void) => Promise<void>;
|
|
10
9
|
}
|
|
11
10
|
//# sourceMappingURL=value-stream.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"value-stream.types.d.ts","sourceRoot":"","sources":["../../src/value-stream.types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"value-stream.types.d.ts","sourceRoot":"","sources":["../../src/value-stream.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,GAAG,CAClC,SACE,IAAI,CAAC,cAAc,EAAE,MAAM,eAAe,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC,EAC1E,eAAe,EACf,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC;IACjC;;OAEG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Variables } from "@unikvs/core";
|
|
2
|
+
import type { ValueOf } from "./utils.types.js";
|
|
3
|
+
/**
|
|
4
|
+
* [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#variables-and-cancellation)
|
|
5
|
+
*/
|
|
6
|
+
export type VariableEntry = readonly [key: keyof Variables, value: ValueOf<Variables>];
|
|
7
|
+
/**
|
|
8
|
+
* [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#variables-and-cancellation)
|
|
9
|
+
*/
|
|
10
|
+
export type VariablesSource = Readonly<Variables> | readonly VariableEntry[];
|
|
11
|
+
//# sourceMappingURL=variables.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variables.types.d.ts","sourceRoot":"","sources":["../../src/variables.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;AAEvF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,SAAS,aAAa,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unikvs",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.12",
|
|
4
|
+
"description": "A modular and portable KVS client implemented in TypeScript.",
|
|
5
5
|
"homepage": "https://github.com/tai-kun/unikvs",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "tai-kun",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"dist",
|
|
13
13
|
"src",
|
|
14
14
|
"package.json",
|
|
15
|
+
"README.md",
|
|
15
16
|
"LICENSE"
|
|
16
17
|
],
|
|
17
18
|
"type": "module",
|
|
@@ -25,33 +26,33 @@
|
|
|
25
26
|
}
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
28
|
-
"@tai-kun/valibot-extra-lab": "
|
|
29
|
-
"@unikvs/core": "0.0.
|
|
30
|
-
"abort-signal-utils": "
|
|
31
|
-
"asyncmux": "
|
|
32
|
-
"call-fn-once": "
|
|
33
|
-
"try-capture-stack-trace": "
|
|
29
|
+
"@tai-kun/valibot-extra-lab": "0.0.5",
|
|
30
|
+
"@unikvs/core": "0.0.12",
|
|
31
|
+
"abort-signal-utils": "0.0.3",
|
|
32
|
+
"asyncmux": "0.0.10",
|
|
33
|
+
"call-fn-once": "0.0.6",
|
|
34
|
+
"try-capture-stack-trace": "0.0.3"
|
|
34
35
|
},
|
|
35
36
|
"devDependencies": {
|
|
36
|
-
"@tsconfig/node24": "
|
|
37
|
-
"@tsconfig/strictest": "
|
|
38
|
-
"@types/node": "
|
|
39
|
-
"@unikvs/checksum": "0.0.
|
|
40
|
-
"@unikvs/compression": "0.0.
|
|
41
|
-
"@unikvs/fs.node": "0.0.
|
|
42
|
-
"@unikvs/memory": "0.0.
|
|
43
|
-
"@unikvs/opfs": "0.0.
|
|
44
|
-
"@unikvs/utils": "0.0.
|
|
45
|
-
"@vitest/browser": "
|
|
46
|
-
"@vitest/browser-playwright": "
|
|
47
|
-
"npm-check-updates": "
|
|
48
|
-
"playwright": "
|
|
49
|
-
"vite": "
|
|
50
|
-
"vitest": "
|
|
37
|
+
"@tsconfig/node24": "24.0.5",
|
|
38
|
+
"@tsconfig/strictest": "2.0.8",
|
|
39
|
+
"@types/node": "24.13.6",
|
|
40
|
+
"@unikvs/checksum": "0.0.12",
|
|
41
|
+
"@unikvs/compression": "0.0.12",
|
|
42
|
+
"@unikvs/fs.node": "0.0.12",
|
|
43
|
+
"@unikvs/memory": "0.0.12",
|
|
44
|
+
"@unikvs/opfs": "0.0.12",
|
|
45
|
+
"@unikvs/utils": "0.0.12",
|
|
46
|
+
"@vitest/browser": "4.1.11",
|
|
47
|
+
"@vitest/browser-playwright": "4.1.11",
|
|
48
|
+
"npm-check-updates": "20.0.2",
|
|
49
|
+
"playwright": "1.63.0",
|
|
50
|
+
"vite": "8.3.0",
|
|
51
|
+
"vitest": "4.1.11"
|
|
51
52
|
},
|
|
52
53
|
"peerDependencies": {
|
|
53
|
-
"@logtape/logtape": "
|
|
54
|
-
"valibot": "
|
|
54
|
+
"@logtape/logtape": "2.0.0",
|
|
55
|
+
"valibot": "1.0.0"
|
|
55
56
|
},
|
|
56
57
|
"scripts": {
|
|
57
58
|
"build": "tsc --project ./.config/tsconfig.build.json"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Variables } from "@unikvs/core";
|
|
2
|
+
|
|
3
|
+
import type { VariablesSource } from "./variables.types.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 2 つの Variables オブジェクトを結合します。
|
|
7
|
+
*
|
|
8
|
+
* 基本となる Variables に対して、追加または上書きする変数情報を結合し、新しい Variables オブジェクトを生成して返します。追加する変数情報が配列(キーと値のペアの配列)である場合は、オブジェクトに変換した上で結合処理を行います。
|
|
9
|
+
*
|
|
10
|
+
* @param a ベースとなる読み取り専用の Variables オブジェクトです。
|
|
11
|
+
* @param b 結合する読み取り専用の Variables、または VariablesSource、あるいは undefined です。
|
|
12
|
+
* @returns 結合された新しい Variables オブジェクトです。
|
|
13
|
+
*/
|
|
14
|
+
export default function mergeVariables(
|
|
15
|
+
a: Readonly<Variables>,
|
|
16
|
+
b: Readonly<Variables> | VariablesSource | undefined,
|
|
17
|
+
): Variables {
|
|
18
|
+
return { ...a, ...(Array.isArray(b) ? Object.fromEntries(b) : b) };
|
|
19
|
+
}
|
package/src/_storage.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
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";
|
|
3
10
|
import * as v from "./_valibot.js";
|
|
4
11
|
import {
|
|
5
12
|
type PluginOperationAggregateError,
|
|
@@ -8,6 +15,22 @@ import {
|
|
|
8
15
|
WritableStreamNotSupportedError,
|
|
9
16
|
} from "./errors.js";
|
|
10
17
|
|
|
18
|
+
/**
|
|
19
|
+
* `ReadableStream` のインターフェースを満たすかを検証するためのスキーマです。
|
|
20
|
+
*/
|
|
21
|
+
const ReadableStreamSchema = v.custom<IReadableStream>(
|
|
22
|
+
isReadableStream,
|
|
23
|
+
"Expected a ReadableStream",
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* `WritableStream` のインターフェースを満たすかを検証するためのスキーマです。
|
|
28
|
+
*/
|
|
29
|
+
const WritableStreamSchema = v.custom<IWritableStream>(
|
|
30
|
+
isWritableStream,
|
|
31
|
+
"Expected a WritableStream",
|
|
32
|
+
);
|
|
33
|
+
|
|
11
34
|
export default class UniKvsStorage {
|
|
12
35
|
private readonly io: IStorage;
|
|
13
36
|
|
|
@@ -18,29 +41,29 @@ export default class UniKvsStorage {
|
|
|
18
41
|
this.managed = false;
|
|
19
42
|
}
|
|
20
43
|
|
|
21
|
-
public async open(
|
|
44
|
+
public async open(vars: Variables, signal: AbortSignal): Promise<void> {
|
|
22
45
|
if (typeof this.io.open !== "function") {
|
|
23
46
|
return;
|
|
24
47
|
}
|
|
25
48
|
|
|
26
49
|
if (!this.io.isOpen) {
|
|
27
50
|
this.managed = true;
|
|
28
|
-
await this.io.open({
|
|
51
|
+
await this.io.open({ vars, signal });
|
|
29
52
|
}
|
|
30
53
|
}
|
|
31
54
|
|
|
32
|
-
public async close(
|
|
55
|
+
public async close(vars: Variables, signal: AbortSignal): Promise<void> {
|
|
33
56
|
if (typeof this.io.close !== "function") {
|
|
34
57
|
return;
|
|
35
58
|
}
|
|
36
59
|
|
|
37
60
|
if (this.io.isOpen && this.managed) {
|
|
38
|
-
await this.io.close({
|
|
61
|
+
await this.io.close({ vars, signal });
|
|
39
62
|
}
|
|
40
63
|
}
|
|
41
64
|
|
|
42
65
|
public async write(
|
|
43
|
-
|
|
66
|
+
vars: Variables,
|
|
44
67
|
signal: AbortSignal,
|
|
45
68
|
key: IStorage.Key,
|
|
46
69
|
data: unknown,
|
|
@@ -49,48 +72,48 @@ export default class UniKvsStorage {
|
|
|
49
72
|
throw new StorageIsNotOpenError({ name: this.io.name });
|
|
50
73
|
}
|
|
51
74
|
|
|
52
|
-
await this.io.write({ key, data,
|
|
75
|
+
await this.io.write({ key, data, vars, signal });
|
|
53
76
|
}
|
|
54
77
|
|
|
55
|
-
public async read(
|
|
78
|
+
public async read(vars: Variables, signal: AbortSignal, key: IStorage.Key): Promise<unknown> {
|
|
56
79
|
if (!this.io.isOpen) {
|
|
57
80
|
throw new StorageIsNotOpenError({ name: this.io.name });
|
|
58
81
|
}
|
|
59
82
|
|
|
60
|
-
const output = await this.io.read({ key,
|
|
83
|
+
const output = await this.io.read({ key, vars, signal });
|
|
61
84
|
|
|
62
85
|
return output;
|
|
63
86
|
}
|
|
64
87
|
|
|
65
|
-
public async exists(
|
|
88
|
+
public async exists(vars: Variables, signal: AbortSignal, key: IStorage.Key): Promise<boolean> {
|
|
66
89
|
if (!this.io.isOpen) {
|
|
67
90
|
throw new StorageIsNotOpenError({ name: this.io.name });
|
|
68
91
|
}
|
|
69
92
|
|
|
70
|
-
const output = await this.io.exists({ key,
|
|
93
|
+
const output = await this.io.exists({ key, vars, signal });
|
|
71
94
|
const parsed = Boolean(output);
|
|
72
95
|
|
|
73
96
|
return parsed;
|
|
74
97
|
}
|
|
75
98
|
|
|
76
|
-
public async delete(
|
|
99
|
+
public async delete(vars: Variables, signal: AbortSignal, key: IStorage.Key): Promise<void> {
|
|
77
100
|
if (!this.io.isOpen) {
|
|
78
101
|
throw new StorageIsNotOpenError({ name: this.io.name });
|
|
79
102
|
}
|
|
80
103
|
|
|
81
|
-
await this.io.delete({ key,
|
|
104
|
+
await this.io.delete({ key, vars, signal });
|
|
82
105
|
}
|
|
83
106
|
|
|
84
|
-
public async clear(
|
|
107
|
+
public async clear(vars: Variables, signal: AbortSignal): Promise<void> {
|
|
85
108
|
if (!this.io.isOpen) {
|
|
86
109
|
throw new StorageIsNotOpenError({ name: this.io.name });
|
|
87
110
|
}
|
|
88
111
|
|
|
89
|
-
await this.io.clear({
|
|
112
|
+
await this.io.clear({ vars, signal });
|
|
90
113
|
}
|
|
91
114
|
|
|
92
115
|
public async getReadable(
|
|
93
|
-
|
|
116
|
+
vars: Variables,
|
|
94
117
|
signal: AbortSignal,
|
|
95
118
|
key: IStorage.Key,
|
|
96
119
|
): Promise<IReadableStream> {
|
|
@@ -102,14 +125,14 @@ export default class UniKvsStorage {
|
|
|
102
125
|
throw new ReadableStreamNotSupportedError({ name: this.io.name });
|
|
103
126
|
}
|
|
104
127
|
|
|
105
|
-
const output = await this.io.getReadable({ key,
|
|
106
|
-
const parsed = v.parseOutput(
|
|
128
|
+
const output = await this.io.getReadable({ key, vars, signal });
|
|
129
|
+
const parsed = v.parseOutput(ReadableStreamSchema, output);
|
|
107
130
|
|
|
108
131
|
return parsed;
|
|
109
132
|
}
|
|
110
133
|
|
|
111
134
|
public async getWritable(
|
|
112
|
-
|
|
135
|
+
vars: Variables,
|
|
113
136
|
signal: AbortSignal,
|
|
114
137
|
key: IStorage.Key,
|
|
115
138
|
): Promise<IWritableStream> {
|
|
@@ -121,14 +144,14 @@ export default class UniKvsStorage {
|
|
|
121
144
|
throw new WritableStreamNotSupportedError({ name: this.io.name });
|
|
122
145
|
}
|
|
123
146
|
|
|
124
|
-
const output = await this.io.getWritable({ key,
|
|
125
|
-
const parsed = v.parseOutput(
|
|
147
|
+
const output = await this.io.getWritable({ key, vars, signal });
|
|
148
|
+
const parsed = v.parseOutput(WritableStreamSchema, output);
|
|
126
149
|
|
|
127
150
|
return parsed;
|
|
128
151
|
}
|
|
129
152
|
|
|
130
153
|
public async onOtherWriteError(
|
|
131
|
-
|
|
154
|
+
vars: Variables,
|
|
132
155
|
signal: AbortSignal,
|
|
133
156
|
key: IStorage.Key,
|
|
134
157
|
err: PluginOperationAggregateError,
|
|
@@ -152,7 +175,7 @@ export default class UniKvsStorage {
|
|
|
152
175
|
}[];
|
|
153
176
|
}>,
|
|
154
177
|
signal,
|
|
155
|
-
|
|
178
|
+
vars,
|
|
156
179
|
});
|
|
157
180
|
}
|
|
158
181
|
}
|
package/src/_streams.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { IReadableStream, IWritableStream } from "@unikvs/core";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 値が `ReadableStream` のインターフェースを満たすかどうかを判定します。
|
|
5
|
+
*
|
|
6
|
+
* ランタイムによっては `ReadableStream` クラスを継承せずに同じインターフェースを備えたオブジェクトが存在するため、`instanceof` ではなく必要なメソッドの有無で判定します。
|
|
7
|
+
*
|
|
8
|
+
* @param input 判定する値です。
|
|
9
|
+
* @returns `ReadableStream` のインターフェースを満たす場合は `true` を返します。
|
|
10
|
+
*/
|
|
11
|
+
export function isReadableStream(input: unknown): input is IReadableStream {
|
|
12
|
+
if (typeof input !== "object" || input === null) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const stream = input as Partial<IReadableStream>;
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
typeof stream.getReader === "function" &&
|
|
20
|
+
typeof stream.pipeThrough === "function" &&
|
|
21
|
+
typeof stream.pipeTo === "function" &&
|
|
22
|
+
typeof stream.tee === "function" &&
|
|
23
|
+
typeof stream.cancel === "function"
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 値が `WritableStream` のインターフェースを満たすかどうかを判定します。
|
|
29
|
+
*
|
|
30
|
+
* ランタイムによっては `WritableStream` クラスを継承せずに同じインターフェースを備えたオブジェクトが存在するため、`instanceof` ではなく必要なメソッドの有無で判定します。
|
|
31
|
+
*
|
|
32
|
+
* @param input 判定する値です。
|
|
33
|
+
* @returns `WritableStream` のインターフェースを満たす場合は `true` を返します。
|
|
34
|
+
*/
|
|
35
|
+
export function isWritableStream(input: unknown): input is IWritableStream {
|
|
36
|
+
if (typeof input !== "object" || input === null) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const stream = input as Partial<IWritableStream>;
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
typeof stream.getWriter === "function" &&
|
|
44
|
+
typeof stream.abort === "function" &&
|
|
45
|
+
typeof stream.close === "function"
|
|
46
|
+
);
|
|
47
|
+
}
|
package/src/_to-value-stream.ts
CHANGED
|
@@ -17,17 +17,47 @@ export default function toValueStream<T>(
|
|
|
17
17
|
onAsyncDispose: () => Promise<void>,
|
|
18
18
|
): ValueStream<T> {
|
|
19
19
|
const cacheMap = new Map();
|
|
20
|
+
const reader = readableStream.getReader();
|
|
21
|
+
|
|
20
22
|
async function disposeValueStream(): Promise<void> {
|
|
21
|
-
await callAsyncableFnOnce(cacheMap, "dispose",
|
|
23
|
+
await callAsyncableFnOnce(cacheMap, "dispose", async () => {
|
|
24
|
+
try {
|
|
25
|
+
await reader.cancel();
|
|
26
|
+
} catch (ex) {
|
|
27
|
+
logger.error`Failed to cancel the source stream: ${ex}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
await onAsyncDispose();
|
|
31
|
+
});
|
|
22
32
|
}
|
|
23
33
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
// cancel・エラー・早期 break であっても dispose されるように、readable 側のキャンセルを直接フックしたストリームを返します。
|
|
35
|
+
const valueStream = new ReadableStream<T>({
|
|
36
|
+
async pull(controller) {
|
|
37
|
+
try {
|
|
38
|
+
const { done, value } = await reader.read();
|
|
39
|
+
if (done) {
|
|
40
|
+
// ストリームが正常に完了したことも dispose 対象とし、完了を通知する前に破棄を完了させます。
|
|
41
|
+
await disposeValueStream();
|
|
42
|
+
controller.close();
|
|
43
|
+
} else {
|
|
44
|
+
controller.enqueue(value);
|
|
45
|
+
}
|
|
46
|
+
} catch (ex) {
|
|
47
|
+
// ソースエラー時も dispose (ロック解放など) を行わないと、ストリームを放棄した consumer に対してキーの I/O ロックがリークします。
|
|
48
|
+
// dispose 自体が失敗しても元の例外の伝播を壊さないように、失敗はログに残すだけにします。
|
|
49
|
+
await disposeValueStream().catch((e) => logger.error`Failed to dispose value stream: ${e}`);
|
|
50
|
+
controller.error(ex);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
async cancel() {
|
|
55
|
+
await disposeValueStream();
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const stream = Object.assign(
|
|
60
|
+
valueStream,
|
|
31
61
|
|
|
32
62
|
// AsyncDisposable
|
|
33
63
|
{
|
|
@@ -63,6 +93,13 @@ export default function toValueStream<T>(
|
|
|
63
93
|
|
|
64
94
|
throw ex;
|
|
65
95
|
} finally {
|
|
96
|
+
// cancel・エラー・早期 break など完了方法に関係なくストリームを破棄し、キーの読み取りロックがリークしないようにします (2 回目以降は no-op)。
|
|
97
|
+
try {
|
|
98
|
+
await disposeValueStream();
|
|
99
|
+
} catch (ex) {
|
|
100
|
+
logger.error`Failed to dispose value stream: ${ex}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
66
103
|
// 最後に必ずリーダーのロックを解放し、ストリームを再利用可能な状態にします。
|
|
67
104
|
try {
|
|
68
105
|
r.releaseLock();
|
|
@@ -73,4 +110,6 @@ export default function toValueStream<T>(
|
|
|
73
110
|
},
|
|
74
111
|
},
|
|
75
112
|
);
|
|
113
|
+
|
|
114
|
+
return stream;
|
|
76
115
|
}
|
package/src/_transformer.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Variables, IDecodable, ITransformer, IEncodable } from "@unikvs/core";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
DecodableStreamNotSupportedError,
|
|
@@ -16,48 +16,48 @@ export default class UniKvsTransformer {
|
|
|
16
16
|
this.managed = false;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
public async open(
|
|
19
|
+
public async open(vars: Variables, signal: AbortSignal): Promise<void> {
|
|
20
20
|
if (typeof this.tf.open !== "function") {
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
if (!this.tf.isOpen) {
|
|
25
25
|
this.managed = true;
|
|
26
|
-
await this.tf.open({
|
|
26
|
+
await this.tf.open({ vars, signal });
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
public async close(
|
|
30
|
+
public async close(vars: Variables, signal: AbortSignal): Promise<void> {
|
|
31
31
|
if (typeof this.tf.close !== "function") {
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
if (this.tf.isOpen && this.managed) {
|
|
36
|
-
await this.tf.close({
|
|
36
|
+
await this.tf.close({ vars, signal });
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
public async encode(
|
|
40
|
+
public async encode(vars: Variables, signal: AbortSignal, data: any): Promise<unknown> {
|
|
41
41
|
if (!this.tf.isOpen) {
|
|
42
42
|
throw new TransformerIsNotOpenError({ name: this.tf.name });
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
const output = await this.tf.encode({ data,
|
|
45
|
+
const output = await this.tf.encode({ data, vars, signal });
|
|
46
46
|
|
|
47
47
|
return output;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
public async decode(
|
|
50
|
+
public async decode(vars: Variables, signal: AbortSignal, data: any): Promise<unknown> {
|
|
51
51
|
if (!this.tf.isOpen) {
|
|
52
52
|
throw new TransformerIsNotOpenError({ name: this.tf.name });
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
const output = await this.tf.decode({ data,
|
|
55
|
+
const output = await this.tf.decode({ data, vars, signal });
|
|
56
56
|
|
|
57
57
|
return output;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
public async getEncodable(
|
|
60
|
+
public async getEncodable(vars: Variables, signal: AbortSignal): Promise<IEncodable> {
|
|
61
61
|
if (!this.tf.isOpen) {
|
|
62
62
|
throw new TransformerIsNotOpenError({ name: this.tf.name });
|
|
63
63
|
}
|
|
@@ -66,13 +66,13 @@ export default class UniKvsTransformer {
|
|
|
66
66
|
throw new EncodableStreamNotSupportedError({ name: this.tf.name });
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
const output = await this.tf.getEncodable({
|
|
69
|
+
const output = await this.tf.getEncodable({ vars, signal });
|
|
70
70
|
const parsed = output; // TODO(tai-kun): 要検証
|
|
71
71
|
|
|
72
72
|
return parsed;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
public async getDecodable(
|
|
75
|
+
public async getDecodable(vars: Variables, signal: AbortSignal): Promise<IDecodable> {
|
|
76
76
|
if (!this.tf.isOpen) {
|
|
77
77
|
throw new TransformerIsNotOpenError({ name: this.tf.name });
|
|
78
78
|
}
|
|
@@ -81,7 +81,7 @@ export default class UniKvsTransformer {
|
|
|
81
81
|
throw new DecodableStreamNotSupportedError({ name: this.tf.name });
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
const output = await this.tf.getDecodable({
|
|
84
|
+
const output = await this.tf.getDecodable({ vars, signal });
|
|
85
85
|
const parsed = output; // TODO(tai-kun): 要検証
|
|
86
86
|
|
|
87
87
|
return parsed;
|
package/src/_valibot.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { ErrorOptions } from "@unikvs/core";
|
|
2
1
|
import { tryCaptureStackTrace } from "try-capture-stack-trace";
|
|
3
2
|
import { type InferOutput, safeParse } from "valibot";
|
|
4
3
|
|
|
@@ -9,9 +8,11 @@ import {
|
|
|
9
8
|
InvalidOutputError,
|
|
10
9
|
} from "./errors.js";
|
|
11
10
|
|
|
12
|
-
export type { InferInput, InferOutput } from "valibot";
|
|
11
|
+
export type { GenericSchema, InferInput, InferOutput } from "valibot";
|
|
13
12
|
export {
|
|
14
13
|
any,
|
|
14
|
+
check,
|
|
15
|
+
custom,
|
|
15
16
|
omit,
|
|
16
17
|
pipe,
|
|
17
18
|
union,
|
|
@@ -23,20 +24,21 @@ export {
|
|
|
23
24
|
minValue,
|
|
24
25
|
optional,
|
|
25
26
|
safeInteger,
|
|
27
|
+
safeParse,
|
|
26
28
|
} from "valibot";
|
|
27
29
|
|
|
28
30
|
export { array, tuple, object, record, transform } from "@tai-kun/valibot-extra-lab";
|
|
29
31
|
|
|
30
32
|
type BaseSchema = typeof safeParse extends (schema: infer S, ...args: any) => any ? S : never;
|
|
31
33
|
|
|
32
|
-
export interface
|
|
33
|
-
new (args: InvalidInputErrorArgs
|
|
34
|
+
export interface IParseInputErrorConstructor {
|
|
35
|
+
new (args: InvalidInputErrorArgs): Error;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
export function parseInput<const TSchema extends BaseSchema>(
|
|
37
39
|
schema: TSchema,
|
|
38
40
|
value: unknown,
|
|
39
|
-
Error:
|
|
41
|
+
Error: IParseInputErrorConstructor = InvalidInputError,
|
|
40
42
|
): InferOutput<TSchema> {
|
|
41
43
|
const result = safeParse(schema, value);
|
|
42
44
|
if (result.success) {
|
|
@@ -49,7 +51,7 @@ export function parseInput<const TSchema extends BaseSchema>(
|
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
export interface ParseOutputErrorConstructor {
|
|
52
|
-
new (args: InvalidOutputErrorArgs
|
|
54
|
+
new (args: InvalidOutputErrorArgs): Error;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
export function parseOutput<const TSchema extends BaseSchema>(
|