unikvs 0.0.3 → 0.0.4

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 (146) hide show
  1. package/dist/src/_combine-signals.d.ts +9 -0
  2. package/dist/src/_combine-signals.d.ts.map +1 -0
  3. package/dist/src/_combine-signals.js +59 -0
  4. package/dist/src/_logger.d.ts +3 -0
  5. package/dist/src/_logger.d.ts.map +1 -0
  6. package/dist/src/_logger.js +3 -0
  7. package/dist/src/_merge-context.d.ts +4 -0
  8. package/dist/src/_merge-context.d.ts.map +1 -0
  9. package/dist/src/_merge-context.js +3 -0
  10. package/dist/src/_storage.d.ts +17 -0
  11. package/dist/src/_storage.d.ts.map +1 -0
  12. package/dist/src/_storage.js +84 -0
  13. package/dist/src/_to-value-stream.d.ts +12 -0
  14. package/dist/src/_to-value-stream.d.ts.map +1 -0
  15. package/dist/src/_to-value-stream.js +53 -0
  16. package/dist/src/_transformer.d.ts +12 -0
  17. package/dist/src/_transformer.d.ts.map +1 -0
  18. package/dist/src/_transformer.js +52 -0
  19. package/dist/src/_valibot.d.ts +13 -0
  20. package/dist/src/_valibot.d.ts.map +1 -0
  21. package/dist/src/_valibot.js +12 -0
  22. package/dist/src/context.types.d.ts +17 -0
  23. package/dist/src/context.types.d.ts.map +1 -0
  24. package/dist/src/errors.d.ts +108 -0
  25. package/dist/src/errors.d.ts.map +1 -0
  26. package/dist/src/errors.js +169 -0
  27. package/dist/src/index.d.ts +10 -0
  28. package/dist/src/index.d.ts.map +1 -0
  29. package/dist/src/index.js +3 -0
  30. package/dist/src/unikvs-config.d.ts +255 -0
  31. package/dist/src/unikvs-config.d.ts.map +1 -0
  32. package/dist/src/unikvs-config.js +105 -0
  33. package/dist/src/unikvs.d.ts +324 -0
  34. package/dist/src/unikvs.d.ts.map +1 -0
  35. package/dist/src/unikvs.js +693 -0
  36. package/dist/src/utils.types.d.ts +7 -0
  37. package/dist/src/utils.types.d.ts.map +1 -0
  38. package/dist/src/value-stream.types.d.ts +11 -0
  39. package/dist/src/value-stream.types.d.ts.map +1 -0
  40. package/package.json +22 -39
  41. package/src/_combine-signals.ts +67 -0
  42. package/src/_logger.ts +5 -0
  43. package/src/_merge-context.ts +10 -0
  44. package/src/_storage.ts +130 -0
  45. package/src/_to-value-stream.ts +59 -0
  46. package/src/_transformer.ts +75 -0
  47. package/src/_valibot.ts +30 -0
  48. package/src/context.types.ts +19 -0
  49. package/src/errors.ts +382 -0
  50. package/src/index.ts +52 -0
  51. package/src/unikvs-config.ts +429 -0
  52. package/src/unikvs.ts +1171 -0
  53. package/src/utils.types.ts +6 -0
  54. package/src/value-stream.types.ts +14 -0
  55. package/dist/src/core/_assign-context.d.ts +0 -3
  56. package/dist/src/core/_assign-context.d.ts.map +0 -1
  57. package/dist/src/core/_assign-context.js +0 -3
  58. package/dist/src/core/_combine-signals.d.ts +0 -3
  59. package/dist/src/core/_combine-signals.d.ts.map +0 -1
  60. package/dist/src/core/_combine-signals.js +0 -34
  61. package/dist/src/core/_is-iterable.d.ts +0 -2
  62. package/dist/src/core/_is-iterable.d.ts.map +0 -1
  63. package/dist/src/core/_is-iterable.js +0 -3
  64. package/dist/src/core/_is-plain-object.d.ts +0 -2
  65. package/dist/src/core/_is-plain-object.d.ts.map +0 -1
  66. package/dist/src/core/_is-plain-object.js +0 -7
  67. package/dist/src/core/_logger.d.ts +0 -3
  68. package/dist/src/core/_logger.d.ts.map +0 -1
  69. package/dist/src/core/_logger.js +0 -3
  70. package/dist/src/core/_merge-context.d.ts +0 -3
  71. package/dist/src/core/_merge-context.d.ts.map +0 -1
  72. package/dist/src/core/_merge-context.js +0 -4
  73. package/dist/src/core/_to-context.d.ts +0 -7
  74. package/dist/src/core/_to-context.d.ts.map +0 -1
  75. package/dist/src/core/_to-context.js +0 -42
  76. package/dist/src/core/_to-value-stream.d.ts +0 -4
  77. package/dist/src/core/_to-value-stream.d.ts.map +0 -1
  78. package/dist/src/core/_to-value-stream.js +0 -38
  79. package/dist/src/core/_with-readable-stream-from.d.ts +0 -6
  80. package/dist/src/core/_with-readable-stream-from.d.ts.map +0 -1
  81. package/dist/src/core/_with-readable-stream-from.js +0 -58
  82. package/dist/src/core/context.types.d.ts +0 -5
  83. package/dist/src/core/context.types.d.ts.map +0 -1
  84. package/dist/src/core/errors.d.ts +0 -13
  85. package/dist/src/core/errors.d.ts.map +0 -1
  86. package/dist/src/core/errors.js +0 -20
  87. package/dist/src/core/index.d.ts +0 -15
  88. package/dist/src/core/index.d.ts.map +0 -1
  89. package/dist/src/core/index.js +0 -4
  90. package/dist/src/core/plugin.types.d.ts +0 -8
  91. package/dist/src/core/plugin.types.d.ts.map +0 -1
  92. package/dist/src/core/plugin.types.js +0 -1
  93. package/dist/src/core/storage.types.d.ts +0 -22
  94. package/dist/src/core/storage.types.d.ts.map +0 -1
  95. package/dist/src/core/storage.types.js +0 -1
  96. package/dist/src/core/to-readable-stream.d.ts +0 -2
  97. package/dist/src/core/to-readable-stream.d.ts.map +0 -1
  98. package/dist/src/core/to-readable-stream.js +0 -4
  99. package/dist/src/core/transformer.types.d.ts +0 -18
  100. package/dist/src/core/transformer.types.d.ts.map +0 -1
  101. package/dist/src/core/transformer.types.js +0 -1
  102. package/dist/src/core/unikvs-config.d.ts +0 -82
  103. package/dist/src/core/unikvs-config.d.ts.map +0 -1
  104. package/dist/src/core/unikvs-config.js +0 -49
  105. package/dist/src/core/unikvs.d.ts +0 -73
  106. package/dist/src/core/unikvs.d.ts.map +0 -1
  107. package/dist/src/core/unikvs.js +0 -678
  108. package/dist/src/core/utils.types.d.ts +0 -3
  109. package/dist/src/core/utils.types.d.ts.map +0 -1
  110. package/dist/src/core/value-stream.types.d.ts +0 -4
  111. package/dist/src/core/value-stream.types.d.ts.map +0 -1
  112. package/dist/src/destinations/memory-storage.d.ts +0 -17
  113. package/dist/src/destinations/memory-storage.d.ts.map +0 -1
  114. package/dist/src/destinations/memory-storage.js +0 -113
  115. package/dist/src/types/storage.d.ts +0 -5
  116. package/dist/src/types/storage.d.ts.map +0 -1
  117. package/dist/src/types/storage.js +0 -1
  118. package/dist/src/types/transformer.d.ts +0 -5
  119. package/dist/src/types/transformer.d.ts.map +0 -1
  120. package/dist/src/types/transformer.js +0 -1
  121. package/src/core/_assign-context.ts +0 -5
  122. package/src/core/_combine-signals.ts +0 -40
  123. package/src/core/_is-iterable.ts +0 -3
  124. package/src/core/_is-plain-object.ts +0 -11
  125. package/src/core/_logger.ts +0 -5
  126. package/src/core/_merge-context.ts +0 -9
  127. package/src/core/_to-context.ts +0 -59
  128. package/src/core/_to-value-stream.ts +0 -41
  129. package/src/core/_with-readable-stream-from.ts +0 -70
  130. package/src/core/context.types.ts +0 -7
  131. package/src/core/errors.ts +0 -37
  132. package/src/core/index.ts +0 -23
  133. package/src/core/plugin.types.ts +0 -10
  134. package/src/core/storage.types.ts +0 -53
  135. package/src/core/to-readable-stream.ts +0 -7
  136. package/src/core/transformer.types.ts +0 -110
  137. package/src/core/unikvs-config.ts +0 -230
  138. package/src/core/unikvs.ts +0 -740
  139. package/src/core/utils.types.ts +0 -3
  140. package/src/core/value-stream.types.ts +0 -3
  141. package/src/destinations/memory-storage.ts +0 -160
  142. package/src/types/storage.ts +0 -5
  143. package/src/types/transformer.ts +0 -5
  144. /package/dist/src/{core/context.types.js → context.types.js} +0 -0
  145. /package/dist/src/{core/utils.types.js → utils.types.js} +0 -0
  146. /package/dist/src/{core/value-stream.types.js → value-stream.types.js} +0 -0
@@ -0,0 +1,7 @@
1
+ /**
2
+ * オブジェクトのプロパティー値の型のユニオン型を抽出するユーティリティー型です。
3
+ *
4
+ * @template T 対象となるオブジェクトの型です。
5
+ */
6
+ export type ValueOf<T> = T[keyof T];
7
+ //# sourceMappingURL=utils.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.types.d.ts","sourceRoot":"","sources":["../../src/utils.types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 値を非同期に流すための読み取り専用ストリームを定義するインターフェースです。
3
+ *
4
+ * `ReadableStream` を拡張しており、標準的なストリーム操作に加えて非同期イテレーターによる反復処理をサポートします。
5
+ *
6
+ * @template T ストリームを流れるデータの型です。
7
+ */
8
+ export interface ValueStream<T = any> extends Omit<ReadableStream, keyof AsyncDisposable | keyof AsyncIteratorObject<T>>, AsyncDisposable, AsyncIteratorObject<T, void, void> {
9
+ dispose(): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=value-stream.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-stream.types.d.ts","sourceRoot":"","sources":["../../src/value-stream.types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,GAAG,CAClC,SACE,IAAI,CAAC,cAAc,EAAE,MAAM,eAAe,GAAG,MAAM,mBAAmB,CAAC,CAAC,CAAC,CAAC,EAC1E,eAAe,EACf,mBAAmB,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC;IACpC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B"}
package/package.json CHANGED
@@ -1,11 +1,7 @@
1
1
  {
2
2
  "name": "unikvs",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "",
5
- "keywords": [
6
- "kv",
7
- "kvs"
8
- ],
9
5
  "homepage": "https://github.com/tai-kun/unikvs",
10
6
  "license": "MIT",
11
7
  "author": "tai-kun",
@@ -20,54 +16,41 @@
20
16
  ],
21
17
  "type": "module",
22
18
  "sideEffects": false,
23
- "main": "./dist/src/core/index.js",
24
- "module": "./dist/src/core/index.js",
25
- "types": "./dist/src/core/index.d.ts",
19
+ "main": "./dist/src/index.js",
20
+ "types": "./dist/src/index.d.ts",
26
21
  "exports": {
27
22
  ".": {
28
- "types": "./dist/src/core/index.d.ts",
29
- "import": "./dist/src/core/index.js",
30
- "require": "./dist/src/core/index.js"
31
- },
32
- "./storage/memory": {
33
- "types": "./dist/src/destinations/memory-storage.d.ts",
34
- "import": "./dist/src/destinations/memory-storage.js",
35
- "require": "./dist/src/destinations/memory-storage.js"
36
- },
37
- "./types/storage": {
38
- "types": "./dist/src/types/storage.d.ts",
39
- "import": "./dist/src/types/storage.js",
40
- "require": "./dist/src/types/storage.js"
41
- },
42
- "./types/transformer": {
43
- "types": "./dist/src/types/transformer.d.ts",
44
- "import": "./dist/src/types/transformer.js",
45
- "require": "./dist/src/types/transformer.js"
23
+ "types": "./dist/src/index.d.ts",
24
+ "default": "./dist/src/index.js"
46
25
  }
47
26
  },
48
27
  "scripts": {
49
28
  "build": "tsc --project ./.config/tsconfig.build.json"
50
29
  },
51
30
  "dependencies": {
52
- "@logtape/logtape": "^2.0.5",
31
+ "@unikvs/core": "0.0.4",
53
32
  "asyncmux": "^0.0.5",
54
- "i18n-error-base": "^0.0.3",
55
- "type-name": "^2.0.2"
33
+ "call-fn-once": "^0.0.4",
34
+ "try-capture-stack-trace": "^0.0.3"
56
35
  },
57
36
  "devDependencies": {
58
37
  "@tsconfig/node22": "^22.0.5",
59
38
  "@tsconfig/strictest": "^2.0.8",
60
- "@types/filename-reserved-regex": "^3.0.0",
61
39
  "@types/node": "^22.19.17",
62
- "@types/type-name": "^1.0.32",
63
- "@vitest/browser": "^4.1.2",
64
- "@vitest/browser-playwright": "^4.1.2",
65
- "npm-check-updates": "^20.0.0",
66
- "oxfmt": "^0.44.0",
67
- "oxlint": "^1.59.0",
68
- "oxlint-tsgolint": "^0.20.0",
40
+ "@unikvs/checksum": "0.0.4",
41
+ "@unikvs/compression": "0.0.4",
42
+ "@unikvs/fs.node": "0.0.4",
43
+ "@unikvs/memory": "0.0.4",
44
+ "@unikvs/opfs": "0.0.4",
45
+ "@unikvs/utils": "0.0.4",
46
+ "@vitest/browser": "^4.1.4",
47
+ "@vitest/browser-playwright": "^4.1.4",
48
+ "npm-check-updates": "^20.0.2",
69
49
  "playwright": "^1.59.1",
70
- "typescript": "^6.0.2",
71
- "vitest": "^4.1.2"
50
+ "vitest": "^4.1.4"
51
+ },
52
+ "peerDependencies": {
53
+ "@logtape/logtape": "^2.0.0",
54
+ "valibot": "^1.0.0"
72
55
  }
73
56
  }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * 複数の AbortSignal を 1 つに結合します。
3
+ *
4
+ * @param signals 結合対象となる AbortSignal、または null / undefined の配列です。
5
+ * @returns 結合された新しい AbortSignal です。
6
+ */
7
+ let combineSignals: (signals: readonly (AbortSignal | null | undefined)[]) => AbortSignal;
8
+
9
+ if ("any" in AbortSignal && typeof AbortSignal.any === "function") {
10
+ // AbortSignal.any がネイティブでサポートされている場合はそれを使用します。
11
+
12
+ const AbortSignalAny = AbortSignal.any.bind(AbortSignal);
13
+ combineSignals = function combineSignals(inputSignals) {
14
+ const signals = inputSignals.filter((signal) => signal instanceof AbortSignal);
15
+ return AbortSignalAny(signals);
16
+ };
17
+ } else {
18
+ // AbortSignal.any が未実装の環境向けのポリフィル実装です。
19
+
20
+ combineSignals = function combineSignals(inputSignals) {
21
+ const ac = new AbortController();
22
+ const signals: AbortSignal[] = [];
23
+ for (const signal of inputSignals) {
24
+ if (signal?.aborted) {
25
+ // すでに中断されている場合は、その理由(reason)を使用して即座に中断処理を行います。
26
+ ac.abort(signal.reason);
27
+ return ac.signal;
28
+ }
29
+
30
+ if (signal instanceof AbortSignal) {
31
+ signals.push(signal);
32
+ }
33
+ }
34
+
35
+ /**
36
+ * すべての監視対象信号からイベントリスナーを削除するクリーンアップ関数です。
37
+ *
38
+ * メモリーリークを防ぐために、いずれかの信号が中断された際に実行されます。
39
+ */
40
+ function cleanup(): void {
41
+ for (const signal of signals) {
42
+ signal.removeEventListener("abort", handleAbort);
43
+ }
44
+ }
45
+
46
+ /**
47
+ * いずれかの信号が abort イベントを発火させた際に呼び出されるハンドラーです。
48
+ *
49
+ * @this AbortSignal 中断を検知した AbortSignal インスタンス自身を指します。
50
+ */
51
+ function handleAbort(this: AbortSignal): void {
52
+ // 親のコントローラーに対して、検知した信号の理由を添えて中断を指示します。
53
+ ac.abort(this.reason);
54
+ // 一つの信号が中断されれば他の監視は不要になるため、クリーンアップを呼び出します。
55
+ cleanup();
56
+ }
57
+
58
+ // すべての有効な信号に対して、中断イベントを監視するリスナーを登録します。
59
+ for (const signal of signals) {
60
+ signal.addEventListener("abort", handleAbort, { once: true });
61
+ }
62
+
63
+ return ac.signal;
64
+ };
65
+ }
66
+
67
+ export default combineSignals;
package/src/_logger.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { getLogger } from "@logtape/logtape";
2
+
3
+ const logger = getLogger("unikvs");
4
+
5
+ export default logger;
@@ -0,0 +1,10 @@
1
+ import { Context } from "@unikvs/core";
2
+
3
+ import type { ContextSource } from "./context.types.js";
4
+
5
+ export default function mergeContext(
6
+ a: Readonly<Context>,
7
+ b: Readonly<Context> | ContextSource | undefined,
8
+ ): Context {
9
+ return { ...a, ...(Array.isArray(b) ? Object.fromEntries(b) : b) };
10
+ }
@@ -0,0 +1,130 @@
1
+ import type { Context, IReadableStream, IStorage, IWritableStream, Key } from "@unikvs/core";
2
+
3
+ import {
4
+ type PluginOperationAggregateError,
5
+ ReadableStreamNotSupportedError,
6
+ StorageIsNotOpenError,
7
+ WritableStreamNotSupportedError,
8
+ } from "./errors.js";
9
+
10
+ export class UniKvsStorage {
11
+ private readonly io: IStorage;
12
+
13
+ public constructor(io: IStorage) {
14
+ this.io = io;
15
+ }
16
+
17
+ public async open(context: Context, signal: AbortSignal): Promise<void> {
18
+ if (typeof this.io.open !== "function") {
19
+ return;
20
+ }
21
+
22
+ if (!this.io.isOpen) {
23
+ await this.io.open({ signal, context });
24
+ }
25
+ }
26
+
27
+ public async close(context: Context, signal: AbortSignal): Promise<void> {
28
+ if (typeof this.io.close !== "function") {
29
+ return;
30
+ }
31
+
32
+ if (this.io.isOpen) {
33
+ await this.io.close({ signal, context });
34
+ }
35
+ }
36
+
37
+ public async onOtherWriteError(
38
+ context: Context,
39
+ signal: AbortSignal,
40
+ key: Key,
41
+ error: PluginOperationAggregateError,
42
+ ): Promise<void> {
43
+ if (!this.io.isOpen) {
44
+ throw new StorageIsNotOpenError({ name: this.io.name });
45
+ }
46
+
47
+ if (typeof this.io.onOtherWriteError !== "function") {
48
+ return;
49
+ }
50
+
51
+ await this.io.onOtherWriteError({
52
+ key,
53
+ error: error as any,
54
+ signal,
55
+ context,
56
+ });
57
+ }
58
+
59
+ public async write(context: Context, signal: AbortSignal, key: Key, data: any): Promise<void> {
60
+ if (!this.io.isOpen) {
61
+ throw new StorageIsNotOpenError({ name: this.io.name });
62
+ }
63
+
64
+ await this.io.write({ key, data, signal, context });
65
+ }
66
+
67
+ public async read(context: Context, signal: AbortSignal, key: Key): Promise<any> {
68
+ if (!this.io.isOpen) {
69
+ throw new StorageIsNotOpenError({ name: this.io.name });
70
+ }
71
+
72
+ return await this.io.read({ key, signal, context });
73
+ }
74
+
75
+ public async exists(context: Context, signal: AbortSignal, key: Key): Promise<boolean> {
76
+ if (!this.io.isOpen) {
77
+ throw new StorageIsNotOpenError({ name: this.io.name });
78
+ }
79
+
80
+ return await this.io.exists({ key, signal, context });
81
+ }
82
+
83
+ public async delete(context: Context, signal: AbortSignal, key: Key): Promise<void> {
84
+ if (!this.io.isOpen) {
85
+ throw new StorageIsNotOpenError({ name: this.io.name });
86
+ }
87
+
88
+ await this.io.delete({ key, signal, context });
89
+ }
90
+
91
+ public async clear(context: Context, signal: AbortSignal): Promise<void> {
92
+ if (!this.io.isOpen) {
93
+ throw new StorageIsNotOpenError({ name: this.io.name });
94
+ }
95
+
96
+ await this.io.clear({ signal, context });
97
+ }
98
+
99
+ public async getWritable(
100
+ context: Context,
101
+ signal: AbortSignal,
102
+ key: Key,
103
+ ): Promise<IWritableStream> {
104
+ if (!this.io.isOpen) {
105
+ throw new StorageIsNotOpenError({ name: this.io.name });
106
+ }
107
+
108
+ if (typeof this.io.getWritable !== "function") {
109
+ throw new WritableStreamNotSupportedError({ name: this.io.name });
110
+ }
111
+
112
+ return await this.io.getWritable({ key, signal, context });
113
+ }
114
+
115
+ public async getReadable(
116
+ context: Context,
117
+ signal: AbortSignal,
118
+ key: Key,
119
+ ): Promise<IReadableStream> {
120
+ if (!this.io.isOpen) {
121
+ throw new StorageIsNotOpenError({ name: this.io.name });
122
+ }
123
+
124
+ if (typeof this.io.getReadable !== "function") {
125
+ throw new ReadableStreamNotSupportedError({ name: this.io.name });
126
+ }
127
+
128
+ return await this.io.getReadable({ key, signal, context });
129
+ }
130
+ }
@@ -0,0 +1,59 @@
1
+ import type { IReadableStream } from "@unikvs/core";
2
+ import { callAsyncableFnOnce } from "call-fn-once";
3
+
4
+ import logger from "./_logger.js";
5
+ import type { ValueStream } from "./value-stream.types.js";
6
+
7
+ /**
8
+ * 与えられた `IReadableStream` を `ValueStream` に変換します。
9
+ *
10
+ * @template T ストリームが保持する値の型です。
11
+ * @param readableStream 変換対象となる `IReadableStream` インスタンスです。
12
+ * @param onAsyncDispose ストリーム破棄時の処理です。
13
+ * @returns 非同期イテレーターが付与された `ValueStream` インスタンスを返します。
14
+ */
15
+ export default function toValueStream<T>(
16
+ readableStream: IReadableStream<T>,
17
+ onAsyncDispose: () => Promise<void>,
18
+ ): ValueStream<T> {
19
+ const cacheMap = new Map();
20
+ async function handleDispose(): Promise<void> {
21
+ await callAsyncableFnOnce(cacheMap, "dispose", onAsyncDispose);
22
+ }
23
+
24
+ // 既存のストリームに対して Symbol.asyncIterator を動的に割り当てて返します。
25
+ return Object.assign(readableStream.pipeThrough(new TransformStream({ flush: handleDispose })), {
26
+ dispose: handleDispose,
27
+ [Symbol.asyncDispose]: handleDispose,
28
+ async *[Symbol.asyncIterator](this: IReadableStream<T>) {
29
+ const r = this.getReader();
30
+ try {
31
+ // ストリームが終了するまでループを回し、チャンクを読み取ります。
32
+ while (true) {
33
+ const { done, value } = await r.read();
34
+ if (done) {
35
+ break;
36
+ }
37
+
38
+ yield value;
39
+ }
40
+ } catch (ex) {
41
+ // エラーが発生した場合は、リーダーのキャンセルを試みます。
42
+ try {
43
+ await r.cancel(ex);
44
+ } catch (ex) {
45
+ logger.error`Failed to cancel reader: ${ex}`;
46
+ }
47
+
48
+ throw ex;
49
+ } finally {
50
+ // 最後に必ずリーダーのロックを解放し、ストリームを再利用可能な状態にします。
51
+ try {
52
+ r.releaseLock();
53
+ } catch (ex) {
54
+ logger.error`Failed to release reader's lock: ${ex}`;
55
+ }
56
+ }
57
+ },
58
+ }) as unknown as ValueStream<T>;
59
+ }
@@ -0,0 +1,75 @@
1
+ import type { Context, IDecodable, ITransformer, IEncodable } from "@unikvs/core";
2
+
3
+ import {
4
+ DecodableStreamNotSupportedError,
5
+ EncodableStreamNotSupportedError,
6
+ TransformerIsNotOpenError,
7
+ } from "./errors.js";
8
+
9
+ export default class UniKvsTransformer {
10
+ private readonly tf: ITransformer;
11
+
12
+ public constructor(tf: ITransformer) {
13
+ this.tf = tf;
14
+ }
15
+
16
+ public async open(context: Context, signal: AbortSignal): Promise<void> {
17
+ if (typeof this.tf.open !== "function") {
18
+ return;
19
+ }
20
+
21
+ if (!this.tf.isOpen) {
22
+ await this.tf.open({ signal, context });
23
+ }
24
+ }
25
+
26
+ public async close(context: Context, signal: AbortSignal): Promise<void> {
27
+ if (typeof this.tf.close !== "function") {
28
+ return;
29
+ }
30
+
31
+ if (this.tf.isOpen) {
32
+ await this.tf.close({ signal, context });
33
+ }
34
+ }
35
+
36
+ public async encode(context: Context, signal: AbortSignal, data: any): Promise<void> {
37
+ if (!this.tf.isOpen) {
38
+ throw new TransformerIsNotOpenError({ name: this.tf.name });
39
+ }
40
+
41
+ return await this.tf.encode({ data, signal, context });
42
+ }
43
+
44
+ public async decode(context: Context, signal: AbortSignal, data: any): Promise<any> {
45
+ if (!this.tf.isOpen) {
46
+ throw new TransformerIsNotOpenError({ name: this.tf.name });
47
+ }
48
+
49
+ return await this.tf.decode({ data, signal, context });
50
+ }
51
+
52
+ public async getEncodable(context: Context, signal: AbortSignal): Promise<IEncodable> {
53
+ if (!this.tf.isOpen) {
54
+ throw new TransformerIsNotOpenError({ name: this.tf.name });
55
+ }
56
+
57
+ if (typeof this.tf.getEncodable !== "function") {
58
+ throw new EncodableStreamNotSupportedError({ name: this.tf.name });
59
+ }
60
+
61
+ return await this.tf.getEncodable({ signal, context });
62
+ }
63
+
64
+ public async getDecodable(context: Context, signal: AbortSignal): Promise<IDecodable> {
65
+ if (!this.tf.isOpen) {
66
+ throw new TransformerIsNotOpenError({ name: this.tf.name });
67
+ }
68
+
69
+ if (typeof this.tf.getDecodable !== "function") {
70
+ throw new DecodableStreamNotSupportedError({ name: this.tf.name });
71
+ }
72
+
73
+ return await this.tf.getDecodable({ signal, context });
74
+ }
75
+ }
@@ -0,0 +1,30 @@
1
+ import { tryCaptureStackTrace } from "try-capture-stack-trace";
2
+ import { type InferOutput, safeParse } from "valibot";
3
+
4
+ import { InvalidInputError, type Issue } from "./errors.js";
5
+
6
+ type BaseSchema = typeof safeParse extends (schema: infer S, ...args: any) => any ? S : never;
7
+
8
+ export type ParseErrorConstructorArgs = {
9
+ readonly value: unknown;
10
+ readonly issues: readonly [Issue, ...Issue[]];
11
+ };
12
+
13
+ export interface ParseErrorConstructor {
14
+ new (args: ParseErrorConstructorArgs): Error;
15
+ }
16
+
17
+ export function parse<const TSchema extends BaseSchema>(
18
+ schema: TSchema,
19
+ value: unknown,
20
+ Error: ParseErrorConstructor = InvalidInputError,
21
+ ): InferOutput<TSchema> {
22
+ const result = safeParse(schema, value);
23
+ if (result.success) {
24
+ return result.output;
25
+ }
26
+
27
+ const error = new Error({ value, issues: result.issues });
28
+ tryCaptureStackTrace(error, parse);
29
+ throw error;
30
+ }
@@ -0,0 +1,19 @@
1
+ import type { Context } from "@unikvs/core";
2
+
3
+ import type { ValueOf } from "./utils.types.js";
4
+
5
+ /**
6
+ * コンテキストの単一のエントリーを表す、読み取り専用のキーと値のペア(タプル)です。
7
+ *
8
+ * インデックス 0 はキー、1 は値を保持します。
9
+ */
10
+ export type ContextKeyValuePair = readonly [key: keyof Context, value: ValueOf<Context>];
11
+
12
+ /**
13
+ * コンテキストの初期化や更新に使用できる、データソースの型定義です。
14
+ *
15
+ * 以下のいずれかの形式を受け入れます:
16
+ * 1. 読み取り専用のコンテキストオブジェクト
17
+ * 2. キーと値のペアを列挙した反復可能なオブジェクト
18
+ */
19
+ export type ContextSource = Readonly<Context> | readonly ContextKeyValuePair[];