@rotorsoft/act-tck 1.17.0 → 1.18.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.js CHANGED
@@ -1,5 +1,139 @@
1
+ // src/cache-differential-tck.ts
2
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
3
+
4
+ // src/fixtures/helpers.ts
5
+ import { randomUUID } from "crypto";
6
+ var uid = () => randomUUID().slice(0, 8);
7
+ var actor = (name = "tester") => ({ id: randomUUID(), name });
8
+ var make_meta = (opts = {}) => ({
9
+ correlation: opts.correlation ?? randomUUID(),
10
+ causation: opts.stream ? {
11
+ action: {
12
+ name: opts.action ?? "Test",
13
+ stream: opts.stream,
14
+ actor: actor()
15
+ }
16
+ } : {}
17
+ });
18
+ var inc = (amount = 1) => ({
19
+ name: "Incremented",
20
+ data: { amount }
21
+ });
22
+ var dec = (amount = 1) => ({
23
+ name: "Decremented",
24
+ data: { amount }
25
+ });
26
+ var reset = () => ({ name: "Reset", data: {} });
27
+ var seed_stream = async (store, stream, count, correlation) => {
28
+ const out = [];
29
+ for (let i = 0; i < count; i++) {
30
+ const committed = await store.commit(
31
+ stream,
32
+ [inc(1)],
33
+ make_meta({ correlation, stream })
34
+ );
35
+ out.push(...committed);
36
+ }
37
+ return out;
38
+ };
39
+ var collect = async (store, query) => {
40
+ const out = [];
41
+ await store.query((e) => {
42
+ out.push(e);
43
+ }, query);
44
+ return out;
45
+ };
46
+
47
+ // src/cache-differential-tck.ts
48
+ var mulberry32 = (seed) => {
49
+ let a = seed >>> 0;
50
+ return () => {
51
+ a = a + 1831565813 | 0;
52
+ let t = Math.imul(a ^ a >>> 15, 1 | a);
53
+ t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
54
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
55
+ };
56
+ };
57
+ var build_cache_plan = (seed, stream_count) => {
58
+ const rng = mulberry32(seed);
59
+ const prefix = `cdiff-${uid()}-`;
60
+ const streams = Array.from(
61
+ { length: stream_count },
62
+ (_, i) => `${prefix}${i}`
63
+ );
64
+ const make_entry = () => {
65
+ const v = Math.floor(rng() * 1e3);
66
+ return {
67
+ state: { count: v, label: `k${v % 7}` },
68
+ version: v,
69
+ event_id: v,
70
+ patches: 1 + Math.floor(rng() * 5),
71
+ snaps: Math.floor(rng() * 3)
72
+ };
73
+ };
74
+ const pick_stream = () => streams[Math.floor(rng() * streams.length)];
75
+ const ops = [];
76
+ for (const stream of streams)
77
+ ops.push({ t: "set", stream, entry: make_entry() });
78
+ const middle = 6 + Math.floor(rng() * 14);
79
+ for (let i = 0; i < middle; i++) {
80
+ const kind = Math.floor(rng() * 3);
81
+ if (kind === 0)
82
+ ops.push({ t: "set", stream: pick_stream(), entry: make_entry() });
83
+ else if (kind === 1) ops.push({ t: "invalidate", stream: pick_stream() });
84
+ else ops.push({ t: "clear" });
85
+ }
86
+ return { streams, ops };
87
+ };
88
+ var apply_op = async (cache, op) => {
89
+ if (op.t === "set") await cache.set(op.stream, op.entry);
90
+ else if (op.t === "invalidate") await cache.invalidate(op.stream);
91
+ else await cache.clear();
92
+ };
93
+ var snapshot = async (cache, streams) => {
94
+ const out = {};
95
+ for (const stream of streams)
96
+ out[stream] = await cache.get(stream);
97
+ return out;
98
+ };
99
+ var runCacheDifferentialTck = (options) => {
100
+ describe(`TCK / Cache differential / ${options.name}`, () => {
101
+ const base_seed = options.seed ?? 3244;
102
+ const stream_count = options.streams ?? 6;
103
+ const plans = Array.from(
104
+ { length: options.runs ?? 8 },
105
+ (_, r) => build_cache_plan(base_seed + r, stream_count)
106
+ );
107
+ const live = [];
108
+ beforeAll(async () => {
109
+ for (const spec of options.caches) {
110
+ live.push({ name: spec.name, cache: await spec.factory() });
111
+ }
112
+ });
113
+ afterAll(async () => {
114
+ for (const { cache } of live) await cache.dispose();
115
+ });
116
+ plans.forEach((plan, run) => {
117
+ const seed_hex = `0x${(base_seed + run).toString(16)}`;
118
+ it(`agrees on get() after every op (workload ${run}, seed ${seed_hex})`, async () => {
119
+ for (const op of plan.ops) {
120
+ for (const { cache } of live) await apply_op(cache, op);
121
+ const reference = await snapshot(live[0].cache, plan.streams);
122
+ for (let i = 1; i < live.length; i++) {
123
+ const actual = await snapshot(live[i].cache, plan.streams);
124
+ expect(
125
+ actual,
126
+ `${live[i].name} diverged from ${live[0].name} after ${op.t}`
127
+ ).toEqual(reference);
128
+ }
129
+ }
130
+ });
131
+ });
132
+ });
133
+ };
134
+
1
135
  // src/cache-tck.ts
2
- import { afterEach, beforeEach as beforeEach2, describe, expect, it } from "vitest";
136
+ import { afterEach, beforeEach as beforeEach2, describe as describe2, expect as expect2, it as it2 } from "vitest";
3
137
  var entry = (event_id, state = {}) => ({
4
138
  state,
5
139
  version: event_id,
@@ -8,7 +142,7 @@ var entry = (event_id, state = {}) => ({
8
142
  snaps: 0
9
143
  });
10
144
  var runCacheTck = (options) => {
11
- describe(`TCK / Cache / ${options.name}`, () => {
145
+ describe2(`TCK / Cache / ${options.name}`, () => {
12
146
  let cache;
13
147
  beforeEach2(() => {
14
148
  cache = options.factory();
@@ -16,55 +150,55 @@ var runCacheTck = (options) => {
16
150
  afterEach(async () => {
17
151
  await cache.dispose();
18
152
  });
19
- it("returns undefined for an unset stream", async () => {
20
- expect(await cache.get("missing")).toBeUndefined();
153
+ it2("returns undefined for an unset stream", async () => {
154
+ expect2(await cache.get("missing")).toBeUndefined();
21
155
  });
22
- it("set then get round-trips an entry", async () => {
156
+ it2("set then get round-trips an entry", async () => {
23
157
  const e = entry(1, { count: 7 });
24
158
  await cache.set("s1", e);
25
- expect(await cache.get("s1")).toEqual(e);
159
+ expect2(await cache.get("s1")).toEqual(e);
26
160
  });
27
- it("set overwrites a prior entry on the same stream", async () => {
161
+ it2("set overwrites a prior entry on the same stream", async () => {
28
162
  await cache.set("s1", entry(1, { count: 1 }));
29
163
  await cache.set("s1", entry(2, { count: 2 }));
30
164
  const got = await cache.get("s1");
31
- expect(got?.event_id).toBe(2);
32
- expect(got?.state).toEqual({ count: 2 });
165
+ expect2(got?.event_id).toBe(2);
166
+ expect2(got?.state).toEqual({ count: 2 });
33
167
  });
34
- it("invalidate removes one stream and leaves others", async () => {
168
+ it2("invalidate removes one stream and leaves others", async () => {
35
169
  await cache.set("a", entry(1));
36
170
  await cache.set("b", entry(2));
37
171
  await cache.invalidate("a");
38
- expect(await cache.get("a")).toBeUndefined();
39
- expect(await cache.get("b")).toBeDefined();
172
+ expect2(await cache.get("a")).toBeUndefined();
173
+ expect2(await cache.get("b")).toBeDefined();
40
174
  });
41
- it("invalidate on an unknown stream is a no-op", async () => {
42
- await expect(cache.invalidate("never-set")).resolves.toBeUndefined();
175
+ it2("invalidate on an unknown stream is a no-op", async () => {
176
+ await expect2(cache.invalidate("never-set")).resolves.toBeUndefined();
43
177
  });
44
- it("clear empties every stream", async () => {
178
+ it2("clear empties every stream", async () => {
45
179
  await cache.set("a", entry(1));
46
180
  await cache.set("b", entry(2));
47
181
  await cache.set("c", entry(3));
48
182
  await cache.clear();
49
- expect(await cache.get("a")).toBeUndefined();
50
- expect(await cache.get("b")).toBeUndefined();
51
- expect(await cache.get("c")).toBeUndefined();
183
+ expect2(await cache.get("a")).toBeUndefined();
184
+ expect2(await cache.get("b")).toBeUndefined();
185
+ expect2(await cache.get("c")).toBeUndefined();
52
186
  });
53
- it("clear on an empty cache is a no-op", async () => {
54
- await expect(cache.clear()).resolves.toBeUndefined();
187
+ it2("clear on an empty cache is a no-op", async () => {
188
+ await expect2(cache.clear()).resolves.toBeUndefined();
55
189
  });
56
- it("entries are isolated per stream", async () => {
190
+ it2("entries are isolated per stream", async () => {
57
191
  const ea = entry(1, { id: "a" });
58
192
  const eb = entry(2, { id: "b" });
59
193
  await cache.set("a", ea);
60
194
  await cache.set("b", eb);
61
- expect(await cache.get("a")).toEqual(ea);
62
- expect(await cache.get("b")).toEqual(eb);
195
+ expect2(await cache.get("a")).toEqual(ea);
196
+ expect2(await cache.get("b")).toEqual(eb);
63
197
  });
64
- it("dispose is idempotent", async () => {
198
+ it2("dispose is idempotent", async () => {
65
199
  await cache.set("a", entry(1));
66
200
  await cache.dispose();
67
- await expect(cache.dispose()).resolves.toBeUndefined();
201
+ await expect2(cache.dispose()).resolves.toBeUndefined();
68
202
  });
69
203
  });
70
204
  };
@@ -85,105 +219,122 @@ var COUNTER_EVENT_NAMES = [
85
219
  "Reset"
86
220
  ];
87
221
 
88
- // src/fixtures/helpers.ts
89
- import { randomUUID } from "crypto";
90
- var uid = () => randomUUID().slice(0, 8);
91
- var actor = (name = "tester") => ({ id: randomUUID(), name });
92
- var make_meta = (opts = {}) => ({
93
- correlation: opts.correlation ?? randomUUID(),
94
- causation: opts.stream ? {
95
- action: {
96
- name: opts.action ?? "Test",
97
- stream: opts.stream,
98
- actor: actor()
99
- }
100
- } : {}
101
- });
102
- var inc = (amount = 1) => ({
103
- name: "Incremented",
104
- data: { amount }
105
- });
106
- var dec = (amount = 1) => ({
107
- name: "Decremented",
108
- data: { amount }
109
- });
110
- var reset = () => ({ name: "Reset", data: {} });
111
- var seed_stream = async (store, stream, count, correlation) => {
222
+ // src/logger-differential-tck.ts
223
+ import { afterEach as afterEach2, beforeEach as beforeEach3, describe as describe3, expect as expect3, it as it3 } from "vitest";
224
+ var LEVELS = ["fatal", "error", "warn", "info", "debug", "trace"];
225
+ var drive = (logger) => {
112
226
  const out = [];
113
- for (let i = 0; i < count; i++) {
114
- const committed = await store.commit(
115
- stream,
116
- [inc(1)],
117
- make_meta({ correlation, stream })
118
- );
119
- out.push(...committed);
227
+ const ok = (fn) => {
228
+ try {
229
+ fn();
230
+ out.push(true);
231
+ } catch {
232
+ out.push(false);
233
+ }
234
+ };
235
+ out.push(typeof logger.level === "string" && logger.level.length > 0);
236
+ for (const level of LEVELS) {
237
+ ok(() => logger[level]("message"));
238
+ ok(() => logger[level]({ k: "v", n: 1 }));
239
+ ok(() => logger[level]({ k: "v" }, "context"));
120
240
  }
241
+ ok(() => logger.info(null, "null payload"));
242
+ ok(() => {
243
+ const cyclic = { name: "loop" };
244
+ cyclic.self = cyclic;
245
+ logger.info(cyclic, "cycle");
246
+ });
247
+ const child = logger.child({ request_id: "abc" });
248
+ out.push(typeof child.level === "string" && child.level.length > 0);
249
+ out.push(LEVELS.every((level) => typeof child[level] === "function"));
250
+ out.push(typeof child.child === "function");
251
+ ok(() => child.child({ nested: true }).info("nested"));
121
252
  return out;
122
253
  };
123
- var collect = async (store, query) => {
124
- const out = [];
125
- await store.query((e) => {
126
- out.push(e);
127
- }, query);
128
- return out;
254
+ var runLoggerDifferentialTck = (options) => {
255
+ describe3(`TCK / Logger differential / ${options.name}`, () => {
256
+ let live = [];
257
+ let original_stdout;
258
+ beforeEach3(() => {
259
+ live = options.loggers.map((spec) => ({
260
+ name: spec.name,
261
+ logger: spec.factory()
262
+ }));
263
+ original_stdout = process.stdout.write.bind(process.stdout);
264
+ process.stdout.write = (() => true);
265
+ });
266
+ afterEach2(async () => {
267
+ process.stdout.write = original_stdout;
268
+ for (const { logger } of live) await logger.dispose();
269
+ });
270
+ it3("agrees on robustness and structural parity across the call surface", () => {
271
+ const reference = drive(live[0].logger);
272
+ for (let i = 1; i < live.length; i++) {
273
+ const actual = drive(live[i].logger);
274
+ expect3(actual, `${live[i].name} diverged from ${live[0].name}`).toEqual(
275
+ reference
276
+ );
277
+ }
278
+ });
279
+ });
129
280
  };
130
281
 
131
282
  // src/logger-tck.ts
132
- import { afterEach as afterEach2, beforeEach as beforeEach3, describe as describe2, expect as expect2, it as it2 } from "vitest";
133
- var LEVELS = ["fatal", "error", "warn", "info", "debug", "trace"];
283
+ import { afterEach as afterEach3, beforeEach as beforeEach4, describe as describe4, expect as expect4, it as it4 } from "vitest";
284
+ var LEVELS2 = ["fatal", "error", "warn", "info", "debug", "trace"];
134
285
  var runLoggerTck = (options) => {
135
- describe2(`TCK / Logger / ${options.name}`, () => {
286
+ describe4(`TCK / Logger / ${options.name}`, () => {
136
287
  let logger;
137
288
  let original_stdout;
138
- beforeEach3(() => {
289
+ beforeEach4(() => {
139
290
  logger = options.factory();
140
291
  original_stdout = process.stdout.write.bind(process.stdout);
141
292
  process.stdout.write = (() => true);
142
293
  });
143
- afterEach2(async () => {
294
+ afterEach3(async () => {
144
295
  process.stdout.write = original_stdout;
145
296
  await logger.dispose();
146
297
  });
147
- it2("exposes a non-empty `level` string", () => {
148
- expect2(typeof logger.level).toBe("string");
149
- expect2(logger.level.length).toBeGreaterThan(0);
298
+ it4("exposes a non-empty `level` string", () => {
299
+ expect4(typeof logger.level).toBe("string");
300
+ expect4(logger.level.length).toBeGreaterThan(0);
150
301
  });
151
- for (const level of LEVELS) {
152
- it2(`${level}(msg) does not throw`, () => {
153
- expect2(() => logger[level]("hello")).not.toThrow();
302
+ for (const level of LEVELS2) {
303
+ it4(`${level}(msg) does not throw`, () => {
304
+ expect4(() => logger[level]("hello")).not.toThrow();
154
305
  });
155
- it2(`${level}(obj) does not throw`, () => {
156
- expect2(() => logger[level]({ k: "v" })).not.toThrow();
306
+ it4(`${level}(obj) does not throw`, () => {
307
+ expect4(() => logger[level]({ k: "v" })).not.toThrow();
157
308
  });
158
- it2(`${level}(obj, msg) does not throw`, () => {
159
- expect2(() => logger[level]({ k: "v" }, "context")).not.toThrow();
309
+ it4(`${level}(obj, msg) does not throw`, () => {
310
+ expect4(() => logger[level]({ k: "v" }, "context")).not.toThrow();
160
311
  });
161
312
  }
162
- it2("accepts a null payload", () => {
163
- expect2(() => logger.info(null, "null payload")).not.toThrow();
313
+ it4("accepts a null payload", () => {
314
+ expect4(() => logger.info(null, "null payload")).not.toThrow();
164
315
  });
165
- it2("accepts a cyclic payload without throwing", () => {
316
+ it4("accepts a cyclic payload without throwing", () => {
166
317
  const cyclic = { name: "loop" };
167
318
  cyclic.self = cyclic;
168
- expect2(() => logger.info(cyclic, "cycle")).not.toThrow();
319
+ expect4(() => logger.info(cyclic, "cycle")).not.toThrow();
169
320
  });
170
- it2("child(bindings) returns a Logger satisfying the same contract", () => {
321
+ it4("child(bindings) returns a Logger satisfying the same contract", () => {
171
322
  const child = logger.child({ request_id: "abc" });
172
- expect2(typeof child.level).toBe("string");
173
- for (const level of LEVELS) {
174
- expect2(typeof child[level]).toBe("function");
323
+ expect4(typeof child.level).toBe("string");
324
+ for (const level of LEVELS2) {
325
+ expect4(typeof child[level]).toBe("function");
175
326
  }
176
- expect2(typeof child.child).toBe("function");
177
- expect2(typeof child.dispose).toBe("function");
327
+ expect4(typeof child.child).toBe("function");
328
+ expect4(typeof child.dispose).toBe("function");
178
329
  });
179
- it2("child loggers can themselves spawn children", () => {
330
+ it4("child loggers can themselves spawn children", () => {
180
331
  const c1 = logger.child({ a: 1 });
181
332
  const c2 = c1.child({ b: 2 });
182
- expect2(() => c2.info("nested")).not.toThrow();
333
+ expect4(() => c2.info("nested")).not.toThrow();
183
334
  });
184
- it2("dispose is idempotent and awaitable", async () => {
185
- await expect2(logger.dispose()).resolves.toBeUndefined();
186
- await expect2(logger.dispose()).resolves.toBeUndefined();
335
+ it4("dispose is idempotent and awaitable", async () => {
336
+ await expect4(logger.dispose()).resolves.toBeUndefined();
337
+ await expect4(logger.dispose()).resolves.toBeUndefined();
187
338
  });
188
339
  });
189
340
  };
@@ -191,14 +342,14 @@ var runLoggerTck = (options) => {
191
342
  // src/stability-tck.ts
192
343
  import { promises as fs } from "fs";
193
344
  import path from "path";
194
- import { describe as describe3, expect as expect3, it as it3 } from "vitest";
345
+ import { describe as describe5, expect as expect5, it as it5 } from "vitest";
195
346
  function runStabilityTck(options) {
196
- describe3(`${options.name} \u2014 public API stability`, () => {
347
+ describe5(`${options.name} \u2014 public API stability`, () => {
197
348
  for (const [subpath, entry2] of Object.entries(options.entryPoints)) {
198
349
  const label = subpath || "(root)";
199
- it3(`stable public surface for ${label}`, async () => {
350
+ it5(`stable public surface for ${label}`, async () => {
200
351
  const surface = await load_surface(entry2);
201
- expect3(surface).toMatchSnapshot();
352
+ expect5(surface).toMatchSnapshot();
202
353
  });
203
354
  }
204
355
  });
@@ -228,9 +379,220 @@ ${content}`;
228
379
  }).join("\n");
229
380
  }
230
381
 
382
+ // src/store-differential-tck.ts
383
+ import { SNAP_EVENT } from "@rotorsoft/act";
384
+ import { afterAll as afterAll2, beforeAll as beforeAll2, describe as describe6, expect as expect6, it as it6 } from "vitest";
385
+ var mulberry322 = (seed) => {
386
+ let a = seed >>> 0;
387
+ return () => {
388
+ a = a + 1831565813 | 0;
389
+ let t = Math.imul(a ^ a >>> 15, 1 | a);
390
+ t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
391
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
392
+ };
393
+ };
394
+ var normalize_event = (e) => ({
395
+ stream: e.stream,
396
+ version: e.version,
397
+ name: e.name,
398
+ data: e.data
399
+ });
400
+ var build_plan = (seed, stream_count) => {
401
+ const rng = mulberry322(seed);
402
+ const tag = uid();
403
+ const event_prefix = `diff-${tag}-evt-`;
404
+ const sub_prefix = `diff-${tag}-sub-`;
405
+ const event_streams = Array.from(
406
+ { length: stream_count },
407
+ (_, i) => `${event_prefix}${i}`
408
+ );
409
+ let type_cursor = 0;
410
+ const next_msg = () => {
411
+ const kind = type_cursor++ % 3;
412
+ const amount = 1 + Math.floor(rng() * 9);
413
+ return kind === 0 ? inc(amount) : kind === 1 ? dec(amount) : reset();
414
+ };
415
+ const batch = () => Array.from({ length: 1 + Math.floor(rng() * 3) }, next_msg);
416
+ const pick_stream = () => event_streams[Math.floor(rng() * event_streams.length)];
417
+ const ops = [];
418
+ for (const stream of event_streams)
419
+ ops.push({ t: "commit", stream, msgs: batch() });
420
+ const middle = 8 + Math.floor(rng() * 16);
421
+ for (let i = 0; i < middle; i++) {
422
+ const stream = pick_stream();
423
+ const kind = Math.floor(rng() * 3);
424
+ if (kind === 0) ops.push({ t: "commit", stream, msgs: batch() });
425
+ else if (kind === 1)
426
+ ops.push({ t: "snapshot", stream, count: Math.floor(rng() * 1e3) });
427
+ else ops.push({ t: "truncate", stream, count: Math.floor(rng() * 1e3) });
428
+ }
429
+ for (const stream of event_streams)
430
+ ops.push({ t: "commit", stream, msgs: batch() });
431
+ const lanes = ["default", "slow", "fast"];
432
+ const subs = event_streams.map((source, i) => ({
433
+ stream: `${sub_prefix}${i}`,
434
+ source,
435
+ lane: lanes[i % lanes.length],
436
+ priority: i % 4
437
+ }));
438
+ return { event_prefix, event_streams, sub_prefix, ops, subs };
439
+ };
440
+ var apply_plan = async (store, plan) => {
441
+ for (const op of plan.ops) {
442
+ if (op.t === "commit") {
443
+ await store.commit(
444
+ op.stream,
445
+ op.msgs,
446
+ make_meta({ stream: op.stream })
447
+ );
448
+ } else if (op.t === "snapshot") {
449
+ await store.commit(
450
+ op.stream,
451
+ [{ name: SNAP_EVENT, data: { count: op.count } }],
452
+ make_meta({ stream: op.stream })
453
+ );
454
+ } else {
455
+ await store.truncate([
456
+ { stream: op.stream, snapshot: { count: op.count } }
457
+ ]);
458
+ }
459
+ }
460
+ await store.subscribe(
461
+ plan.subs.map((s) => ({
462
+ stream: s.stream,
463
+ source: s.source,
464
+ lane: s.lane,
465
+ priority: s.priority
466
+ }))
467
+ );
468
+ };
469
+ var runStoreDifferentialTck = (options) => {
470
+ describe6(`TCK / Store differential / ${options.name}`, () => {
471
+ const base_seed = options.seed ?? 2759;
472
+ const stream_count = options.streams ?? 4;
473
+ const plans = Array.from(
474
+ { length: options.runs ?? 8 },
475
+ (_, r) => build_plan(base_seed + r, stream_count)
476
+ );
477
+ const live = [];
478
+ beforeAll2(async () => {
479
+ for (const spec of options.stores) {
480
+ const store = await spec.factory();
481
+ await store.drop();
482
+ await store.seed();
483
+ for (const plan of plans) await apply_plan(store, plan);
484
+ live.push({ name: spec.name, store });
485
+ }
486
+ });
487
+ afterAll2(async () => {
488
+ for (const { store } of live) await store.dispose();
489
+ });
490
+ const assert_identical = async (label, produce) => {
491
+ const reference = await produce(live[0].store);
492
+ for (let i = 1; i < live.length; i++) {
493
+ const actual = await produce(live[i].store);
494
+ expect6(
495
+ actual,
496
+ `${live[i].name} diverged from ${live[0].name} on "${label}"`
497
+ ).toEqual(reference);
498
+ }
499
+ };
500
+ plans.forEach((plan, run) => {
501
+ const seed_hex = `0x${(base_seed + run).toString(16)}`;
502
+ describe6(`workload ${run} (seed ${seed_hex})`, () => {
503
+ it6("yields identical event order under a global forward query", async () => {
504
+ await assert_identical("forward query", async (store) => {
505
+ const out = [];
506
+ await store.query(
507
+ (e) => {
508
+ out.push(normalize_event(e));
509
+ },
510
+ { stream: `^${plan.event_prefix}` }
511
+ );
512
+ return out;
513
+ });
514
+ });
515
+ it6("yields identical snapshot floors under with_snaps", async () => {
516
+ await assert_identical("with_snaps floor", async (store) => {
517
+ const by_stream = {};
518
+ for (const stream of plan.event_streams) {
519
+ const out = [];
520
+ await store.query(
521
+ (e) => {
522
+ out.push(normalize_event(e));
523
+ },
524
+ { stream, stream_exact: true, with_snaps: true }
525
+ );
526
+ by_stream[stream] = out;
527
+ }
528
+ return by_stream;
529
+ });
530
+ });
531
+ it6("yields identical order under backward traversal", async () => {
532
+ await assert_identical("backward query", async (store) => {
533
+ const by_stream = {};
534
+ for (const stream of plan.event_streams) {
535
+ const out = [];
536
+ await store.query(
537
+ (e) => {
538
+ out.push(normalize_event(e));
539
+ },
540
+ { stream, stream_exact: true, backward: true }
541
+ );
542
+ by_stream[stream] = out;
543
+ }
544
+ return by_stream;
545
+ });
546
+ });
547
+ it6("yields identical query_stats output (head/tail/count/names)", async () => {
548
+ await assert_identical("query_stats", async (store) => {
549
+ const stats = await store.query_stats(
550
+ { stream: `^${plan.event_prefix}` },
551
+ { tail: true, count: true, names: true }
552
+ );
553
+ const keys = [...stats.keys()];
554
+ const content = {};
555
+ for (const [stream, s] of stats) {
556
+ content[stream] = {
557
+ head: normalize_event(s.head),
558
+ tail: normalize_event(
559
+ s.tail
560
+ ),
561
+ count: s.count,
562
+ names: s.names
563
+ };
564
+ }
565
+ return { keys, content };
566
+ });
567
+ });
568
+ it6("yields identical query_streams output", async () => {
569
+ await assert_identical("query_streams", async (store) => {
570
+ const rows = [];
571
+ const { count } = await store.query_streams(
572
+ (p) => {
573
+ rows.push({
574
+ stream: p.stream,
575
+ source: p.source,
576
+ at: p.at,
577
+ blocked: p.blocked,
578
+ priority: p.priority,
579
+ lane: p.lane
580
+ });
581
+ },
582
+ { stream: `^${plan.sub_prefix}`, limit: 1e3 }
583
+ );
584
+ rows.sort((a, b) => a.stream.localeCompare(b.stream));
585
+ return { count, rows };
586
+ });
587
+ });
588
+ });
589
+ });
590
+ });
591
+ };
592
+
231
593
  // src/store-property-tck.ts
232
594
  import { fc, test } from "@fast-check/vitest";
233
- import { afterAll, beforeAll, describe as describe4, expect as expect4 } from "vitest";
595
+ import { afterAll as afterAll3, beforeAll as beforeAll3, describe as describe7, expect as expect7 } from "vitest";
234
596
  var streamArb = fc.constantFrom("s1", "s2", "s3");
235
597
  var commitArb = fc.record({
236
598
  stream: streamArb,
@@ -246,20 +608,20 @@ var opArb = fc.oneof(
246
608
  var events = (count) => Array.from({ length: count }, () => inc(1));
247
609
  var runStorePropertyTck = (options) => {
248
610
  const numRuns = options.numRuns ?? 100;
249
- describe4(`TCK / Store properties / ${options.name}`, () => {
611
+ describe7(`TCK / Store properties / ${options.name}`, () => {
250
612
  let store;
251
- beforeAll(async () => {
613
+ beforeAll3(async () => {
252
614
  store = await options.factory();
253
615
  await store.seed();
254
616
  });
255
- afterAll(async () => {
617
+ afterAll3(async () => {
256
618
  await store.dispose();
257
619
  });
258
620
  const reset2 = async () => {
259
621
  await store.drop();
260
622
  await store.seed();
261
623
  };
262
- describe4("commit version invariants", () => {
624
+ describe7("commit version invariants", () => {
263
625
  test.prop([fc.array(commitArb, { minLength: 0, maxLength: 30 })], {
264
626
  numRuns
265
627
  })(
@@ -275,14 +637,14 @@ var runStorePropertyTck = (options) => {
275
637
  make_meta({ stream })
276
638
  );
277
639
  committed.forEach((e, i) => {
278
- expect4(e.version).toBe(before + 1 + i);
640
+ expect7(e.version).toBe(before + 1 + i);
279
641
  });
280
642
  expected.set(stream, before + count);
281
643
  }
282
644
  for (const stream of new Set(commits.map((c) => c.stream))) {
283
645
  const seen = await collect(store, { stream, stream_exact: true });
284
646
  seen.forEach((e, i) => {
285
- expect4(e.version).toBe(i);
647
+ expect7(e.version).toBe(i);
286
648
  });
287
649
  }
288
650
  }
@@ -302,7 +664,7 @@ var runStorePropertyTck = (options) => {
302
664
  }
303
665
  const stream = commits[0].stream;
304
666
  const before = await collect(store, { stream, stream_exact: true });
305
- await expect4(
667
+ await expect7(
306
668
  store.commit(
307
669
  stream,
308
670
  [inc(1)],
@@ -311,11 +673,11 @@ var runStorePropertyTck = (options) => {
311
673
  )
312
674
  ).rejects.toThrow();
313
675
  const after = await collect(store, { stream, stream_exact: true });
314
- expect4(after.length).toBe(before.length);
676
+ expect7(after.length).toBe(before.length);
315
677
  }
316
678
  );
317
679
  });
318
- describe4("claim/lease lifecycle invariants", () => {
680
+ describe7("claim/lease lifecycle invariants", () => {
319
681
  test.prop([fc.array(opArb, { minLength: 1, maxLength: 30 })], {
320
682
  numRuns
321
683
  })(
@@ -357,7 +719,7 @@ var runStorePropertyTck = (options) => {
357
719
  );
358
720
  }
359
721
  }
360
- expect4(totalResolved + pending.length).toBe(totalClaims);
722
+ expect7(totalResolved + pending.length).toBe(totalClaims);
361
723
  }
362
724
  );
363
725
  test.prop(
@@ -395,7 +757,7 @@ var runStorePropertyTck = (options) => {
395
757
  await store.claim(10, 10, "worker", 6e4)
396
758
  );
397
759
  for (const lease of acked2) {
398
- expect4(lease.at).toBeGreaterThanOrEqual(
760
+ expect7(lease.at).toBeGreaterThanOrEqual(
399
761
  watermark1.get(lease.stream)
400
762
  );
401
763
  }
@@ -424,7 +786,7 @@ var runStorePropertyTck = (options) => {
424
786
  make_meta({ stream: "ctrl" })
425
787
  );
426
788
  const reclaim = await store.claim(10, 10, "worker2", 6e4);
427
- for (const l of reclaim) expect4(blockedSet.has(l.stream)).toBe(false);
789
+ for (const l of reclaim) expect7(blockedSet.has(l.stream)).toBe(false);
428
790
  });
429
791
  });
430
792
  });
@@ -435,41 +797,41 @@ import {
435
797
  act,
436
798
  ConcurrencyError,
437
799
  InMemoryCache,
438
- SNAP_EVENT,
800
+ SNAP_EVENT as SNAP_EVENT2,
439
801
  TOMBSTONE_EVENT
440
802
  } from "@rotorsoft/act";
441
- import { afterAll as afterAll2, beforeAll as beforeAll2, describe as describe5, expect as expect5, it as it4 } from "vitest";
803
+ import { afterAll as afterAll4, beforeAll as beforeAll4, describe as describe8, expect as expect8, it as it7 } from "vitest";
442
804
  var runStoreTck = (options) => {
443
- describe5(`TCK / Store / ${options.name}`, () => {
805
+ describe8(`TCK / Store / ${options.name}`, () => {
444
806
  let store;
445
807
  const caps = { ...options.capabilities };
446
- beforeAll2(async () => {
808
+ beforeAll4(async () => {
447
809
  store = await options.factory();
448
810
  await store.drop();
449
811
  await store.seed();
450
812
  });
451
- afterAll2(async () => {
813
+ afterAll4(async () => {
452
814
  await store.dispose();
453
815
  });
454
- describe5("commit", () => {
455
- it4("returns committed events with sequenced ids and versions", async () => {
816
+ describe8("commit", () => {
817
+ it7("returns committed events with sequenced ids and versions", async () => {
456
818
  const s = `commit-seq-${uid()}`;
457
819
  const committed = await store.commit(
458
820
  s,
459
821
  [inc(1), inc(2), dec(3)],
460
822
  make_meta({ stream: s })
461
823
  );
462
- expect5(committed).toHaveLength(3);
463
- expect5(committed[0].version).toBe(0);
464
- expect5(committed[1].version).toBe(1);
465
- expect5(committed[2].version).toBe(2);
466
- expect5(committed[0].name).toBe("Incremented");
467
- expect5(committed[2].data).toEqual({ amount: 3 });
824
+ expect8(committed).toHaveLength(3);
825
+ expect8(committed[0].version).toBe(0);
826
+ expect8(committed[1].version).toBe(1);
827
+ expect8(committed[2].version).toBe(2);
828
+ expect8(committed[0].name).toBe("Incremented");
829
+ expect8(committed[2].data).toEqual({ amount: 3 });
468
830
  for (let i = 1; i < committed.length; i++) {
469
- expect5(committed[i].id).toBeGreaterThan(committed[i - 1].id);
831
+ expect8(committed[i].id).toBeGreaterThan(committed[i - 1].id);
470
832
  }
471
833
  });
472
- it4("attaches correlation and stream metadata", async () => {
834
+ it7("attaches correlation and stream metadata", async () => {
473
835
  const s = `commit-meta-${uid()}`;
474
836
  const correlation = `cor-${uid()}`;
475
837
  const committed = await store.commit(
@@ -477,10 +839,10 @@ var runStoreTck = (options) => {
477
839
  [inc(1)],
478
840
  make_meta({ stream: s, correlation })
479
841
  );
480
- expect5(committed[0].stream).toBe(s);
481
- expect5(committed[0].meta.correlation).toBe(correlation);
842
+ expect8(committed[0].stream).toBe(s);
843
+ expect8(committed[0].meta.correlation).toBe(correlation);
482
844
  });
483
- it4("throws ConcurrencyError when expectedVersion is wrong", async () => {
845
+ it7("throws ConcurrencyError when expectedVersion is wrong", async () => {
484
846
  const s = `commit-cc-${uid()}`;
485
847
  await store.commit(
486
848
  s,
@@ -493,26 +855,26 @@ var runStoreTck = (options) => {
493
855
  make_meta({ stream: s }),
494
856
  0
495
857
  );
496
- await expect5(
858
+ await expect8(
497
859
  store.commit(s, [inc(1)], make_meta({ stream: s }), 0)
498
860
  ).rejects.toBeInstanceOf(ConcurrencyError);
499
861
  });
500
- it4("preserves prior events when a concurrent commit is rejected", async () => {
862
+ it7("preserves prior events when a concurrent commit is rejected", async () => {
501
863
  const s = `commit-cc-preserve-${uid()}`;
502
864
  await store.commit(
503
865
  s,
504
866
  [inc(1), inc(2)],
505
867
  make_meta({ stream: s })
506
868
  );
507
- await expect5(
869
+ await expect8(
508
870
  store.commit(s, [inc(3)], make_meta({ stream: s }), 0)
509
871
  ).rejects.toBeInstanceOf(ConcurrencyError);
510
872
  const found = await collect(store, { stream: s, stream_exact: true });
511
- expect5(found).toHaveLength(2);
873
+ expect8(found).toHaveLength(2);
512
874
  });
513
875
  });
514
- describe5("query", () => {
515
- it4("filters by stream, names, correlation, limit, with_snaps", async () => {
876
+ describe8("query", () => {
877
+ it7("filters by stream, names, correlation, limit, with_snaps", async () => {
516
878
  const s1 = `q-s1-${uid()}`;
517
879
  const s2 = `q-s2-${uid()}`;
518
880
  const cor = `q-cor-${uid()}`;
@@ -530,23 +892,23 @@ var runStoreTck = (options) => {
530
892
  stream: s1,
531
893
  stream_exact: true
532
894
  });
533
- expect5(by_stream).toHaveLength(2);
895
+ expect8(by_stream).toHaveLength(2);
534
896
  const by_name = await collect(store, {
535
897
  stream: s2,
536
898
  stream_exact: true,
537
899
  names: ["Reset"]
538
900
  });
539
- expect5(by_name).toHaveLength(1);
540
- expect5(by_name[0].name).toBe("Reset");
901
+ expect8(by_name).toHaveLength(1);
902
+ expect8(by_name[0].name).toBe("Reset");
541
903
  const by_correlation = await collect(store, { correlation: cor });
542
- expect5(by_correlation).toHaveLength(5);
904
+ expect8(by_correlation).toHaveLength(5);
543
905
  const limited = await collect(store, {
544
906
  correlation: cor,
545
907
  limit: 2
546
908
  });
547
- expect5(limited).toHaveLength(2);
909
+ expect8(limited).toHaveLength(2);
548
910
  });
549
- it4("with_snaps resumes from the latest snapshot per stream", async () => {
911
+ it7("with_snaps resumes from the latest snapshot per stream", async () => {
550
912
  const s = `q-snap-${uid()}`;
551
913
  await store.commit(
552
914
  s,
@@ -555,7 +917,7 @@ var runStoreTck = (options) => {
555
917
  );
556
918
  const [snap] = await store.commit(
557
919
  s,
558
- [{ name: SNAP_EVENT, data: { count: 2 } }],
920
+ [{ name: SNAP_EVENT2, data: { count: 2 } }],
559
921
  make_meta({ stream: s })
560
922
  );
561
923
  await store.commit(
@@ -568,17 +930,17 @@ var runStoreTck = (options) => {
568
930
  stream_exact: true,
569
931
  with_snaps: true
570
932
  });
571
- expect5(from_snap).toHaveLength(4);
572
- expect5(from_snap[0].name).toBe(SNAP_EVENT);
933
+ expect8(from_snap).toHaveLength(4);
934
+ expect8(from_snap[0].name).toBe(SNAP_EVENT2);
573
935
  const domain = await collect(store, { stream: s, stream_exact: true });
574
- expect5(domain).toHaveLength(5);
936
+ expect8(domain).toHaveLength(5);
575
937
  const after_snap = await collect(store, {
576
938
  stream: s,
577
939
  stream_exact: true,
578
940
  with_snaps: true,
579
941
  after: snap.id
580
942
  });
581
- expect5(after_snap).toHaveLength(3);
943
+ expect8(after_snap).toHaveLength(3);
582
944
  const s2 = `q-nosnap-${uid()}`;
583
945
  await store.commit(
584
946
  s2,
@@ -590,9 +952,9 @@ var runStoreTck = (options) => {
590
952
  stream_exact: true,
591
953
  with_snaps: true
592
954
  });
593
- expect5(full).toHaveLength(2);
955
+ expect8(full).toHaveLength(2);
594
956
  });
595
- it4("supports backward traversal", async () => {
957
+ it7("supports backward traversal", async () => {
596
958
  const s = `q-back-${uid()}`;
597
959
  const committed = await store.commit(
598
960
  s,
@@ -605,8 +967,8 @@ var runStoreTck = (options) => {
605
967
  stream_exact: true,
606
968
  backward: true
607
969
  });
608
- expect5(forward.map((e) => e.id)).toEqual(committed.map((c) => c.id));
609
- expect5(backward.map((e) => e.id)).toEqual(
970
+ expect8(forward.map((e) => e.id)).toEqual(committed.map((c) => c.id));
971
+ expect8(backward.map((e) => e.id)).toEqual(
610
972
  [...committed].reverse().map((c) => c.id)
611
973
  );
612
974
  const latest = await collect(store, {
@@ -615,10 +977,10 @@ var runStoreTck = (options) => {
615
977
  backward: true,
616
978
  limit: 1
617
979
  });
618
- expect5(latest).toHaveLength(1);
619
- expect5(latest[0].id).toBe(committed.at(-1).id);
980
+ expect8(latest).toHaveLength(1);
981
+ expect8(latest[0].id).toBe(committed.at(-1).id);
620
982
  });
621
- it4("after/before bound the id range", async () => {
983
+ it7("after/before bound the id range", async () => {
622
984
  const s = `q-bounds-${uid()}`;
623
985
  const committed = await store.commit(
624
986
  s,
@@ -630,7 +992,7 @@ var runStoreTck = (options) => {
630
992
  stream_exact: true,
631
993
  after: committed[0].id
632
994
  });
633
- expect5(after_first.map((e) => e.id)).toEqual(
995
+ expect8(after_first.map((e) => e.id)).toEqual(
634
996
  committed.slice(1).map((c) => c.id)
635
997
  );
636
998
  const before_last = await collect(store, {
@@ -638,11 +1000,11 @@ var runStoreTck = (options) => {
638
1000
  stream_exact: true,
639
1001
  before: committed[committed.length - 1].id
640
1002
  });
641
- expect5(before_last.map((e) => e.id)).toEqual(
1003
+ expect8(before_last.map((e) => e.id)).toEqual(
642
1004
  committed.slice(0, -1).map((c) => c.id)
643
1005
  );
644
1006
  });
645
- it4("created_after/created_before filter by timestamp", async () => {
1007
+ it7("created_after/created_before filter by timestamp", async () => {
646
1008
  const s = `q-ts-${uid()}`;
647
1009
  const committed = await store.commit(
648
1010
  s,
@@ -658,15 +1020,15 @@ var runStoreTck = (options) => {
658
1020
  created_after: before,
659
1021
  created_before: future
660
1022
  });
661
- expect5(in_window.length).toBe(1);
1023
+ expect8(in_window.length).toBe(1);
662
1024
  const out_of_window = await collect(store, {
663
1025
  stream: s,
664
1026
  stream_exact: true,
665
1027
  created_after: future
666
1028
  });
667
- expect5(out_of_window.length).toBe(0);
1029
+ expect8(out_of_window.length).toBe(0);
668
1030
  });
669
- it4("backward traversal short-circuits at `after` id boundary", async () => {
1031
+ it7("backward traversal short-circuits at `after` id boundary", async () => {
670
1032
  const s = `q-back-after-${uid()}`;
671
1033
  const committed = await store.commit(
672
1034
  s,
@@ -679,12 +1041,12 @@ var runStoreTck = (options) => {
679
1041
  backward: true,
680
1042
  after: committed[0].id
681
1043
  });
682
- expect5(got.map((e) => e.id)).toEqual([
1044
+ expect8(got.map((e) => e.id)).toEqual([
683
1045
  committed[2].id,
684
1046
  committed[1].id
685
1047
  ]);
686
1048
  });
687
- it4("backward traversal short-circuits at `created_after` boundary", async () => {
1049
+ it7("backward traversal short-circuits at `created_after` boundary", async () => {
688
1050
  const s = `q-back-cafter-${uid()}`;
689
1051
  await store.commit(
690
1052
  s,
@@ -698,9 +1060,9 @@ var runStoreTck = (options) => {
698
1060
  backward: true,
699
1061
  created_after: future
700
1062
  });
701
- expect5(got).toHaveLength(0);
1063
+ expect8(got).toHaveLength(0);
702
1064
  });
703
- it4("backward traversal honors created_before by skipping newer events", async () => {
1065
+ it7("backward traversal honors created_before by skipping newer events", async () => {
704
1066
  const s = `q-back-ts-${uid()}`;
705
1067
  const committed = await store.commit(
706
1068
  s,
@@ -714,9 +1076,9 @@ var runStoreTck = (options) => {
714
1076
  backward: true,
715
1077
  created_before: past
716
1078
  });
717
- expect5(got).toHaveLength(0);
1079
+ expect8(got).toHaveLength(0);
718
1080
  });
719
- it4("stream_exact disables regex matching", async () => {
1081
+ it7("stream_exact disables regex matching", async () => {
720
1082
  const tag = uid();
721
1083
  const a = `q-exact-${tag}`;
722
1084
  const b = `q-exact-${tag}-extra`;
@@ -731,10 +1093,10 @@ var runStoreTck = (options) => {
731
1093
  make_meta({ stream: b })
732
1094
  );
733
1095
  const exact = await collect(store, { stream: a, stream_exact: true });
734
- expect5(exact).toHaveLength(1);
735
- expect5(exact[0].data).toEqual({ amount: 1 });
1096
+ expect8(exact).toHaveLength(1);
1097
+ expect8(exact[0].data).toEqual({ amount: 1 });
736
1098
  });
737
- it4("plain regex without anchors is a substring match", async () => {
1099
+ it7("plain regex without anchors is a substring match", async () => {
738
1100
  const tag = uid();
739
1101
  const inner = `qr-${tag}-inner`;
740
1102
  const longer = `qr-${tag}-inner-extra`;
@@ -749,9 +1111,9 @@ var runStoreTck = (options) => {
749
1111
  make_meta({ stream: longer })
750
1112
  );
751
1113
  const got = await collect(store, { stream: `qr-${tag}-inner` });
752
- expect5(got.map((e) => e.stream).sort()).toEqual([inner, longer].sort());
1114
+ expect8(got.map((e) => e.stream).sort()).toEqual([inner, longer].sort());
753
1115
  });
754
- it4("caller-anchored `^name$` matches only the whole string", async () => {
1116
+ it7("caller-anchored `^name$` matches only the whole string", async () => {
755
1117
  const tag = uid();
756
1118
  const inner = `qr-${tag}-anchor`;
757
1119
  const longer = `qr-${tag}-anchor-extra`;
@@ -766,10 +1128,10 @@ var runStoreTck = (options) => {
766
1128
  make_meta({ stream: longer })
767
1129
  );
768
1130
  const got = await collect(store, { stream: `^qr-${tag}-anchor$` });
769
- expect5(got).toHaveLength(1);
770
- expect5(got[0].stream).toBe(inner);
1131
+ expect8(got).toHaveLength(1);
1132
+ expect8(got[0].stream).toBe(inner);
771
1133
  });
772
- it4("caller-anchored `^prefix` matches by prefix", async () => {
1134
+ it7("caller-anchored `^prefix` matches by prefix", async () => {
773
1135
  const tag = uid();
774
1136
  const a = `qr-${tag}-pfx-a`;
775
1137
  const b = `qr-${tag}-pfx-b`;
@@ -790,18 +1152,39 @@ var runStoreTck = (options) => {
790
1152
  make_meta({ stream: other })
791
1153
  );
792
1154
  const got = await collect(store, { stream: `^qr-${tag}-pfx-` });
793
- expect5(got.map((e) => e.stream).sort()).toEqual([a, b].sort());
1155
+ expect8(got.map((e) => e.stream).sort()).toEqual([a, b].sort());
794
1156
  });
795
1157
  });
796
- describe5("subscribe + claim + ack", () => {
797
- it4("subscribes new streams and is idempotent on repeat", async () => {
1158
+ describe8("subscribe + claim + ack", () => {
1159
+ it7("subscribes new streams and is idempotent on repeat", async () => {
798
1160
  const s = `sub-${uid()}`;
799
1161
  const first = await store.subscribe([{ stream: s }]);
800
- expect5(first.subscribed).toBe(1);
1162
+ expect8(first.subscribed).toBe(1);
801
1163
  const second = await store.subscribe([{ stream: s }]);
802
- expect5(second.subscribed).toBe(0);
1164
+ expect8(second.subscribed).toBe(0);
1165
+ });
1166
+ it7("keeps the maximum priority when a stream is re-subscribed", async () => {
1167
+ const s = `sub-pri-${uid()}`;
1168
+ const read = async () => {
1169
+ const got = {};
1170
+ await store.query_streams(
1171
+ (p) => {
1172
+ got.priority = p.priority;
1173
+ },
1174
+ { stream: s, stream_exact: true }
1175
+ );
1176
+ return got.priority;
1177
+ };
1178
+ await store.subscribe([{ stream: s, priority: 3 }]);
1179
+ expect8(await read()).toBe(3);
1180
+ await store.subscribe([{ stream: s, priority: 10 }]);
1181
+ expect8(await read()).toBe(10);
1182
+ await store.subscribe([{ stream: s, priority: 1 }]);
1183
+ expect8(await read()).toBe(10);
1184
+ await store.subscribe([{ stream: s }]);
1185
+ expect8(await read()).toBe(10);
803
1186
  });
804
- it4("claims a subscribed stream and ack releases the lease", async () => {
1187
+ it7("claims a subscribed stream and ack releases the lease", async () => {
805
1188
  const s = `claim-${uid()}`;
806
1189
  await store.subscribe([{ stream: s }]);
807
1190
  await store.commit(
@@ -812,11 +1195,11 @@ var runStoreTck = (options) => {
812
1195
  const by = `worker-${uid()}`;
813
1196
  const leased = await store.claim(100, 0, by, 1e4);
814
1197
  const mine = leased.find((l) => l.stream === s);
815
- expect5(mine).toBeDefined();
816
- expect5(mine.by).toBe(by);
1198
+ expect8(mine).toBeDefined();
1199
+ expect8(mine.by).toBe(by);
817
1200
  await store.ack([{ ...mine, at: mine.at + 1 }]);
818
1201
  });
819
- it4("does not double-claim a held lease", async () => {
1202
+ it7("does not double-claim a held lease", async () => {
820
1203
  const s = `claim-held-${uid()}`;
821
1204
  const other = `claim-other-${uid()}`;
822
1205
  await store.subscribe([{ stream: s }]);
@@ -827,7 +1210,7 @@ var runStoreTck = (options) => {
827
1210
  );
828
1211
  const leasedA = await store.claim(100, 0, `wA-${uid()}`, 1e5);
829
1212
  const targetA = leasedA.find((l) => l.stream === s);
830
- expect5(targetA).toBeDefined();
1213
+ expect8(targetA).toBeDefined();
831
1214
  await store.subscribe([{ stream: other }]);
832
1215
  await store.commit(
833
1216
  other,
@@ -835,11 +1218,11 @@ var runStoreTck = (options) => {
835
1218
  make_meta({ stream: other })
836
1219
  );
837
1220
  const leasedB = await store.claim(100, 0, `wB-${uid()}`, 1e5);
838
- expect5(leasedB.length).toBeGreaterThan(0);
839
- expect5(leasedB.find((l) => l.stream === s)).toBeUndefined();
840
- expect5(leasedB.find((l) => l.stream === other)).toBeDefined();
1221
+ expect8(leasedB.length).toBeGreaterThan(0);
1222
+ expect8(leasedB.find((l) => l.stream === s)).toBeUndefined();
1223
+ expect8(leasedB.find((l) => l.stream === other)).toBeDefined();
841
1224
  });
842
- it4("supports dual frontiers (lagging + leading)", async () => {
1225
+ it7("supports dual frontiers (lagging + leading)", async () => {
843
1226
  const s = `claim-dual-${uid()}`;
844
1227
  await store.subscribe([{ stream: s }]);
845
1228
  await store.commit(
@@ -849,12 +1232,12 @@ var runStoreTck = (options) => {
849
1232
  );
850
1233
  const first = await store.claim(100, 0, `w-${uid()}`, 1);
851
1234
  const mine = first.find((l) => l.stream === s);
852
- expect5(mine).toBeDefined();
1235
+ expect8(mine).toBeDefined();
853
1236
  await store.ack([{ ...mine, at: mine.at + 1 }]);
854
1237
  const second = await store.claim(0, 100, `w-${uid()}`, 1);
855
- expect5(second.find((l) => l.stream === s)).toBeDefined();
1238
+ expect8(second.find((l) => l.stream === s)).toBeDefined();
856
1239
  });
857
- it4("dedupes when both frontiers would return the same stream", async () => {
1240
+ it7("dedupes when both frontiers would return the same stream", async () => {
858
1241
  const s = `claim-dedup-${uid()}`;
859
1242
  await store.subscribe([{ stream: s }]);
860
1243
  await store.commit(
@@ -864,9 +1247,9 @@ var runStoreTck = (options) => {
864
1247
  );
865
1248
  const claimed = await store.claim(100, 100, `w-${uid()}`, 1e5);
866
1249
  const matches = claimed.filter((l) => l.stream === s);
867
- expect5(matches).toHaveLength(1);
1250
+ expect8(matches).toHaveLength(1);
868
1251
  });
869
- it4("silently ignores ack from the wrong holder", async () => {
1252
+ it7("silently ignores ack from the wrong holder", async () => {
870
1253
  const s = `ack-wrong-${uid()}`;
871
1254
  const sibling = `ack-sibling-${uid()}`;
872
1255
  await store.subscribe([{ stream: s }, { stream: sibling }]);
@@ -883,40 +1266,40 @@ var runStoreTck = (options) => {
883
1266
  const leased = await store.claim(100, 0, `right-${uid()}`, 1e5);
884
1267
  const mine = leased.find((l) => l.stream === s);
885
1268
  const sibling_lease = leased.find((l) => l.stream === sibling);
886
- expect5(mine).toBeDefined();
887
- expect5(sibling_lease).toBeDefined();
1269
+ expect8(mine).toBeDefined();
1270
+ expect8(sibling_lease).toBeDefined();
888
1271
  const acked = await store.ack([
889
1272
  { ...mine, by: "imposter" },
890
1273
  sibling_lease
891
1274
  ]);
892
- expect5(acked.length).toBeGreaterThan(0);
893
- expect5(acked.find((l) => l.stream === s)).toBeUndefined();
1275
+ expect8(acked.length).toBeGreaterThan(0);
1276
+ expect8(acked.find((l) => l.stream === s)).toBeUndefined();
894
1277
  });
895
- it4("ack with a stale (lower) watermark does not throw", async () => {
1278
+ it7("ack with a stale (lower) watermark does not throw", async () => {
896
1279
  const s = `ack-stale-${uid()}`;
897
1280
  await store.subscribe([{ stream: s }]);
898
1281
  const by = `w-${uid()}`;
899
1282
  const leased = await store.claim(100, 0, by, 1e5);
900
1283
  const mine = leased.find((l) => l.stream === s);
901
- expect5(mine).toBeDefined();
902
- await expect5(
1284
+ expect8(mine).toBeDefined();
1285
+ await expect8(
903
1286
  store.ack([{ ...mine, at: -5 }])
904
1287
  ).resolves.toBeDefined();
905
1288
  });
906
- it4("claim with no subscribed streams returns an empty array", async () => {
1289
+ it7("claim with no subscribed streams returns an empty array", async () => {
907
1290
  const fresh = await options.factory();
908
1291
  try {
909
1292
  await fresh.drop();
910
1293
  await fresh.seed();
911
1294
  const claimed = await fresh.claim(1, 1, `w-${uid()}`, 1e3);
912
- expect5(claimed).toEqual([]);
1295
+ expect8(claimed).toEqual([]);
913
1296
  } finally {
914
1297
  await fresh.dispose();
915
1298
  }
916
1299
  });
917
1300
  });
918
- describe5("lease semantics", () => {
919
- it4("returns retry=0 on first claim and increments on re-claim without ack", async () => {
1301
+ describe8("lease semantics", () => {
1302
+ it7("returns retry=0 on first claim and increments on re-claim without ack", async () => {
920
1303
  const fresh = await options.factory();
921
1304
  try {
922
1305
  await fresh.drop();
@@ -930,17 +1313,17 @@ var runStoreTck = (options) => {
930
1313
  );
931
1314
  const first = await fresh.claim(1, 0, `w-${uid()}`, 0);
932
1315
  const f = first.find((l) => l.stream === s);
933
- expect5(f).toBeDefined();
934
- expect5(f.retry).toBe(0);
1316
+ expect8(f).toBeDefined();
1317
+ expect8(f.retry).toBe(0);
935
1318
  const second = await fresh.claim(1, 0, `w-${uid()}`, 1e5);
936
1319
  const sec = second.find((l) => l.stream === s);
937
- expect5(sec).toBeDefined();
938
- expect5(sec.retry).toBe(1);
1320
+ expect8(sec).toBeDefined();
1321
+ expect8(sec.retry).toBe(1);
939
1322
  } finally {
940
1323
  await fresh.dispose();
941
1324
  }
942
1325
  });
943
- it4("reports lagging=true from the lagging frontier and false from the leading frontier", async () => {
1326
+ it7("reports lagging=true from the lagging frontier and false from the leading frontier", async () => {
944
1327
  const fresh = await options.factory();
945
1328
  try {
946
1329
  await fresh.drop();
@@ -953,16 +1336,16 @@ var runStoreTck = (options) => {
953
1336
  make_meta({ stream: s })
954
1337
  );
955
1338
  const lag = await fresh.claim(1, 0, `w-${uid()}`, 0);
956
- expect5(lag.find((l) => l.stream === s)?.lagging).toBe(true);
1339
+ expect8(lag.find((l) => l.stream === s)?.lagging).toBe(true);
957
1340
  const lead = await fresh.claim(0, 1, `w-${uid()}`, 1e5);
958
- expect5(lead.find((l) => l.stream === s)?.lagging).toBe(false);
1341
+ expect8(lead.find((l) => l.stream === s)?.lagging).toBe(false);
959
1342
  } finally {
960
1343
  await fresh.dispose();
961
1344
  }
962
1345
  });
963
1346
  });
964
- describe5.skipIf(!caps.concurrent_claim)("concurrency (capability)", () => {
965
- it4("never double-leases a stream across concurrent claimers", async () => {
1347
+ describe8.skipIf(!caps.concurrent_claim)("concurrency (capability)", () => {
1348
+ it7("never double-leases a stream across concurrent claimers", async () => {
966
1349
  const fresh = await options.factory();
967
1350
  try {
968
1351
  await fresh.drop();
@@ -985,15 +1368,15 @@ var runStoreTck = (options) => {
985
1368
  fresh.claim(100, 100, `wB-${uid()}`, 6e4)
986
1369
  ]);
987
1370
  const claimed = [...a, ...b].map((l) => l.stream).filter((stream) => owned.has(stream));
988
- expect5(new Set(claimed).size).toBe(claimed.length);
989
- expect5(claimed.length).toBe(owned.size);
1371
+ expect8(new Set(claimed).size).toBe(claimed.length);
1372
+ expect8(claimed.length).toBe(owned.size);
990
1373
  } finally {
991
1374
  await fresh.dispose();
992
1375
  }
993
1376
  });
994
1377
  });
995
- describe5("block", () => {
996
- it4("hides blocked streams from claim", async () => {
1378
+ describe8("block", () => {
1379
+ it7("hides blocked streams from claim", async () => {
997
1380
  const s = `block-${uid()}`;
998
1381
  await store.subscribe([{ stream: s }]);
999
1382
  await store.commit(
@@ -1003,18 +1386,18 @@ var runStoreTck = (options) => {
1003
1386
  );
1004
1387
  const leased = await store.claim(100, 0, `w-${uid()}`, 1e5);
1005
1388
  const mine = leased.find((l) => l.stream === s);
1006
- expect5(mine).toBeDefined();
1389
+ expect8(mine).toBeDefined();
1007
1390
  const others = leased.filter((l) => l.stream !== s);
1008
1391
  await store.ack(others);
1009
1392
  const blocked = await store.block([
1010
1393
  { ...mine, error: "boom" }
1011
1394
  ]);
1012
- expect5(blocked).toHaveLength(1);
1013
- expect5(blocked[0].error).toBe("boom");
1395
+ expect8(blocked).toHaveLength(1);
1396
+ expect8(blocked[0].error).toBe("boom");
1014
1397
  const again = await store.claim(100, 100, `w2-${uid()}`, 1e5);
1015
- expect5(again.find((l) => l.stream === s)).toBeUndefined();
1398
+ expect8(again.find((l) => l.stream === s)).toBeUndefined();
1016
1399
  });
1017
- it4("rejects block calls from a different holder", async () => {
1400
+ it7("rejects block calls from a different holder", async () => {
1018
1401
  const s = `block-wrong-${uid()}`;
1019
1402
  await store.subscribe([{ stream: s }]);
1020
1403
  await store.commit(
@@ -1024,17 +1407,115 @@ var runStoreTck = (options) => {
1024
1407
  );
1025
1408
  const leased = await store.claim(100, 0, `right-${uid()}`, 1e5);
1026
1409
  const mine = leased.find((l) => l.stream === s);
1027
- expect5(mine).toBeDefined();
1410
+ expect8(mine).toBeDefined();
1028
1411
  const others = leased.filter((l) => l.stream !== s);
1029
1412
  await store.ack(others);
1030
1413
  const blocked = await store.block([
1031
1414
  { ...mine, by: "imposter", error: "no" }
1032
1415
  ]);
1033
- expect5(blocked).toHaveLength(0);
1416
+ expect8(blocked).toHaveLength(0);
1417
+ });
1418
+ });
1419
+ describe8("defer", () => {
1420
+ it7("hides a stream from claim until its deferred_at passes", async () => {
1421
+ const s = `defer-${uid()}`;
1422
+ const ctl = `defer-ctl-${uid()}`;
1423
+ await store.subscribe([{ stream: s }, { stream: ctl }]);
1424
+ for (const st of [s, ctl])
1425
+ await store.commit(
1426
+ st,
1427
+ [inc(1)],
1428
+ make_meta({ stream: st })
1429
+ );
1430
+ expect8(await store.defer([s], Date.now() + 36e5)).toBe(1);
1431
+ const leased = await store.claim(100, 100, `w-${uid()}`, 1e5);
1432
+ expect8(leased.find((l) => l.stream === ctl)).toBeDefined();
1433
+ expect8(leased.find((l) => l.stream === s)).toBeUndefined();
1434
+ });
1435
+ it7("makes a stream claimable once the deferred_at is in the past", async () => {
1436
+ const s = `defer-past-${uid()}`;
1437
+ await store.subscribe([{ stream: s }]);
1438
+ await store.commit(
1439
+ s,
1440
+ [inc(1)],
1441
+ make_meta({ stream: s })
1442
+ );
1443
+ expect8(await store.defer([s], Date.now() - 1e3)).toBe(1);
1444
+ const leased = await store.claim(100, 100, `w-${uid()}`, 1e5);
1445
+ const mine = leased.find((l) => l.stream === s);
1446
+ expect8(mine).toBeDefined();
1447
+ await store.ack(
1448
+ leased.filter((l) => l.stream !== s).concat(mine)
1449
+ );
1450
+ });
1451
+ it7("does not bump retry while a stream is deferred", async () => {
1452
+ const s = `defer-retry-${uid()}`;
1453
+ await store.subscribe([{ stream: s }]);
1454
+ await store.commit(
1455
+ s,
1456
+ [inc(1)],
1457
+ make_meta({ stream: s })
1458
+ );
1459
+ await store.defer([s], Date.now() + 36e5);
1460
+ await store.claim(100, 100, `w1-${uid()}`, 1e5);
1461
+ await store.claim(100, 100, `w2-${uid()}`, 1e5);
1462
+ await store.defer([s], Date.now() - 1e3);
1463
+ const leased = await store.claim(100, 100, `w3-${uid()}`, 1e5);
1464
+ const mine = leased.find((l) => l.stream === s);
1465
+ expect8(mine).toBeDefined();
1466
+ expect8(mine.retry).toBe(0);
1467
+ await store.ack(
1468
+ leased.filter((l) => l.stream !== s).concat(mine)
1469
+ );
1470
+ });
1471
+ it7("reset clears a pending defer", async () => {
1472
+ const s = `defer-reset-${uid()}`;
1473
+ await store.subscribe([{ stream: s }]);
1474
+ await store.commit(
1475
+ s,
1476
+ [inc(1)],
1477
+ make_meta({ stream: s })
1478
+ );
1479
+ await store.defer([s], Date.now() + 36e5);
1480
+ expect8(await store.reset([s])).toBe(1);
1481
+ const leased = await store.claim(100, 100, `w-${uid()}`, 1e5);
1482
+ expect8(leased.find((l) => l.stream === s)).toBeDefined();
1483
+ });
1484
+ it7("defers streams matching a filter and counts matches", async () => {
1485
+ const tag = uid();
1486
+ const a = `deferfilter-${tag}-a`;
1487
+ const b = `deferfilter-${tag}-b`;
1488
+ await store.subscribe([{ stream: a }, { stream: b }]);
1489
+ for (const s of [a, b])
1490
+ await store.commit(
1491
+ s,
1492
+ [inc(1)],
1493
+ make_meta({ stream: s })
1494
+ );
1495
+ const ctl = `defer-filterctl-${tag}`;
1496
+ await store.subscribe([{ stream: ctl }]);
1497
+ await store.commit(
1498
+ ctl,
1499
+ [inc(1)],
1500
+ make_meta({ stream: ctl })
1501
+ );
1502
+ const n = await store.defer(
1503
+ { stream: `^deferfilter-${tag}-`, stream_exact: false },
1504
+ Date.now() + 36e5
1505
+ );
1506
+ expect8(n).toBe(2);
1507
+ const leased = await store.claim(100, 100, `w-${uid()}`, 1e5);
1508
+ expect8(leased.find((l) => l.stream === ctl)).toBeDefined();
1509
+ expect8(leased.find((l) => l.stream === a)).toBeUndefined();
1510
+ expect8(leased.find((l) => l.stream === b)).toBeUndefined();
1511
+ });
1512
+ it7("returns 0 for unknown streams and empty input", async () => {
1513
+ expect8(await store.defer([`missing-${uid()}`], Date.now())).toBe(0);
1514
+ expect8(await store.defer([], Date.now())).toBe(0);
1034
1515
  });
1035
1516
  });
1036
- describe5("reset", () => {
1037
- it4("rewinds a stream watermark to -1", async () => {
1517
+ describe8("reset", () => {
1518
+ it7("rewinds a stream watermark to -1", async () => {
1038
1519
  const s = `reset-${uid()}`;
1039
1520
  await store.subscribe([{ stream: s }]);
1040
1521
  await store.commit(
@@ -1044,15 +1525,15 @@ var runStoreTck = (options) => {
1044
1525
  );
1045
1526
  const leased = await store.claim(100, 0, `w-${uid()}`, 1e5);
1046
1527
  const mine = leased.find((l) => l.stream === s);
1047
- expect5(mine).toBeDefined();
1528
+ expect8(mine).toBeDefined();
1048
1529
  await store.ack([{ ...mine, at: 99 }]);
1049
- expect5(await store.reset([s])).toBe(1);
1530
+ expect8(await store.reset([s])).toBe(1);
1050
1531
  const after = await store.claim(100, 0, `w2-${uid()}`, 1e5);
1051
1532
  const back = after.find((l) => l.stream === s);
1052
- expect5(back).toBeDefined();
1053
- expect5(back.at).toBe(-1);
1533
+ expect8(back).toBeDefined();
1534
+ expect8(back.at).toBe(-1);
1054
1535
  });
1055
- it4("clears blocked status when resetting", async () => {
1536
+ it7("clears blocked status when resetting", async () => {
1056
1537
  const s = `reset-blk-${uid()}`;
1057
1538
  await store.subscribe([{ stream: s }]);
1058
1539
  await store.commit(
@@ -1065,17 +1546,17 @@ var runStoreTck = (options) => {
1065
1546
  const others = leased.filter((l) => l.stream !== s);
1066
1547
  await store.ack(others);
1067
1548
  await store.block([{ ...mine, error: "boom" }]);
1068
- expect5(await store.reset([s])).toBe(1);
1549
+ expect8(await store.reset([s])).toBe(1);
1069
1550
  const after = await store.claim(100, 0, `w2-${uid()}`, 1e5);
1070
- expect5(after.find((l) => l.stream === s)).toBeDefined();
1551
+ expect8(after.find((l) => l.stream === s)).toBeDefined();
1071
1552
  });
1072
- it4("returns 0 for unknown streams and empty input", async () => {
1073
- expect5(await store.reset([`missing-${uid()}`])).toBe(0);
1074
- expect5(await store.reset([])).toBe(0);
1553
+ it7("returns 0 for unknown streams and empty input", async () => {
1554
+ expect8(await store.reset([`missing-${uid()}`])).toBe(0);
1555
+ expect8(await store.reset([])).toBe(0);
1075
1556
  });
1076
1557
  });
1077
- describe5("unblock", () => {
1078
- it4("clears blocked flag and preserves the watermark", async () => {
1558
+ describe8("unblock", () => {
1559
+ it7("clears blocked flag and preserves the watermark", async () => {
1079
1560
  const s = `unblock-${uid()}`;
1080
1561
  await store.subscribe([{ stream: s }]);
1081
1562
  await store.commit(
@@ -1093,7 +1574,7 @@ var runStoreTck = (options) => {
1093
1574
  await store.ack([{ ...m1, at: m1.at }]);
1094
1575
  const before_block = await store.claim(100, 0, `w-${uid()}`, 1e5);
1095
1576
  const m2 = before_block.find((l) => l.stream === s);
1096
- expect5(m2).toBeDefined();
1577
+ expect8(m2).toBeDefined();
1097
1578
  const watermark_before = m2.at;
1098
1579
  await store.block([{ ...m2, error: "permanent" }]);
1099
1580
  let blocked_flag;
@@ -1103,15 +1584,15 @@ var runStoreTck = (options) => {
1103
1584
  },
1104
1585
  { stream: s, stream_exact: true, limit: 1 }
1105
1586
  );
1106
- expect5(blocked_flag).toBe(true);
1107
- expect5(await store.unblock([s])).toBe(1);
1587
+ expect8(blocked_flag).toBe(true);
1588
+ expect8(await store.unblock([s])).toBe(1);
1108
1589
  const after = await store.claim(100, 0, `w-${uid()}`, 1e5);
1109
1590
  const back = after.find((l) => l.stream === s);
1110
- expect5(back).toBeDefined();
1111
- expect5(back.at).toBe(watermark_before);
1112
- expect5(back.retry).toBe(0);
1591
+ expect8(back).toBeDefined();
1592
+ expect8(back.at).toBe(watermark_before);
1593
+ expect8(back.retry).toBe(0);
1113
1594
  });
1114
- it4("returns 0 when the stream is not blocked", async () => {
1595
+ it7("returns 0 when the stream is not blocked", async () => {
1115
1596
  const s = `unblock-noop-${uid()}`;
1116
1597
  await store.subscribe([{ stream: s }]);
1117
1598
  await store.commit(
@@ -1119,13 +1600,13 @@ var runStoreTck = (options) => {
1119
1600
  [inc(1)],
1120
1601
  make_meta({ stream: s })
1121
1602
  );
1122
- expect5(await store.unblock([s])).toBe(0);
1603
+ expect8(await store.unblock([s])).toBe(0);
1123
1604
  });
1124
- it4("returns 0 for unknown streams and empty input", async () => {
1125
- expect5(await store.unblock([`missing-${uid()}`])).toBe(0);
1126
- expect5(await store.unblock([])).toBe(0);
1605
+ it7("returns 0 for unknown streams and empty input", async () => {
1606
+ expect8(await store.unblock([`missing-${uid()}`])).toBe(0);
1607
+ expect8(await store.unblock([])).toBe(0);
1127
1608
  });
1128
- it4("only counts streams that were actually blocked", async () => {
1609
+ it7("only counts streams that were actually blocked", async () => {
1129
1610
  const s1 = `unblock-mix-a-${uid()}`;
1130
1611
  const s2 = `unblock-mix-b-${uid()}`;
1131
1612
  await store.subscribe([{ stream: s1 }, { stream: s2 }]);
@@ -1144,9 +1625,9 @@ var runStoreTck = (options) => {
1144
1625
  const others = leased.filter((l) => l.stream !== s1);
1145
1626
  await store.ack(others);
1146
1627
  await store.block([{ ...m1, error: "boom" }]);
1147
- expect5(await store.unblock([s1, s2])).toBe(1);
1628
+ expect8(await store.unblock([s1, s2])).toBe(1);
1148
1629
  });
1149
- it4("filter form: unblocks by stream pattern", async () => {
1630
+ it7("filter form: unblocks by stream pattern", async () => {
1150
1631
  const tag = uid();
1151
1632
  const s1 = `unblock-filter-${tag}-a`;
1152
1633
  const s2 = `unblock-filter-${tag}-b`;
@@ -1178,13 +1659,13 @@ var runStoreTck = (options) => {
1178
1659
  const count = await store.unblock({
1179
1660
  stream: `^unblock-filter-${tag}-`
1180
1661
  });
1181
- expect5(count).toBe(2);
1662
+ expect8(count).toBe(2);
1182
1663
  const after = await store.claim(100, 0, `w-${uid()}`, 1e5);
1183
- expect5(after.find((l) => l.stream === s3)).toBeUndefined();
1184
- expect5(after.find((l) => l.stream === s1)).toBeDefined();
1185
- expect5(after.find((l) => l.stream === s2)).toBeDefined();
1664
+ expect8(after.find((l) => l.stream === s3)).toBeUndefined();
1665
+ expect8(after.find((l) => l.stream === s1)).toBeDefined();
1666
+ expect8(after.find((l) => l.stream === s2)).toBeDefined();
1186
1667
  });
1187
- it4("filter form: empty filter unblocks every blocked stream", async () => {
1668
+ it7("filter form: empty filter unblocks every blocked stream", async () => {
1188
1669
  const tag = uid();
1189
1670
  const s1 = `unblock-empty-${tag}-a`;
1190
1671
  const s2 = `unblock-empty-${tag}-b`;
@@ -1208,9 +1689,9 @@ var runStoreTck = (options) => {
1208
1689
  const count = await store.unblock({
1209
1690
  stream: `^unblock-empty-${tag}-`
1210
1691
  });
1211
- expect5(count).toBe(2);
1692
+ expect8(count).toBe(2);
1212
1693
  });
1213
- it4("filter form: explicit blocked:false matches nothing", async () => {
1694
+ it7("filter form: explicit blocked:false matches nothing", async () => {
1214
1695
  const tag = uid();
1215
1696
  const s = `unblock-blocked-false-${tag}`;
1216
1697
  await store.subscribe([{ stream: s }]);
@@ -1219,7 +1700,7 @@ var runStoreTck = (options) => {
1219
1700
  [inc(1)],
1220
1701
  make_meta({ stream: s })
1221
1702
  );
1222
- expect5(
1703
+ expect8(
1223
1704
  await store.unblock({
1224
1705
  stream: `^unblock-blocked-false-${tag}`,
1225
1706
  blocked: false
@@ -1227,8 +1708,8 @@ var runStoreTck = (options) => {
1227
1708
  ).toBe(0);
1228
1709
  });
1229
1710
  });
1230
- describe5("reset filter form", () => {
1231
- it4("resets streams matching a stream pattern", async () => {
1711
+ describe8("reset filter form", () => {
1712
+ it7("resets streams matching a stream pattern", async () => {
1232
1713
  const tag = uid();
1233
1714
  const s1 = `reset-filter-${tag}-a`;
1234
1715
  const s2 = `reset-filter-${tag}-b`;
@@ -1259,7 +1740,7 @@ var runStoreTck = (options) => {
1259
1740
  );
1260
1741
  await store.ack(mine.map((l) => ({ ...l, at: l.at + 100 })));
1261
1742
  const count = await store.reset({ stream: `^reset-filter-${tag}-` });
1262
- expect5(count).toBe(2);
1743
+ expect8(count).toBe(2);
1263
1744
  const position_for = async (name) => {
1264
1745
  let at = null;
1265
1746
  await store.query_streams(
@@ -1270,11 +1751,11 @@ var runStoreTck = (options) => {
1270
1751
  );
1271
1752
  return at;
1272
1753
  };
1273
- expect5(await position_for(s1)).toBe(-1);
1274
- expect5(await position_for(s2)).toBe(-1);
1275
- expect5(await position_for(other)).toBeGreaterThan(-1);
1754
+ expect8(await position_for(s1)).toBe(-1);
1755
+ expect8(await position_for(s2)).toBe(-1);
1756
+ expect8(await position_for(other)).toBeGreaterThan(-1);
1276
1757
  });
1277
- it4("filter form: resets only blocked streams when blocked:true", async () => {
1758
+ it7("filter form: resets only blocked streams when blocked:true", async () => {
1278
1759
  const tag = uid();
1279
1760
  const s1 = `reset-blocked-${tag}-blocked`;
1280
1761
  const s2 = `reset-blocked-${tag}-fine`;
@@ -1297,11 +1778,11 @@ var runStoreTck = (options) => {
1297
1778
  stream: `^reset-blocked-${tag}-`,
1298
1779
  blocked: true
1299
1780
  });
1300
- expect5(count).toBe(1);
1781
+ expect8(count).toBe(1);
1301
1782
  });
1302
1783
  });
1303
- describe5("prioritize", () => {
1304
- it4("sets priority directly, overriding subscribe's max() rule", async () => {
1784
+ describe8("prioritize", () => {
1785
+ it7("sets priority directly, overriding subscribe's max() rule", async () => {
1305
1786
  const tag = uid();
1306
1787
  const s1 = `pri-${tag}-a`;
1307
1788
  const s2 = `pri-${tag}-b`;
@@ -1313,7 +1794,7 @@ var runStoreTck = (options) => {
1313
1794
  { stream: s1, stream_exact: true },
1314
1795
  3
1315
1796
  );
1316
- expect5(updated).toBe(1);
1797
+ expect8(updated).toBe(1);
1317
1798
  const got1 = {};
1318
1799
  const got2 = {};
1319
1800
  await store.query_streams(
@@ -1323,12 +1804,12 @@ var runStoreTck = (options) => {
1323
1804
  },
1324
1805
  { stream: `pri-${tag}-.*`, limit: 100 }
1325
1806
  );
1326
- expect5(got1.priority).toBe(3);
1327
- expect5(got2.priority).toBe(5);
1807
+ expect8(got1.priority).toBe(3);
1808
+ expect8(got2.priority).toBe(5);
1328
1809
  });
1329
1810
  });
1330
- describe5("lanes", () => {
1331
- it4("subscribe defaults lane to 'default' when omitted", async () => {
1811
+ describe8("lanes", () => {
1812
+ it7("subscribe defaults lane to 'default' when omitted", async () => {
1332
1813
  const s = `lane-default-${uid()}`;
1333
1814
  await store.subscribe([{ stream: s }]);
1334
1815
  const seen = [];
@@ -1336,9 +1817,9 @@ var runStoreTck = (options) => {
1336
1817
  stream: s,
1337
1818
  stream_exact: true
1338
1819
  });
1339
- expect5(seen).toEqual(["default"]);
1820
+ expect8(seen).toEqual(["default"]);
1340
1821
  });
1341
- it4("subscribe records the lane passed in", async () => {
1822
+ it7("subscribe records the lane passed in", async () => {
1342
1823
  const s = `lane-set-${uid()}`;
1343
1824
  await store.subscribe([{ stream: s, lane: "slow" }]);
1344
1825
  const seen = [];
@@ -1346,9 +1827,9 @@ var runStoreTck = (options) => {
1346
1827
  stream: s,
1347
1828
  stream_exact: true
1348
1829
  });
1349
- expect5(seen).toEqual(["slow"]);
1830
+ expect8(seen).toEqual(["slow"]);
1350
1831
  });
1351
- it4("subscribe re-lanes existing streams on subsequent calls", async () => {
1832
+ it7("subscribe re-lanes existing streams on subsequent calls", async () => {
1352
1833
  const s = `lane-upsert-${uid()}`;
1353
1834
  await store.subscribe([{ stream: s, lane: "slow" }]);
1354
1835
  await store.subscribe([{ stream: s, lane: "fast" }]);
@@ -1357,9 +1838,9 @@ var runStoreTck = (options) => {
1357
1838
  stream: s,
1358
1839
  stream_exact: true
1359
1840
  });
1360
- expect5(seen).toEqual(["fast"]);
1841
+ expect8(seen).toEqual(["fast"]);
1361
1842
  });
1362
- it4("claim() filters by lane when supplied and returns lane on the Lease", async () => {
1843
+ it7("claim() filters by lane when supplied and returns lane on the Lease", async () => {
1363
1844
  const tag = uid();
1364
1845
  const src1 = `lane-claim-src1-${tag}`;
1365
1846
  const src2 = `lane-claim-src2-${tag}`;
@@ -1383,19 +1864,19 @@ var runStoreTck = (options) => {
1383
1864
  const slow_mine = slow.filter(
1384
1865
  (l) => l.stream === sub_default || l.stream === sub_slow
1385
1866
  );
1386
- expect5(slow_mine.map((l) => l.stream)).toEqual([sub_slow]);
1387
- expect5(slow_mine[0]?.lane).toBe("slow");
1867
+ expect8(slow_mine.map((l) => l.stream)).toEqual([sub_slow]);
1868
+ expect8(slow_mine[0]?.lane).toBe("slow");
1388
1869
  await store.ack(slow_mine.map((l) => ({ ...l, at: l.at + 1 })));
1389
1870
  const all = await store.claim(50, 0, `w-all-${tag}`, 1e3);
1390
1871
  const all_mine = all.filter((l) => l.stream === sub_default || l.stream === sub_slow).map((l) => ({ stream: l.stream, lane: l.lane }));
1391
- expect5(all_mine).toEqual(
1392
- expect5.arrayContaining([
1872
+ expect8(all_mine).toEqual(
1873
+ expect8.arrayContaining([
1393
1874
  { stream: sub_default, lane: "default" },
1394
1875
  { stream: sub_slow, lane: "slow" }
1395
1876
  ])
1396
1877
  );
1397
1878
  });
1398
- it4("query_streams filters by lane", async () => {
1879
+ it7("query_streams filters by lane", async () => {
1399
1880
  const tag = uid();
1400
1881
  const a = `lane-q-a-${tag}`;
1401
1882
  const b = `lane-q-b-${tag}`;
@@ -1411,9 +1892,9 @@ var runStoreTck = (options) => {
1411
1892
  stream: `lane-q-.*-${tag}`,
1412
1893
  limit: 100
1413
1894
  });
1414
- expect5(seen.sort()).toEqual([a, c]);
1895
+ expect8(seen.sort()).toEqual([a, c]);
1415
1896
  });
1416
- it4("prioritize filters by lane", async () => {
1897
+ it7("prioritize filters by lane", async () => {
1417
1898
  const tag = uid();
1418
1899
  const a = `lane-pri-a-${tag}`;
1419
1900
  const b = `lane-pri-b-${tag}`;
@@ -1422,16 +1903,16 @@ var runStoreTck = (options) => {
1422
1903
  { stream: b, lane: `pfast-${tag}` }
1423
1904
  ]);
1424
1905
  const updated = await store.prioritize({ lane: `pslow-${tag}` }, 7);
1425
- expect5(updated).toBe(1);
1906
+ expect8(updated).toBe(1);
1426
1907
  const seen = /* @__PURE__ */ new Map();
1427
1908
  await store.query_streams((p) => seen.set(p.stream, p.priority), {
1428
1909
  stream: `lane-pri-.*-${tag}`,
1429
1910
  limit: 100
1430
1911
  });
1431
- expect5(seen.get(a)).toBe(7);
1432
- expect5(seen.get(b)).toBe(0);
1912
+ expect8(seen.get(a)).toBe(7);
1913
+ expect8(seen.get(b)).toBe(0);
1433
1914
  });
1434
- it4("reset filters by lane", async () => {
1915
+ it7("reset filters by lane", async () => {
1435
1916
  const tag = uid();
1436
1917
  const src = `lane-reset-src-${tag}`;
1437
1918
  const a = `lane-reset-a-${tag}`;
@@ -1449,7 +1930,7 @@ var runStoreTck = (options) => {
1449
1930
  const mine = leases.filter((l) => l.stream === a || l.stream === b);
1450
1931
  await store.ack(mine.map((l) => ({ ...l, at: l.at + 1 })));
1451
1932
  const count = await store.reset({ lane: `rslow-${tag}` });
1452
- expect5(count).toBe(1);
1933
+ expect8(count).toBe(1);
1453
1934
  const ats = /* @__PURE__ */ new Map();
1454
1935
  for (const name of [a, b]) {
1455
1936
  await store.query_streams((p) => ats.set(p.stream, p.at), {
@@ -1457,10 +1938,10 @@ var runStoreTck = (options) => {
1457
1938
  stream_exact: true
1458
1939
  });
1459
1940
  }
1460
- expect5(ats.get(a)).toBe(-1);
1461
- expect5(ats.get(b)).toBeGreaterThanOrEqual(0);
1941
+ expect8(ats.get(a)).toBe(-1);
1942
+ expect8(ats.get(b)).toBeGreaterThanOrEqual(0);
1462
1943
  });
1463
- it4("unblock filters by lane", async () => {
1944
+ it7("unblock filters by lane", async () => {
1464
1945
  const tag = uid();
1465
1946
  const src = `lane-ub-src-${tag}`;
1466
1947
  const a = `lane-ub-a-${tag}`;
@@ -1478,7 +1959,7 @@ var runStoreTck = (options) => {
1478
1959
  const mine = leases.filter((l) => l.stream === a || l.stream === b);
1479
1960
  await store.block(mine.map((l) => ({ ...l, error: "boom" })));
1480
1961
  const count = await store.unblock({ lane: `uslow-${tag}` });
1481
- expect5(count).toBe(1);
1962
+ expect8(count).toBe(1);
1482
1963
  const blocked = /* @__PURE__ */ new Map();
1483
1964
  for (const name of [a, b]) {
1484
1965
  await store.query_streams((p) => blocked.set(p.stream, p.blocked), {
@@ -1486,12 +1967,12 @@ var runStoreTck = (options) => {
1486
1967
  stream_exact: true
1487
1968
  });
1488
1969
  }
1489
- expect5(blocked.get(a)).toBe(false);
1490
- expect5(blocked.get(b)).toBe(true);
1970
+ expect8(blocked.get(a)).toBe(false);
1971
+ expect8(blocked.get(b)).toBe(true);
1491
1972
  });
1492
1973
  });
1493
- describe5("truncate", () => {
1494
- it4("seeds a tombstone when no snapshot is provided", async () => {
1974
+ describe8("truncate", () => {
1975
+ it7("seeds a tombstone when no snapshot is provided", async () => {
1495
1976
  const s = `trunc-tomb-${uid()}`;
1496
1977
  await store.commit(
1497
1978
  s,
@@ -1499,7 +1980,7 @@ var runStoreTck = (options) => {
1499
1980
  make_meta({ stream: s })
1500
1981
  );
1501
1982
  const result = await store.truncate([{ stream: s }]);
1502
- expect5(result.get(s)?.deleted).toBe(2);
1983
+ expect8(result.get(s)?.deleted).toBe(2);
1503
1984
  const remaining = [];
1504
1985
  await store.query(
1505
1986
  (e) => {
@@ -1507,12 +1988,12 @@ var runStoreTck = (options) => {
1507
1988
  },
1508
1989
  { stream: s, stream_exact: true }
1509
1990
  );
1510
- expect5(remaining).toHaveLength(1);
1511
- expect5(remaining[0].name).toBe(
1991
+ expect8(remaining).toHaveLength(1);
1992
+ expect8(remaining[0].name).toBe(
1512
1993
  "__tombstone__"
1513
1994
  );
1514
1995
  });
1515
- it4("seeds a snapshot when one is provided", async () => {
1996
+ it7("seeds a snapshot when one is provided", async () => {
1516
1997
  const s = `trunc-snap-${uid()}`;
1517
1998
  await store.commit(
1518
1999
  s,
@@ -1522,7 +2003,7 @@ var runStoreTck = (options) => {
1522
2003
  const result = await store.truncate([
1523
2004
  { stream: s, snapshot: { count: 7 } }
1524
2005
  ]);
1525
- expect5(result.get(s)?.deleted).toBe(1);
2006
+ expect8(result.get(s)?.deleted).toBe(1);
1526
2007
  const remaining = [];
1527
2008
  await store.query(
1528
2009
  (e) => {
@@ -1530,24 +2011,24 @@ var runStoreTck = (options) => {
1530
2011
  },
1531
2012
  { stream: s, stream_exact: true, with_snaps: true }
1532
2013
  );
1533
- expect5(remaining).toHaveLength(1);
1534
- expect5(remaining[0].name).toBe(
2014
+ expect8(remaining).toHaveLength(1);
2015
+ expect8(remaining[0].name).toBe(
1535
2016
  "__snapshot__"
1536
2017
  );
1537
- expect5(remaining[0].data).toEqual({ count: 7 });
2018
+ expect8(remaining[0].data).toEqual({ count: 7 });
1538
2019
  });
1539
- it4("returns an empty map for empty input", async () => {
2020
+ it7("returns an empty map for empty input", async () => {
1540
2021
  const result = await store.truncate([]);
1541
- expect5(result.size).toBe(0);
2022
+ expect8(result.size).toBe(0);
1542
2023
  });
1543
- it4("returns 0 deleted for streams that don't exist", async () => {
2024
+ it7("returns 0 deleted for streams that don't exist", async () => {
1544
2025
  const s = `trunc-missing-${uid()}`;
1545
2026
  const result = await store.truncate([{ stream: s }]);
1546
- expect5(result.get(s)?.deleted).toBe(0);
2027
+ expect8(result.get(s)?.deleted).toBe(0);
1547
2028
  });
1548
2029
  });
1549
- describe5("query_streams", () => {
1550
- it4("returns positions filtered by stream regex, exact, source, and source_exact", async () => {
2030
+ describe8("query_streams", () => {
2031
+ it7("returns positions filtered by stream regex, exact, source, and source_exact", async () => {
1551
2032
  const tag = uid();
1552
2033
  const proj1 = `qs-${tag}-projection-tickets`;
1553
2034
  const proj2 = `qs-${tag}-projection-users`;
@@ -1566,37 +2047,37 @@ var runStoreTck = (options) => {
1566
2047
  (p) => all.push({ stream: p.stream, source: p.source }),
1567
2048
  { stream: `qs-${tag}-.*` }
1568
2049
  );
1569
- expect5(all_result.count).toBe(4);
1570
- expect5(all_result.maxEventId).toBeGreaterThanOrEqual(-1);
1571
- expect5(all.map((p) => p.stream).sort()).toEqual(
2050
+ expect8(all_result.count).toBe(4);
2051
+ expect8(all_result.maxEventId).toBeGreaterThanOrEqual(-1);
2052
+ expect8(all.map((p) => p.stream).sort()).toEqual(
1572
2053
  [proj1, proj2, dyn1, dyn2].sort()
1573
2054
  );
1574
2055
  const projections = [];
1575
2056
  await store.query_streams((p) => projections.push(p.stream), {
1576
2057
  stream: `qs-${tag}-projection-.*`
1577
2058
  });
1578
- expect5(projections.sort()).toEqual([proj1, proj2].sort());
2059
+ expect8(projections.sort()).toEqual([proj1, proj2].sort());
1579
2060
  const exact = [];
1580
2061
  await store.query_streams((p) => exact.push(p.stream), {
1581
2062
  stream: dyn1,
1582
2063
  stream_exact: true
1583
2064
  });
1584
- expect5(exact).toEqual([dyn1]);
2065
+ expect8(exact).toEqual([dyn1]);
1585
2066
  const by_source = [];
1586
2067
  await store.query_streams((p) => by_source.push(p.stream), {
1587
2068
  stream: `qs-${tag}-.*`,
1588
2069
  source: `qs-${tag}-src-.*`
1589
2070
  });
1590
- expect5(by_source.sort()).toEqual([dyn1, dyn2].sort());
2071
+ expect8(by_source.sort()).toEqual([dyn1, dyn2].sort());
1591
2072
  const exact_source = [];
1592
2073
  await store.query_streams((p) => exact_source.push(p.stream), {
1593
2074
  stream: `qs-${tag}-.*`,
1594
2075
  source: src2,
1595
2076
  source_exact: true
1596
2077
  });
1597
- expect5(exact_source).toEqual([dyn2]);
2078
+ expect8(exact_source).toEqual([dyn2]);
1598
2079
  });
1599
- it4("paginates with limit + after (keyset)", async () => {
2080
+ it7("paginates with limit + after (keyset)", async () => {
1600
2081
  const tag = uid();
1601
2082
  const streams = [
1602
2083
  `qp-${tag}-a`,
@@ -1610,17 +2091,17 @@ var runStoreTck = (options) => {
1610
2091
  stream: `qp-${tag}-.*`,
1611
2092
  limit: 2
1612
2093
  });
1613
- expect5(page1).toHaveLength(2);
2094
+ expect8(page1).toHaveLength(2);
1614
2095
  const page2 = [];
1615
2096
  await store.query_streams((p) => page2.push(p.stream), {
1616
2097
  stream: `qp-${tag}-.*`,
1617
2098
  limit: 2,
1618
2099
  after: page1.at(-1)
1619
2100
  });
1620
- expect5(page2).toHaveLength(2);
1621
- expect5([...page1, ...page2].sort()).toEqual([...streams].sort());
2101
+ expect8(page2).toHaveLength(2);
2102
+ expect8([...page1, ...page2].sort()).toEqual([...streams].sort());
1622
2103
  });
1623
- it4("filters by blocked status", async () => {
2104
+ it7("filters by blocked status", async () => {
1624
2105
  const tag = uid();
1625
2106
  const s = `qb-${tag}`;
1626
2107
  const sibling = `qb-${tag}-other`;
@@ -1640,18 +2121,18 @@ var runStoreTck = (options) => {
1640
2121
  (p) => blocked.push({ stream: p.stream, error: p.error }),
1641
2122
  { stream: `qb-${tag}.*`, blocked: true }
1642
2123
  );
1643
- expect5(blocked).toHaveLength(1);
1644
- expect5(blocked[0].error).toBe("boom");
2124
+ expect8(blocked).toHaveLength(1);
2125
+ expect8(blocked[0].error).toBe("boom");
1645
2126
  const unblocked = [];
1646
2127
  await store.query_streams((p) => unblocked.push(p.stream), {
1647
2128
  stream: `qb-${tag}.*`,
1648
2129
  blocked: false
1649
2130
  });
1650
- expect5(unblocked).toEqual([sibling]);
2131
+ expect8(unblocked).toEqual([sibling]);
1651
2132
  });
1652
2133
  });
1653
- describe5("query_stats", () => {
1654
- it4("array input \u2014 returns head per stream, absent when not in input", async () => {
2134
+ describe8("query_stats", () => {
2135
+ it7("array input \u2014 returns head per stream, absent when not in input", async () => {
1655
2136
  const tag = uid();
1656
2137
  const sA = `qst-${tag}-a`;
1657
2138
  const sB = `qst-${tag}-b`;
@@ -1672,18 +2153,18 @@ var runStoreTck = (options) => {
1672
2153
  make_meta({ stream: sUnasked })
1673
2154
  );
1674
2155
  const stats = await store.query_stats([sA, sB]);
1675
- expect5(stats.size).toBe(2);
1676
- expect5(stats.get(sA)?.head.name).toBe("Incremented");
1677
- expect5((stats.get(sA)?.head.data).amount).toBe(2);
1678
- expect5(stats.get(sB)?.head.name).toBe("Decremented");
1679
- expect5((stats.get(sB)?.head.data).amount).toBe(5);
1680
- expect5(stats.has(sUnasked)).toBe(false);
2156
+ expect8(stats.size).toBe(2);
2157
+ expect8(stats.get(sA)?.head.name).toBe("Incremented");
2158
+ expect8((stats.get(sA)?.head.data).amount).toBe(2);
2159
+ expect8(stats.get(sB)?.head.name).toBe("Decremented");
2160
+ expect8((stats.get(sB)?.head.data).amount).toBe(5);
2161
+ expect8(stats.has(sUnasked)).toBe(false);
1681
2162
  const empty = await store.query_stats([]);
1682
- expect5(empty.size).toBe(0);
2163
+ expect8(empty.size).toBe(0);
1683
2164
  const unknown = await store.query_stats([`qst-${tag}-missing`]);
1684
- expect5(unknown.size).toBe(0);
2165
+ expect8(unknown.size).toBe(0);
1685
2166
  });
1686
- it4("tail returns the earliest event per stream", async () => {
2167
+ it7("tail returns the earliest event per stream", async () => {
1687
2168
  const tag = uid();
1688
2169
  const s = `qst-tail-${tag}`;
1689
2170
  await store.commit(
@@ -1705,12 +2186,12 @@ var runStoreTck = (options) => {
1705
2186
  tail: true
1706
2187
  });
1707
2188
  const r = stats.get(s);
1708
- expect5(r?.head.name).toBe("Incremented");
1709
- expect5((r?.head.data).amount).toBe(3);
1710
- expect5(r?.tail?.name).toBe("Incremented");
1711
- expect5((r?.tail?.data).amount).toBe(1);
2189
+ expect8(r?.head.name).toBe("Incremented");
2190
+ expect8((r?.head.data).amount).toBe(3);
2191
+ expect8(r?.tail?.name).toBe("Incremented");
2192
+ expect8((r?.tail?.data).amount).toBe(1);
1712
2193
  });
1713
- it4("count + names \u2014 full aggregates including framework markers", async () => {
2194
+ it7("count + names \u2014 full aggregates including framework markers", async () => {
1714
2195
  const tag = uid();
1715
2196
  const s = `qst-cn-${tag}`;
1716
2197
  await store.commit(
@@ -1729,13 +2210,13 @@ var runStoreTck = (options) => {
1729
2210
  names: true
1730
2211
  });
1731
2212
  const r = stats.get(s);
1732
- expect5(r?.count).toBe(4);
1733
- expect5(r?.names?.[SNAP_EVENT]).toBe(1);
1734
- expect5(r?.names?.Incremented).toBe(2);
1735
- expect5(r?.names?.Decremented).toBe(1);
1736
- expect5(r?.names?.[SNAP_EVENT]).toBe(1);
2213
+ expect8(r?.count).toBe(4);
2214
+ expect8(r?.names?.[SNAP_EVENT2]).toBe(1);
2215
+ expect8(r?.names?.Incremented).toBe(2);
2216
+ expect8(r?.names?.Decremented).toBe(1);
2217
+ expect8(r?.names?.[SNAP_EVENT2]).toBe(1);
1737
2218
  });
1738
- it4("exclude shifts head past filtered events; stream absent when all filtered", async () => {
2219
+ it7("exclude shifts head past filtered events; stream absent when all filtered", async () => {
1739
2220
  const tag = uid();
1740
2221
  const s = `qst-excl-${tag}`;
1741
2222
  const sAllOut = `qst-allout-${tag}`;
@@ -1750,23 +2231,23 @@ var runStoreTck = (options) => {
1750
2231
  make_meta({ stream: sAllOut })
1751
2232
  );
1752
2233
  const all = await store.query_stats([s]);
1753
- expect5(all.get(s)?.head.name).toBe("Incremented");
1754
- expect5((all.get(s)?.head.data).amount).toBe(3);
2234
+ expect8(all.get(s)?.head.name).toBe("Incremented");
2235
+ expect8((all.get(s)?.head.data).amount).toBe(3);
1755
2236
  const excl = await store.query_stats([s], {
1756
2237
  exclude: ["Incremented"]
1757
2238
  });
1758
- expect5(excl.get(s)?.head.name).toBe("Decremented");
1759
- expect5((excl.get(s)?.head.data).amount).toBe(2);
2239
+ expect8(excl.get(s)?.head.name).toBe("Decremented");
2240
+ expect8((excl.get(s)?.head.data).amount).toBe(2);
1760
2241
  const wipe = await store.query_stats([sAllOut], {
1761
2242
  exclude: ["Incremented", "Decremented", "Reset"]
1762
2243
  });
1763
- expect5(wipe.has(sAllOut)).toBe(false);
2244
+ expect8(wipe.has(sAllOut)).toBe(false);
1764
2245
  const no_tomb = await store.query_stats([s], {
1765
2246
  exclude: [TOMBSTONE_EVENT]
1766
2247
  });
1767
- expect5(no_tomb.get(s)?.head.name).toBe("Incremented");
2248
+ expect8(no_tomb.get(s)?.head.name).toBe("Incremented");
1768
2249
  });
1769
- it4("before \u2014 time travel narrows head/tail/count", async () => {
2250
+ it7("before \u2014 time travel narrows head/tail/count", async () => {
1770
2251
  const tag = uid();
1771
2252
  const s = `qst-tt-${tag}`;
1772
2253
  const c1 = await store.commit(
@@ -1791,15 +2272,15 @@ var runStoreTck = (options) => {
1791
2272
  before
1792
2273
  });
1793
2274
  const r = stats.get(s);
1794
- expect5(r?.count).toBe(1);
1795
- expect5(r?.head.id).toBe(c1[0].id);
1796
- expect5(r?.tail?.id).toBe(c1[0].id);
2275
+ expect8(r?.count).toBe(1);
2276
+ expect8(r?.head.id).toBe(c1[0].id);
2277
+ expect8(r?.tail?.id).toBe(c1[0].id);
1797
2278
  const empty = await store.query_stats([s], {
1798
2279
  before: 0
1799
2280
  });
1800
- expect5(empty.has(s)).toBe(false);
2281
+ expect8(empty.has(s)).toBe(false);
1801
2282
  });
1802
- it4("filter form \u2014 stream regex, stream_exact, empty {} match", async () => {
2283
+ it7("filter form \u2014 stream regex, stream_exact, empty {} match", async () => {
1803
2284
  const tag = uid();
1804
2285
  const sA = `qsf-${tag}-orders-1`;
1805
2286
  const sB = `qsf-${tag}-orders-2`;
@@ -1822,18 +2303,18 @@ var runStoreTck = (options) => {
1822
2303
  const orders = await store.query_stats({
1823
2304
  stream: `^qsf-${tag}-orders-`
1824
2305
  });
1825
- expect5([...orders.keys()].sort()).toEqual([sA, sB].sort());
2306
+ expect8([...orders.keys()].sort()).toEqual([sA, sB].sort());
1826
2307
  const exact = await store.query_stats({
1827
2308
  stream: sA,
1828
2309
  stream_exact: true
1829
2310
  });
1830
- expect5([...exact.keys()]).toEqual([sA]);
2311
+ expect8([...exact.keys()]).toEqual([sA]);
1831
2312
  const all = await store.query_stats({
1832
2313
  stream: `^qsf-${tag}-`
1833
2314
  });
1834
- expect5([...all.keys()].sort()).toEqual([sA, sB, sOther].sort());
2315
+ expect8([...all.keys()].sort()).toEqual([sA, sB, sOther].sort());
1835
2316
  });
1836
- it4("compose with query_streams for subscription-level filters", async () => {
2317
+ it7("compose with query_streams for subscription-level filters", async () => {
1837
2318
  const tag = uid();
1838
2319
  const a = `qsc-${tag}-a`;
1839
2320
  const b = `qsc-${tag}-b`;
@@ -1850,7 +2331,7 @@ var runStoreTck = (options) => {
1850
2331
  );
1851
2332
  const leased = await store.claim(100, 0, `w-${uid()}`, 1e5);
1852
2333
  const mine = leased.find((l) => l.stream === a);
1853
- expect5(mine).toBeDefined();
2334
+ expect8(mine).toBeDefined();
1854
2335
  const others = leased.filter((l) => l.stream !== a);
1855
2336
  await store.ack(others);
1856
2337
  await store.block([{ ...mine, error: "boom" }]);
@@ -1859,12 +2340,12 @@ var runStoreTck = (options) => {
1859
2340
  stream: `^qsc-${tag}-`,
1860
2341
  blocked: true
1861
2342
  });
1862
- expect5(blocked_names).toEqual([a]);
2343
+ expect8(blocked_names).toEqual([a]);
1863
2344
  const stats = await store.query_stats(blocked_names);
1864
- expect5(stats.get(a)?.head.name).toBe("Incremented");
1865
- expect5(stats.has(b)).toBe(false);
2345
+ expect8(stats.get(a)?.head.name).toBe("Incremented");
2346
+ expect8(stats.has(b)).toBe(false);
1866
2347
  });
1867
- it4("empty filter {} \u2014 matches every event-bearing stream", async () => {
2348
+ it7("empty filter {} \u2014 matches every event-bearing stream", async () => {
1868
2349
  const tag = uid();
1869
2350
  const a = `qse-${tag}-a`;
1870
2351
  const b = `qse-${tag}-b`;
@@ -1879,10 +2360,10 @@ var runStoreTck = (options) => {
1879
2360
  make_meta({ stream: b })
1880
2361
  );
1881
2362
  const all = await store.query_stats({});
1882
- expect5(all.has(a)).toBe(true);
1883
- expect5(all.has(b)).toBe(true);
2363
+ expect8(all.has(a)).toBe(true);
2364
+ expect8(all.has(b)).toBe(true);
1884
2365
  });
1885
- it4("stat-flag combinations \u2014 count-only, names-only, tail-only", async () => {
2366
+ it7("stat-flag combinations \u2014 count-only, names-only, tail-only", async () => {
1886
2367
  const tag = uid();
1887
2368
  const s = `qsfl-${tag}`;
1888
2369
  await store.commit(
@@ -1893,22 +2374,22 @@ var runStoreTck = (options) => {
1893
2374
  const c = await store.query_stats([s], {
1894
2375
  count: true
1895
2376
  });
1896
- expect5(c.get(s)?.count).toBe(3);
1897
- expect5(c.get(s)?.names).toBeUndefined();
1898
- expect5(c.get(s)?.tail).toBeUndefined();
2377
+ expect8(c.get(s)?.count).toBe(3);
2378
+ expect8(c.get(s)?.names).toBeUndefined();
2379
+ expect8(c.get(s)?.tail).toBeUndefined();
1899
2380
  const n = await store.query_stats([s], {
1900
2381
  names: true
1901
2382
  });
1902
- expect5(n.get(s)?.names).toEqual({ Incremented: 2, Decremented: 1 });
1903
- expect5(n.get(s)?.count).toBeUndefined();
1904
- expect5(n.get(s)?.tail).toBeUndefined();
2383
+ expect8(n.get(s)?.names).toEqual({ Incremented: 2, Decremented: 1 });
2384
+ expect8(n.get(s)?.count).toBeUndefined();
2385
+ expect8(n.get(s)?.tail).toBeUndefined();
1905
2386
  const t = await store.query_stats([s], { tail: true });
1906
- expect5(t.get(s)?.tail?.name).toBe("Incremented");
1907
- expect5((t.get(s)?.tail?.data).amount).toBe(1);
1908
- expect5(t.get(s)?.count).toBeUndefined();
1909
- expect5(t.get(s)?.names).toBeUndefined();
2387
+ expect8(t.get(s)?.tail?.name).toBe("Incremented");
2388
+ expect8((t.get(s)?.tail?.data).amount).toBe(1);
2389
+ expect8(t.get(s)?.count).toBeUndefined();
2390
+ expect8(t.get(s)?.names).toBeUndefined();
1910
2391
  });
1911
- it4("paginates with limit + after (keyset), ordered by stream name", async () => {
2392
+ it7("paginates with limit + after (keyset), ordered by stream name", async () => {
1912
2393
  const tag = uid();
1913
2394
  const streams = [
1914
2395
  `qsp-${tag}-a`,
@@ -1928,28 +2409,28 @@ var runStoreTck = (options) => {
1928
2409
  { limit: 2 }
1929
2410
  );
1930
2411
  const k1 = [...page1.keys()];
1931
- expect5(k1).toEqual([`qsp-${tag}-a`, `qsp-${tag}-b`]);
2412
+ expect8(k1).toEqual([`qsp-${tag}-a`, `qsp-${tag}-b`]);
1932
2413
  const page2 = await store.query_stats(
1933
2414
  { stream: `qsp-${tag}-.*` },
1934
2415
  { limit: 2, after: k1.at(-1) }
1935
2416
  );
1936
2417
  const k2 = [...page2.keys()];
1937
- expect5(k2).toEqual([`qsp-${tag}-c`, `qsp-${tag}-d`]);
2418
+ expect8(k2).toEqual([`qsp-${tag}-c`, `qsp-${tag}-d`]);
1938
2419
  const page3 = await store.query_stats(
1939
2420
  { stream: `qsp-${tag}-.*` },
1940
2421
  { limit: 2, after: k2.at(-1) }
1941
2422
  );
1942
- expect5(page3.size).toBe(0);
2423
+ expect8(page3.size).toBe(0);
1943
2424
  const all = await store.query_stats({
1944
2425
  stream: `qsp-${tag}-.*`
1945
2426
  });
1946
- expect5([...all.keys()].sort()).toEqual([...streams].sort());
2427
+ expect8([...all.keys()].sort()).toEqual([...streams].sort());
1947
2428
  });
1948
2429
  });
1949
- describe5.skipIf(!caps.source_matches)(
2430
+ describe8.skipIf(!caps.source_matches)(
1950
2431
  "query_streams source_matches (capability)",
1951
2432
  () => {
1952
- it4("returns only subscriptions whose source pattern matches a name", async () => {
2433
+ it7("returns only subscriptions whose source pattern matches a name", async () => {
1953
2434
  const tag = uid();
1954
2435
  const subConcreteA = `sm-${tag}-sub-a`;
1955
2436
  const subConcreteB = `sm-${tag}-sub-b`;
@@ -1970,7 +2451,7 @@ var runStoreTck = (options) => {
1970
2451
  stream: `sm-${tag}-sub-.*`,
1971
2452
  source_matches: [srcA]
1972
2453
  });
1973
- expect5(matched.sort()).toEqual(
2454
+ expect8(matched.sort()).toEqual(
1974
2455
  [subConcreteA, subRegex, subNoSource].sort()
1975
2456
  );
1976
2457
  const none = [];
@@ -1978,20 +2459,20 @@ var runStoreTck = (options) => {
1978
2459
  stream: `sm-${tag}-sub-.*`,
1979
2460
  source_matches: [`sm-${tag}-unrelated`]
1980
2461
  });
1981
- expect5(none).toEqual([subNoSource]);
2462
+ expect8(none).toEqual([subNoSource]);
1982
2463
  const both = [];
1983
2464
  await store.query_streams((p) => both.push(p.stream), {
1984
2465
  stream: `sm-${tag}-sub-.*`,
1985
2466
  source_matches: [srcA, srcB]
1986
2467
  });
1987
- expect5(both.sort()).toEqual(
2468
+ expect8(both.sort()).toEqual(
1988
2469
  [subConcreteA, subConcreteB, subRegex, subNoSource].sort()
1989
2470
  );
1990
2471
  });
1991
2472
  }
1992
2473
  );
1993
- describe5("query_streams anchor contract", () => {
1994
- it4("plain regex without anchors is a substring match", async () => {
2474
+ describe8("query_streams anchor contract", () => {
2475
+ it7("plain regex without anchors is a substring match", async () => {
1995
2476
  const tag = uid();
1996
2477
  const inner = `qsr-${tag}-inner`;
1997
2478
  const longer = `qsr-${tag}-inner-extra`;
@@ -2005,9 +2486,9 @@ var runStoreTck = (options) => {
2005
2486
  await store.query_streams((p) => seen.push(p.stream), {
2006
2487
  stream: `qsr-${tag}-inner`
2007
2488
  });
2008
- expect5(seen.sort()).toEqual([inner, longer].sort());
2489
+ expect8(seen.sort()).toEqual([inner, longer].sort());
2009
2490
  });
2010
- it4("caller-anchored `^name$` matches only the whole string", async () => {
2491
+ it7("caller-anchored `^name$` matches only the whole string", async () => {
2011
2492
  const tag = uid();
2012
2493
  const inner = `qsr-${tag}-anchor`;
2013
2494
  const longer = `qsr-${tag}-anchor-extra`;
@@ -2016,9 +2497,9 @@ var runStoreTck = (options) => {
2016
2497
  await store.query_streams((p) => seen.push(p.stream), {
2017
2498
  stream: `^qsr-${tag}-anchor$`
2018
2499
  });
2019
- expect5(seen).toEqual([inner]);
2500
+ expect8(seen).toEqual([inner]);
2020
2501
  });
2021
- it4("caller-anchored `^prefix` matches by prefix", async () => {
2502
+ it7("caller-anchored `^prefix` matches by prefix", async () => {
2022
2503
  const tag = uid();
2023
2504
  const a = `qsr-${tag}-pfx-a`;
2024
2505
  const b = `qsr-${tag}-pfx-b`;
@@ -2032,11 +2513,11 @@ var runStoreTck = (options) => {
2032
2513
  await store.query_streams((p) => seen.push(p.stream), {
2033
2514
  stream: `^qsr-${tag}-pfx-`
2034
2515
  });
2035
- expect5(seen.sort()).toEqual([a, b].sort());
2516
+ expect8(seen.sort()).toEqual([a, b].sort());
2036
2517
  });
2037
2518
  });
2038
- describe5("prioritize anchor contract", () => {
2039
- it4("caller-anchored `^name$` filter matches only the whole string", async () => {
2519
+ describe8("prioritize anchor contract", () => {
2520
+ it7("caller-anchored `^name$` filter matches only the whole string", async () => {
2040
2521
  const tag = uid();
2041
2522
  const inner = `pr-${tag}-anchor`;
2042
2523
  const longer = `pr-${tag}-anchor-extra`;
@@ -2048,17 +2529,17 @@ var runStoreTck = (options) => {
2048
2529
  { stream: `^pr-${tag}-anchor$` },
2049
2530
  7
2050
2531
  );
2051
- expect5(updated).toBe(1);
2532
+ expect8(updated).toBe(1);
2052
2533
  const seen = /* @__PURE__ */ new Map();
2053
2534
  await store.query_streams((p) => seen.set(p.stream, p.priority), {
2054
2535
  stream: `pr-${tag}-anchor`
2055
2536
  });
2056
- expect5(seen.get(inner)).toBe(7);
2057
- expect5(seen.get(longer)).toBe(0);
2537
+ expect8(seen.get(inner)).toBe(7);
2538
+ expect8(seen.get(longer)).toBe(0);
2058
2539
  });
2059
2540
  });
2060
- describe5("query_streams head", () => {
2061
- it4("maxEventId tracks the highest committed id", async () => {
2541
+ describe8("query_streams head", () => {
2542
+ it7("maxEventId tracks the highest committed id", async () => {
2062
2543
  const s = `head-${uid()}`;
2063
2544
  await store.subscribe([{ stream: s }]);
2064
2545
  await store.commit(
@@ -2071,21 +2552,21 @@ var runStoreTck = (options) => {
2071
2552
  (p) => positions.push(p.stream),
2072
2553
  { stream: s, stream_exact: true, limit: 1 }
2073
2554
  );
2074
- expect5(maxEventId).toBeGreaterThanOrEqual(0);
2075
- expect5(positions).toEqual([s]);
2555
+ expect8(maxEventId).toBeGreaterThanOrEqual(0);
2556
+ expect8(positions).toEqual([s]);
2076
2557
  });
2077
2558
  });
2078
- describe5("seed_stream helper coverage", () => {
2079
- it4("commits N events with monotonically increasing ids", async () => {
2559
+ describe8("seed_stream helper coverage", () => {
2560
+ it7("commits N events with monotonically increasing ids", async () => {
2080
2561
  const s = `seed-${uid()}`;
2081
2562
  const committed = await seed_stream(store, s, 3);
2082
- expect5(committed).toHaveLength(3);
2563
+ expect8(committed).toHaveLength(3);
2083
2564
  for (let i = 1; i < committed.length; i++) {
2084
- expect5(committed[i].id).toBeGreaterThan(committed[i - 1].id);
2565
+ expect8(committed[i].id).toBeGreaterThan(committed[i - 1].id);
2085
2566
  }
2086
2567
  });
2087
2568
  });
2088
- describe5.skipIf(!caps.restore)("restore (capability)", () => {
2569
+ describe8.skipIf(!caps.restore)("restore (capability)", () => {
2089
2570
  beforeEach(async () => {
2090
2571
  await store.drop();
2091
2572
  await store.seed();
@@ -2122,18 +2603,18 @@ var runStoreTck = (options) => {
2122
2603
  await cache.dispose();
2123
2604
  }
2124
2605
  };
2125
- it4("returns kept=0 on an empty source", async () => {
2606
+ it7("returns kept=0 on an empty source", async () => {
2126
2607
  const result = await restore(as_source([]));
2127
- expect5(result.kept).toBe(0);
2128
- expect5(result.duration_ms).toBeGreaterThanOrEqual(0);
2129
- expect5(result.dropped).toEqual({
2608
+ expect8(result.kept).toBe(0);
2609
+ expect8(result.duration_ms).toBeGreaterThanOrEqual(0);
2610
+ expect8(result.dropped).toEqual({
2130
2611
  closed_streams: 0,
2131
2612
  snapshots: 0
2132
2613
  });
2133
2614
  const events2 = await collect(store, { limit: 10 });
2134
- expect5(events2).toHaveLength(0);
2615
+ expect8(events2).toHaveLength(0);
2135
2616
  });
2136
- it4("rebuilds a single stream and preserves `created` verbatim", async () => {
2617
+ it7("rebuilds a single stream and preserves `created` verbatim", async () => {
2137
2618
  const s = `restore-single-${uid()}`;
2138
2619
  const t0 = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
2139
2620
  const t1 = /* @__PURE__ */ new Date("2020-01-02T00:00:00.000Z");
@@ -2144,7 +2625,7 @@ var runStoreTck = (options) => {
2144
2625
  event(3, s, 2, "Decremented", t2, { amount: 1 })
2145
2626
  ];
2146
2627
  const result = await restore(as_source(events2));
2147
- expect5(result.kept).toBe(3);
2628
+ expect8(result.kept).toBe(3);
2148
2629
  const back = [];
2149
2630
  await store.query(
2150
2631
  (e) => {
@@ -2152,8 +2633,8 @@ var runStoreTck = (options) => {
2152
2633
  },
2153
2634
  { stream: s, stream_exact: true }
2154
2635
  );
2155
- expect5(back).toHaveLength(3);
2156
- expect5(
2636
+ expect8(back).toHaveLength(3);
2637
+ expect8(
2157
2638
  back.map((e) => ({
2158
2639
  stream: e.stream,
2159
2640
  version: e.version,
@@ -2185,7 +2666,7 @@ var runStoreTck = (options) => {
2185
2666
  }
2186
2667
  ]);
2187
2668
  });
2188
- it4("rebuilds multiple streams interleaved", async () => {
2669
+ it7("rebuilds multiple streams interleaved", async () => {
2189
2670
  const a = `restore-multi-a-${uid()}`;
2190
2671
  const b = `restore-multi-b-${uid()}`;
2191
2672
  const t = /* @__PURE__ */ new Date("2020-06-01T00:00:00.000Z");
@@ -2196,7 +2677,7 @@ var runStoreTck = (options) => {
2196
2677
  event(4, b, 1, "Incremented", t, { amount: 30 })
2197
2678
  ];
2198
2679
  const result = await restore(as_source(events2));
2199
- expect5(result.kept).toBe(4);
2680
+ expect8(result.kept).toBe(4);
2200
2681
  const aBack = [];
2201
2682
  const bBack = [];
2202
2683
  await store.query(
@@ -2211,10 +2692,10 @@ var runStoreTck = (options) => {
2211
2692
  },
2212
2693
  { stream: b, stream_exact: true }
2213
2694
  );
2214
- expect5(aBack.map((e) => e.version)).toEqual([0, 1]);
2215
- expect5(bBack.map((e) => e.version)).toEqual([0, 1]);
2695
+ expect8(aBack.map((e) => e.version)).toEqual([0, 1]);
2696
+ expect8(bBack.map((e) => e.version)).toEqual([0, 1]);
2216
2697
  });
2217
- it4("preserves Date `created` verbatim", async () => {
2698
+ it7("preserves Date `created` verbatim", async () => {
2218
2699
  const s = `restore-isoc-${uid()}`;
2219
2700
  const iso = "2021-07-15T12:34:56.789Z";
2220
2701
  await restore(
@@ -2237,10 +2718,10 @@ var runStoreTck = (options) => {
2237
2718
  },
2238
2719
  { stream: s, stream_exact: true }
2239
2720
  );
2240
- expect5(back).toHaveLength(1);
2241
- expect5(back[0].created.toISOString()).toBe(iso);
2721
+ expect8(back).toHaveLength(1);
2722
+ expect8(back[0].created.toISOString()).toBe(iso);
2242
2723
  });
2243
- it4("wipes pre-existing events before inserting", async () => {
2724
+ it7("wipes pre-existing events before inserting", async () => {
2244
2725
  const old = `restore-old-${uid()}`;
2245
2726
  await store.commit(
2246
2727
  old,
@@ -2256,14 +2737,14 @@ var runStoreTck = (options) => {
2256
2737
  stream: old,
2257
2738
  stream_exact: true
2258
2739
  });
2259
- expect5(old_back).toHaveLength(0);
2740
+ expect8(old_back).toHaveLength(0);
2260
2741
  const fresh_back = await collect(store, {
2261
2742
  stream: fresh,
2262
2743
  stream_exact: true
2263
2744
  });
2264
- expect5(fresh_back).toHaveLength(1);
2745
+ expect8(fresh_back).toHaveLength(1);
2265
2746
  });
2266
- it4("clears subscription/stream-position metadata", async () => {
2747
+ it7("clears subscription/stream-position metadata", async () => {
2267
2748
  const sub = `restore-sub-${uid()}`;
2268
2749
  await store.subscribe([{ stream: sub, source: "anything" }]);
2269
2750
  const collect_streams = async () => {
@@ -2274,12 +2755,12 @@ var runStoreTck = (options) => {
2274
2755
  return out;
2275
2756
  };
2276
2757
  const before = await collect_streams();
2277
- expect5(before.includes(sub)).toBe(true);
2758
+ expect8(before.includes(sub)).toBe(true);
2278
2759
  await restore(as_source([]));
2279
2760
  const after = await collect_streams();
2280
- expect5(after.includes(sub)).toBe(false);
2761
+ expect8(after.includes(sub)).toBe(false);
2281
2762
  });
2282
- it4("preserves snapshot events through restore", async () => {
2763
+ it7("preserves snapshot events through restore", async () => {
2283
2764
  const s = `restore-snap-${uid()}`;
2284
2765
  const t = /* @__PURE__ */ new Date("2020-04-01T00:00:00.000Z");
2285
2766
  await restore(
@@ -2288,7 +2769,7 @@ var runStoreTck = (options) => {
2288
2769
  id: 1,
2289
2770
  stream: s,
2290
2771
  version: 0,
2291
- name: SNAP_EVENT,
2772
+ name: SNAP_EVENT2,
2292
2773
  data: { count: 42 },
2293
2774
  created: t,
2294
2775
  meta: { correlation: "snap", causation: {} }
@@ -2300,10 +2781,10 @@ var runStoreTck = (options) => {
2300
2781
  stream_exact: true,
2301
2782
  with_snaps: true
2302
2783
  });
2303
- expect5(back).toHaveLength(1);
2304
- expect5(back[0].name).toBe(SNAP_EVENT);
2784
+ expect8(back).toHaveLength(1);
2785
+ expect8(back[0].name).toBe(SNAP_EVENT2);
2305
2786
  });
2306
- it4("rewrites causation refs through the old\u2192new id map", async () => {
2787
+ it7("rewrites causation refs through the old\u2192new id map", async () => {
2307
2788
  const s = `restore-caus-${uid()}`;
2308
2789
  const t = /* @__PURE__ */ new Date("2020-08-01T00:00:00.000Z");
2309
2790
  const events2 = [
@@ -2353,12 +2834,12 @@ var runStoreTck = (options) => {
2353
2834
  },
2354
2835
  { stream: s, stream_exact: true }
2355
2836
  );
2356
- expect5(back).toHaveLength(3);
2357
- expect5(back[0].meta.causation.event).toBeUndefined();
2358
- expect5(back[1].meta.causation.event?.id).toBe(back[0].id);
2359
- expect5(back[2].meta.causation.event?.id).toBe(back[1].id);
2837
+ expect8(back).toHaveLength(3);
2838
+ expect8(back[0].meta.causation.event).toBeUndefined();
2839
+ expect8(back[1].meta.causation.event?.id).toBe(back[0].id);
2840
+ expect8(back[2].meta.causation.event?.id).toBe(back[1].id);
2360
2841
  });
2361
- it4("leaves causation refs unmapped when the target isn't in the source", async () => {
2842
+ it7("leaves causation refs unmapped when the target isn't in the source", async () => {
2362
2843
  const s = `restore-orphan-${uid()}`;
2363
2844
  const t = /* @__PURE__ */ new Date("2020-09-01T00:00:00.000Z");
2364
2845
  await restore(
@@ -2386,9 +2867,9 @@ var runStoreTck = (options) => {
2386
2867
  },
2387
2868
  { stream: s, stream_exact: true }
2388
2869
  );
2389
- expect5(back[0].meta.causation.event?.id).toBe(999);
2870
+ expect8(back[0].meta.causation.event?.id).toBe(999);
2390
2871
  });
2391
- it4("rolls back atomically when the source throws mid-iteration", async () => {
2872
+ it7("rolls back atomically when the source throws mid-iteration", async () => {
2392
2873
  const original = `restore-pre-${uid()}`;
2393
2874
  const committed = await store.commit(
2394
2875
  original,
@@ -2414,7 +2895,7 @@ var runStoreTck = (options) => {
2414
2895
  async dispose() {
2415
2896
  }
2416
2897
  };
2417
- await expect5(restore(explosive)).rejects.toThrow("boom");
2898
+ await expect8(restore(explosive)).rejects.toThrow("boom");
2418
2899
  const back = [];
2419
2900
  await store.query(
2420
2901
  (e) => {
@@ -2422,10 +2903,10 @@ var runStoreTck = (options) => {
2422
2903
  },
2423
2904
  { stream: original, stream_exact: true }
2424
2905
  );
2425
- expect5(back).toHaveLength(3);
2426
- expect5(back.map((e) => e.id)).toEqual(committed.map((c) => c.id));
2906
+ expect8(back).toHaveLength(3);
2907
+ expect8(back.map((e) => e.id)).toEqual(committed.map((c) => c.id));
2427
2908
  });
2428
- it4("drop_snapshots: skips SNAP_EVENT rows and counts them", async () => {
2909
+ it7("drop_snapshots: skips SNAP_EVENT rows and counts them", async () => {
2429
2910
  const s = `restore-drop-snap-${uid()}`;
2430
2911
  const t = /* @__PURE__ */ new Date("2020-10-01T00:00:00.000Z");
2431
2912
  const result = await restore(
@@ -2435,7 +2916,7 @@ var runStoreTck = (options) => {
2435
2916
  id: 2,
2436
2917
  stream: s,
2437
2918
  version: 1,
2438
- name: SNAP_EVENT,
2919
+ name: SNAP_EVENT2,
2439
2920
  data: { count: 1 },
2440
2921
  created: t,
2441
2922
  meta: { correlation: "snap", causation: {} }
@@ -2444,19 +2925,19 @@ var runStoreTck = (options) => {
2444
2925
  ]),
2445
2926
  { drop_snapshots: true }
2446
2927
  );
2447
- expect5(result.kept).toBe(2);
2448
- expect5(result.dropped.snapshots).toBe(1);
2928
+ expect8(result.kept).toBe(2);
2929
+ expect8(result.dropped.snapshots).toBe(1);
2449
2930
  const back = await collect(store, {
2450
2931
  stream: s,
2451
2932
  stream_exact: true,
2452
2933
  with_snaps: true
2453
2934
  });
2454
- expect5(back).toHaveLength(2);
2455
- expect5(
2456
- back.every((e) => e.name !== SNAP_EVENT)
2935
+ expect8(back).toHaveLength(2);
2936
+ expect8(
2937
+ back.every((e) => e.name !== SNAP_EVENT2)
2457
2938
  ).toBe(true);
2458
2939
  });
2459
- it4("on_progress fires once per event (caller throttles)", async () => {
2940
+ it7("on_progress fires once per event (caller throttles)", async () => {
2460
2941
  const calls = [];
2461
2942
  const s = `restore-progress-${uid()}`;
2462
2943
  const t = /* @__PURE__ */ new Date("2021-02-01T00:00:00.000Z");
@@ -2467,11 +2948,11 @@ var runStoreTck = (options) => {
2467
2948
  ]),
2468
2949
  { on_progress: (p) => calls.push(p.processed) }
2469
2950
  );
2470
- expect5(calls).toEqual([1, 2]);
2951
+ expect8(calls).toEqual([1, 2]);
2471
2952
  });
2472
2953
  });
2473
- describe5.skipIf(!caps.pii_isolation)("pii_isolation (capability)", () => {
2474
- it4("commits and loads pii alongside data", async () => {
2954
+ describe8.skipIf(!caps.pii_isolation)("pii_isolation (capability)", () => {
2955
+ it7("commits and loads pii alongside data", async () => {
2475
2956
  const s = `pii-roundtrip-${uid()}`;
2476
2957
  const committed = await store.commit(
2477
2958
  s,
@@ -2484,8 +2965,8 @@ var runStoreTck = (options) => {
2484
2965
  ],
2485
2966
  make_meta({ stream: s })
2486
2967
  );
2487
- expect5(committed).toHaveLength(1);
2488
- expect5(committed[0].pii).toEqual({
2968
+ expect8(committed).toHaveLength(1);
2969
+ expect8(committed[0].pii).toEqual({
2489
2970
  email: "u@example.com",
2490
2971
  name: "Ursula"
2491
2972
  });
@@ -2496,11 +2977,11 @@ var runStoreTck = (options) => {
2496
2977
  },
2497
2978
  { stream: s, stream_exact: true }
2498
2979
  );
2499
- expect5(seen).toHaveLength(1);
2500
- expect5(seen[0].pii).toEqual({ email: "u@example.com", name: "Ursula" });
2501
- expect5(seen[0].data).toEqual({ amount: 1 });
2980
+ expect8(seen).toHaveLength(1);
2981
+ expect8(seen[0].pii).toEqual({ email: "u@example.com", name: "Ursula" });
2982
+ expect8(seen[0].data).toEqual({ amount: 1 });
2502
2983
  });
2503
- it4("passes through events without pii (pii is null or undefined on load)", async () => {
2984
+ it7("passes through events without pii (pii is null or undefined on load)", async () => {
2504
2985
  const s = `pii-none-${uid()}`;
2505
2986
  await store.commit(
2506
2987
  s,
@@ -2514,10 +2995,10 @@ var runStoreTck = (options) => {
2514
2995
  },
2515
2996
  { stream: s, stream_exact: true }
2516
2997
  );
2517
- expect5(seen).toHaveLength(1);
2518
- expect5(seen[0].pii == null).toBe(true);
2998
+ expect8(seen).toHaveLength(1);
2999
+ expect8(seen[0].pii == null).toBe(true);
2519
3000
  });
2520
- it4("wipes pii for every event on the stream via forget_pii", async () => {
3001
+ it7("wipes pii for every event on the stream via forget_pii", async () => {
2521
3002
  const s = `pii-forget-${uid()}`;
2522
3003
  await store.commit(
2523
3004
  s,
@@ -2536,9 +3017,9 @@ var runStoreTck = (options) => {
2536
3017
  make_meta({ stream: s })
2537
3018
  );
2538
3019
  const forget = store.forget_pii;
2539
- expect5(forget).toBeDefined();
3020
+ expect8(forget).toBeDefined();
2540
3021
  const wiped = await forget.call(store, s);
2541
- expect5(wiped).toBe(2);
3022
+ expect8(wiped).toBe(2);
2542
3023
  const seen = [];
2543
3024
  await store.query(
2544
3025
  (e) => {
@@ -2546,13 +3027,13 @@ var runStoreTck = (options) => {
2546
3027
  },
2547
3028
  { stream: s, stream_exact: true }
2548
3029
  );
2549
- expect5(seen).toHaveLength(2);
3030
+ expect8(seen).toHaveLength(2);
2550
3031
  for (const e of seen) {
2551
- expect5(e.pii == null).toBe(true);
2552
- expect5(e.data).toBeDefined();
3032
+ expect8(e.pii == null).toBe(true);
3033
+ expect8(e.data).toBeDefined();
2553
3034
  }
2554
3035
  });
2555
- it4("is idempotent \u2014 second forget_pii returns 0, no error", async () => {
3036
+ it7("is idempotent \u2014 second forget_pii returns 0, no error", async () => {
2556
3037
  const s = `pii-forget-idem-${uid()}`;
2557
3038
  await store.commit(
2558
3039
  s,
@@ -2567,11 +3048,11 @@ var runStoreTck = (options) => {
2567
3048
  );
2568
3049
  const forget = store.forget_pii;
2569
3050
  const first = await forget.call(store, s);
2570
- expect5(first).toBe(1);
3051
+ expect8(first).toBe(1);
2571
3052
  const second = await forget.call(store, s);
2572
- expect5(second).toBe(0);
3053
+ expect8(second).toBe(0);
2573
3054
  });
2574
- it4("only wipes the targeted stream \u2014 siblings untouched", async () => {
3055
+ it7("only wipes the targeted stream \u2014 siblings untouched", async () => {
2575
3056
  const sA = `pii-iso-a-${uid()}`;
2576
3057
  const sB = `pii-iso-b-${uid()}`;
2577
3058
  await store.commit(
@@ -2604,7 +3085,7 @@ var runStoreTck = (options) => {
2604
3085
  },
2605
3086
  { stream: sA, stream_exact: true }
2606
3087
  );
2607
- expect5(a[0].pii == null).toBe(true);
3088
+ expect8(a[0].pii == null).toBe(true);
2608
3089
  const b = [];
2609
3090
  await store.query(
2610
3091
  (e) => {
@@ -2612,9 +3093,9 @@ var runStoreTck = (options) => {
2612
3093
  },
2613
3094
  { stream: sB, stream_exact: true }
2614
3095
  );
2615
- expect5(b[0].pii).toEqual({ email: "bob@example.com" });
3096
+ expect8(b[0].pii).toEqual({ email: "bob@example.com" });
2616
3097
  });
2617
- it4("forget_pii on a stream with no pii events returns 0", async () => {
3098
+ it7("forget_pii on a stream with no pii events returns 0", async () => {
2618
3099
  const s = `pii-forget-empty-${uid()}`;
2619
3100
  await store.commit(
2620
3101
  s,
@@ -2622,14 +3103,14 @@ var runStoreTck = (options) => {
2622
3103
  make_meta({ stream: s })
2623
3104
  );
2624
3105
  const wiped = await store.forget_pii.call(store, s);
2625
- expect5(wiped).toBe(0);
3106
+ expect8(wiped).toBe(0);
2626
3107
  });
2627
3108
  });
2628
3109
  if (caps.notify) {
2629
- describe5("notify (capability)", () => {
2630
- it4("delivers a notification when a different instance commits", async () => {
3110
+ describe8("notify (capability)", () => {
3111
+ it7("delivers a notification when a different instance commits", async () => {
2631
3112
  const notify = store.notify;
2632
- expect5(notify).toBeDefined();
3113
+ expect8(notify).toBeDefined();
2633
3114
  const received = [];
2634
3115
  let resolve_arrived;
2635
3116
  const arrived = new Promise((res) => {
@@ -2648,9 +3129,9 @@ var runStoreTck = (options) => {
2648
3129
  make_meta({ stream })
2649
3130
  );
2650
3131
  await arrived;
2651
- expect5(received.length).toBeGreaterThanOrEqual(1);
2652
- expect5(received[0].stream).toBe(stream);
2653
- expect5(received[0].events.length).toBeGreaterThanOrEqual(1);
3132
+ expect8(received.length).toBeGreaterThanOrEqual(1);
3133
+ expect8(received[0].stream).toBe(stream);
3134
+ expect8(received[0].events.length).toBeGreaterThanOrEqual(1);
2654
3135
  } finally {
2655
3136
  await writer.dispose();
2656
3137
  await Promise.resolve(disposer());
@@ -2671,9 +3152,12 @@ export {
2671
3152
  dec,
2672
3153
  inc,
2673
3154
  reset,
3155
+ runCacheDifferentialTck,
2674
3156
  runCacheTck,
3157
+ runLoggerDifferentialTck,
2675
3158
  runLoggerTck,
2676
3159
  runStabilityTck,
3160
+ runStoreDifferentialTck,
2677
3161
  runStorePropertyTck,
2678
3162
  runStoreTck,
2679
3163
  uid