@procedures/collections 0.55.2 → 0.57.0

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.
@@ -6,8 +6,9 @@
6
6
  * `@procedures/sqlite`. Before, each package copied the cases of `InMemoryStorage`.
7
7
  *
8
8
  * The suite is in the test-only entry `@procedures/collections/testing`. It imports no test
9
- * framework: the caller gives `describe` and `it`, and the checks throw `ContractViolation`. So a
10
- * storage package imports the suite without a cycle, and a runtime entry never loads vitest.
9
+ * framework: the caller gives `describe` and `it`, and the checks throw the `AssertionError` of
10
+ * `node:assert`. So a storage package imports the suite without a cycle, and a runtime entry does
11
+ * not load vitest.
11
12
  *
12
13
  * ```ts
13
14
  * import { describe, it } from "vitest";
@@ -42,7 +43,14 @@ import {
42
43
  type StorageSelector,
43
44
  type VersionConflict,
44
45
  } from "@procedures/client/query";
45
- import { holds, rejects, same, show } from "@mark1russell7/collections/testing";
46
+ import assert from "node:assert/strict";
47
+ import { inspect } from "node:util";
48
+ import { rejects } from "@mark1russell7/rigor-testkit";
49
+
50
+ /** This function gives the text of a value for the message of a failed check, on one line. */
51
+ function show(value: unknown): string {
52
+ return inspect(value, { breakLength: Infinity, depth: null });
53
+ }
46
54
 
47
55
  /** The item of the suite. Its `id` is its key, so a `HybridStorage` can sync it. */
48
56
  export interface ContractItem {
@@ -324,7 +332,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
324
332
  ["size", storage.size()],
325
333
  ["getBatch", storage.getBatch(["a"])],
326
334
  ];
327
- for (const [name, result] of results) holds(isPromise(result), `${name}() did not give a promise`);
335
+ for (const [name, result] of results) assert.ok(isPromise(result), `${name}() did not give a promise`);
328
336
  await Promise.all(results.map(([, result]) => result));
329
337
  for (const [name, start] of [
330
338
  ["set", () => storage.set("a", item("a", 1))],
@@ -334,7 +342,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
334
342
  ["clear", () => storage.clear()],
335
343
  ] as Array<[string, () => Promise<unknown>]>) {
336
344
  const result = start();
337
- holds(isPromise(result), `${name}() did not give a promise`);
345
+ assert.ok(isPromise(result), `${name}() did not give a promise`);
338
346
  await result;
339
347
  }
340
348
  }),
@@ -342,16 +350,16 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
342
350
 
343
351
  add("an empty storage has no item", () =>
344
352
  withStorage(create, async (storage) => {
345
- same(await storage.size(), 0, "size() of an empty storage");
346
- same(await storage.getAll(), [], "getAll() of an empty storage");
347
- same(await storage.get("a"), undefined, "get() of a missing id");
348
- same(await storage.has("a"), false, "has() of a missing id");
349
- same(await storage.getBatch(["a", "b"]), new Map(), "getBatch() of missing ids");
350
- same(await storage.find(() => true), [], "find() in an empty storage");
351
- same(await storage.delete("a"), false, "delete() of a missing id");
352
- same(await storage.deleteBatch(["a", "b"]), 0, "deleteBatch() of missing ids");
353
- if (storage.getEntries) same(await storage.getEntries(), [], "getEntries() of an empty storage");
354
- if (storage.getIds) same(await storage.getIds(), [], "getIds() of an empty storage");
353
+ assert.deepStrictEqual(await storage.size(), 0, "size() of an empty storage");
354
+ assert.deepStrictEqual(await storage.getAll(), [], "getAll() of an empty storage");
355
+ assert.deepStrictEqual(await storage.get("a"), undefined, "get() of a missing id");
356
+ assert.deepStrictEqual(await storage.has("a"), false, "has() of a missing id");
357
+ assert.deepStrictEqual(await storage.getBatch(["a", "b"]), new Map(), "getBatch() of missing ids");
358
+ assert.deepStrictEqual(await storage.find(() => true), [], "find() in an empty storage");
359
+ assert.deepStrictEqual(await storage.delete("a"), false, "delete() of a missing id");
360
+ assert.deepStrictEqual(await storage.deleteBatch(["a", "b"]), 0, "deleteBatch() of missing ids");
361
+ if (storage.getEntries) assert.deepStrictEqual(await storage.getEntries(), [], "getEntries() of an empty storage");
362
+ if (storage.getIds) assert.deepStrictEqual(await storage.getIds(), [], "getIds() of an empty storage");
355
363
  }),
356
364
  );
357
365
 
@@ -359,41 +367,41 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
359
367
  withStorage(create, async (storage) => {
360
368
  await storage.set("a", item("a", 1, ["x"]));
361
369
  await storage.set("b", item("b", 2));
362
- same(await storage.get("a"), item("a", 1, ["x"]), "get() after set()");
363
- same(await storage.has("a"), true, "has() after set()");
364
- same(await storage.size(), 2, "size() after two set() calls");
370
+ assert.deepStrictEqual(await storage.get("a"), item("a", 1, ["x"]), "get() after set()");
371
+ assert.deepStrictEqual(await storage.has("a"), true, "has() after set()");
372
+ assert.deepStrictEqual(await storage.size(), 2, "size() after two set() calls");
365
373
  await storage.set("a", item("a", 10));
366
- same(await storage.get("a"), item("a", 10), "get() after a second set() of the id");
367
- same(await storage.size(), 2, "size() after a second set() of an id");
374
+ assert.deepStrictEqual(await storage.get("a"), item("a", 10), "get() after a second set() of the id");
375
+ assert.deepStrictEqual(await storage.size(), 2, "size() after a second set() of an id");
368
376
  }),
369
377
  );
370
378
 
371
379
  add("delete() gives true for an item that existed, and deleteBatch() counts the items that existed", () =>
372
380
  withStorage(create, async (storage) => {
373
381
  await storage.setBatch([["a", item("a", 1)], ["b", item("b", 2)], ["c", item("c", 3)]]);
374
- same(await storage.delete("a"), true, "delete() of an item");
375
- same(await storage.delete("a"), false, "a second delete() of the id");
376
- same(await storage.has("a"), false, "has() after delete()");
377
- same(await storage.get("a"), undefined, "get() after delete()");
378
- same(await storage.deleteBatch(["b", "missing", "b"]), 1, "deleteBatch() with a missing id and a repeated id");
379
- same(ids(await storage.getAll()), ["c"], "getAll() after the deletes");
382
+ assert.deepStrictEqual(await storage.delete("a"), true, "delete() of an item");
383
+ assert.deepStrictEqual(await storage.delete("a"), false, "a second delete() of the id");
384
+ assert.deepStrictEqual(await storage.has("a"), false, "has() after delete()");
385
+ assert.deepStrictEqual(await storage.get("a"), undefined, "get() after delete()");
386
+ assert.deepStrictEqual(await storage.deleteBatch(["b", "missing", "b"]), 1, "deleteBatch() with a missing id and a repeated id");
387
+ assert.deepStrictEqual(ids(await storage.getAll()), ["c"], "getAll() after the deletes");
380
388
  }),
381
389
  );
382
390
 
383
391
  add("setBatch() and getBatch(): the last value of an id wins, a missing id is not in the map, and empty batches change nothing", () =>
384
392
  withStorage(create, async (storage) => {
385
393
  await storage.setBatch([["a", item("a", 1)], ["b", item("b", 2)], ["a", item("a", 3)]]);
386
- same(await storage.get("a"), item("a", 3), "get() of an id that setBatch() set two times");
387
- same(await storage.size(), 2, "size() after setBatch() with a repeated id");
388
- same(
394
+ assert.deepStrictEqual(await storage.get("a"), item("a", 3), "get() of an id that setBatch() set two times");
395
+ assert.deepStrictEqual(await storage.size(), 2, "size() after setBatch() with a repeated id");
396
+ assert.deepStrictEqual(
389
397
  await storage.getBatch(["b", "missing", "a"]),
390
398
  new Map([["b", item("b", 2)], ["a", item("a", 3)]]),
391
399
  "getBatch() with a missing id",
392
400
  );
393
401
  await storage.setBatch([]);
394
- same(await storage.deleteBatch([]), 0, "deleteBatch() of no id");
395
- same(await storage.getBatch([]), new Map(), "getBatch() of no id");
396
- same(await storage.size(), 2, "size() after the empty batches");
402
+ assert.deepStrictEqual(await storage.deleteBatch([]), 0, "deleteBatch() of no id");
403
+ assert.deepStrictEqual(await storage.getBatch([]), new Map(), "getBatch() of no id");
404
+ assert.deepStrictEqual(await storage.size(), 2, "size() after the empty batches");
397
405
  }),
398
406
  );
399
407
 
@@ -401,15 +409,15 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
401
409
  withStorage(create, async (storage) => {
402
410
  await storage.setBatch([["c", item("c", 3)], ["a", item("a", 1)], ["b", item("b", 2)]]);
403
411
  await storage.set("a", item("a", 10));
404
- same(ids(await storage.getAll()), ["c", "a", "b"], "getAll() after a second set() of an id: the id keeps its place");
412
+ assert.deepStrictEqual(ids(await storage.getAll()), ["c", "a", "b"], "getAll() after a second set() of an id: the id keeps its place");
405
413
  // A delete, then a set: the id goes to the end
406
414
  await storage.delete("c");
407
415
  await storage.set("c", item("c", 30));
408
416
  const expected: Array<[string, ContractItem]> = [["a", item("a", 10)], ["b", item("b", 2)], ["c", item("c", 30)]];
409
- same(await storage.getAll(), expected.map(([, value]) => value), "getAll() after a delete and a new set() of an id");
410
- same(ids(await storage.find(() => true)), ["a", "b", "c"], "find() keeps the order of the entries");
411
- if (storage.getEntries) same(await storage.getEntries(), expected, "getEntries() keeps the order of the entries");
412
- if (storage.getIds) same(await storage.getIds(), ["a", "b", "c"], "getIds() keeps the order of the entries");
417
+ assert.deepStrictEqual(await storage.getAll(), expected.map(([, value]) => value), "getAll() after a delete and a new set() of an id");
418
+ assert.deepStrictEqual(ids(await storage.find(() => true)), ["a", "b", "c"], "find() keeps the order of the entries");
419
+ if (storage.getEntries) assert.deepStrictEqual(await storage.getEntries(), expected, "getEntries() keeps the order of the entries");
420
+ if (storage.getIds) assert.deepStrictEqual(await storage.getIds(), ["a", "b", "c"], "getIds() keeps the order of the entries");
413
421
  }),
414
422
  );
415
423
 
@@ -420,20 +428,20 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
420
428
  await storage.delete("a");
421
429
  await storage.set("a", item("a", 10));
422
430
  const first = await storage.getIds!();
423
- same(first, ["c", "b", "a"], "getIds() after a delete and a new set() of an id");
431
+ assert.deepStrictEqual(first, ["c", "b", "a"], "getIds() after a delete and a new set() of an id");
424
432
  first.splice(0);
425
- same(await storage.getIds!(), ["c", "b", "a"], "getIds() after a change of an earlier result");
426
- if (storage.getEntries) same(await storage.getIds!(), (await storage.getEntries()).map(([id]) => id), "getIds() and the ids of getEntries()");
433
+ assert.deepStrictEqual(await storage.getIds!(), ["c", "b", "a"], "getIds() after a change of an earlier result");
434
+ if (storage.getEntries) assert.deepStrictEqual(await storage.getIds!(), (await storage.getEntries()).map(([id]) => id), "getIds() and the ids of getEntries()");
427
435
  await storage.clear();
428
- same(await storage.getIds!(), [], "getIds() after clear()");
436
+ assert.deepStrictEqual(await storage.getIds!(), [], "getIds() after clear()");
429
437
  }),
430
438
  );
431
439
 
432
440
  add("find() gives the matching items in order, and an error of the predicate rejects the promise", () =>
433
441
  withStorage(create, async (storage) => {
434
442
  await storage.setBatch([["a", item("a", 1)], ["b", item("b", 2)], ["c", item("c", 3)], ["d", item("d", 4)]]);
435
- same(ids(await storage.find((value) => value.n % 2 === 0)), ["b", "d"], "find() of the even items");
436
- same(await storage.find(() => false), [], "find() without a match");
443
+ assert.deepStrictEqual(ids(await storage.find((value) => value.n % 2 === 0)), ["b", "d"], "find() of the even items");
444
+ assert.deepStrictEqual(await storage.find(() => false), [], "find() without a match");
437
445
  const error = await rejects(
438
446
  () =>
439
447
  storage.find(() => {
@@ -441,7 +449,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
441
449
  }),
442
450
  "find() with a predicate that throws",
443
451
  );
444
- holds(error instanceof Error && error.message.includes("the predicate failed"), `find() must reject with the error of the predicate, not ${show(error instanceof Error ? error.message : error)}`);
452
+ assert.ok(error instanceof Error && error.message.includes("the predicate failed"), `find() must reject with the error of the predicate, not ${show(error instanceof Error ? error.message : error)}`);
445
453
  }),
446
454
  );
447
455
 
@@ -449,12 +457,12 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
449
457
  withStorage(create, async (storage) => {
450
458
  await storage.setBatch([["a", item("a", 1)], ["b", item("b", 2)], ["c", item("c", 3)]]);
451
459
  await storage.clear();
452
- same(await storage.size(), 0, "size() after clear()");
453
- same(await storage.getAll(), [], "getAll() after clear()");
454
- same(await storage.has("a"), false, "has() after clear()");
460
+ assert.deepStrictEqual(await storage.size(), 0, "size() after clear()");
461
+ assert.deepStrictEqual(await storage.getAll(), [], "getAll() after clear()");
462
+ assert.deepStrictEqual(await storage.has("a"), false, "has() after clear()");
455
463
  await storage.clear();
456
464
  await storage.set("d", item("d", 4));
457
- same(await storage.getAll(), [item("d", 4)], "getAll() after clear() and set()");
465
+ assert.deepStrictEqual(await storage.getAll(), [item("d", 4)], "getAll() after clear() and set()");
458
466
  }),
459
467
  );
460
468
 
@@ -470,9 +478,9 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
470
478
  batch.delete("a");
471
479
  batch.set("z", item("z", 0));
472
480
  if (storage.getEntries) (await storage.getEntries()).splice(0);
473
- same(ids(await storage.getAll()), ["a", "b"], "getAll() after changes of the results");
474
- same(await storage.has("z"), false, "has() of an id that only a result got");
475
- same(await storage.getBatch(["a"]), new Map([["a", item("a", 1)]]), "getBatch() after a change of a result");
481
+ assert.deepStrictEqual(ids(await storage.getAll()), ["a", "b"], "getAll() after changes of the results");
482
+ assert.deepStrictEqual(await storage.has("z"), false, "has() of an id that only a result got");
483
+ assert.deepStrictEqual(await storage.getBatch(["a"]), new Map([["a", item("a", 1)]]), "getBatch() after a change of a result");
476
484
  }),
477
485
  );
478
486
 
@@ -486,8 +494,8 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
486
494
  await storage.setBatch([["b", batch]]);
487
495
  batch.tags!.push("changed after setBatch");
488
496
  const read = (await storage.get("a"))!;
489
- same(read, item("a", 1, ["x"]), "get() after a change of the value that set() took");
490
- same(await storage.get("b"), item("b", 2, ["y"]), "get() after a change of the value that setBatch() took");
497
+ assert.deepStrictEqual(read, item("a", 1, ["x"]), "get() after a change of the value that set() took");
498
+ assert.deepStrictEqual(await storage.get("b"), item("b", 2, ["y"]), "get() after a change of the value that setBatch() took");
491
499
  read.n = 98;
492
500
  read.tags!.push("changed after get");
493
501
  (await storage.getAll())[0]!.n = 97;
@@ -512,10 +520,10 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
512
520
  });
513
521
  await storage.set("c", item("c", 3, ["z"]));
514
522
  stop();
515
- same(await storage.get("c"), item("c", 3, ["z"]), "get() after an observer changed the value of a change");
523
+ assert.deepStrictEqual(await storage.get("c"), item("c", 3, ["z"]), "get() after an observer changed the value of a change");
516
524
  }
517
- same(await storage.get("a"), item("a", 1, ["x"]), "get() after changes of the read values");
518
- same(await storage.get("b"), item("b", 2, ["y"]), "get() of the other item after changes of the read values");
525
+ assert.deepStrictEqual(await storage.get("a"), item("a", 1, ["x"]), "get() after changes of the read values");
526
+ assert.deepStrictEqual(await storage.get("b"), item("b", 2, ["y"]), "get() of the other item after changes of the read values");
519
527
  }),
520
528
  );
521
529
 
@@ -533,14 +541,14 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
533
541
  ["null", null],
534
542
  ];
535
543
  await storage.setBatch(values);
536
- for (const [id, value] of values) same(await storage.get(id), value, `get("${id}")`);
537
- same(await storage.getAll(), values.map(([, value]) => value), "getAll() of the JSON values");
538
- same(await storage.getBatch(values.map(([id]) => id)), new Map(values), "getBatch() of the JSON values");
539
- same(await storage.size(), values.length, "size() with the JSON values");
540
- same(await storage.has("null"), true, "has() of an id whose value is null");
544
+ for (const [id, value] of values) assert.deepStrictEqual(await storage.get(id), value, `get("${id}")`);
545
+ assert.deepStrictEqual(await storage.getAll(), values.map(([, value]) => value), "getAll() of the JSON values");
546
+ assert.deepStrictEqual(await storage.getBatch(values.map(([id]) => id)), new Map(values), "getBatch() of the JSON values");
547
+ assert.deepStrictEqual(await storage.size(), values.length, "size() with the JSON values");
548
+ assert.deepStrictEqual(await storage.has("null"), true, "has() of an id whose value is null");
541
549
  await storage.set("single", null);
542
- same(await storage.get("single"), null, "get() of an id that set() gave the value null");
543
- same(await storage.get("missing"), undefined, "get() of a missing id, next to a stored null");
550
+ assert.deepStrictEqual(await storage.get("single"), null, "get() of an id that set() gave the value null");
551
+ assert.deepStrictEqual(await storage.get("missing"), undefined, "get() of a missing id, next to a stored null");
544
552
  }),
545
553
  );
546
554
 
@@ -548,8 +556,8 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
548
556
  withStorage(create, async (storage) => {
549
557
  const count = 20;
550
558
  await Promise.all(Array.from({ length: count }, (_, n) => storage.set(`k${n}`, item(`k${n}`, n))));
551
- same(await storage.size(), count, `size() after ${count} writes at the same time`);
552
- same(ids(await storage.getAll()).sort(), Array.from({ length: count }, (_, n) => `k${n}`).sort(), "the ids after the writes at the same time");
559
+ assert.deepStrictEqual(await storage.size(), count, `size() after ${count} writes at the same time`);
560
+ assert.deepStrictEqual(ids(await storage.getAll()).sort(), Array.from({ length: count }, (_, n) => `k${n}`).sort(), "the ids after the writes at the same time");
553
561
  }),
554
562
  );
555
563
 
@@ -561,10 +569,10 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
561
569
  await storage.setBatch(entries);
562
570
  await storage.set("c", item("c", 30));
563
571
  const first = await changes();
564
- holds(typeof first.version === "string" && first.version !== "", `the version must be a text that is not empty, not ${show(first.version)}`);
565
- same(first.full, true, "full of the first call");
566
- same(first.changed, [["c", item("c", 30)], ["a", item("a", 1)], ["b", item("b", 2)]], "changed of the first call: every item, in the order of the entries");
567
- same(first.deleted, [], "deleted of a full result");
572
+ assert.ok(typeof first.version === "string" && first.version !== "", `the version must be a text that is not empty, not ${show(first.version)}`);
573
+ assert.deepStrictEqual(first.full, true, "full of the first call");
574
+ assert.deepStrictEqual(first.changed, [["c", item("c", 30)], ["a", item("a", 1)], ["b", item("b", 2)]], "changed of the first call: every item, in the order of the entries");
575
+ assert.deepStrictEqual(first.deleted, [], "deleted of a full result");
568
576
  }),
569
577
  );
570
578
 
@@ -579,10 +587,10 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
579
587
  await storage.delete("missing");
580
588
  await storage.set("d", item("d", 4));
581
589
  const delta = await changes(start.version);
582
- same(delta.full, false, "full of a delta");
583
- same(delta.changed, [["a", item("a", 10)], ["d", item("d", 4)]], "changed of a delta");
584
- same(delta.deleted, ["b"], "deleted of a delta");
585
- holds(delta.version !== start.version, "the version must change after a write");
590
+ assert.deepStrictEqual(delta.full, false, "full of a delta");
591
+ assert.deepStrictEqual(delta.changed, [["a", item("a", 10)], ["d", item("d", 4)]], "changed of a delta");
592
+ assert.deepStrictEqual(delta.deleted, ["b"], "deleted of a delta");
593
+ assert.ok(delta.version !== start.version, "the version must change after a write");
586
594
  }),
587
595
  );
588
596
 
@@ -599,7 +607,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
599
607
  await storage.delete("c");
600
608
  await storage.setBatch([["e", item("e", 5)], ["b", item("b", 21)]]);
601
609
  const delta = await changes(start.version);
602
- same(
610
+ assert.deepStrictEqual(
603
611
  { changed: delta.changed, deleted: delta.deleted },
604
612
  { changed: [["a", item("a", 10)], ["e", item("e", 5)], ["b", item("b", 21)]], deleted: ["d", "c"] },
605
613
  "the order of a delta: an id written again after another id comes after it",
@@ -609,7 +617,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
609
617
  await storage.set("c", item("c", 30));
610
618
  await storage.deleteBatch(["e", "a"]);
611
619
  const next = await changes(delta.version);
612
- same({ changed: next.changed, deleted: next.deleted }, { changed: [["c", item("c", 30)]], deleted: ["e", "a"] }, "the order of the next delta");
620
+ assert.deepStrictEqual({ changed: next.changed, deleted: next.deleted }, { changed: [["c", item("c", 30)]], deleted: ["e", "a"] }, "the order of the next delta");
613
621
  }),
614
622
  );
615
623
 
@@ -622,14 +630,14 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
622
630
  await storage.delete("b");
623
631
  await storage.set("b", item("b", 20));
624
632
  const back = await changes(start.version);
625
- same({ full: back.full, changed: back.changed, deleted: back.deleted }, { full: false, changed: [["b", item("b", 20)]], deleted: [] }, "a delete, then a set of the id");
633
+ assert.deepStrictEqual({ full: back.full, changed: back.changed, deleted: back.deleted }, { full: false, changed: [["b", item("b", 20)]], deleted: [] }, "a delete, then a set of the id");
626
634
 
627
635
  // The entries are a, c, b now: b went to the end at its new set
628
636
  await storage.clear();
629
637
  const cleared = await changes(back.version);
630
- same({ full: cleared.full, changed: cleared.changed, deleted: cleared.deleted }, { full: false, changed: [], deleted: ["a", "c", "b"] }, "the changes of clear()");
638
+ assert.deepStrictEqual({ full: cleared.full, changed: cleared.changed, deleted: cleared.deleted }, { full: false, changed: [], deleted: ["a", "c", "b"] }, "the changes of clear()");
631
639
  const quiet = await changes(cleared.version);
632
- same({ full: quiet.full, changed: quiet.changed, deleted: quiet.deleted }, { full: false, changed: [], deleted: [] }, "the changes without a write");
640
+ assert.deepStrictEqual({ full: quiet.full, changed: quiet.changed, deleted: quiet.deleted }, { full: false, changed: [], deleted: [] }, "the changes without a write");
633
641
  }),
634
642
  );
635
643
 
@@ -641,12 +649,12 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
641
649
  await changes();
642
650
  for (const unknown of ["not a version", ""]) {
643
651
  const result = await changes(unknown);
644
- same({ full: result.full, changed: result.changed, deleted: result.deleted }, { full: true, changed: [["a", item("a", 1)], ["b", item("b", 2)]], deleted: [] }, `the changes since ${show(unknown)}`);
652
+ assert.deepStrictEqual({ full: result.full, changed: result.changed, deleted: result.deleted }, { full: true, changed: [["a", item("a", 1)], ["b", item("b", 2)]], deleted: [] }, `the changes since ${show(unknown)}`);
645
653
  }
646
654
  await withStorage(create, async (other) => {
647
655
  await other.set("x", item("x", 9));
648
656
  const foreign = (await changesOf(other)()).version;
649
- same((await changes(foreign)).full, true, "full for a version of another storage");
657
+ assert.deepStrictEqual((await changes(foreign)).full, true, "full for a version of another storage");
650
658
  });
651
659
  }),
652
660
  );
@@ -662,12 +670,12 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
662
670
  // Two deletes fit in the log
663
671
  await storage.deleteBatch(["a", "b"]);
664
672
  const two = await changes(start.version);
665
- same({ full: two.full, changed: two.changed, deleted: two.deleted }, { full: false, changed: [], deleted: ["a", "b"] }, "two deletes in a log of two");
673
+ assert.deepStrictEqual({ full: two.full, changed: two.changed, deleted: two.deleted }, { full: false, changed: [], deleted: ["a", "b"] }, "two deletes in a log of two");
666
674
  // The third delete drops the oldest one: the start version gives all items now
667
675
  await storage.delete("c");
668
676
  const after = await changes(start.version);
669
- same({ full: after.full, changed: after.changed, deleted: after.deleted }, { full: true, changed: [["d", item("d", 4)]], deleted: [] }, "a version older than a dropped delete");
670
- same((await changes(after.version)).full, false, "a version after the dropped deletes still gives a delta");
677
+ assert.deepStrictEqual({ full: after.full, changed: after.changed, deleted: after.deleted }, { full: true, changed: [["d", item("d", 4)]], deleted: [] }, "a version older than a dropped delete");
678
+ assert.deepStrictEqual((await changes(after.version)).full, false, "a version after the dropped deletes still gives a delta");
671
679
  }),
672
680
  );
673
681
  }
@@ -702,7 +710,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
702
710
  label = `delete(${id})`;
703
711
  const existed = model.delete(id);
704
712
  if (existed) note(id, true);
705
- same(await storage.delete(id), existed, `the result of step ${step}: ${label}`);
713
+ assert.deepStrictEqual(await storage.delete(id), existed, `the result of step ${step}: ${label}`);
706
714
  } else if (kind < 15) {
707
715
  const batch: Array<[string, ContractItem]> = Array.from({ length: 1 + random(3) }, (_, index) => {
708
716
  const id = pick();
@@ -722,7 +730,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
722
730
  if (existed) note(id, true);
723
731
  return existed;
724
732
  }).length;
725
- same(await storage.deleteBatch(batch), expected, `the result of step ${step}: ${label}`);
733
+ assert.deepStrictEqual(await storage.deleteBatch(batch), expected, `the result of step ${step}: ${label}`);
726
734
  } else if (kind < 19) {
727
735
  label = "clear()";
728
736
  await storage.clear();
@@ -732,17 +740,17 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
732
740
  label = "a saved version";
733
741
  if (hasChanges) versions.push({ version: (await storage.getChangesSince!()).version, entries: new Map(model), at: clock });
734
742
  }
735
- same(await storage.getAll(), [...model.values()], `getAll() after step ${step}: ${label}`);
743
+ assert.deepStrictEqual(await storage.getAll(), [...model.values()], `getAll() after step ${step}: ${label}`);
736
744
  }
737
- same(await storage.size(), model.size, "size() after the sequence");
738
- if (storage.getEntries) same(await storage.getEntries(), [...model.entries()], "getEntries() after the sequence");
739
- if (storage.getIds) same(await storage.getIds(), [...model.keys()], "getIds() after the sequence");
745
+ assert.deepStrictEqual(await storage.size(), model.size, "size() after the sequence");
746
+ if (storage.getEntries) assert.deepStrictEqual(await storage.getEntries(), [...model.entries()], "getEntries() after the sequence");
747
+ if (storage.getIds) assert.deepStrictEqual(await storage.getIds(), [...model.keys()], "getIds() after the sequence");
740
748
  if (!hasChanges) return;
741
- holds(versions.length > 0, "the sequence saved no version: change the seed");
749
+ assert.ok(versions.length > 0, "the sequence saved no version: change the seed");
742
750
  for (const [index, saved] of versions.entries()) {
743
751
  const result = await storage.getChangesSince!(saved.version);
744
752
  if (result.full) {
745
- same(result.changed, [...model.entries()], `the full changes since version ${index}: every item, in the order of the entries`);
753
+ assert.deepStrictEqual(result.changed, [...model.entries()], `the full changes since version ${index}: every item, in the order of the entries`);
746
754
  continue;
747
755
  }
748
756
  // A delta: the changes after the version, in the order of the last change of each id
@@ -751,11 +759,11 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
751
759
  changed: after.filter(([, change]) => !change.deleted).map(([id]): [string, ContractItem] => [id, model.get(id)!]),
752
760
  deleted: after.filter(([, change]) => change.deleted).map(([id]) => id),
753
761
  };
754
- same({ changed: result.changed, deleted: result.deleted }, expected, `the changes since version ${index}`);
762
+ assert.deepStrictEqual({ changed: result.changed, deleted: result.deleted }, expected, `the changes since version ${index}`);
755
763
  const rebuilt = new Map(saved.entries);
756
764
  for (const id of result.deleted) rebuilt.delete(id);
757
765
  for (const [id, value] of result.changed) rebuilt.set(id, value);
758
- same(rebuilt, new Map(model), `the items of version ${index} with its changes`);
766
+ assert.deepStrictEqual(rebuilt, new Map(model), `the items of version ${index} with its changes`);
759
767
  }
760
768
  }),
761
769
  );
@@ -771,8 +779,8 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
771
779
  await storage.setBatch([...DOCUMENTS]);
772
780
  for (const [selector, expected] of SELECTOR_CASES) {
773
781
  const result = await storage.query!(selector);
774
- same(entryIds(result), expected, `the ids of query(${show(selector)})`);
775
- same(result, queryEntries(DOCUMENTS, selector), `the entries of query(${show(selector)})`);
782
+ assert.deepStrictEqual(entryIds(result), expected, `the ids of query(${show(selector)})`);
783
+ assert.deepStrictEqual(result, queryEntries(DOCUMENTS, selector), `the entries of query(${show(selector)})`);
776
784
  }
777
785
  }),
778
786
  );
@@ -783,9 +791,9 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
783
791
  const storage = typed as unknown as JsonStorage;
784
792
  await storage.setBatch([...DOCUMENTS]);
785
793
  for (const [options, expected] of OPTION_CASES) {
786
- same(entryIds(await storage.query!({}, options)), expected, `the ids of query({}, ${show(options)})`);
794
+ assert.deepStrictEqual(entryIds(await storage.query!({}, options)), expected, `the ids of query({}, ${show(options)})`);
787
795
  }
788
- same(entryIds(await storage.query!({ n: { $exists: true } }, { sort: { n: -1 }, limit: 2 })), ["e", "d"], "a selector with a sort and a limit");
796
+ assert.deepStrictEqual(entryIds(await storage.query!({ n: { $exists: true } }, { sort: { n: -1 }, limit: 2 })), ["e", "d"], "a selector with a sort and a limit");
789
797
  }),
790
798
  );
791
799
 
@@ -833,7 +841,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
833
841
  expected = undefined;
834
842
  }
835
843
  if (expected === undefined) await rejects(() => storage.query!(selector, options), label);
836
- else same(await storage.query!(selector, options), expected, label);
844
+ else assert.deepStrictEqual(await storage.query!(selector, options), expected, label);
837
845
  }
838
846
  }),
839
847
  );
@@ -856,8 +864,8 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
856
864
  await storage.setBatch([...DOCUMENTS]);
857
865
  for (const [selector, expected] of REGEX_CASES) {
858
866
  const result = await storage.query!(selector);
859
- same(entryIds(result), expected, `the ids of query(${show(selector)})`);
860
- same(result, queryEntries(DOCUMENTS, selector, {}, REGEX_POLICY), `the entries of query(${show(selector)})`);
867
+ assert.deepStrictEqual(entryIds(result), expected, `the ids of query(${show(selector)})`);
868
+ assert.deepStrictEqual(result, queryEntries(DOCUMENTS, selector, {}, REGEX_POLICY), `the entries of query(${show(selector)})`);
861
869
  }
862
870
  await rejects(() => storage.query!(REDOS), `query(${show(REDOS)}) under a policy with $regex`);
863
871
  }),
@@ -903,7 +911,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
903
911
  [{}, { skip: 5 }, ["f", "g"]],
904
912
  ];
905
913
  for (const [selector, query, expected] of permitted) {
906
- same(entryIds(await storage.query!(selector, query)), expected, `the ids of query(${show(selector)}, ${show(query)})`);
914
+ assert.deepStrictEqual(entryIds(await storage.query!(selector, query)), expected, `the ids of query(${show(selector)}, ${show(query)})`);
907
915
  }
908
916
  },
909
917
  ),
@@ -919,19 +927,19 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
919
927
  if (lacks(typed, "patch", context)) return;
920
928
  const storage = typed as unknown as JsonStorage;
921
929
  await storage.set("a", { id: "a", n: 1, tags: ["x"], meta: { kind: "k1", score: 10 } });
922
- same(await storage.patch!("a", { n: 2 }), { id: "a", n: 2, tags: ["x"], meta: { kind: "k1", score: 10 } }, "patch() of one field");
923
- same(await storage.patch!("a", { meta: { score: 11, extra: true }, tags: null }), { id: "a", n: 2, meta: { kind: "k1", score: 11, extra: true } }, "patch() of an object field and a null field");
924
- same(await storage.patch!("a", { tags: ["y", "z"], meta: { extra: null } }), { id: "a", n: 2, meta: { kind: "k1", score: 11 }, tags: ["y", "z"] }, "patch() of an array field and a nested null");
925
- same(await storage.get("a"), { id: "a", n: 2, meta: { kind: "k1", score: 11 }, tags: ["y", "z"] }, "get() after the patches");
926
- same(await storage.patch!("missing", { n: 1 }), undefined, "patch() of a missing id");
927
- same(await storage.has("missing"), false, "has() of a missing id after patch()");
928
- same(await storage.size(), 1, "size() after patch() of a missing id");
930
+ assert.deepStrictEqual(await storage.patch!("a", { n: 2 }), { id: "a", n: 2, tags: ["x"], meta: { kind: "k1", score: 10 } }, "patch() of one field");
931
+ assert.deepStrictEqual(await storage.patch!("a", { meta: { score: 11, extra: true }, tags: null }), { id: "a", n: 2, meta: { kind: "k1", score: 11, extra: true } }, "patch() of an object field and a null field");
932
+ assert.deepStrictEqual(await storage.patch!("a", { tags: ["y", "z"], meta: { extra: null } }), { id: "a", n: 2, meta: { kind: "k1", score: 11 }, tags: ["y", "z"] }, "patch() of an array field and a nested null");
933
+ assert.deepStrictEqual(await storage.get("a"), { id: "a", n: 2, meta: { kind: "k1", score: 11 }, tags: ["y", "z"] }, "get() after the patches");
934
+ assert.deepStrictEqual(await storage.patch!("missing", { n: 1 }), undefined, "patch() of a missing id");
935
+ assert.deepStrictEqual(await storage.has("missing"), false, "has() of a missing id after patch()");
936
+ assert.deepStrictEqual(await storage.size(), 1, "size() after patch() of a missing id");
929
937
  await storage.set("plain", 5);
930
- same(await storage.patch!("plain", { n: 1 }), { n: 1 }, "patch() of an item that is not an object");
938
+ assert.deepStrictEqual(await storage.patch!("plain", { n: 1 }), { n: 1 }, "patch() of an item that is not an object");
931
939
  for (const fields of [null, [1], "x", 3]) {
932
940
  await rejects(() => storage.patch!("a", fields as never), `patch() with the fields ${show(fields)}`);
933
941
  }
934
- same(await storage.get("a"), { id: "a", n: 2, meta: { kind: "k1", score: 11 }, tags: ["y", "z"] }, "get() after the patches that were not correct");
942
+ assert.deepStrictEqual(await storage.get("a"), { id: "a", n: 2, meta: { kind: "k1", score: 11 }, tags: ["y", "z"] }, "get() after the patches that were not correct");
935
943
  }),
936
944
  );
937
945
 
@@ -940,12 +948,12 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
940
948
  if (lacks(typed, "patch", context)) return;
941
949
  const storage = typed as unknown as JsonStorage;
942
950
  await storage.set("a", { id: "a", n: 1, tags: ["x", "y"], meta: { kind: "k1", score: 10 } });
943
- same(
951
+ assert.deepStrictEqual(
944
952
  await storage.patch!("a", { $set: { "meta.kind": "k2", note: null, "tags.1": "z", "deep.new.path": 1 }, $unset: ["meta.score"] }),
945
953
  { id: "a", n: 1, tags: ["x", "z"], meta: { kind: "k2" }, note: null, deep: { new: { path: 1 } } },
946
954
  "patch() with $set and $unset",
947
955
  );
948
- same(
956
+ assert.deepStrictEqual(
949
957
  await storage.patch!("a", { $unset: ["tags.0", "missing.path", "deep"], $set: { "tags.2": "w" } }),
950
958
  { id: "a", n: 1, tags: [null, "z", "w"], meta: { kind: "k2" }, note: null },
951
959
  "patch() that removes an element of an array, a missing path and a field, and adds an element",
@@ -961,9 +969,9 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
961
969
  ["a path past the end of an array", { $set: { "tags.7": "v" } }],
962
970
  ];
963
971
  for (const [what, fields] of wrong) await rejects(() => storage.patch!("a", fields as never), `patch() with ${what}`);
964
- same(await storage.get("a"), after, "get() after the patches that were not correct");
965
- same(await storage.patch!("missing", { $set: { n: 1 } }), undefined, "patch() with $set of a missing id");
966
- same(await storage.has("missing"), false, "has() of a missing id after patch() with $set");
972
+ assert.deepStrictEqual(await storage.get("a"), after, "get() after the patches that were not correct");
973
+ assert.deepStrictEqual(await storage.patch!("missing", { $set: { n: 1 } }), undefined, "patch() with $set of a missing id");
974
+ assert.deepStrictEqual(await storage.has("missing"), false, "has() of a missing id after patch() with $set");
967
975
  }),
968
976
  );
969
977
 
@@ -972,12 +980,12 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
972
980
  if (lacks(typed, "patch", context)) return;
973
981
  const storage = typed as unknown as JsonStorage;
974
982
  await storage.set("a", { id: "a", tags: ["a", "b", "c", "d"], rows: [{ n: 1, keys: ["x"] }, { n: 2, keys: ["y"] }], meta: { kind: "k1" } });
975
- same(
983
+ assert.deepStrictEqual(
976
984
  await storage.patch!("a", { $remove: ["tags.1", "tags.3", "meta.kind"], $insert: { "rows.1.keys.0": "w" } }),
977
985
  { id: "a", tags: ["a", "c"], rows: [{ n: 1, keys: ["x"] }, { n: 2, keys: ["w", "y"] }], meta: {} },
978
986
  "patch() with $remove and $insert",
979
987
  );
980
- same(
988
+ assert.deepStrictEqual(
981
989
  await storage.patch!("a", { $insert: { "tags.0": "z", "tags.2": "e" }, $remove: ["rows.0", "missing.0"], $set: { "rows.1.n": 3 } }),
982
990
  { id: "a", tags: ["z", "a", "c", "e"], rows: [{ n: 3, keys: ["w", "y"] }], meta: {} },
983
991
  "patch() that inserts at the start and at the end, and removes a missing path",
@@ -992,7 +1000,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
992
1000
  ["an $insert into a value that is not an array", { $insert: { "meta.0": "q" } }],
993
1001
  ];
994
1002
  for (const [what, fields] of wrong) await rejects(() => storage.patch!("a", fields as never), `patch() with ${what}`);
995
- same(await storage.get("a"), after, "get() after the patches that were not correct");
1003
+ assert.deepStrictEqual(await storage.get("a"), after, "get() after the patches that were not correct");
996
1004
  }),
997
1005
  );
998
1006
 
@@ -1005,7 +1013,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
1005
1013
  await Promise.all(Array.from({ length: count }, (_, n) => storage.patch!("a", { [`f${n}`]: n })));
1006
1014
  const expected: Record<string, unknown> = { id: "a" };
1007
1015
  for (let n = 0; n < count; n++) expected[`f${n}`] = n;
1008
- same(await storage.get("a"), expected, `get() after ${count} patches at the same time`);
1016
+ assert.deepStrictEqual(await storage.get("a"), expected, `get() after ${count} patches at the same time`);
1009
1017
  }),
1010
1018
  );
1011
1019
 
@@ -1017,7 +1025,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
1017
1025
  await storage.patch!("a", { n: 10 });
1018
1026
  await storage.patch!("missing", { n: 3 });
1019
1027
  const delta = await storage.getChangesSince!(start.version);
1020
- same({ full: delta.full, changed: delta.changed, deleted: delta.deleted }, { full: false, changed: [["a", item("a", 10)]], deleted: [] }, "the changes after a patch");
1028
+ assert.deepStrictEqual({ full: delta.full, changed: delta.changed, deleted: delta.deleted }, { full: false, changed: [["a", item("a", 10)]], deleted: [] }, "the changes after a patch");
1021
1029
  }),
1022
1030
  );
1023
1031
 
@@ -1031,14 +1039,14 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
1031
1039
  const batches: unknown[][] = [];
1032
1040
  const stop = storage.observe!((batch) => batches.push(plainBatch(batch)));
1033
1041
  await storage.set("a", item("a", 1));
1034
- same(batches.length, 1, "the batches when set() resolves");
1042
+ assert.deepStrictEqual(batches.length, 1, "the batches when set() resolves");
1035
1043
  await storage.setBatch([["b", item("b", 2)], ["c", item("c", 3)]]);
1036
1044
  await storage.delete("a");
1037
1045
  await storage.deleteBatch(["b", "missing"]);
1038
1046
  if (storage.patch) await storage.patch("c", { n: 30 });
1039
1047
  await storage.clear();
1040
1048
  stop();
1041
- same(
1049
+ assert.deepStrictEqual(
1042
1050
  batches,
1043
1051
  [
1044
1052
  [{ type: "set", id: "a", value: item("a", 1) }],
@@ -1067,7 +1075,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
1067
1075
  await storage.setBatch([]);
1068
1076
  await storage.clear();
1069
1077
  if (storage.patch) await storage.patch("missing", { n: 1 });
1070
- same(batches, [], "the batches of the writes that change nothing");
1078
+ assert.deepStrictEqual(batches, [], "the batches of the writes that change nothing");
1071
1079
  await storage.set("a", item("a", 1), { origin: "sync" });
1072
1080
  await storage.setBatch([["b", item("b", 2)]], { origin: "app" });
1073
1081
  await storage.delete("a", { origin: "sync" });
@@ -1075,7 +1083,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
1075
1083
  await storage.set("c", item("c", 3), {});
1076
1084
  await storage.clear({ origin: "reset" });
1077
1085
  stop();
1078
- same(
1086
+ assert.deepStrictEqual(
1079
1087
  batches,
1080
1088
  [
1081
1089
  [{ type: "set", id: "a", value: item("a", 1), origin: "sync" }],
@@ -1103,8 +1111,8 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
1103
1111
  await storage.delete("a");
1104
1112
  stopSecond();
1105
1113
  await storage.set("b", item("b", 2));
1106
- same(first, ["set"], "the changes of the first observer");
1107
- same(second, ["set", "delete"], "the changes of the second observer");
1114
+ assert.deepStrictEqual(first, ["set"], "the changes of the first observer");
1115
+ assert.deepStrictEqual(second, ["set", "delete"], "the changes of the second observer");
1108
1116
  }),
1109
1117
  );
1110
1118
 
@@ -1114,7 +1122,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
1114
1122
  await storage.flush!();
1115
1123
  await storage.set("a", item("a", 1));
1116
1124
  await storage.flush!();
1117
- same(await storage.get("a"), item("a", 1), "get() after flush()");
1125
+ assert.deepStrictEqual(await storage.get("a"), item("a", 1), "get() after flush()");
1118
1126
  }),
1119
1127
  );
1120
1128
 
@@ -1123,8 +1131,8 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
1123
1131
  if (lacks(storage, "getMetadata", context)) return;
1124
1132
  await storage.setBatch([["a", item("a", 1)], ["b", item("b", 2)]]);
1125
1133
  const metadata = await storage.getMetadata!();
1126
- holds(["memory", "api", "hybrid", "synced", "custom"].includes(metadata.type), `getMetadata() gave the unknown type ${show(metadata.type)}`);
1127
- same(metadata.size, 2, "the size of getMetadata()");
1134
+ assert.ok(["memory", "api", "hybrid", "synced", "custom"].includes(metadata.type), `getMetadata() gave the unknown type ${show(metadata.type)}`);
1135
+ assert.deepStrictEqual(metadata.size, 2, "the size of getMetadata()");
1128
1136
  }),
1129
1137
  );
1130
1138
 
@@ -1158,7 +1166,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
1158
1166
  const check = async (when: string): Promise<void> => {
1159
1167
  for (const [name, start] of operations) {
1160
1168
  const error = await rejects(start, `${name}() ${when}`);
1161
- holds(
1169
+ assert.ok(
1162
1170
  error instanceof Error && /closed/i.test(error.message),
1163
1171
  `${name}() ${when} must reject with an Error whose message says "closed", not ${show(error instanceof Error ? error.message : error)}`,
1164
1172
  );
@@ -1172,7 +1180,7 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
1172
1180
  } catch (thrown) {
1173
1181
  error = thrown;
1174
1182
  }
1175
- holds(error instanceof Error && /closed/i.test(error.message), `observe() ${when} must throw an Error whose message says "closed", not ${show(error instanceof Error ? error.message : error)}`);
1183
+ assert.ok(error instanceof Error && /closed/i.test(error.message), `observe() ${when} must throw an Error whose message says "closed", not ${show(error instanceof Error ? error.message : error)}`);
1176
1184
  };
1177
1185
  await check("after close()");
1178
1186
  checkObserve("after close()");
@@ -1194,9 +1202,9 @@ export function collectionStorageContract(options: CollectionStorageContractOpti
1194
1202
  */
1195
1203
  function conflictsOfRejection(error: unknown, what: string): readonly VersionConflict[] {
1196
1204
  const code = (error as { code?: unknown } | null)?.code;
1197
- holds(code === "VERSION_CONFLICT", `${what}: the error must have the code VERSION_CONFLICT, not ${show(code)} (${show(error instanceof Error ? error.message : error)})`);
1205
+ assert.ok(code === "VERSION_CONFLICT", `${what}: the error must have the code VERSION_CONFLICT, not ${show(code)} (${show(error instanceof Error ? error.message : error)})`);
1198
1206
  const conflicts = versionConflictsOf(error);
1199
- holds(conflicts !== undefined, `${what}: the error must have its conflicts`);
1207
+ assert.ok(conflicts !== undefined, `${what}: the error must have its conflicts`);
1200
1208
  return conflicts!;
1201
1209
  }
1202
1210
 
@@ -1212,10 +1220,10 @@ function addPreconditionCases(
1212
1220
  await rejects(() => storage.set("a", item("a", 2), { expectedVersion: "v1" }), "set() with expectedVersion on a storage without versions");
1213
1221
  await rejects(() => storage.delete("a", { expectedVersion: "v1" }), "delete() with expectedVersion on a storage without versions");
1214
1222
  await rejects(() => storage.setBatch([["a", item("a", 3)]], { expectedVersions: [["a", "v1"]] }), "setBatch() with expectedVersions on a storage without versions");
1215
- same(await storage.get("a"), item("a", 1), "the item after the refused writes");
1223
+ assert.deepStrictEqual(await storage.get("a"), item("a", 1), "the item after the refused writes");
1216
1224
  // A write without a precondition is the write of before
1217
1225
  await storage.set("a", item("a", 4));
1218
- same(await storage.get("a"), item("a", 4), "a write without expectedVersion");
1226
+ assert.deepStrictEqual(await storage.get("a"), item("a", 4), "a write without expectedVersion");
1219
1227
  }),
1220
1228
  );
1221
1229
 
@@ -1226,11 +1234,11 @@ function addPreconditionCases(
1226
1234
  withStorage(versioned, async (storage) => {
1227
1235
  await storage.set("a", item("a", 1));
1228
1236
  await storage.set("a", item("a", 2), { expectedVersion: "v1" });
1229
- same(await storage.get("a"), item("a", 2), "the item after set() with the expected version");
1237
+ assert.deepStrictEqual(await storage.get("a"), item("a", 2), "the item after set() with the expected version");
1230
1238
  await storage.set("a", item("a", 3));
1231
- same(await storage.get("a"), item("a", 3), "the item after set() without expectedVersion");
1232
- same(await storage.delete("a", { expectedVersion: "v3" }), true, "delete() with the expected version");
1233
- same(await storage.get("a"), undefined, "the item after delete() with the expected version");
1239
+ assert.deepStrictEqual(await storage.get("a"), item("a", 3), "the item after set() without expectedVersion");
1240
+ assert.deepStrictEqual(await storage.delete("a", { expectedVersion: "v3" }), true, "delete() with the expected version");
1241
+ assert.deepStrictEqual(await storage.get("a"), undefined, "the item after delete() with the expected version");
1234
1242
  }),
1235
1243
  );
1236
1244
 
@@ -1244,15 +1252,15 @@ function addPreconditionCases(
1244
1252
  const before = storage.getChangesSince ? (await storage.getChangesSince()).version : undefined;
1245
1253
  const expected: VersionConflict = { id: "a", expected: "v2", found: true, value: item("a", 1), version: "v1" };
1246
1254
  const setError = await rejects(() => storage.set("a", item("a", 3), { expectedVersion: "v2" }), "set() with a stale version");
1247
- same(conflictsOfRejection(setError, "set() with a stale version"), [expected], "the conflicts of set() with a stale version");
1255
+ assert.deepStrictEqual(conflictsOfRejection(setError, "set() with a stale version"), [expected], "the conflicts of set() with a stale version");
1248
1256
  const deleteError = await rejects(() => storage.delete("a", { expectedVersion: "v2" }), "delete() with a stale version");
1249
- same(conflictsOfRejection(deleteError, "delete() with a stale version"), [expected], "the conflicts of delete() with a stale version");
1250
- same(await storage.get("a"), item("a", 1), "the item after the refused writes");
1257
+ assert.deepStrictEqual(conflictsOfRejection(deleteError, "delete() with a stale version"), [expected], "the conflicts of delete() with a stale version");
1258
+ assert.deepStrictEqual(await storage.get("a"), item("a", 1), "the item after the refused writes");
1251
1259
  stop?.();
1252
- same(batches, 0, "the batches of observe() for the refused writes");
1260
+ assert.deepStrictEqual(batches, 0, "the batches of observe() for the refused writes");
1253
1261
  if (storage.getChangesSince && before !== undefined) {
1254
1262
  const after = await storage.getChangesSince(before);
1255
- same({ changed: after.changed, deleted: after.deleted }, { changed: [], deleted: [] }, "the changes after the refused writes");
1263
+ assert.deepStrictEqual({ changed: after.changed, deleted: after.deleted }, { changed: [], deleted: [] }, "the changes after the refused writes");
1256
1264
  }
1257
1265
  }),
1258
1266
  );
@@ -1260,13 +1268,13 @@ function addPreconditionCases(
1260
1268
  add("the expected version null expects no item", () =>
1261
1269
  withStorage(versioned, async (storage) => {
1262
1270
  await storage.set("b", item("b", 1), { expectedVersion: null });
1263
- same(await storage.get("b"), item("b", 1), "set() with expectedVersion null of a missing id");
1271
+ assert.deepStrictEqual(await storage.get("b"), item("b", 1), "set() with expectedVersion null of a missing id");
1264
1272
  const exists = await rejects(() => storage.set("b", item("b", 2), { expectedVersion: null }), "set() with expectedVersion null of an existing id");
1265
- same(conflictsOfRejection(exists, "set() with expectedVersion null of an existing id"), [{ id: "b", expected: null, found: true, value: item("b", 1), version: "v1" }], "the conflict of an existing id");
1273
+ assert.deepStrictEqual(conflictsOfRejection(exists, "set() with expectedVersion null of an existing id"), [{ id: "b", expected: null, found: true, value: item("b", 1), version: "v1" }], "the conflict of an existing id");
1266
1274
  const missing = await rejects(() => storage.set("c", item("c", 1), { expectedVersion: "v1" }), "set() with a version of a missing id");
1267
- same(conflictsOfRejection(missing, "set() with a version of a missing id"), [{ id: "c", expected: "v1", found: false, version: null }], "the conflict of a missing id");
1268
- same(await storage.has("c"), false, "the missing id after the refused set()");
1269
- same(await storage.delete("x", { expectedVersion: null }), false, "delete() with expectedVersion null of a missing id");
1275
+ assert.deepStrictEqual(conflictsOfRejection(missing, "set() with a version of a missing id"), [{ id: "c", expected: "v1", found: false, version: null }], "the conflict of a missing id");
1276
+ assert.deepStrictEqual(await storage.has("c"), false, "the missing id after the refused set()");
1277
+ assert.deepStrictEqual(await storage.delete("x", { expectedVersion: null }), false, "delete() with expectedVersion null of a missing id");
1270
1278
  }),
1271
1279
  );
1272
1280
 
@@ -1277,11 +1285,11 @@ function addPreconditionCases(
1277
1285
  () => storage.setBatch([["a", item("a", 2)], ["b", item("b", 2)], ["c", item("c", 1)]], { expectedVersions: [["a", "v1"], ["b", "v9"]] }),
1278
1286
  "setBatch() with one stale version",
1279
1287
  );
1280
- same(conflictsOfRejection(error, "setBatch() with one stale version"), [{ id: "b", expected: "v9", found: true, value: item("b", 1), version: "v1" }], "the conflicts of setBatch()");
1281
- same(await storage.getBatch(["a", "b", "c"]), new Map([["a", item("a", 1)], ["b", item("b", 1)]]), "the items after the refused batch");
1288
+ assert.deepStrictEqual(conflictsOfRejection(error, "setBatch() with one stale version"), [{ id: "b", expected: "v9", found: true, value: item("b", 1), version: "v1" }], "the conflicts of setBatch()");
1289
+ assert.deepStrictEqual(await storage.getBatch(["a", "b", "c"]), new Map([["a", item("a", 1)], ["b", item("b", 1)]]), "the items after the refused batch");
1282
1290
  // An id without an expected version has no precondition
1283
1291
  await storage.setBatch([["a", item("a", 2)], ["b", item("b", 2)], ["c", item("c", 1)]], { expectedVersions: [["a", "v1"], ["b", "v1"]] });
1284
- same(await storage.getBatch(["a", "b", "c"]), new Map([["a", item("a", 2)], ["b", item("b", 2)], ["c", item("c", 1)]]), "the items after the batch");
1292
+ assert.deepStrictEqual(await storage.getBatch(["a", "b", "c"]), new Map([["a", item("a", 2)], ["b", item("b", 2)], ["c", item("c", 1)]]), "the items after the batch");
1285
1293
  }),
1286
1294
  );
1287
1295
 
@@ -1293,11 +1301,11 @@ function addPreconditionCases(
1293
1301
  storage.set("a", item("a", 3), { expectedVersion: "v1" }),
1294
1302
  ]);
1295
1303
  const won = results.flatMap((result, index) => (result.status === "fulfilled" ? [index] : []));
1296
- same(won.length, 1, "the number of writes that won");
1304
+ assert.deepStrictEqual(won.length, 1, "the number of writes that won");
1297
1305
  const lost = results.find((result): result is PromiseRejectedResult => result.status === "rejected")!;
1298
1306
  const conflicts = conflictsOfRejection(lost.reason, "the write that lost");
1299
- same(conflicts.map((conflict) => conflict.id), ["a"], "the conflict of the write that lost");
1300
- same(await storage.get("a"), item("a", won[0] === 0 ? 2 : 3), "the item of the write that won");
1307
+ assert.deepStrictEqual(conflicts.map((conflict) => conflict.id), ["a"], "the conflict of the write that lost");
1308
+ assert.deepStrictEqual(await storage.get("a"), item("a", won[0] === 0 ? 2 : 3), "the item of the write that won");
1301
1309
  }),
1302
1310
  );
1303
1311
  }