@rotorsoft/act-tck 1.41.4 → 2.0.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.
package/dist/index.cjs CHANGED
@@ -82,8 +82,7 @@ var seed_stream = async (store, stream, count, correlation) => {
82
82
  const out = [];
83
83
  for (let i = 0; i < count; i++) {
84
84
  const committed = await store.commit(
85
- stream,
86
- [inc(1)],
85
+ [{ stream, msgs: [inc(1)] }],
87
86
  make_meta({ correlation, stream })
88
87
  );
89
88
  out.push(...committed);
@@ -646,14 +645,17 @@ var apply_plan = async (store, plan, pii_isolation) => {
646
645
  if (op.t === "commit") {
647
646
  const msgs = op.pii && pii_isolation ? op.msgs.map((m, i) => i === 0 ? { ...m, pii: op.pii } : m) : op.msgs;
648
647
  await store.commit(
649
- op.stream,
650
- msgs,
648
+ [{ stream: op.stream, msgs }],
651
649
  make_meta({ stream: op.stream, correlation: plan.correlation })
652
650
  );
653
651
  } else if (op.t === "snapshot") {
654
652
  await store.commit(
655
- op.stream,
656
- [{ name: import_act.SNAP_EVENT, data: { count: op.count } }],
653
+ [
654
+ {
655
+ stream: op.stream,
656
+ msgs: [{ name: import_act.SNAP_EVENT, data: { count: op.count } }]
657
+ }
658
+ ],
657
659
  make_meta({ stream: op.stream, correlation: plan.correlation })
658
660
  );
659
661
  } else if (op.t === "truncate") {
@@ -662,8 +664,12 @@ var apply_plan = async (store, plan, pii_isolation) => {
662
664
  ]);
663
665
  } else if (op.t === "truncate_windowed") {
664
666
  await store.commit(
665
- op.stream,
666
- [{ name: import_act.SNAP_EVENT, data: { count: 1 } }],
667
+ [
668
+ {
669
+ stream: op.stream,
670
+ msgs: [{ name: import_act.SNAP_EVENT, data: { count: 1 } }]
671
+ }
672
+ ],
667
673
  make_meta({ stream: op.stream, correlation: plan.correlation })
668
674
  );
669
675
  await store.truncate([
@@ -974,8 +980,7 @@ var runStorePropertyTck = (options) => {
974
980
  for (const { stream, count } of commits) {
975
981
  const before = expected.get(stream) ?? -1;
976
982
  const committed = await store.commit(
977
- stream,
978
- events(count),
983
+ [{ stream, msgs: events(count) }],
979
984
  make_meta({ stream })
980
985
  );
981
986
  committed.forEach((e, i) => {
@@ -1000,8 +1005,7 @@ var runStorePropertyTck = (options) => {
1000
1005
  await reset2();
1001
1006
  for (const { stream: stream2, count } of commits) {
1002
1007
  await store.commit(
1003
- stream2,
1004
- events(count),
1008
+ [{ stream: stream2, msgs: events(count) }],
1005
1009
  make_meta({ stream: stream2 })
1006
1010
  );
1007
1011
  }
@@ -1009,10 +1013,8 @@ var runStorePropertyTck = (options) => {
1009
1013
  const before = await collect(store, { stream, stream_exact: true });
1010
1014
  await (0, import_vitest8.expect)(
1011
1015
  store.commit(
1012
- stream,
1013
- [inc(1)],
1014
- make_meta({ stream }),
1015
- before.length
1016
+ [{ stream, msgs: [inc(1)], expectedVersion: before.length }],
1017
+ make_meta({ stream })
1016
1018
  )
1017
1019
  ).rejects.toThrow();
1018
1020
  const after = await collect(store, { stream, stream_exact: true });
@@ -1039,8 +1041,7 @@ var runStorePropertyTck = (options) => {
1039
1041
  for (const op of ops) {
1040
1042
  if (op.kind === "commit") {
1041
1043
  await store.commit(
1042
- op.stream,
1043
- [inc(1)],
1044
+ [{ stream: op.stream, msgs: [inc(1)] }],
1044
1045
  make_meta({ stream: op.stream })
1045
1046
  );
1046
1047
  } else if (op.kind === "claim") {
@@ -1082,8 +1083,7 @@ var runStorePropertyTck = (options) => {
1082
1083
  await store.subscribe(all.map((stream) => ({ stream })));
1083
1084
  for (const stream of commitsA) {
1084
1085
  await store.commit(
1085
- stream,
1086
- [inc(1)],
1086
+ [{ stream, msgs: [inc(1)] }],
1087
1087
  make_meta({ stream })
1088
1088
  );
1089
1089
  }
@@ -1095,8 +1095,7 @@ var runStorePropertyTck = (options) => {
1095
1095
  for (const l of acked1) watermark1.set(l.stream, l.at);
1096
1096
  for (const stream of commitsB) {
1097
1097
  await store.commit(
1098
- stream,
1099
- [inc(1)],
1098
+ [{ stream, msgs: [inc(1)] }],
1100
1099
  make_meta({ stream })
1101
1100
  );
1102
1101
  }
@@ -1122,8 +1121,7 @@ var runStorePropertyTck = (options) => {
1122
1121
  await store.subscribe(streams.map((stream) => ({ stream })));
1123
1122
  for (const stream of commits) {
1124
1123
  await store.commit(
1125
- stream,
1126
- [inc(1)],
1124
+ [{ stream, msgs: [inc(1)] }],
1127
1125
  make_meta({ stream })
1128
1126
  );
1129
1127
  }
@@ -1133,8 +1131,7 @@ var runStorePropertyTck = (options) => {
1133
1131
  const blockedSet = new Set(claimed.map((l) => l.stream));
1134
1132
  await store.subscribe([{ stream: "ctrl" }]);
1135
1133
  await store.commit(
1136
- "ctrl",
1137
- [inc(1)],
1134
+ [{ stream: "ctrl", msgs: [inc(1)] }],
1138
1135
  make_meta({ stream: "ctrl" })
1139
1136
  );
1140
1137
  await mark_all(store);
@@ -1213,14 +1210,12 @@ var runStoreTck = (options) => {
1213
1210
  await zero_config.seed();
1214
1211
  const s = `default-config-${uid()}`;
1215
1212
  const first = await zero_config.commit(
1216
- s,
1217
- [inc(1)],
1213
+ [{ stream: s, msgs: [inc(1)] }],
1218
1214
  make_meta({ stream: s })
1219
1215
  );
1220
1216
  (0, import_vitest9.expect)(first[0].version).toBe(0);
1221
1217
  const second = await zero_config.commit(
1222
- s,
1223
- [inc(2)],
1218
+ [{ stream: s, msgs: [inc(2)] }],
1224
1219
  make_meta({ stream: s })
1225
1220
  );
1226
1221
  (0, import_vitest9.expect)(second[0].version).toBe(1);
@@ -1236,12 +1231,371 @@ var runStoreTck = (options) => {
1236
1231
  });
1237
1232
  });
1238
1233
  }
1234
+ (0, import_vitest9.describe)("commit across streams", () => {
1235
+ const meta = make_meta({ stream: "across" });
1236
+ const count = (stream) => store.query(() => {
1237
+ }, { stream, stream_exact: true });
1238
+ (0, import_vitest9.it)("lands every append, each from its own head, with ids in append order", async () => {
1239
+ const a = `across-a-${uid()}`;
1240
+ const b = `across-b-${uid()}`;
1241
+ await store.commit(
1242
+ [{ stream: a, msgs: [inc(1)] }],
1243
+ meta
1244
+ );
1245
+ const committed = await store.commit(
1246
+ [
1247
+ { stream: a, msgs: [inc(2), inc(3)], expectedVersion: 0 },
1248
+ { stream: b, msgs: [dec(4)], expectedVersion: -1 }
1249
+ ],
1250
+ meta
1251
+ );
1252
+ (0, import_vitest9.expect)(committed.map((e) => [e.stream, e.version])).toEqual([
1253
+ [a, 1],
1254
+ [a, 2],
1255
+ [b, 0]
1256
+ ]);
1257
+ for (let i = 1; i < committed.length; i++)
1258
+ (0, import_vitest9.expect)(committed[i].id).toBeGreaterThan(committed[i - 1].id);
1259
+ const read = [];
1260
+ await store.query((e) => read.push(e.id), {
1261
+ after: committed[0].id - 1
1262
+ });
1263
+ (0, import_vitest9.expect)(read.filter((id) => committed.some((e) => e.id === id))).toEqual(
1264
+ committed.map((e) => e.id)
1265
+ );
1266
+ });
1267
+ (0, import_vitest9.it)("stores nothing when the first, a middle or the last append is stale, and names its stream", async () => {
1268
+ for (const at of [0, 1, 2]) {
1269
+ const streams = [0, 1, 2].map((i) => `across-stale-${i}-${uid()}`);
1270
+ for (const stream of streams)
1271
+ await store.commit(
1272
+ [{ stream, msgs: [inc(1)] }],
1273
+ meta
1274
+ );
1275
+ const refused = store.commit(
1276
+ streams.map((stream, i) => ({
1277
+ stream,
1278
+ msgs: [inc(2)],
1279
+ expectedVersion: i === at ? 5 : 0
1280
+ })),
1281
+ meta
1282
+ );
1283
+ await (0, import_vitest9.expect)(refused).rejects.toBeInstanceOf(import_act2.ConcurrencyError);
1284
+ await (0, import_vitest9.expect)(refused).rejects.toMatchObject({ stream: streams[at] });
1285
+ for (const stream of streams) (0, import_vitest9.expect)(await count(stream)).toBe(1);
1286
+ }
1287
+ });
1288
+ (0, import_vitest9.it)("refuses a stream named twice and an append with no events, storing nothing", async () => {
1289
+ const a = `across-twice-${uid()}`;
1290
+ const b = `across-empty-${uid()}`;
1291
+ await (0, import_vitest9.expect)(
1292
+ store.commit(
1293
+ [
1294
+ { stream: a, msgs: [inc(1)] },
1295
+ { stream: a, msgs: [inc(2)] }
1296
+ ],
1297
+ meta
1298
+ )
1299
+ ).rejects.toThrow(`stream "${a}" is named twice`);
1300
+ await (0, import_vitest9.expect)(
1301
+ store.commit(
1302
+ [
1303
+ { stream: a, msgs: [inc(1)] },
1304
+ { stream: b, msgs: [] }
1305
+ ],
1306
+ meta
1307
+ )
1308
+ ).rejects.toThrow(`the append to "${b}" has no events`);
1309
+ (0, import_vitest9.expect)(await count(a)).toBe(0);
1310
+ (0, import_vitest9.expect)(await count(b)).toBe(0);
1311
+ });
1312
+ (0, import_vitest9.it)("commits nothing for no appends", async () => {
1313
+ (0, import_vitest9.expect)(await store.commit([], meta)).toEqual([]);
1314
+ });
1315
+ (0, import_vitest9.it)("lands an unguarded append beside guarded ones", async () => {
1316
+ const a = `across-guarded-${uid()}`;
1317
+ const b = `across-free-${uid()}`;
1318
+ await store.commit(
1319
+ [{ stream: b, msgs: [inc(1)] }],
1320
+ meta
1321
+ );
1322
+ const committed = await store.commit(
1323
+ [
1324
+ { stream: a, msgs: [inc(1)], expectedVersion: -1 },
1325
+ { stream: b, msgs: [inc(2)] }
1326
+ ],
1327
+ meta
1328
+ );
1329
+ (0, import_vitest9.expect)(committed.map((e) => [e.stream, e.version])).toEqual([
1330
+ [a, 0],
1331
+ [b, 1]
1332
+ ]);
1333
+ });
1334
+ (0, import_vitest9.it)("stores every event of every append, whole", async () => {
1335
+ const a = `across-whole-a-${uid()}`;
1336
+ const b = `across-whole-b-${uid()}`;
1337
+ const across = make_meta({ stream: a });
1338
+ const committed = await store.commit(
1339
+ [
1340
+ { stream: a, msgs: [inc(1)] },
1341
+ { stream: b, msgs: [inc(2), dec(3)] }
1342
+ ],
1343
+ across
1344
+ );
1345
+ const shape = (e) => [
1346
+ e.name,
1347
+ e.data,
1348
+ e.meta
1349
+ ];
1350
+ const expected = [
1351
+ ["Incremented", { amount: 2 }, across],
1352
+ ["Decremented", { amount: 3 }, across]
1353
+ ];
1354
+ (0, import_vitest9.expect)(committed.filter((e) => e.stream === b).map(shape)).toEqual(
1355
+ expected
1356
+ );
1357
+ const stored = [];
1358
+ await store.query((e) => stored.push(e), {
1359
+ stream: b,
1360
+ stream_exact: true
1361
+ });
1362
+ (0, import_vitest9.expect)(stored.map(shape)).toEqual(expected);
1363
+ });
1364
+ import_vitest9.it.skipIf(!caps.pii_isolation)(
1365
+ "keeps the sensitive fields of a later append",
1366
+ async () => {
1367
+ const a = `across-pii-a-${uid()}`;
1368
+ const b = `across-pii-b-${uid()}`;
1369
+ await store.commit(
1370
+ [
1371
+ { stream: a, msgs: [inc(1)] },
1372
+ { stream: b, msgs: [{ ...inc(2), pii: { email: "e" } }] }
1373
+ ],
1374
+ make_meta({ stream: a })
1375
+ );
1376
+ const stored = [];
1377
+ await store.query((e) => stored.push(e.pii), {
1378
+ stream: b,
1379
+ stream_exact: true
1380
+ });
1381
+ (0, import_vitest9.expect)(stored).toEqual([{ email: "e" }]);
1382
+ }
1383
+ );
1384
+ (0, import_vitest9.it)("leaves nothing of the commit that lost a race, on any of its streams", async () => {
1385
+ const shared = `across-all-shared-${uid()}`;
1386
+ const [x, y] = [`across-all-x-${uid()}`, `across-all-y-${uid()}`];
1387
+ const race = (own) => store.commit(
1388
+ [
1389
+ { stream: own, msgs: [inc(1)], expectedVersion: -1 },
1390
+ { stream: shared, msgs: [inc(1)], expectedVersion: -1 }
1391
+ ],
1392
+ meta
1393
+ );
1394
+ const rs = await Promise.allSettled([race(x), race(y)]);
1395
+ (0, import_vitest9.expect)(rs.filter((r) => r.status === "fulfilled")).toHaveLength(1);
1396
+ (0, import_vitest9.expect)(await count(x) + await count(y)).toBe(1);
1397
+ });
1398
+ (0, import_vitest9.it)("lets one of two racing commits on a shared stream win, and both on disjoint streams", async () => {
1399
+ const shared = `across-shared-${uid()}`;
1400
+ const [x, y] = [`across-x-${uid()}`, `across-y-${uid()}`];
1401
+ const race = (own, other) => store.commit(
1402
+ [
1403
+ { stream: own, msgs: [inc(1)], expectedVersion: -1 },
1404
+ { stream: other, msgs: [inc(1)], expectedVersion: -1 }
1405
+ ],
1406
+ meta
1407
+ );
1408
+ const shared_race = await Promise.allSettled([
1409
+ race(x, shared),
1410
+ race(y, shared)
1411
+ ]);
1412
+ (0, import_vitest9.expect)(
1413
+ shared_race.filter((r2) => r2.status === "fulfilled")
1414
+ ).toHaveLength(1);
1415
+ const lost = shared_race.find((r2) => r2.status === "rejected");
1416
+ (0, import_vitest9.expect)(lost.reason).toBeInstanceOf(
1417
+ import_act2.ConcurrencyError
1418
+ );
1419
+ (0, import_vitest9.expect)(await count(shared)).toBe(1);
1420
+ const [p, q, r, t] = [0, 1, 2, 3].map((i) => `across-d${i}-${uid()}`);
1421
+ const disjoint = await Promise.allSettled([race(p, q), race(r, t)]);
1422
+ (0, import_vitest9.expect)(disjoint.every((d) => d.status === "fulfilled")).toBe(true);
1423
+ });
1424
+ });
1425
+ (0, import_vitest9.describe)("what a commit, guard or truncate must not get wrong", () => {
1426
+ const edge_uid = () => uid();
1427
+ const E = (data = { a: 1 }, pii) => ({
1428
+ name: "E",
1429
+ data,
1430
+ ...pii ? { pii } : {}
1431
+ });
1432
+ const edge_meta = (correlation = "m") => ({ correlation, causation: {} });
1433
+ const rows = async (query) => {
1434
+ const found = [];
1435
+ await store.query((e) => found.push(e), query);
1436
+ return found;
1437
+ };
1438
+ const one = (stream) => ({ stream, stream_exact: true });
1439
+ (0, import_vitest9.it)("names the FIRST stale stream when two are stale", async () => {
1440
+ const [a, b] = [`a-${edge_uid()}`, `b-${edge_uid()}`];
1441
+ const e = await store.commit(
1442
+ [
1443
+ { stream: a, msgs: [E()], expectedVersion: 3 },
1444
+ { stream: b, msgs: [E()], expectedVersion: 4 }
1445
+ ],
1446
+ edge_meta()
1447
+ ).catch((x) => x);
1448
+ (0, import_vitest9.expect)(e).toBeInstanceOf(import_act2.ConcurrencyError);
1449
+ (0, import_vitest9.expect)(e.stream).toBe(a);
1450
+ });
1451
+ (0, import_vitest9.it)("checks a stale expectedVersion of 0 inside a multi-stream commit", async () => {
1452
+ const [a, b] = [`a-${edge_uid()}`, `b-${edge_uid()}`];
1453
+ await store.commit(
1454
+ [{ stream: b, msgs: [E(), E()] }],
1455
+ edge_meta()
1456
+ );
1457
+ await (0, import_vitest9.expect)(
1458
+ store.commit(
1459
+ [
1460
+ { stream: a, msgs: [E()], expectedVersion: -1 },
1461
+ { stream: b, msgs: [E()], expectedVersion: 0 }
1462
+ ],
1463
+ edge_meta()
1464
+ )
1465
+ ).rejects.toBeInstanceOf(import_act2.ConcurrencyError);
1466
+ (0, import_vitest9.expect)(await rows(one(a))).toHaveLength(0);
1467
+ });
1468
+ (0, import_vitest9.it)("attaches meta to every append, not just the last", async () => {
1469
+ const ss = [0, 1, 2].map((i) => `m${i}-${edge_uid()}`);
1470
+ const c = `corr-${edge_uid()}`;
1471
+ await store.commit(
1472
+ ss.map((stream) => ({ stream, msgs: [E()] })),
1473
+ edge_meta(c)
1474
+ );
1475
+ for (const stream of ss)
1476
+ (0, import_vitest9.expect)((await rows(one(stream)))[0].meta.correlation).toBe(c);
1477
+ });
1478
+ (0, import_vitest9.it)("refuses a stream named twice when not adjacent", async () => {
1479
+ const [a, b] = [`a-${edge_uid()}`, `b-${edge_uid()}`];
1480
+ await (0, import_vitest9.expect)(
1481
+ store.commit(
1482
+ [
1483
+ { stream: a, msgs: [E()] },
1484
+ { stream: b, msgs: [E()] },
1485
+ { stream: a, msgs: [E()] }
1486
+ ],
1487
+ edge_meta()
1488
+ )
1489
+ ).rejects.toThrow("named twice");
1490
+ (0, import_vitest9.expect)(await rows(one(a))).toHaveLength(0);
1491
+ });
1492
+ (0, import_vitest9.it)("refuses a lone empty append (a version check alone)", async () => {
1493
+ const a = `a-${edge_uid()}`;
1494
+ await (0, import_vitest9.expect)(
1495
+ store.commit(
1496
+ [{ stream: a, msgs: [], expectedVersion: -1 }],
1497
+ edge_meta()
1498
+ )
1499
+ ).rejects.toThrow("no events");
1500
+ });
1501
+ (0, import_vitest9.it)("refuses an empty FIRST append", async () => {
1502
+ const [a, b] = [`a-${edge_uid()}`, `b-${edge_uid()}`];
1503
+ await (0, import_vitest9.expect)(
1504
+ store.commit(
1505
+ [
1506
+ { stream: a, msgs: [] },
1507
+ { stream: b, msgs: [E()] }
1508
+ ],
1509
+ edge_meta()
1510
+ )
1511
+ ).rejects.toThrow("no events");
1512
+ (0, import_vitest9.expect)(await rows(one(b))).toHaveLength(0);
1513
+ });
1514
+ (0, import_vitest9.it)("keeps the sensitive fields of the FIRST append", async () => {
1515
+ const [a, b] = [`a-${edge_uid()}`, `b-${edge_uid()}`];
1516
+ await store.commit(
1517
+ [
1518
+ { stream: a, msgs: [E({}, { email: "x" })] },
1519
+ { stream: b, msgs: [E()] }
1520
+ ],
1521
+ edge_meta()
1522
+ );
1523
+ (0, import_vitest9.expect)((await rows(one(a)))[0].pii).toEqual({ email: "x" });
1524
+ });
1525
+ (0, import_vitest9.it)("a guard below a trailing snapshot is stale", async () => {
1526
+ const a = `a-${edge_uid()}`;
1527
+ await store.commit([{ stream: a, msgs: [E()] }], edge_meta());
1528
+ await store.commit(
1529
+ [
1530
+ {
1531
+ stream: a,
1532
+ msgs: [{ name: import_act2.SNAP_EVENT, data: {} }],
1533
+ expectedVersion: 0
1534
+ }
1535
+ ],
1536
+ edge_meta()
1537
+ );
1538
+ await (0, import_vitest9.expect)(
1539
+ store.commit(
1540
+ [{ stream: a, msgs: [E()], expectedVersion: 0 }],
1541
+ edge_meta()
1542
+ )
1543
+ ).rejects.toBeInstanceOf(import_act2.ConcurrencyError);
1544
+ });
1545
+ (0, import_vitest9.it)("a guard below a trailing tombstone is stale (what stops a writer during a close)", async () => {
1546
+ const a = `a-${edge_uid()}`;
1547
+ await store.commit([{ stream: a, msgs: [E()] }], edge_meta());
1548
+ await store.commit(
1549
+ [
1550
+ {
1551
+ stream: a,
1552
+ msgs: [{ name: "__tombstone__", data: {} }],
1553
+ expectedVersion: 0
1554
+ }
1555
+ ],
1556
+ edge_meta()
1557
+ );
1558
+ await (0, import_vitest9.expect)(
1559
+ store.commit(
1560
+ [{ stream: a, msgs: [E()], expectedVersion: 0 }],
1561
+ edge_meta()
1562
+ )
1563
+ ).rejects.toBeInstanceOf(import_act2.ConcurrencyError);
1564
+ });
1565
+ (0, import_vitest9.it)("a commit after a full truncate continues from the seed at version 0", async () => {
1566
+ const a = `a-${edge_uid()}`;
1567
+ await store.commit(
1568
+ [{ stream: a, msgs: [E(), E(), E()] }],
1569
+ edge_meta()
1570
+ );
1571
+ await store.truncate([{ stream: a, snapshot: { n: 3 } }]);
1572
+ const [c] = await store.commit(
1573
+ [{ stream: a, msgs: [E()], expectedVersion: 0 }],
1574
+ edge_meta()
1575
+ );
1576
+ (0, import_vitest9.expect)(c.version).toBe(1);
1577
+ });
1578
+ (0, import_vitest9.it)("seeds a full truncate at version 0, carrying the meta it was given", async () => {
1579
+ const a = `a-${edge_uid()}`;
1580
+ await store.commit(
1581
+ [{ stream: a, msgs: [E(), E(), E()] }],
1582
+ edge_meta()
1583
+ );
1584
+ const c = `close-${edge_uid()}`;
1585
+ const r = await store.truncate([
1586
+ { stream: a, snapshot: { n: 3 }, meta: edge_meta(c) }
1587
+ ]);
1588
+ (0, import_vitest9.expect)(r.get(a).committed.version).toBe(0);
1589
+ const [seed] = await rows({ ...one(a), with_snaps: true });
1590
+ (0, import_vitest9.expect)(seed.version).toBe(0);
1591
+ (0, import_vitest9.expect)(seed.meta.correlation).toBe(c);
1592
+ });
1593
+ });
1239
1594
  (0, import_vitest9.describe)("commit", () => {
1240
1595
  (0, import_vitest9.it)("returns committed events with sequenced ids and versions", async () => {
1241
1596
  const s = `commit-seq-${uid()}`;
1242
1597
  const committed = await store.commit(
1243
- s,
1244
- [inc(1), inc(2), dec(3)],
1598
+ [{ stream: s, msgs: [inc(1), inc(2), dec(3)] }],
1245
1599
  make_meta({ stream: s })
1246
1600
  );
1247
1601
  (0, import_vitest9.expect)(committed).toHaveLength(3);
@@ -1258,8 +1612,7 @@ var runStoreTck = (options) => {
1258
1612
  const s = `commit-meta-${uid()}`;
1259
1613
  const correlation = `cor-${uid()}`;
1260
1614
  const committed = await store.commit(
1261
- s,
1262
- [inc(1)],
1615
+ [{ stream: s, msgs: [inc(1)] }],
1263
1616
  make_meta({ stream: s, correlation })
1264
1617
  );
1265
1618
  (0, import_vitest9.expect)(committed[0].stream).toBe(s);
@@ -1268,64 +1621,50 @@ var runStoreTck = (options) => {
1268
1621
  (0, import_vitest9.it)("throws ConcurrencyError when expectedVersion is wrong", async () => {
1269
1622
  const s = `commit-cc-${uid()}`;
1270
1623
  await store.commit(
1271
- s,
1272
- [inc(1)],
1624
+ [{ stream: s, msgs: [inc(1)] }],
1273
1625
  make_meta({ stream: s })
1274
1626
  );
1275
1627
  await store.commit(
1276
- s,
1277
- [inc(1)],
1278
- make_meta({ stream: s }),
1279
- 0
1628
+ [{ stream: s, msgs: [inc(1)], expectedVersion: 0 }],
1629
+ make_meta({ stream: s })
1280
1630
  );
1281
1631
  await (0, import_vitest9.expect)(
1282
- store.commit(s, [inc(1)], make_meta({ stream: s }), 0)
1632
+ store.commit(
1633
+ [{ stream: s, msgs: [inc(1)], expectedVersion: 0 }],
1634
+ make_meta({ stream: s })
1635
+ )
1283
1636
  ).rejects.toBeInstanceOf(import_act2.ConcurrencyError);
1284
1637
  });
1285
1638
  (0, import_vitest9.it)("treats expectedVersion -1 as an empty stream", async () => {
1286
1639
  const s = `commit-new-cc-${uid()}`;
1287
1640
  const [first] = await store.commit(
1288
- s,
1289
- [inc(1)],
1290
- make_meta({ stream: s }),
1291
- -1
1292
- );
1293
- (0, import_vitest9.expect)(first.version).toBe(0);
1294
- await (0, import_vitest9.expect)(
1295
- store.commit(s, [inc(1)], make_meta({ stream: s }), -1)
1296
- ).rejects.toBeInstanceOf(import_act2.ConcurrencyError);
1297
- });
1298
- (0, import_vitest9.it)("checks expectedVersion even when committing no events", async () => {
1299
- const s = `commit-empty-cc-${uid()}`;
1300
- await store.commit(
1301
- s,
1302
- [inc(1)],
1641
+ [{ stream: s, msgs: [inc(1)], expectedVersion: -1 }],
1303
1642
  make_meta({ stream: s })
1304
1643
  );
1644
+ (0, import_vitest9.expect)(first.version).toBe(0);
1305
1645
  await (0, import_vitest9.expect)(
1306
- store.commit(s, [], make_meta({ stream: s }), 5)
1646
+ store.commit(
1647
+ [{ stream: s, msgs: [inc(1)], expectedVersion: -1 }],
1648
+ make_meta({ stream: s })
1649
+ )
1307
1650
  ).rejects.toBeInstanceOf(import_act2.ConcurrencyError);
1308
- (0, import_vitest9.expect)(
1309
- await store.commit(s, [], make_meta({ stream: s }), 0)
1310
- ).toEqual([]);
1311
1651
  });
1312
1652
  (0, import_vitest9.it)("takes concurrent commits, reads and writes on one instance", async () => {
1313
1653
  const x = `commit-concurrent-x-${uid()}`;
1314
1654
  const y = `commit-concurrent-y-${uid()}`;
1315
1655
  const [first, second, other, read, subscribed] = await Promise.allSettled([
1316
1656
  store.commit(
1317
- x,
1318
- [inc(1)],
1319
- make_meta({ stream: x }),
1320
- -1
1657
+ [{ stream: x, msgs: [inc(1)], expectedVersion: -1 }],
1658
+ make_meta({ stream: x })
1321
1659
  ),
1322
1660
  store.commit(
1323
- x,
1324
- [inc(2)],
1325
- make_meta({ stream: x }),
1326
- -1
1661
+ [{ stream: x, msgs: [inc(2)], expectedVersion: -1 }],
1662
+ make_meta({ stream: x })
1663
+ ),
1664
+ store.commit(
1665
+ [{ stream: y, msgs: [inc(1)] }],
1666
+ make_meta({ stream: y })
1327
1667
  ),
1328
- store.commit(y, [inc(1)], make_meta({ stream: y })),
1329
1668
  store.query(() => {
1330
1669
  }, { stream: x, stream_exact: true }),
1331
1670
  // A source nothing writes, so later claims never see it.
@@ -1347,12 +1686,14 @@ var runStoreTck = (options) => {
1347
1686
  (0, import_vitest9.it)("preserves prior events when a concurrent commit is rejected", async () => {
1348
1687
  const s = `commit-cc-preserve-${uid()}`;
1349
1688
  await store.commit(
1350
- s,
1351
- [inc(1), inc(2)],
1689
+ [{ stream: s, msgs: [inc(1), inc(2)] }],
1352
1690
  make_meta({ stream: s })
1353
1691
  );
1354
1692
  await (0, import_vitest9.expect)(
1355
- store.commit(s, [inc(3)], make_meta({ stream: s }), 0)
1693
+ store.commit(
1694
+ [{ stream: s, msgs: [inc(3)], expectedVersion: 0 }],
1695
+ make_meta({ stream: s })
1696
+ )
1356
1697
  ).rejects.toBeInstanceOf(import_act2.ConcurrencyError);
1357
1698
  const found = await collect(store, { stream: s, stream_exact: true });
1358
1699
  (0, import_vitest9.expect)(found).toHaveLength(2);
@@ -1364,13 +1705,11 @@ var runStoreTck = (options) => {
1364
1705
  const s2 = `q-s2-${uid()}`;
1365
1706
  const cor = `q-cor-${uid()}`;
1366
1707
  await store.commit(
1367
- s1,
1368
- [inc(1), dec(1)],
1708
+ [{ stream: s1, msgs: [inc(1), dec(1)] }],
1369
1709
  make_meta({ stream: s1, correlation: cor })
1370
1710
  );
1371
1711
  await store.commit(
1372
- s2,
1373
- [inc(2), dec(2), reset()],
1712
+ [{ stream: s2, msgs: [inc(2), dec(2), reset()] }],
1374
1713
  make_meta({ stream: s2, correlation: cor })
1375
1714
  );
1376
1715
  const by_stream = await collect(store, {
@@ -1396,8 +1735,7 @@ var runStoreTck = (options) => {
1396
1735
  (0, import_vitest9.it)("excludes snapshots when called with no query object", async () => {
1397
1736
  const s = `q-nofilter-${uid()}`;
1398
1737
  await store.commit(
1399
- s,
1400
- [{ name: import_act2.SNAP_EVENT, data: { count: 0 } }],
1738
+ [{ stream: s, msgs: [{ name: import_act2.SNAP_EVENT, data: { count: 0 } }] }],
1401
1739
  make_meta({ stream: s })
1402
1740
  );
1403
1741
  const names = [];
@@ -1409,18 +1747,15 @@ var runStoreTck = (options) => {
1409
1747
  (0, import_vitest9.it)("with_snaps resumes from the latest snapshot per stream", async () => {
1410
1748
  const s = `q-snap-${uid()}`;
1411
1749
  await store.commit(
1412
- s,
1413
- [inc(1), inc(1)],
1750
+ [{ stream: s, msgs: [inc(1), inc(1)] }],
1414
1751
  make_meta({ stream: s })
1415
1752
  );
1416
1753
  const [snap] = await store.commit(
1417
- s,
1418
- [{ name: import_act2.SNAP_EVENT, data: { count: 2 } }],
1754
+ [{ stream: s, msgs: [{ name: import_act2.SNAP_EVENT, data: { count: 2 } }] }],
1419
1755
  make_meta({ stream: s })
1420
1756
  );
1421
1757
  await store.commit(
1422
- s,
1423
- [inc(1), inc(1), inc(1)],
1758
+ [{ stream: s, msgs: [inc(1), inc(1), inc(1)] }],
1424
1759
  make_meta({ stream: s })
1425
1760
  );
1426
1761
  const from_snap = await collect(store, {
@@ -1441,8 +1776,7 @@ var runStoreTck = (options) => {
1441
1776
  (0, import_vitest9.expect)(after_snap).toHaveLength(3);
1442
1777
  const s2 = `q-nosnap-${uid()}`;
1443
1778
  await store.commit(
1444
- s2,
1445
- [inc(1), inc(1)],
1779
+ [{ stream: s2, msgs: [inc(1), inc(1)] }],
1446
1780
  make_meta({ stream: s2 })
1447
1781
  );
1448
1782
  const full = await collect(store, {
@@ -1455,18 +1789,15 @@ var runStoreTck = (options) => {
1455
1789
  (0, import_vitest9.it)("with_snaps applies the resume floor on a backward scan too", async () => {
1456
1790
  const s = `q-snap-back-${uid()}`;
1457
1791
  await store.commit(
1458
- s,
1459
- [inc(1), inc(1)],
1792
+ [{ stream: s, msgs: [inc(1), inc(1)] }],
1460
1793
  make_meta({ stream: s })
1461
1794
  );
1462
1795
  const [snap] = await store.commit(
1463
- s,
1464
- [{ name: import_act2.SNAP_EVENT, data: { count: 2 } }],
1796
+ [{ stream: s, msgs: [{ name: import_act2.SNAP_EVENT, data: { count: 2 } }] }],
1465
1797
  make_meta({ stream: s })
1466
1798
  );
1467
1799
  await store.commit(
1468
- s,
1469
- [inc(1), inc(1), inc(1)],
1800
+ [{ stream: s, msgs: [inc(1), inc(1), inc(1)] }],
1470
1801
  make_meta({ stream: s })
1471
1802
  );
1472
1803
  const backward = await collect(store, {
@@ -1480,8 +1811,7 @@ var runStoreTck = (options) => {
1480
1811
  (0, import_vitest9.expect)(backward.every((e) => e.id >= snap.id)).toBe(true);
1481
1812
  const s2 = `q-nosnap-back-${uid()}`;
1482
1813
  await store.commit(
1483
- s2,
1484
- [inc(1), inc(1)],
1814
+ [{ stream: s2, msgs: [inc(1), inc(1)] }],
1485
1815
  make_meta({ stream: s2 })
1486
1816
  );
1487
1817
  const full = await collect(store, {
@@ -1495,8 +1825,7 @@ var runStoreTck = (options) => {
1495
1825
  (0, import_vitest9.it)("supports backward traversal", async () => {
1496
1826
  const s = `q-back-${uid()}`;
1497
1827
  const committed = await store.commit(
1498
- s,
1499
- [inc(1), inc(2), inc(3)],
1828
+ [{ stream: s, msgs: [inc(1), inc(2), inc(3)] }],
1500
1829
  make_meta({ stream: s })
1501
1830
  );
1502
1831
  const forward = await collect(store, { stream: s, stream_exact: true });
@@ -1521,8 +1850,7 @@ var runStoreTck = (options) => {
1521
1850
  (0, import_vitest9.it)("after/before bound the id range", async () => {
1522
1851
  const s = `q-bounds-${uid()}`;
1523
1852
  const committed = await store.commit(
1524
- s,
1525
- [inc(1), inc(2), inc(3), inc(4)],
1853
+ [{ stream: s, msgs: [inc(1), inc(2), inc(3), inc(4)] }],
1526
1854
  make_meta({ stream: s })
1527
1855
  );
1528
1856
  const after_first = await collect(store, {
@@ -1545,8 +1873,7 @@ var runStoreTck = (options) => {
1545
1873
  (0, import_vitest9.it)("names:[] matches no events", async () => {
1546
1874
  const s = `q-names-empty-${uid()}`;
1547
1875
  await store.commit(
1548
- s,
1549
- [inc(1), dec(1)],
1876
+ [{ stream: s, msgs: [inc(1), dec(1)] }],
1550
1877
  make_meta({ stream: s })
1551
1878
  );
1552
1879
  const none = await collect(store, {
@@ -1561,8 +1888,7 @@ var runStoreTck = (options) => {
1561
1888
  (0, import_vitest9.it)("after:0 and before:0 are honored as id bounds", async () => {
1562
1889
  const s = `q-zero-bound-${uid()}`;
1563
1890
  await store.commit(
1564
- s,
1565
- [inc(1), inc(2), inc(3)],
1891
+ [{ stream: s, msgs: [inc(1), inc(2), inc(3)] }],
1566
1892
  make_meta({ stream: s })
1567
1893
  );
1568
1894
  (0, import_vitest9.expect)(
@@ -1593,8 +1919,7 @@ var runStoreTck = (options) => {
1593
1919
  (0, import_vitest9.it)("created_after/created_before filter by timestamp", async () => {
1594
1920
  const s = `q-ts-${uid()}`;
1595
1921
  const committed = await store.commit(
1596
- s,
1597
- [inc(1)],
1922
+ [{ stream: s, msgs: [inc(1)] }],
1598
1923
  make_meta({ stream: s })
1599
1924
  );
1600
1925
  const ts = committed[0].created.getTime();
@@ -1617,8 +1942,7 @@ var runStoreTck = (options) => {
1617
1942
  (0, import_vitest9.it)("created bounds exclude the event they are pinned to", async () => {
1618
1943
  const s = `q-ts-self-${uid()}`;
1619
1944
  const committed = await store.commit(
1620
- s,
1621
- [inc(1)],
1945
+ [{ stream: s, msgs: [inc(1)] }],
1622
1946
  make_meta({ stream: s })
1623
1947
  );
1624
1948
  const own = committed[0].created;
@@ -1638,8 +1962,7 @@ var runStoreTck = (options) => {
1638
1962
  (0, import_vitest9.it)("backward traversal short-circuits at `after` id boundary", async () => {
1639
1963
  const s = `q-back-after-${uid()}`;
1640
1964
  const committed = await store.commit(
1641
- s,
1642
- [inc(1), inc(2), inc(3)],
1965
+ [{ stream: s, msgs: [inc(1), inc(2), inc(3)] }],
1643
1966
  make_meta({ stream: s })
1644
1967
  );
1645
1968
  const got = await collect(store, {
@@ -1656,8 +1979,7 @@ var runStoreTck = (options) => {
1656
1979
  (0, import_vitest9.it)("backward traversal short-circuits at `created_after` boundary", async () => {
1657
1980
  const s = `q-back-cafter-${uid()}`;
1658
1981
  await store.commit(
1659
- s,
1660
- [inc(1)],
1982
+ [{ stream: s, msgs: [inc(1)] }],
1661
1983
  make_meta({ stream: s })
1662
1984
  );
1663
1985
  const future = new Date(Date.now() + 6e4);
@@ -1672,8 +1994,7 @@ var runStoreTck = (options) => {
1672
1994
  (0, import_vitest9.it)("backward traversal honors created_before by skipping newer events", async () => {
1673
1995
  const s = `q-back-ts-${uid()}`;
1674
1996
  const committed = await store.commit(
1675
- s,
1676
- [inc(1)],
1997
+ [{ stream: s, msgs: [inc(1)] }],
1677
1998
  make_meta()
1678
1999
  );
1679
2000
  const past = new Date(committed[0].created.getTime() - 6e4);
@@ -1690,13 +2011,11 @@ var runStoreTck = (options) => {
1690
2011
  const a = `q-exact-${tag}`;
1691
2012
  const b = `q-exact-${tag}-extra`;
1692
2013
  await store.commit(
1693
- a,
1694
- [inc(1)],
2014
+ [{ stream: a, msgs: [inc(1)] }],
1695
2015
  make_meta({ stream: a })
1696
2016
  );
1697
2017
  await store.commit(
1698
- b,
1699
- [inc(2)],
2018
+ [{ stream: b, msgs: [inc(2)] }],
1700
2019
  make_meta({ stream: b })
1701
2020
  );
1702
2021
  const exact = await collect(store, { stream: a, stream_exact: true });
@@ -1708,13 +2027,11 @@ var runStoreTck = (options) => {
1708
2027
  const inner = `qr-${tag}-inner`;
1709
2028
  const longer = `qr-${tag}-inner-extra`;
1710
2029
  await store.commit(
1711
- inner,
1712
- [inc(1)],
2030
+ [{ stream: inner, msgs: [inc(1)] }],
1713
2031
  make_meta({ stream: inner })
1714
2032
  );
1715
2033
  await store.commit(
1716
- longer,
1717
- [inc(2)],
2034
+ [{ stream: longer, msgs: [inc(2)] }],
1718
2035
  make_meta({ stream: longer })
1719
2036
  );
1720
2037
  const got = await collect(store, { stream: `qr-${tag}-inner` });
@@ -1725,13 +2042,11 @@ var runStoreTck = (options) => {
1725
2042
  const inner = `qr-${tag}-anchor`;
1726
2043
  const longer = `qr-${tag}-anchor-extra`;
1727
2044
  await store.commit(
1728
- inner,
1729
- [inc(1)],
2045
+ [{ stream: inner, msgs: [inc(1)] }],
1730
2046
  make_meta({ stream: inner })
1731
2047
  );
1732
2048
  await store.commit(
1733
- longer,
1734
- [inc(2)],
2049
+ [{ stream: longer, msgs: [inc(2)] }],
1735
2050
  make_meta({ stream: longer })
1736
2051
  );
1737
2052
  const got = await collect(store, { stream: `^qr-${tag}-anchor$` });
@@ -1744,18 +2059,15 @@ var runStoreTck = (options) => {
1744
2059
  const b = `qr-${tag}-pfx-b`;
1745
2060
  const other = `zz-${tag}-other`;
1746
2061
  await store.commit(
1747
- a,
1748
- [inc(1)],
2062
+ [{ stream: a, msgs: [inc(1)] }],
1749
2063
  make_meta({ stream: a })
1750
2064
  );
1751
2065
  await store.commit(
1752
- b,
1753
- [inc(2)],
2066
+ [{ stream: b, msgs: [inc(2)] }],
1754
2067
  make_meta({ stream: b })
1755
2068
  );
1756
2069
  await store.commit(
1757
- other,
1758
- [inc(3)],
2070
+ [{ stream: other, msgs: [inc(3)] }],
1759
2071
  make_meta({ stream: other })
1760
2072
  );
1761
2073
  const got = await collect(store, { stream: `^qr-${tag}-pfx-` });
@@ -1766,8 +2078,7 @@ var runStoreTck = (options) => {
1766
2078
  const seed_streams = async (streams) => {
1767
2079
  for (const s of streams)
1768
2080
  await store.commit(
1769
- s,
1770
- [inc(1)],
2081
+ [{ stream: s, msgs: [inc(1)] }],
1771
2082
  make_meta({ stream: s })
1772
2083
  );
1773
2084
  };
@@ -1946,8 +2257,7 @@ var runStoreTck = (options) => {
1946
2257
  const src = `fresh-first-src-${uid()}`;
1947
2258
  await store.subscribe([{ stream: s, source: src }]);
1948
2259
  const [first] = await store.commit(
1949
- src,
1950
- [inc(1)],
2260
+ [{ stream: src, msgs: [inc(1)] }],
1951
2261
  make_meta({ stream: src })
1952
2262
  );
1953
2263
  await store.subscribe([{ stream: s, correlated_at: first.id }]);
@@ -2136,8 +2446,7 @@ var runStoreTck = (options) => {
2136
2446
  const src = `ws-unmarked-src-${uid()}`;
2137
2447
  await store.subscribe([{ stream: s, source: src }]);
2138
2448
  const [event] = await store.commit(
2139
- src,
2140
- [inc(1)],
2449
+ [{ stream: src, msgs: [inc(1)] }],
2141
2450
  make_meta({ stream: src })
2142
2451
  );
2143
2452
  (0, import_vitest9.expect)(await claimable(s)).toBe(false);
@@ -2169,8 +2478,7 @@ var runStoreTck = (options) => {
2169
2478
  const s = `claim-${uid()}`;
2170
2479
  await store.subscribe([{ stream: s }]);
2171
2480
  await store.commit(
2172
- s,
2173
- [inc(1)],
2481
+ [{ stream: s, msgs: [inc(1)] }],
2174
2482
  make_meta({ stream: s })
2175
2483
  );
2176
2484
  const by = `worker-${uid()}`;
@@ -2193,8 +2501,7 @@ var runStoreTck = (options) => {
2193
2501
  const other = `claim-other-${uid()}`;
2194
2502
  await store.subscribe([{ stream: s }]);
2195
2503
  await store.commit(
2196
- s,
2197
- [inc(1)],
2504
+ [{ stream: s, msgs: [inc(1)] }],
2198
2505
  make_meta({ stream: s })
2199
2506
  );
2200
2507
  await correlate();
@@ -2203,8 +2510,7 @@ var runStoreTck = (options) => {
2203
2510
  (0, import_vitest9.expect)(targetA).toBeDefined();
2204
2511
  await store.subscribe([{ stream: other }]);
2205
2512
  await store.commit(
2206
- other,
2207
- [inc(2)],
2513
+ [{ stream: other, msgs: [inc(2)] }],
2208
2514
  make_meta({ stream: other })
2209
2515
  );
2210
2516
  await correlate();
@@ -2217,8 +2523,7 @@ var runStoreTck = (options) => {
2217
2523
  const s = `claim-stolen-${uid()}`;
2218
2524
  await store.subscribe([{ stream: s }]);
2219
2525
  await store.commit(
2220
- s,
2221
- [inc(1), inc(2)],
2526
+ [{ stream: s, msgs: [inc(1), inc(2)] }],
2222
2527
  make_meta({ stream: s })
2223
2528
  );
2224
2529
  await correlate();
@@ -2244,8 +2549,7 @@ var runStoreTck = (options) => {
2244
2549
  const s = `claim-dual-${uid()}`;
2245
2550
  await store.subscribe([{ stream: s }]);
2246
2551
  await store.commit(
2247
- s,
2248
- [inc(1), inc(2)],
2552
+ [{ stream: s, msgs: [inc(1), inc(2)] }],
2249
2553
  make_meta({ stream: s })
2250
2554
  );
2251
2555
  await correlate();
@@ -2274,13 +2578,11 @@ var runStoreTck = (options) => {
2274
2578
  ]);
2275
2579
  for (const stream of highs)
2276
2580
  await fresh.commit(
2277
- stream,
2278
- [inc(1)],
2581
+ [{ stream, msgs: [inc(1)] }],
2279
2582
  make_meta({ stream })
2280
2583
  );
2281
2584
  await fresh.commit(
2282
- low,
2283
- [inc(1)],
2585
+ [{ stream: low, msgs: [inc(1)] }],
2284
2586
  make_meta({ stream: low })
2285
2587
  );
2286
2588
  const by = `w-${uid()}`;
@@ -2296,8 +2598,7 @@ var runStoreTck = (options) => {
2296
2598
  for (const l of leases) {
2297
2599
  await fresh.ack([{ ...l, at: l.at + 1 }]);
2298
2600
  await fresh.commit(
2299
- l.stream,
2300
- [inc(1)],
2601
+ [{ stream: l.stream, msgs: [inc(1)] }],
2301
2602
  make_meta({ stream: l.stream })
2302
2603
  );
2303
2604
  }
@@ -2311,8 +2612,7 @@ var runStoreTck = (options) => {
2311
2612
  const s = `claim-dedup-${uid()}`;
2312
2613
  await store.subscribe([{ stream: s }]);
2313
2614
  await store.commit(
2314
- s,
2315
- [inc(1)],
2615
+ [{ stream: s, msgs: [inc(1)] }],
2316
2616
  make_meta({ stream: s })
2317
2617
  );
2318
2618
  await correlate();
@@ -2325,13 +2625,11 @@ var runStoreTck = (options) => {
2325
2625
  const sibling = `ack-sibling-${uid()}`;
2326
2626
  await store.subscribe([{ stream: s }, { stream: sibling }]);
2327
2627
  await store.commit(
2328
- s,
2329
- [inc(1)],
2628
+ [{ stream: s, msgs: [inc(1)] }],
2330
2629
  make_meta({ stream: s })
2331
2630
  );
2332
2631
  await store.commit(
2333
- sibling,
2334
- [inc(2)],
2632
+ [{ stream: sibling, msgs: [inc(2)] }],
2335
2633
  make_meta({ stream: sibling })
2336
2634
  );
2337
2635
  await correlate();
@@ -2381,8 +2679,7 @@ var runStoreTck = (options) => {
2381
2679
  const s = `lease-retry-${uid()}`;
2382
2680
  await fresh.subscribe([{ stream: s }]);
2383
2681
  await fresh.commit(
2384
- s,
2385
- [inc(1)],
2682
+ [{ stream: s, msgs: [inc(1)] }],
2386
2683
  make_meta({ stream: s })
2387
2684
  );
2388
2685
  await correlate(fresh);
@@ -2407,8 +2704,7 @@ var runStoreTck = (options) => {
2407
2704
  const s = `lease-zero-${uid()}`;
2408
2705
  await fresh.subscribe([{ stream: s }]);
2409
2706
  const [committed] = await fresh.commit(
2410
- s,
2411
- [inc(1)],
2707
+ [{ stream: s, msgs: [inc(1)] }],
2412
2708
  make_meta({ stream: s })
2413
2709
  );
2414
2710
  await correlate(fresh);
@@ -2437,8 +2733,7 @@ var runStoreTck = (options) => {
2437
2733
  const s = `lease-lag-${uid()}`;
2438
2734
  await fresh.subscribe([{ stream: s }]);
2439
2735
  await fresh.commit(
2440
- s,
2441
- [inc(1)],
2736
+ [{ stream: s, msgs: [inc(1)] }],
2442
2737
  make_meta({ stream: s })
2443
2738
  );
2444
2739
  await correlate(fresh);
@@ -2567,8 +2862,7 @@ var runStoreTck = (options) => {
2567
2862
  await fresh.subscribe(streams.map((stream) => ({ stream })));
2568
2863
  for (const stream of streams) {
2569
2864
  await fresh.commit(
2570
- stream,
2571
- [inc(1)],
2865
+ [{ stream, msgs: [inc(1)] }],
2572
2866
  make_meta({ stream })
2573
2867
  );
2574
2868
  }
@@ -2640,8 +2934,7 @@ var runStoreTck = (options) => {
2640
2934
  const s = `block-${uid()}`;
2641
2935
  await store.subscribe([{ stream: s }]);
2642
2936
  await store.commit(
2643
- s,
2644
- [inc(1)],
2937
+ [{ stream: s, msgs: [inc(1)] }],
2645
2938
  make_meta({ stream: s })
2646
2939
  );
2647
2940
  await correlate();
@@ -2663,8 +2956,7 @@ var runStoreTck = (options) => {
2663
2956
  const s = `block-returns-${uid()}`;
2664
2957
  await store.subscribe([{ stream: s }]);
2665
2958
  await store.commit(
2666
- s,
2667
- [inc(1)],
2959
+ [{ stream: s, msgs: [inc(1)] }],
2668
2960
  make_meta({ stream: s })
2669
2961
  );
2670
2962
  await correlate();
@@ -2689,8 +2981,7 @@ var runStoreTck = (options) => {
2689
2981
  const s = `block-wrong-${uid()}`;
2690
2982
  await store.subscribe([{ stream: s }]);
2691
2983
  await store.commit(
2692
- s,
2693
- [inc(1)],
2984
+ [{ stream: s, msgs: [inc(1)] }],
2694
2985
  make_meta({ stream: s })
2695
2986
  );
2696
2987
  await correlate();
@@ -2708,8 +2999,7 @@ var runStoreTck = (options) => {
2708
2999
  const s = `block-twice-${uid()}`;
2709
3000
  await store.subscribe([{ stream: s }]);
2710
3001
  await store.commit(
2711
- s,
2712
- [inc(1)],
3002
+ [{ stream: s, msgs: [inc(1)] }],
2713
3003
  make_meta({ stream: s })
2714
3004
  );
2715
3005
  await correlate();
@@ -2734,8 +3024,7 @@ var runStoreTck = (options) => {
2734
3024
  await store.subscribe([{ stream: s }, { stream: ctl }]);
2735
3025
  for (const st of [s, ctl])
2736
3026
  await store.commit(
2737
- st,
2738
- [inc(1)],
3027
+ [{ stream: st, msgs: [inc(1)] }],
2739
3028
  make_meta({ stream: st })
2740
3029
  );
2741
3030
  (0, import_vitest9.expect)(await store.defer([s], Date.now() + 36e5)).toBe(1);
@@ -2748,8 +3037,7 @@ var runStoreTck = (options) => {
2748
3037
  const s = `defer-clock-${uid()}`;
2749
3038
  await store.subscribe([{ stream: s }]);
2750
3039
  await store.commit(
2751
- s,
2752
- [inc(1)],
3040
+ [{ stream: s, msgs: [inc(1)] }],
2753
3041
  make_meta({ stream: s })
2754
3042
  );
2755
3043
  (0, import_vitest9.expect)(await store.defer([s], Date.now() + 6e4)).toBe(1);
@@ -2772,8 +3060,7 @@ var runStoreTck = (options) => {
2772
3060
  const s = `defer-past-${uid()}`;
2773
3061
  await store.subscribe([{ stream: s }]);
2774
3062
  await store.commit(
2775
- s,
2776
- [inc(1)],
3063
+ [{ stream: s, msgs: [inc(1)] }],
2777
3064
  make_meta({ stream: s })
2778
3065
  );
2779
3066
  (0, import_vitest9.expect)(await store.defer([s], Date.now() - 1e3)).toBe(1);
@@ -2789,8 +3076,7 @@ var runStoreTck = (options) => {
2789
3076
  const s = `defer-retry-${uid()}`;
2790
3077
  await store.subscribe([{ stream: s }]);
2791
3078
  await store.commit(
2792
- s,
2793
- [inc(1)],
3079
+ [{ stream: s, msgs: [inc(1)] }],
2794
3080
  make_meta({ stream: s })
2795
3081
  );
2796
3082
  await store.defer([s], Date.now() + 36e5);
@@ -2812,8 +3098,7 @@ var runStoreTck = (options) => {
2812
3098
  const s = `defer-reset-${uid()}`;
2813
3099
  await store.subscribe([{ stream: s }]);
2814
3100
  await store.commit(
2815
- s,
2816
- [inc(1)],
3101
+ [{ stream: s, msgs: [inc(1)] }],
2817
3102
  make_meta({ stream: s })
2818
3103
  );
2819
3104
  await store.defer([s], Date.now() + 36e5);
@@ -2828,8 +3113,7 @@ var runStoreTck = (options) => {
2828
3113
  await store.subscribe([{ stream: deferred }, { stream: plain }]);
2829
3114
  for (const s of [deferred, plain])
2830
3115
  await store.commit(
2831
- s,
2832
- [inc(1)],
3116
+ [{ stream: s, msgs: [inc(1)] }],
2833
3117
  make_meta({ stream: s })
2834
3118
  );
2835
3119
  const due = Date.now() + 36e5;
@@ -2851,15 +3135,13 @@ var runStoreTck = (options) => {
2851
3135
  await store.subscribe([{ stream: a }, { stream: b }]);
2852
3136
  for (const s of [a, b])
2853
3137
  await store.commit(
2854
- s,
2855
- [inc(1)],
3138
+ [{ stream: s, msgs: [inc(1)] }],
2856
3139
  make_meta({ stream: s })
2857
3140
  );
2858
3141
  const ctl = `defer-filterctl-${tag}`;
2859
3142
  await store.subscribe([{ stream: ctl }]);
2860
3143
  await store.commit(
2861
- ctl,
2862
- [inc(1)],
3144
+ [{ stream: ctl, msgs: [inc(1)] }],
2863
3145
  make_meta({ stream: ctl })
2864
3146
  );
2865
3147
  const n = await store.defer(
@@ -2881,8 +3163,7 @@ var runStoreTck = (options) => {
2881
3163
  const s = `defer-dup-${uid()}`;
2882
3164
  await store.subscribe([{ stream: s }]);
2883
3165
  await store.commit(
2884
- s,
2885
- [inc(1)],
3166
+ [{ stream: s, msgs: [inc(1)] }],
2886
3167
  make_meta({ stream: s })
2887
3168
  );
2888
3169
  (0, import_vitest9.expect)(await store.defer([s, s], Date.now() + 36e5)).toBe(1);
@@ -2894,13 +3175,11 @@ var runStoreTck = (options) => {
2894
3175
  const ctl = `ackdefer-ctl-${uid()}`;
2895
3176
  await store.subscribe([{ stream: s }, { stream: ctl }]);
2896
3177
  await store.commit(
2897
- s,
2898
- [inc(1)],
3178
+ [{ stream: s, msgs: [inc(1)] }],
2899
3179
  make_meta({ stream: s })
2900
3180
  );
2901
3181
  const [ctl_head] = await store.commit(
2902
- ctl,
2903
- [inc(1)],
3182
+ [{ stream: ctl, msgs: [inc(1)] }],
2904
3183
  make_meta({ stream: ctl })
2905
3184
  );
2906
3185
  await correlate();
@@ -2914,8 +3193,7 @@ var runStoreTck = (options) => {
2914
3193
  (0, import_vitest9.expect)(acked.find((l) => l.stream === ctl)).toBeDefined();
2915
3194
  (0, import_vitest9.expect)(acked.find((l) => l.stream === s)).toBeUndefined();
2916
3195
  await store.commit(
2917
- ctl,
2918
- [inc(2)],
3196
+ [{ stream: ctl, msgs: [inc(2)] }],
2919
3197
  make_meta({ stream: ctl })
2920
3198
  );
2921
3199
  await correlate();
@@ -2927,8 +3205,7 @@ var runStoreTck = (options) => {
2927
3205
  const s = `ackdefer-past-${uid()}`;
2928
3206
  await store.subscribe([{ stream: s }]);
2929
3207
  await store.commit(
2930
- s,
2931
- [inc(1)],
3208
+ [{ stream: s, msgs: [inc(1)] }],
2932
3209
  make_meta({ stream: s })
2933
3210
  );
2934
3211
  await correlate();
@@ -2947,8 +3224,7 @@ var runStoreTck = (options) => {
2947
3224
  const s = `ackdefer-retry-${uid()}`;
2948
3225
  await store.subscribe([{ stream: s }]);
2949
3226
  await store.commit(
2950
- s,
2951
- [inc(1)],
3227
+ [{ stream: s, msgs: [inc(1)] }],
2952
3228
  make_meta({ stream: s })
2953
3229
  );
2954
3230
  await correlate();
@@ -2967,13 +3243,11 @@ var runStoreTck = (options) => {
2967
3243
  const s = `ackadvance-${uid()}`;
2968
3244
  await store.subscribe([{ stream: s }]);
2969
3245
  const [e1] = await store.commit(
2970
- s,
2971
- [inc(1)],
3246
+ [{ stream: s, msgs: [inc(1)] }],
2972
3247
  make_meta({ stream: s })
2973
3248
  );
2974
3249
  await store.commit(
2975
- s,
2976
- [inc(1)],
3250
+ [{ stream: s, msgs: [inc(1)] }],
2977
3251
  make_meta({ stream: s })
2978
3252
  );
2979
3253
  await correlate();
@@ -2995,8 +3269,7 @@ var runStoreTck = (options) => {
2995
3269
  const s = `ackdefer-owner-${uid()}`;
2996
3270
  await store.subscribe([{ stream: s }]);
2997
3271
  await store.commit(
2998
- s,
2999
- [inc(1)],
3272
+ [{ stream: s, msgs: [inc(1)] }],
3000
3273
  make_meta({ stream: s })
3001
3274
  );
3002
3275
  await correlate();
@@ -3014,8 +3287,7 @@ var runStoreTck = (options) => {
3014
3287
  const s = `reset-${uid()}`;
3015
3288
  await store.subscribe([{ stream: s }]);
3016
3289
  await store.commit(
3017
- s,
3018
- [inc(1)],
3290
+ [{ stream: s, msgs: [inc(1)] }],
3019
3291
  make_meta({ stream: s })
3020
3292
  );
3021
3293
  await correlate();
@@ -3034,8 +3306,7 @@ var runStoreTck = (options) => {
3034
3306
  const s = `reset-blk-${uid()}`;
3035
3307
  await store.subscribe([{ stream: s }]);
3036
3308
  await store.commit(
3037
- s,
3038
- [inc(1)],
3309
+ [{ stream: s, msgs: [inc(1)] }],
3039
3310
  make_meta({ stream: s })
3040
3311
  );
3041
3312
  await correlate();
@@ -3057,8 +3328,7 @@ var runStoreTck = (options) => {
3057
3328
  const s = `reset-dup-${uid()}`;
3058
3329
  await store.subscribe([{ stream: s }]);
3059
3330
  await store.commit(
3060
- s,
3061
- [inc(1)],
3331
+ [{ stream: s, msgs: [inc(1)] }],
3062
3332
  make_meta({ stream: s })
3063
3333
  );
3064
3334
  (0, import_vitest9.expect)(await store.reset([s, s])).toBe(1);
@@ -3069,13 +3339,11 @@ var runStoreTck = (options) => {
3069
3339
  const s = `unblock-${uid()}`;
3070
3340
  await store.subscribe([{ stream: s }]);
3071
3341
  await store.commit(
3072
- s,
3073
- [inc(1)],
3342
+ [{ stream: s, msgs: [inc(1)] }],
3074
3343
  make_meta({ stream: s })
3075
3344
  );
3076
3345
  await store.commit(
3077
- s,
3078
- [inc(2)],
3346
+ [{ stream: s, msgs: [inc(2)] }],
3079
3347
  make_meta({ stream: s })
3080
3348
  );
3081
3349
  await correlate();
@@ -3108,8 +3376,7 @@ var runStoreTck = (options) => {
3108
3376
  const s = `unblock-noop-${uid()}`;
3109
3377
  await store.subscribe([{ stream: s }]);
3110
3378
  await store.commit(
3111
- s,
3112
- [inc(1)],
3379
+ [{ stream: s, msgs: [inc(1)] }],
3113
3380
  make_meta({ stream: s })
3114
3381
  );
3115
3382
  (0, import_vitest9.expect)(await store.unblock([s])).toBe(0);
@@ -3123,13 +3390,11 @@ var runStoreTck = (options) => {
3123
3390
  const s2 = `unblock-mix-b-${uid()}`;
3124
3391
  await store.subscribe([{ stream: s1 }, { stream: s2 }]);
3125
3392
  await store.commit(
3126
- s1,
3127
- [inc(1)],
3393
+ [{ stream: s1, msgs: [inc(1)] }],
3128
3394
  make_meta({ stream: s1 })
3129
3395
  );
3130
3396
  await store.commit(
3131
- s2,
3132
- [inc(1)],
3397
+ [{ stream: s2, msgs: [inc(1)] }],
3133
3398
  make_meta({ stream: s2 })
3134
3399
  );
3135
3400
  await correlate();
@@ -3147,18 +3412,15 @@ var runStoreTck = (options) => {
3147
3412
  const s3 = `other-${tag}`;
3148
3413
  await store.subscribe([{ stream: s1 }, { stream: s2 }, { stream: s3 }]);
3149
3414
  await store.commit(
3150
- s1,
3151
- [inc(1)],
3415
+ [{ stream: s1, msgs: [inc(1)] }],
3152
3416
  make_meta({ stream: s1 })
3153
3417
  );
3154
3418
  await store.commit(
3155
- s2,
3156
- [inc(1)],
3419
+ [{ stream: s2, msgs: [inc(1)] }],
3157
3420
  make_meta({ stream: s2 })
3158
3421
  );
3159
3422
  await store.commit(
3160
- s3,
3161
- [inc(1)],
3423
+ [{ stream: s3, msgs: [inc(1)] }],
3162
3424
  make_meta({ stream: s3 })
3163
3425
  );
3164
3426
  await correlate();
@@ -3186,13 +3448,11 @@ var runStoreTck = (options) => {
3186
3448
  const s2 = `unblock-empty-${tag}-b`;
3187
3449
  await store.subscribe([{ stream: s1 }, { stream: s2 }]);
3188
3450
  await store.commit(
3189
- s1,
3190
- [inc(1)],
3451
+ [{ stream: s1, msgs: [inc(1)] }],
3191
3452
  make_meta({ stream: s1 })
3192
3453
  );
3193
3454
  await store.commit(
3194
- s2,
3195
- [inc(1)],
3455
+ [{ stream: s2, msgs: [inc(1)] }],
3196
3456
  make_meta({ stream: s2 })
3197
3457
  );
3198
3458
  await correlate();
@@ -3212,8 +3472,7 @@ var runStoreTck = (options) => {
3212
3472
  const s = `unblock-blocked-false-${tag}`;
3213
3473
  await store.subscribe([{ stream: s }]);
3214
3474
  await store.commit(
3215
- s,
3216
- [inc(1)],
3475
+ [{ stream: s, msgs: [inc(1)] }],
3217
3476
  make_meta({ stream: s })
3218
3477
  );
3219
3478
  (0, import_vitest9.expect)(
@@ -3236,18 +3495,15 @@ var runStoreTck = (options) => {
3236
3495
  { stream: other }
3237
3496
  ]);
3238
3497
  await store.commit(
3239
- s1,
3240
- [inc(1)],
3498
+ [{ stream: s1, msgs: [inc(1)] }],
3241
3499
  make_meta({ stream: s1 })
3242
3500
  );
3243
3501
  await store.commit(
3244
- s2,
3245
- [inc(1)],
3502
+ [{ stream: s2, msgs: [inc(1)] }],
3246
3503
  make_meta({ stream: s2 })
3247
3504
  );
3248
3505
  await store.commit(
3249
- other,
3250
- [inc(1)],
3506
+ [{ stream: other, msgs: [inc(1)] }],
3251
3507
  make_meta({ stream: other })
3252
3508
  );
3253
3509
  await correlate();
@@ -3278,13 +3534,11 @@ var runStoreTck = (options) => {
3278
3534
  const s2 = `reset-blocked-${tag}-fine`;
3279
3535
  await store.subscribe([{ stream: s1 }, { stream: s2 }]);
3280
3536
  await store.commit(
3281
- s1,
3282
- [inc(1)],
3537
+ [{ stream: s1, msgs: [inc(1)] }],
3283
3538
  make_meta({ stream: s1 })
3284
3539
  );
3285
3540
  await store.commit(
3286
- s2,
3287
- [inc(1)],
3541
+ [{ stream: s2, msgs: [inc(1)] }],
3288
3542
  make_meta({ stream: s2 })
3289
3543
  );
3290
3544
  await correlate();
@@ -3363,8 +3617,7 @@ var runStoreTck = (options) => {
3363
3617
  const ok = `pri-${tag}-ok`;
3364
3618
  const bad = `pri-${tag}-bad`;
3365
3619
  await fresh.commit(
3366
- src,
3367
- [inc(1)],
3620
+ [{ stream: src, msgs: [inc(1)] }],
3368
3621
  make_meta({ stream: src })
3369
3622
  );
3370
3623
  await fresh.subscribe([
@@ -3410,8 +3663,7 @@ var runStoreTck = (options) => {
3410
3663
  const tag = uid();
3411
3664
  const src = `pri-src-${tag}`;
3412
3665
  await fresh.commit(
3413
- src,
3414
- [inc(1), inc(2)],
3666
+ [{ stream: src, msgs: [inc(1), inc(2)] }],
3415
3667
  make_meta({ stream: src })
3416
3668
  );
3417
3669
  await fresh.subscribe([
@@ -3509,13 +3761,11 @@ var runStoreTck = (options) => {
3509
3761
  const sub_default = `lane-claim-def-${tag}`;
3510
3762
  const sub_slow = `lane-claim-slow-${tag}`;
3511
3763
  await store.commit(
3512
- src1,
3513
- [inc(1)],
3764
+ [{ stream: src1, msgs: [inc(1)] }],
3514
3765
  make_meta({ stream: src1 })
3515
3766
  );
3516
3767
  await store.commit(
3517
- src2,
3518
- [inc(1)],
3768
+ [{ stream: src2, msgs: [inc(1)] }],
3519
3769
  make_meta({ stream: src2 })
3520
3770
  );
3521
3771
  await store.subscribe([
@@ -3582,8 +3832,7 @@ var runStoreTck = (options) => {
3582
3832
  const a = `lane-reset-a-${tag}`;
3583
3833
  const b = `lane-reset-b-${tag}`;
3584
3834
  await store.commit(
3585
- src,
3586
- [inc(1)],
3835
+ [{ stream: src, msgs: [inc(1)] }],
3587
3836
  make_meta({ stream: src })
3588
3837
  );
3589
3838
  await store.subscribe([
@@ -3612,8 +3861,7 @@ var runStoreTck = (options) => {
3612
3861
  const a = `lane-ub-a-${tag}`;
3613
3862
  const b = `lane-ub-b-${tag}`;
3614
3863
  await store.commit(
3615
- src,
3616
- [inc(1)],
3864
+ [{ stream: src, msgs: [inc(1)] }],
3617
3865
  make_meta({ stream: src })
3618
3866
  );
3619
3867
  await store.subscribe([
@@ -3642,8 +3890,7 @@ var runStoreTck = (options) => {
3642
3890
  const tag = uid();
3643
3891
  const long = `${tag}-${"x".repeat(140)}`;
3644
3892
  await store.commit(
3645
- long,
3646
- [inc(1)],
3893
+ [{ stream: long, msgs: [inc(1)] }],
3647
3894
  make_meta({ stream: long })
3648
3895
  );
3649
3896
  await store.subscribe([
@@ -3668,8 +3915,7 @@ var runStoreTck = (options) => {
3668
3915
  for (const s of [restarted, retired]) {
3669
3916
  await store.subscribe([{ stream: s }]);
3670
3917
  await store.commit(
3671
- s,
3672
- [inc(1)],
3918
+ [{ stream: s, msgs: [inc(1)] }],
3673
3919
  make_meta({ stream: s })
3674
3920
  );
3675
3921
  }
@@ -3693,8 +3939,7 @@ var runStoreTck = (options) => {
3693
3939
  const lane = `inert-lane-${uid()}`;
3694
3940
  const s = `trunc-inert-${uid()}`;
3695
3941
  const [e] = await store.commit(
3696
- s,
3697
- [inc(1)],
3942
+ [{ stream: s, msgs: [inc(1)] }],
3698
3943
  make_meta({ stream: s })
3699
3944
  );
3700
3945
  await store.subscribe([{ stream: s, correlated_at: e.id, lane }]);
@@ -3709,8 +3954,7 @@ var runStoreTck = (options) => {
3709
3954
  (0, import_vitest9.it)("seeds a tombstone when no snapshot is provided", async () => {
3710
3955
  const s = `trunc-tomb-${uid()}`;
3711
3956
  await store.commit(
3712
- s,
3713
- [inc(1), inc(2)],
3957
+ [{ stream: s, msgs: [inc(1), inc(2)] }],
3714
3958
  make_meta({ stream: s })
3715
3959
  );
3716
3960
  const result = await store.truncate([{ stream: s }]);
@@ -3730,8 +3974,7 @@ var runStoreTck = (options) => {
3730
3974
  (0, import_vitest9.it)("seeds a snapshot when one is provided", async () => {
3731
3975
  const s = `trunc-snap-${uid()}`;
3732
3976
  await store.commit(
3733
- s,
3734
- [inc(1)],
3977
+ [{ stream: s, msgs: [inc(1)] }],
3735
3978
  make_meta({ stream: s })
3736
3979
  );
3737
3980
  const result = await store.truncate([
@@ -3754,8 +3997,7 @@ var runStoreTck = (options) => {
3754
3997
  (0, import_vitest9.it)("leaves exactly one seed when a stream is listed twice", async () => {
3755
3998
  const s = `trunc-dup-${uid()}`;
3756
3999
  await store.commit(
3757
- s,
3758
- [inc(1), inc(2)],
4000
+ [{ stream: s, msgs: [inc(1), inc(2)] }],
3759
4001
  make_meta({ stream: s })
3760
4002
  );
3761
4003
  const result = await store.truncate([
@@ -3776,13 +4018,11 @@ var runStoreTck = (options) => {
3776
4018
  (0, import_vitest9.it)("applies windowed targets before full ones", async () => {
3777
4019
  const s = `trunc-mix-${uid()}`;
3778
4020
  await store.commit(
3779
- s,
3780
- [inc(1)],
4021
+ [{ stream: s, msgs: [inc(1)] }],
3781
4022
  make_meta({ stream: s })
3782
4023
  );
3783
4024
  await store.commit(
3784
- s,
3785
- [inc(2)],
4025
+ [{ stream: s, msgs: [inc(2)] }],
3786
4026
  make_meta({ stream: s })
3787
4027
  );
3788
4028
  await (0, import_act2.sleep)(5);
@@ -3819,28 +4059,23 @@ var runStoreTck = (options) => {
3819
4059
  (0, import_vitest9.describe)("windowed (before boundary)", () => {
3820
4060
  async function seed_windowed(s) {
3821
4061
  await store.commit(
3822
- s,
3823
- [inc(1), inc(1)],
4062
+ [{ stream: s, msgs: [inc(1), inc(1)] }],
3824
4063
  make_meta({ stream: s })
3825
4064
  );
3826
4065
  const [snap_a] = await store.commit(
3827
- s,
3828
- [{ name: import_act2.SNAP_EVENT, data: { count: 2 } }],
4066
+ [{ stream: s, msgs: [{ name: import_act2.SNAP_EVENT, data: { count: 2 } }] }],
3829
4067
  make_meta({ stream: s })
3830
4068
  );
3831
4069
  await store.commit(
3832
- s,
3833
- [inc(1)],
4070
+ [{ stream: s, msgs: [inc(1)] }],
3834
4071
  make_meta({ stream: s })
3835
4072
  );
3836
4073
  const [snap_b] = await store.commit(
3837
- s,
3838
- [{ name: import_act2.SNAP_EVENT, data: { count: 3 } }],
4074
+ [{ stream: s, msgs: [{ name: import_act2.SNAP_EVENT, data: { count: 3 } }] }],
3839
4075
  make_meta({ stream: s })
3840
4076
  );
3841
4077
  await store.commit(
3842
- s,
3843
- [inc(1)],
4078
+ [{ stream: s, msgs: [inc(1)] }],
3844
4079
  make_meta({ stream: s })
3845
4080
  );
3846
4081
  return { snap_a, snap_b };
@@ -3910,8 +4145,7 @@ var runStoreTck = (options) => {
3910
4145
  (0, import_vitest9.it)("no-ops when no snapshot qualifies \u2014 stream absent from the result, events untouched", async () => {
3911
4146
  const s = `trunc-win-noop-${uid()}`;
3912
4147
  await store.commit(
3913
- s,
3914
- [inc(1), inc(1)],
4148
+ [{ stream: s, msgs: [inc(1), inc(1)] }],
3915
4149
  make_meta({ stream: s })
3916
4150
  );
3917
4151
  const none = await store.truncate([
@@ -3919,8 +4153,7 @@ var runStoreTck = (options) => {
3919
4153
  ]);
3920
4154
  (0, import_vitest9.expect)(none.has(s)).toBe(false);
3921
4155
  await store.commit(
3922
- s,
3923
- [{ name: import_act2.SNAP_EVENT, data: { count: 2 } }],
4156
+ [{ stream: s, msgs: [{ name: import_act2.SNAP_EVENT, data: { count: 2 } }] }],
3924
4157
  make_meta({ stream: s })
3925
4158
  );
3926
4159
  const too_early = await store.truncate([
@@ -3958,8 +4191,7 @@ var runStoreTck = (options) => {
3958
4191
  const f = `trunc-win-mix-f-${uid()}`;
3959
4192
  const { snap_b } = await seed_windowed(w);
3960
4193
  await store.commit(
3961
- f,
3962
- [inc(1)],
4194
+ [{ stream: f, msgs: [inc(1)] }],
3963
4195
  make_meta({ stream: f })
3964
4196
  );
3965
4197
  const result = await store.truncate([
@@ -3979,8 +4211,7 @@ var runStoreTck = (options) => {
3979
4211
  { stream: s, before: new Date(Date.now() + 6e4) }
3980
4212
  ]);
3981
4213
  const [next] = await store.commit(
3982
- s,
3983
- [inc(1)],
4214
+ [{ stream: s, msgs: [inc(1)] }],
3984
4215
  make_meta({ stream: s })
3985
4216
  );
3986
4217
  (0, import_vitest9.expect)(next.version).toBe(6);
@@ -4118,8 +4349,7 @@ var runStoreTck = (options) => {
4118
4349
  const sibling = `qb-${tag}-other`;
4119
4350
  await store.subscribe([{ stream: s }, { stream: sibling }]);
4120
4351
  await store.commit(
4121
- s,
4122
- [inc(1)],
4352
+ [{ stream: s, msgs: [inc(1)] }],
4123
4353
  make_meta({ stream: s })
4124
4354
  );
4125
4355
  await correlate();
@@ -4150,18 +4380,15 @@ var runStoreTck = (options) => {
4150
4380
  const sB = `qst-${tag}-b`;
4151
4381
  const sUnasked = `qst-${tag}-unasked`;
4152
4382
  await store.commit(
4153
- sA,
4154
- [inc(1), inc(2)],
4383
+ [{ stream: sA, msgs: [inc(1), inc(2)] }],
4155
4384
  make_meta({ stream: sA })
4156
4385
  );
4157
4386
  await store.commit(
4158
- sB,
4159
- [dec(5)],
4387
+ [{ stream: sB, msgs: [dec(5)] }],
4160
4388
  make_meta({ stream: sB })
4161
4389
  );
4162
4390
  await store.commit(
4163
- sUnasked,
4164
- [inc(99)],
4391
+ [{ stream: sUnasked, msgs: [inc(99)] }],
4165
4392
  make_meta({ stream: sUnasked })
4166
4393
  );
4167
4394
  const stats = await store.query_stats([sA, sB]);
@@ -4179,8 +4406,7 @@ var runStoreTck = (options) => {
4179
4406
  (0, import_vitest9.it)("limit: 0 returns no rows", async () => {
4180
4407
  const s = `qst-zero-${uid()}`;
4181
4408
  await store.commit(
4182
- s,
4183
- [inc(1)],
4409
+ [{ stream: s, msgs: [inc(1)] }],
4184
4410
  make_meta({ stream: s })
4185
4411
  );
4186
4412
  const filter = { stream: s, stream_exact: true };
@@ -4201,8 +4427,7 @@ var runStoreTck = (options) => {
4201
4427
  ];
4202
4428
  for (const s of names)
4203
4429
  await store.commit(
4204
- s,
4205
- [inc(1)],
4430
+ [{ stream: s, msgs: [inc(1)] }],
4206
4431
  make_meta({ stream: s })
4207
4432
  );
4208
4433
  const visited = [];
@@ -4225,18 +4450,15 @@ var runStoreTck = (options) => {
4225
4450
  const tag = uid();
4226
4451
  const s = `qst-tail-${tag}`;
4227
4452
  await store.commit(
4228
- s,
4229
- [inc(1)],
4453
+ [{ stream: s, msgs: [inc(1)] }],
4230
4454
  make_meta({ stream: s })
4231
4455
  );
4232
4456
  await store.commit(
4233
- s,
4234
- [inc(2)],
4457
+ [{ stream: s, msgs: [inc(2)] }],
4235
4458
  make_meta({ stream: s })
4236
4459
  );
4237
4460
  await store.commit(
4238
- s,
4239
- [inc(3)],
4461
+ [{ stream: s, msgs: [inc(3)] }],
4240
4462
  make_meta({ stream: s })
4241
4463
  );
4242
4464
  const stats = await store.query_stats([s], {
@@ -4252,14 +4474,12 @@ var runStoreTck = (options) => {
4252
4474
  const tag = uid();
4253
4475
  const s = `qst-cn-${tag}`;
4254
4476
  await store.commit(
4255
- s,
4256
- [inc(1)],
4477
+ [{ stream: s, msgs: [inc(1)] }],
4257
4478
  make_meta({ stream: s })
4258
4479
  );
4259
4480
  await store.truncate([{ stream: s, snapshot: { count: 99 } }]);
4260
4481
  await store.commit(
4261
- s,
4262
- [inc(2), inc(3), dec(1)],
4482
+ [{ stream: s, msgs: [inc(2), inc(3), dec(1)] }],
4263
4483
  make_meta({ stream: s })
4264
4484
  );
4265
4485
  const stats = await store.query_stats([s], {
@@ -4278,13 +4498,11 @@ var runStoreTck = (options) => {
4278
4498
  const s = `qst-excl-${tag}`;
4279
4499
  const sAllOut = `qst-allout-${tag}`;
4280
4500
  await store.commit(
4281
- s,
4282
- [inc(1), dec(2), inc(3)],
4501
+ [{ stream: s, msgs: [inc(1), dec(2), inc(3)] }],
4283
4502
  make_meta({ stream: s })
4284
4503
  );
4285
4504
  await store.commit(
4286
- sAllOut,
4287
- [inc(7)],
4505
+ [{ stream: sAllOut, msgs: [inc(7)] }],
4288
4506
  make_meta({ stream: sAllOut })
4289
4507
  );
4290
4508
  const all = await store.query_stats([s]);
@@ -4308,18 +4526,15 @@ var runStoreTck = (options) => {
4308
4526
  const tag = uid();
4309
4527
  const s = `qst-tt-${tag}`;
4310
4528
  const c1 = await store.commit(
4311
- s,
4312
- [inc(1)],
4529
+ [{ stream: s, msgs: [inc(1)] }],
4313
4530
  make_meta({ stream: s })
4314
4531
  );
4315
4532
  const c2 = await store.commit(
4316
- s,
4317
- [inc(2)],
4533
+ [{ stream: s, msgs: [inc(2)] }],
4318
4534
  make_meta({ stream: s })
4319
4535
  );
4320
4536
  await store.commit(
4321
- s,
4322
- [inc(3)],
4537
+ [{ stream: s, msgs: [inc(3)] }],
4323
4538
  make_meta({ stream: s })
4324
4539
  );
4325
4540
  const before = c2[0].id;
@@ -4343,18 +4558,15 @@ var runStoreTck = (options) => {
4343
4558
  const sB = `qsf-${tag}-orders-2`;
4344
4559
  const sOther = `qsf-${tag}-users-1`;
4345
4560
  await store.commit(
4346
- sA,
4347
- [inc(1)],
4561
+ [{ stream: sA, msgs: [inc(1)] }],
4348
4562
  make_meta({ stream: sA })
4349
4563
  );
4350
4564
  await store.commit(
4351
- sB,
4352
- [inc(2)],
4565
+ [{ stream: sB, msgs: [inc(2)] }],
4353
4566
  make_meta({ stream: sB })
4354
4567
  );
4355
4568
  await store.commit(
4356
- sOther,
4357
- [inc(3)],
4569
+ [{ stream: sOther, msgs: [inc(3)] }],
4358
4570
  make_meta({ stream: sOther })
4359
4571
  );
4360
4572
  const orders = await store.query_stats({
@@ -4377,13 +4589,11 @@ var runStoreTck = (options) => {
4377
4589
  const b = `qsc-${tag}-b`;
4378
4590
  await store.subscribe([{ stream: a }, { stream: b }]);
4379
4591
  await store.commit(
4380
- a,
4381
- [inc(1)],
4592
+ [{ stream: a, msgs: [inc(1)] }],
4382
4593
  make_meta({ stream: a })
4383
4594
  );
4384
4595
  await store.commit(
4385
- b,
4386
- [inc(2)],
4596
+ [{ stream: b, msgs: [inc(2)] }],
4387
4597
  make_meta({ stream: b })
4388
4598
  );
4389
4599
  await correlate();
@@ -4408,13 +4618,11 @@ var runStoreTck = (options) => {
4408
4618
  const a = `qse-${tag}-a`;
4409
4619
  const b = `qse-${tag}-b`;
4410
4620
  await store.commit(
4411
- a,
4412
- [inc(1)],
4621
+ [{ stream: a, msgs: [inc(1)] }],
4413
4622
  make_meta({ stream: a })
4414
4623
  );
4415
4624
  await store.commit(
4416
- b,
4417
- [dec(2)],
4625
+ [{ stream: b, msgs: [dec(2)] }],
4418
4626
  make_meta({ stream: b })
4419
4627
  );
4420
4628
  const all = await store.query_stats({});
@@ -4425,8 +4633,7 @@ var runStoreTck = (options) => {
4425
4633
  const tag = uid();
4426
4634
  const s = `qsfl-${tag}`;
4427
4635
  await store.commit(
4428
- s,
4429
- [inc(1), inc(2), dec(3)],
4636
+ [{ stream: s, msgs: [inc(1), inc(2), dec(3)] }],
4430
4637
  make_meta({ stream: s })
4431
4638
  );
4432
4639
  const c = await store.query_stats([s], {
@@ -4457,8 +4664,7 @@ var runStoreTck = (options) => {
4457
4664
  ];
4458
4665
  for (const s of streams) {
4459
4666
  await store.commit(
4460
- s,
4461
- [inc(1)],
4667
+ [{ stream: s, msgs: [inc(1)] }],
4462
4668
  make_meta({ stream: s })
4463
4669
  );
4464
4670
  }
@@ -4488,8 +4694,7 @@ var runStoreTck = (options) => {
4488
4694
  const tag = uid();
4489
4695
  for (const s of [`qsc-${tag}-c`, `qsc-${tag}-a`, `qsc-${tag}-b`])
4490
4696
  await store.commit(
4491
- s,
4492
- [inc(1), inc(2)],
4697
+ [{ stream: s, msgs: [inc(1), inc(2)] }],
4493
4698
  make_meta({ stream: s })
4494
4699
  );
4495
4700
  const pattern = { stream: `qsc-${tag}-.*` };
@@ -4638,8 +4843,7 @@ var runStoreTck = (options) => {
4638
4843
  const s = `head-${uid()}`;
4639
4844
  await store.subscribe([{ stream: s }]);
4640
4845
  await store.commit(
4641
- s,
4642
- [inc(1)],
4846
+ [{ stream: s, msgs: [inc(1)] }],
4643
4847
  make_meta({ stream: s })
4644
4848
  );
4645
4849
  const positions = [];
@@ -4655,7 +4859,7 @@ var runStoreTck = (options) => {
4655
4859
  const actor2 = { id: "reader", name: "Reader" };
4656
4860
  const reader = (shape) => {
4657
4861
  const Happened = import_zod2.z.object(shape);
4658
- return (0, import_act2.state)({ Reader: import_zod2.z.object({ n: import_zod2.z.number() }) }).init(() => ({ n: 0 })).emits({ Happened }).patch({ Happened: (_, s) => ({ n: s.n + 1 }) }).on({ Do: Happened }).emit((p) => ["Happened", p]).build();
4862
+ return (0, import_act2.state)({ Reader: import_zod2.z.object({ n: import_zod2.z.number() }) }).init(() => ({ n: 0 })).emits({ Happened }).patch({ Happened: (_, s) => ({ n: s.n + 1 }) }).on({ Do: Happened }).emit("Happened").build();
4659
4863
  };
4660
4864
  const over = async (S) => {
4661
4865
  const fresh = await options.factory();
@@ -4748,10 +4952,16 @@ var runStoreTck = (options) => {
4748
4952
  const t = await over(S);
4749
4953
  try {
4750
4954
  await t.fresh.commit(
4751
- t.stream,
4752
- [{ name: "Happened", data: { at: /* @__PURE__ */ new Date("2020-01-01") } }],
4753
- raw,
4754
- -1
4955
+ [
4956
+ {
4957
+ stream: t.stream,
4958
+ msgs: [
4959
+ { name: "Happened", data: { at: /* @__PURE__ */ new Date("2020-01-01") } }
4960
+ ],
4961
+ expectedVersion: -1
4962
+ }
4963
+ ],
4964
+ raw
4755
4965
  );
4756
4966
  const d = await t.read();
4757
4967
  (0, import_vitest9.expect)(d.label).toBeUndefined();
@@ -4765,10 +4975,14 @@ var runStoreTck = (options) => {
4765
4975
  const t = await over(S);
4766
4976
  try {
4767
4977
  await t.fresh.commit(
4768
- t.stream,
4769
- [{ name: "Happened", data: { at: "not a date" } }],
4770
- raw,
4771
- -1
4978
+ [
4979
+ {
4980
+ stream: t.stream,
4981
+ msgs: [{ name: "Happened", data: { at: "not a date" } }],
4982
+ expectedVersion: -1
4983
+ }
4984
+ ],
4985
+ raw
4772
4986
  );
4773
4987
  (0, import_vitest9.expect)((await t.read()).at).toBe("not a date");
4774
4988
  } finally {
@@ -4908,6 +5122,19 @@ var runStoreTck = (options) => {
4908
5122
  (0, import_vitest9.expect)((await take(k, who)).correlating).toBe(true);
4909
5123
  await release(k, who);
4910
5124
  });
5125
+ (0, import_vitest9.it)("advances the checkpoint for a caller refused the lease", async () => {
5126
+ const k = key();
5127
+ const holder = by();
5128
+ (0, import_vitest9.expect)((await take(k, holder)).correlating).toBe(true);
5129
+ const refused = await store.subscribe([], 123456, {
5130
+ key: k,
5131
+ by: by(),
5132
+ millis: 1e4
5133
+ });
5134
+ (0, import_vitest9.expect)(refused.correlating).toBe(false);
5135
+ (0, import_vitest9.expect)((await take(k, holder)).correlated_at).toBe(123456);
5136
+ await release(k, holder);
5137
+ });
4911
5138
  (0, import_vitest9.it)("answers undefined when no correlator is supplied", async () => {
4912
5139
  (0, import_vitest9.expect)(await store.subscribe([])).not.toHaveProperty("correlating");
4913
5140
  });
@@ -4989,7 +5216,234 @@ var runStoreTck = (options) => {
4989
5216
  });
4990
5217
  }
4991
5218
  );
5219
+ (0, import_vitest9.describe)("an action across streams", () => {
5220
+ const SeatTaken = import_zod2.z.object({ student: import_zod2.z.string() });
5221
+ const Seats = (0, import_act2.state)({
5222
+ Seats: import_zod2.z.object({ taken: import_zod2.z.number() }).refine((s) => s.taken <= 3, "the course is full")
5223
+ }).init(() => ({ taken: 0 })).emits({ SeatTaken }).patch({ SeatTaken: (_, s) => ({ taken: s.taken + 1 }) }).on({ TakeSeat: SeatTaken }).emit("SeatTaken").build();
5224
+ const Enroll = import_zod2.z.object({ course: import_zod2.z.string(), student: import_zod2.z.string() });
5225
+ const course = (data) => `course-${data.course}`;
5226
+ const Enrollment = (0, import_act2.state)({ Enrollment: Enroll }).init(() => ({ course: "", student: "" })).emits({ Enrolled: Enroll }).on({ Enroll }, { maxRetries: 8 }).loads(Seats, course, ["SeatTaken"]).requires([
5227
+ {
5228
+ description: "the course has a free seat",
5229
+ holds: (_, __, ___, { Seats: Seats2 }) => Seats2.taken < 3
5230
+ }
5231
+ ]).emit((data) => [
5232
+ ["Enrolled", data],
5233
+ ["SeatTaken", { student: data.student }]
5234
+ ]).on({ Overfill: Enroll }).loads(Seats, course, ["SeatTaken"]).emit((data) => [
5235
+ ["Enrolled", data],
5236
+ ["SeatTaken", { student: data.student }]
5237
+ ]).build();
5238
+ const actor2 = { id: "a", name: "a" };
5239
+ const at = (stream) => ({ stream, actor: actor2 });
5240
+ const over = async (run) => {
5241
+ const fresh = await options.factory();
5242
+ await fresh.seed();
5243
+ const cache = new import_act2.InMemoryCache();
5244
+ const app = (0, import_act2.act)().withState(Seats).withState(Enrollment).build({ scoped: { store: fresh, cache } });
5245
+ const c = `c${uid()}`;
5246
+ const events2 = async (stream) => {
5247
+ const found = [];
5248
+ await fresh.query((e) => found.push(e), {
5249
+ stream,
5250
+ stream_exact: true
5251
+ });
5252
+ return found;
5253
+ };
5254
+ try {
5255
+ await run({
5256
+ app,
5257
+ fresh,
5258
+ c,
5259
+ events: events2,
5260
+ seat: (student) => ({ course: c, student })
5261
+ });
5262
+ } finally {
5263
+ import_vitest9.vi.restoreAllMocks();
5264
+ await app.shutdown();
5265
+ await cache.dispose();
5266
+ await fresh.dispose();
5267
+ }
5268
+ };
5269
+ (0, import_vitest9.it)("commits both streams at once and fires committed once per stream", () => over(async ({ app, c, events: events2, seat }) => {
5270
+ const stream = `enr-${uid()}`;
5271
+ const heard = [];
5272
+ app.on("committed", (s) => heard.push(s));
5273
+ const snapshots = await app.do("Enroll", at(stream), seat("s1"));
5274
+ (0, import_vitest9.expect)(snapshots.map((s) => s.event?.name)).toEqual([
5275
+ "Enrolled"
5276
+ ]);
5277
+ const [own] = await events2(stream);
5278
+ const [other] = await events2(`course-${c}`);
5279
+ (0, import_vitest9.expect)(own.name).toBe("Enrolled");
5280
+ (0, import_vitest9.expect)(other.name).toBe("SeatTaken");
5281
+ (0, import_vitest9.expect)(other.id).toBeGreaterThan(own.id);
5282
+ (0, import_vitest9.expect)(other.meta.correlation).toBe(own.meta.correlation);
5283
+ (0, import_vitest9.expect)(heard.map((h) => h[0].event?.stream)).toEqual([
5284
+ stream,
5285
+ `course-${c}`
5286
+ ]);
5287
+ (0, import_vitest9.expect)((await app.load(Seats, `course-${c}`)).state.taken).toBe(1);
5288
+ }));
5289
+ (0, import_vitest9.it)("stores nothing on either stream when a rule or a schema refuses", () => over(async ({ app, c, events: events2, seat }) => {
5290
+ for (const i of [1, 2, 3])
5291
+ await app.do("TakeSeat", at(`course-${c}`), { student: `s${i}` });
5292
+ const [a, b] = [`enr-${uid()}`, `enr-${uid()}`];
5293
+ await (0, import_vitest9.expect)(app.do("Enroll", at(a), seat("late"))).rejects.toThrow(
5294
+ import_act2.PreconditionError
5295
+ );
5296
+ await (0, import_vitest9.expect)(app.do("Overfill", at(b), seat("late"))).rejects.toThrow(
5297
+ import_act2.ValidationError
5298
+ );
5299
+ (0, import_vitest9.expect)(await events2(a)).toEqual([]);
5300
+ (0, import_vitest9.expect)(await events2(b)).toEqual([]);
5301
+ (0, import_vitest9.expect)(await events2(`course-${c}`)).toHaveLength(3);
5302
+ }));
5303
+ (0, import_vitest9.it)("a rival on the loaded stream refuses the whole commit, naming that stream", () => over(async ({ app, fresh, c, events: events2, seat }) => {
5304
+ const commit = fresh.commit.bind(fresh);
5305
+ import_vitest9.vi.spyOn(fresh, "commit").mockImplementationOnce(
5306
+ async (...args) => {
5307
+ await commit(
5308
+ [
5309
+ {
5310
+ stream: `course-${c}`,
5311
+ msgs: [{ name: "SeatTaken", data: { student: "rival" } }]
5312
+ }
5313
+ ],
5314
+ { correlation: "rival", causation: {} }
5315
+ );
5316
+ return commit(...args);
5317
+ }
5318
+ );
5319
+ const stream = `enr-${uid()}`;
5320
+ const err = await app.do("Overfill", at(stream), seat("s")).catch((e) => e);
5321
+ (0, import_vitest9.expect)(err).toBeInstanceOf(import_act2.ConcurrencyError);
5322
+ (0, import_vitest9.expect)(err.stream).toBe(`course-${c}`);
5323
+ (0, import_vitest9.expect)(await events2(stream)).toEqual([]);
5324
+ (0, import_vitest9.expect)(await events2(`course-${c}`)).toHaveLength(1);
5325
+ }));
5326
+ (0, import_vitest9.it)("racing enrollments fill the seats exactly: the rest are refused by the rule", () => over(async ({ app, c, events: events2, seat }) => {
5327
+ const results = await Promise.allSettled(
5328
+ [1, 2, 3, 4, 5, 6].map(
5329
+ (i) => app.do("Enroll", at(`race-${uid()}-${i}`), seat(`s${i}`))
5330
+ )
5331
+ );
5332
+ (0, import_vitest9.expect)(results.filter((r) => r.status === "fulfilled")).toHaveLength(
5333
+ 3
5334
+ );
5335
+ for (const r of results.filter((r2) => r2.status === "rejected"))
5336
+ (0, import_vitest9.expect)(r.reason).toBeInstanceOf(
5337
+ import_act2.PreconditionError
5338
+ );
5339
+ (0, import_vitest9.expect)(await events2(`course-${c}`)).toHaveLength(3);
5340
+ }));
5341
+ });
4992
5342
  import_vitest9.describe.skipIf(!caps.restore)("restore (capability)", () => {
5343
+ (0, import_vitest9.describe)("what a restore must not get wrong", () => {
5344
+ const edge_uid = () => uid();
5345
+ const E = (data = { a: 1 }, pii) => ({
5346
+ name: "E",
5347
+ data,
5348
+ ...pii ? { pii } : {}
5349
+ });
5350
+ const edge_meta = (correlation = "m") => ({ correlation, causation: {} });
5351
+ const rows = async (query) => {
5352
+ const found = [];
5353
+ await store.query((e) => found.push(e), query);
5354
+ return found;
5355
+ };
5356
+ const one = (stream) => ({ stream, stream_exact: true });
5357
+ (0, import_vitest9.it)("a commit after restore continues each stream from its restored head", async () => {
5358
+ const a = `a-${edge_uid()}`;
5359
+ await store.commit(
5360
+ [{ stream: a, msgs: [E(), E()] }],
5361
+ edge_meta()
5362
+ );
5363
+ const log = await rows({ with_snaps: true });
5364
+ await store.restore(async (cb) => {
5365
+ for (const e of log) await cb(e);
5366
+ });
5367
+ const [c] = await store.commit(
5368
+ [{ stream: a, msgs: [E()], expectedVersion: 1 }],
5369
+ edge_meta()
5370
+ );
5371
+ (0, import_vitest9.expect)(c.version).toBe(2);
5372
+ });
5373
+ (0, import_vitest9.it)("restore renumbers: ids are dense whatever the source ids were", async () => {
5374
+ const a = `a-${edge_uid()}`;
5375
+ const ev = (version, id) => ({
5376
+ id,
5377
+ stream: a,
5378
+ version,
5379
+ name: "E",
5380
+ data: {},
5381
+ meta: edge_meta(),
5382
+ created: /* @__PURE__ */ new Date()
5383
+ });
5384
+ const ids = [];
5385
+ await store.restore(async (cb) => {
5386
+ ids.push(await cb(ev(0, 500)));
5387
+ ids.push(await cb(ev(1, 900)));
5388
+ });
5389
+ (0, import_vitest9.expect)(ids[1]).toBe(ids[0] + 1);
5390
+ (0, import_vitest9.expect)(ids[0]).toBeLessThanOrEqual(1);
5391
+ });
5392
+ (0, import_vitest9.it)("changes nothing when it fails", async () => {
5393
+ const a = `rb-${edge_uid()}`;
5394
+ const key = `k-${edge_uid()}`;
5395
+ const sub = `sub-${edge_uid()}`;
5396
+ const committed = await store.commit(
5397
+ [{ stream: a, msgs: [E({}, { email: "x" }), E()] }],
5398
+ edge_meta()
5399
+ );
5400
+ const head = committed.at(-1).id;
5401
+ await store.subscribe([{ stream: sub }], head);
5402
+ const keyed = await store.subscribe([], head, {
5403
+ key,
5404
+ by: "w",
5405
+ millis: 1
5406
+ });
5407
+ const shared = await store.subscribe([]);
5408
+ await (0, import_vitest9.expect)(
5409
+ store.restore(async (callback) => {
5410
+ await callback({
5411
+ id: 1,
5412
+ stream: "other",
5413
+ version: 0,
5414
+ name: "E",
5415
+ data: {},
5416
+ meta: edge_meta(),
5417
+ created: /* @__PURE__ */ new Date()
5418
+ });
5419
+ throw new Error("mid-restore");
5420
+ })
5421
+ ).rejects.toThrow();
5422
+ const subscriptions = [];
5423
+ await store.query_streams((p) => subscriptions.push(p.stream), {
5424
+ stream: sub,
5425
+ stream_exact: true
5426
+ });
5427
+ (0, import_vitest9.expect)(subscriptions).toEqual([sub]);
5428
+ (0, import_vitest9.expect)((await store.subscribe([])).correlated_at).toBe(
5429
+ shared.correlated_at
5430
+ );
5431
+ await (0, import_act2.sleep)(5);
5432
+ const keyed_after = await store.subscribe([], void 0, {
5433
+ key,
5434
+ by: "w2",
5435
+ millis: 1
5436
+ });
5437
+ (0, import_vitest9.expect)(keyed_after.correlated_at).toBe(keyed.correlated_at);
5438
+ (0, import_vitest9.expect)((await rows(one(a)))[0].pii).toEqual({ email: "x" });
5439
+ const [next] = await store.commit(
5440
+ [{ stream: a, msgs: [E()], expectedVersion: 1 }],
5441
+ edge_meta()
5442
+ );
5443
+ (0, import_vitest9.expect)(next.version).toBe(2);
5444
+ (0, import_vitest9.expect)(next.id).toBeGreaterThan(head);
5445
+ });
5446
+ });
4993
5447
  beforeEach(async () => {
4994
5448
  await store.drop();
4995
5449
  await store.seed();
@@ -5175,8 +5629,7 @@ var runStoreTck = (options) => {
5175
5629
  (0, import_vitest9.it)("wipes pre-existing events before inserting", async () => {
5176
5630
  const old = `restore-old-${uid()}`;
5177
5631
  await store.commit(
5178
- old,
5179
- [inc(1), inc(2)],
5632
+ [{ stream: old, msgs: [inc(1), inc(2)] }],
5180
5633
  make_meta({ stream: old })
5181
5634
  );
5182
5635
  const fresh = `restore-fresh-${uid()}`;
@@ -5323,8 +5776,7 @@ var runStoreTck = (options) => {
5323
5776
  (0, import_vitest9.it)("rolls back atomically when the source throws mid-iteration", async () => {
5324
5777
  const original = `restore-pre-${uid()}`;
5325
5778
  const committed = await store.commit(
5326
- original,
5327
- [inc(1), inc(2), inc(3)],
5779
+ [{ stream: original, msgs: [inc(1), inc(2), inc(3)] }],
5328
5780
  make_meta({ stream: original })
5329
5781
  );
5330
5782
  const explosive = {
@@ -5497,12 +5949,16 @@ var runStoreTck = (options) => {
5497
5949
  (0, import_vitest9.it)("commits and loads pii alongside data", async () => {
5498
5950
  const s = `pii-roundtrip-${uid()}`;
5499
5951
  const committed = await store.commit(
5500
- s,
5501
5952
  [
5502
5953
  {
5503
- name: "Incremented",
5504
- data: { amount: 1 },
5505
- pii: { email: "u@example.com", name: "Ursula" }
5954
+ stream: s,
5955
+ msgs: [
5956
+ {
5957
+ name: "Incremented",
5958
+ data: { amount: 1 },
5959
+ pii: { email: "u@example.com", name: "Ursula" }
5960
+ }
5961
+ ]
5506
5962
  }
5507
5963
  ],
5508
5964
  make_meta({ stream: s })
@@ -5525,12 +5981,16 @@ var runStoreTck = (options) => {
5525
5981
  });
5526
5982
  (0, import_vitest9.describe)("with_pii", () => {
5527
5983
  const seed_pii = async (s) => await store.commit(
5528
- s,
5529
5984
  [
5530
5985
  {
5531
- name: "Incremented",
5532
- data: { amount: 1 },
5533
- pii: { email: "w@example.com" }
5986
+ stream: s,
5987
+ msgs: [
5988
+ {
5989
+ name: "Incremented",
5990
+ data: { amount: 1 },
5991
+ pii: { email: "w@example.com" }
5992
+ }
5993
+ ]
5534
5994
  }
5535
5995
  ],
5536
5996
  make_meta({ stream: s })
@@ -5591,12 +6051,16 @@ var runStoreTck = (options) => {
5591
6051
  const s = `pii-date-${uid()}`;
5592
6052
  const when = /* @__PURE__ */ new Date("2024-03-01T10:20:30.000Z");
5593
6053
  await store.commit(
5594
- s,
5595
6054
  [
5596
6055
  {
5597
- name: "Incremented",
5598
- data: { amount: 1, at: when },
5599
- pii: { born: when }
6056
+ stream: s,
6057
+ msgs: [
6058
+ {
6059
+ name: "Incremented",
6060
+ data: { amount: 1, at: when },
6061
+ pii: { born: when }
6062
+ }
6063
+ ]
5600
6064
  }
5601
6065
  ],
5602
6066
  make_meta({ stream: s })
@@ -5619,17 +6083,21 @@ var runStoreTck = (options) => {
5619
6083
  (0, import_vitest9.it)("query_stats head/tail never carry pii \u2014 introspection surface is pii-safe", async () => {
5620
6084
  const s = `pii-stats-${uid()}`;
5621
6085
  await store.commit(
5622
- s,
5623
6086
  [
5624
6087
  {
5625
- name: "Incremented",
5626
- data: { amount: 1 },
5627
- pii: { email: "head@example.com" }
5628
- },
5629
- {
5630
- name: "Incremented",
5631
- data: { amount: 2 },
5632
- pii: { email: "tail@example.com" }
6088
+ stream: s,
6089
+ msgs: [
6090
+ {
6091
+ name: "Incremented",
6092
+ data: { amount: 1 },
6093
+ pii: { email: "head@example.com" }
6094
+ },
6095
+ {
6096
+ name: "Incremented",
6097
+ data: { amount: 2 },
6098
+ pii: { email: "tail@example.com" }
6099
+ }
6100
+ ]
5633
6101
  }
5634
6102
  ],
5635
6103
  make_meta({ stream: s })
@@ -5653,8 +6121,7 @@ var runStoreTck = (options) => {
5653
6121
  (0, import_vitest9.it)("passes through events without pii (pii is null or undefined on load)", async () => {
5654
6122
  const s = `pii-none-${uid()}`;
5655
6123
  await store.commit(
5656
- s,
5657
- [inc(1)],
6124
+ [{ stream: s, msgs: [inc(1)] }],
5658
6125
  make_meta({ stream: s })
5659
6126
  );
5660
6127
  const seen = [];
@@ -5670,17 +6137,21 @@ var runStoreTck = (options) => {
5670
6137
  (0, import_vitest9.it)("wipes pii for every event on the stream via forget_pii", async () => {
5671
6138
  const s = `pii-forget-${uid()}`;
5672
6139
  await store.commit(
5673
- s,
5674
6140
  [
5675
6141
  {
5676
- name: "Incremented",
5677
- data: { amount: 1 },
5678
- pii: { email: "a@example.com" }
5679
- },
5680
- {
5681
- name: "Incremented",
5682
- data: { amount: 2 },
5683
- pii: { email: "b@example.com" }
6142
+ stream: s,
6143
+ msgs: [
6144
+ {
6145
+ name: "Incremented",
6146
+ data: { amount: 1 },
6147
+ pii: { email: "a@example.com" }
6148
+ },
6149
+ {
6150
+ name: "Incremented",
6151
+ data: { amount: 2 },
6152
+ pii: { email: "b@example.com" }
6153
+ }
6154
+ ]
5684
6155
  }
5685
6156
  ],
5686
6157
  make_meta({ stream: s })
@@ -5705,12 +6176,16 @@ var runStoreTck = (options) => {
5705
6176
  (0, import_vitest9.it)("is idempotent \u2014 second forget_pii returns 0, no error", async () => {
5706
6177
  const s = `pii-forget-idem-${uid()}`;
5707
6178
  await store.commit(
5708
- s,
5709
6179
  [
5710
6180
  {
5711
- name: "Incremented",
5712
- data: { amount: 1 },
5713
- pii: { email: "u@example.com" }
6181
+ stream: s,
6182
+ msgs: [
6183
+ {
6184
+ name: "Incremented",
6185
+ data: { amount: 1 },
6186
+ pii: { email: "u@example.com" }
6187
+ }
6188
+ ]
5714
6189
  }
5715
6190
  ],
5716
6191
  make_meta({ stream: s })
@@ -5725,23 +6200,31 @@ var runStoreTck = (options) => {
5725
6200
  const sA = `pii-iso-a-${uid()}`;
5726
6201
  const sB = `pii-iso-b-${uid()}`;
5727
6202
  await store.commit(
5728
- sA,
5729
6203
  [
5730
6204
  {
5731
- name: "Incremented",
5732
- data: { amount: 1 },
5733
- pii: { email: "alice@example.com" }
6205
+ stream: sA,
6206
+ msgs: [
6207
+ {
6208
+ name: "Incremented",
6209
+ data: { amount: 1 },
6210
+ pii: { email: "alice@example.com" }
6211
+ }
6212
+ ]
5734
6213
  }
5735
6214
  ],
5736
6215
  make_meta({ stream: sA })
5737
6216
  );
5738
6217
  await store.commit(
5739
- sB,
5740
6218
  [
5741
6219
  {
5742
- name: "Incremented",
5743
- data: { amount: 1 },
5744
- pii: { email: "bob@example.com" }
6220
+ stream: sB,
6221
+ msgs: [
6222
+ {
6223
+ name: "Incremented",
6224
+ data: { amount: 1 },
6225
+ pii: { email: "bob@example.com" }
6226
+ }
6227
+ ]
5745
6228
  }
5746
6229
  ],
5747
6230
  make_meta({ stream: sB })
@@ -5767,8 +6250,7 @@ var runStoreTck = (options) => {
5767
6250
  (0, import_vitest9.it)("forget_pii on a stream with no pii events returns 0", async () => {
5768
6251
  const s = `pii-forget-empty-${uid()}`;
5769
6252
  await store.commit(
5770
- s,
5771
- [inc(1)],
6253
+ [{ stream: s, msgs: [inc(1)] }],
5772
6254
  make_meta({ stream: s })
5773
6255
  );
5774
6256
  const wiped = await store.forget_pii.call(store, s);
@@ -5793,8 +6275,7 @@ var runStoreTck = (options) => {
5793
6275
  try {
5794
6276
  const stream = `notify-${uid()}`;
5795
6277
  await writer.commit(
5796
- stream,
5797
- [inc(1)],
6278
+ [{ stream, msgs: [inc(1)] }],
5798
6279
  make_meta({ stream })
5799
6280
  );
5800
6281
  await arrived;
@@ -5822,18 +6303,15 @@ var runStoreTck = (options) => {
5822
6303
  const writer = await options.factory();
5823
6304
  try {
5824
6305
  await store.commit(
5825
- own,
5826
- [inc(1)],
6306
+ [{ stream: own, msgs: [inc(1)] }],
5827
6307
  make_meta({ stream: own })
5828
6308
  );
5829
6309
  await writer.commit(
5830
- remote,
5831
- [inc(1)],
6310
+ [{ stream: remote, msgs: [inc(1)] }],
5832
6311
  make_meta({ stream: remote })
5833
6312
  );
5834
6313
  await writer.commit(
5835
- sentinel,
5836
- [inc(1)],
6314
+ [{ stream: sentinel, msgs: [inc(1)] }],
5837
6315
  make_meta({ stream: sentinel })
5838
6316
  );
5839
6317
  await sentinel_arrived;
@@ -5845,7 +6323,7 @@ var runStoreTck = (options) => {
5845
6323
  await Promise.resolve(disposer());
5846
6324
  }
5847
6325
  });
5848
- (0, import_vitest9.it)("delivers one notification per commit transaction carrying the full event batch", async () => {
6326
+ (0, import_vitest9.it)("delivers one notification carrying a stream's full batch from one commit", async () => {
5849
6327
  const received = [];
5850
6328
  let resolve_sentinel;
5851
6329
  const sentinel_arrived = new Promise((res) => {
@@ -5860,13 +6338,11 @@ var runStoreTck = (options) => {
5860
6338
  const writer = await options.factory();
5861
6339
  try {
5862
6340
  await writer.commit(
5863
- batch,
5864
- [inc(1), inc(2), inc(3)],
6341
+ [{ stream: batch, msgs: [inc(1), inc(2), inc(3)] }],
5865
6342
  make_meta({ stream: batch })
5866
6343
  );
5867
6344
  await writer.commit(
5868
- sentinel,
5869
- [inc(1)],
6345
+ [{ stream: sentinel, msgs: [inc(1)] }],
5870
6346
  make_meta({ stream: sentinel })
5871
6347
  );
5872
6348
  await sentinel_arrived;
@@ -5889,6 +6365,45 @@ var runStoreTck = (options) => {
5889
6365
  await Promise.resolve(disposer());
5890
6366
  }
5891
6367
  });
6368
+ (0, import_vitest9.it)("delivers one notification per stream a commit appends to, with that stream's events", async () => {
6369
+ const received = [];
6370
+ let resolve_sentinel;
6371
+ const sentinel_arrived = new Promise((res) => {
6372
+ resolve_sentinel = res;
6373
+ });
6374
+ const a = `notify-across-a-${uid()}`;
6375
+ const b = `notify-across-b-${uid()}`;
6376
+ const sentinel = `notify-across-sentinel-${uid()}`;
6377
+ const disposer = await store.notify.call(store, (n) => {
6378
+ received.push(n);
6379
+ if (n.stream === sentinel) resolve_sentinel();
6380
+ });
6381
+ const writer = await options.factory();
6382
+ try {
6383
+ const committed = await writer.commit(
6384
+ [
6385
+ { stream: a, msgs: [inc(1), inc(2)] },
6386
+ { stream: b, msgs: [dec(3)] }
6387
+ ],
6388
+ make_meta({ stream: a })
6389
+ );
6390
+ await writer.commit(
6391
+ [{ stream: sentinel, msgs: [inc(1)] }],
6392
+ make_meta({ stream: sentinel })
6393
+ );
6394
+ await sentinel_arrived;
6395
+ for (const stream of [a, b]) {
6396
+ const of_stream = received.filter((n) => n.stream === stream);
6397
+ (0, import_vitest9.expect)(of_stream).toHaveLength(1);
6398
+ (0, import_vitest9.expect)(of_stream[0].events.map((e) => e.id)).toEqual(
6399
+ committed.filter((e) => e.stream === stream).map((e) => e.id)
6400
+ );
6401
+ }
6402
+ } finally {
6403
+ await writer.dispose();
6404
+ await Promise.resolve(disposer());
6405
+ }
6406
+ });
5892
6407
  });
5893
6408
  }
5894
6409
  });