@voltro/testing 0.79.1 → 0.81.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,19 @@
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, getRowFilter as w, getSystemStoreHandle as ce, makeAppAccess as le, makeConnectionState as ue, makeDataLoader as de, makeEffectStoreLayer as fe, 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 T, runWithDeadlockRetry as Ce, serviceCallerTokenEnv as we, setFieldCipher as Te, setSystemStoreHandle as E, wrapStoreWithMixinBehaviour as D } from "@voltro/runtime";
5
+ import { installEnvSnapshot as Ee } from "@voltro/env";
6
+ import O 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 { CurrentWorkflowRunId as Me, inMemoryWorkflowEngineLayer as Ne, makeInMemoryRecorder as Pe } from "@voltro/workflow";
11
+ import { spawn as Fe } from "node:child_process";
12
+ import { randomBytes as Ie } from "node:crypto";
13
+ import { createRequire as Le } from "node:module";
14
+ import { dirname as Re, join as ze } from "node:path";
11
15
  //#region src/fixtureRow.ts
12
- var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
16
+ var Be = new Set(e), k = 0, Ve = () => ++k, 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;
@@ -27,38 +31,38 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
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
+ }, A = (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)) Be.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
+ }, j = 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 = j(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 = j(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(Ve()) : 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 M(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
+ }, M = 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, A(t, a));
82
+ }, N = (e, t) => typeof e == "function" ? e(t) : e ?? {}, Xe = (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 = {}) => A(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(N(t, n))),
92
+ create: (t, n = {}) => M(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 M(t, e, a(N(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
+ }, P = Symbol.for("voltro/testing/mockClock.installed"), F = () => globalThis, Ze = (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
+ }), Qe = (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
+ }, I = class {
123
127
  currentMs;
124
128
  constructor(e = "2026-01-01T00:00:00Z") {
125
- this.currentMs = L(e);
129
+ this.currentMs = Qe(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 = Qe(e);
138
142
  }
139
143
  get installed() {
140
- return I()[F]?.clock === this;
144
+ return F()[P]?.clock === this;
141
145
  }
142
146
  install() {
143
- let e = I(), t = e[F];
147
+ let e = F(), t = e[P];
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[P] = {
147
151
  realDate: n,
148
152
  clock: this
149
- }, globalThis.Date = Re(n, () => this.currentMs), () => {
153
+ }, globalThis.Date = Ze(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 = F(), t = e[P];
159
+ t !== void 0 && t.clock === this && (globalThis.Date = t.realDate, delete e[P]);
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 I ? e : new I(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 I ? e : new I(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,7 +187,7 @@ 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
+ }, L = class {
187
191
  emitted = [];
188
192
  async emit(e, t) {
189
193
  let n = typeof e == "string" ? e : e.id ?? e.event ?? "(unnamed event)";
@@ -202,14 +206,14 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
202
206
  clear() {
203
207
  this.emitted.length = 0;
204
208
  }
205
- }, B = (e = {}) => {
206
- let t = e.tenantId ?? null, n = new S({
209
+ }, R = (e = {}) => {
210
+ let t = e.tenantId ?? null, n = new te({
207
211
  origin: e.origin ?? "test",
208
212
  ...e.ringSize === void 0 ? {} : { ringSize: e.ringSize }
209
213
  });
210
214
  return {
211
215
  publish: async (e, r, i) => {
212
- let a = await u.runPromise(u.either(pe({
216
+ let a = await u.runPromise(u.either(ve({
213
217
  bus: n,
214
218
  tenantId: t
215
219
  }, e, r, i)));
@@ -258,7 +262,7 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
258
262
  },
259
263
  skipSerials: (e, r, i, a) => {
260
264
  let o = a?.tenantId ?? t, s = {
261
- route: b(o, e.name, r),
265
+ route: x(o, e.name, r),
262
266
  event: e.name,
263
267
  origin: "test-gap",
264
268
  n: i + 1,
@@ -272,7 +276,7 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
272
276
  n.clear();
273
277
  }
274
278
  };
275
- }, V = class {
279
+ }, z = class {
276
280
  queue;
277
281
  calls = [];
278
282
  constructor(e) {
@@ -287,38 +291,41 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
287
291
  remaining() {
288
292
  return this.queue.length;
289
293
  }
290
- }, Ue = (e) => e, H = "00000000000000000000000000000000", U = /* @__PURE__ */ new WeakMap(), W = /* @__PURE__ */ new WeakMap(), We = (e, t) => {
291
- let n = W.get(e);
294
+ }, rt = (e) => e, B = "00000000000000000000000000000000", V = /* @__PURE__ */ new WeakMap(), H = /* @__PURE__ */ new WeakMap(), it = (e, t) => {
295
+ let n = H.get(e);
292
296
  if (n === void 0) throw Error("withRpcConnection requires a context created by makeTestContext");
293
297
  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 = [];
298
+ }, U = /* @__PURE__ */ new WeakMap(), W = /* @__PURE__ */ new WeakMap(), G = /* @__PURE__ */ new WeakMap(), K = (e) => G.get(e) ?? [], q = /* @__PURE__ */ new WeakMap(), J = (e, t, n) => {
299
+ q.set(e, {
300
+ publicApi: t,
301
+ ...n === void 0 ? {} : { remoteAddr: n }
302
+ });
303
+ }, Y = (e) => q.get(e), X = /* @__PURE__ */ new WeakMap(), at = (e, t) => {
304
+ let n = G.get(e) ?? [], r = t === "mutation" ? "interceptMutation" : t === "query" ? "interceptQuery" : "interceptAction", i = [];
298
305
  for (let e of n) {
299
306
  let t = e[r];
300
307
  typeof t == "function" && i.push(t);
301
308
  }
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];
309
+ return b(i);
310
+ }, ot = (e) => {
311
+ let t = (G.get(e) ?? []).map((e) => e.services).filter((e) => e !== void 0), n = X.get(e) ?? [], r = [...t, ...n];
305
312
  if (r.length !== 0) return p.mergeAll(...r);
306
- }, Ye = (e) => {
307
- let t = G.get(e);
313
+ }, st = (e) => {
314
+ let t = U.get(e);
308
315
  t !== void 0 && (t.length = 0);
309
316
  }, Z = async (e) => {
310
- let t = G.get(e);
317
+ let t = U.get(e);
311
318
  if (t === void 0 || t.length === 0) return;
312
319
  let n = [...t];
313
320
  t.length = 0;
314
321
  for (let e of n) await e();
315
- }, Xe = (e) => K.get(e) ?? [], Ze = async (e, t) => {
316
- let n = U.get(e);
322
+ }, ct = (e) => W.get(e) ?? [], lt = async (e, t) => {
323
+ let n = V.get(e);
317
324
  return n === void 0 ? e.store.transactional(async (n) => t({
318
325
  ...e,
319
326
  store: n
320
327
  })) : n(t);
321
- }, Qe = (e) => {
328
+ }, ut = (e) => {
322
329
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = (n) => {
323
330
  let r = t.get(n);
324
331
  return r === void 0 ? !1 : r.expiresAt !== null && r.expiresAt <= e() ? (t.delete(n), !1) : !0;
@@ -357,7 +364,7 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
357
364
  return i(e, o, n.ttlMs, n.tags), o;
358
365
  }
359
366
  };
360
- }, $e = (e) => {
367
+ }, dt = (e) => {
361
368
  let t = /* @__PURE__ */ new Map(), n = (n) => {
362
369
  let r = t.get(n);
363
370
  return r === void 0 ? !1 : r.expiresAt !== null && r.expiresAt <= e() ? (t.delete(n), !1) : !0;
@@ -385,47 +392,47 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
385
392
  t.clear();
386
393
  }
387
394
  };
388
- }, et = async (e, t) => {
389
- let n = ae();
390
- D(e);
395
+ }, ft = async (e, t) => {
396
+ let n = ce();
397
+ E(e);
391
398
  try {
392
399
  return await t();
393
400
  } finally {
394
- n === void 0 ? ie() : D(n);
401
+ n === void 0 ? se() : E(n);
395
402
  }
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;
403
+ }, pt = /* @__PURE__ */ new Set(), mt = (e) => {
404
+ pt.has(e) || (pt.add(e), console.warn(e));
405
+ }, ht = (e, t, n) => {
406
+ let r = gt, i;
400
407
  return () => {
401
408
  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) => {
409
+ return t !== void 0 && w() !== void 0 && t !== w() && mt("[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 = ft(n, () => T(be(a, e, (e) => {
403
410
  console.error("[voltro:testing] row filter failed to load — reads refused for this subject", e);
404
411
  })))), i;
405
412
  };
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));
413
+ }, gt = Symbol("unresolved"), Q = (e, t) => new Proxy(e, { get: (e, n) => {
414
+ if (n === "query") return async (n) => e.query(oe(await t(), n));
408
415
  let r = Reflect.get(e, n, e);
409
416
  return typeof r == "function" ? r.bind(e) : r;
410
- } }), ot = (e = {}) => {
411
- if (ve({
417
+ } }), _t = (e = {}) => {
418
+ if (Ee({
412
419
  ...process.env,
413
420
  ...e.env ?? {}
414
- }), e.fieldEncryptionKey !== void 0 && _e(ue(e.fieldEncryptionKey)), e.relations !== void 0) {
421
+ }), e.fieldEncryptionKey !== void 0 && Te(me(e.fieldEncryptionKey)), e.relations !== void 0) {
415
422
  o();
416
423
  for (let t of e.relations) c(t);
417
424
  }
418
- let n = e.tables ?? t(), r = fe(n), i = new te(e.store ?? {}), a = {
425
+ let n = e.tables ?? t(), r = ge(n), i = new ne(e.store ?? {}), a = {
419
426
  dataStore: i,
420
427
  schemaRegistry: r
421
428
  };
422
- 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) => {
429
+ E(a);
430
+ let s = new I(e.clockStart), l = new L(), u = R(), d = new z(e.llmResponses ?? []), f = ut(() => s.now()), p = dt(() => s.now()), m = (t, n, o = i, c, h = !1) => {
424
431
  let g = {
425
432
  subject: t,
426
- traceId: H,
433
+ traceId: B,
427
434
  ...n === void 0 ? {} : { connection: n }
428
- }, _ = c?.queued ?? [], v = c?.nudges ?? [], y = le({
435
+ }, _ = c?.queued ?? [], v = c?.nudges ?? [], y = pe({
429
436
  bus: u.bus,
430
437
  tenantId: t.tenantId ?? null,
431
438
  ...o === i ? {} : { deferToCommit: (e) => {
@@ -433,9 +440,10 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
433
440
  e();
434
441
  });
435
442
  } }
436
- }), b = ce({ store: o }), x = h ? async () => C : rt(t, e.rowFilter, a), S = {
443
+ }), b = de({ store: o }), x = h ? async () => C : ht(t, e.rowFilter, a), S = {
444
+ apis: e.apis ?? Object.freeze({}),
437
445
  transaction: async (e, r) => {
438
- let a = he(t, r?.tenantId, o !== i);
446
+ let a = xe(t, r?.tenantId, o !== i);
439
447
  if (a !== t) return m(a, n, i, void 0, !0).transaction(e);
440
448
  if (o !== i) return e(S);
441
449
  let s, c = await o.transactional(async (r) => {
@@ -445,7 +453,7 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
445
453
  }, h), a = await e(i);
446
454
  return s = i, a;
447
455
  });
448
- return s !== void 0 && (await Z(s), v.push(...Xe(s))), c;
456
+ return s !== void 0 && (await Z(s), v.push(...ct(s))), c;
449
457
  },
450
458
  clock: s,
451
459
  webhooks: l,
@@ -454,29 +462,29 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
454
462
  llm: d,
455
463
  ...e.ai === void 0 ? {} : { ai: e.ai },
456
464
  request: g,
457
- ...n === void 0 ? {} : { connectionState: se(n, o === i ? void 0 : (e) => {
465
+ ...n === void 0 ? {} : { connectionState: ue(n, o === i ? void 0 : (e) => {
458
466
  _.push(e);
459
467
  }) },
460
- validation: ne,
461
- access: oe(t),
468
+ validation: ae,
469
+ access: le(t),
462
470
  cache: f,
463
471
  kv: p,
464
- store: O(at(o, x), {
472
+ store: D(Q(o, x), {
465
473
  subject: t,
466
474
  schemaRegistry: r,
467
475
  rowFilter: C
468
476
  }),
469
- storeForTenant: (e) => O(at(o, x), {
477
+ storeForTenant: (e) => D(Q(o, x), {
470
478
  subject: ee(t, e),
471
479
  schemaRegistry: r,
472
480
  rowFilter: C
473
481
  }),
474
- outbox: de({
482
+ outbox: he({
475
483
  store: o,
476
484
  subject: t,
477
- traceId: H,
485
+ traceId: B,
478
486
  nudge: () => {
479
- v.push(H);
487
+ v.push(B);
480
488
  },
481
489
  afterCommit: (e) => {
482
490
  _.push(e);
@@ -507,37 +515,37 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
507
515
  nudges: v
508
516
  })
509
517
  };
510
- return G.set(S, _), W.set(S, (e) => m(t, e, o, {
518
+ return U.set(S, _), H.set(S, (e) => m(t, e, o, {
511
519
  queued: _,
512
520
  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, {
521
+ })), 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, {
514
522
  queued: _,
515
523
  nudges: v
516
524
  })))), S;
517
525
  };
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) => {
526
+ return m(e.subject ?? _(null), e.connection);
527
+ }, vt = (e, t) => {
528
+ let n = ot(t);
529
+ return (n === void 0 ? e : u.provide(e, n)).pipe(u.provide(fe(t.store)), u.provideService(g, t.request.subject));
530
+ }, yt = async (e, t, n, r) => {
523
531
  let i = e.input, a = await m.decodeUnknownPromise(i)(n), o = e.kind, s = async (e) => {
524
532
  let n = t(a, e);
525
- return u.isEffect(n) ? E(st(n, e)) : n;
533
+ return u.isEffect(n) ? T(vt(n, e)) : n;
526
534
  }, c = async () => {
527
535
  let t = e.guards;
528
536
  if (t !== void 0 && t.length > 0) {
529
- let e = await u.runPromise(_(r.request.subject, t, a));
537
+ let e = await u.runPromise(v(r.request.subject, t, a));
530
538
  if (e !== null) throw e;
531
539
  }
532
540
  if (o !== "mutation") return s(r);
533
- let n = await ge(async () => Ze(r, async (e) => (Ye(r), s(e))), { delay: () => Promise.resolve() });
541
+ let n = await Ce(async () => lt(r, async (e) => (st(r), s(e))), { delay: () => Promise.resolve() });
534
542
  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);
543
+ }, d = o === "mutation" || o === "query" || o === "action" ? o : void 0, p = d === void 0 ? void 0 : at(r, d);
536
544
  if (p === void 0 || d === void 0) return await c();
537
545
  let h = u.tryPromise({
538
546
  try: () => c(),
539
547
  catch: (e) => e
540
- }), g = Ge(r), v = p(h, {
548
+ }), g = Y(r), _ = p(h, {
541
549
  tag: e.name ?? "",
542
550
  kind: d,
543
551
  input: a,
@@ -547,16 +555,17 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
547
555
  ...g === void 0 ? {} : {
548
556
  surface: "rest",
549
557
  publicApi: g.publicApi
550
- }
551
- }), y = await u.runPromiseExit(v);
558
+ },
559
+ ...g?.remoteAddr === void 0 ? {} : { remoteAddr: g.remoteAddr }
560
+ }), y = await u.runPromiseExit(_);
552
561
  if (f.isSuccess(y)) return y.value;
553
562
  throw l.squash(y.cause);
554
- }, lt = (e) => new Promise((t) => {
555
- let n = new ye.Socket(), r = (e) => {
563
+ }, bt = (e) => new Promise((t) => {
564
+ let n = new O.Socket(), r = (e) => {
556
565
  clearTimeout(i), n.destroy(), t(e);
557
566
  }, i = setTimeout(() => r(!1), e.timeoutMs ?? 750);
558
567
  n.once("connect", () => r(!0)), n.once("error", () => r(!1)), n.connect(e.port, e.host);
559
- }), ut = async (e, t, n, r) => {
568
+ }), xt = async (e, t, n, r) => {
560
569
  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
570
  let i = !1;
562
571
  try {
@@ -564,21 +573,21 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
564
573
  } catch {
565
574
  i = !1;
566
575
  }
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) => {
576
+ De.skipIf(!i)(i ? e : `${e} [SKIPPED: needs ${t}]`, r);
577
+ }, St = async (e, t, n) => {
578
+ await xt(e, `${t.name} at ${t.host}:${t.port}`, () => bt(t), n);
579
+ }, Ct = async (e, t) => {
571
580
  try {
572
581
  let n = await t();
573
582
  n !== void 0 && n !== "" && console.log(`[engine] ${e}: ${n}`);
574
583
  } catch {}
575
- }, pt = "test-tenant", Q = (e, t, n) => ({
584
+ }, wt = "test-tenant", $ = (e, t, n) => ({
576
585
  type: e,
577
586
  id: t,
578
587
  tenantId: n.tenantId ?? "test-tenant",
579
588
  scopes: n.scopes ?? [],
580
589
  ...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) => {
590
+ }), Tt = (e, t = {}) => $("user", e, t), Et = (e, t = {}) => $("apiKey", e, t), Dt = (e, t = {}) => $("serviceAccount", e, t), Ot = (e = null) => _(e), kt = (e = "job:test", t) => t === void 0 ? S(e) : S(e, t), At = "127.0.0.1", jt = (e) => {
582
591
  let t = e.indexOf("?");
583
592
  return t === -1 ? {
584
593
  path: e,
@@ -587,105 +596,110 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
587
596
  path: e.slice(0, t),
588
597
  query: e.slice(t + 1)
589
598
  };
590
- }, bt = (e, t) => {
599
+ }, Mt = (e, t) => {
591
600
  let n = e.split("/").filter((e) => e.length > 0), r = t.split("/").filter((e) => e.length > 0);
592
601
  return n.length === r.length && n.every((e, t) => e.startsWith(":") || e === r[t]);
593
- }, $ = (e) => {
602
+ }, Nt = (e) => {
594
603
  let t = {};
595
604
  for (let [n, r] of Object.entries(e)) t[n.toLowerCase()] = r;
596
605
  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) => ({
606
+ }, Pt = (e) => e === void 0 ? /* @__PURE__ */ new Uint8Array() : new TextEncoder().encode(JSON.stringify(e)), Ft = (e) => e === void 0 ? "" : typeof e == "string" ? e : new TextDecoder().decode(e), It = (e) => {
607
+ let t = Se(e.security?.trustedProxies, process.env, e.security?.clientAddressHeader), { ctx: n } = e, r = Oe((e.publicApi ?? []).map((e) => ({
599
608
  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)))
609
+ invoke: (t, r) => n.withSubject(r.subject, (n) => (e.descriptor.publicApi !== void 0 && J(n, e.descriptor.publicApi, r.remoteAddr), yt(e.descriptor, e.handler, t, n)))
601
610
  })), {
602
- pluginErrors: J(t).flatMap((e) => e.errorSchemas ?? []),
611
+ pluginErrors: K(n).flatMap((e) => e.errorSchemas ?? []),
603
612
  ...e.publicApiProfile === void 0 ? {} : { profile: e.publicApiProfile }
604
- }), r = [...e.restRoutes ?? [], ...n], i = v(e.strategies ?? [], {
613
+ }), i = [...e.restRoutes ?? [], ...r], a = y(e.strategies ?? [], {
605
614
  ...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({
615
+ getStore: () => n.store
616
+ }), o = (r, s) => {
617
+ let c = {
618
+ store: n.store,
619
+ buildContext: () => n,
620
+ resolveSubject: r === void 0 ? async (e) => (await a({
612
621
  headers: e,
613
622
  clientId: -1
614
- })).subject : () => n,
623
+ })).subject : () => r,
615
624
  ...e.idempotency === void 0 ? {} : { idempotency: e.idempotency }
616
- }, c = Ce(r, s).map((e, t) => ({
617
- pattern: r[t].path,
625
+ }, l = Ae(i, c).map((e, t) => ({
626
+ pattern: i[t].path,
618
627
  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 {
628
+ })), u = async (e, r, a = {}) => {
629
+ let { path: o, query: c } = jt(r), u = l.filter((e) => Mt(e.pattern, o)).map((e) => e.route);
630
+ if (u.length === 0) return {
622
631
  status: 404,
623
632
  headers: {},
624
633
  text: "",
625
634
  body: {
626
635
  error: "No route mounted for this path",
627
- mounted: r.map((e) => e.path)
636
+ mounted: i.map((e) => e.path)
628
637
  },
629
638
  stream: !1
630
639
  };
631
- let u = {
640
+ let d = {
641
+ ...Nt(s),
642
+ ...Nt(a.headers ?? {})
643
+ }, f = ye({
644
+ socketAddress: a.remoteAddr ?? At,
645
+ headers: d,
646
+ config: t
647
+ }), p = {
632
648
  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");
649
+ path: o,
650
+ query: c,
651
+ headers: d,
652
+ rawBody: Pt(a.body),
653
+ store: n.store,
654
+ ...f === void 0 ? {} : { remoteAddr: f }
655
+ }, m = await ke(u, p), h = {};
656
+ for (let [e, t] of Object.entries(m.headers ?? {})) h[e.toLowerCase()] = t;
657
+ m.contentType !== void 0 && (h["content-type"] = m.contentType);
658
+ let g = Ft(m.body), _ = (m.contentType ?? "").includes("json");
645
659
  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
660
+ status: m.status,
661
+ headers: h,
662
+ text: g,
663
+ body: _ && g !== "" ? JSON.parse(g) : void 0,
664
+ stream: m.stream !== void 0
651
665
  };
652
666
  };
653
667
  return {
654
- actingAs: (e) => a(e, o),
655
- withHeaders: (e) => a(n, {
656
- ...o,
668
+ actingAs: (e) => o(e, s),
669
+ withHeaders: (e) => o(r, {
670
+ ...s,
657
671
  ...e
658
672
  }),
659
- get: (e, t) => l("GET", e, t ?? {}),
660
- delete: (e, t) => l("DELETE", e, t ?? {}),
661
- post: (e, t, n) => l("POST", e, {
673
+ get: (e, t) => u("GET", e, t ?? {}),
674
+ delete: (e, t) => u("DELETE", e, t ?? {}),
675
+ post: (e, t, n) => u("POST", e, {
662
676
  ...n ?? {},
663
677
  body: t
664
678
  }),
665
- put: (e, t, n) => l("PUT", e, {
679
+ put: (e, t, n) => u("PUT", e, {
666
680
  ...n ?? {},
667
681
  body: t
668
682
  }),
669
- patch: (e, t, n) => l("PATCH", e, {
683
+ patch: (e, t, n) => u("PATCH", e, {
670
684
  ...n ?? {},
671
685
  body: t
672
686
  }),
673
- request: (e, t, n) => l(e, t, n ?? {}),
674
- paths: r.map((e) => e.path)
687
+ request: (e, t, n) => u(e, t, n ?? {}),
688
+ paths: i.map((e) => e.path)
675
689
  };
676
690
  };
677
- return a(void 0, {});
678
- }, wt = (e = {}) => {
691
+ return o(void 0, {});
692
+ }, Lt = (e = {}) => {
679
693
  let t = e.id ?? "test", n = e.store ?? new Proxy({}, { get: (e, t) => {
680
694
  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
695
  } });
682
696
  return {
683
697
  id: t,
684
- log: e.log ?? we({ scope: `subscribe:${t}` }),
698
+ log: e.log ?? je({ scope: `subscribe:${t}` }),
685
699
  store: n,
686
700
  ...e.publish === void 0 ? {} : { publish: e.publish }
687
701
  };
688
- }, Tt = (e) => {
702
+ }, Rt = (e) => {
689
703
  let t = /* @__PURE__ */ new Map();
690
704
  for (let n of e) {
691
705
  let e = t.get(n.stepName);
@@ -711,13 +725,13 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
711
725
  });
712
726
  }
713
727
  return n.sort((e, t) => e._startedAt - t._startedAt), n.map(({ _startedAt: e, ...t }) => t);
714
- }, Et = (e) => {
728
+ }, zt = (e) => {
715
729
  let t = e.workflows ?? [], n = /* @__PURE__ */ new Map(), r = 0;
716
730
  return {
717
731
  start: async (i, a) => {
718
732
  let o = t.find((e) => e.workflow.name === i);
719
733
  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;
734
+ let s = `wfrun_test_${++r}`, c = Pe(), l = o.workflow.toLayer(o.execute).pipe(p.provideMerge(Ne)), d = /* @__PURE__ */ new Date(), f = o.workflow.execute(a).pipe(u.locally(Me, s), u.provide(c.layer), u.provide(l)), m = (e.ctx.store === void 0 ? f : u.provide(f, fe(e.ctx.store))).pipe(u.either), h = await u.runPromise(m), g = Rt(c.readSteps()), _ = /* @__PURE__ */ new Date(), v;
721
735
  if (h._tag === "Right") v = {
722
736
  status: "succeeded",
723
737
  output: h.right,
@@ -757,6 +771,154 @@ var Oe = new Set(e), k = 0, A = () => ++k, ke = (e, t) => {
757
771
  },
758
772
  inspect: async (e) => n.get(e) ?? null
759
773
  };
760
- }, Dt = 1;
774
+ }, Bt = (e, t, n = {}) => {
775
+ let r = n.name ?? "mock", i = [], a = /* @__PURE__ */ new Map(), o = (e, t) => `${e}\u0000${JSON.stringify(t)}`, s = async (n, a, o) => {
776
+ let s = e[n];
777
+ if (s === void 0) throw Error(`makeServiceApiMock: '${n}' is not a service procedure of this api`);
778
+ let c = s.input, l = m.encodeUnknownSync(c)(a), u = m.decodeUnknownSync(c)(l);
779
+ i.push({
780
+ tag: n,
781
+ input: u,
782
+ idempotencyKey: o?.idempotencyKey
783
+ });
784
+ let d = t[n];
785
+ if (d === void 0) throw new h({
786
+ api: r,
787
+ tag: n,
788
+ reason: "transport",
789
+ message: "no handler in makeServiceApiMock"
790
+ });
791
+ let f = await d(u), p = s.output;
792
+ return m.decodeUnknownSync(p)(m.encodeUnknownSync(p)(f));
793
+ }, c = (e) => {
794
+ let t = e.join("."), n = Object.assign((e, n) => s(t, e, n), {
795
+ effect: (e, n) => u.tryPromise({
796
+ try: () => s(t, e, n),
797
+ catch: (e) => e
798
+ }),
799
+ subscribe: (e, n) => {
800
+ let r = o(t, e), i = a.get(r) ?? /* @__PURE__ */ new Set();
801
+ return a.set(r, i), i.add(n.onValue), s(t, e).then(n.onValue, (e) => n.onError?.(e)), { unsubscribe: () => {
802
+ i.delete(n.onValue);
803
+ } };
804
+ }
805
+ });
806
+ return new Proxy(n, { get: (t, n) => {
807
+ if (typeof n == "string") {
808
+ if (n === "effect" || n === "subscribe") return t[n];
809
+ if (n !== "then") return c([...e, n]);
810
+ }
811
+ } });
812
+ };
813
+ return {
814
+ api: new Proxy({}, { get: (e, t) => typeof t == "string" && t !== "then" ? c([t]) : void 0 }),
815
+ calls: (e) => e === void 0 ? [...i] : i.filter((t) => t.tag === e),
816
+ emit: (t, n, r) => {
817
+ let i = e[t], s = i === void 0 ? r : m.decodeUnknownSync(i.output)(m.encodeUnknownSync(i.output)(r));
818
+ for (let e of a.get(o(t, n)) ?? []) e(s);
819
+ }
820
+ };
821
+ }, Vt = () => new Promise((e, t) => {
822
+ let n = O.createServer();
823
+ n.once("error", t), n.listen(0, "127.0.0.1", () => {
824
+ let t = n.address(), r = typeof t == "object" && t ? t.port : 0;
825
+ n.close(() => e(r));
826
+ });
827
+ }), Ht = async (e) => {
828
+ try {
829
+ return (await fetch(`http://127.0.0.1:${e}/internal/readiness`)).status === 200;
830
+ } catch {
831
+ return !1;
832
+ }
833
+ }, Ut = (e) => ze(Re(Le(ze(e, "package.json")).resolve("@voltro/cli/package.json")), "bin", "voltro.mjs"), Wt = 1e4, Gt = (e) => new Promise((t) => {
834
+ if (e.exitCode !== null || e.signalCode !== null) return t();
835
+ let n = setTimeout(() => {
836
+ e.kill("SIGKILL");
837
+ }, Wt);
838
+ e.once("exit", () => {
839
+ clearTimeout(n), t();
840
+ }), e.kill("SIGTERM");
841
+ }), Kt = async (e) => {
842
+ let t = Object.keys(e.apps);
843
+ if (t.length === 0) throw Error("startTestApps: no apps given");
844
+ let n = e.mode ?? "dev", r = e.bootTimeoutMs ?? 3e5, i = e.cli ?? Ut(e.apps[t[0]].root), a = /* @__PURE__ */ new Map();
845
+ for (let e of t) a.set(e, await Vt());
846
+ let o = /* @__PURE__ */ new Map(), s = new Map(t.map((e) => [e, {}]));
847
+ for (let n of e.edges ?? []) {
848
+ 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(", ")})`);
849
+ let e = _e();
850
+ o.set(`${n.caller}\u0000${n.callee}`, e), Object.assign(s.get(n.caller), {
851
+ [re(n.binding)]: e,
852
+ [ie(n.binding)]: `ws://127.0.0.1:${a.get(n.callee)}/ws`
853
+ }), Object.assign(s.get(n.callee), { [we(n.caller)]: e });
854
+ }
855
+ let c = [], l = /* @__PURE__ */ new Set(), u = (t) => {
856
+ if (!c.includes(t)) {
857
+ if (l.has(t)) throw Error(`startTestApps: the edges form a cycle through '${t}' — no app can boot first`);
858
+ l.add(t);
859
+ for (let n of e.edges ?? []) n.caller === t && u(n.callee);
860
+ l.delete(t), c.push(t);
861
+ }
862
+ };
863
+ for (let e of t) u(e);
864
+ let d = [], f = /* @__PURE__ */ new Map(), p = async () => {
865
+ await Promise.all(d.map(Gt));
866
+ };
867
+ for (let t of c) {
868
+ let o = e.apps[t], c = a.get(t), l = "", u = Fe(process.execPath, [
869
+ i,
870
+ n,
871
+ ...n === "serve" ? ["."] : []
872
+ ], {
873
+ cwd: o.root,
874
+ env: {
875
+ ...process.env,
876
+ ...n === "serve" ? { VOLTRO_SESSION_SECRET: Ie(32).toString("base64url") } : {},
877
+ ...o.env,
878
+ ...s.get(t),
879
+ PORT: String(c)
880
+ },
881
+ stdio: [
882
+ "ignore",
883
+ "pipe",
884
+ "pipe"
885
+ ]
886
+ });
887
+ d.push(u), u.stdout?.on("data", (e) => {
888
+ l += e.toString();
889
+ }), u.stderr?.on("data", (e) => {
890
+ l += e.toString();
891
+ }), u.on("exit", (e, t) => {
892
+ l += `\n[exited] code=${String(e)} signal=${String(t)}`;
893
+ });
894
+ let m = {
895
+ name: t,
896
+ port: c,
897
+ url: `http://127.0.0.1:${c}`,
898
+ wsUrl: `ws://127.0.0.1:${c}/ws`,
899
+ log: () => l,
900
+ stop: () => Gt(u)
901
+ };
902
+ f.set(t, m);
903
+ let h = Date.now() + r;
904
+ for (; !await Ht(c);) {
905
+ if (u.exitCode !== null || u.signalCode !== null || Date.now() > h) {
906
+ await p();
907
+ let e = u.exitCode !== null || u.signalCode !== null ? "exited before it was ready" : `was not ready within ${r} ms`;
908
+ throw Error(`startTestApps: '${t}' ${e}\n${m.log().slice(-4e3)}`);
909
+ }
910
+ await new Promise((e) => setTimeout(e, 250));
911
+ }
912
+ }
913
+ return {
914
+ apps: Object.fromEntries(f),
915
+ token: (e, t) => {
916
+ let n = o.get(`${e}\u0000${t}`);
917
+ if (n === void 0) throw Error(`startTestApps: no edge ${e} → ${t}`);
918
+ return n;
919
+ },
920
+ stop: p
921
+ };
922
+ }, qt = 1;
761
923
  //#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 };
924
+ export { I as MockClock, z as MockLLM, L as MockWebhooks, qt as TESTING_PRESET_VERSION, wt as TEST_TENANT_ID, Ot as anonymous, Et as apiKey, n as changeDelete, r as changeInsert, i as changeSoftDelete, a as changeUpdate, Xe as defineFactory, xt as describeIfAvailable, St as describeIfReachable, A as fixtureRow, tt as frozenTime, Ke as hydrateFixtureRows, yt as invoke, bt as isTcpReachable, Bt as makeServiceApiMock, Lt as makeSubscribeContext, It as makeTestApp, _t as makeTestContext, zt as makeWorkflowRunner, J as markRestInvocation, rt as mockStore, Ve as nextSequence, ct as outboxNudgesOf, K as pluginsOf, Ct as reportEngineVersion, st as resetAfterCommit, Y as restInvocationOf, at as rpcInterceptorFor, Z as runAfterCommit, lt as runInStoreTransaction, Dt as serviceAccount, ot as serviceLayerFor, Kt as startTestApps, kt as system, R as testEventBus, Tt as user, et as withFrozenTime, it as withRpcConnection };