@voltro/testing 0.51.0 → 0.53.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,15 +1,15 @@
1
1
  import { AUTO_FILLED_COLUMNS as e, allRegisteredTables as t, changeDelete as n, changeInsert as r, changeSoftDelete as i, changeUpdate as a, clearRelationsRegistry as o, missingRequiredColumns as s, registerRelations as c } from "@voltro/database";
2
2
  import { Cause as l, Effect as u, Exit as d, Layer as f, Schema as p } from "effect";
3
3
  import { SubjectService as m, anonymousSubject as h, checkGuardsEffect as g, composeAuthStrategies as _, composeRpcInterceptors as v, eventRoute as y, systemSubject as b, tenantScopedSubject as ee } from "@voltro/protocol";
4
- import { EventBus as te, InMemoryDataStore as ne, NO_ROW_FILTER as x, applyRowFilterToDescriptor as re, clearSystemStoreHandle as ie, getRowFilter as S, getSystemStoreHandle as ae, makeAppAccess as oe, makeDataLoader as se, makeEffectStoreLayer as ce, makeEventPublisher as le, makeOutboxFacade as ue, makeSchemaRegistry as de, publishEvent as fe, resolveRowFilterScopeFor as pe, runProvidedEffect as C, runWithDeadlockRetry as me, setSystemStoreHandle as w, wrapStoreWithMixinBehaviour as T } from "@voltro/runtime";
5
- import { installEnvSnapshot as he } from "@voltro/env";
6
- import ge from "node:net";
7
- import { describe as _e } from "vitest";
8
- import { collectPublicApiRoutes as ve, dispatchSharedPath as ye, restRoutesToHttpRoutes as be } from "@voltro/protocol/rest";
9
- import { createLogger as xe } from "@voltro/logger";
10
- import { CurrentWorkflowRunId as Se, inMemoryWorkflowEngineLayer as Ce, makeInMemoryRecorder as we } from "@voltro/workflow";
4
+ import { EventBus as te, InMemoryDataStore as ne, NO_ROW_FILTER as x, appValidation as re, applyRowFilterToDescriptor as ie, clearSystemStoreHandle as ae, getRowFilter as S, getSystemStoreHandle as oe, makeAppAccess as se, makeDataLoader as ce, makeEffectStoreLayer as le, makeEventPublisher as ue, makeOutboxFacade as de, makeSchemaRegistry as fe, publishEvent as pe, resolveRowFilterScopeFor as me, runProvidedEffect as C, runWithDeadlockRetry as he, setSystemStoreHandle as w, wrapStoreWithMixinBehaviour as T } from "@voltro/runtime";
5
+ import { installEnvSnapshot as ge } from "@voltro/env";
6
+ import _e from "node:net";
7
+ import { describe as ve } from "vitest";
8
+ import { collectPublicApiRoutes as ye, dispatchSharedPath as be, restRoutesToHttpRoutes as xe } from "@voltro/protocol/rest";
9
+ import { createLogger as Se } from "@voltro/logger";
10
+ import { CurrentWorkflowRunId as Ce, inMemoryWorkflowEngineLayer as we, makeInMemoryRecorder as Te } from "@voltro/workflow";
11
11
  //#region src/fixtureRow.ts
12
- var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
12
+ var Ee = new Set(e), E = 0, De = () => ++E, Oe = (e, t) => {
13
13
  if (t.oneOf && t.oneOf.length > 0) return t.oneOf[0];
14
14
  if (t.enumValues && t.enumValues.length > 0) return t.enumValues[0];
15
15
  let n = t.unique === !0;
@@ -27,21 +27,21 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
27
27
  case "date": return /* @__PURE__ */ new Date(0);
28
28
  default: throw Error(`fixtureRow: column '${e}' is a required '${t.type}' with no default, and fixtureRow can't synthesize a safe placeholder for that type. Pass it explicitly: fixtureRow(table, { ${e}: … }).`);
29
29
  }
30
- }, O = (e, t = {}) => {
30
+ }, D = (e, t = {}) => {
31
31
  let n = {};
32
- for (let r of s(e, t)) Te.has(r) || (n[r] = Ee(r, e.fields[r]));
32
+ for (let r of s(e, t)) Ee.has(r) || (n[r] = Oe(r, e.fields[r]));
33
33
  return {
34
34
  ...n,
35
35
  ...t
36
36
  };
37
- }, De = (e) => {
37
+ }, ke = (e) => {
38
38
  let t = {};
39
- for (let [n, r] of Object.entries(e)) t[n] = typeof r == "function" ? r(D()) : r;
39
+ for (let [n, r] of Object.entries(e)) t[n] = typeof r == "function" ? r(De()) : r;
40
40
  return t;
41
- }, Oe = (e) => {
41
+ }, Ae = (e) => {
42
42
  for (let [t, n] of Object.entries(e.fields)) if (n.type === "id") return t;
43
43
  return "id";
44
- }, ke = async (e, t, n, r, i) => {
44
+ }, je = async (e, t, n, r, i) => {
45
45
  let a = {};
46
46
  for (let o of s(t, n)) {
47
47
  let n = t.fields[o];
@@ -49,29 +49,29 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
49
49
  let s = n.references();
50
50
  if (i.includes(s.tableName)) throw Error(`defineFactory: creating '${t.tableName}' requires '${s.tableName}' via '${o}', and that reference is cyclic (${[...i, s.tableName].join(" → ")}). Insert one side first and pass the id: create(store, { ${o}: existing.id }).`);
51
51
  let c = r[o];
52
- a[o] = (c === void 0 ? await k(e, s, {}, {}, [...i, s.tableName]) : await c.create(e, {}))[Oe(s)];
52
+ a[o] = (c === void 0 ? await O(e, s, {}, {}, [...i, s.tableName]) : await c.create(e, {}))[Ae(s)];
53
53
  }
54
54
  return a;
55
- }, k = async (e, t, n, r, i) => {
55
+ }, O = async (e, t, n, r, i) => {
56
56
  let a = {
57
- ...await ke(e, t, n, r, i),
57
+ ...await je(e, t, n, r, i),
58
58
  ...n
59
59
  };
60
- return e.insert(t.tableName, O(t, a));
61
- }, A = (e, t) => typeof e == "function" ? e(t) : e ?? {}, Ae = (e, t = {}) => {
60
+ return e.insert(t.tableName, D(t, a));
61
+ }, k = (e, t) => typeof e == "function" ? e(t) : e ?? {}, Me = (e, t = {}) => {
62
62
  let n = t.traits ?? {}, r = t.associations ?? {}, i = (t) => {
63
63
  let a = (e = {}) => ({
64
- ...De(t),
64
+ ...ke(t),
65
65
  ...e
66
- }), o = (t = {}) => O(e, a(t));
66
+ }), o = (t = {}) => D(e, a(t));
67
67
  return {
68
68
  table: e,
69
69
  build: o,
70
- buildList: (e, t) => Array.from({ length: e }, (e, n) => o(A(t, n))),
71
- create: (t, n = {}) => k(t, e, a(n), r, [e.tableName]),
70
+ buildList: (e, t) => Array.from({ length: e }, (e, n) => o(k(t, n))),
71
+ create: (t, n = {}) => O(t, e, a(n), r, [e.tableName]),
72
72
  createList: async (t, n, i) => {
73
73
  let o = [];
74
- for (let s = 0; s < n; s++) o.push(await k(t, e, a(A(i, s)), r, [e.tableName]));
74
+ for (let s = 0; s < n; s++) o.push(await O(t, e, a(k(i, s)), r, [e.tableName]));
75
75
  return o;
76
76
  },
77
77
  with: (...r) => {
@@ -93,19 +93,19 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
93
93
  };
94
94
  };
95
95
  return i(t.defaults ?? {});
96
- }, j = Symbol.for("voltro/testing/mockClock.installed"), M = () => globalThis, je = (e, t) => new Proxy(e, {
96
+ }, A = Symbol.for("voltro/testing/mockClock.installed"), j = () => globalThis, Ne = (e, t) => new Proxy(e, {
97
97
  construct: (e, n, r) => Reflect.construct(e, n.length === 0 ? [t()] : n, r),
98
98
  apply: () => new e(t()).toString(),
99
99
  get: (e, n, r) => n === "now" ? () => t() : Reflect.get(e, n, r)
100
- }), N = (e) => {
100
+ }), Pe = (e) => {
101
101
  if (typeof e == "number") return e;
102
102
  let t = e instanceof Date ? e.getTime() : Date.parse(e);
103
103
  if (Number.isNaN(t)) throw Error(`mockClock: cannot read an instant from '${String(e)}'`);
104
104
  return t;
105
- }, P = class {
105
+ }, M = class {
106
106
  currentMs;
107
107
  constructor(e = "2026-01-01T00:00:00Z") {
108
- this.currentMs = N(e);
108
+ this.currentMs = Pe(e);
109
109
  }
110
110
  now() {
111
111
  return this.currentMs;
@@ -114,47 +114,47 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
114
114
  return new Date(this.currentMs);
115
115
  }
116
116
  advance(e) {
117
- this.currentMs += typeof e == "number" ? e : Fe(e);
117
+ this.currentMs += typeof e == "number" ? e : Re(e);
118
118
  }
119
119
  set(e) {
120
- this.currentMs = N(e);
120
+ this.currentMs = Pe(e);
121
121
  }
122
122
  get installed() {
123
- return M()[j]?.clock === this;
123
+ return j()[A]?.clock === this;
124
124
  }
125
125
  install() {
126
- let e = M(), t = e[j];
126
+ let e = j(), t = e[A];
127
127
  if (t !== void 0) throw Error("mockClock: global time is already faked" + (t.clock === this ? " by this same clock" : " by another MockClock") + ". Uninstall it before installing again — a nested install restores the outer fake on the way out, which leaves the realm frozen with nothing pointing at why. `withFrozenTime` always restores, including on a throw.");
128
128
  let n = globalThis.Date;
129
- return e[j] = {
129
+ return e[A] = {
130
130
  realDate: n,
131
131
  clock: this
132
- }, globalThis.Date = je(n, () => this.currentMs), () => {
132
+ }, globalThis.Date = Ne(n, () => this.currentMs), () => {
133
133
  this.uninstall();
134
134
  };
135
135
  }
136
136
  uninstall() {
137
- let e = M(), t = e[j];
138
- t !== void 0 && t.clock === this && (globalThis.Date = t.realDate, delete e[j]);
137
+ let e = j(), t = e[A];
138
+ t !== void 0 && t.clock === this && (globalThis.Date = t.realDate, delete e[A]);
139
139
  }
140
- }, Me = (e) => typeof e == "object" && !!e && typeof e.then == "function", Ne = (e, t) => {
141
- let n = e instanceof P ? e : new P(e);
140
+ }, Fe = (e) => typeof e == "object" && !!e && typeof e.then == "function", Ie = (e, t) => {
141
+ let n = e instanceof M ? e : new M(e);
142
142
  n.install();
143
143
  let r = !1;
144
144
  try {
145
145
  let e = t(n);
146
- return Me(e) ? (r = !0, e.then((e) => (n.uninstall(), e), (e) => {
146
+ return Fe(e) ? (r = !0, e.then((e) => (n.uninstall(), e), (e) => {
147
147
  throw n.uninstall(), e;
148
148
  })) : e;
149
149
  } finally {
150
150
  r || n.uninstall();
151
151
  }
152
- }, Pe = (e) => u.acquireRelease(u.sync(() => {
153
- let t = e instanceof P ? e : new P(e);
152
+ }, Le = (e) => u.acquireRelease(u.sync(() => {
153
+ let t = e instanceof M ? e : new M(e);
154
154
  return t.install(), t;
155
155
  }), (e) => u.sync(() => {
156
156
  e.uninstall();
157
- })), Fe = (e) => {
157
+ })), Re = (e) => {
158
158
  let t = /^\s*(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)\s*$/.exec(e);
159
159
  if (!t) throw Error(`mockClock: cannot parse duration '${e}'`);
160
160
  let n = Number(t[1]), r = t[2];
@@ -166,7 +166,7 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
166
166
  case "d": return n * 864e5;
167
167
  default: throw Error(`mockClock: unknown unit '${r}'`);
168
168
  }
169
- }, F = class {
169
+ }, N = class {
170
170
  emitted = [];
171
171
  async emit(e, t) {
172
172
  let n = typeof e == "string" ? e : e.id ?? e.event ?? "(unnamed event)";
@@ -185,14 +185,14 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
185
185
  clear() {
186
186
  this.emitted.length = 0;
187
187
  }
188
- }, I = (e = {}) => {
188
+ }, P = (e = {}) => {
189
189
  let t = e.tenantId ?? null, n = new te({
190
190
  origin: e.origin ?? "test",
191
191
  ...e.ringSize === void 0 ? {} : { ringSize: e.ringSize }
192
192
  });
193
193
  return {
194
194
  publish: async (e, r, i) => {
195
- let a = await u.runPromise(u.either(fe({
195
+ let a = await u.runPromise(u.either(pe({
196
196
  bus: n,
197
197
  tenantId: t
198
198
  }, e, r, i)));
@@ -255,7 +255,7 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
255
255
  n.clear();
256
256
  }
257
257
  };
258
- }, L = class {
258
+ }, F = class {
259
259
  queue;
260
260
  calls = [];
261
261
  constructor(e) {
@@ -270,32 +270,32 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
270
270
  remaining() {
271
271
  return this.queue.length;
272
272
  }
273
- }, Ie = (e) => e, R = "00000000000000000000000000000000", z = /* @__PURE__ */ new WeakMap(), B = /* @__PURE__ */ new WeakMap(), V = /* @__PURE__ */ new WeakMap(), H = /* @__PURE__ */ new WeakMap(), U = /* @__PURE__ */ new WeakMap(), W = (e, t) => {
274
- let n = H.get(e) ?? [], r = t === "mutation" ? "interceptMutation" : t === "query" ? "interceptQuery" : "interceptAction", i = [];
273
+ }, ze = (e) => e, I = "00000000000000000000000000000000", L = /* @__PURE__ */ new WeakMap(), R = /* @__PURE__ */ new WeakMap(), z = /* @__PURE__ */ new WeakMap(), B = /* @__PURE__ */ new WeakMap(), V = /* @__PURE__ */ new WeakMap(), H = (e, t) => {
274
+ let n = B.get(e) ?? [], r = t === "mutation" ? "interceptMutation" : t === "query" ? "interceptQuery" : "interceptAction", i = [];
275
275
  for (let e of n) {
276
276
  let t = e[r];
277
277
  typeof t == "function" && i.push(t);
278
278
  }
279
279
  return v(i);
280
- }, G = (e) => {
281
- let t = (H.get(e) ?? []).map((e) => e.services).filter((e) => e !== void 0), n = U.get(e) ?? [], r = [...t, ...n];
280
+ }, U = (e) => {
281
+ let t = (B.get(e) ?? []).map((e) => e.services).filter((e) => e !== void 0), n = V.get(e) ?? [], r = [...t, ...n];
282
282
  if (r.length !== 0) return f.mergeAll(...r);
283
- }, K = (e) => {
284
- let t = B.get(e);
283
+ }, W = (e) => {
284
+ let t = R.get(e);
285
285
  t !== void 0 && (t.length = 0);
286
- }, q = async (e) => {
287
- let t = B.get(e);
286
+ }, G = async (e) => {
287
+ let t = R.get(e);
288
288
  if (t === void 0 || t.length === 0) return;
289
289
  let n = [...t];
290
290
  t.length = 0;
291
291
  for (let e of n) await e();
292
- }, Le = (e) => V.get(e) ?? [], J = async (e, t) => {
293
- let n = z.get(e);
292
+ }, Be = (e) => z.get(e) ?? [], K = async (e, t) => {
293
+ let n = L.get(e);
294
294
  return n === void 0 ? e.store.transactional(async (n) => t({
295
295
  ...e,
296
296
  store: n
297
297
  })) : n(t);
298
- }, Re = (e) => {
298
+ }, Ve = (e) => {
299
299
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = (n) => {
300
300
  let r = t.get(n);
301
301
  return r === void 0 ? !1 : r.expiresAt !== null && r.expiresAt <= e() ? (t.delete(n), !1) : !0;
@@ -334,7 +334,7 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
334
334
  return i(e, o, n.ttlMs, n.tags), o;
335
335
  }
336
336
  };
337
- }, ze = (e) => {
337
+ }, He = (e) => {
338
338
  let t = /* @__PURE__ */ new Map(), n = (n) => {
339
339
  let r = t.get(n);
340
340
  return r === void 0 ? !1 : r.expiresAt !== null && r.expiresAt <= e() ? (t.delete(n), !1) : !0;
@@ -362,49 +362,49 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
362
362
  t.clear();
363
363
  }
364
364
  };
365
- }, Be = async (e, t) => {
366
- let n = ae();
365
+ }, Ue = async (e, t) => {
366
+ let n = oe();
367
367
  w(e);
368
368
  try {
369
369
  return await t();
370
370
  } finally {
371
- n === void 0 ? ie() : w(n);
371
+ n === void 0 ? ae() : w(n);
372
372
  }
373
- }, Y = /* @__PURE__ */ new Set(), Ve = (e) => {
374
- Y.has(e) || (Y.add(e), console.warn(e));
375
- }, He = (e, t, n) => {
376
- let r = Ue, i;
373
+ }, q = /* @__PURE__ */ new Set(), We = (e) => {
374
+ q.has(e) || (q.add(e), console.warn(e));
375
+ }, Ge = (e, t, n) => {
376
+ let r = Ke, i;
377
377
  return () => {
378
378
  let a = t ?? S();
379
- return t !== void 0 && S() !== void 0 && t !== S() && Ve("[voltro:testing] this test passes `rowFilter:` while a DIFFERENT filter is registered via `setRowFilter`. The option wins, so this test does not exercise your app's registration. Drop `rowFilter:` to run the real process-global one."), (i === void 0 || a !== r) && (r = a, i = Be(n, () => C(pe(a, e, (e) => {
379
+ return t !== void 0 && S() !== void 0 && t !== S() && We("[voltro:testing] this test passes `rowFilter:` while a DIFFERENT filter is registered via `setRowFilter`. The option wins, so this test does not exercise your app's registration. Drop `rowFilter:` to run the real process-global one."), (i === void 0 || a !== r) && (r = a, i = Ue(n, () => C(me(a, e, (e) => {
380
380
  console.error("[voltro:testing] row filter failed to load — reads refused for this subject", e);
381
381
  })))), i;
382
382
  };
383
- }, Ue = Symbol("unresolved"), X = (e, t) => new Proxy(e, { get: (e, n) => {
384
- if (n === "query") return async (n) => e.query(re(await t(), n));
383
+ }, Ke = Symbol("unresolved"), J = (e, t) => new Proxy(e, { get: (e, n) => {
384
+ if (n === "query") return async (n) => e.query(ie(await t(), n));
385
385
  let r = Reflect.get(e, n, e);
386
386
  return typeof r == "function" ? r.bind(e) : r;
387
- } }), We = (e = {}) => {
388
- if (he({
387
+ } }), qe = (e = {}) => {
388
+ if (ge({
389
389
  ...process.env,
390
390
  ...e.env ?? {}
391
391
  }), e.relations !== void 0) {
392
392
  o();
393
393
  for (let t of e.relations) c(t);
394
394
  }
395
- let n = e.tables ?? t(), r = de(n), i = new ne(e.store ?? {}), a = {
395
+ let n = e.tables ?? t(), r = fe(n), i = new ne(e.store ?? {}), a = {
396
396
  dataStore: i,
397
397
  schemaRegistry: r
398
398
  };
399
399
  w(a);
400
- let s = new P(e.clockStart), l = new F(), u = I(), d = new L(e.llmResponses ?? []), f = Re(() => s.now()), p = ze(() => s.now()), m = (t, n = i, o) => {
400
+ let s = new M(e.clockStart), l = new N(), u = P(), d = new F(e.llmResponses ?? []), f = Ve(() => s.now()), p = He(() => s.now()), m = (t, n = i, o) => {
401
401
  let c = {
402
402
  subject: t,
403
- traceId: R
404
- }, h = le({
403
+ traceId: I
404
+ }, h = ue({
405
405
  bus: u.bus,
406
406
  tenantId: t.tenantId ?? null
407
- }), g = o?.queued ?? [], _ = o?.nudges ?? [], v = se({ store: n }), y = He(t, e.rowFilter, a), b = {
407
+ }), g = o?.queued ?? [], _ = o?.nudges ?? [], v = ce({ store: n }), y = Ge(t, e.rowFilter, a), b = {
408
408
  clock: s,
409
409
  webhooks: l,
410
410
  events: h,
@@ -412,25 +412,26 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
412
412
  llm: d,
413
413
  ...e.ai === void 0 ? {} : { ai: e.ai },
414
414
  request: c,
415
- access: oe(t),
415
+ validation: re,
416
+ access: se(t),
416
417
  cache: f,
417
418
  kv: p,
418
- store: T(X(n, y), {
419
+ store: T(J(n, y), {
419
420
  subject: t,
420
421
  schemaRegistry: r,
421
422
  rowFilter: x
422
423
  }),
423
- storeForTenant: (e) => T(X(n, y), {
424
+ storeForTenant: (e) => T(J(n, y), {
424
425
  subject: ee(t, e),
425
426
  schemaRegistry: r,
426
427
  rowFilter: x
427
428
  }),
428
- outbox: ue({
429
+ outbox: de({
429
430
  store: n,
430
431
  subject: t,
431
- traceId: R,
432
+ traceId: I,
432
433
  nudge: () => {
433
- _.push(R);
434
+ _.push(I);
434
435
  },
435
436
  afterCommit: (e) => {
436
437
  g.push(e);
@@ -450,19 +451,19 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
450
451
  nudges: _
451
452
  })))
452
453
  };
453
- return B.set(b, g), V.set(b, _), H.set(b, e.plugins ?? []), U.set(b, e.layers ?? []), z.set(b, (e) => n.transactional((n) => e(m(t, n, {
454
+ return R.set(b, g), z.set(b, _), B.set(b, e.plugins ?? []), V.set(b, e.layers ?? []), L.set(b, (e) => n.transactional((n) => e(m(t, n, {
454
455
  queued: g,
455
456
  nudges: _
456
457
  })))), b;
457
458
  };
458
459
  return m(e.subject ?? h(null));
459
- }, Ge = (e, t) => {
460
- let n = G(t);
461
- return (n === void 0 ? e : u.provide(e, n)).pipe(u.provide(ce(t.store)), u.provideService(m, t.request.subject));
462
- }, Ke = async (e, t, n, r) => {
460
+ }, Je = (e, t) => {
461
+ let n = U(t);
462
+ return (n === void 0 ? e : u.provide(e, n)).pipe(u.provide(le(t.store)), u.provideService(m, t.request.subject));
463
+ }, Y = async (e, t, n, r) => {
463
464
  let i = e.input, a = await p.decodeUnknownPromise(i)(n), o = e.kind, s = async (e) => {
464
465
  let n = t(a, e);
465
- return u.isEffect(n) ? C(Ge(n, e)) : n;
466
+ return u.isEffect(n) ? C(Je(n, e)) : n;
466
467
  }, c = async () => {
467
468
  let t = e.guards;
468
469
  if (t !== void 0 && t.length > 0) {
@@ -470,9 +471,9 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
470
471
  if (e !== null) throw e;
471
472
  }
472
473
  if (o !== "mutation") return s(r);
473
- let n = await me(async () => (K(r), J(r, async (e) => s(e))), { delay: () => Promise.resolve() });
474
- return await q(r), n;
475
- }, f = o === "mutation" || o === "query" || o === "action" ? o : void 0, m = f === void 0 ? void 0 : W(r, f);
474
+ let n = await he(async () => (W(r), K(r, async (e) => s(e))), { delay: () => Promise.resolve() });
475
+ return await G(r), n;
476
+ }, f = o === "mutation" || o === "query" || o === "action" ? o : void 0, m = f === void 0 ? void 0 : H(r, f);
476
477
  if (m === void 0 || f === void 0) return await c();
477
478
  let h = m(u.tryPromise({
478
479
  try: () => c(),
@@ -487,8 +488,8 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
487
488
  }), _ = await u.runPromiseExit(h);
488
489
  if (d.isSuccess(_)) return _.value;
489
490
  throw l.squash(_.cause);
490
- }, qe = (e) => new Promise((t) => {
491
- let n = new ge.Socket(), r = (e) => {
491
+ }, X = (e) => new Promise((t) => {
492
+ let n = new _e.Socket(), r = (e) => {
492
493
  clearTimeout(i), n.destroy(), t(e);
493
494
  }, i = setTimeout(() => r(!1), e.timeoutMs ?? 750);
494
495
  n.once("connect", () => r(!0)), n.once("error", () => r(!1)), n.connect(e.port, e.host);
@@ -500,21 +501,21 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
500
501
  } catch {
501
502
  i = !1;
502
503
  }
503
- _e.skipIf(!i)(i ? e : `${e} [SKIPPED: needs ${t}]`, r);
504
- }, Je = async (e, t, n) => {
505
- await Z(e, `${t.name} at ${t.host}:${t.port}`, () => qe(t), n);
506
- }, Ye = async (e, t) => {
504
+ ve.skipIf(!i)(i ? e : `${e} [SKIPPED: needs ${t}]`, r);
505
+ }, Ye = async (e, t, n) => {
506
+ await Z(e, `${t.name} at ${t.host}:${t.port}`, () => X(t), n);
507
+ }, Xe = async (e, t) => {
507
508
  try {
508
509
  let n = await t();
509
510
  n !== void 0 && n !== "" && console.log(`[engine] ${e}: ${n}`);
510
511
  } catch {}
511
- }, Xe = "test-tenant", Q = (e, t, n) => ({
512
+ }, Ze = "test-tenant", Q = (e, t, n) => ({
512
513
  type: e,
513
514
  id: t,
514
515
  tenantId: n.tenantId ?? "test-tenant",
515
516
  scopes: n.scopes ?? [],
516
517
  ...n.metadata === void 0 ? {} : { metadata: n.metadata }
517
- }), Ze = (e, t = {}) => Q("user", e, t), Qe = (e, t = {}) => Q("apiKey", e, t), $e = (e, t = {}) => Q("serviceAccount", e, t), et = (e = null) => h(e), tt = (e = "job:test", t) => t === void 0 ? b(e) : b(e, t), nt = (e) => {
518
+ }), Qe = (e, t = {}) => Q("user", e, t), $e = (e, t = {}) => Q("apiKey", e, t), et = (e, t = {}) => Q("serviceAccount", e, t), tt = (e = null) => h(e), nt = (e = "job:test", t) => t === void 0 ? b(e) : b(e, t), rt = (e) => {
518
519
  let t = e.indexOf("?");
519
520
  return t === -1 ? {
520
521
  path: e,
@@ -523,17 +524,17 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
523
524
  path: e.slice(0, t),
524
525
  query: e.slice(t + 1)
525
526
  };
526
- }, rt = (e, t) => {
527
+ }, it = (e, t) => {
527
528
  let n = e.split("/").filter((e) => e.length > 0), r = t.split("/").filter((e) => e.length > 0);
528
529
  return n.length === r.length && n.every((e, t) => e.startsWith(":") || e === r[t]);
529
530
  }, $ = (e) => {
530
531
  let t = {};
531
532
  for (let [n, r] of Object.entries(e)) t[n.toLowerCase()] = r;
532
533
  return t;
533
- }, it = (e) => e === void 0 ? /* @__PURE__ */ new Uint8Array() : new TextEncoder().encode(JSON.stringify(e)), at = (e) => e === void 0 ? "" : typeof e == "string" ? e : new TextDecoder().decode(e), ot = (e) => {
534
- let { ctx: t } = e, n = ve((e.publicApi ?? []).map((e) => ({
534
+ }, at = (e) => e === void 0 ? /* @__PURE__ */ new Uint8Array() : new TextEncoder().encode(JSON.stringify(e)), ot = (e) => e === void 0 ? "" : typeof e == "string" ? e : new TextDecoder().decode(e), st = (e) => {
535
+ let { ctx: t } = e, n = ye((e.publicApi ?? []).map((e) => ({
535
536
  descriptor: e.descriptor,
536
- invoke: (n, r) => t.withSubject(r.subject, (t) => Ke(e.descriptor, e.handler, n, t))
537
+ invoke: (n, r) => t.withSubject(r.subject, (t) => Y(e.descriptor, e.handler, n, t))
537
538
  }))), r = [...e.restRoutes ?? [], ...n], i = _(e.strategies ?? [], {
538
539
  ...e.anonymousTenantRequired === void 0 ? {} : { anonymousTenantRequired: e.anonymousTenantRequired },
539
540
  getStore: () => t.store
@@ -545,11 +546,11 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
545
546
  clientId: -1
546
547
  })).subject : () => n,
547
548
  ...e.idempotency === void 0 ? {} : { idempotency: e.idempotency }
548
- }, c = be(r, s).map((e, t) => ({
549
+ }, c = xe(r, s).map((e, t) => ({
549
550
  pattern: r[t].path,
550
551
  route: e
551
552
  })), l = async (e, n, i = {}) => {
552
- let { path: a, query: s } = nt(n), l = c.filter((e) => rt(e.pattern, a)).map((e) => e.route);
553
+ let { path: a, query: s } = rt(n), l = c.filter((e) => it(e.pattern, a)).map((e) => e.route);
553
554
  if (l.length === 0) return {
554
555
  status: 404,
555
556
  headers: {},
@@ -568,11 +569,11 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
568
569
  ...$(o),
569
570
  ...$(i.headers ?? {})
570
571
  },
571
- rawBody: it(i.body),
572
+ rawBody: at(i.body),
572
573
  store: t.store
573
- }, d = await ye(l, u), f = $(d.headers ?? {});
574
+ }, d = await be(l, u), f = $(d.headers ?? {});
574
575
  d.contentType !== void 0 && (f["content-type"] = d.contentType);
575
- let p = at(d.body), m = (d.contentType ?? "").includes("json");
576
+ let p = ot(d.body), m = (d.contentType ?? "").includes("json");
576
577
  return {
577
578
  status: d.status,
578
579
  headers: f,
@@ -606,17 +607,17 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
606
607
  };
607
608
  };
608
609
  return a(void 0, {});
609
- }, st = (e = {}) => {
610
+ }, ct = (e = {}) => {
610
611
  let t = e.id ?? "test", n = e.store ?? new Proxy({}, { get: (e, t) => {
611
612
  throw Error(`makeSubscribeContext: this subscriber reached ctx.store.${String(t)} and the test passed no store. Pass \`{ store: makeTestContext().store }\` so the subscriber and the code under test share one — an empty stand-in would let a read of the wrong table pass.`);
612
613
  } });
613
614
  return {
614
615
  id: t,
615
- log: e.log ?? xe({ scope: `subscribe:${t}` }),
616
+ log: e.log ?? Se({ scope: `subscribe:${t}` }),
616
617
  store: n,
617
618
  ...e.publish === void 0 ? {} : { publish: e.publish }
618
619
  };
619
- }, ct = (e) => {
620
+ }, lt = (e) => {
620
621
  let t = /* @__PURE__ */ new Map();
621
622
  for (let n of e) {
622
623
  let e = t.get(n.stepName);
@@ -642,13 +643,13 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
642
643
  });
643
644
  }
644
645
  return n.sort((e, t) => e._startedAt - t._startedAt), n.map(({ _startedAt: e, ...t }) => t);
645
- }, lt = (e) => {
646
+ }, ut = (e) => {
646
647
  let t = e.workflows ?? [], n = /* @__PURE__ */ new Map(), r = 0;
647
648
  return {
648
649
  start: async (i, a) => {
649
650
  let o = t.find((e) => e.workflow.name === i);
650
651
  if (o === void 0) throw Error(`makeWorkflowRunner: no workflow named '${i}' — pass it in makeWorkflowRunner({ ctx, workflows: [{ workflow, execute }] }).`);
651
- let s = `wfrun_test_${++r}`, c = we(), l = o.workflow.toLayer(o.execute).pipe(f.provideMerge(Ce)), d = /* @__PURE__ */ new Date(), p = o.workflow.execute(a).pipe(u.locally(Se, s), u.provide(c.layer), u.provide(l), u.either), m = await u.runPromise(p), h = ct(c.readSteps()), g = /* @__PURE__ */ new Date(), _;
652
+ let s = `wfrun_test_${++r}`, c = Te(), l = o.workflow.toLayer(o.execute).pipe(f.provideMerge(we)), d = /* @__PURE__ */ new Date(), p = o.workflow.execute(a).pipe(u.locally(Ce, s), u.provide(c.layer), u.provide(l), u.either), m = await u.runPromise(p), h = lt(c.readSteps()), g = /* @__PURE__ */ new Date(), _;
652
653
  if (m._tag === "Right") _ = {
653
654
  status: "succeeded",
654
655
  output: m.right,
@@ -688,6 +689,6 @@ var Te = new Set(e), E = 0, D = () => ++E, Ee = (e, t) => {
688
689
  },
689
690
  inspect: async (e) => n.get(e) ?? null
690
691
  };
691
- }, ut = 1;
692
+ }, dt = 1;
692
693
  //#endregion
693
- export { P as MockClock, L as MockLLM, F as MockWebhooks, ut as TESTING_PRESET_VERSION, Xe as TEST_TENANT_ID, et as anonymous, Qe as apiKey, n as changeDelete, r as changeInsert, i as changeSoftDelete, a as changeUpdate, Ae as defineFactory, Z as describeIfAvailable, Je as describeIfReachable, O as fixtureRow, Pe as frozenTime, Ke as invoke, qe as isTcpReachable, st as makeSubscribeContext, ot as makeTestApp, We as makeTestContext, lt as makeWorkflowRunner, Ie as mockStore, D as nextSequence, Le as outboxNudgesOf, Ye as reportEngineVersion, K as resetAfterCommit, W as rpcInterceptorFor, q as runAfterCommit, J as runInStoreTransaction, $e as serviceAccount, G as serviceLayerFor, tt as system, I as testEventBus, Ze as user, Ne as withFrozenTime };
694
+ export { M as MockClock, F as MockLLM, N as MockWebhooks, dt as TESTING_PRESET_VERSION, Ze as TEST_TENANT_ID, tt as anonymous, $e as apiKey, n as changeDelete, r as changeInsert, i as changeSoftDelete, a as changeUpdate, Me as defineFactory, Z as describeIfAvailable, Ye as describeIfReachable, D as fixtureRow, Le as frozenTime, Y as invoke, X as isTcpReachable, ct as makeSubscribeContext, st as makeTestApp, qe as makeTestContext, ut as makeWorkflowRunner, ze as mockStore, De as nextSequence, Be as outboxNudgesOf, Xe as reportEngineVersion, W as resetAfterCommit, H as rpcInterceptorFor, G as runAfterCommit, K as runInStoreTransaction, et as serviceAccount, U as serviceLayerFor, nt as system, P as testEventBus, Qe as user, Ie as withFrozenTime };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/testing",
3
- "version": "0.51.0",
3
+ "version": "0.53.0",
4
4
  "description": "Test utilities for Voltro apps — deterministic clock, subject and row factories, a handler-level invoke and a request-level app harness, queued LLM responses, scoped subject/tenant runners, and a cross-dialect parity harness.",
5
5
  "keywords": [
6
6
  "voltro",
@@ -43,15 +43,15 @@
43
43
  "node": ">=24.0.0"
44
44
  },
45
45
  "dependencies": {
46
- "@voltro/database": "0.51.0",
47
- "@voltro/env": "0.51.0",
48
- "@voltro/logger": "0.51.0",
49
- "@voltro/protocol": "0.51.0",
50
- "@voltro/runtime": "0.51.0",
51
- "@voltro/workflow": "0.51.0"
46
+ "@voltro/database": "0.53.0",
47
+ "@voltro/env": "0.53.0",
48
+ "@voltro/logger": "0.53.0",
49
+ "@voltro/protocol": "0.53.0",
50
+ "@voltro/runtime": "0.53.0",
51
+ "@voltro/workflow": "0.53.0"
52
52
  },
53
53
  "peerDependencies": {
54
- "@voltro/client": "0.51.0",
54
+ "@voltro/client": "0.53.0",
55
55
  "effect": "^3.22.0",
56
56
  "react": "^19.0.0",
57
57
  "@effect/sql": "^0.52.0"