unikvs 0.0.10 → 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.
Files changed (59) hide show
  1. package/README.md +3 -0
  2. package/dist/src/_merge-variables.d.ts +13 -0
  3. package/dist/src/_merge-variables.d.ts.map +1 -0
  4. package/dist/src/_merge-variables.js +12 -0
  5. package/dist/src/_storage.d.ts +11 -11
  6. package/dist/src/_storage.d.ts.map +1 -1
  7. package/dist/src/_storage.js +31 -22
  8. package/dist/src/_streams.d.ts +20 -0
  9. package/dist/src/_streams.d.ts.map +1 -0
  10. package/dist/src/_streams.js +36 -0
  11. package/dist/src/_transformer.d.ts +7 -7
  12. package/dist/src/_transformer.d.ts.map +1 -1
  13. package/dist/src/_transformer.js +12 -12
  14. package/dist/src/_valibot.d.ts +2 -2
  15. package/dist/src/_valibot.d.ts.map +1 -1
  16. package/dist/src/_valibot.js +1 -1
  17. package/dist/src/_value-schemas.d.ts +179 -0
  18. package/dist/src/_value-schemas.d.ts.map +1 -0
  19. package/dist/src/_value-schemas.js +150 -0
  20. package/dist/src/errors.d.ts +60 -94
  21. package/dist/src/errors.d.ts.map +1 -1
  22. package/dist/src/errors.js +15 -31
  23. package/dist/src/index.d.ts +3 -3
  24. package/dist/src/index.d.ts.map +1 -1
  25. package/dist/src/index.js +2 -2
  26. package/dist/src/unikvs-config.d.ts +58 -139
  27. package/dist/src/unikvs-config.d.ts.map +1 -1
  28. package/dist/src/unikvs-config.js +42 -47
  29. package/dist/src/unikvs.d.ts +84 -166
  30. package/dist/src/unikvs.d.ts.map +1 -1
  31. package/dist/src/unikvs.js +230 -169
  32. package/dist/src/utils.types.d.ts +1 -3
  33. package/dist/src/utils.types.d.ts.map +1 -1
  34. package/dist/src/value-stream.types.d.ts +2 -8
  35. package/dist/src/value-stream.types.d.ts.map +1 -1
  36. package/dist/src/variables.types.d.ts +11 -0
  37. package/dist/src/variables.types.d.ts.map +1 -0
  38. package/package.json +17 -16
  39. package/src/_merge-variables.ts +19 -0
  40. package/src/_storage.ts +47 -24
  41. package/src/_streams.ts +47 -0
  42. package/src/_transformer.ts +13 -13
  43. package/src/_valibot.ts +4 -1
  44. package/src/_value-schemas.ts +362 -0
  45. package/src/errors.ts +60 -109
  46. package/src/index.ts +2 -3
  47. package/src/unikvs-config.ts +143 -168
  48. package/src/unikvs.ts +359 -290
  49. package/src/utils.types.ts +1 -3
  50. package/src/value-stream.types.ts +2 -8
  51. package/src/variables.types.ts +13 -0
  52. package/dist/src/_merge-context.d.ts +0 -13
  53. package/dist/src/_merge-context.d.ts.map +0 -1
  54. package/dist/src/_merge-context.js +0 -12
  55. package/dist/src/context.types.d.ts +0 -17
  56. package/dist/src/context.types.d.ts.map +0 -1
  57. package/src/_merge-context.ts +0 -19
  58. package/src/context.types.ts +0 -19
  59. /package/dist/src/{context.types.js → variables.types.js} +0 -0
@@ -9,25 +9,67 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _UniKvs_instances, _UniKvs_con, _UniKvs_acSet, _UniKvs_context, _UniKvs_destinations, _UniKvs_transformers, _UniKvs_close;
12
+ var _UniKvs_instances, _UniKvs_con, _UniKvs_acSet, _UniKvs_vars, _UniKvs_destinations, _UniKvs_transformers, _UniKvs_valueSchemaResolver, _UniKvs_resolveValueSchema, _UniKvs_close;
13
13
  import { combineSignals } from "abort-signal-utils";
14
14
  import { asyncmux, Asyncmux } from "asyncmux";
15
15
  import logger from "./_logger.js";
16
- import mergeContext from "./_merge-context.js";
16
+ import mergeVariables from "./_merge-variables.js";
17
+ import { isReadableStream } from "./_streams.js";
17
18
  import toValueStream from "./_to-value-stream.js";
18
19
  import * as v from "./_valibot.js";
19
- import { KeyNotFoundError, UniKvsIsOpenError, PluginOperationAggregateError, UniKvsIsNotOpenError, } from "./errors.js";
20
+ import { KeyNotFoundError, UniKvsIsOpenError, UniKvsIsNotOpenError, PluginOperationAggregateError, } from "./errors.js";
20
21
  import UniKvsConfig from "./unikvs-config.js";
21
22
  // -------------------------------------------------------------------------------------------------
22
23
  //
24
+ // 値の検証
25
+ //
26
+ // -------------------------------------------------------------------------------------------------
27
+ /**
28
+ * プレーン値専用のスキーマに ReadableStream が渡されたことを報告するためのスキーマです。
29
+ */
30
+ const PlainValueInputSchema = v.pipe(v.unknown(), v.check((input) => !isReadableStream(input), "Expected a plain value, but received a ReadableStream"));
31
+ /**
32
+ * ストリーム専用のスキーマにプレーン値が渡されたことを報告するためのスキーマです。
33
+ */
34
+ const StreamValueInputSchema = v.pipe(v.unknown(), v.check(isReadableStream, "Expected a ReadableStream, but received a plain value"));
35
+ /**
36
+ * スキーマ情報に基づいて `set` の入力値を検証します。
37
+ *
38
+ * プレーン値はその場で検証し、ストリームはチャンクごとに検証するストリームに変換します。
39
+ *
40
+ * @param info キーに対応するスキーマ情報です。
41
+ * @param value 検証する入力値です。
42
+ * @returns 検証済みの入力値を返します。
43
+ */
44
+ function parseSetValue(info, value) {
45
+ if (isReadableStream(value)) {
46
+ if (info.kind === "plain") {
47
+ // 必ず検証に失敗するため、InvalidInputError が投げられます。
48
+ v.parseInput(PlainValueInputSchema, value);
49
+ }
50
+ // 入力チャンクを検証し、変換後の値を後続のパイプラインへ流します。
51
+ return value.pipeThrough(new TransformStream({
52
+ transform(chunk, controller) {
53
+ controller.enqueue(v.parseInput(info.schema, chunk));
54
+ },
55
+ }));
56
+ }
57
+ if (info.kind === "stream") {
58
+ // 必ず検証に失敗するため、InvalidInputError が投げられます。
59
+ v.parseInput(StreamValueInputSchema, value);
60
+ }
61
+ return v.parseInput(info.schema, value);
62
+ }
63
+ // -------------------------------------------------------------------------------------------------
64
+ //
23
65
  // スキーマ
24
66
  //
25
67
  // -------------------------------------------------------------------------------------------------
26
- const ContextKeySchema = v.string();
27
- // 配列形式の context も正当な入力であるため、record スキーマより先に判定する必要があります。
28
- // record スキーマは配列にもマッチして数値キーのオブジェクトに変換してしまうため、配列形式を先に処理しないと mergeContext での配列としてのマージが行われません。
29
- const ContextSourceSchema = v.union([
30
- v.array(v.tuple([ContextKeySchema, v.unknown()])),
68
+ const VariablesKeySchema = v.string();
69
+ // 配列形式の vars も正当な入力であるため、record スキーマより先に判定する必要があります。
70
+ // record スキーマは配列にもマッチして数値キーのオブジェクトに変換してしまうため、配列形式を先に処理しないと mergeVariables での配列としてのマージが行われません。
71
+ const VariablesSourceSchema = v.union([
72
+ v.array(v.tuple([VariablesKeySchema, v.unknown()])),
31
73
  v.record(v.any(), v.unknown()),
32
74
  ]);
33
75
  const OpenOptionsSchema = v.object({
@@ -36,9 +78,9 @@ const OpenOptionsSchema = v.object({
36
78
  */
37
79
  signal: v.optional(v.instance(AbortSignal)),
38
80
  /**
39
- * 実行時のコンテキスト情報です。
81
+ * 実行時の変数です。
40
82
  */
41
- context: v.optional(ContextSourceSchema),
83
+ vars: v.optional(VariablesSourceSchema),
42
84
  });
43
85
  const OpenArgsSchema = v.tuple([v.optional(OpenOptionsSchema)]);
44
86
  const CloseOptionsSchema = v.object({
@@ -47,16 +89,16 @@ const CloseOptionsSchema = v.object({
47
89
  */
48
90
  signal: v.optional(v.instance(AbortSignal)),
49
91
  /**
50
- * 実行時のコンテキスト情報です。
92
+ * 実行時の変数です。
51
93
  */
52
- context: v.optional(ContextSourceSchema),
94
+ vars: v.optional(VariablesSourceSchema),
53
95
  });
54
96
  const CloseArgsSchema = v.tuple([v.optional(CloseOptionsSchema)]);
55
97
  const SetOptionsSchema = v.object({
56
98
  key: v.string(),
57
99
  value: v.unknown(),
58
100
  signal: v.optional(v.instance(AbortSignal)),
59
- context: v.optional(ContextSourceSchema),
101
+ vars: v.optional(VariablesSourceSchema),
60
102
  });
61
103
  const SetArgsSchema = v.union([
62
104
  v.tuple([SetOptionsSchema]),
@@ -69,7 +111,7 @@ const SetArgsSchema = v.union([
69
111
  const GetOptionsSchema = v.object({
70
112
  key: v.string(),
71
113
  signal: v.optional(v.instance(AbortSignal)),
72
- context: v.optional(ContextSourceSchema),
114
+ vars: v.optional(VariablesSourceSchema),
73
115
  });
74
116
  const GetArgsSchema = v.union([
75
117
  v.tuple([GetOptionsSchema]),
@@ -78,7 +120,7 @@ const GetArgsSchema = v.union([
78
120
  const StreamOptionsSchema = v.object({
79
121
  key: v.string(),
80
122
  signal: v.optional(v.instance(AbortSignal)),
81
- context: v.optional(ContextSourceSchema),
123
+ vars: v.optional(VariablesSourceSchema),
82
124
  });
83
125
  const StreamArgsSchema = v.union([
84
126
  v.tuple([StreamOptionsSchema]),
@@ -87,7 +129,7 @@ const StreamArgsSchema = v.union([
87
129
  const HasOptionsSchema = v.object({
88
130
  key: v.string(),
89
131
  signal: v.optional(v.instance(AbortSignal)),
90
- context: v.optional(ContextSourceSchema),
132
+ vars: v.optional(VariablesSourceSchema),
91
133
  });
92
134
  const HasArgsSchema = v.union([
93
135
  v.tuple([HasOptionsSchema]),
@@ -96,7 +138,7 @@ const HasArgsSchema = v.union([
96
138
  const DeleteOptionsSchema = v.object({
97
139
  key: v.string(),
98
140
  signal: v.optional(v.instance(AbortSignal)),
99
- context: v.optional(ContextSourceSchema),
141
+ vars: v.optional(VariablesSourceSchema),
100
142
  });
101
143
  const DeleteArgsSchema = v.union([
102
144
  v.tuple([DeleteOptionsSchema]),
@@ -108,9 +150,9 @@ const ClearOptionsSchema = v.object({
108
150
  */
109
151
  signal: v.optional(v.instance(AbortSignal)),
110
152
  /**
111
- * 実行時のコンテキスト情報です。
153
+ * 実行時の変数です。
112
154
  */
113
- context: v.optional(ContextSourceSchema),
155
+ vars: v.optional(VariablesSourceSchema),
114
156
  });
115
157
  const ClearArgsSchema = v.tuple([v.optional(ClearOptionsSchema)]);
116
158
  // -------------------------------------------------------------------------------------------------
@@ -135,50 +177,16 @@ const ioLockRegistry = typeof FinalizationRegistry !== "function"
135
177
  });
136
178
  });
137
179
  /**
138
- * UniKvs メインクラスです。
139
- *
140
- * 複数のストレージとトランスフォーマーを統合して KVS 操作を提供します。
141
- *
142
- * @template TKeyValueMapping キーと値のマッピング定義です。
180
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
143
181
  */
144
182
  export default class UniKvs {
145
- /**
146
- * UniKvs の設定ビルダーを作成します。
147
- *
148
- * @template TKeyValueMapping マッピング定義です。
149
- * @returns 設定ビルダーのインスタンスです。
150
- * @example
151
- * ```typescript
152
- * import { Compression } from "@unikvs/compression";
153
- * import { FileSystem } from "@unikvs/fs.node";
154
- * import { UniKvs, type Value } from "unikvs";
155
- *
156
- * const kvs = UniKvs.config<{
157
- * foo: Value<Uint8Array<ArrayBuffer>>;
158
- * }>()
159
- * .appendTransformer(new Compression("gzip"))
160
- * .appendStorage(new FileSystem(".tmp"))
161
- * .create();
162
- *
163
- * await kvs.open();
164
- *
165
- * await kvs.set("foo", Uint8Array.from([0, 1, 2]));
166
- *
167
- * await kvs.close();
168
- * ```
169
- */
170
- static config() {
171
- return new UniKvsConfig(this);
183
+ static config(options) {
184
+ return new UniKvsConfig(this, options);
172
185
  }
173
186
  /**
174
- * インスタンスを初期化します。
175
- *
176
- * @internal UniKvs の設定ビルダー経由で使用します。
177
- * @param context コンテキストです。
178
- * @param destinations ストレージのリストです。
179
- * @param transformers トランスフォーマーのリストです。
187
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
180
188
  */
181
- constructor(context, destinations, transformers) {
189
+ constructor(vars, destinations, transformers, valueSchemaResolver = null) {
182
190
  _UniKvs_instances.add(this);
183
191
  /**
184
192
  * 現在の接続状態です。非接続時は null となります。
@@ -186,27 +194,30 @@ export default class UniKvs {
186
194
  _UniKvs_con.set(this, void 0);
187
195
  _UniKvs_acSet.set(this, void 0);
188
196
  /**
189
- * 基本となる実行コンテキスト情報です。
197
+ * 基本となる実行変数情報です。
190
198
  */
191
- _UniKvs_context.set(this, void 0);
199
+ _UniKvs_vars.set(this, void 0);
192
200
  /**
193
- * データの永続化先となるストレージのリストです。
201
+ * データの永続化先となるストレージと前段パイプラインのリストです。
194
202
  */
195
203
  _UniKvs_destinations.set(this, void 0);
196
204
  /**
197
- * データの変換を行うトランスフォーマーのリストです。
205
+ * データの変換を行うトランスフォーマーのリストです。open/close の管理用に全件を保持します。
198
206
  */
199
207
  _UniKvs_transformers.set(this, void 0);
208
+ /**
209
+ * キーに対応する値のスキーマ情報を解決するリゾルバーです。スキーマ未設定時は null となります。
210
+ */
211
+ _UniKvs_valueSchemaResolver.set(this, void 0);
200
212
  __classPrivateFieldSet(this, _UniKvs_con, null, "f");
201
213
  __classPrivateFieldSet(this, _UniKvs_acSet, new Set(), "f");
202
- __classPrivateFieldSet(this, _UniKvs_context, { ...context }, "f");
214
+ __classPrivateFieldSet(this, _UniKvs_vars, { ...vars }, "f");
203
215
  __classPrivateFieldSet(this, _UniKvs_destinations, destinations, "f");
204
216
  __classPrivateFieldSet(this, _UniKvs_transformers, transformers, "f");
217
+ __classPrivateFieldSet(this, _UniKvs_valueSchemaResolver, valueSchemaResolver, "f");
205
218
  }
206
219
  /**
207
- * UniKvs が利用可能であるかを確認します。
208
- *
209
- * @returns 利用可能である場合は true、そうでない場合は false を返します。
220
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
210
221
  */
211
222
  get isOpen() {
212
223
  return __classPrivateFieldGet(this, _UniKvs_con, "f") !== null;
@@ -216,11 +227,11 @@ export default class UniKvs {
216
227
  throw new UniKvsIsOpenError();
217
228
  }
218
229
  const [options = {}] = v.parseInput(OpenArgsSchema, args);
219
- const { signal: signalOption, context: contextOption } = options;
230
+ const { signal: signalOption, vars: varsOption } = options;
220
231
  const ac = new AbortController();
221
232
  const signal = combineSignals([ac.signal, signalOption]);
222
- const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
223
- context["unikvs:action"] = "open";
233
+ const vars = mergeVariables(__classPrivateFieldGet(this, _UniKvs_vars, "f"), varsOption);
234
+ vars["unikvs:action"] = "open";
224
235
  signal.throwIfAborted();
225
236
  __classPrivateFieldGet(this, _UniKvs_acSet, "f").add(ac);
226
237
  const dispose = [];
@@ -231,13 +242,13 @@ export default class UniKvs {
231
242
  }
232
243
  const openFns = [];
233
244
  // 各ストレージのオープン処理をリストに追加します。
234
- for (const storage of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
245
+ for (const { storage } of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
235
246
  openFns.push([
236
247
  async () => {
237
- await storage.open(context, signal);
248
+ await storage.open(vars, signal);
238
249
  dispose.push(async () => {
239
250
  try {
240
- await storage.close(context, signal);
251
+ await storage.close(vars, signal);
241
252
  }
242
253
  catch (ex) {
243
254
  logger.error `Failed to close storage: ${ex}`;
@@ -251,10 +262,10 @@ export default class UniKvs {
251
262
  for (const transformer of __classPrivateFieldGet(this, _UniKvs_transformers, "f")) {
252
263
  openFns.push([
253
264
  async () => {
254
- await transformer.open(context, signal);
265
+ await transformer.open(vars, signal);
255
266
  dispose.push(async () => {
256
267
  try {
257
- await transformer.close(context, signal);
268
+ await transformer.close(vars, signal);
258
269
  }
259
270
  catch (ex) {
260
271
  logger.error `Failed to close transformer: ${ex}`;
@@ -305,9 +316,9 @@ export default class UniKvs {
305
316
  close(...args) {
306
317
  try {
307
318
  const [options = {}] = v.parseInput(CloseArgsSchema, args);
308
- const { signal = AbortSignal.timeout(10e3), context: contextOption } = options;
309
- const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
310
- context["unikvs:action"] = "close";
319
+ const { signal = AbortSignal.timeout(10e3), vars: varsOption } = options;
320
+ const vars = mergeVariables(__classPrivateFieldGet(this, _UniKvs_vars, "f"), varsOption);
321
+ vars["unikvs:action"] = "close";
311
322
  if (__classPrivateFieldGet(this, _UniKvs_con, "f") === null) {
312
323
  const acArr = [...__classPrivateFieldGet(this, _UniKvs_acSet, "f")];
313
324
  __classPrivateFieldGet(this, _UniKvs_acSet, "f").clear();
@@ -327,15 +338,15 @@ export default class UniKvs {
327
338
  ac.abort(new UniKvsIsNotOpenError());
328
339
  }
329
340
  }
330
- return __classPrivateFieldGet(this, _UniKvs_instances, "m", _UniKvs_close).call(this, context, signal, con).catch(async (ex) => {
331
- // #close が失敗した場合、コネクションの AbortController は既に abort 済みであり、以降の操作がすべて即座に失敗する壊れた状態になります。
341
+ return __classPrivateFieldGet(this, _UniKvs_instances, "m", _UniKvs_close).call(this, vars, signal, con).catch(async (ex) => {
342
+ // #close が失敗した場合、コネクションの AbortController はすでに abort 済みであり、以降の操作がすべて即座に失敗する壊れた状態になります。
332
343
  // そこで接続を破棄して isOpen=false の一貫した状態にし、ベストエフォートでプラグインのクローズ処理を実行します。
333
344
  if (__classPrivateFieldGet(this, _UniKvs_con, "f") === con) {
334
345
  __classPrivateFieldSet(this, _UniKvs_con, null, "f");
335
346
  const disposeSignal = AbortSignal.timeout(10e3);
336
- await Promise.all([...__classPrivateFieldGet(this, _UniKvs_destinations, "f"), ...__classPrivateFieldGet(this, _UniKvs_transformers, "f")].map(async (plugin) => {
347
+ await Promise.all([...__classPrivateFieldGet(this, _UniKvs_destinations, "f").map((dest) => dest.storage), ...__classPrivateFieldGet(this, _UniKvs_transformers, "f")].map(async (plugin) => {
337
348
  try {
338
- await plugin.close(context, disposeSignal);
349
+ await plugin.close(vars, disposeSignal);
339
350
  }
340
351
  catch (reason) {
341
352
  logger.error `Failed to close plugin after close failure: ${reason}`;
@@ -350,13 +361,11 @@ export default class UniKvs {
350
361
  }
351
362
  }
352
363
  /**
353
- * UniKvs が開いている場合にクローズします。
354
- *
355
- * `await using` 構文による自動クローズに使用されます。
356
- *
357
- * @returns 完了を通知する Promise です。
364
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
358
365
  */
359
- async [(_UniKvs_con = new WeakMap(), _UniKvs_acSet = new WeakMap(), _UniKvs_context = new WeakMap(), _UniKvs_destinations = new WeakMap(), _UniKvs_transformers = new WeakMap(), _UniKvs_instances = new WeakSet(), _UniKvs_close = async function _UniKvs_close(context, signal, con) {
366
+ async [(_UniKvs_con = new WeakMap(), _UniKvs_acSet = new WeakMap(), _UniKvs_vars = new WeakMap(), _UniKvs_destinations = new WeakMap(), _UniKvs_transformers = new WeakMap(), _UniKvs_valueSchemaResolver = new WeakMap(), _UniKvs_instances = new WeakSet(), _UniKvs_resolveValueSchema = function _UniKvs_resolveValueSchema(key) {
367
+ return __classPrivateFieldGet(this, _UniKvs_valueSchemaResolver, "f")?.resolve(key);
368
+ }, _UniKvs_close = async function _UniKvs_close(vars, signal, con) {
360
369
  const lock = await asyncmux(this, signal);
361
370
  try {
362
371
  // ロック待機中に接続状態が変更されていないか再確認します。
@@ -368,10 +377,10 @@ export default class UniKvs {
368
377
  try {
369
378
  const closeFns = [];
370
379
  // ストレージのクローズ処理を登録します。
371
- for (const plugin of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
380
+ for (const { storage } of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
372
381
  closeFns.push([
373
382
  async () => {
374
- await plugin.close(context, signal);
383
+ await storage.close(vars, signal);
375
384
  },
376
385
  "storage",
377
386
  ]);
@@ -380,7 +389,7 @@ export default class UniKvs {
380
389
  for (const plugin of __classPrivateFieldGet(this, _UniKvs_transformers, "f")) {
381
390
  closeFns.push([
382
391
  async () => {
383
- await plugin.close(context, signal);
392
+ await plugin.close(vars, signal);
384
393
  },
385
394
  "transformer",
386
395
  ]);
@@ -420,12 +429,14 @@ export default class UniKvs {
420
429
  throw new UniKvsIsNotOpenError();
421
430
  }
422
431
  const [options] = v.parseInput(SetArgsSchema, args);
423
- const { key, value, signal: signalOption, context: contextOption } = options;
432
+ const { key, signal: signalOption, vars: varsOption } = options;
433
+ const valueSchema = __classPrivateFieldGet(this, _UniKvs_instances, "m", _UniKvs_resolveValueSchema).call(this, key);
434
+ const value = valueSchema ? parseSetValue(valueSchema, options.value) : options.value;
424
435
  const { ac, io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
425
436
  const signal = combineSignals([ac.signal, signalOption]);
426
- const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
427
- context["unikvs:action"] = "set";
428
- context["unikvs:key"] = key;
437
+ const vars = mergeVariables(__classPrivateFieldGet(this, _UniKvs_vars, "f"), varsOption);
438
+ vars["unikvs:action"] = "set";
439
+ vars["unikvs:key"] = key;
429
440
  const lock = await asyncmux(this, signal);
430
441
  try {
431
442
  // ロック待機中に接続状態が変更されていないか再確認します。
@@ -434,52 +445,75 @@ export default class UniKvs {
434
445
  }
435
446
  const errors = [];
436
447
  const errorStorageSet = new Set();
437
- if (value instanceof ReadableStream) {
438
- // 各トランスフォーマーを通してデータをエンコードストリームへ変換します。
439
- let data = value;
448
+ if (isReadableStream(value)) {
449
+ // 各ストレージ専用の前段パイプラインを通すため、tee で分岐しながらエンコードストリームを構築します。
450
+ // 最長の前段パイプラインを基準にし、ストレージの登録順に分岐点を作ります。
451
+ let longest = [];
452
+ for (const dest of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
453
+ if (dest.transformers.length > longest.length) {
454
+ longest = dest.transformers;
455
+ }
456
+ }
457
+ let cur = value;
458
+ const branches = [];
459
+ const built = [];
440
460
  try {
441
- for (const transformer of __classPrivateFieldGet(this, _UniKvs_transformers, "f")) {
442
- const e = await transformer.getEncodable(context, signal);
443
- data = data.pipeThrough(e);
461
+ let applied = 0;
462
+ for (let i = 0; i < __classPrivateFieldGet(this, _UniKvs_destinations, "f").length; i++) {
463
+ const dest = __classPrivateFieldGet(this, _UniKvs_destinations, "f")[i];
464
+ while (applied < dest.transformers.length) {
465
+ const e = await longest[applied].getEncodable(vars, signal);
466
+ cur = cur.pipeThrough(e);
467
+ applied++;
468
+ }
469
+ if (i === __classPrivateFieldGet(this, _UniKvs_destinations, "f").length - 1) {
470
+ branches[i] = cur;
471
+ }
472
+ else {
473
+ const [branch, rest] = cur.tee();
474
+ branches[i] = branch;
475
+ built.push(branch);
476
+ cur = rest;
477
+ }
444
478
  }
445
479
  }
446
480
  catch (ex) {
447
481
  // チェーンの構築中に失敗した場合、パイプが保持するソースストリームのリソースを解放するためにキャンセルします。
448
482
  // キャンセルしないとソースストリームはロックされたままリークします。
449
483
  try {
450
- await data.cancel(ex);
484
+ await cur.cancel(ex);
451
485
  }
452
486
  catch {
453
487
  // キャンセルに失敗しても元の例外の伝播を優先します。
454
488
  }
489
+ await Promise.all(built.map(async (branch) => {
490
+ try {
491
+ await branch.cancel(ex);
492
+ }
493
+ catch {
494
+ // キャンセルに失敗しても元の例外の伝播を優先します。
495
+ }
496
+ }));
455
497
  throw ex;
456
498
  }
457
499
  const lock = await io.lock({ key, signal });
458
500
  try {
459
- await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (storage, i) => {
501
+ await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (dest, i) => {
460
502
  // tee ブランチはキャンセルされるまで健康なブランチの読み取り分のチャンクを保持し続けるため、失敗時に放棄したブランチを確実にキャンセルできるよう参照を保持します。
461
- let branch = null;
503
+ const branch = branches[i];
462
504
  try {
463
- // 複数のストレージがある場合は、tee メソッドを使用してストリームを分岐させます。
464
- let r = data;
465
- if (i !== __classPrivateFieldGet(this, _UniKvs_destinations, "f").length - 1) {
466
- [r, data] = data.tee();
467
- }
468
- branch = r;
469
- const w = await storage.getWritable(context, signal, key);
470
- await r.pipeTo(w, { signal });
505
+ const w = await dest.storage.getWritable(vars, signal, key);
506
+ await branch.pipeTo(w, { signal });
471
507
  }
472
508
  catch (reason) {
473
- if (branch !== null) {
474
- try {
475
- await branch.cancel(reason);
476
- }
477
- catch {
478
- // キャンセルに失敗してもエラー集約を優先します。
479
- }
509
+ try {
510
+ await branch.cancel(reason);
511
+ }
512
+ catch {
513
+ // キャンセルに失敗してもエラー集約を優先します。
480
514
  }
481
515
  errors.push({ reason });
482
- errorStorageSet.add(storage);
516
+ errorStorageSet.add(dest);
483
517
  }
484
518
  }));
485
519
  }
@@ -488,20 +522,27 @@ export default class UniKvs {
488
522
  }
489
523
  }
490
524
  else {
491
- // 登録されているトランスフォーマーを順番に適用してデータをエンコードします。
492
- let data = value;
493
- for (const transformer of __classPrivateFieldGet(this, _UniKvs_transformers, "f")) {
494
- data = await transformer.encode(context, signal, data);
525
+ // 各ストレージ専用の前段パイプラインでデータをエンコードします。共有プレフィックスは使い回します。
526
+ let longest = [];
527
+ for (const dest of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
528
+ if (dest.transformers.length > longest.length) {
529
+ longest = dest.transformers;
530
+ }
531
+ }
532
+ const prefix = [value];
533
+ for (const transformer of longest) {
534
+ prefix.push(await transformer.encode(vars, signal, prefix[prefix.length - 1]));
495
535
  }
536
+ const encoded = __classPrivateFieldGet(this, _UniKvs_destinations, "f").map((dest) => prefix[dest.transformers.length]);
496
537
  const lock = await io.lock({ key, signal });
497
538
  try {
498
- await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (storage) => {
539
+ await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (dest, i) => {
499
540
  try {
500
- await storage.write(context, signal, key, data);
541
+ await dest.storage.write(vars, signal, key, encoded[i]);
501
542
  }
502
543
  catch (reason) {
503
544
  errors.push({ reason });
504
- errorStorageSet.add(storage);
545
+ errorStorageSet.add(dest);
505
546
  }
506
547
  }));
507
548
  }
@@ -518,12 +559,12 @@ export default class UniKvs {
518
559
  });
519
560
  {
520
561
  const errors = [];
521
- await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (storage) => {
522
- if (errorStorageSet.has(storage)) {
562
+ await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (dest) => {
563
+ if (errorStorageSet.has(dest)) {
523
564
  return;
524
565
  }
525
566
  try {
526
- await storage.onOtherWriteError(context, signal, key, error);
567
+ await dest.storage.onOtherWriteError(vars, signal, key, error);
527
568
  }
528
569
  catch (ex) {
529
570
  errors.push(ex);
@@ -545,12 +586,13 @@ export default class UniKvs {
545
586
  throw new UniKvsIsNotOpenError();
546
587
  }
547
588
  const [options] = v.parseInput(GetArgsSchema, args);
548
- const { key, signal: signalOption, context: contextOption } = options;
589
+ const { key, signal: signalOption, vars: varsOption } = options;
590
+ const valueSchema = __classPrivateFieldGet(this, _UniKvs_instances, "m", _UniKvs_resolveValueSchema).call(this, key);
549
591
  const { ac, io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
550
592
  const signal = combineSignals([ac.signal, signalOption]);
551
- const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
552
- context["unikvs:action"] = "get";
553
- context["unikvs:key"] = key;
593
+ const vars = mergeVariables(__classPrivateFieldGet(this, _UniKvs_vars, "f"), varsOption);
594
+ vars["unikvs:action"] = "get";
595
+ vars["unikvs:key"] = key;
554
596
  const lock = await asyncmux.readonly(this, signal);
555
597
  try {
556
598
  // ロック待機中に接続状態が変更されていないか再確認します。
@@ -559,17 +601,19 @@ export default class UniKvs {
559
601
  }
560
602
  const NONE = {};
561
603
  let data = NONE;
604
+ let transformers = [];
562
605
  const errors = [];
563
606
  const lock = await io.rLock({ key, signal });
564
607
  try {
565
608
  // 各ストレージを巡回し、最初に見つかったデータを取得します。
566
609
  // あるストレージの読み取りに失敗しても、他のストレージからデータを取得できるようにフォールバックします。
567
- for (const storage of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
610
+ for (const dest of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
568
611
  try {
569
- if (!(await storage.exists(context, signal, key))) {
612
+ if (!(await dest.storage.exists(vars, signal, key))) {
570
613
  continue;
571
614
  }
572
- data = await storage.read(context, signal, key);
615
+ data = await dest.storage.read(vars, signal, key);
616
+ transformers = dest.transformers;
573
617
  break;
574
618
  }
575
619
  catch (ex) {
@@ -601,11 +645,13 @@ export default class UniKvs {
601
645
  }
602
646
  throw new KeyNotFoundError(args);
603
647
  }
604
- // トランスフォーマーを逆順に適用してデータをデコードします。
605
- if (__classPrivateFieldGet(this, _UniKvs_transformers, "f").length > 0) {
606
- for (const transformer of __classPrivateFieldGet(this, _UniKvs_transformers, "f").toReversed()) {
607
- data = await transformer.decode(context, signal, data);
608
- }
648
+ // 見つかったストレージ専用の前段パイプラインを逆順に適用してデータをデコードします。
649
+ for (const transformer of transformers.toReversed()) {
650
+ data = await transformer.decode(vars, signal, data);
651
+ }
652
+ // デコード後のデータを検証します。
653
+ if (valueSchema) {
654
+ data = v.parseOutput(valueSchema.schema, data);
609
655
  }
610
656
  return data;
611
657
  }
@@ -618,12 +664,13 @@ export default class UniKvs {
618
664
  throw new UniKvsIsNotOpenError();
619
665
  }
620
666
  const [options] = v.parseInput(StreamArgsSchema, args);
621
- const { key, signal: signalOption, context: contextOption } = options;
667
+ const { key, signal: signalOption, vars: varsOption } = options;
668
+ const valueSchema = __classPrivateFieldGet(this, _UniKvs_instances, "m", _UniKvs_resolveValueSchema).call(this, key);
622
669
  const { ac, io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
623
670
  const signal = combineSignals([ac.signal, signalOption]);
624
- const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
625
- context["unikvs:action"] = "stream";
626
- context["unikvs:key"] = key;
671
+ const vars = mergeVariables(__classPrivateFieldGet(this, _UniKvs_vars, "f"), varsOption);
672
+ vars["unikvs:action"] = "stream";
673
+ vars["unikvs:key"] = key;
627
674
  const lock = await asyncmux.readonly(this, signal);
628
675
  try {
629
676
  // ロック待機中に接続状態が変更されていないか再確認します。
@@ -632,17 +679,19 @@ export default class UniKvs {
632
679
  }
633
680
  const NONE = {};
634
681
  let r = NONE;
682
+ let transformers = [];
635
683
  const errors = [];
636
684
  const lock = await io.rLock({ key, signal });
637
685
  try {
638
686
  // 各ストレージを巡回し、最初に見つかったデータを取得します。
639
687
  // あるストレージの読み取りに失敗しても、他のストレージからデータを取得できるようにフォールバックします。
640
- for (const storage of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
688
+ for (const dest of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
641
689
  try {
642
- if (!(await storage.exists(context, signal, key))) {
690
+ if (!(await dest.storage.exists(vars, signal, key))) {
643
691
  continue;
644
692
  }
645
- r = await storage.getReadable(context, signal, key);
693
+ r = await dest.storage.getReadable(vars, signal, key);
694
+ transformers = dest.transformers;
646
695
  break;
647
696
  }
648
697
  catch (ex) {
@@ -670,11 +719,19 @@ export default class UniKvs {
670
719
  }
671
720
  throw new KeyNotFoundError(args);
672
721
  }
673
- // トランスフォーマーを逆順に適用し、デコード用トランスフォームを連結します。
674
- for (const transformer of __classPrivateFieldGet(this, _UniKvs_transformers, "f").toReversed()) {
675
- const d = await transformer.getDecodable(context, signal);
722
+ // 見つかったストレージ専用の前段パイプラインを逆順に適用し、デコード用トランスフォームを連結します。
723
+ for (const transformer of transformers.toReversed()) {
724
+ const d = await transformer.getDecodable(vars, signal);
676
725
  r = r.pipeThrough(d);
677
726
  }
727
+ // デコード後のチャンクを検証します。
728
+ if (valueSchema) {
729
+ r = r.pipeThrough(new TransformStream({
730
+ transform(chunk, controller) {
731
+ controller.enqueue(v.parseOutput(valueSchema.schema, chunk));
732
+ },
733
+ }));
734
+ }
678
735
  if (!ioLockRegistry) {
679
736
  return toValueStream(r, async () => {
680
737
  try {
@@ -722,12 +779,14 @@ export default class UniKvs {
722
779
  throw new UniKvsIsNotOpenError();
723
780
  }
724
781
  const [options] = v.parseInput(HasArgsSchema, args);
725
- const { key, signal: signalOption, context: contextOption } = options;
782
+ const { key, signal: signalOption, vars: varsOption } = options;
783
+ // キーがキースキーマに一致するかを検証します。
784
+ __classPrivateFieldGet(this, _UniKvs_instances, "m", _UniKvs_resolveValueSchema).call(this, key);
726
785
  const { ac, io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
727
786
  const signal = combineSignals([ac.signal, signalOption]);
728
- const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
729
- context["unikvs:action"] = "has";
730
- context["unikvs:key"] = key;
787
+ const vars = mergeVariables(__classPrivateFieldGet(this, _UniKvs_vars, "f"), varsOption);
788
+ vars["unikvs:action"] = "has";
789
+ vars["unikvs:key"] = key;
731
790
  const lock = await asyncmux.readonly(this, signal);
732
791
  try {
733
792
  // ロック待機中に接続状態が変更されていないか再確認します。
@@ -739,9 +798,9 @@ export default class UniKvs {
739
798
  // いずれかのストレージに存在すれば true を返します。
740
799
  // あるストレージの存在確認に失敗しても、他のストレージで存在を確認できるようにフォールバックします。
741
800
  const errors = [];
742
- for (const storage of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
801
+ for (const { storage } of __classPrivateFieldGet(this, _UniKvs_destinations, "f")) {
743
802
  try {
744
- if (await storage.exists(context, signal, key)) {
803
+ if (await storage.exists(vars, signal, key)) {
745
804
  return true;
746
805
  }
747
806
  }
@@ -784,12 +843,14 @@ export default class UniKvs {
784
843
  throw new UniKvsIsNotOpenError();
785
844
  }
786
845
  const [options] = v.parseInput(DeleteArgsSchema, args);
787
- const { key, signal: signalOption, context: contextOption } = options;
846
+ const { key, signal: signalOption, vars: varsOption } = options;
847
+ // キーがキースキーマに一致するかを検証します。
848
+ __classPrivateFieldGet(this, _UniKvs_instances, "m", _UniKvs_resolveValueSchema).call(this, key);
788
849
  const { ac, io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
789
850
  const signal = combineSignals([ac.signal, signalOption]);
790
- const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
791
- context["unikvs:action"] = "delete";
792
- context["unikvs:key"] = key;
851
+ const vars = mergeVariables(__classPrivateFieldGet(this, _UniKvs_vars, "f"), varsOption);
852
+ vars["unikvs:action"] = "delete";
853
+ vars["unikvs:key"] = key;
793
854
  const lock = await asyncmux(this, signal);
794
855
  try {
795
856
  // ロック待機中に接続状態が変更されていないか再確認します。
@@ -801,10 +862,10 @@ export default class UniKvs {
801
862
  // すべてのストレージから対象データを削除します。
802
863
  // すべての処理を並列に実行し、エラーが発生した場合は集約します。
803
864
  const errors = [];
804
- await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (storage) => {
865
+ await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async ({ storage }) => {
805
866
  try {
806
- if (await storage.exists(context, signal, key)) {
807
- await storage.delete(context, signal, key);
867
+ if (await storage.exists(vars, signal, key)) {
868
+ await storage.delete(vars, signal, key);
808
869
  }
809
870
  }
810
871
  catch (reason) {
@@ -828,11 +889,11 @@ export default class UniKvs {
828
889
  throw new UniKvsIsNotOpenError();
829
890
  }
830
891
  const [options = {}] = v.parseInput(ClearArgsSchema, args);
831
- const { signal: signalOption, context: contextOption } = options;
892
+ const { signal: signalOption, vars: varsOption } = options;
832
893
  const { ac, io } = __classPrivateFieldGet(this, _UniKvs_con, "f");
833
894
  const signal = combineSignals([ac.signal, signalOption]);
834
- const context = mergeContext(__classPrivateFieldGet(this, _UniKvs_context, "f"), contextOption);
835
- context["unikvs:action"] = "clear";
895
+ const vars = mergeVariables(__classPrivateFieldGet(this, _UniKvs_vars, "f"), varsOption);
896
+ vars["unikvs:action"] = "clear";
836
897
  const lock = await asyncmux(this, signal);
837
898
  try {
838
899
  // ロック待機中に接続状態が変更されていないか再確認します。
@@ -844,9 +905,9 @@ export default class UniKvs {
844
905
  // すべてのストレージで一括削除を実行します。
845
906
  // すべての処理を並列に実行し、エラーが発生した場合は集約します。
846
907
  const errors = [];
847
- await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async (storage) => {
908
+ await Promise.all(__classPrivateFieldGet(this, _UniKvs_destinations, "f").map(async ({ storage }) => {
848
909
  try {
849
- await storage.clear(context, signal);
910
+ await storage.clear(vars, signal);
850
911
  }
851
912
  catch (reason) {
852
913
  errors.push({ reason });