unikvs 0.0.5 → 0.0.7

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/src/unikvs.ts CHANGED
@@ -67,39 +67,149 @@ export type KeyofKeyValueMappingHasStreamValue<TKeyValueMapping extends KeyValue
67
67
 
68
68
  // -------------------------------------------------------------------------------------------------
69
69
  //
70
- // 型定義
70
+ // スキーマ
71
71
  //
72
72
  // -------------------------------------------------------------------------------------------------
73
73
 
74
- /**
75
- * オープン操作時のオプションです。
76
- */
77
- export type OpenOptions = {
74
+ const ContextKeySchema = v.string();
75
+
76
+ const ContextSourceSchema = v.union([
77
+ v.record(v.any(), v.unknown()),
78
+ v.array(v.tuple([ContextKeySchema, v.unknown()])),
79
+ ]);
80
+
81
+ const OpenOptionsSchema = v.object({
78
82
  /**
79
83
  * 処理の中断を通知するためのシグナルです。
80
84
  */
81
- readonly signal?: AbortSignal | undefined;
85
+ signal: v.optional(v.instance(AbortSignal)),
82
86
 
83
87
  /**
84
88
  * 実行時のコンテキスト情報です。
85
89
  */
86
- readonly context?: ContextSource | undefined;
87
- };
90
+ context: v.optional(ContextSourceSchema),
91
+ });
88
92
 
89
- /**
90
- * クローズ操作時のオプションです。
91
- */
92
- export type CloseOptions = {
93
+ const OpenArgsSchema = v.tuple([v.optional(OpenOptionsSchema)]);
94
+
95
+ const CloseOptionsSchema = v.object({
93
96
  /**
94
97
  * 処理の中断を通知するためのシグナルです。
95
98
  */
96
- readonly signal?: AbortSignal | undefined;
99
+ signal: v.optional(v.instance(AbortSignal)),
97
100
 
98
101
  /**
99
102
  * 実行時のコンテキスト情報です。
100
103
  */
101
- readonly context?: ContextSource | undefined;
102
- };
104
+ context: v.optional(ContextSourceSchema),
105
+ });
106
+
107
+ const CloseArgsSchema = v.tuple([v.optional(CloseOptionsSchema)]);
108
+
109
+ const SetOptionsSchema = v.object({
110
+ key: v.string(),
111
+ value: v.unknown(),
112
+ signal: v.optional(v.instance(AbortSignal)),
113
+ context: v.optional(ContextSourceSchema),
114
+ });
115
+
116
+ const SetArgsSchema = v.union([
117
+ v.tuple([SetOptionsSchema]),
118
+ v.pipe(
119
+ v.tuple([
120
+ SetOptionsSchema.entries.key,
121
+ SetOptionsSchema.entries.value,
122
+ v.optional(v.omit(SetOptionsSchema, ["key", "value"])),
123
+ ]),
124
+ v.transform(([key, value, options]) => [{ ...options, key, value }]),
125
+ ),
126
+ ]);
127
+
128
+ const GetOptionsSchema = v.object({
129
+ key: v.string(),
130
+ signal: v.optional(v.instance(AbortSignal)),
131
+ context: v.optional(ContextSourceSchema),
132
+ });
133
+
134
+ const GetArgsSchema = v.union([
135
+ v.tuple([GetOptionsSchema]),
136
+ v.pipe(
137
+ v.tuple([GetOptionsSchema.entries.key, v.optional(v.omit(GetOptionsSchema, ["key"]))]),
138
+ v.transform(([key, options]) => [{ ...options, key }]),
139
+ ),
140
+ ]);
141
+
142
+ const StreamOptionsSchema = v.object({
143
+ key: v.string(),
144
+ signal: v.optional(v.instance(AbortSignal)),
145
+ context: v.optional(ContextSourceSchema),
146
+ });
147
+
148
+ const StreamArgsSchema = v.union([
149
+ v.tuple([StreamOptionsSchema]),
150
+ v.pipe(
151
+ v.tuple([StreamOptionsSchema.entries.key, v.optional(v.omit(StreamOptionsSchema, ["key"]))]),
152
+ v.transform(([key, options]) => [{ ...options, key }]),
153
+ ),
154
+ ]);
155
+
156
+ const HasOptionsSchema = v.object({
157
+ key: v.string(),
158
+ signal: v.optional(v.instance(AbortSignal)),
159
+ context: v.optional(ContextSourceSchema),
160
+ });
161
+
162
+ const HasArgsSchema = v.union([
163
+ v.tuple([HasOptionsSchema]),
164
+ v.pipe(
165
+ v.tuple([HasOptionsSchema.entries.key, v.optional(v.omit(HasOptionsSchema, ["key"]))]),
166
+ v.transform(([key, options]) => [{ ...options, key }]),
167
+ ),
168
+ ]);
169
+
170
+ const DeleteOptionsSchema = v.object({
171
+ key: v.string(),
172
+ signal: v.optional(v.instance(AbortSignal)),
173
+ context: v.optional(ContextSourceSchema),
174
+ });
175
+
176
+ const DeleteArgsSchema = v.union([
177
+ v.tuple([DeleteOptionsSchema]),
178
+ v.pipe(
179
+ v.tuple([DeleteOptionsSchema.entries.key, v.optional(v.omit(DeleteOptionsSchema, ["key"]))]),
180
+ v.transform(([key, options]) => [{ ...options, key }]),
181
+ ),
182
+ ]);
183
+
184
+ const ClearOptionsSchema = v.object({
185
+ /**
186
+ * 処理の中断を通知するためのシグナルです。
187
+ */
188
+ signal: v.optional(v.instance(AbortSignal)),
189
+
190
+ /**
191
+ * 実行時のコンテキスト情報です。
192
+ */
193
+ context: v.optional(ContextSourceSchema),
194
+ });
195
+
196
+ const ClearArgsSchema = v.tuple([v.optional(ClearOptionsSchema)]);
197
+
198
+ // -------------------------------------------------------------------------------------------------
199
+ //
200
+ // 型定義
201
+ //
202
+ // -------------------------------------------------------------------------------------------------
203
+
204
+ /**
205
+ * オープン操作時のオプションです。
206
+ */
207
+ export type OpenOptions = v.InferInput<typeof OpenOptionsSchema>;
208
+
209
+ /**
210
+ * クローズ操作時のオプションです。
211
+ */
212
+ export type CloseOptions = v.InferInput<typeof CloseOptionsSchema>;
103
213
 
104
214
  /**
105
215
  * 保存操作時のオプションです。
@@ -223,126 +333,7 @@ export type DeleteOptions<TKey = IStorage.Key> = {
223
333
  /**
224
334
  * 全削除操作時のオプションです。
225
335
  */
226
- export type ClearOptions = {
227
- /**
228
- * 処理の中断を通知するためのシグナルです。
229
- */
230
- readonly signal?: AbortSignal | undefined;
231
-
232
- /**
233
- * 実行時のコンテキスト情報です。
234
- */
235
- readonly context?: ContextSource | undefined;
236
- };
237
-
238
- // -------------------------------------------------------------------------------------------------
239
- //
240
- // スキーマ
241
- //
242
- // -------------------------------------------------------------------------------------------------
243
-
244
- const ContextKeySchema = v.union([v.string(), v.symbol(), v.number()]);
245
-
246
- const ContextSourceSchema = v.union([
247
- v.record(v.any(), v.unknown()),
248
- v.array(v.tuple([ContextKeySchema, v.unknown()])),
249
- ]);
250
-
251
- const OpenOptionsSchema = v.object({
252
- signal: v.optional(v.instance(AbortSignal)),
253
- context: v.optional(ContextSourceSchema),
254
- });
255
-
256
- const OpenArgsSchema = v.tuple([v.optional(OpenOptionsSchema)]);
257
-
258
- const CloseOptionsSchema = v.object({
259
- signal: v.optional(v.instance(AbortSignal)),
260
- context: v.optional(ContextSourceSchema),
261
- });
262
-
263
- const CloseArgsSchema = v.tuple([v.optional(CloseOptionsSchema)]);
264
-
265
- const SetOptionsSchema = v.object({
266
- key: v.string(),
267
- value: v.unknown(),
268
- signal: v.optional(v.instance(AbortSignal)),
269
- context: v.optional(ContextSourceSchema),
270
- });
271
-
272
- const SetArgsSchema = v.union([
273
- v.tuple([SetOptionsSchema]),
274
- v.pipe(
275
- v.tuple([
276
- SetOptionsSchema.entries.key,
277
- SetOptionsSchema.entries.value,
278
- v.optional(v.omit(SetOptionsSchema, ["key", "value"])),
279
- ]),
280
- v.transform(([key, value, options]) => [{ ...options, key, value }]),
281
- ),
282
- ]);
283
-
284
- const GetOptionsSchema = v.object({
285
- key: v.string(),
286
- signal: v.optional(v.instance(AbortSignal)),
287
- context: v.optional(ContextSourceSchema),
288
- });
289
-
290
- const GetArgsSchema = v.union([
291
- v.tuple([GetOptionsSchema]),
292
- v.pipe(
293
- v.tuple([GetOptionsSchema.entries.key, v.optional(v.omit(GetOptionsSchema, ["key"]))]),
294
- v.transform(([key, options]) => [{ ...options, key }]),
295
- ),
296
- ]);
297
-
298
- const StreamOptionsSchema = v.object({
299
- key: v.string(),
300
- signal: v.optional(v.instance(AbortSignal)),
301
- context: v.optional(ContextSourceSchema),
302
- });
303
-
304
- const StreamArgsSchema = v.union([
305
- v.tuple([StreamOptionsSchema]),
306
- v.pipe(
307
- v.tuple([StreamOptionsSchema.entries.key, v.optional(v.omit(StreamOptionsSchema, ["key"]))]),
308
- v.transform(([key, options]) => [{ ...options, key }]),
309
- ),
310
- ]);
311
-
312
- const HasOptionsSchema = v.object({
313
- key: v.string(),
314
- signal: v.optional(v.instance(AbortSignal)),
315
- context: v.optional(ContextSourceSchema),
316
- });
317
-
318
- const HasArgsSchema = v.union([
319
- v.tuple([HasOptionsSchema]),
320
- v.pipe(
321
- v.tuple([HasOptionsSchema.entries.key, v.optional(v.omit(HasOptionsSchema, ["key"]))]),
322
- v.transform(([key, options]) => [{ ...options, key }]),
323
- ),
324
- ]);
325
-
326
- const DeleteOptionsSchema = v.object({
327
- key: v.string(),
328
- signal: v.optional(v.instance(AbortSignal)),
329
- context: v.optional(ContextSourceSchema),
330
- });
331
-
332
- const DeleteArgsSchema = v.union([
333
- v.tuple([DeleteOptionsSchema]),
334
- v.pipe(
335
- v.tuple([DeleteOptionsSchema.entries.key, v.optional(v.omit(DeleteOptionsSchema, ["key"]))]),
336
- v.transform(([key, options]) => [{ ...options, key }]),
337
- ),
338
- ]);
339
-
340
- const ClearOptionsSchema = v.object({
341
- signal: v.optional(v.instance(AbortSignal)),
342
- context: v.optional(ContextSourceSchema),
343
- });
344
-
345
- const ClearArgsSchema = v.tuple([v.optional(ClearOptionsSchema)]);
336
+ export type ClearOptions = v.InferInput<typeof ClearOptionsSchema>;
346
337
 
347
338
  // -------------------------------------------------------------------------------------------------
348
339
  //
@@ -369,12 +360,12 @@ type Connection = {
369
360
  /**
370
361
  * 接続全体を管理する AbortController です。
371
362
  */
372
- readonly conAc: AbortController;
363
+ readonly ac: AbortController;
373
364
 
374
365
  /**
375
366
  * I/O の多重化を制御する Asyncmux インスタンスです。
376
367
  */
377
- readonly ioMux: Asyncmux;
368
+ readonly io: Asyncmux;
378
369
  };
379
370
 
380
371
  /**
@@ -421,6 +412,8 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
421
412
  */
422
413
  #con: Connection | null;
423
414
 
415
+ readonly #acSet: Set<AbortController>;
416
+
424
417
  /**
425
418
  * 基本となる実行コンテキスト情報です。
426
419
  */
@@ -450,10 +443,8 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
450
443
  transformers: readonly UniKvsTransformer[],
451
444
  ) {
452
445
  this.#con = null;
453
- this.#context = {
454
- ...context,
455
- "unikvs:instance": this,
456
- };
446
+ this.#acSet = new Set();
447
+ this.#context = { ...context };
457
448
  this.#destinations = destinations;
458
449
  this.#transformers = transformers;
459
450
  }
@@ -464,7 +455,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
464
455
  * @returns 利用可能である場合は true、そうでない場合は false を返します。
465
456
  */
466
457
  public get isOpen(): boolean {
467
- return !!this.#con;
458
+ return this.#con !== null;
468
459
  }
469
460
 
470
461
  /**
@@ -476,134 +467,114 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
476
467
  public open(options?: OpenOptions): Promise<void>;
477
468
 
478
469
  public async open(...args: any): Promise<void> {
479
- if (this.#con) {
470
+ if (this.#con !== null) {
480
471
  throw new UniKvsIsOpenError();
481
472
  }
482
473
 
483
- this.#con = {
484
- conAc: new AbortController(),
485
- ioMux: new Asyncmux(),
486
- };
487
- try {
488
- const [options = {}] = v.parseInput(OpenArgsSchema, args);
489
- const { signal: signalOption, context: contextOption } = options;
474
+ const [options = {}] = v.parseInput(OpenArgsSchema, args);
475
+ const { signal: signalOption, context: contextOption } = options;
490
476
 
491
- const { conAc } = this.#con;
492
- const signal = combineSignals([conAc.signal, signalOption]);
477
+ const ac = new AbortController();
478
+ const signal = combineSignals([ac.signal, signalOption]);
493
479
 
494
- const context = mergeContext(this.#context, contextOption);
495
- context["unikvs:action"] = "open";
480
+ const context = mergeContext(this.#context, contextOption);
481
+ context["unikvs:action"] = "open";
482
+
483
+ signal.throwIfAborted();
484
+
485
+ this.#acSet.add(ac);
486
+
487
+ const dispose: (() => Promise<void>)[] = [];
488
+
489
+ const lock = await asyncmux(this, signal);
490
+ try {
491
+ if (this.#con !== null) {
492
+ throw new UniKvsIsOpenError();
493
+ }
496
494
 
497
495
  const openFns: [() => Promise<void>, plugin: "storage" | "transformer"][] = [];
498
- const dispose: (() => Promise<void>)[] = [];
499
- const lock = await asyncmux(this, signal);
500
- try {
501
- // ロック待機中に接続状態が変更されていないか再確認します。
502
- if (this.#con.conAc !== conAc) {
503
- throw new UniKvsIsOpenError();
504
- }
505
496
 
506
- // 各ストレージのオープン処理をリストに追加します。
507
- for (const storage of this.#destinations) {
508
- openFns.push([
509
- async () => {
510
- await storage.open(context, signal);
497
+ // 各ストレージのオープン処理をリストに追加します。
498
+ for (const storage of this.#destinations) {
499
+ openFns.push([
500
+ async () => {
501
+ await storage.open(context, signal);
511
502
 
512
- dispose.push(async () => {
513
- try {
514
- await storage.close(context, signal);
515
- } catch (ex) {
516
- logger.error`Failed to close storage: ${ex}`;
517
- }
518
- });
519
- },
520
- "storage",
521
- ]);
522
- }
503
+ dispose.push(async () => {
504
+ try {
505
+ await storage.close(context, signal);
506
+ } catch (ex) {
507
+ logger.error`Failed to close storage: ${ex}`;
508
+ }
509
+ });
510
+ },
511
+ "storage",
512
+ ]);
513
+ }
523
514
 
524
- // 各トランスフォーマーのオープン処理をリストに追加します。
525
- for (const transformer of this.#transformers) {
526
- openFns.push([
527
- async () => {
528
- await transformer.open(context, signal);
515
+ // 各トランスフォーマーのオープン処理をリストに追加します。
516
+ for (const transformer of this.#transformers) {
517
+ openFns.push([
518
+ async () => {
519
+ await transformer.open(context, signal);
529
520
 
530
- dispose.push(async () => {
531
- try {
532
- await transformer.close(context, signal);
533
- } catch (ex) {
534
- logger.error`Failed to close transformer: ${ex}`;
535
- }
536
- });
537
- },
538
- "transformer",
539
- ]);
540
- }
521
+ dispose.push(async () => {
522
+ try {
523
+ await transformer.close(context, signal);
524
+ } catch (ex) {
525
+ logger.error`Failed to close transformer: ${ex}`;
526
+ }
527
+ });
528
+ },
529
+ "transformer",
530
+ ]);
531
+ }
541
532
 
542
- // すべての処理を並列に実行し、エラーが発生した場合は集約します。
543
- const errors: { plugin: "storage" | "transformer"; reason: unknown }[] = [];
533
+ // すべての処理を並列に実行し、エラーが発生した場合は集約します。
534
+ const errors: { plugin: "storage" | "transformer"; reason: unknown }[] = [];
535
+ await Promise.all(
536
+ openFns.map(async ([f, plugin]) => {
537
+ try {
538
+ await f();
539
+ } catch (reason) {
540
+ errors.push({ plugin, reason });
541
+ }
542
+ }),
543
+ );
544
+ if (errors.length > 0) {
545
+ throw new PluginOperationAggregateError({ action: "open", errors });
546
+ }
547
+
548
+ this.#con = {
549
+ ac,
550
+ io: new Asyncmux(),
551
+ };
552
+ } catch (ex) {
553
+ if (dispose.length > 0) {
544
554
  await Promise.all(
545
- openFns.map(async ([f, plugin]) => {
546
- try {
547
- await f();
548
- } catch (reason) {
549
- errors.push({ plugin, reason });
550
- }
555
+ dispose.map(async (f) => {
556
+ await f();
551
557
  }),
552
558
  );
553
- if (errors.length > 0) {
554
- throw new PluginOperationAggregateError({ action: "open", errors });
555
- }
556
- } catch (ex) {
557
- this.#con = null; // unlock の前に null に戻します。
558
-
559
- if (dispose.length > 0) {
560
- await Promise.all(
561
- dispose.map(async (f) => {
562
- await f();
563
- }),
564
- );
565
- }
566
-
567
- throw ex;
568
- } finally {
569
- lock.release();
570
559
  }
571
- } catch (ex) {
572
- this.#con = null;
560
+
573
561
  throw ex;
562
+ } finally {
563
+ this.#acSet.delete(ac);
564
+ lock.release();
574
565
  }
575
566
  }
576
567
 
577
- /**
578
- * ストレージをクローズします。
579
- *
580
- * @param options クローズ時のオプションです。
581
- * @returns 完了を通知する Promise です。
582
- */
583
- public close(options?: CloseOptions): Promise<void>;
584
-
585
- public async close(...args: any): Promise<void> {
586
- if (!this.#con) {
587
- throw new UniKvsIsNotOpenError();
588
- }
589
-
590
- const [options = {}] = v.parseInput(CloseArgsSchema, args);
591
- const { signal = AbortSignal.timeout(10e3), context: contextOption } = options;
592
-
593
- const context = mergeContext(this.#context, contextOption);
594
- context["unikvs:action"] = "close";
595
-
596
- const { conAc, ioMux } = this.#con;
597
- conAc.abort(new UniKvsIsNotOpenError()); // 実行中の他の操作をすべて中断させるために signal を発火させます。
598
-
568
+ async #close(context: Context, signal: AbortSignal, con: Connection): Promise<void> {
599
569
  const lock = await asyncmux(this, signal);
600
570
  try {
601
571
  // ロック待機中に接続状態が変更されていないか再確認します。
602
- if (!this.#con) {
572
+ if (this.#con !== con) {
603
573
  throw new UniKvsIsNotOpenError();
604
574
  }
605
575
 
606
- const lock = await ioMux.lock({ signal });
576
+ const { io } = this.#con;
577
+ const lock = await io.lock({ signal });
607
578
  try {
608
579
  const closeFns: [() => Promise<void>, plugin: "storage" | "transformer"][] = [];
609
580
 
@@ -644,12 +615,56 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
644
615
  } finally {
645
616
  lock.release();
646
617
  }
647
- } finally {
618
+
648
619
  this.#con = null;
620
+ } finally {
649
621
  lock.release();
650
622
  }
651
623
  }
652
624
 
625
+ /**
626
+ * ストレージをクローズします。
627
+ *
628
+ * @param options クローズ時のオプションです。
629
+ * @returns 完了を通知する Promise です。
630
+ */
631
+ public close(options?: CloseOptions): Promise<void>;
632
+
633
+ public close(...args: any): Promise<void> {
634
+ try {
635
+ const [options = {}] = v.parseInput(CloseArgsSchema, args);
636
+ const { signal = AbortSignal.timeout(10e3), context: contextOption } = options;
637
+
638
+ const context = mergeContext(this.#context, contextOption);
639
+ context["unikvs:action"] = "close";
640
+
641
+ if (this.#con === null) {
642
+ const acArr = [...this.#acSet];
643
+ this.#acSet.clear();
644
+ for (const ac of acArr) {
645
+ if (!ac.signal.aborted) {
646
+ ac.abort(new UniKvsIsNotOpenError());
647
+ }
648
+ }
649
+
650
+ throw new UniKvsIsNotOpenError();
651
+ }
652
+
653
+ const { ac } = this.#con;
654
+ const acArr = [ac, ...this.#acSet];
655
+ this.#acSet.clear();
656
+ for (const ac of acArr) {
657
+ if (!ac.signal.aborted) {
658
+ ac.abort(new UniKvsIsNotOpenError());
659
+ }
660
+ }
661
+
662
+ return this.#close(context, signal, this.#con);
663
+ } catch (ex) {
664
+ return Promise.reject(ex);
665
+ }
666
+ }
667
+
653
668
  async [Symbol.asyncDispose](): Promise<void> {
654
669
  if (!this.isOpen) {
655
670
  return;
@@ -661,41 +676,41 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
661
676
  }
662
677
 
663
678
  /**
664
- * 指定したキーに値を保存します。
679
+ * 指定したオプションで値を保存します。
665
680
  *
666
681
  * @template TKey 対象キーの型定義です。
667
- * @param key 操作対象を識別するためのキーです。
668
- * @param value 保存する値です。
669
- * @param options 追加のオプションです。
682
+ * @param options セット操作のオプション一式です。
670
683
  * @returns 完了を通知する Promise です。
671
684
  */
672
685
  public set<const TKey extends KeyofKeyValueMapping<TKeyValueMapping>>(
673
- key: TKey,
674
- value: SetValue<TKeyValueMapping[TKey]>,
675
- options?: Omit<SetOptions, "key" | "value">,
686
+ options: SetOptions<TKeyValueMapping, TKey>,
676
687
  ): Promise<void>;
677
688
 
678
689
  /**
679
- * 指定したオプションで値を保存します。
690
+ * 指定したキーに値を保存します。
680
691
  *
681
692
  * @template TKey 対象キーの型定義です。
682
- * @param options セット操作のオプション一式です。
693
+ * @param key 操作対象を識別するためのキーです。
694
+ * @param value 保存する値です。
695
+ * @param options 追加のオプションです。
683
696
  * @returns 完了を通知する Promise です。
684
697
  */
685
698
  public set<const TKey extends KeyofKeyValueMapping<TKeyValueMapping>>(
686
- options: SetOptions<TKeyValueMapping, TKey>,
699
+ key: TKey,
700
+ value: SetValue<TKeyValueMapping[TKey]>,
701
+ options?: Omit<SetOptions, "key" | "value">,
687
702
  ): Promise<void>;
688
703
 
689
704
  public async set(...args: any): Promise<void> {
690
- if (!this.#con) {
705
+ if (this.#con === null) {
691
706
  throw new UniKvsIsNotOpenError();
692
707
  }
693
708
 
694
709
  const [options] = v.parseInput(SetArgsSchema, args);
695
710
  const { key, value, signal: signalOption, context: contextOption } = options;
696
711
 
697
- const { conAc, ioMux } = this.#con;
698
- const signal = combineSignals([conAc.signal, signalOption]);
712
+ const { ac, io } = this.#con;
713
+ const signal = combineSignals([ac.signal, signalOption]);
699
714
 
700
715
  const context = mergeContext(this.#context, contextOption);
701
716
  context["unikvs:action"] = "set";
@@ -704,7 +719,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
704
719
  const lock = await asyncmux(this, signal);
705
720
  try {
706
721
  // ロック待機中に接続状態が変更されていないか再確認します。
707
- if (!this.#con) {
722
+ if (this.#con === null) {
708
723
  throw new UniKvsIsNotOpenError();
709
724
  }
710
725
 
@@ -718,7 +733,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
718
733
  data = data.pipeThrough(e);
719
734
  }
720
735
 
721
- const lock = await ioMux.lock({ key, signal });
736
+ const lock = await io.lock({ key, signal });
722
737
  try {
723
738
  await Promise.all(
724
739
  this.#destinations.map(async (storage, i) => {
@@ -747,7 +762,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
747
762
  data = await transformer.encode(context, signal, data);
748
763
  }
749
764
 
750
- const lock = await ioMux.lock({ key, signal });
765
+ const lock = await io.lock({ key, signal });
751
766
  try {
752
767
  await Promise.all(
753
768
  this.#destinations.map(async (storage) => {
@@ -799,39 +814,39 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
799
814
  }
800
815
 
801
816
  /**
802
- * 指定したキーから値を取得します。
817
+ * 指定したオプションで値を取得します。
803
818
  *
804
819
  * @template TKey 対象キーの型定義です。
805
- * @param key 操作対象を識別するためのキーです。
806
- * @param options 追加のオプションです。
820
+ * @param options 取得操作のオプション一式です。
807
821
  * @returns 取得した値を返します。
808
822
  */
809
823
  public get<const TKey extends KeyofKeyValueMappingHasPlainValue<TKeyValueMapping>>(
810
- key: TKey,
811
- options?: Omit<GetOptions, "key">,
824
+ options: GetOptions<TKey>,
812
825
  ): Promise<$InferPlainValueData<TKeyValueMapping[TKey]>>;
813
826
 
814
827
  /**
815
- * 指定したオプションで値を取得します。
828
+ * 指定したキーから値を取得します。
816
829
  *
817
830
  * @template TKey 対象キーの型定義です。
818
- * @param options 取得操作のオプション一式です。
831
+ * @param key 操作対象を識別するためのキーです。
832
+ * @param options 追加のオプションです。
819
833
  * @returns 取得した値を返します。
820
834
  */
821
835
  public get<const TKey extends KeyofKeyValueMappingHasPlainValue<TKeyValueMapping>>(
822
- options: GetOptions<TKey>,
836
+ key: TKey,
837
+ options?: Omit<GetOptions, "key">,
823
838
  ): Promise<$InferPlainValueData<TKeyValueMapping[TKey]>>;
824
839
 
825
840
  public async get(...args: any): Promise<unknown> {
826
- if (!this.#con) {
841
+ if (this.#con === null) {
827
842
  throw new UniKvsIsNotOpenError();
828
843
  }
829
844
 
830
845
  const [options] = v.parseInput(GetArgsSchema, args);
831
846
  const { key, signal: signalOption, context: contextOption } = options;
832
847
 
833
- const { conAc, ioMux } = this.#con;
834
- const signal = combineSignals([conAc.signal, signalOption]);
848
+ const { ac, io } = this.#con;
849
+ const signal = combineSignals([ac.signal, signalOption]);
835
850
 
836
851
  const context = mergeContext(this.#context, contextOption);
837
852
  context["unikvs:action"] = "get";
@@ -840,14 +855,14 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
840
855
  const lock = await asyncmux.readonly(this, signal);
841
856
  try {
842
857
  // ロック待機中に接続状態が変更されていないか再確認します。
843
- if (!this.#con) {
858
+ if (this.#con === null) {
844
859
  throw new UniKvsIsNotOpenError();
845
860
  }
846
861
 
847
862
  const NONE = {};
848
863
  let data: any = NONE;
849
864
 
850
- const lock = await ioMux.rLock({ key, signal });
865
+ const lock = await io.rLock({ key, signal });
851
866
  try {
852
867
  // 各ストレージを巡回し、最初に見つかったデータを取得します。
853
868
  for (const storage of this.#destinations) {
@@ -878,39 +893,39 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
878
893
  }
879
894
 
880
895
  /**
881
- * 指定したキーからストリームを取得します。
896
+ * 指定したオプションでストリームを取得します。
882
897
  *
883
898
  * @template TKey 対象キーの型定義です。
884
- * @param key 操作対象を識別するためのキーです。
885
- * @param options 追加のオプションです。
899
+ * @param options ストリーム取得操作のオプション一式です。
886
900
  * @returns 取得したストリームを返します。
887
901
  */
888
902
  public stream<const TKey extends KeyofKeyValueMappingHasStreamValue<TKeyValueMapping>>(
889
- key: TKey,
890
- options?: Omit<StreamOptions, "key">,
903
+ options: StreamOptions<TKey>,
891
904
  ): Promise<ValueStream<$InferStreamValueChunkData<TKeyValueMapping[TKey]>>>;
892
905
 
893
906
  /**
894
- * 指定したオプションでストリームを取得します。
907
+ * 指定したキーからストリームを取得します。
895
908
  *
896
909
  * @template TKey 対象キーの型定義です。
897
- * @param options ストリーム取得操作のオプション一式です。
910
+ * @param key 操作対象を識別するためのキーです。
911
+ * @param options 追加のオプションです。
898
912
  * @returns 取得したストリームを返します。
899
913
  */
900
914
  public stream<const TKey extends KeyofKeyValueMappingHasStreamValue<TKeyValueMapping>>(
901
- options: StreamOptions<TKey>,
915
+ key: TKey,
916
+ options?: Omit<StreamOptions, "key">,
902
917
  ): Promise<ValueStream<$InferStreamValueChunkData<TKeyValueMapping[TKey]>>>;
903
918
 
904
919
  public async stream(...args: any): Promise<ValueStream> {
905
- if (!this.#con) {
920
+ if (this.#con === null) {
906
921
  throw new UniKvsIsNotOpenError();
907
922
  }
908
923
 
909
924
  const [options] = v.parseInput(StreamArgsSchema, args);
910
925
  const { key, signal: signalOption, context: contextOption } = options;
911
926
 
912
- const { conAc, ioMux } = this.#con;
913
- const signal = combineSignals([conAc.signal, signalOption]);
927
+ const { ac, io } = this.#con;
928
+ const signal = combineSignals([ac.signal, signalOption]);
914
929
 
915
930
  const context = mergeContext(this.#context, contextOption);
916
931
  context["unikvs:action"] = "stream";
@@ -919,14 +934,14 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
919
934
  const lock = await asyncmux(this, signal);
920
935
  try {
921
936
  // ロック待機中に接続状態が変更されていないか再確認します。
922
- if (!this.#con) {
937
+ if (this.#con === null) {
923
938
  throw new UniKvsIsNotOpenError();
924
939
  }
925
940
 
926
941
  const NONE: any = {};
927
942
  let r: IReadableStream = NONE;
928
943
 
929
- const lock = await ioMux.rLock({ key, signal });
944
+ const lock = await io.rLock({ key, signal });
930
945
  try {
931
946
  // 各ストレージを巡回し、最初に見つかったデータを取得します。
932
947
  for (const storage of this.#destinations) {
@@ -985,6 +1000,14 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
985
1000
  }
986
1001
  }
987
1002
 
1003
+ /**
1004
+ * 指定したオプションでキーの存在を確認します。
1005
+ *
1006
+ * @param options 存在確認操作のオプションです。
1007
+ * @returns 存在する場合は true、そうでない場合は false を返します。
1008
+ */
1009
+ public has(options: HasOptions<KeyofKeyValueMapping<TKeyValueMapping>>): Promise<boolean>;
1010
+
988
1011
  /**
989
1012
  * 指定したキーが存在するかを確認します。
990
1013
  *
@@ -997,24 +1020,16 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
997
1020
  options?: Omit<HasOptions, "key">,
998
1021
  ): Promise<boolean>;
999
1022
 
1000
- /**
1001
- * 指定したオプションでキーの存在を確認します。
1002
- *
1003
- * @param options 存在確認操作のオプションです。
1004
- * @returns 存在する場合は true、そうでない場合は false を返します。
1005
- */
1006
- public has(options: HasOptions<KeyofKeyValueMapping<TKeyValueMapping>>): Promise<boolean>;
1007
-
1008
1023
  public async has(...args: any): Promise<boolean> {
1009
- if (!this.#con) {
1024
+ if (this.#con === null) {
1010
1025
  throw new UniKvsIsNotOpenError();
1011
1026
  }
1012
1027
 
1013
1028
  const [options] = v.parseInput(HasArgsSchema, args);
1014
1029
  const { key, signal: signalOption, context: contextOption } = options;
1015
1030
 
1016
- const { conAc, ioMux } = this.#con;
1017
- const signal = combineSignals([conAc.signal, signalOption]);
1031
+ const { ac, io } = this.#con;
1032
+ const signal = combineSignals([ac.signal, signalOption]);
1018
1033
 
1019
1034
  const context = mergeContext(this.#context, contextOption);
1020
1035
  context["unikvs:action"] = "has";
@@ -1023,11 +1038,11 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1023
1038
  const lock = await asyncmux(this, signal);
1024
1039
  try {
1025
1040
  // ロック待機中に接続状態が変更されていないか再確認します。
1026
- if (!this.#con) {
1041
+ if (this.#con === null) {
1027
1042
  throw new UniKvsIsNotOpenError();
1028
1043
  }
1029
1044
 
1030
- const lock = await ioMux.rLock({ key, signal });
1045
+ const lock = await io.rLock({ key, signal });
1031
1046
  try {
1032
1047
  // いずれかのストレージに存在すれば true を返します。
1033
1048
  for (const storage of this.#destinations) {
@@ -1045,6 +1060,14 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1045
1060
  }
1046
1061
  }
1047
1062
 
1063
+ /**
1064
+ * 指定したオプションでキーを削除します。
1065
+ *
1066
+ * @param options 削除操作のオプションです。
1067
+ * @returns 完了を通知する Promise です。
1068
+ */
1069
+ public delete(options: DeleteOptions<KeyofKeyValueMapping<TKeyValueMapping>>): Promise<void>;
1070
+
1048
1071
  /**
1049
1072
  * 指定したキーを削除します。
1050
1073
  *
@@ -1057,24 +1080,16 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1057
1080
  options?: Omit<DeleteOptions, "key">,
1058
1081
  ): Promise<void>;
1059
1082
 
1060
- /**
1061
- * 指定したオプションでキーを削除します。
1062
- *
1063
- * @param options 削除操作のオプションです。
1064
- * @returns 完了を通知する Promise です。
1065
- */
1066
- public delete(options: DeleteOptions<KeyofKeyValueMapping<TKeyValueMapping>>): Promise<void>;
1067
-
1068
1083
  public async delete(...args: any): Promise<void> {
1069
- if (!this.#con) {
1084
+ if (this.#con === null) {
1070
1085
  throw new UniKvsIsNotOpenError();
1071
1086
  }
1072
1087
 
1073
1088
  const [options] = v.parseInput(DeleteArgsSchema, args);
1074
1089
  const { key, signal: signalOption, context: contextOption } = options;
1075
1090
 
1076
- const { conAc, ioMux } = this.#con;
1077
- const signal = combineSignals([conAc.signal, signalOption]);
1091
+ const { ac, io } = this.#con;
1092
+ const signal = combineSignals([ac.signal, signalOption]);
1078
1093
 
1079
1094
  const context = mergeContext(this.#context, contextOption);
1080
1095
  context["unikvs:action"] = "delete";
@@ -1083,11 +1098,11 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1083
1098
  const lock = await asyncmux(this, signal);
1084
1099
  try {
1085
1100
  // ロック待機中に接続状態が変更されていないか再確認します。
1086
- if (!this.#con) {
1101
+ if (this.#con === null) {
1087
1102
  throw new UniKvsIsNotOpenError();
1088
1103
  }
1089
1104
 
1090
- const lock = await ioMux.lock({ key, signal });
1105
+ const lock = await io.lock({ key, signal });
1091
1106
  try {
1092
1107
  // すべてのストレージから対象データを削除します。
1093
1108
  // すべての処理を並列に実行し、エラーが発生した場合は集約します。
@@ -1123,15 +1138,15 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1123
1138
  public async clear(options?: ClearOptions): Promise<void>;
1124
1139
 
1125
1140
  public async clear(...args: any): Promise<void> {
1126
- if (!this.#con) {
1141
+ if (this.#con === null) {
1127
1142
  throw new UniKvsIsNotOpenError();
1128
1143
  }
1129
1144
 
1130
1145
  const [options = {}] = v.parseInput(ClearArgsSchema, args);
1131
1146
  const { signal: signalOption, context: contextOption } = options;
1132
1147
 
1133
- const { conAc, ioMux } = this.#con;
1134
- const signal = combineSignals([conAc.signal, signalOption]);
1148
+ const { ac, io } = this.#con;
1149
+ const signal = combineSignals([ac.signal, signalOption]);
1135
1150
 
1136
1151
  const context = mergeContext(this.#context, contextOption);
1137
1152
  context["unikvs:action"] = "clear";
@@ -1139,11 +1154,11 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1139
1154
  const lock = await asyncmux(this, signal);
1140
1155
  try {
1141
1156
  // ロック待機中に接続状態が変更されていないか再確認します。
1142
- if (!this.#con) {
1157
+ if (this.#con === null) {
1143
1158
  throw new UniKvsIsNotOpenError();
1144
1159
  }
1145
1160
 
1146
- const lock = await ioMux.lock({ signal });
1161
+ const lock = await io.lock({ signal });
1147
1162
  try {
1148
1163
  // すべてのストレージで一括削除を実行します。
1149
1164
  // すべての処理を並列に実行し、エラーが発生した場合は集約します。