@voltro/testing 0.69.1 → 0.71.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,47 +1,47 @@
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 x, InMemoryDataStore as te, NO_ROW_FILTER as S, appValidation as ne, applyRowFilterToDescriptor as re, clearSystemStoreHandle as ie, getRowFilter as C, getSystemStoreHandle as ae, makeAppAccess as oe, makeConnectionState 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 w, runWithDeadlockRetry as he, setSystemStoreHandle as T, wrapStoreWithMixinBehaviour as E } 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";
4
+ import { EventBus as x, InMemoryDataStore as S, NO_ROW_FILTER as C, appValidation as te, applyRowFilterToDescriptor as ne, clearSystemStoreHandle as re, getRowFilter as w, getSystemStoreHandle as ie, makeAppAccess as ae, makeConnectionState as oe, makeDataLoader as se, makeEffectStoreLayer as ce, makeEventPublisher as le, makeFieldCipher as ue, makeOutboxFacade as de, makeSchemaRegistry as fe, publishEvent as pe, resolveRowFilterScopeFor as me, resolveTransactionSubject as he, runProvidedEffect as T, runWithDeadlockRetry as ge, setFieldCipher as _e, setSystemStoreHandle as E, wrapStoreWithMixinBehaviour as D } from "@voltro/runtime";
5
+ import { installEnvSnapshot as ve } from "@voltro/env";
6
+ import ye from "node:net";
7
+ import { describe as be } from "vitest";
8
+ import { collectPublicApiRoutes as xe, dispatchSharedPath as Se, restRoutesToHttpRoutes as Ce } from "@voltro/protocol/rest";
9
+ import { createLogger as we } from "@voltro/logger";
10
+ import { CurrentWorkflowRunId as Te, inMemoryWorkflowEngineLayer as Ee, makeInMemoryRecorder as De } from "@voltro/workflow";
11
11
  //#region src/fixtureRow.ts
12
- var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
12
+ var Oe = new Set(e), O = 0, k = () => ++O, ke = (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;
16
16
  switch (t.type) {
17
17
  case "text":
18
18
  case "id":
19
- case "enum": return n ? `${e}-${++D}` : e;
20
- case "reference": return t.referenceStorage === "numeric" ? n ? ++D : 0 : n ? `${e}-${++D}` : e;
19
+ case "enum": return n ? `${e}-${++O}` : e;
20
+ case "reference": return t.referenceStorage === "numeric" ? n ? ++O : 0 : n ? `${e}-${++O}` : e;
21
21
  case "integer":
22
- case "real": return n ? ++D : 0;
22
+ case "real": return n ? ++O : 0;
23
23
  case "decimal":
24
- case "bigint": return n ? String(++D) : "0";
24
+ case "bigint": return n ? String(++O) : "0";
25
25
  case "boolean": return !1;
26
26
  case "timestamp":
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
- }, k = (e, t = {}) => {
30
+ }, A = (e, t = {}) => {
31
31
  let n = {};
32
- for (let r of s(e, t)) Ee.has(r) || (n[r] = De(r, e.fields[r]));
32
+ for (let r of s(e, t)) Oe.has(r) || (n[r] = ke(r, e.fields[r]));
33
33
  return {
34
34
  ...n,
35
35
  ...t
36
36
  };
37
- }, Oe = (e) => {
37
+ }, Ae = (e) => {
38
38
  let t = {};
39
- for (let [n, r] of Object.entries(e)) t[n] = typeof r == "function" ? r(O()) : r;
39
+ for (let [n, r] of Object.entries(e)) t[n] = typeof r == "function" ? r(k()) : r;
40
40
  return t;
41
- }, ke = (e) => {
41
+ }, je = (e) => {
42
42
  for (let [t, n] of Object.entries(e.fields)) if (n.type === "id") return t;
43
43
  return "id";
44
- }, Ae = async (e, t, n, r, i) => {
44
+ }, Me = 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 Ee = new Set(e), D = 0, O = () => ++D, De = (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 A(e, s, {}, {}, [...i, s.tableName]) : await c.create(e, {}))[n.referenceColumn ?? ke(s)];
52
+ a[o] = (c === void 0 ? await j(e, s, {}, {}, [...i, s.tableName]) : await c.create(e, {}))[n.referenceColumn ?? je(s)];
53
53
  }
54
54
  return a;
55
- }, A = async (e, t, n, r, i) => {
55
+ }, j = async (e, t, n, r, i) => {
56
56
  let a = {
57
- ...await Ae(e, t, n, r, i),
57
+ ...await Me(e, t, n, r, i),
58
58
  ...n
59
59
  };
60
- return e.insert(t.tableName, k(t, a));
61
- }, j = (e, t) => typeof e == "function" ? e(t) : e ?? {}, je = (e, t = {}) => {
60
+ return e.insert(t.tableName, A(t, a));
61
+ }, M = (e, t) => typeof e == "function" ? e(t) : e ?? {}, Ne = (e, t = {}) => {
62
62
  let n = t.traits ?? {}, r = t.associations ?? {}, i = (t) => {
63
63
  let a = (e = {}) => ({
64
- ...Oe(t),
64
+ ...Ae(t),
65
65
  ...e
66
- }), o = (t = {}) => k(e, a(t));
66
+ }), o = (t = {}) => A(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(j(t, n))),
71
- create: (t, n = {}) => A(t, e, a(n), r, [e.tableName]),
70
+ buildList: (e, t) => Array.from({ length: e }, (e, n) => o(M(t, n))),
71
+ create: (t, n = {}) => j(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 A(t, e, a(j(i, s)), r, [e.tableName]));
74
+ for (let s = 0; s < n; s++) o.push(await j(t, e, a(M(i, s)), r, [e.tableName]));
75
75
  return o;
76
76
  },
77
77
  with: (...r) => {
@@ -93,19 +93,19 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
93
93
  };
94
94
  };
95
95
  return i(t.defaults ?? {});
96
- }, M = Symbol.for("voltro/testing/mockClock.installed"), N = () => globalThis, Me = (e, t) => new Proxy(e, {
96
+ }, N = Symbol.for("voltro/testing/mockClock.installed"), P = () => globalThis, Pe = (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
- }), P = (e) => {
100
+ }), F = (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
- }, F = class {
105
+ }, I = class {
106
106
  currentMs;
107
107
  constructor(e = "2026-01-01T00:00:00Z") {
108
- this.currentMs = P(e);
108
+ this.currentMs = F(e);
109
109
  }
110
110
  now() {
111
111
  return this.currentMs;
@@ -114,47 +114,47 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
114
114
  return new Date(this.currentMs);
115
115
  }
116
116
  advance(e) {
117
- this.currentMs += typeof e == "number" ? e : Ie(e);
117
+ this.currentMs += typeof e == "number" ? e : Re(e);
118
118
  }
119
119
  set(e) {
120
- this.currentMs = P(e);
120
+ this.currentMs = F(e);
121
121
  }
122
122
  get installed() {
123
- return N()[M]?.clock === this;
123
+ return P()[N]?.clock === this;
124
124
  }
125
125
  install() {
126
- let e = N(), t = e[M];
126
+ let e = P(), t = e[N];
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[M] = {
129
+ return e[N] = {
130
130
  realDate: n,
131
131
  clock: this
132
- }, globalThis.Date = Me(n, () => this.currentMs), () => {
132
+ }, globalThis.Date = Pe(n, () => this.currentMs), () => {
133
133
  this.uninstall();
134
134
  };
135
135
  }
136
136
  uninstall() {
137
- let e = N(), t = e[M];
138
- t !== void 0 && t.clock === this && (globalThis.Date = t.realDate, delete e[M]);
137
+ let e = P(), t = e[N];
138
+ t !== void 0 && t.clock === this && (globalThis.Date = t.realDate, delete e[N]);
139
139
  }
140
- }, Ne = (e) => typeof e == "object" && !!e && typeof e.then == "function", Pe = (e, t) => {
141
- let n = e instanceof F ? e : new F(e);
140
+ }, Fe = (e) => typeof e == "object" && !!e && typeof e.then == "function", Ie = (e, t) => {
141
+ let n = e instanceof I ? e : new I(e);
142
142
  n.install();
143
143
  let r = !1;
144
144
  try {
145
145
  let e = t(n);
146
- return Ne(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
- }, Fe = (e) => u.acquireRelease(u.sync(() => {
153
- let t = e instanceof F ? e : new F(e);
152
+ }, Le = (e) => u.acquireRelease(u.sync(() => {
153
+ let t = e instanceof I ? e : new I(e);
154
154
  return t.install(), t;
155
155
  }), (e) => u.sync(() => {
156
156
  e.uninstall();
157
- })), Ie = (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 Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
166
166
  case "d": return n * 864e5;
167
167
  default: throw Error(`mockClock: unknown unit '${r}'`);
168
168
  }
169
- }, I = class {
169
+ }, L = 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,7 +185,7 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
185
185
  clear() {
186
186
  this.emitted.length = 0;
187
187
  }
188
- }, L = (e = {}) => {
188
+ }, R = (e = {}) => {
189
189
  let t = e.tenantId ?? null, n = new x({
190
190
  origin: e.origin ?? "test",
191
191
  ...e.ringSize === void 0 ? {} : { ringSize: e.ringSize }
@@ -255,7 +255,7 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
255
255
  n.clear();
256
256
  }
257
257
  };
258
- }, R = class {
258
+ }, z = class {
259
259
  queue;
260
260
  calls = [];
261
261
  constructor(e) {
@@ -270,36 +270,38 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
270
270
  remaining() {
271
271
  return this.queue.length;
272
272
  }
273
- }, Le = (e) => e, z = "00000000000000000000000000000000", B = /* @__PURE__ */ new WeakMap(), V = /* @__PURE__ */ new WeakMap(), Re = (e, t) => {
274
- let n = V.get(e);
273
+ }, ze = (e) => e, B = "00000000000000000000000000000000", V = /* @__PURE__ */ new WeakMap(), H = /* @__PURE__ */ new WeakMap(), Be = (e, t) => {
274
+ let n = H.get(e);
275
275
  if (n === void 0) throw Error("withRpcConnection requires a context created by makeTestContext");
276
276
  return n(t);
277
- }, H = /* @__PURE__ */ new WeakMap(), U = /* @__PURE__ */ new WeakMap(), W = /* @__PURE__ */ new WeakMap(), G = /* @__PURE__ */ new WeakMap(), K = (e, t) => {
278
- let n = W.get(e) ?? [], r = t === "mutation" ? "interceptMutation" : t === "query" ? "interceptQuery" : "interceptAction", i = [];
277
+ }, U = /* @__PURE__ */ new WeakMap(), W = /* @__PURE__ */ new WeakMap(), G = /* @__PURE__ */ new WeakMap(), K = (e) => G.get(e) ?? [], q = /* @__PURE__ */ new WeakMap(), J = (e, t) => {
278
+ q.set(e, { publicApi: t });
279
+ }, Y = (e) => q.get(e), X = /* @__PURE__ */ new WeakMap(), Ve = (e, t) => {
280
+ let n = G.get(e) ?? [], r = t === "mutation" ? "interceptMutation" : t === "query" ? "interceptQuery" : "interceptAction", i = [];
279
281
  for (let e of n) {
280
282
  let t = e[r];
281
283
  typeof t == "function" && i.push(t);
282
284
  }
283
285
  return v(i);
284
- }, q = (e) => {
285
- let t = (W.get(e) ?? []).map((e) => e.services).filter((e) => e !== void 0), n = G.get(e) ?? [], r = [...t, ...n];
286
+ }, He = (e) => {
287
+ let t = (G.get(e) ?? []).map((e) => e.services).filter((e) => e !== void 0), n = X.get(e) ?? [], r = [...t, ...n];
286
288
  if (r.length !== 0) return f.mergeAll(...r);
287
- }, J = (e) => {
288
- let t = H.get(e);
289
+ }, Ue = (e) => {
290
+ let t = U.get(e);
289
291
  t !== void 0 && (t.length = 0);
290
- }, Y = async (e) => {
291
- let t = H.get(e);
292
+ }, Z = async (e) => {
293
+ let t = U.get(e);
292
294
  if (t === void 0 || t.length === 0) return;
293
295
  let n = [...t];
294
296
  t.length = 0;
295
297
  for (let e of n) await e();
296
- }, ze = (e) => U.get(e) ?? [], X = async (e, t) => {
297
- let n = B.get(e);
298
+ }, We = (e) => W.get(e) ?? [], Ge = async (e, t) => {
299
+ let n = V.get(e);
298
300
  return n === void 0 ? e.store.transactional(async (n) => t({
299
301
  ...e,
300
302
  store: n
301
303
  })) : n(t);
302
- }, Be = (e) => {
304
+ }, Ke = (e) => {
303
305
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = (n) => {
304
306
  let r = t.get(n);
305
307
  return r === void 0 ? !1 : r.expiresAt !== null && r.expiresAt <= e() ? (t.delete(n), !1) : !0;
@@ -338,7 +340,7 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
338
340
  return i(e, o, n.ttlMs, n.tags), o;
339
341
  }
340
342
  };
341
- }, Ve = (e) => {
343
+ }, qe = (e) => {
342
344
  let t = /* @__PURE__ */ new Map(), n = (n) => {
343
345
  let r = t.get(n);
344
346
  return r === void 0 ? !1 : r.expiresAt !== null && r.expiresAt <= e() ? (t.delete(n), !1) : !0;
@@ -366,131 +368,144 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
366
368
  t.clear();
367
369
  }
368
370
  };
369
- }, He = async (e, t) => {
370
- let n = ae();
371
- T(e);
371
+ }, Je = async (e, t) => {
372
+ let n = ie();
373
+ E(e);
372
374
  try {
373
375
  return await t();
374
376
  } finally {
375
- n === void 0 ? ie() : T(n);
377
+ n === void 0 ? re() : E(n);
376
378
  }
377
- }, Z = /* @__PURE__ */ new Set(), Ue = (e) => {
378
- Z.has(e) || (Z.add(e), console.warn(e));
379
- }, We = (e, t, n) => {
380
- let r = Ge, i;
379
+ }, Ye = /* @__PURE__ */ new Set(), Xe = (e) => {
380
+ Ye.has(e) || (Ye.add(e), console.warn(e));
381
+ }, Ze = (e, t, n) => {
382
+ let r = Qe, i;
381
383
  return () => {
382
- let a = t ?? C();
383
- return t !== void 0 && C() !== void 0 && t !== C() && Ue("[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 = He(n, () => w(me(a, e, (e) => {
384
+ let a = t ?? w();
385
+ return t !== void 0 && w() !== void 0 && t !== w() && Xe("[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 = Je(n, () => T(me(a, e, (e) => {
384
386
  console.error("[voltro:testing] row filter failed to load — reads refused for this subject", e);
385
387
  })))), i;
386
388
  };
387
- }, Ge = Symbol("unresolved"), Ke = (e, t) => new Proxy(e, { get: (e, n) => {
388
- if (n === "query") return async (n) => e.query(re(await t(), n));
389
+ }, Qe = Symbol("unresolved"), $e = (e, t) => new Proxy(e, { get: (e, n) => {
390
+ if (n === "query") return async (n) => e.query(ne(await t(), n));
389
391
  let r = Reflect.get(e, n, e);
390
392
  return typeof r == "function" ? r.bind(e) : r;
391
- } }), qe = (e = {}) => {
392
- if (ge({
393
+ } }), et = (e = {}) => {
394
+ if (ve({
393
395
  ...process.env,
394
396
  ...e.env ?? {}
395
- }), e.relations !== void 0) {
397
+ }), e.fieldEncryptionKey !== void 0 && _e(ue(e.fieldEncryptionKey)), e.relations !== void 0) {
396
398
  o();
397
399
  for (let t of e.relations) c(t);
398
400
  }
399
- let n = e.tables ?? t(), r = fe(n), i = new te(e.store ?? {}), a = {
401
+ let n = e.tables ?? t(), r = fe(n), i = new S(e.store ?? {}), a = {
400
402
  dataStore: i,
401
403
  schemaRegistry: r
402
404
  };
403
- T(a);
404
- let s = new F(e.clockStart), l = new I(), u = L(), d = new R(e.llmResponses ?? []), f = Be(() => s.now()), p = Ve(() => s.now()), m = (t, n, o = i, c) => {
405
- let h = {
405
+ E(a);
406
+ let s = new I(e.clockStart), l = new L(), u = R(), d = new z(e.llmResponses ?? []), f = Ke(() => s.now()), p = qe(() => s.now()), m = (t, n, o = i, c, h = !1) => {
407
+ let g = {
406
408
  subject: t,
407
- traceId: z,
409
+ traceId: B,
408
410
  ...n === void 0 ? {} : { connection: n }
409
- }, g = c?.queued ?? [], _ = c?.nudges ?? [], v = ue({
411
+ }, _ = c?.queued ?? [], v = c?.nudges ?? [], y = le({
410
412
  bus: u.bus,
411
413
  tenantId: t.tenantId ?? null,
412
414
  ...o === i ? {} : { deferToCommit: (e) => {
413
- g.push(async () => {
415
+ _.push(async () => {
414
416
  e();
415
417
  });
416
418
  } }
417
- }), y = ce({ store: o }), b = We(t, e.rowFilter, a), x = {
419
+ }), b = se({ store: o }), x = h ? async () => C : Ze(t, e.rowFilter, a), S = {
420
+ transaction: async (e, r) => {
421
+ let a = he(t, r?.tenantId, o !== i);
422
+ if (a !== t) return m(a, n, i, void 0, !0).transaction(e);
423
+ if (o !== i) return e(S);
424
+ let s, c = await o.transactional(async (r) => {
425
+ let i = m(t, n, r, {
426
+ queued: [],
427
+ nudges: []
428
+ }, h), a = await e(i);
429
+ return s = i, a;
430
+ });
431
+ return s !== void 0 && (await Z(s), v.push(...We(s))), c;
432
+ },
418
433
  clock: s,
419
434
  webhooks: l,
420
- events: v,
435
+ events: y,
421
436
  eventBus: u,
422
437
  llm: d,
423
438
  ...e.ai === void 0 ? {} : { ai: e.ai },
424
- request: h,
425
- ...n === void 0 ? {} : { connectionState: se(n, o === i ? void 0 : (e) => {
426
- g.push(e);
439
+ request: g,
440
+ ...n === void 0 ? {} : { connectionState: oe(n, o === i ? void 0 : (e) => {
441
+ _.push(e);
427
442
  }) },
428
- validation: ne,
429
- access: oe(t),
443
+ validation: te,
444
+ access: ae(t),
430
445
  cache: f,
431
446
  kv: p,
432
- store: E(Ke(o, b), {
447
+ store: D($e(o, x), {
433
448
  subject: t,
434
449
  schemaRegistry: r,
435
- rowFilter: S
450
+ rowFilter: C
436
451
  }),
437
- storeForTenant: (e) => E(Ke(o, b), {
452
+ storeForTenant: (e) => D($e(o, x), {
438
453
  subject: ee(t, e),
439
454
  schemaRegistry: r,
440
- rowFilter: S
455
+ rowFilter: C
441
456
  }),
442
457
  outbox: de({
443
458
  store: o,
444
459
  subject: t,
445
- traceId: z,
460
+ traceId: B,
446
461
  nudge: () => {
447
- _.push(z);
462
+ v.push(B);
448
463
  },
449
464
  afterCommit: (e) => {
450
- g.push(e);
465
+ _.push(e);
451
466
  }
452
467
  }),
453
- load: y.load,
454
- loadMany: y.loadMany,
468
+ load: b.load,
469
+ loadMany: b.loadMany,
455
470
  withSubject: (e, t) => Promise.resolve(t(m(e, n, o, {
456
- queued: g,
457
- nudges: _
471
+ queued: _,
472
+ nudges: v
458
473
  }))),
459
474
  withTenant: (e, r) => Promise.resolve(r(m({
460
475
  ...t,
461
476
  tenantId: e
462
477
  }, n, o, {
463
- queued: g,
464
- nudges: _
478
+ queued: _,
479
+ nudges: v
465
480
  }))),
466
481
  asSubject: (e) => m(e, n, o, {
467
- queued: g,
468
- nudges: _
482
+ queued: _,
483
+ nudges: v
469
484
  }),
470
485
  asTenant: (e) => m({
471
486
  ...t,
472
487
  tenantId: e
473
488
  }, n, o, {
474
- queued: g,
475
- nudges: _
489
+ queued: _,
490
+ nudges: v
476
491
  })
477
492
  };
478
- return H.set(x, g), V.set(x, (e) => m(t, e, o, {
479
- queued: g,
480
- nudges: _
481
- })), U.set(x, _), W.set(x, e.plugins ?? []), G.set(x, e.layers ?? []), B.set(x, (e) => o.transactional((r) => e(m(t, n, r, {
482
- queued: g,
483
- nudges: _
484
- })))), x;
493
+ return U.set(S, _), H.set(S, (e) => m(t, e, o, {
494
+ queued: _,
495
+ nudges: v
496
+ })), W.set(S, v), G.set(S, e.plugins ?? []), X.set(S, e.layers ?? []), V.set(S, (e) => o.transactional((r) => e(m(t, n, r, {
497
+ queued: _,
498
+ nudges: v
499
+ })))), S;
485
500
  };
486
501
  return m(e.subject ?? h(null), e.connection);
487
- }, Je = (e, t) => {
488
- let n = q(t);
489
- return (n === void 0 ? e : u.provide(e, n)).pipe(u.provide(le(t.store)), u.provideService(m, t.request.subject));
490
- }, Ye = async (e, t, n, r) => {
502
+ }, tt = (e, t) => {
503
+ let n = He(t);
504
+ return (n === void 0 ? e : u.provide(e, n)).pipe(u.provide(ce(t.store)), u.provideService(m, t.request.subject));
505
+ }, nt = async (e, t, n, r) => {
491
506
  let i = e.input, a = await p.decodeUnknownPromise(i)(n), o = e.kind, s = async (e) => {
492
507
  let n = t(a, e);
493
- return u.isEffect(n) ? w(Je(n, e)) : n;
508
+ return u.isEffect(n) ? T(tt(n, e)) : n;
494
509
  }, c = async () => {
495
510
  let t = e.guards;
496
511
  if (t !== void 0 && t.length > 0) {
@@ -498,29 +513,33 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
498
513
  if (e !== null) throw e;
499
514
  }
500
515
  if (o !== "mutation") return s(r);
501
- let n = await he(async () => X(r, async (e) => (J(r), s(e))), { delay: () => Promise.resolve() });
502
- return await Y(r), n;
503
- }, f = o === "mutation" || o === "query" || o === "action" ? o : void 0, m = f === void 0 ? void 0 : K(r, f);
516
+ let n = await ge(async () => Ge(r, async (e) => (Ue(r), s(e))), { delay: () => Promise.resolve() });
517
+ return await Z(r), n;
518
+ }, f = o === "mutation" || o === "query" || o === "action" ? o : void 0, m = f === void 0 ? void 0 : Ve(r, f);
504
519
  if (m === void 0 || f === void 0) return await c();
505
- let h = m(u.tryPromise({
520
+ let h = u.tryPromise({
506
521
  try: () => c(),
507
522
  catch: (e) => e
508
- }), {
523
+ }), _ = Y(r), v = m(h, {
509
524
  tag: e.name ?? "",
510
525
  kind: f,
511
526
  input: a,
512
527
  subject: r.request.subject,
513
528
  traceId: r.request.traceId,
514
- ...r.request.spanId === void 0 ? {} : { spanId: r.request.spanId }
515
- }), _ = await u.runPromiseExit(h);
516
- if (d.isSuccess(_)) return _.value;
517
- throw l.squash(_.cause);
518
- }, Xe = (e) => new Promise((t) => {
519
- let n = new _e.Socket(), r = (e) => {
529
+ ...r.request.spanId === void 0 ? {} : { spanId: r.request.spanId },
530
+ ..._ === void 0 ? {} : {
531
+ surface: "rest",
532
+ publicApi: _.publicApi
533
+ }
534
+ }), y = await u.runPromiseExit(v);
535
+ if (d.isSuccess(y)) return y.value;
536
+ throw l.squash(y.cause);
537
+ }, rt = (e) => new Promise((t) => {
538
+ let n = new ye.Socket(), r = (e) => {
520
539
  clearTimeout(i), n.destroy(), t(e);
521
540
  }, i = setTimeout(() => r(!1), e.timeoutMs ?? 750);
522
541
  n.once("connect", () => r(!0)), n.once("error", () => r(!1)), n.connect(e.port, e.host);
523
- }), Ze = async (e, t, n, r) => {
542
+ }), it = async (e, t, n, r) => {
524
543
  if (typeof t != "string" || typeof n != "function" || typeof r != "function") throw TypeError(`describeIfAvailable('${e}', ...): expected (label, dependency, probe, suite) — got dependency: ${typeof t}, probe: ${typeof n}, suite: ${typeof r}. Three arguments means the suite body is being used as the probe: it would run at file scope, unconditionally, and the skip would silently do nothing.`);
525
544
  let i = !1;
526
545
  try {
@@ -528,21 +547,21 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
528
547
  } catch {
529
548
  i = !1;
530
549
  }
531
- ve.skipIf(!i)(i ? e : `${e} [SKIPPED: needs ${t}]`, r);
532
- }, Qe = async (e, t, n) => {
533
- await Ze(e, `${t.name} at ${t.host}:${t.port}`, () => Xe(t), n);
534
- }, $e = async (e, t) => {
550
+ be.skipIf(!i)(i ? e : `${e} [SKIPPED: needs ${t}]`, r);
551
+ }, at = async (e, t, n) => {
552
+ await it(e, `${t.name} at ${t.host}:${t.port}`, () => rt(t), n);
553
+ }, ot = async (e, t) => {
535
554
  try {
536
555
  let n = await t();
537
556
  n !== void 0 && n !== "" && console.log(`[engine] ${e}: ${n}`);
538
557
  } catch {}
539
- }, et = "test-tenant", Q = (e, t, n) => ({
558
+ }, st = "test-tenant", Q = (e, t, n) => ({
540
559
  type: e,
541
560
  id: t,
542
561
  tenantId: n.tenantId ?? "test-tenant",
543
562
  scopes: n.scopes ?? [],
544
563
  ...n.metadata === void 0 ? {} : { metadata: n.metadata }
545
- }), tt = (e, t = {}) => Q("user", e, t), nt = (e, t = {}) => Q("apiKey", e, t), rt = (e, t = {}) => Q("serviceAccount", e, t), it = (e = null) => h(e), at = (e = "job:test", t) => t === void 0 ? b(e) : b(e, t), ot = (e) => {
564
+ }), ct = (e, t = {}) => Q("user", e, t), lt = (e, t = {}) => Q("apiKey", e, t), ut = (e, t = {}) => Q("serviceAccount", e, t), dt = (e = null) => h(e), ft = (e = "job:test", t) => t === void 0 ? b(e) : b(e, t), pt = (e) => {
546
565
  let t = e.indexOf("?");
547
566
  return t === -1 ? {
548
567
  path: e,
@@ -551,18 +570,21 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
551
570
  path: e.slice(0, t),
552
571
  query: e.slice(t + 1)
553
572
  };
554
- }, st = (e, t) => {
573
+ }, mt = (e, t) => {
555
574
  let n = e.split("/").filter((e) => e.length > 0), r = t.split("/").filter((e) => e.length > 0);
556
575
  return n.length === r.length && n.every((e, t) => e.startsWith(":") || e === r[t]);
557
576
  }, $ = (e) => {
558
577
  let t = {};
559
578
  for (let [n, r] of Object.entries(e)) t[n.toLowerCase()] = r;
560
579
  return t;
561
- }, ct = (e) => e === void 0 ? /* @__PURE__ */ new Uint8Array() : new TextEncoder().encode(JSON.stringify(e)), lt = (e) => e === void 0 ? "" : typeof e == "string" ? e : new TextDecoder().decode(e), ut = (e) => {
562
- let { ctx: t } = e, n = ye((e.publicApi ?? []).map((e) => ({
580
+ }, ht = (e) => e === void 0 ? /* @__PURE__ */ new Uint8Array() : new TextEncoder().encode(JSON.stringify(e)), gt = (e) => e === void 0 ? "" : typeof e == "string" ? e : new TextDecoder().decode(e), _t = (e) => {
581
+ let { ctx: t } = e, n = xe((e.publicApi ?? []).map((e) => ({
563
582
  descriptor: e.descriptor,
564
- invoke: (n, r) => t.withSubject(r.subject, (t) => Ye(e.descriptor, e.handler, n, t))
565
- }))), r = [...e.restRoutes ?? [], ...n], i = _(e.strategies ?? [], {
583
+ invoke: (n, r) => t.withSubject(r.subject, (t) => (e.descriptor.publicApi !== void 0 && J(t, e.descriptor.publicApi), nt(e.descriptor, e.handler, n, t)))
584
+ })), {
585
+ pluginErrors: K(t).flatMap((e) => e.errorSchemas ?? []),
586
+ ...e.publicApiProfile === void 0 ? {} : { profile: e.publicApiProfile }
587
+ }), r = [...e.restRoutes ?? [], ...n], i = _(e.strategies ?? [], {
566
588
  ...e.anonymousTenantRequired === void 0 ? {} : { anonymousTenantRequired: e.anonymousTenantRequired },
567
589
  getStore: () => t.store
568
590
  }), a = (n, o) => {
@@ -574,11 +596,11 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
574
596
  clientId: -1
575
597
  })).subject : () => n,
576
598
  ...e.idempotency === void 0 ? {} : { idempotency: e.idempotency }
577
- }, c = xe(r, s).map((e, t) => ({
599
+ }, c = Ce(r, s).map((e, t) => ({
578
600
  pattern: r[t].path,
579
601
  route: e
580
602
  })), l = async (e, n, i = {}) => {
581
- let { path: a, query: s } = ot(n), l = c.filter((e) => st(e.pattern, a)).map((e) => e.route);
603
+ let { path: a, query: s } = pt(n), l = c.filter((e) => mt(e.pattern, a)).map((e) => e.route);
582
604
  if (l.length === 0) return {
583
605
  status: 404,
584
606
  headers: {},
@@ -597,12 +619,12 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
597
619
  ...$(o),
598
620
  ...$(i.headers ?? {})
599
621
  },
600
- rawBody: ct(i.body),
622
+ rawBody: ht(i.body),
601
623
  store: t.store
602
- }, d = await be(l, u), f = {};
624
+ }, d = await Se(l, u), f = {};
603
625
  for (let [e, t] of Object.entries(d.headers ?? {})) f[e.toLowerCase()] = t;
604
626
  d.contentType !== void 0 && (f["content-type"] = d.contentType);
605
- let p = lt(d.body), m = (d.contentType ?? "").includes("json");
627
+ let p = gt(d.body), m = (d.contentType ?? "").includes("json");
606
628
  return {
607
629
  status: d.status,
608
630
  headers: f,
@@ -636,17 +658,17 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
636
658
  };
637
659
  };
638
660
  return a(void 0, {});
639
- }, dt = (e = {}) => {
661
+ }, vt = (e = {}) => {
640
662
  let t = e.id ?? "test", n = e.store ?? new Proxy({}, { get: (e, t) => {
641
663
  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.`);
642
664
  } });
643
665
  return {
644
666
  id: t,
645
- log: e.log ?? Se({ scope: `subscribe:${t}` }),
667
+ log: e.log ?? we({ scope: `subscribe:${t}` }),
646
668
  store: n,
647
669
  ...e.publish === void 0 ? {} : { publish: e.publish }
648
670
  };
649
- }, ft = (e) => {
671
+ }, yt = (e) => {
650
672
  let t = /* @__PURE__ */ new Map();
651
673
  for (let n of e) {
652
674
  let e = t.get(n.stepName);
@@ -672,13 +694,13 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
672
694
  });
673
695
  }
674
696
  return n.sort((e, t) => e._startedAt - t._startedAt), n.map(({ _startedAt: e, ...t }) => t);
675
- }, pt = (e) => {
697
+ }, bt = (e) => {
676
698
  let t = e.workflows ?? [], n = /* @__PURE__ */ new Map(), r = 0;
677
699
  return {
678
700
  start: async (i, a) => {
679
701
  let o = t.find((e) => e.workflow.name === i);
680
702
  if (o === void 0) throw Error(`makeWorkflowRunner: no workflow named '${i}' — pass it in makeWorkflowRunner({ ctx, workflows: [{ workflow, execute }] }).`);
681
- 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 = ft(c.readSteps()), g = /* @__PURE__ */ new Date(), _;
703
+ let s = `wfrun_test_${++r}`, c = De(), l = o.workflow.toLayer(o.execute).pipe(f.provideMerge(Ee)), d = /* @__PURE__ */ new Date(), p = o.workflow.execute(a).pipe(u.locally(Te, s), u.provide(c.layer), u.provide(l), u.either), m = await u.runPromise(p), h = yt(c.readSteps()), g = /* @__PURE__ */ new Date(), _;
682
704
  if (m._tag === "Right") _ = {
683
705
  status: "succeeded",
684
706
  output: m.right,
@@ -718,6 +740,6 @@ var Ee = new Set(e), D = 0, O = () => ++D, De = (e, t) => {
718
740
  },
719
741
  inspect: async (e) => n.get(e) ?? null
720
742
  };
721
- }, mt = 1;
743
+ }, xt = 1;
722
744
  //#endregion
723
- export { F as MockClock, R as MockLLM, I as MockWebhooks, mt as TESTING_PRESET_VERSION, et as TEST_TENANT_ID, it as anonymous, nt as apiKey, n as changeDelete, r as changeInsert, i as changeSoftDelete, a as changeUpdate, je as defineFactory, Ze as describeIfAvailable, Qe as describeIfReachable, k as fixtureRow, Fe as frozenTime, Ye as invoke, Xe as isTcpReachable, dt as makeSubscribeContext, ut as makeTestApp, qe as makeTestContext, pt as makeWorkflowRunner, Le as mockStore, O as nextSequence, ze as outboxNudgesOf, $e as reportEngineVersion, J as resetAfterCommit, K as rpcInterceptorFor, Y as runAfterCommit, X as runInStoreTransaction, rt as serviceAccount, q as serviceLayerFor, at as system, L as testEventBus, tt as user, Pe as withFrozenTime, Re as withRpcConnection };
745
+ export { I as MockClock, z as MockLLM, L as MockWebhooks, xt as TESTING_PRESET_VERSION, st as TEST_TENANT_ID, dt as anonymous, lt as apiKey, n as changeDelete, r as changeInsert, i as changeSoftDelete, a as changeUpdate, Ne as defineFactory, it as describeIfAvailable, at as describeIfReachable, A as fixtureRow, Le as frozenTime, nt as invoke, rt as isTcpReachable, vt as makeSubscribeContext, _t as makeTestApp, et as makeTestContext, bt as makeWorkflowRunner, J as markRestInvocation, ze as mockStore, k as nextSequence, We as outboxNudgesOf, K as pluginsOf, ot as reportEngineVersion, Ue as resetAfterCommit, Y as restInvocationOf, Ve as rpcInterceptorFor, Z as runAfterCommit, Ge as runInStoreTransaction, ut as serviceAccount, He as serviceLayerFor, ft as system, R as testEventBus, ct as user, Ie as withFrozenTime, Be as withRpcConnection };