unikvs 0.0.14 → 0.0.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unikvs",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "description": "A modular and portable KVS client implemented in TypeScript.",
5
5
  "homepage": "https://tai-kun.github.io/unikvs/",
6
6
  "license": "MIT",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@tai-kun/valibot-extra-lab": "^0.0.5",
28
- "@unikvs/core": "0.0.14",
28
+ "@unikvs/core": "0.0.16",
29
29
  "abort-signal-utils": "^0.0.6",
30
30
  "asyncmux": "^0.0.12",
31
31
  "call-fn-once": "^0.0.12",
@@ -35,14 +35,14 @@
35
35
  "devDependencies": {
36
36
  "@babel/plugin-proposal-decorators": "^8.0.2",
37
37
  "@rolldown/plugin-babel": "^0.2.4",
38
- "@unikvs/allow-repair": "0.0.14",
39
- "@unikvs/checksum": "0.0.14",
40
- "@unikvs/compression": "0.0.14",
41
- "@unikvs/fs.node": "0.0.14",
42
- "@unikvs/memory": "0.0.14",
43
- "@unikvs/opfs": "0.0.14",
38
+ "@unikvs/allow-repair": "0.0.16",
39
+ "@unikvs/checksum": "0.0.16",
40
+ "@unikvs/compression": "0.0.16",
41
+ "@unikvs/fs.node": "0.0.16",
42
+ "@unikvs/memory": "0.0.16",
43
+ "@unikvs/opfs": "0.0.16",
44
44
  "@unikvs/testing": "0.0.0",
45
- "@unikvs/utils": "0.0.14",
45
+ "@unikvs/utils": "0.0.16",
46
46
  "@vitest/browser-playwright": "5.0.5",
47
47
  "@vitest/coverage-istanbul": "5.0.5",
48
48
  "@vitest/coverage-v8": "5.0.5",
package/src/_contexts.ts CHANGED
@@ -2,6 +2,8 @@ import {
2
2
  type IGetContext,
3
3
  type IHasContext,
4
4
  type ISetContext,
5
+ type ICopyContext,
6
+ type IMoveContext,
5
7
  type IOpenContext,
6
8
  type IClearContext,
7
9
  type ICloseContext,
@@ -15,6 +17,7 @@ import {
15
17
  type IPipelineContext,
16
18
  type ILifecycleContext,
17
19
  type ITransformContext,
20
+ type VariablesSnapshot,
18
21
  type IKeyedActionContext,
19
22
  type IDecodeStreamContext,
20
23
  type IEncodeStreamContext,
@@ -196,6 +199,15 @@ class PipelineContext implements IPipelineContext {
196
199
 
197
200
  return this;
198
201
  }
202
+
203
+ /**
204
+ * 現在の実行時変数の浅いコピーを作成します。
205
+ *
206
+ * @returns 実行時変数のスナップショットを返します。
207
+ */
208
+ public snapshot(): VariablesSnapshot {
209
+ return new Map(this.#data);
210
+ }
199
211
  }
200
212
 
201
213
  /**
@@ -723,6 +735,81 @@ export class DeleteContext extends KeyedActionContext<"delete"> implements IDele
723
735
  }
724
736
  }
725
737
 
738
+ /**
739
+ * コピー・移動系コンテキストの初期値です。
740
+ */
741
+ type TransferContextInit<TAction extends "copy" | "move"> = KeyedActionContextInit<TAction> & {
742
+ /**
743
+ * コピー先または移動先のキーです。
744
+ */
745
+ readonly destinationKey: string;
746
+ };
747
+
748
+ /**
749
+ * コピー・移動で共通のコンテキストです。
750
+ */
751
+ class TransferContext<TAction extends "copy" | "move"> extends KeyedActionContext<TAction> {
752
+ /**
753
+ * コピー先または移動先のキーです。
754
+ */
755
+ public readonly destinationKey: string;
756
+
757
+ /**
758
+ * コンテキストを作成します。
759
+ *
760
+ * @param init 初期値です。
761
+ */
762
+ public constructor(init: TransferContextInit<TAction>) {
763
+ const { destinationKey, ...superInit } = init;
764
+ super(superInit);
765
+ this.destinationKey = destinationKey;
766
+ }
767
+ }
768
+
769
+ /**
770
+ * `CopyContext` の初期値です。
771
+ */
772
+ type CopyContextInit = Omit<TransferContextInit<"copy">, "action">;
773
+
774
+ /**
775
+ * コピー処理のコンテキストです。
776
+ */
777
+ export class CopyContext extends TransferContext<"copy"> implements ICopyContext {
778
+ /**
779
+ * コンテキストを作成します。
780
+ *
781
+ * @param init 初期値です。
782
+ */
783
+ public constructor(init: CopyContextInit) {
784
+ super({
785
+ ...init,
786
+ action: "copy",
787
+ });
788
+ }
789
+ }
790
+
791
+ /**
792
+ * `MoveContext` の初期値です。
793
+ */
794
+ type MoveContextInit = Omit<TransferContextInit<"move">, "action">;
795
+
796
+ /**
797
+ * 移動処理のコンテキストです。
798
+ */
799
+ export class MoveContext extends TransferContext<"move"> implements IMoveContext {
800
+ /**
801
+ * コンテキストを作成します。
802
+ *
803
+ * @param init 初期値です。
804
+ */
805
+ public constructor(init: MoveContextInit) {
806
+ super({
807
+ ...init,
808
+ action: "move",
809
+ });
810
+ }
811
+ }
812
+
726
813
  /**
727
814
  * `ClearContext` の初期値です。
728
815
  */
package/src/_storage.ts CHANGED
@@ -157,6 +157,32 @@ export default class UniKvsStorage {
157
157
  await this.#io.clear(c);
158
158
  }
159
159
 
160
+ /**
161
+ * データを別のキーへ複製します。
162
+ *
163
+ * @param c コピー元とコピー先のキーを持つコンテキストです。
164
+ */
165
+ public async copy(c: IStorage.CopyContext): Promise<void> {
166
+ if (!this.#io.isOpen) {
167
+ throw new StorageIsNotOpenError({ name: this.name });
168
+ }
169
+
170
+ await this.#io.copy(c);
171
+ }
172
+
173
+ /**
174
+ * データを別のキーへ移動します。
175
+ *
176
+ * @param c 移動元と移動先のキーを持つコンテキストです。
177
+ */
178
+ public async move(c: IStorage.MoveContext): Promise<void> {
179
+ if (!this.#io.isOpen) {
180
+ throw new StorageIsNotOpenError({ name: this.name });
181
+ }
182
+
183
+ await this.#io.move(c);
184
+ }
185
+
160
186
  /**
161
187
  * 読み取り用のストリームを取得します。
162
188
  *
@@ -413,6 +413,130 @@ export const DeleteArgsSchema: GenericSchema<
413
413
  ),
414
414
  ]);
415
415
 
416
+ export const CopyOptionsSchema: ObjectSchema<
417
+ {
418
+ readonly key: StringSchema<undefined>;
419
+ readonly vars: OptionalSchema<typeof VariablesInitSchema, undefined>;
420
+ readonly signal: OptionalSchema<InstanceSchema<typeof AbortSignal, undefined>, undefined>;
421
+ readonly destinationKey: StringSchema<undefined>;
422
+ },
423
+ undefined
424
+ > = v.object({
425
+ key: v.string(),
426
+ vars: v.optional(VariablesInitSchema),
427
+ signal: v.optional(v.instance(AbortSignal)),
428
+ destinationKey: v.string(),
429
+ });
430
+
431
+ export const CopyArgsSchema: GenericSchema<
432
+ any,
433
+ readonly [
434
+ {
435
+ readonly key: string;
436
+ readonly vars?: readonly VariablesEntry[] | undefined;
437
+ readonly signal?: AbortSignal | undefined;
438
+ readonly destinationKey: string;
439
+ },
440
+ ]
441
+ > = v.union([
442
+ v.tuple([CopyOptionsSchema]),
443
+ v.pipe(
444
+ v.tuple([
445
+ CopyOptionsSchema.entries.key,
446
+ CopyOptionsSchema.entries.destinationKey,
447
+ v.optional(v.omit(CopyOptionsSchema, ["key", "destinationKey"])),
448
+ ]),
449
+ v.transform(
450
+ ([key, destinationKey, options]: [
451
+ string,
452
+ string,
453
+ (
454
+ | {
455
+ vars?: readonly VariablesEntry[] | undefined;
456
+ signal?: AbortSignal | undefined;
457
+ }
458
+ | undefined
459
+ ),
460
+ ]): [
461
+ {
462
+ key: string;
463
+ vars?: readonly VariablesEntry[] | undefined;
464
+ signal?: AbortSignal | undefined;
465
+ destinationKey: string;
466
+ },
467
+ ] => [
468
+ {
469
+ ...options,
470
+ key,
471
+ destinationKey,
472
+ },
473
+ ],
474
+ ),
475
+ ),
476
+ ]);
477
+
478
+ export const MoveOptionsSchema: ObjectSchema<
479
+ {
480
+ readonly key: StringSchema<undefined>;
481
+ readonly vars: OptionalSchema<typeof VariablesInitSchema, undefined>;
482
+ readonly signal: OptionalSchema<InstanceSchema<typeof AbortSignal, undefined>, undefined>;
483
+ readonly destinationKey: StringSchema<undefined>;
484
+ },
485
+ undefined
486
+ > = v.object({
487
+ key: v.string(),
488
+ vars: v.optional(VariablesInitSchema),
489
+ signal: v.optional(v.instance(AbortSignal)),
490
+ destinationKey: v.string(),
491
+ });
492
+
493
+ export const MoveArgsSchema: GenericSchema<
494
+ any,
495
+ readonly [
496
+ {
497
+ readonly key: string;
498
+ readonly vars?: readonly VariablesEntry[] | undefined;
499
+ readonly signal?: AbortSignal | undefined;
500
+ readonly destinationKey: string;
501
+ },
502
+ ]
503
+ > = v.union([
504
+ v.tuple([MoveOptionsSchema]),
505
+ v.pipe(
506
+ v.tuple([
507
+ MoveOptionsSchema.entries.key,
508
+ MoveOptionsSchema.entries.destinationKey,
509
+ v.optional(v.omit(MoveOptionsSchema, ["key", "destinationKey"])),
510
+ ]),
511
+ v.transform(
512
+ ([key, destinationKey, options]: [
513
+ string,
514
+ string,
515
+ (
516
+ | {
517
+ vars?: readonly VariablesEntry[] | undefined;
518
+ signal?: AbortSignal | undefined;
519
+ }
520
+ | undefined
521
+ ),
522
+ ]): [
523
+ {
524
+ key: string;
525
+ vars?: readonly VariablesEntry[] | undefined;
526
+ signal?: AbortSignal | undefined;
527
+ destinationKey: string;
528
+ },
529
+ ] => [
530
+ {
531
+ ...options,
532
+ key,
533
+ destinationKey,
534
+ },
535
+ ],
536
+ ),
537
+ ),
538
+ ]);
539
+
416
540
  export const ClearOptionsSchema: ObjectSchema<
417
541
  {
418
542
  readonly vars: OptionalSchema<typeof VariablesInitSchema, undefined>;
package/src/errors.ts CHANGED
@@ -715,7 +715,7 @@ export type PluginOperationAggregateErrorMeta = {
715
715
  /**
716
716
  * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#errors)
717
717
  */
718
- readonly action: "open" | "close" | "write" | "read" | "delete" | "clear";
718
+ readonly action: "open" | "close" | "write" | "read" | "delete" | "copy" | "move" | "clear";
719
719
 
720
720
  /**
721
721
  * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#errors)
@@ -755,7 +755,7 @@ export type PluginOperationAggregateErrorArgs = ErrorOptions & {
755
755
  /**
756
756
  * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#errors)
757
757
  */
758
- readonly action: "open" | "close" | "write" | "read" | "delete" | "clear";
758
+ readonly action: "open" | "close" | "write" | "read" | "delete" | "copy" | "move" | "clear";
759
759
 
760
760
  /**
761
761
  * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#errors)
package/src/unikvs.ts CHANGED
@@ -9,6 +9,8 @@ import {
9
9
  GetContext,
10
10
  HasContext,
11
11
  SetContext,
12
+ CopyContext,
13
+ MoveContext,
12
14
  OpenContext,
13
15
  ClearContext,
14
16
  CloseContext,
@@ -26,6 +28,8 @@ import {
26
28
  GetArgsSchema,
27
29
  HasArgsSchema,
28
30
  SetArgsSchema,
31
+ CopyArgsSchema,
32
+ MoveArgsSchema,
29
33
  OpenArgsSchema,
30
34
  ClearArgsSchema,
31
35
  CloseArgsSchema,
@@ -58,6 +62,8 @@ import type {
58
62
  GetOptions,
59
63
  HasOptions,
60
64
  SetOptions,
65
+ CopyOptions,
66
+ MoveOptions,
61
67
  OpenOptions,
62
68
  ClearOptions,
63
69
  CloseOptions,
@@ -1222,6 +1228,56 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1222
1228
  }
1223
1229
  }
1224
1230
 
1231
+ /**
1232
+ * キーの値を別のキーへ複製します。
1233
+ *
1234
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
1235
+ *
1236
+ * @param options コピー元とコピー先のキーを持つオプションです。
1237
+ *
1238
+ * @returns コピーが完了したら解決します。
1239
+ */
1240
+ public copy<const TKey extends KeyofKeyValueMapping<TKeyValueMapping>>(
1241
+ options: CopyOptions<TKey>,
1242
+ ): Promise<void>;
1243
+ public copy<
1244
+ const TSourceKey extends KeyofKeyValueMapping<TKeyValueMapping>,
1245
+ const TDestinationKey extends KeyofKeyValueMapping<TKeyValueMapping>,
1246
+ >(
1247
+ key: TSourceKey,
1248
+ destinationKey: TDestinationKey,
1249
+ options?: Omit<CopyOptions<TSourceKey | TDestinationKey>, "key" | "destinationKey">,
1250
+ ): Promise<void>;
1251
+ public async copy(...args: any): Promise<void> {
1252
+ const [options] = v.parseInput(CopyArgsSchema, args);
1253
+ await this.#transfer("copy", options);
1254
+ }
1255
+
1256
+ /**
1257
+ * キーの値を別のキーへ移動します。
1258
+ *
1259
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
1260
+ *
1261
+ * @param options 移動元と移動先のキーを持つオプションです。
1262
+ *
1263
+ * @returns 移動が完了したら解決します。
1264
+ */
1265
+ public move<const TKey extends KeyofKeyValueMapping<TKeyValueMapping>>(
1266
+ options: MoveOptions<TKey>,
1267
+ ): Promise<void>;
1268
+ public move<
1269
+ const TSourceKey extends KeyofKeyValueMapping<TKeyValueMapping>,
1270
+ const TDestinationKey extends KeyofKeyValueMapping<TKeyValueMapping>,
1271
+ >(
1272
+ key: TSourceKey,
1273
+ destinationKey: TDestinationKey,
1274
+ options?: Omit<MoveOptions<TSourceKey | TDestinationKey>, "key" | "destinationKey">,
1275
+ ): Promise<void>;
1276
+ public async move(...args: any): Promise<void> {
1277
+ const [options] = v.parseInput(MoveArgsSchema, args);
1278
+ await this.#transfer("move", options);
1279
+ }
1280
+
1225
1281
  public async clear(options?: ClearOptions): Promise<void>;
1226
1282
  public async clear(...args: any): Promise<void> {
1227
1283
  if (this.#con === null) {
@@ -1280,6 +1336,187 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1280
1336
  }
1281
1337
  }
1282
1338
 
1339
+ /**
1340
+ * コピーまたは移動を実行します。
1341
+ *
1342
+ * @param action 実行する操作です。
1343
+ * @param options コピー元・移動元とコピー先・移動先のキーを持つオプションです。
1344
+ *
1345
+ * @returns 操作が完了したら解決します。
1346
+ */
1347
+ async #transfer(
1348
+ action: "copy" | "move",
1349
+ options: {
1350
+ readonly key: string;
1351
+ readonly vars?: readonly VariablesEntry[] | undefined;
1352
+ readonly signal?: AbortSignal | undefined;
1353
+ readonly destinationKey: string;
1354
+ },
1355
+ ): Promise<void> {
1356
+ if (this.#con === null) {
1357
+ throw new UniKvsIsNotOpenError();
1358
+ }
1359
+
1360
+ const { key, destinationKey } = options;
1361
+
1362
+ // コピー元・移動元とコピー先・移動先の両方がスキーマに適合するか検証します。
1363
+ this.#resolveValueSchema(key);
1364
+ this.#resolveValueSchema(destinationKey);
1365
+
1366
+ const { ac, io } = this.#con;
1367
+ const signal = combineSignals([ac.signal, options.signal]);
1368
+ const store = this.#createOperationStore(options.vars);
1369
+
1370
+ using _lock = await asyncmux.readonly(this, signal);
1371
+ // ロック待機中に接続状態が変更されていないか再確認します。
1372
+ if (this.#con === null) {
1373
+ throw new UniKvsIsNotOpenError();
1374
+ }
1375
+
1376
+ const useContext =
1377
+ action === "copy"
1378
+ ? new CopyContext({
1379
+ key,
1380
+ store,
1381
+ signal,
1382
+ destinationKey,
1383
+ })
1384
+ : new MoveContext({
1385
+ key,
1386
+ store,
1387
+ signal,
1388
+ destinationKey,
1389
+ });
1390
+ await this.#use(action, useContext);
1391
+
1392
+ throwIfAborted(signal);
1393
+
1394
+ const sourceResolver = this.#pipeline.createResolver({
1395
+ key,
1396
+ store,
1397
+ signal,
1398
+ });
1399
+ const destinationResolver =
1400
+ key === destinationKey
1401
+ ? sourceResolver
1402
+ : this.#pipeline.createResolver({
1403
+ key: destinationKey,
1404
+ store,
1405
+ signal,
1406
+ });
1407
+
1408
+ if (key === destinationKey) {
1409
+ // 同一キーへのコピー・移動は存在確認だけを行います。
1410
+ using _ioLock = await io.lock({
1411
+ key,
1412
+ signal,
1413
+ });
1414
+
1415
+ await this.#transferLeaves(action, key, store, signal, sourceResolver, destinationResolver);
1416
+
1417
+ return;
1418
+ }
1419
+
1420
+ // デッドロックを避けるため、キーを常に同じ順序でロックします。
1421
+ const firstLockKey = key < destinationKey ? key : destinationKey;
1422
+ const secondLockKey = key < destinationKey ? destinationKey : key;
1423
+ using _firstLock = await io.lock({
1424
+ key: firstLockKey,
1425
+ signal,
1426
+ });
1427
+ using _secondLock = await io.lock({
1428
+ key: secondLockKey,
1429
+ signal,
1430
+ });
1431
+
1432
+ await this.#transferLeaves(action, key, store, signal, sourceResolver, destinationResolver);
1433
+ }
1434
+
1435
+ /**
1436
+ * 各ストレージへコピーまたは移動を適用します。
1437
+ *
1438
+ * @param action 実行する操作です。
1439
+ * @param key コピー元または移動元の論理キーです。
1440
+ * @param store 操作内で共有される変数ストアです。
1441
+ * @param signal 中断シグナルです。
1442
+ * @param sourceResolver コピー元・移動元のキーを解決するリゾルバーです。
1443
+ * @param destinationResolver コピー先・移動先のキーを解決するリゾルバーです。
1444
+ *
1445
+ * @returns 操作が完了したら解決します。
1446
+ */
1447
+ async #transferLeaves(
1448
+ action: "copy" | "move",
1449
+ key: string,
1450
+ store: VariablesStore,
1451
+ signal: AbortSignal,
1452
+ sourceResolver: ReturnType<PipelineGraph["createResolver"]>,
1453
+ destinationResolver: ReturnType<PipelineGraph["createResolver"]>,
1454
+ ): Promise<void> {
1455
+ const errors: PluginErrorRecord[] = [];
1456
+ let found = 0;
1457
+ await Promise.all(
1458
+ this.#pipeline.leaves.map(async (leaf) => {
1459
+ const sourceKey = sourceResolver.resolve(leaf).key;
1460
+ const destinationKey = destinationResolver.resolve(leaf).key;
1461
+
1462
+ try {
1463
+ const existsContext = new HasContext({
1464
+ key: sourceKey,
1465
+ store,
1466
+ signal,
1467
+ });
1468
+
1469
+ if (!(await leaf.storage.exists(existsContext))) {
1470
+ return;
1471
+ }
1472
+
1473
+ found += 1;
1474
+
1475
+ if (action === "copy") {
1476
+ const c = new CopyContext({
1477
+ key: sourceKey,
1478
+ store,
1479
+ signal,
1480
+ destinationKey,
1481
+ });
1482
+ await leaf.storage.copy(c);
1483
+ } else {
1484
+ const c = new MoveContext({
1485
+ key: sourceKey,
1486
+ store,
1487
+ signal,
1488
+ destinationKey,
1489
+ });
1490
+ await leaf.storage.move(c);
1491
+ }
1492
+ } catch (ex) {
1493
+ if (signal.aborted) {
1494
+ throw ex;
1495
+ }
1496
+
1497
+ errors.push({
1498
+ name: leaf.name,
1499
+ index: leaf.index,
1500
+ reason: ex,
1501
+ });
1502
+ logger.error`Failed to ${action} in a storage: ${ex}`;
1503
+ }
1504
+ }),
1505
+ );
1506
+
1507
+ if (found === 0) {
1508
+ throw this.#notFound(key, errors, action);
1509
+ }
1510
+
1511
+ if (errors.length > 0) {
1512
+ throw new PluginOperationAggregateError({
1513
+ action,
1514
+ errors,
1515
+ plugin: "storage",
1516
+ });
1517
+ }
1518
+ }
1519
+
1283
1520
  /**
1284
1521
  * 基本変数と操作固有変数を結合した実行時変数マップを作成します。
1285
1522
  *
@@ -1328,10 +1565,15 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1328
1565
  *
1329
1566
  * @param key 読み取ったキーです。
1330
1567
  * @param errors 収集した失敗です。
1568
+ * @param action 失敗を集約する操作です。
1331
1569
  *
1332
1570
  * @returns `KeyNotFoundError` を返します。
1333
1571
  */
1334
- #notFound(key: string, errors: readonly PluginErrorRecord[]): KeyNotFoundError {
1572
+ #notFound(
1573
+ key: string,
1574
+ errors: readonly PluginErrorRecord[],
1575
+ action: "read" | "copy" | "move" = "read",
1576
+ ): KeyNotFoundError {
1335
1577
  const args: KeyNotFoundErrorArgs = { key };
1336
1578
 
1337
1579
  switch (errors.length) {
@@ -1351,7 +1593,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1351
1593
 
1352
1594
  default: {
1353
1595
  args.cause = new PluginOperationAggregateError({
1354
- action: "read",
1596
+ action,
1355
1597
  errors,
1356
1598
  plugin: "storage",
1357
1599
  });
@@ -1543,7 +1785,7 @@ export default class UniKvs<TKeyValueMapping extends KeyValueMapping = KeyValueM
1543
1785
  * @param c 共有の `use` コンテキストです。
1544
1786
  */
1545
1787
  async #use(
1546
- action: "read" | "write" | "delete" | "clear",
1788
+ action: "read" | "write" | "delete" | "copy" | "move" | "clear",
1547
1789
  c: IMiddleware.UseContext,
1548
1790
  ): Promise<void> {
1549
1791
  throwIfAborted(c.signal);
@@ -188,6 +188,56 @@ export type DeleteOptions<TKey = string> = {
188
188
  readonly vars?: VariablesInit | undefined;
189
189
  };
190
190
 
191
+ /**
192
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
193
+ */
194
+ export type CopyOptions<TKey = string> = {
195
+ /**
196
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
197
+ */
198
+ readonly key: TKey;
199
+
200
+ /**
201
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
202
+ */
203
+ readonly destinationKey: TKey;
204
+
205
+ /**
206
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#variables-and-cancellation)
207
+ */
208
+ readonly signal?: AbortSignal | undefined;
209
+
210
+ /**
211
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#variables-and-cancellation)
212
+ */
213
+ readonly vars?: VariablesInit | undefined;
214
+ };
215
+
216
+ /**
217
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
218
+ */
219
+ export type MoveOptions<TKey = string> = {
220
+ /**
221
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
222
+ */
223
+ readonly key: TKey;
224
+
225
+ /**
226
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
227
+ */
228
+ readonly destinationKey: TKey;
229
+
230
+ /**
231
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#variables-and-cancellation)
232
+ */
233
+ readonly signal?: AbortSignal | undefined;
234
+
235
+ /**
236
+ * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#variables-and-cancellation)
237
+ */
238
+ readonly vars?: VariablesInit | undefined;
239
+ };
240
+
191
241
  /**
192
242
  * [API Reference](https://tai-kun.github.io/unikvs/packages/unikvs#client-operations)
193
243
  */