@voltro/testing 0.80.0 → 0.82.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,64 +1,68 @@
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, Either as d, Exit as f, Layer as p, Schema as m } from "effect";
3
- import { SubjectService as h, anonymousSubject as g, checkGuardsEffect as _, composeAuthStrategies as v, composeRpcInterceptors as y, eventRoute as b, systemSubject as x, tenantScopedSubject as ee } from "@voltro/protocol";
4
- import { EventBus as S, InMemoryDataStore as te, NO_ROW_FILTER as C, appValidation as ne, applyRowFilterToDescriptor as re, clearSystemStoreHandle as ie, getRowFilter as w, getSystemStoreHandle as ae, makeAppAccess as oe, makeConnectionState as se, makeDataLoader as ce, makeEffectStoreLayer as T, makeEventPublisher as le, makeFieldCipher as ue, makeOutboxFacade as de, makeSchemaRegistry as fe, publishEvent as pe, resolveRowFilterScopeFor as me, resolveTransactionSubject as he, runProvidedEffect as E, runWithDeadlockRetry as ge, setFieldCipher as _e, setSystemStoreHandle as D, wrapStoreWithMixinBehaviour as O } 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";
3
+ import { ApiUnavailable as h, SubjectService as g, anonymousSubject as _, checkGuardsEffect as v, composeAuthStrategies as y, composeRpcInterceptors as b, eventRoute as x, systemSubject as S, tenantScopedSubject as ee } from "@voltro/protocol";
4
+ import { EventBus as te, InMemoryDataStore as ne, NO_ROW_FILTER as C, apiBindingTokenEnv as re, apiBindingUrlEnv as ie, appValidation as ae, applyRowFilterToDescriptor as oe, clearSystemStoreHandle as se, getFieldCipher as ce, getRowFilter as w, getSystemStoreHandle as le, makeAppAccess as ue, makeConnectionState as de, makeDataLoader as fe, makeEffectStoreLayer as T, makeEventPublisher as pe, makeFieldCipher as me, makeOutboxFacade as he, makeSchemaRegistry as ge, mintServiceToken as _e, publishEvent as ve, resolveRequestClientAddress as ye, resolveRowFilterScopeFor as be, resolveTransactionSubject as xe, resolveTrustedProxies as Se, runProvidedEffect as E, runWithDeadlockRetry as Ce, serviceCallerTokenEnv as we, setFieldCipher as Te, setSystemStoreHandle as D, wrapStoreWithMixinBehaviour as O } from "@voltro/runtime";
5
+ import { installEnvSnapshot as Ee } from "@voltro/env";
6
+ import k from "node:net";
7
+ import { describe as De } from "vitest";
8
+ import { collectPublicApiRoutes as Oe, dispatchSharedPath as ke, restRoutesToHttpRoutes as Ae } from "@voltro/protocol/rest";
9
+ import { createLogger as je } from "@voltro/logger";
10
+ import { randomBytes as Me } from "node:crypto";
11
+ import { CurrentWorkflowRunId as Ne, getWorkflowJournalCipher as Pe, inMemoryWorkflowEngineLayer as Fe, makeInMemoryRecorder as Ie, setWorkflowJournalCipher as Le } from "@voltro/workflow";
12
+ import { spawn as Re } from "node:child_process";
13
+ import { createRequire as ze } from "node:module";
14
+ import { dirname as Be, join as A } from "node:path";
11
15
  //#region src/fixtureRow.ts
12
- var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
16
+ var Ve = new Set(e), j = 0, M = () => ++j, He = (e, t) => {
13
17
  if (t.oneOf && t.oneOf.length > 0) return t.oneOf[0];
14
18
  if (t.enumValues && t.enumValues.length > 0) return t.enumValues[0];
15
19
  let n = t.unique === !0;
16
20
  switch (t.type) {
17
21
  case "text":
18
22
  case "id":
19
- case "enum": return n ? `${e}-${++k}` : e;
20
- case "reference": return t.referenceStorage === "numeric" ? n ? ++k : 0 : n ? `${e}-${++k}` : e;
23
+ case "enum": return n ? `${e}-${++j}` : e;
24
+ case "reference": return t.referenceStorage === "numeric" ? n ? ++j : 0 : n ? `${e}-${++j}` : e;
21
25
  case "integer":
22
- case "real": return n ? ++k : 0;
26
+ case "real": return n ? ++j : 0;
23
27
  case "decimal":
24
- case "bigint": return n ? String(++k) : "0";
28
+ case "bigint": return n ? String(++j) : "0";
25
29
  case "boolean": return !1;
26
30
  case "timestamp":
27
31
  case "date": return /* @__PURE__ */ new Date(0);
28
32
  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
33
  }
30
- }, j = (e, t = {}) => {
34
+ }, N = (e, t = {}) => {
31
35
  let n = {};
32
- for (let r of s(e, t)) Oe.has(r) || (n[r] = ke(r, e.fields[r]));
36
+ for (let r of s(e, t)) Ve.has(r) || (n[r] = He(r, e.fields[r]));
33
37
  return {
34
38
  ...n,
35
39
  ...t
36
40
  };
37
- }, M = m.decodeUnknownEither(m.DateFromString), Ae = /^\d{4}-\d{2}-\d{2}$/, je = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/, Me = (e, t) => {
38
- if (typeof e != "string" || !je.test(e) && !(t === "date" && Ae.test(e))) return !1;
39
- let n = e.slice(0, 10), r = M(n);
41
+ }, P = m.decodeUnknownEither(m.DateFromString), Ue = /^\d{4}-\d{2}-\d{2}$/, We = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/, Ge = (e, t) => {
42
+ if (typeof e != "string" || !We.test(e) && !(t === "date" && Ue.test(e))) return !1;
43
+ let n = e.slice(0, 10), r = P(n);
40
44
  return d.isRight(r) && Number.isFinite(r.right.getTime()) && r.right.toISOString().slice(0, 10) === n;
41
- }, Ne = (e, t) => {
45
+ }, Ke = (e, t) => {
42
46
  let n = Object.entries(e.fields).filter(([, e]) => e.type === "timestamp" || e.type === "date");
43
47
  return t.map((t, r) => {
44
48
  let i = { ...t };
45
49
  for (let [a, o] of n) {
46
50
  let n = t[a];
47
51
  if (n == null || n instanceof Date && Number.isFinite(n.getTime())) continue;
48
- let s = M(n);
49
- if (!Me(n, o.type) || d.isLeft(s) || !Number.isFinite(s.right.getTime())) throw TypeError(`hydrateFixtureRows: table '${e.tableName}', row ${r}, column '${a}' requires a valid Date or ISO date-time with Z or an offset${o.type === "date" ? " (YYYY-MM-DD is also accepted as UTC midnight)" : ""}.`);
52
+ let s = P(n);
53
+ if (!Ge(n, o.type) || d.isLeft(s) || !Number.isFinite(s.right.getTime())) throw TypeError(`hydrateFixtureRows: table '${e.tableName}', row ${r}, column '${a}' requires a valid Date or ISO date-time with Z or an offset${o.type === "date" ? " (YYYY-MM-DD is also accepted as UTC midnight)" : ""}.`);
50
54
  i[a] = s.right;
51
55
  }
52
56
  return i;
53
57
  });
54
- }, Pe = (e) => {
58
+ }, qe = (e) => {
55
59
  let t = {};
56
- for (let [n, r] of Object.entries(e)) t[n] = typeof r == "function" ? r(A()) : r;
60
+ for (let [n, r] of Object.entries(e)) t[n] = typeof r == "function" ? r(M()) : r;
57
61
  return t;
58
- }, Fe = (e) => {
62
+ }, Je = (e) => {
59
63
  for (let [t, n] of Object.entries(e.fields)) if (n.type === "id") return t;
60
64
  return "id";
61
- }, Ie = async (e, t, n, r, i) => {
65
+ }, Ye = async (e, t, n, r, i) => {
62
66
  let a = {};
63
67
  for (let o of s(t, n)) {
64
68
  let n = t.fields[o];
@@ -66,29 +70,29 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
66
70
  let s = n.references();
67
71
  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 }).`);
68
72
  let c = r[o];
69
- a[o] = (c === void 0 ? await N(e, s, {}, {}, [...i, s.tableName]) : await c.create(e, {}))[n.referenceColumn ?? Fe(s)];
73
+ a[o] = (c === void 0 ? await F(e, s, {}, {}, [...i, s.tableName]) : await c.create(e, {}))[n.referenceColumn ?? Je(s)];
70
74
  }
71
75
  return a;
72
- }, N = async (e, t, n, r, i) => {
76
+ }, F = async (e, t, n, r, i) => {
73
77
  let a = {
74
- ...await Ie(e, t, n, r, i),
78
+ ...await Ye(e, t, n, r, i),
75
79
  ...n
76
80
  };
77
- return e.insert(t.tableName, j(t, a));
78
- }, P = (e, t) => typeof e == "function" ? e(t) : e ?? {}, Le = (e, t = {}) => {
81
+ return e.insert(t.tableName, N(t, a));
82
+ }, Xe = (e, t) => typeof e == "function" ? e(t) : e ?? {}, Ze = (e, t = {}) => {
79
83
  let n = t.traits ?? {}, r = t.associations ?? {}, i = (t) => {
80
84
  let a = (e = {}) => ({
81
- ...Pe(t),
85
+ ...qe(t),
82
86
  ...e
83
- }), o = (t = {}) => j(e, a(t));
87
+ }), o = (t = {}) => N(e, a(t));
84
88
  return {
85
89
  table: e,
86
90
  build: o,
87
- buildList: (e, t) => Array.from({ length: e }, (e, n) => o(P(t, n))),
88
- create: (t, n = {}) => N(t, e, a(n), r, [e.tableName]),
91
+ buildList: (e, t) => Array.from({ length: e }, (e, n) => o(Xe(t, n))),
92
+ create: (t, n = {}) => F(t, e, a(n), r, [e.tableName]),
89
93
  createList: async (t, n, i) => {
90
94
  let o = [];
91
- for (let s = 0; s < n; s++) o.push(await N(t, e, a(P(i, s)), r, [e.tableName]));
95
+ for (let s = 0; s < n; s++) o.push(await F(t, e, a(Xe(i, s)), r, [e.tableName]));
92
96
  return o;
93
97
  },
94
98
  with: (...r) => {
@@ -110,19 +114,19 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
110
114
  };
111
115
  };
112
116
  return i(t.defaults ?? {});
113
- }, F = Symbol.for("voltro/testing/mockClock.installed"), I = () => globalThis, Re = (e, t) => new Proxy(e, {
117
+ }, I = Symbol.for("voltro/testing/mockClock.installed"), L = () => globalThis, Qe = (e, t) => new Proxy(e, {
114
118
  construct: (e, n, r) => Reflect.construct(e, n.length === 0 ? [t()] : n, r),
115
119
  apply: () => new e(t()).toString(),
116
120
  get: (e, n, r) => n === "now" ? () => t() : Reflect.get(e, n, r)
117
- }), L = (e) => {
121
+ }), R = (e) => {
118
122
  if (typeof e == "number") return e;
119
123
  let t = e instanceof Date ? e.getTime() : Date.parse(e);
120
124
  if (Number.isNaN(t)) throw Error(`mockClock: cannot read an instant from '${String(e)}'`);
121
125
  return t;
122
- }, R = class {
126
+ }, z = class {
123
127
  currentMs;
124
128
  constructor(e = "2026-01-01T00:00:00Z") {
125
- this.currentMs = L(e);
129
+ this.currentMs = R(e);
126
130
  }
127
131
  now() {
128
132
  return this.currentMs;
@@ -131,47 +135,47 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
131
135
  return new Date(this.currentMs);
132
136
  }
133
137
  advance(e) {
134
- this.currentMs += typeof e == "number" ? e : He(e);
138
+ this.currentMs += typeof e == "number" ? e : nt(e);
135
139
  }
136
140
  set(e) {
137
- this.currentMs = L(e);
141
+ this.currentMs = R(e);
138
142
  }
139
143
  get installed() {
140
- return I()[F]?.clock === this;
144
+ return L()[I]?.clock === this;
141
145
  }
142
146
  install() {
143
- let e = I(), t = e[F];
147
+ let e = L(), t = e[I];
144
148
  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.");
145
149
  let n = globalThis.Date;
146
- return e[F] = {
150
+ return e[I] = {
147
151
  realDate: n,
148
152
  clock: this
149
- }, globalThis.Date = Re(n, () => this.currentMs), () => {
153
+ }, globalThis.Date = Qe(n, () => this.currentMs), () => {
150
154
  this.uninstall();
151
155
  };
152
156
  }
153
157
  uninstall() {
154
- let e = I(), t = e[F];
155
- t !== void 0 && t.clock === this && (globalThis.Date = t.realDate, delete e[F]);
158
+ let e = L(), t = e[I];
159
+ t !== void 0 && t.clock === this && (globalThis.Date = t.realDate, delete e[I]);
156
160
  }
157
- }, ze = (e) => typeof e == "object" && !!e && typeof e.then == "function", Be = (e, t) => {
158
- let n = e instanceof R ? e : new R(e);
161
+ }, $e = (e) => typeof e == "object" && !!e && typeof e.then == "function", et = (e, t) => {
162
+ let n = e instanceof z ? e : new z(e);
159
163
  n.install();
160
164
  let r = !1;
161
165
  try {
162
166
  let e = t(n);
163
- return ze(e) ? (r = !0, e.then((e) => (n.uninstall(), e), (e) => {
167
+ return $e(e) ? (r = !0, e.then((e) => (n.uninstall(), e), (e) => {
164
168
  throw n.uninstall(), e;
165
169
  })) : e;
166
170
  } finally {
167
171
  r || n.uninstall();
168
172
  }
169
- }, Ve = (e) => u.acquireRelease(u.sync(() => {
170
- let t = e instanceof R ? e : new R(e);
173
+ }, tt = (e) => u.acquireRelease(u.sync(() => {
174
+ let t = e instanceof z ? e : new z(e);
171
175
  return t.install(), t;
172
176
  }), (e) => u.sync(() => {
173
177
  e.uninstall();
174
- })), He = (e) => {
178
+ })), nt = (e) => {
175
179
  let t = /^\s*(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)\s*$/.exec(e);
176
180
  if (!t) throw Error(`mockClock: cannot parse duration '${e}'`);
177
181
  let n = Number(t[1]), r = t[2];
@@ -183,16 +187,19 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
183
187
  case "d": return n * 864e5;
184
188
  default: throw Error(`mockClock: unknown unit '${r}'`);
185
189
  }
186
- }, z = class {
190
+ }, B = class {
187
191
  emitted = [];
188
192
  async emit(e, t) {
189
- let n = typeof e == "string" ? e : e.id ?? e.event ?? "(unnamed event)";
193
+ let n = typeof e == "string" ? e : e.name ?? e.id ?? e.event ?? "(unnamed event)";
190
194
  return this.emitted.push({
191
195
  event: n,
192
196
  payload: t,
193
197
  emittedAt: /* @__PURE__ */ new Date()
194
198
  }), { delivered: 0 };
195
199
  }
200
+ async listTargets(e, t) {
201
+ return [];
202
+ }
196
203
  payloadsFor(e) {
197
204
  return this.emitted.filter((t) => t.event === e).map((e) => e.payload);
198
205
  }
@@ -202,14 +209,14 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
202
209
  clear() {
203
210
  this.emitted.length = 0;
204
211
  }
205
- }, B = (e = {}) => {
206
- let t = e.tenantId ?? null, n = new S({
212
+ }, V = (e = {}) => {
213
+ let t = e.tenantId ?? null, n = new te({
207
214
  origin: e.origin ?? "test",
208
215
  ...e.ringSize === void 0 ? {} : { ringSize: e.ringSize }
209
216
  });
210
217
  return {
211
218
  publish: async (e, r, i) => {
212
- let a = await u.runPromise(u.either(pe({
219
+ let a = await u.runPromise(u.either(ve({
213
220
  bus: n,
214
221
  tenantId: t
215
222
  }, e, r, i)));
@@ -258,7 +265,7 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
258
265
  },
259
266
  skipSerials: (e, r, i, a) => {
260
267
  let o = a?.tenantId ?? t, s = {
261
- route: b(o, e.name, r),
268
+ route: x(o, e.name, r),
262
269
  event: e.name,
263
270
  origin: "test-gap",
264
271
  n: i + 1,
@@ -272,7 +279,7 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
272
279
  n.clear();
273
280
  }
274
281
  };
275
- }, V = class {
282
+ }, H = class {
276
283
  queue;
277
284
  calls = [];
278
285
  constructor(e) {
@@ -287,38 +294,41 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
287
294
  remaining() {
288
295
  return this.queue.length;
289
296
  }
290
- }, Ue = (e) => e, H = "00000000000000000000000000000000", U = /* @__PURE__ */ new WeakMap(), W = /* @__PURE__ */ new WeakMap(), We = (e, t) => {
291
- let n = W.get(e);
297
+ }, rt = (e) => e, U = "00000000000000000000000000000000", W = /* @__PURE__ */ new WeakMap(), G = /* @__PURE__ */ new WeakMap(), it = (e, t) => {
298
+ let n = G.get(e);
292
299
  if (n === void 0) throw Error("withRpcConnection requires a context created by makeTestContext");
293
300
  return n(t);
294
- }, G = /* @__PURE__ */ new WeakMap(), K = /* @__PURE__ */ new WeakMap(), q = /* @__PURE__ */ new WeakMap(), J = (e) => q.get(e) ?? [], Y = /* @__PURE__ */ new WeakMap(), X = (e, t) => {
295
- Y.set(e, { publicApi: t });
296
- }, Ge = (e) => Y.get(e), Ke = /* @__PURE__ */ new WeakMap(), qe = (e, t) => {
297
- let n = q.get(e) ?? [], r = t === "mutation" ? "interceptMutation" : t === "query" ? "interceptQuery" : "interceptAction", i = [];
301
+ }, K = /* @__PURE__ */ new WeakMap(), q = /* @__PURE__ */ new WeakMap(), J = /* @__PURE__ */ new WeakMap(), Y = (e) => J.get(e) ?? [], X = /* @__PURE__ */ new WeakMap(), Z = (e, t, n) => {
302
+ X.set(e, {
303
+ publicApi: t,
304
+ ...n === void 0 ? {} : { remoteAddr: n }
305
+ });
306
+ }, at = (e) => X.get(e), ot = /* @__PURE__ */ new WeakMap(), st = (e, t) => {
307
+ let n = J.get(e) ?? [], r = t === "mutation" ? "interceptMutation" : t === "query" ? "interceptQuery" : "interceptAction", i = [];
298
308
  for (let e of n) {
299
309
  let t = e[r];
300
310
  typeof t == "function" && i.push(t);
301
311
  }
302
- return y(i);
303
- }, Je = (e) => {
304
- let t = (q.get(e) ?? []).map((e) => e.services).filter((e) => e !== void 0), n = Ke.get(e) ?? [], r = [...t, ...n];
312
+ return b(i);
313
+ }, ct = (e) => {
314
+ let t = (J.get(e) ?? []).map((e) => e.services).filter((e) => e !== void 0), n = ot.get(e) ?? [], r = [...t, ...n];
305
315
  if (r.length !== 0) return p.mergeAll(...r);
306
- }, Ye = (e) => {
307
- let t = G.get(e);
316
+ }, lt = (e) => {
317
+ let t = K.get(e);
308
318
  t !== void 0 && (t.length = 0);
309
- }, Z = async (e) => {
310
- let t = G.get(e);
319
+ }, Q = async (e) => {
320
+ let t = K.get(e);
311
321
  if (t === void 0 || t.length === 0) return;
312
322
  let n = [...t];
313
323
  t.length = 0;
314
324
  for (let e of n) await e();
315
- }, Xe = (e) => K.get(e) ?? [], Ze = async (e, t) => {
316
- let n = U.get(e);
325
+ }, ut = (e) => q.get(e) ?? [], dt = async (e, t) => {
326
+ let n = W.get(e);
317
327
  return n === void 0 ? e.store.transactional(async (n) => t({
318
328
  ...e,
319
329
  store: n
320
330
  })) : n(t);
321
- }, Qe = (e) => {
331
+ }, ft = (e) => {
322
332
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = (n) => {
323
333
  let r = t.get(n);
324
334
  return r === void 0 ? !1 : r.expiresAt !== null && r.expiresAt <= e() ? (t.delete(n), !1) : !0;
@@ -357,7 +367,7 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
357
367
  return i(e, o, n.ttlMs, n.tags), o;
358
368
  }
359
369
  };
360
- }, $e = (e) => {
370
+ }, pt = (e) => {
361
371
  let t = /* @__PURE__ */ new Map(), n = (n) => {
362
372
  let r = t.get(n);
363
373
  return r === void 0 ? !1 : r.expiresAt !== null && r.expiresAt <= e() ? (t.delete(n), !1) : !0;
@@ -385,47 +395,49 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
385
395
  t.clear();
386
396
  }
387
397
  };
388
- }, et = async (e, t) => {
389
- let n = ae();
398
+ }, mt = async (e, t) => {
399
+ let n = le();
390
400
  D(e);
391
401
  try {
392
402
  return await t();
393
403
  } finally {
394
- n === void 0 ? ie() : D(n);
404
+ n === void 0 ? se() : D(n);
395
405
  }
396
- }, tt = /* @__PURE__ */ new Set(), nt = (e) => {
397
- tt.has(e) || (tt.add(e), console.warn(e));
398
- }, rt = (e, t, n) => {
399
- let r = it, i;
406
+ }, ht = /* @__PURE__ */ new Set(), gt = (e) => {
407
+ ht.has(e) || (ht.add(e), console.warn(e));
408
+ }, _t = (e, t, n) => {
409
+ let r = vt, i;
400
410
  return () => {
401
411
  let a = t ?? w();
402
- return t !== void 0 && w() !== void 0 && t !== w() && nt("[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 = et(n, () => E(me(a, e, (e) => {
412
+ return t !== void 0 && w() !== void 0 && t !== w() && gt("[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 = mt(n, () => E(be(a, e, (e) => {
403
413
  console.error("[voltro:testing] row filter failed to load — reads refused for this subject", e);
404
414
  })))), i;
405
415
  };
406
- }, it = Symbol("unresolved"), at = (e, t) => new Proxy(e, { get: (e, n) => {
407
- if (n === "query") return async (n) => e.query(re(await t(), n));
416
+ }, vt = Symbol("unresolved"), yt = (e, t) => new Proxy(e, { get: (e, n) => {
417
+ if (n === "query") return async (n) => e.query(oe(await t(), n));
408
418
  let r = Reflect.get(e, n, e);
409
419
  return typeof r == "function" ? r.bind(e) : r;
410
- } }), ot = (e = {}) => {
411
- if (ve({
420
+ } }), bt = (e = {}) => {
421
+ if (Ee({
412
422
  ...process.env,
413
423
  ...e.env ?? {}
414
- }), e.fieldEncryptionKey !== void 0 && _e(ue(e.fieldEncryptionKey)), e.relations !== void 0) {
424
+ }), e.fieldEncryptionKey !== void 0 && Te(me(e.fieldEncryptionKey)), e.relations !== void 0) {
415
425
  o();
416
426
  for (let t of e.relations) c(t);
417
427
  }
418
- let n = e.tables ?? t(), r = fe(n), i = new te(e.store ?? {}), a = {
428
+ let n = e.tables ?? t(), r = ge(n), i = new ne(e.store ?? {});
429
+ for (let t of e.plugins ?? []) t.bindDataStore?.(i);
430
+ let a = {
419
431
  dataStore: i,
420
432
  schemaRegistry: r
421
433
  };
422
434
  D(a);
423
- let s = new R(e.clockStart), l = new z(), u = B(), d = new V(e.llmResponses ?? []), f = Qe(() => s.now()), p = $e(() => s.now()), m = (t, n, o = i, c, h = !1) => {
435
+ let s = new z(e.clockStart), l = new B(), u = V(), d = new H(e.llmResponses ?? []), f = ft(() => s.now()), p = pt(() => s.now()), m = (t, n, o = i, c, h = !1) => {
424
436
  let g = {
425
437
  subject: t,
426
- traceId: H,
438
+ traceId: U,
427
439
  ...n === void 0 ? {} : { connection: n }
428
- }, _ = c?.queued ?? [], v = c?.nudges ?? [], y = le({
440
+ }, _ = c?.queued ?? [], v = c?.nudges ?? [], y = pe({
429
441
  bus: u.bus,
430
442
  tenantId: t.tenantId ?? null,
431
443
  ...o === i ? {} : { deferToCommit: (e) => {
@@ -433,9 +445,10 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
433
445
  e();
434
446
  });
435
447
  } }
436
- }), b = ce({ store: o }), x = h ? async () => C : rt(t, e.rowFilter, a), S = {
448
+ }), b = fe({ store: o }), x = h ? async () => C : _t(t, e.rowFilter, a), S = {
449
+ apis: e.apis ?? Object.freeze({}),
437
450
  transaction: async (e, r) => {
438
- let a = he(t, r?.tenantId, o !== i);
451
+ let a = xe(t, r?.tenantId, o !== i);
439
452
  if (a !== t) return m(a, n, i, void 0, !0).transaction(e);
440
453
  if (o !== i) return e(S);
441
454
  let s, c = await o.transactional(async (r) => {
@@ -445,7 +458,7 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
445
458
  }, h), a = await e(i);
446
459
  return s = i, a;
447
460
  });
448
- return s !== void 0 && (await Z(s), v.push(...Xe(s))), c;
461
+ return s !== void 0 && (await Q(s), v.push(...ut(s))), c;
449
462
  },
450
463
  clock: s,
451
464
  webhooks: l,
@@ -454,29 +467,29 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
454
467
  llm: d,
455
468
  ...e.ai === void 0 ? {} : { ai: e.ai },
456
469
  request: g,
457
- ...n === void 0 ? {} : { connectionState: se(n, o === i ? void 0 : (e) => {
470
+ ...n === void 0 ? {} : { connectionState: de(n, o === i ? void 0 : (e) => {
458
471
  _.push(e);
459
472
  }) },
460
- validation: ne,
461
- access: oe(t),
473
+ validation: ae,
474
+ access: ue(t),
462
475
  cache: f,
463
476
  kv: p,
464
- store: O(at(o, x), {
477
+ store: O(yt(o, x), {
465
478
  subject: t,
466
479
  schemaRegistry: r,
467
480
  rowFilter: C
468
481
  }),
469
- storeForTenant: (e) => O(at(o, x), {
482
+ storeForTenant: (e) => O(yt(o, x), {
470
483
  subject: ee(t, e),
471
484
  schemaRegistry: r,
472
485
  rowFilter: C
473
486
  }),
474
- outbox: de({
487
+ outbox: he({
475
488
  store: o,
476
489
  subject: t,
477
- traceId: H,
490
+ traceId: U,
478
491
  nudge: () => {
479
- v.push(H);
492
+ v.push(U);
480
493
  },
481
494
  afterCommit: (e) => {
482
495
  _.push(e);
@@ -507,37 +520,37 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
507
520
  nudges: v
508
521
  })
509
522
  };
510
- return G.set(S, _), W.set(S, (e) => m(t, e, o, {
523
+ return K.set(S, _), G.set(S, (e) => m(t, e, o, {
511
524
  queued: _,
512
525
  nudges: v
513
- })), K.set(S, v), q.set(S, e.plugins ?? []), Ke.set(S, e.layers ?? []), U.set(S, (e) => o.transactional((r) => e(m(t, n, r, {
526
+ })), q.set(S, v), J.set(S, e.plugins ?? []), ot.set(S, e.layers ?? []), W.set(S, (e) => o.transactional((r) => e(m(t, n, r, {
514
527
  queued: _,
515
528
  nudges: v
516
529
  })))), S;
517
530
  };
518
- return m(e.subject ?? g(null), e.connection);
519
- }, st = (e, t) => {
520
- let n = Je(t);
521
- return (n === void 0 ? e : u.provide(e, n)).pipe(u.provide(T(t.store)), u.provideService(h, t.request.subject));
522
- }, ct = async (e, t, n, r) => {
531
+ return m(e.subject ?? _(null), e.connection);
532
+ }, xt = (e, t) => {
533
+ let n = ct(t);
534
+ return (n === void 0 ? e : u.provide(e, n)).pipe(u.provide(T(t.store)), u.provideService(g, t.request.subject));
535
+ }, St = async (e, t, n, r) => {
523
536
  let i = e.input, a = await m.decodeUnknownPromise(i)(n), o = e.kind, s = async (e) => {
524
537
  let n = t(a, e);
525
- return u.isEffect(n) ? E(st(n, e)) : n;
538
+ return u.isEffect(n) ? E(xt(n, e)) : n;
526
539
  }, c = async () => {
527
540
  let t = e.guards;
528
541
  if (t !== void 0 && t.length > 0) {
529
- let e = await u.runPromise(_(r.request.subject, t, a));
542
+ let e = await u.runPromise(v(r.request.subject, t, a));
530
543
  if (e !== null) throw e;
531
544
  }
532
545
  if (o !== "mutation") return s(r);
533
- let n = await ge(async () => Ze(r, async (e) => (Ye(r), s(e))), { delay: () => Promise.resolve() });
534
- return await Z(r), n;
535
- }, d = o === "mutation" || o === "query" || o === "action" ? o : void 0, p = d === void 0 ? void 0 : qe(r, d);
546
+ let n = await Ce(async () => dt(r, async (e) => (lt(r), s(e))), { delay: () => Promise.resolve() });
547
+ return await Q(r), n;
548
+ }, d = o === "mutation" || o === "query" || o === "action" ? o : void 0, p = d === void 0 ? void 0 : st(r, d);
536
549
  if (p === void 0 || d === void 0) return await c();
537
550
  let h = u.tryPromise({
538
551
  try: () => c(),
539
552
  catch: (e) => e
540
- }), g = Ge(r), v = p(h, {
553
+ }), g = at(r), _ = p(h, {
541
554
  tag: e.name ?? "",
542
555
  kind: d,
543
556
  input: a,
@@ -547,16 +560,17 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
547
560
  ...g === void 0 ? {} : {
548
561
  surface: "rest",
549
562
  publicApi: g.publicApi
550
- }
551
- }), y = await u.runPromiseExit(v);
563
+ },
564
+ ...g?.remoteAddr === void 0 ? {} : { remoteAddr: g.remoteAddr }
565
+ }), y = await u.runPromiseExit(_);
552
566
  if (f.isSuccess(y)) return y.value;
553
567
  throw l.squash(y.cause);
554
- }, lt = (e) => new Promise((t) => {
555
- let n = new ye.Socket(), r = (e) => {
568
+ }, Ct = (e) => new Promise((t) => {
569
+ let n = new k.Socket(), r = (e) => {
556
570
  clearTimeout(i), n.destroy(), t(e);
557
571
  }, i = setTimeout(() => r(!1), e.timeoutMs ?? 750);
558
572
  n.once("connect", () => r(!0)), n.once("error", () => r(!1)), n.connect(e.port, e.host);
559
- }), ut = async (e, t, n, r) => {
573
+ }), wt = async (e, t, n, r) => {
560
574
  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.`);
561
575
  let i = !1;
562
576
  try {
@@ -564,21 +578,21 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
564
578
  } catch {
565
579
  i = !1;
566
580
  }
567
- be.skipIf(!i)(i ? e : `${e} [SKIPPED: needs ${t}]`, r);
568
- }, dt = async (e, t, n) => {
569
- await ut(e, `${t.name} at ${t.host}:${t.port}`, () => lt(t), n);
570
- }, ft = async (e, t) => {
581
+ De.skipIf(!i)(i ? e : `${e} [SKIPPED: needs ${t}]`, r);
582
+ }, Tt = async (e, t, n) => {
583
+ await wt(e, `${t.name} at ${t.host}:${t.port}`, () => Ct(t), n);
584
+ }, Et = async (e, t) => {
571
585
  try {
572
586
  let n = await t();
573
587
  n !== void 0 && n !== "" && console.log(`[engine] ${e}: ${n}`);
574
588
  } catch {}
575
- }, pt = "test-tenant", Q = (e, t, n) => ({
589
+ }, Dt = "test-tenant", $ = (e, t, n) => ({
576
590
  type: e,
577
591
  id: t,
578
592
  tenantId: n.tenantId ?? "test-tenant",
579
593
  scopes: n.scopes ?? [],
580
594
  ...n.metadata === void 0 ? {} : { metadata: n.metadata }
581
- }), mt = (e, t = {}) => Q("user", e, t), ht = (e, t = {}) => Q("apiKey", e, t), gt = (e, t = {}) => Q("serviceAccount", e, t), _t = (e = null) => g(e), vt = (e = "job:test", t) => t === void 0 ? x(e) : x(e, t), yt = (e) => {
595
+ }), Ot = (e, t = {}) => $("user", e, t), kt = (e, t = {}) => $("apiKey", e, t), At = (e, t = {}) => $("serviceAccount", e, t), jt = (e = null) => _(e), Mt = (e = "job:test", t) => t === void 0 ? S(e) : S(e, t), Nt = "127.0.0.1", Pt = (e) => {
582
596
  let t = e.indexOf("?");
583
597
  return t === -1 ? {
584
598
  path: e,
@@ -587,105 +601,110 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
587
601
  path: e.slice(0, t),
588
602
  query: e.slice(t + 1)
589
603
  };
590
- }, bt = (e, t) => {
604
+ }, Ft = (e, t) => {
591
605
  let n = e.split("/").filter((e) => e.length > 0), r = t.split("/").filter((e) => e.length > 0);
592
606
  return n.length === r.length && n.every((e, t) => e.startsWith(":") || e === r[t]);
593
- }, $ = (e) => {
607
+ }, It = (e) => {
594
608
  let t = {};
595
609
  for (let [n, r] of Object.entries(e)) t[n.toLowerCase()] = r;
596
610
  return t;
597
- }, xt = (e) => e === void 0 ? /* @__PURE__ */ new Uint8Array() : new TextEncoder().encode(JSON.stringify(e)), St = (e) => e === void 0 ? "" : typeof e == "string" ? e : new TextDecoder().decode(e), Ct = (e) => {
598
- let { ctx: t } = e, n = xe((e.publicApi ?? []).map((e) => ({
611
+ }, Lt = (e) => e === void 0 ? /* @__PURE__ */ new Uint8Array() : new TextEncoder().encode(JSON.stringify(e)), Rt = (e) => e === void 0 ? "" : typeof e == "string" ? e : new TextDecoder().decode(e), zt = (e) => {
612
+ let t = Se(e.security?.trustedProxies, process.env, e.security?.clientAddressHeader), { ctx: n } = e, r = Oe((e.publicApi ?? []).map((e) => ({
599
613
  descriptor: e.descriptor,
600
- invoke: (n, r) => t.withSubject(r.subject, (t) => (e.descriptor.publicApi !== void 0 && X(t, e.descriptor.publicApi), ct(e.descriptor, e.handler, n, t)))
614
+ invoke: (t, r) => n.withSubject(r.subject, (n) => (e.descriptor.publicApi !== void 0 && Z(n, e.descriptor.publicApi, r.remoteAddr), St(e.descriptor, e.handler, t, n)))
601
615
  })), {
602
- pluginErrors: J(t).flatMap((e) => e.errorSchemas ?? []),
616
+ pluginErrors: Y(n).flatMap((e) => e.errorSchemas ?? []),
603
617
  ...e.publicApiProfile === void 0 ? {} : { profile: e.publicApiProfile }
604
- }), r = [...e.restRoutes ?? [], ...n], i = v(e.strategies ?? [], {
605
- ...e.anonymousTenantRequired === void 0 ? {} : { anonymousTenantRequired: e.anonymousTenantRequired },
606
- getStore: () => t.store
607
- }), a = (n, o) => {
608
- let s = {
609
- store: t.store,
610
- buildContext: () => t,
611
- resolveSubject: n === void 0 ? async (e) => (await i({
618
+ }), i = [...e.restRoutes ?? [], ...r], a = y(e.strategies ?? [], {
619
+ anonymous: e.anonymous ?? { headerOrTenant: "acme" },
620
+ getStore: () => n.store
621
+ }), o = (r, s) => {
622
+ let c = {
623
+ store: n.store,
624
+ buildContext: () => n,
625
+ resolveSubject: r === void 0 ? async (e) => (await a({
612
626
  headers: e,
613
627
  clientId: -1
614
- })).subject : () => n,
628
+ })).subject : () => r,
615
629
  ...e.idempotency === void 0 ? {} : { idempotency: e.idempotency }
616
- }, c = Ce(r, s).map((e, t) => ({
617
- pattern: r[t].path,
630
+ }, l = Ae(i, c).map((e, t) => ({
631
+ pattern: i[t].path,
618
632
  route: e
619
- })), l = async (e, n, i = {}) => {
620
- let { path: a, query: s } = yt(n), l = c.filter((e) => bt(e.pattern, a)).map((e) => e.route);
621
- if (l.length === 0) return {
633
+ })), u = async (e, r, a = {}) => {
634
+ let { path: o, query: c } = Pt(r), u = l.filter((e) => Ft(e.pattern, o)).map((e) => e.route);
635
+ if (u.length === 0) return {
622
636
  status: 404,
623
637
  headers: {},
624
638
  text: "",
625
639
  body: {
626
640
  error: "No route mounted for this path",
627
- mounted: r.map((e) => e.path)
641
+ mounted: i.map((e) => e.path)
628
642
  },
629
643
  stream: !1
630
644
  };
631
- let u = {
645
+ let d = {
646
+ ...It(s),
647
+ ...It(a.headers ?? {})
648
+ }, f = ye({
649
+ socketAddress: a.remoteAddr ?? Nt,
650
+ headers: d,
651
+ config: t
652
+ }), p = {
632
653
  method: e.toUpperCase(),
633
- path: a,
634
- query: s,
635
- headers: {
636
- ...$(o),
637
- ...$(i.headers ?? {})
638
- },
639
- rawBody: xt(i.body),
640
- store: t.store
641
- }, d = await Se(l, u), f = {};
642
- for (let [e, t] of Object.entries(d.headers ?? {})) f[e.toLowerCase()] = t;
643
- d.contentType !== void 0 && (f["content-type"] = d.contentType);
644
- let p = St(d.body), m = (d.contentType ?? "").includes("json");
654
+ path: o,
655
+ query: c,
656
+ headers: d,
657
+ rawBody: Lt(a.body),
658
+ store: n.store,
659
+ ...f === void 0 ? {} : { remoteAddr: f }
660
+ }, m = await ke(u, p), h = {};
661
+ for (let [e, t] of Object.entries(m.headers ?? {})) h[e.toLowerCase()] = t;
662
+ m.contentType !== void 0 && (h["content-type"] = m.contentType);
663
+ let g = Rt(m.body), _ = (m.contentType ?? "").includes("json");
645
664
  return {
646
- status: d.status,
647
- headers: f,
648
- text: p,
649
- body: m && p !== "" ? JSON.parse(p) : void 0,
650
- stream: d.stream !== void 0
665
+ status: m.status,
666
+ headers: h,
667
+ text: g,
668
+ body: _ && g !== "" ? JSON.parse(g) : void 0,
669
+ stream: m.stream !== void 0
651
670
  };
652
671
  };
653
672
  return {
654
- actingAs: (e) => a(e, o),
655
- withHeaders: (e) => a(n, {
656
- ...o,
673
+ actingAs: (e) => o(e, s),
674
+ withHeaders: (e) => o(r, {
675
+ ...s,
657
676
  ...e
658
677
  }),
659
- get: (e, t) => l("GET", e, t ?? {}),
660
- delete: (e, t) => l("DELETE", e, t ?? {}),
661
- post: (e, t, n) => l("POST", e, {
678
+ get: (e, t) => u("GET", e, t ?? {}),
679
+ delete: (e, t) => u("DELETE", e, t ?? {}),
680
+ post: (e, t, n) => u("POST", e, {
662
681
  ...n ?? {},
663
682
  body: t
664
683
  }),
665
- put: (e, t, n) => l("PUT", e, {
684
+ put: (e, t, n) => u("PUT", e, {
666
685
  ...n ?? {},
667
686
  body: t
668
687
  }),
669
- patch: (e, t, n) => l("PATCH", e, {
688
+ patch: (e, t, n) => u("PATCH", e, {
670
689
  ...n ?? {},
671
690
  body: t
672
691
  }),
673
- request: (e, t, n) => l(e, t, n ?? {}),
674
- paths: r.map((e) => e.path)
692
+ request: (e, t, n) => u(e, t, n ?? {}),
693
+ paths: i.map((e) => e.path)
675
694
  };
676
695
  };
677
- return a(void 0, {});
678
- }, wt = (e = {}) => {
696
+ return o(void 0, {});
697
+ }, Bt = (e = {}) => {
679
698
  let t = e.id ?? "test", n = e.store ?? new Proxy({}, { get: (e, t) => {
680
699
  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.`);
681
700
  } });
682
701
  return {
683
702
  id: t,
684
- log: e.log ?? we({ scope: `subscribe:${t}` }),
703
+ log: e.log ?? je({ scope: `subscribe:${t}` }),
685
704
  store: n,
686
705
  ...e.publish === void 0 ? {} : { publish: e.publish }
687
706
  };
688
- }, Tt = (e) => {
707
+ }, Vt = (e) => {
689
708
  let t = /* @__PURE__ */ new Map();
690
709
  for (let n of e) {
691
710
  let e = t.get(n.stepName);
@@ -711,13 +730,18 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
711
730
  });
712
731
  }
713
732
  return n.sort((e, t) => e._startedAt - t._startedAt), n.map(({ _startedAt: e, ...t }) => t);
714
- }, Et = (e) => {
733
+ }, Ht = () => {
734
+ if (Pe() !== void 0) return;
735
+ let e = me(Me(32).toString("hex"));
736
+ Le(() => ce() ?? e);
737
+ }, Ut = (e) => {
738
+ Ht();
715
739
  let t = e.workflows ?? [], n = /* @__PURE__ */ new Map(), r = 0;
716
740
  return {
717
741
  start: async (i, a) => {
718
742
  let o = t.find((e) => e.workflow.name === i);
719
743
  if (o === void 0) throw Error(`makeWorkflowRunner: no workflow named '${i}' — pass it in makeWorkflowRunner({ ctx, workflows: [{ workflow, execute }] }).`);
720
- let s = `wfrun_test_${++r}`, c = De(), l = o.workflow.toLayer(o.execute).pipe(p.provideMerge(Ee)), d = /* @__PURE__ */ new Date(), f = o.workflow.execute(a).pipe(u.locally(Te, s), u.provide(c.layer), u.provide(l)), m = (e.ctx.store === void 0 ? f : u.provide(f, T(e.ctx.store))).pipe(u.either), h = await u.runPromise(m), g = Tt(c.readSteps()), _ = /* @__PURE__ */ new Date(), v;
744
+ let s = `wfrun_test_${++r}`, c = Ie(), l = o.workflow.toLayer(o.execute).pipe(p.provideMerge(Fe)), d = /* @__PURE__ */ new Date(), f = o.workflow.execute(a).pipe(u.locally(Ne, s), u.provide(c.layer), u.provide(l)), m = (e.ctx.store === void 0 ? f : u.provide(f, T(e.ctx.store))).pipe(u.either), h = await u.runPromise(m), g = Vt(c.readSteps()), _ = /* @__PURE__ */ new Date(), v;
721
745
  if (h._tag === "Right") v = {
722
746
  status: "succeeded",
723
747
  output: h.right,
@@ -757,6 +781,154 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
757
781
  },
758
782
  inspect: async (e) => n.get(e) ?? null
759
783
  };
760
- }, Dt = 1;
784
+ }, Wt = (e, t, n = {}) => {
785
+ let r = n.name ?? "mock", i = [], a = /* @__PURE__ */ new Map(), o = (e, t) => `${e}\u0000${JSON.stringify(t)}`, s = async (n, a, o) => {
786
+ let s = e[n];
787
+ if (s === void 0) throw Error(`makeServiceApiMock: '${n}' is not a service procedure of this api`);
788
+ let c = s.input, l = m.encodeUnknownSync(c)(a), u = m.decodeUnknownSync(c)(l);
789
+ i.push({
790
+ tag: n,
791
+ input: u,
792
+ idempotencyKey: o?.idempotencyKey
793
+ });
794
+ let d = t[n];
795
+ if (d === void 0) throw new h({
796
+ api: r,
797
+ tag: n,
798
+ reason: "transport",
799
+ message: "no handler in makeServiceApiMock"
800
+ });
801
+ let f = await d(u), p = s.output;
802
+ return m.decodeUnknownSync(p)(m.encodeUnknownSync(p)(f));
803
+ }, c = (e) => {
804
+ let t = e.join("."), n = Object.assign((e, n) => s(t, e, n), {
805
+ effect: (e, n) => u.tryPromise({
806
+ try: () => s(t, e, n),
807
+ catch: (e) => e
808
+ }),
809
+ subscribe: (e, n) => {
810
+ let r = o(t, e), i = a.get(r) ?? /* @__PURE__ */ new Set();
811
+ return a.set(r, i), i.add(n.onValue), s(t, e).then(n.onValue, (e) => n.onError?.(e)), { unsubscribe: () => {
812
+ i.delete(n.onValue);
813
+ } };
814
+ }
815
+ });
816
+ return new Proxy(n, { get: (t, n) => {
817
+ if (typeof n == "string") {
818
+ if (n === "effect" || n === "subscribe") return t[n];
819
+ if (n !== "then") return c([...e, n]);
820
+ }
821
+ } });
822
+ };
823
+ return {
824
+ api: new Proxy({}, { get: (e, t) => typeof t == "string" && t !== "then" ? c([t]) : void 0 }),
825
+ calls: (e) => e === void 0 ? [...i] : i.filter((t) => t.tag === e),
826
+ emit: (t, n, r) => {
827
+ let i = e[t], s = i === void 0 ? r : m.decodeUnknownSync(i.output)(m.encodeUnknownSync(i.output)(r));
828
+ for (let e of a.get(o(t, n)) ?? []) e(s);
829
+ }
830
+ };
831
+ }, Gt = () => new Promise((e, t) => {
832
+ let n = k.createServer();
833
+ n.once("error", t), n.listen(0, "127.0.0.1", () => {
834
+ let t = n.address(), r = typeof t == "object" && t ? t.port : 0;
835
+ n.close(() => e(r));
836
+ });
837
+ }), Kt = async (e) => {
838
+ try {
839
+ return (await fetch(`http://127.0.0.1:${e}/internal/readiness`)).status === 200;
840
+ } catch {
841
+ return !1;
842
+ }
843
+ }, qt = (e) => A(Be(ze(A(e, "package.json")).resolve("@voltro/cli/package.json")), "bin", "voltro.mjs"), Jt = 1e4, Yt = (e) => new Promise((t) => {
844
+ if (e.exitCode !== null || e.signalCode !== null) return t();
845
+ let n = setTimeout(() => {
846
+ e.kill("SIGKILL");
847
+ }, Jt);
848
+ e.once("exit", () => {
849
+ clearTimeout(n), t();
850
+ }), e.kill("SIGTERM");
851
+ }), Xt = async (e) => {
852
+ let t = Object.keys(e.apps);
853
+ if (t.length === 0) throw Error("startTestApps: no apps given");
854
+ let n = e.mode ?? "dev", r = e.bootTimeoutMs ?? 3e5, i = e.cli ?? qt(e.apps[t[0]].root), a = /* @__PURE__ */ new Map();
855
+ for (let e of t) a.set(e, await Gt());
856
+ let o = /* @__PURE__ */ new Map(), s = new Map(t.map((e) => [e, {}]));
857
+ for (let n of e.edges ?? []) {
858
+ for (let e of [n.caller, n.callee]) if (!t.includes(e)) throw Error(`startTestApps: edge names '${e}', which is not among the apps (${t.join(", ")})`);
859
+ let e = _e();
860
+ o.set(`${n.caller}\u0000${n.callee}`, e), Object.assign(s.get(n.caller), {
861
+ [re(n.binding)]: e,
862
+ [ie(n.binding)]: `ws://127.0.0.1:${a.get(n.callee)}/ws`
863
+ }), Object.assign(s.get(n.callee), { [we(n.caller)]: e });
864
+ }
865
+ let c = [], l = /* @__PURE__ */ new Set(), u = (t) => {
866
+ if (!c.includes(t)) {
867
+ if (l.has(t)) throw Error(`startTestApps: the edges form a cycle through '${t}' — no app can boot first`);
868
+ l.add(t);
869
+ for (let n of e.edges ?? []) n.caller === t && u(n.callee);
870
+ l.delete(t), c.push(t);
871
+ }
872
+ };
873
+ for (let e of t) u(e);
874
+ let d = [], f = /* @__PURE__ */ new Map(), p = async () => {
875
+ await Promise.all(d.map(Yt));
876
+ };
877
+ for (let t of c) {
878
+ let o = e.apps[t], c = a.get(t), l = "", u = Re(process.execPath, [
879
+ i,
880
+ n,
881
+ ...n === "serve" ? ["."] : []
882
+ ], {
883
+ cwd: o.root,
884
+ env: {
885
+ ...process.env,
886
+ ...n === "serve" ? { VOLTRO_SESSION_SECRET: Me(32).toString("base64url") } : {},
887
+ ...o.env,
888
+ ...s.get(t),
889
+ PORT: String(c)
890
+ },
891
+ stdio: [
892
+ "ignore",
893
+ "pipe",
894
+ "pipe"
895
+ ]
896
+ });
897
+ d.push(u), u.stdout?.on("data", (e) => {
898
+ l += e.toString();
899
+ }), u.stderr?.on("data", (e) => {
900
+ l += e.toString();
901
+ }), u.on("exit", (e, t) => {
902
+ l += `\n[exited] code=${String(e)} signal=${String(t)}`;
903
+ });
904
+ let m = {
905
+ name: t,
906
+ port: c,
907
+ url: `http://127.0.0.1:${c}`,
908
+ wsUrl: `ws://127.0.0.1:${c}/ws`,
909
+ log: () => l,
910
+ stop: () => Yt(u)
911
+ };
912
+ f.set(t, m);
913
+ let h = Date.now() + r;
914
+ for (; !await Kt(c);) {
915
+ if (u.exitCode !== null || u.signalCode !== null || Date.now() > h) {
916
+ await p();
917
+ let e = u.exitCode !== null || u.signalCode !== null ? "exited before it was ready" : `was not ready within ${r} ms`;
918
+ throw Error(`startTestApps: '${t}' ${e}\n${m.log().slice(-4e3)}`);
919
+ }
920
+ await new Promise((e) => setTimeout(e, 250));
921
+ }
922
+ }
923
+ return {
924
+ apps: Object.fromEntries(f),
925
+ token: (e, t) => {
926
+ let n = o.get(`${e}\u0000${t}`);
927
+ if (n === void 0) throw Error(`startTestApps: no edge ${e} → ${t}`);
928
+ return n;
929
+ },
930
+ stop: p
931
+ };
932
+ }, Zt = 1;
761
933
  //#endregion
762
- export { R as MockClock, V as MockLLM, z as MockWebhooks, Dt as TESTING_PRESET_VERSION, pt as TEST_TENANT_ID, _t as anonymous, ht as apiKey, n as changeDelete, r as changeInsert, i as changeSoftDelete, a as changeUpdate, Le as defineFactory, ut as describeIfAvailable, dt as describeIfReachable, j as fixtureRow, Ve as frozenTime, Ne as hydrateFixtureRows, ct as invoke, lt as isTcpReachable, wt as makeSubscribeContext, Ct as makeTestApp, ot as makeTestContext, Et as makeWorkflowRunner, X as markRestInvocation, Ue as mockStore, A as nextSequence, Xe as outboxNudgesOf, J as pluginsOf, ft as reportEngineVersion, Ye as resetAfterCommit, Ge as restInvocationOf, qe as rpcInterceptorFor, Z as runAfterCommit, Ze as runInStoreTransaction, gt as serviceAccount, Je as serviceLayerFor, vt as system, B as testEventBus, mt as user, Be as withFrozenTime, We as withRpcConnection };
934
+ export { z as MockClock, H as MockLLM, B as MockWebhooks, Zt as TESTING_PRESET_VERSION, Dt as TEST_TENANT_ID, jt as anonymous, kt as apiKey, n as changeDelete, r as changeInsert, i as changeSoftDelete, a as changeUpdate, Ze as defineFactory, wt as describeIfAvailable, Tt as describeIfReachable, N as fixtureRow, tt as frozenTime, Ke as hydrateFixtureRows, St as invoke, Ct as isTcpReachable, Wt as makeServiceApiMock, Bt as makeSubscribeContext, zt as makeTestApp, bt as makeTestContext, Ut as makeWorkflowRunner, Z as markRestInvocation, rt as mockStore, M as nextSequence, ut as outboxNudgesOf, Y as pluginsOf, Et as reportEngineVersion, lt as resetAfterCommit, at as restInvocationOf, st as rpcInterceptorFor, Q as runAfterCommit, dt as runInStoreTransaction, At as serviceAccount, ct as serviceLayerFor, Xt as startTestApps, Mt as system, V as testEventBus, Ot as user, et as withFrozenTime, it as withRpcConnection };