@voltro/cli 0.20.2 → 0.22.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.
Files changed (75) hide show
  1. package/CHANGELOG.md +398 -0
  2. package/THIRD-PARTY-NOTICES.md +61 -61
  3. package/dist/{apiBuild-qZBEu59d.js → apiBuild-2zRxj2hJ.js} +93 -80
  4. package/dist/apiBuild-sqNmWmY5.js +2 -0
  5. package/dist/bin.js +41 -20
  6. package/dist/{commands-kYbfVoPO.js → commands-DGaeTn2f.js} +3055 -2640
  7. package/dist/dbCommand-CO3eSAZR.js +2 -0
  8. package/dist/{dbCommand-BPp9R0Wc.js → dbCommand-DVASmZj2.js} +305 -249
  9. package/dist/dev-BEYBSGJ7.js +3 -0
  10. package/dist/{dev-OHLsAq4K.js → dev-DeHVUxQx.js} +1732 -1686
  11. package/dist/index.js +1 -1
  12. package/dist/inspect-BA67TF6v.js +2 -0
  13. package/dist/inspect-_ldwsAwH.js +945 -0
  14. package/dist/{inspectMetrics-DvPNXmGA.js → inspectMetrics-4AVPn6IS.js} +584 -571
  15. package/dist/{manifestBuild-P9yuCY2d.js → manifestBuild-Bs1Uw22_.js} +1 -1
  16. package/dist/manifestBuild-i-fRHg_H.js +2 -0
  17. package/dist/serveCommand-DEVTtnLy.js +1161 -0
  18. package/dist/serveEntry.js +2 -2
  19. package/dist/{start-CXQ7WL1W.js → start-BjGUIIvj.js} +389 -389
  20. package/dist/startEntry.js +2 -2
  21. package/package.json +27 -27
  22. package/templates/AGENTS.md +1 -1
  23. package/templates/agent-docs/_index.md +1 -1
  24. package/templates/agent-docs/cli.md +181 -5
  25. package/templates/agent-docs/data.md +58 -0
  26. package/templates/agent-docs/database/migrations.md +175 -31
  27. package/templates/agent-docs/database/schema.md +7 -0
  28. package/templates/agent-docs/database/seedsdialects.md +3 -3
  29. package/templates/agent-docs/plugins.md +1 -1
  30. package/templates/agent-docs/schema-driven-ui.md +2 -2
  31. package/templates/agent-docs/templates/apibackends.md +1 -1
  32. package/templates/agent-docs/whats-new.md +236 -9
  33. package/templates/apps/api-ai/package.json +12 -12
  34. package/templates/apps/api-auth/package.json +13 -13
  35. package/templates/apps/api-backend/package.json +12 -12
  36. package/templates/apps/api-backend-deactivation/package.json +12 -12
  37. package/templates/apps/api-backend-mail/package.json +11 -11
  38. package/templates/apps/api-backend-mariadb/package.json +14 -14
  39. package/templates/apps/api-backend-storage/package.json +11 -11
  40. package/templates/apps/api-data-advanced/package.json +13 -13
  41. package/templates/apps/api-durable/package.json +13 -13
  42. package/templates/apps/api-feature-flags/package.json +14 -14
  43. package/templates/apps/api-governance/package.json +13 -13
  44. package/templates/apps/api-kv/package.json +13 -13
  45. package/templates/apps/api-moderation/package.json +13 -13
  46. package/templates/apps/api-observability/package.json +13 -13
  47. package/templates/apps/api-ratelimit/package.json +13 -13
  48. package/templates/apps/api-rbac/package.json +13 -13
  49. package/templates/apps/api-rest/package.json +12 -12
  50. package/templates/apps/api-saas/package.json +16 -16
  51. package/templates/apps/api-search/package.json +13 -13
  52. package/templates/apps/api-versioning/package.json +13 -13
  53. package/templates/apps/api-webhooks/package.json +14 -14
  54. package/templates/apps/changelog/package.json +8 -8
  55. package/templates/apps/edge-functions/package.json +5 -5
  56. package/templates/apps/frontend-admin/package.json +10 -10
  57. package/templates/apps/frontend-app/package.json +10 -10
  58. package/templates/apps/frontend-blank/package.json +9 -9
  59. package/templates/apps/frontend-contact/package.json +11 -11
  60. package/templates/apps/frontend-dashboard/package.json +9 -9
  61. package/templates/apps/frontend-docs/package.json +9 -9
  62. package/templates/apps/frontend-i18n/package.json +8 -8
  63. package/templates/apps/frontend-landing/package.json +9 -9
  64. package/templates/apps/frontend-spa/package.json +9 -9
  65. package/templates/apps/frontend-ssr/package.json +9 -9
  66. package/templates/apps/frontend-ssr-api/package.json +10 -10
  67. package/templates/apps/frontend-static-blog/package.json +8 -8
  68. package/dist/apiBuild-C9aHz4Yh.js +0 -2
  69. package/dist/dbCommand-DtUe-0dM.js +0 -2
  70. package/dist/dev-2AvdzDg2.js +0 -3
  71. package/dist/inspect-DcZ04OME.js +0 -2
  72. package/dist/inspect-Dwx0_tUj.js +0 -921
  73. package/dist/manifestBuild-D1MzJAiQ.js +0 -2
  74. package/dist/serveCommand-BKqTKWTX.js +0 -1136
  75. /package/templates/patches/{@effect__cluster@0.59.0.patch → @effect__cluster@0.60.0.patch} +0 -0
@@ -0,0 +1,1161 @@
1
+ import { at as e, t } from "./inspectMetrics-4AVPn6IS.js";
2
+ import { s as n } from "./seedRunner-D6eu-u5U.js";
3
+ import { r, t as i } from "./appModuleLoader-C9r9mxZt.js";
4
+ import { f as a, m as o, n as s, p as c, u as l } from "./frameworkTableAssembly-sg41s14F.js";
5
+ import { l as u } from "./fileConventions-CBNPZVOV.js";
6
+ import { p as d } from "./inspect-_ldwsAwH.js";
7
+ import { $ as ee, A as f, B as p, C as te, D as m, E as ne, F as re, G as ie, H as ae, I as h, K as oe, L as g, M as _, N as se, O as v, P as y, R as ce, S as le, T as ue, V as de, W as fe, _ as b, at as pe, b as me, c as he, et as ge, h as x, i as _e, it as S, j as ve, k as ye, lt as C, m as be, nt as w, o as T, ot as xe, q as E, r as Se, rt as Ce, st as we, t as Te, tt as Ee, u as De, ut as Oe, v as ke, w as Ae, x as D, y as je, z as Me } from "./dev-DeHVUxQx.js";
8
+ import { l as O, r as k } from "./apiBuild-2zRxj2hJ.js";
9
+ import { t as Ne } from "./bootTiming-BdyP9nYw.js";
10
+ import { n as Pe } from "./cliArgs-qdZSElM3.js";
11
+ import { join as Fe } from "node:path";
12
+ import { pathToFileURL as Ie } from "node:url";
13
+ import { Cause as Le, Effect as A, Layer as j, ManagedRuntime as Re } from "effect";
14
+ import { createLogger as M } from "@voltro/logger";
15
+ import { existsSync as ze } from "node:fs";
16
+ import { AggregateRegistry as N, Dispatcher as Be, apiKeyManagementRoutes as Ve, applySoftDeleteScope as He, applyTenantScope as Ue, attachAnalyticsMirror as P, awaitServerListening as We, bindMutation as F, bindStream as Ge, bindSubscription as I, buildTracingLayer as Ke, cancelWakeup as qe, compileCron as Je, dataStoreApiKeyStore as Ye, dataStoreIdempotencyStore as Xe, formatServerOnlyLeaks as Ze, frameworkApiKeyStrategy as Qe, installPolicyGuardResolver as $e, loadResourceTuples as et, makeActionRunner as L, makeAdvisoryLockCoordinator as tt, makeApiKeyService as nt, makeApiKeyUsageBuffer as rt, makeApiKeyUsageFlusher as it, makeAsyncKv as at, makeCoordinatedScheduler as ot, makeEffectStoreLayer as st, makeLazyWorkflowFacade as ct, makeMutationRunner as lt, makeOneShotQueryRunner as ut, makeQueryDescriptorProducer as dt, makeQueryReauthorizer as ft, makeQuerySubscriber as pt, makeSchemaRegistry as mt, makeWorkflowFacade as ht, makeWorkflowFacadeWithCallerContext as gt, makeWorkflowLayers as _t, noopKv as R, onProcessShutdown as vt, recordSubscriptionDelivery as yt, registerWakeup as bt, resolveSecretsBackend as xt, runProvidedEffect as St, setSecretsBackend as Ct, setSystemStoreHandle as z, setTupleSource as wt, singleCoordinator as Tt, startRpcServer as Et, startScheduler as Dt, workflowToRpc as B, wrapStoreWithBootCodec as Ot } from "@voltro/runtime";
17
+ import { RpcGroup as kt } from "@effect/rpc";
18
+ import { SqlClient as At } from "@effect/sql";
19
+ import { and as jt, ensureTableRegistered as Mt, eq as V, or as Nt } from "@voltro/database";
20
+ import { appStorageProvider as H, fromNodeReadable as Pt, getObjectStream as Ft, putObjectStream as It, toNodeReadable as U } from "@voltro/plugin-storage";
21
+ import { AuthMiddleware as W, ConnectionInfoMiddleware as G, actionToRpc as K, anonymousSubject as Lt, isWireReachable as Rt, mutationToRpc as zt, queryToRpc as q, streamToRpc as Bt, workflowCancelDescriptor as Vt, workflowDomainEventsQueryDescriptor as J, workflowEventDeliveriesQueryDescriptor as Ht, workflowResumeDescriptor as Ut, workflowRunEventsQueryDescriptor as Y, workflowRunQueryDescriptor as X, workflowRunStepsQueryDescriptor as Wt, workflowRunsQueryDescriptor as Z, workflowSignalDescriptor as Gt, workflowUpdateDescriptor as Kt } from "@voltro/protocol";
22
+ import { assertProductionSessionSecret as qt } from "@voltro/protocol/session";
23
+ import { createHash as Jt, timingSafeEqual as Yt } from "node:crypto";
24
+ import { declaredSnapshot as Xt, describeOutcome as Zt, runPlannedMigrations as Qt } from "@voltro/database/sql";
25
+ import { getAuthSessionStrategy as $t } from "@voltro/plugin-auth";
26
+ import { collectPublicApiRoutes as en, restRoutesToHttpRoutes as tn } from "@voltro/protocol/rest";
27
+ import { buildDeliverWebhookExecute as nn, buildWebhooksService as rn, defaultIncomingPath as an, deliverWebhookWorkflow as on, mountIncomingWebhook as sn } from "@voltro/plugin-webhooks";
28
+ import { packBundle as cn, runExport as ln, runImport as un, storageBlobSink as dn, storageRefsBlobSource as fn, unpackBundle as pn, unpackBundleToDir as mn } from "@voltro/data-transfer";
29
+ //#region src/bootRefusal.ts
30
+ var hn = "VoltroBootRefusal", gn = (e) => {
31
+ let t = Error(e);
32
+ return t.name = hn, t;
33
+ }, _n = "/_voltro/admin/import", vn = "/_voltro/admin/export", Q = (e, t) => ({
34
+ status: e,
35
+ contentType: "application/json; charset=utf-8",
36
+ body: JSON.stringify(t)
37
+ }), yn = (e) => {
38
+ let t = e.authorization ?? e.Authorization, n = t ? /^Bearer\s+(.+)$/i.exec(t) : null;
39
+ return n ? n[1] : null;
40
+ }, bn = (e, t) => Yt(Jt("sha256").update(e).digest(), Jt("sha256").update(t).digest()), xn = (e, t) => {
41
+ if (e.method.toUpperCase() !== "POST") return Q(405, { error: "method not allowed" });
42
+ if (!t || t.length < 16) return Q(503, { error: "data transfer misconfigured (no/weak secret)" });
43
+ let n = yn(e.headers);
44
+ return !n || !bn(n, t) ? Q(401, { error: "unauthorized" }) : null;
45
+ }, Sn = M({ scope: "voltro:admin-import" }), Cn = "VBUNDLE2", wn = async function* (e) {
46
+ yield e;
47
+ }, Tn = (e) => async (t) => {
48
+ let n = xn(t, e.secret);
49
+ if (n) return n;
50
+ let r = t.headers["x-import-mode"], i = t.headers["x-import-on-conflict"], a = t.headers["x-import-atomic"] === "1" || t.headers["x-import-atomic"] === "true", o = t.headers["x-import-force"] === "1" || t.headers["x-import-force"] === "true", s = t.rawBody.byteLength >= 8 && Buffer.from(t.rawBody.subarray(0, 8)).toString("latin1") === Cn, c, l;
51
+ if (s) c = wn(t.rawBody), l = "upload";
52
+ else {
53
+ let n;
54
+ try {
55
+ n = JSON.parse(Buffer.from(t.rawBody).toString("utf8") || "{}");
56
+ } catch {
57
+ return Q(400, { error: "body must be a packed bundle archive or { bundleKey } JSON" });
58
+ }
59
+ if (typeof n.bundleKey != "string" || !n.bundleKey) return Q(400, { error: "body.bundleKey (string) is required for the storage transport" });
60
+ if (!e.openArchive) return Q(501, { error: "storage transport not configured on this instance" });
61
+ c = e.openArchive(n.bundleKey), l = "storage";
62
+ }
63
+ let u = await import("node:os"), d = await import("node:fs/promises"), ee = await import("node:path"), f = await d.mkdtemp(ee.join(u.tmpdir(), "voltro-admin-import-"));
64
+ try {
65
+ e.assetSink ? await pn(c, {
66
+ dir: f,
67
+ blobs: e.assetSink
68
+ }) : await mn(c, f);
69
+ let t = await A.runPromiseExit(un({
70
+ store: e.store,
71
+ bundleDir: f,
72
+ ...r ? { mode: r } : {},
73
+ ...i ? { onConflict: i } : {},
74
+ ...a ? { atomic: a } : {},
75
+ ...e.snapshot ? { targetSnapshot: e.snapshot } : {},
76
+ force: o,
77
+ onWarn: (e) => Sn.warn("admin.import", { message: e }),
78
+ ...e.assetSink ? { assetsAlreadyRestored: !0 } : {}
79
+ }));
80
+ if (t._tag === "Failure") {
81
+ let e = t.cause._tag === "Fail" ? t.cause.error : void 0;
82
+ if (e && e._tag === "SchemaDriftError") {
83
+ let t = e;
84
+ return Sn.warn("admin.import refused (schema drift)", {
85
+ transport: l,
86
+ bundle: t.bundleFingerprint.slice(0, 16),
87
+ target: t.targetFingerprint.slice(0, 16)
88
+ }), Q(409, {
89
+ error: "schema drift",
90
+ bundleFingerprint: t.bundleFingerprint,
91
+ targetFingerprint: t.targetFingerprint,
92
+ diff: t.diff,
93
+ hint: "re-export against the current schema, or resend with x-import-force: 1"
94
+ });
95
+ }
96
+ throw Error(String(e?.message ?? e ?? "import failed"));
97
+ }
98
+ let n = t.value, s = n.tables.reduce((e, t) => e + t.rowCount, 0);
99
+ return Sn.info("admin.import", {
100
+ transport: l,
101
+ tables: n.tables.length,
102
+ rows: s,
103
+ mode: r ?? "upsert",
104
+ atomic: a
105
+ }), Q(200, {
106
+ tables: n.tables.length,
107
+ rows: s,
108
+ transport: l
109
+ });
110
+ } catch (e) {
111
+ return Sn.warn("admin.import failed", {
112
+ transport: l,
113
+ error: e?.message ?? String(e)
114
+ }), Q(500, {
115
+ error: "import failed",
116
+ message: e?.message ?? String(e)
117
+ });
118
+ } finally {
119
+ await d.rm(f, {
120
+ recursive: !0,
121
+ force: !0
122
+ });
123
+ }
124
+ }, En = M({ scope: "voltro:admin-export" }), Dn = async (e) => {
125
+ let t = [];
126
+ for await (let n of e) t.push(Buffer.from(n));
127
+ return new Uint8Array(Buffer.concat(t));
128
+ }, On = (e) => typeof e.tenant == "string" && e.tenant ? {
129
+ kind: "tenant",
130
+ tenantId: e.tenant
131
+ } : Array.isArray(e.tables) && e.tables.length ? {
132
+ kind: "tables",
133
+ tables: e.tables.filter((e) => typeof e == "string")
134
+ } : { kind: "all" }, kn = (e) => async (t) => {
135
+ let n = xn(t, e.secret);
136
+ if (n) return n;
137
+ let r;
138
+ try {
139
+ r = JSON.parse(Buffer.from(t.rawBody).toString("utf8") || "{}");
140
+ } catch {
141
+ return Q(400, { error: "body must be JSON: { profile?, tenant?, tables?, consistency?, compression?, bundleKey? }" });
142
+ }
143
+ let i = {};
144
+ if (typeof r.profile == "string" && r.profile) {
145
+ if (!e.loadProfile) return Q(501, { error: "server-side profiles not configured on this instance" });
146
+ try {
147
+ i = await e.loadProfile(r.profile);
148
+ } catch (e) {
149
+ return Q(400, {
150
+ error: `profile '${r.profile}' could not be loaded`,
151
+ message: e?.message ?? String(e)
152
+ });
153
+ }
154
+ }
155
+ let a = r.consistency === "snapshot" ? "snapshot" : i.consistency ?? "live", o = (typeof r.compression == "string" ? r.compression : void 0) ?? i.compression, s = i.scope ?? On(r), c = typeof r.bundleKey == "string" && r.bundleKey.length > 0, l = r.assets === !0 && e.assetSource ? { blobs: e.assetSource } : {}, u = await import("node:os"), d = await import("node:fs/promises"), ee = await import("node:path"), f = await d.mkdtemp(ee.join(u.tmpdir(), "voltro-admin-export-"));
156
+ try {
157
+ let t = await A.runPromise(ln({
158
+ store: e.store,
159
+ snapshot: e.snapshot,
160
+ dialect: e.dialect,
161
+ outDir: f,
162
+ ...i.subset ? { subset: i.subset } : {
163
+ scope: s,
164
+ ...e.tenantTables && e.tenantTables.length > 0 ? { tenantTables: e.tenantTables } : {}
165
+ },
166
+ consistency: a,
167
+ ...o ? { compression: o } : {},
168
+ ...i.masking ? { masking: i.masking } : {}
169
+ })), n = t.tables.reduce((e, t) => e + t.rowCount, 0), u = t.masking?.transformed.length ?? 0;
170
+ if (c) {
171
+ if (!e.putArchive) return Q(501, { error: "storage transport not configured on this instance" });
172
+ let i = r.bundleKey;
173
+ return await e.putArchive(i, () => cn({
174
+ dir: f,
175
+ ...l
176
+ })), En.info("admin.export", {
177
+ transport: "storage",
178
+ tables: t.tables.length,
179
+ rows: n,
180
+ masked: u,
181
+ bundleKey: i
182
+ }), Q(200, {
183
+ bundleKey: i,
184
+ tables: t.tables.length,
185
+ rows: n,
186
+ masked: u,
187
+ transport: "storage"
188
+ });
189
+ }
190
+ let d = await Dn(cn({
191
+ dir: f,
192
+ ...l
193
+ }));
194
+ return En.info("admin.export", {
195
+ transport: "download",
196
+ tables: t.tables.length,
197
+ rows: n,
198
+ masked: u,
199
+ bytes: d.byteLength
200
+ }), {
201
+ status: 200,
202
+ contentType: "application/octet-stream",
203
+ body: d,
204
+ headers: {
205
+ "x-export-tables": String(t.tables.length),
206
+ "x-export-rows": String(n),
207
+ "x-export-masked": String(u)
208
+ }
209
+ };
210
+ } catch (e) {
211
+ return En.warn("admin.export failed", { error: e?.message ?? String(e) }), Q(500, {
212
+ error: "export failed",
213
+ message: e?.message ?? String(e)
214
+ });
215
+ } finally {
216
+ await d.rm(f, {
217
+ recursive: !0,
218
+ force: !0
219
+ });
220
+ }
221
+ }, An = async (e) => {
222
+ let { resolve: t } = await import("node:path"), { existsSync: n } = await import("node:fs"), r = [
223
+ e,
224
+ `${e}.profile.ts`,
225
+ `data-profiles/${e}.ts`,
226
+ `data-profiles/${e}.profile.ts`
227
+ ].map((e) => t(process.cwd(), e)), i = r.find((e) => n(e));
228
+ if (!i) throw Error(`data profile '${e}' not found (looked for: ${r.join(", ")})`);
229
+ let a = await import(i), o = a.default ?? a.profile;
230
+ if (!o) throw Error(`data profile '${i}' has no default export`);
231
+ return o;
232
+ }, jn = (e, t, n = {}) => (async function* () {
233
+ let r = await U((await A.runPromise(Ft(e, t).pipe(A.timeout(n.openTimeout ?? "30 seconds")))).stream), i = n.stallMs ?? 12e4, a, o = () => {
234
+ a && clearTimeout(a), a = setTimeout(() => r.destroy(/* @__PURE__ */ Error(`storage read stalled for ${i}ms reading '${t}'`)), i);
235
+ };
236
+ try {
237
+ o();
238
+ for await (let e of r) o(), yield e instanceof Uint8Array ? e : new Uint8Array(e);
239
+ } finally {
240
+ a && clearTimeout(a), r.destroy();
241
+ }
242
+ })(), Mn = {
243
+ get: async () => void 0,
244
+ set: async () => {},
245
+ setWithTags: async () => {},
246
+ remove: async () => !1,
247
+ has: async () => !1,
248
+ clear: async () => {},
249
+ invalidateTag: async () => 0,
250
+ wrap: async (e, t, n) => n()
251
+ }, Nn = async (e) => {
252
+ z({
253
+ dataStore: e.store,
254
+ schemaRegistry: e.schemaRegistry
255
+ });
256
+ let t = new Be({
257
+ store: e.store,
258
+ ...e.snapshotCache ? { cache: e.snapshotCache } : {},
259
+ recordDelivery: (e) => yt({
260
+ label: e.label,
261
+ kind: e.kind,
262
+ durationMs: e.durationMs,
263
+ rowCount: e.rowCount
264
+ })
265
+ }), n = e.cache ?? Mn, r = e.kv ?? R, i, a, o, s = /* @__PURE__ */ new Map(), c = () => `wfctx_${globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`}`, l = async (t, n, r) => {
266
+ let i = {
267
+ ...r,
268
+ source: r.source ?? `workflow:${t}`
269
+ };
270
+ s.set(n, i);
271
+ try {
272
+ let r = await e.store.query({
273
+ table: "_voltro_workflow_start_contexts",
274
+ order: [],
275
+ predicate: V("executionId", n),
276
+ projection: ["id"],
277
+ skip: void 0,
278
+ take: 1
279
+ }), a = {
280
+ workflowName: t,
281
+ executionId: n,
282
+ subject: i.subject ?? null,
283
+ traceId: i.traceId ?? null,
284
+ source: i.source ?? null,
285
+ parentExecutionId: i.parentExecutionId ?? null,
286
+ parentClosePolicy: i.parentClosePolicy ?? null,
287
+ createdAt: /* @__PURE__ */ new Date()
288
+ };
289
+ r[0] === void 0 ? await e.store.insert("_voltro_workflow_start_contexts", {
290
+ id: c(),
291
+ ...a
292
+ }) : await e.store.update("_voltro_workflow_start_contexts", r[0].id, a);
293
+ } catch (e) {
294
+ process.stderr.write(`[workflow] failed to persist start context for ${t}/${n}: ${e?.message ?? String(e)}\n`);
295
+ }
296
+ }, u = async (t, n) => {
297
+ let r = s.get(n);
298
+ if (r !== void 0) return r;
299
+ try {
300
+ let t = (await e.store.query({
301
+ table: "_voltro_workflow_start_contexts",
302
+ order: [],
303
+ predicate: V("executionId", n),
304
+ projection: void 0,
305
+ skip: void 0,
306
+ take: 1
307
+ }))[0];
308
+ if (t === void 0) return;
309
+ let r = {
310
+ ...t.subject === null ? {} : { subject: t.subject },
311
+ ...t.traceId === null ? {} : { traceId: t.traceId },
312
+ ...t.source === null ? {} : { source: t.source },
313
+ ...t.parentExecutionId === null ? {} : { parentExecutionId: t.parentExecutionId },
314
+ ...t.parentClosePolicy === null ? {} : { parentClosePolicy: t.parentClosePolicy }
315
+ };
316
+ return s.set(n, r), r;
317
+ } catch (e) {
318
+ process.stderr.write(`[workflow] failed to load start context for ${n}: ${e?.message ?? String(e)}\n`);
319
+ return;
320
+ }
321
+ }, d = (e.discovered.workflows?.length ?? 0) > 0 ? ct(() => i) : void 0, f = (e.discovered.workflows?.length ?? 0) > 0 || (e.discovered.eventTriggers?.length ?? 0) > 0, te = f || (e.discovered.workflowWorkers?.length ?? 0) > 0 || e.scheduleCoordination === "cluster", re = e.tenantIsolation === "namespace", ie = (e.log ?? M({ scope: "voltro:serve" })).child("webhooks"), ae, h = e.discovered.webhooks;
322
+ if (h && h.outgoing.length > 0 && e.workflowEngineLayer !== void 0) {
323
+ let t = e.workflowEngineLayer, i = S({
324
+ store: e.store,
325
+ schemaRegistry: e.schemaRegistry,
326
+ cache: n,
327
+ kv: r
328
+ }), a = h.outgoing.map((e) => e.descriptor);
329
+ ae = rn(i, async (e) => {
330
+ let n = on.execute(e).pipe(A.provide(on.toLayer(nn(i, { events: a })).pipe(j.provideMerge(t))));
331
+ A.runPromise(n).catch((t) => {
332
+ ie.error("deliverWebhook workflow crashed", {
333
+ deliveryId: e.deliveryId,
334
+ targetId: e.targetId
335
+ }, t);
336
+ });
337
+ }, { events: a });
338
+ }
339
+ let oe = /* @__PURE__ */ new Map();
340
+ if (h) for (let e of h.incoming) {
341
+ let t = e.descriptor.path ?? an(e.descriptor.id), n = `VOLTRO_WEBHOOK_SECRET_${e.descriptor.id.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`, r = sn(e.descriptor, {
342
+ resolveSecret: async () => process.env[n] ?? null,
343
+ resolveWorkflows: () => d === void 0 ? void 0 : gt(d, {
344
+ traceId: `incoming:${e.descriptor.id}`,
345
+ source: `incoming:${e.descriptor.id}`
346
+ }),
347
+ log: (e) => {
348
+ let t = {
349
+ webhookId: e.webhookId,
350
+ status: e.status,
351
+ signatureOk: String(e.signatureOk),
352
+ idempotency: e.idempotency,
353
+ durationMs: e.durationMs
354
+ };
355
+ e.status >= 500 ? ie.error("incoming delivery failed", t) : e.status >= 400 ? ie.warn("incoming delivery rejected", t) : ie.info("incoming delivery handled", t);
356
+ }
357
+ });
358
+ oe.set(t, { handle: r });
359
+ }
360
+ $e(), wt((t) => et(e.store, t.subjectId, t.resourceType, t.resourceId));
361
+ let se = (e.discovered.outboxHandlers?.length ?? 0) > 0 ? p({
362
+ handlers: e.discovered.outboxHandlers ?? [],
363
+ store: e.store,
364
+ log: (e.log ?? M({ scope: "voltro:serve" })).child("outbox")
365
+ }) : void 0, v = ce({
366
+ definitions: (e.discovered.connections ?? []).map((e) => e.definition),
367
+ store: e.store,
368
+ publicUrl: g(e.port ?? 4e3),
369
+ log: (e.log ?? M({ scope: "voltro:serve" })).child("connections")
370
+ }), y = Ce({
371
+ store: e.store,
372
+ schemaRegistry: e.schemaRegistry,
373
+ cache: n,
374
+ kv: r,
375
+ ...ae === void 0 ? {} : { webhooksService: ae },
376
+ ...d === void 0 ? {} : { workflowsProxy: d },
377
+ eventTriggers: e.discovered.eventTriggers ?? [],
378
+ namespaceIsolationOn: re,
379
+ ...se === void 0 ? {} : { outbox: { nudge: se.nudge } },
380
+ ...v.active ? { connections: { registry: v.registry } } : {}
381
+ }), ue = j.succeed(N, m), fe = (t, n) => {
382
+ let r = t.pipe(A.provide(st(n)));
383
+ return St((e.baseLayer ? r.pipe(A.provide(e.baseLayer)) : r).pipe(A.provide(ue)));
384
+ }, pe = lt({
385
+ store: e.store,
386
+ buildContext: (e, t, n) => y(e, t, n),
387
+ runEffect: fe,
388
+ undoCapture: le()
389
+ }), me = D(), he = L({
390
+ buildContext: (e) => y(e),
391
+ runEffect: fe
392
+ }), ge = {
393
+ buildContext: (e) => y(e),
394
+ finalize: (t, n) => He(Ue(t, e.tenantScopedTables, n.subject.tenantId), e.softDeleteScopedTables),
395
+ provideEffect: (e, t) => e.pipe(A.provide(st(t)))
396
+ }, x = dt(ge), _e = ut({
397
+ ...ge,
398
+ queryRows: (t) => e.store.query(t)
399
+ }), ye = pt({
400
+ ...ge,
401
+ subscribeDescriptor: (e, n, r) => t.subscribe(e, n, r),
402
+ subscribeComputed: (e, n, r) => t.subscribeComputed(e, n, r)
403
+ }), C = {};
404
+ for (let n of [
405
+ ...e.discovered.queries,
406
+ ...me.queries,
407
+ ...v.queries
408
+ ]) C[n.descriptor.name] = (e) => I(x(n, e), t, `subscription.${n.descriptor.name}`, void 0, void 0, ft(n, e));
409
+ for (let t of [
410
+ ...e.discovered.mutations,
411
+ ...me.mutations,
412
+ ...v.mutations
413
+ ]) C[t.descriptor.name] = (e) => F(async (e, n) => pe(t, e, n), e, `mutation.${t.descriptor.name}`);
414
+ for (let t of [...e.discovered.actions, ...v.actions]) C[t.descriptor.name] = (e) => F(async (e, n) => he(t, e, n), e, `action.${t.descriptor.name}`);
415
+ let be = () => `public-${Math.random().toString(36).slice(2, 10)}`, T = [
416
+ ...e.discovered.queries.filter((e) => e.descriptor.publicApi !== void 0).map((e) => ({
417
+ descriptor: e.descriptor,
418
+ invoke: (t, n) => _e(e, t, {
419
+ subject: n.subject,
420
+ traceId: be()
421
+ }),
422
+ subscribe: (t, n, r) => ye(e, t, {
423
+ subject: n.subject,
424
+ traceId: be()
425
+ }, r)
426
+ })),
427
+ ...e.discovered.mutations.filter((e) => e.descriptor.publicApi !== void 0).map((e) => ({
428
+ descriptor: e.descriptor,
429
+ invoke: (t, n) => pe(e, t, {
430
+ subject: n.subject,
431
+ traceId: be()
432
+ })
433
+ })),
434
+ ...e.discovered.actions.filter((e) => e.descriptor.publicApi !== void 0).map((e) => ({
435
+ descriptor: e.descriptor,
436
+ invoke: (t, n) => he(e, t, {
437
+ subject: n.subject,
438
+ traceId: be()
439
+ })
440
+ }))
441
+ ], xe = T.length > 0 ? tn(en(T), {
442
+ store: e.store,
443
+ resolveSubject: (t) => e.resolveSubject(t, -1)
444
+ }) : [], E = e.dataTransferSecret ?? process.env.VOLTRO_DATA_TRANSFER_SECRET, Se = E && E.length >= 16 ? [{
445
+ method: "POST",
446
+ path: _n,
447
+ handle: Tn({
448
+ secret: E,
449
+ store: e.store,
450
+ ...e.dataTransferSnapshot ? { snapshot: e.dataTransferSnapshot } : {},
451
+ assetSink: dn(H()),
452
+ openArchive: (e) => jn(H(), e)
453
+ })
454
+ }, {
455
+ method: "POST",
456
+ path: vn,
457
+ handle: kn({
458
+ secret: E,
459
+ store: e.store,
460
+ snapshot: e.dataTransferSnapshot ?? { tables: [] },
461
+ dialect: e.dataTransferDialect ?? "memory",
462
+ tenantTables: [...e.tenantScopedTables],
463
+ loadProfile: An,
464
+ assetSource: fn(H(), e.store),
465
+ putArchive: async (e, t) => {
466
+ let { Readable: n } = await import("node:stream"), r = H(), i = Pt("storage", () => n.from(t()));
467
+ await A.runPromise(It(r, e, i, { contentType: "application/octet-stream" }));
468
+ }
469
+ })
470
+ }] : [], we = [
471
+ ...e.httpRoutes ?? [],
472
+ ...xe,
473
+ ...Se,
474
+ ...v.httpRoutes
475
+ ];
476
+ for (let t of e.discovered.streams ?? []) C[t.descriptor.name] = (n) => Ge((r) => {
477
+ let i = y(r), a = t.executor(n, i);
478
+ if (A.isEffect(a)) {
479
+ let t = a.pipe(A.provide(st(i.store)));
480
+ return (e.baseLayer ? t.pipe(A.provide(e.baseLayer)) : t).pipe(A.provide(ue));
481
+ }
482
+ return typeof a == "object" && a && typeof a.then == "function" ? A.promise(() => a) : a;
483
+ }, `stream.${t.descriptor.name}`);
484
+ for (let t of e.discovered.workflows ?? []) C[t.definition.name] = (e) => F(async (e, n) => {
485
+ let r = n;
486
+ return gt(d, {
487
+ subject: r.subject,
488
+ traceId: r.traceId,
489
+ source: "workflow-rpc"
490
+ }).start(t.definition.name, e);
491
+ }, e, `workflow.${t.definition.name}`);
492
+ f && (C[X.name] = (e) => I(x({
493
+ descriptor: X,
494
+ executor: (e) => {
495
+ let t = e.id;
496
+ return {
497
+ table: "_voltro_workflow_runs",
498
+ order: [{
499
+ column: "startedAt",
500
+ direction: "desc"
501
+ }],
502
+ predicate: Nt(V("id", t), V("executionId", t)),
503
+ take: 1,
504
+ skip: void 0,
505
+ projection: void 0
506
+ };
507
+ }
508
+ }, e), t, `subscription.${X.name}`), C[Z.name] = (e) => I(x({
509
+ descriptor: Z,
510
+ executor: (e) => {
511
+ let t = e, n = [...t.tag === void 0 ? [] : [V("tag", t.tag)], ...t.status === void 0 ? [] : [V("status", t.status)]], r = Number.isFinite(t.limit) && t.limit !== void 0 ? Math.min(Math.max(Math.floor(t.limit), 1), 500) : 100;
512
+ return {
513
+ table: "_voltro_workflow_runs",
514
+ order: [{
515
+ column: "startedAt",
516
+ direction: "desc"
517
+ }],
518
+ predicate: n.length === 0 ? void 0 : n.length === 1 ? n[0] : jt(...n),
519
+ take: r,
520
+ skip: void 0,
521
+ projection: void 0
522
+ };
523
+ }
524
+ }, e), t, `subscription.${Z.name}`), C[Wt.name] = (e) => I(x({
525
+ descriptor: Wt,
526
+ executor: (e) => {
527
+ let t = e.runId;
528
+ return {
529
+ table: "_voltro_workflow_run_steps",
530
+ order: [{
531
+ column: "startedAt",
532
+ direction: "asc"
533
+ }],
534
+ predicate: V("runId", t),
535
+ take: 1e3,
536
+ skip: void 0,
537
+ projection: void 0
538
+ };
539
+ }
540
+ }, e), t, `subscription.${Wt.name}`), C[Y.name] = (e) => I(x({
541
+ descriptor: Y,
542
+ executor: (e) => {
543
+ let t = e.runId;
544
+ return {
545
+ table: "_voltro_workflow_run_events",
546
+ order: [{
547
+ column: "occurredAt",
548
+ direction: "asc"
549
+ }],
550
+ predicate: V("runId", t),
551
+ take: 1e3,
552
+ skip: void 0,
553
+ projection: void 0
554
+ };
555
+ }
556
+ }, e), t, `subscription.${Y.name}`), C[J.name] = (e) => I(x({
557
+ descriptor: J,
558
+ executor: (e) => {
559
+ let t = e;
560
+ return {
561
+ table: "_voltro_workflow_events",
562
+ order: [{
563
+ column: "occurredAt",
564
+ direction: "desc"
565
+ }],
566
+ predicate: t.name === void 0 ? void 0 : V("name", t.name),
567
+ take: Math.max(1, Math.min(500, t.limit ?? 100)),
568
+ skip: void 0,
569
+ projection: void 0
570
+ };
571
+ }
572
+ }, e), t, `subscription.${J.name}`), C[Ht.name] = (e) => I(x({
573
+ descriptor: Ht,
574
+ executor: (e) => {
575
+ let t = e.eventId;
576
+ return {
577
+ table: "_voltro_workflow_event_deliveries",
578
+ order: [{
579
+ column: "createdAt",
580
+ direction: "asc"
581
+ }],
582
+ predicate: V("eventId", t),
583
+ take: 500,
584
+ skip: void 0,
585
+ projection: void 0
586
+ };
587
+ }
588
+ }, e), t, `subscription.${Ht.name}`), C[Vt.name] = (t) => F(async (t, n) => {
589
+ let r = t;
590
+ return await w(e.store, n.subject, { executionId: r.executionId }), await d.cancel(r.workflowName, r.executionId), await Pe(r.workflowName, r.executionId, "workflow.cancel"), { ok: !0 };
591
+ }, t, `action.${Vt.name}`), C[Ut.name] = (t) => F(async (t, n) => {
592
+ let r = t;
593
+ return await w(e.store, n.subject, { executionId: r.executionId }), await d.resume(r.workflowName, r.executionId), { ok: !0 };
594
+ }, t, `action.${Ut.name}`), C[Gt.name] = (t) => F(async (t, n) => {
595
+ let r = t;
596
+ return await w(e.store, n.subject, { id: r.id }), d.signal({ id: r.id }, r.signalName, r.payload);
597
+ }, t, `action.${Gt.name}`), C[Kt.name] = (t) => F(async (t, n) => {
598
+ let r = t;
599
+ return await w(e.store, n.subject, { id: r.id }), d.update({ id: r.id }, r.updateName, r.payload, r.timeoutMs === void 0 ? void 0 : { timeoutMs: r.timeoutMs });
600
+ }, t, `action.${Kt.name}`));
601
+ let Te = (e) => e.filter((e) => Rt(e.descriptor)), Ee = [
602
+ ...Te(e.discovered.queries).map((e) => q(e.descriptor)),
603
+ ...Te(e.discovered.mutations).map((e) => zt(e.descriptor)),
604
+ ...Te(e.discovered.actions).map((e) => K(e.descriptor)),
605
+ ...me.queries.map((e) => q(e.descriptor)),
606
+ ...me.mutations.map((e) => zt(e.descriptor)),
607
+ ...v.queries.map((e) => q(e.descriptor)),
608
+ ...v.mutations.map((e) => zt(e.descriptor)),
609
+ ...v.actions.map((e) => K(e.descriptor)),
610
+ ...(e.discovered.streams ?? []).map((e) => Bt(e.descriptor)),
611
+ ...(e.discovered.workflows ?? []).map((e) => B(e.definition)),
612
+ ...f ? [
613
+ q(X),
614
+ q(Z),
615
+ q(Wt),
616
+ q(Y),
617
+ q(J),
618
+ q(Ht),
619
+ K(Vt),
620
+ K(Ut),
621
+ K(Gt),
622
+ K(Kt)
623
+ ] : []
624
+ ], De = kt.make(...Ee).middleware(W).middleware(G), Oe = j.succeed(W, W.of(({ headers: t, clientId: n }) => A.promise(() => e.resolveSubject(t, n)))), Ae = j.succeed(G, G.of(({ clientId: e }) => A.succeed({ clientId: e }))), je = e.dormancyTenantId ?? "default", Me = e.dormancy === "sleep" ? {
625
+ register: (t, n, r) => bt(e.store, {
626
+ tenantId: r ?? je,
627
+ kind: "workflow",
628
+ refId: t,
629
+ wakeAt: n
630
+ }),
631
+ cancel: (t, n) => qe(e.store, {
632
+ tenantId: n ?? je,
633
+ kind: "workflow",
634
+ refId: t
635
+ }).then(() => {})
636
+ } : void 0, O = te ? await import("@voltro/workflow") : void 0, k = O?.makeWorkflowRunRecorder({
637
+ store: e.store,
638
+ ...Me === void 0 ? {} : { wakeups: Me }
639
+ }), Ne = async (t, n) => {
640
+ await O.closeWorkflowChildrenForParent({
641
+ store: e.store,
642
+ parentExecutionId: t,
643
+ parentStatus: n,
644
+ recorder: k,
645
+ log: { warn: (e, t) => {
646
+ process.stderr.write(`[workflow] ${e} ${t ? JSON.stringify(t) : ""}\n`);
647
+ } },
648
+ interruptChild: async (t, n) => {
649
+ let r = (e.discovered.workflows ?? []).find((e) => e.definition.name === t);
650
+ if (!r) throw Error(`Unknown child workflow: ${t}`);
651
+ if (!a) throw Error("Workflow runtime is not ready");
652
+ await a.runPromise(r.definition.interrupt(n));
653
+ }
654
+ });
655
+ }, Pe = async (t, n, r) => {
656
+ let i = (await e.store.query({
657
+ table: "_voltro_workflow_runs",
658
+ order: [],
659
+ predicate: V("executionId", n),
660
+ projection: void 0,
661
+ skip: void 0,
662
+ take: 1
663
+ }))[0];
664
+ if (i === void 0) return;
665
+ let a = await e.store.update("_voltro_workflow_runs", i.id, {
666
+ status: "cancelled",
667
+ cancelled: !0,
668
+ completedAt: /* @__PURE__ */ new Date()
669
+ }), o = i.subject?.tenantId ?? void 0;
670
+ a && await k.recordEvent({
671
+ runId: i.id,
672
+ eventType: "run-cancelled",
673
+ payload: {
674
+ reason: r,
675
+ workflowName: t,
676
+ executionId: n,
677
+ ...o == null ? {} : { tenantId: o }
678
+ }
679
+ }), a && await Ne(n, "cancelled");
680
+ }, Fe = [..._t(e.discovered.workflows ?? [], {
681
+ buildContext: (t, n) => e.buildContextForWorkflow?.(t, n) ?? y({
682
+ subject: t.subject,
683
+ traceId: t.traceId
684
+ }, e.store, void 0, `workflow:${n.workflowName}`, { parentExecutionId: n.executionId }),
685
+ resolveStartContext: u
686
+ }, (t, n, r) => {
687
+ let i = O.getWorkflowVersionMetadata(t.definition);
688
+ return O.wrapWorkflowExecuteWithRunRecording({
689
+ name: t.definition.name,
690
+ store: e.store,
691
+ subject: r.subject,
692
+ source: r.source ?? null,
693
+ traceId: r.traceId,
694
+ workflowVersion: i.version,
695
+ workflowCompatibleVersions: i.compatibleWith,
696
+ workflowPatches: i.patches,
697
+ parentExecutionId: r?.parentExecutionId ?? null,
698
+ parentClosePolicy: r?.parentClosePolicy ?? null,
699
+ onParentClose: ({ executionId: e, status: t }) => Ne(e, t),
700
+ recorder: k
701
+ }, n);
702
+ }), ...e.discovered.workflowWorkers ?? []], Ie = Fe.length > 0 ? j.mergeAll(...Fe) : j.empty;
703
+ if (((e.discovered.workflows?.length ?? 0) > 0 || (e.discovered.workflowWorkers?.length ?? 0) > 0 || e.scheduleCoordination === "cluster") && e.workflowEngineLayer !== void 0) {
704
+ let t = Ie.pipe(j.provideMerge(e.workflowEngineLayer));
705
+ a = Re.make(e.baseLayer === void 0 ? t : t.pipe(j.provideMerge(e.baseLayer))), await a.runPromise(A.void), i = (e.discovered.workflows?.length ?? 0) > 0 ? ht({
706
+ workflows: e.discovered.workflows ?? [],
707
+ runEffect: (e) => a.runPromise(e),
708
+ rememberStartContext: l,
709
+ signal: async (t, n, r) => {
710
+ let i = await O.sendWorkflowSignal({
711
+ store: e.store,
712
+ recorder: k,
713
+ target: t,
714
+ signalName: n,
715
+ payload: r
716
+ });
717
+ return await a.runPromise(O.completeSuspendingSignal({
718
+ store: e.store,
719
+ target: t,
720
+ signalName: n,
721
+ payload: r
722
+ })).catch(() => {}), i;
723
+ },
724
+ update: (t, n, r, i) => O.sendWorkflowUpdate({
725
+ store: e.store,
726
+ recorder: k,
727
+ target: t,
728
+ updateName: n,
729
+ payload: r,
730
+ ...i === void 0 ? {} : { options: i }
731
+ }),
732
+ listRuns: (t) => b(e.store, t),
733
+ retry: (t, n) => ke({
734
+ store: e.store,
735
+ workflows: e.discovered.workflows ?? [],
736
+ runPromise: (e) => a.runPromise(e)
737
+ }, t, n)
738
+ }) : void 0;
739
+ }
740
+ let Le = j.mergeAll(De.toLayer(C), Oe, Ae), ze = ee(C, e.discovered.queries.map((e) => e.descriptor.name), f), Ve = j.mergeAll(De.toLayer(ze), Oe, Ae), P = e.observability, Je = await Ke({
741
+ ...P && P.spanProcessors.length > 0 ? { extraSpanProcessors: P.spanProcessors } : {},
742
+ ...P && P.metricReaders.length > 0 ? { extraMetricReaders: P.metricReaders } : {},
743
+ ...P && Object.keys(P.resourceAttributes).length > 0 ? { resourceAttributes: P.resourceAttributes } : {},
744
+ ...P && P.sampler !== void 0 ? { sampler: P.sampler } : {}
745
+ }), Ye = !1, Xe = e.store.ping ? () => e.store.ping().then(() => !0).catch(() => !1) : void 0, { server: Ze, shutdown: Qe } = Et({
746
+ group: De,
747
+ handlersLayer: Le,
748
+ httpHandlersLayer: Ve,
749
+ port: e.port ?? 4e3,
750
+ path: e.path ?? "/ws",
751
+ tracerLayer: Je.layer,
752
+ healthCheck: {
753
+ isReady: () => Ye,
754
+ ...Xe ? { ping: Xe } : {}
755
+ },
756
+ ...we.length > 0 ? { httpRoutes: we } : {},
757
+ ...e.getStore === void 0 ? {} : { getStore: e.getStore },
758
+ ...oe.size > 0 ? { webhookRoutes: oe } : {},
759
+ ...e.inspectRoute === void 0 ? {} : { inspectRoute: e.inspectRoute }
760
+ });
761
+ if (await We(Ze), (e.discovered.schedules?.length ?? 0) > 0) {
762
+ let t = (e.scheduleCoordination ?? "single") === "advisoryLock" ? tt(e.store, e.scheduleReplicaId ?? `pid-${process.pid}`) : Tt;
763
+ o = await Dt(e.discovered.schedules ?? [], {
764
+ store: e.store,
765
+ coordinator: t,
766
+ defaultTrigger: e.scheduleDefaultTrigger ?? "self",
767
+ replicaId: e.scheduleReplicaId ?? `pid-${process.pid}`,
768
+ armSelf: e.scheduleArmSelf ?? !0,
769
+ dormancy: e.dormancy ?? "always-on",
770
+ ...e.dormancyTenantId === void 0 ? {} : { dormancyTenantId: e.dormancyTenantId },
771
+ buildContext: ({ traceId: t, scheduleName: n, subject: r }) => y({
772
+ subject: r,
773
+ traceId: t
774
+ }, e.store, void 0, `schedule:${n}`),
775
+ log: {
776
+ info: (e, t) => {
777
+ process.stdout.write(`[schedule] ${e} ${t ? JSON.stringify(t) : ""}\n`);
778
+ },
779
+ warn: (e, t) => {
780
+ process.stderr.write(`[schedule] ${e} ${t ? JSON.stringify(t) : ""}\n`);
781
+ },
782
+ error: (e, t) => {
783
+ process.stderr.write(`[schedule] ERROR ${e} ${t ? JSON.stringify(t) : ""}\n`);
784
+ },
785
+ debug: () => {}
786
+ },
787
+ ...e.scheduleFireInterceptor === void 0 ? {} : { interceptFire: e.scheduleFireInterceptor },
788
+ ...e.onScheduleRunEvent === void 0 ? {} : { onRunEvent: e.onScheduleRunEvent }
789
+ }), e.onSchedulerReady?.(o);
790
+ }
791
+ let nt = e.log ?? M({ scope: "voltro:serve" }), rt, it;
792
+ if ((e.discovered.subscribers?.length ?? 0) > 0 && (rt = de(e.discovered.subscribers ?? [], e.store, nt.child("subscribe"), e.schemaRegistry)), (e.discovered.reactions?.length ?? 0) > 0) {
793
+ let t = nt.child("reaction");
794
+ it = ve(e.discovered.reactions ?? [], e.store, {
795
+ runAct: async (n, r) => {
796
+ if (n.kind === "workflow") {
797
+ if (d === void 0) {
798
+ t.warn("reaction workflow act skipped — no workflow engine in this app", { workflow: n.workflow });
799
+ return;
800
+ }
801
+ let e = r.new ?? r.old ?? {};
802
+ await gt(d, {
803
+ traceId: `reaction:${n.workflow}`,
804
+ source: `reaction:${n.workflow}`
805
+ }).start(n.workflow, e);
806
+ return;
807
+ }
808
+ await _(n.agent, r, {
809
+ findAgentSend: (t) => e.discovered.actions.find((e) => e.descriptor.name === `${t}.send`),
810
+ runAction: (e, t, n) => Promise.resolve(he(e, t, n)),
811
+ makeSubject: (e) => Lt(e),
812
+ now: () => Date.now(),
813
+ log: t
814
+ });
815
+ },
816
+ checkBudget: async (n, r) => {
817
+ try {
818
+ let { requireAiBudget: t } = await import("@voltro/ai");
819
+ return (await A.runPromise(A.either(t(e.store, {
820
+ tenantId: n,
821
+ limitUsd: r
822
+ }))))._tag === "Right";
823
+ } catch (e) {
824
+ return t.warn("reaction budget check failed — refusing the act", { tenantId: n }, e), !1;
825
+ }
826
+ }
827
+ }, t);
828
+ }
829
+ let at;
830
+ return (e.discovered.aggregates?.length ?? 0) > 0 && (at = await ne({
831
+ discovered: e.discovered.aggregates ?? [],
832
+ store: e.store,
833
+ log: nt.child("aggregate"),
834
+ ...e.analytics === void 0 ? {} : { analytics: e.analytics },
835
+ ...e.aggregateStorage === void 0 ? {} : { storage: e.aggregateStorage },
836
+ ...e.aggregateCoordinator === void 0 ? {} : { coordinator: e.aggregateCoordinator }
837
+ }), ue = j.succeed(N, at.registry)), Ye = !0, e.bootTiming?.mark("ready"), {
838
+ dispatcher: t,
839
+ server: Ze,
840
+ scheduler: o,
841
+ close: async () => {
842
+ Ye = !1, at?.detach(), it?.(), rt?.(), await o?.shutdown(), t.close(), await a?.dispose(), await new Promise((e) => Ze.close(() => e())), await Qe();
843
+ }
844
+ };
845
+ }, $ = M({ scope: "voltro:serve" }), Pn = (e, t, n) => (e === "production" || e === "staging") && t !== "memory" && n !== "0", Fn = Pe, In = async (e) => {
846
+ let t = O(process.cwd());
847
+ if (ze(t)) {
848
+ let n;
849
+ try {
850
+ let e = await import(Ie(t).href);
851
+ typeof e.runServe == "function" ? n = e.runServe : $.warn("serve bundle has no runServe export — using the standard serve path");
852
+ } catch (e) {
853
+ $.warn("serve bundle failed to load — using the standard serve path", {}, e);
854
+ }
855
+ if (n) return $.info("serve: booting from the precompiled serve bundle"), n(e);
856
+ }
857
+ return Ln(e);
858
+ }, Ln = async (ee) => {
859
+ let p = Ne();
860
+ process.env.NODE_ENV || (process.env.NODE_ENV = "production");
861
+ try {
862
+ qt();
863
+ } catch (e) {
864
+ throw gn(e instanceof Error ? e.message : String(e));
865
+ }
866
+ let m = process.cwd(), ne = Number(process.env.PORT ?? Fn(ee, "--port") ?? 4e3), g = await he(m);
867
+ Ct(xt(g?.secrets)), await e({
868
+ rawEnv: g?.env,
869
+ appType: "api",
870
+ root: m,
871
+ log: $,
872
+ generateTypes: !1
873
+ }), p.mark("config");
874
+ let _ = (process.env.DB_DIALECT ?? g?.store ?? "memory").toLowerCase(), ce = (_ === "mariadb" || _ === "postgres" || _ === "mssql") && (process.env.CDC ?? "1") !== "0", le = _ === "mariadb" ? "mariadb" : _ === "mssql" ? "mssql" : void 0, de = k(m);
875
+ if (!i() && ze(de)) try {
876
+ let e = await import(Ie(de).href);
877
+ if (e.modules) {
878
+ let t = {};
879
+ for (let [n, r] of Object.entries(e.modules)) t[Fe(m, n)] = r;
880
+ r(t), $.info("precompiled api bundle loaded", { modules: Object.keys(t).length });
881
+ }
882
+ } catch (e) {
883
+ $.warn("precompiled api bundle failed to load — falling back to source", {}, e);
884
+ }
885
+ let b = await be(m), S = await De(b, { cdc: ce && le !== void 0 });
886
+ {
887
+ let e = h(S.serverOnlyLeaks, re(process.env, "strict"), Ze, "`voltro serve`");
888
+ if (e.action === "fail") throw gn(e.message ?? "");
889
+ e.action === "warn" && $.warn(e.message ?? "");
890
+ }
891
+ let ve = b.filter((e) => Ae.test(e)), w = ve.length > 0 ? await ue(ve, $.child("webhooks")) : void 0, Ce = s({
892
+ mix: S.featureMix,
893
+ plugins: g?.plugins ?? [],
894
+ cdc: ce && le !== void 0,
895
+ ...le ? { cdcDialect: le } : {}
896
+ }), ke = g?.analytics !== void 0 && g.analytics.kind !== "noop" && _ !== "memory" ? (await n(_)).makeSqlLayer(T()) : void 0, D = await ie({
897
+ spec: g?.analytics,
898
+ sqlLayer: ke,
899
+ log: $
900
+ }), O = (() => {
901
+ let e = new Set(S.tables.map((e) => e.tableName)), t = [...S.tables];
902
+ for (let n of [...Ce, ...D.tables]) e.has(n.tableName) || (e.add(n.tableName), t.push(n));
903
+ return t;
904
+ })();
905
+ for (let e of O) Mt(e);
906
+ let Pe = (process.env.NODE_ENV ?? "").toLowerCase();
907
+ if (Pn(Pe, _, process.env.VOLTRO_AUTO_MIGRATE)) {
908
+ let e = (await n(_)).makeSqlLayer(T()), t = await A.runPromise(At.SqlClient.pipe(A.flatMap((e) => Qt(e, O, {
909
+ appliedBy: `serve:${Pe}`,
910
+ environment: "prod",
911
+ dialectId: _
912
+ })), A.provide(e)));
913
+ t.kind === "prod-mismatch" && ($.error(Zt(t, _)), $.error("serve: refusing to boot — apply the schema first (voltro db apply in a pre-deploy step), or set VOLTRO_AUTO_MIGRATE=0 to bypass this check."), process.exit(1)), $.info(Zt(t, _));
914
+ }
915
+ let M = mt(O);
916
+ p.mark("discover");
917
+ let N = await _e(g, void 0), Be = Ot(N, _);
918
+ for (let e of we({
919
+ dialect: String(g?.store ?? process.env.DB_DIALECT ?? "postgres"),
920
+ changeStrategy: (process.env.CDC ?? "1") === "0" ? "inline" : "cdc",
921
+ dbUrl: process.env.DB_URL,
922
+ tables: S.tables.map((e) => ({
923
+ tableName: e.tableName,
924
+ isReactive: e.isReactive === !0
925
+ })),
926
+ querySources: S.queries.flatMap((e) => {
927
+ let t = e.descriptor.source;
928
+ return t === void 0 ? [] : typeof t == "string" ? [t] : [...t];
929
+ })
930
+ })) e.level === "warn" ? $.warn(e.message) : $.info(e.message);
931
+ g?.cache && !process.env.CACHE_BACKEND && (process.env.CACHE_BACKEND = g.cache), g?.cacheRedisUrl && !process.env.CACHE_REDIS_URL && (process.env.CACHE_REDIS_URL = g.cacheRedisUrl), g?.cacheRedisDriver && !process.env.CACHE_REDIS_DRIVER && (process.env.CACHE_REDIS_DRIVER = g.cacheRedisDriver), g?.cacheKeyPrefix && !process.env.CACHE_KEY_PREFIX && (process.env.CACHE_KEY_PREFIX = g.cacheKeyPrefix);
932
+ let { service: He, invalidationBus: Ue, snapshotCache: We, cache: F, backend: Ge, dispose: I } = await xe({ env: process.env });
933
+ $.info(`cache backend resolved: ${Ge}` + (Ge === "redis" ? ` (driver ${process.env.CACHE_REDIS_DRIVER ?? "resp"})` : " — in-process, not cross-instance")), N.onChange((e) => {
934
+ A.runFork(Ue.publish(e.table));
935
+ }), g?.kv && !process.env.KV_BACKEND && (process.env.KV_BACKEND = g.kv), g?.kvRedisUrl && !process.env.KV_REDIS_URL && (process.env.KV_REDIS_URL = g.kvRedisUrl), g?.kvKeyPrefix && !process.env.KV_KEY_PREFIX && (process.env.KV_KEY_PREFIX = g.kvKeyPrefix);
936
+ let { kv: Ke, service: qe } = await at({ store: N });
937
+ p.mark("store");
938
+ let $e = P({
939
+ store: N,
940
+ sink: D.sink,
941
+ log: $
942
+ }), et = pe({
943
+ store: N,
944
+ dialect: _
945
+ }), L = g?.plugins ?? [], st = process.env.POD_NAME ?? process.env.HOSTNAME ?? `serve-${process.pid}`, ct, lt;
946
+ _ !== "memory" && (ct = Re.make((await n(_)).makeSqlLayer(T())), lt = await ct.runPromise(At.SqlClient));
947
+ let ut = ot({
948
+ coordinator: [
949
+ "postgres",
950
+ "mariadb",
951
+ "mysql",
952
+ "mssql"
953
+ ].includes(_) ? tt(N, st, $) : Tt,
954
+ replicaId: st,
955
+ log: $
956
+ }), dt = [], ft = {
957
+ ...lt ? { sql: lt } : {},
958
+ scheduleCoordinated: (e, t, n) => {
959
+ let r = ut(e, t, n);
960
+ return dt.push(r), r;
961
+ }
962
+ };
963
+ for (let e of L) e.bindDataStore?.(N, ft);
964
+ let pt = L.filter((e) => typeof e.onChangeEvent == "function");
965
+ if (pt.length > 0) {
966
+ let e = N.changeScope ?? "local";
967
+ N.onChange((t) => {
968
+ let n = y(t, e);
969
+ for (let e of pt) A.runFork(e.onChangeEvent(n).pipe(A.catchAllCause((t) => A.sync(() => $.warn(`plugin ${e.name} onChangeEvent failed`, { error: Le.pretty(t) })))));
970
+ });
971
+ }
972
+ let ht = me({
973
+ plugins: L,
974
+ appName: g?.name ?? "voltro-api",
975
+ appType: "api",
976
+ voltroVersion: process.env.npm_package_version ?? "0.0.0",
977
+ log: $
978
+ });
979
+ L.length && await ht.activate(), p.mark("plugins");
980
+ let gt = await ht.gatherObservability(), _t = await x(N, g, _, {
981
+ info: (e, t) => process.stdout.write(`[broadcast] ${e} ${t ? JSON.stringify(t) : ""}\n`),
982
+ warn: (e, t) => process.stderr.write(`[broadcast] ${e} ${t ? JSON.stringify(t) : ""}\n`),
983
+ debug: () => {}
984
+ }), R = g?.apiKeys, yt = (typeof R == "object" ? R.prefix : void 0) ?? "voltro_", bt = R ? Ye(N) : void 0, St = bt ? rt({ flush: it(bt) }) : void 0;
985
+ St && vt(() => St.shutdown());
986
+ let z = bt ? nt(bt, {
987
+ prefix: yt,
988
+ ...St ? { usage: St } : {}
989
+ }) : void 0, wt = z ? [Qe(z, { prefix: yt })] : [], Et = Se([...g?.auth?.strategies ?? [], ...wt], $t(g?.plugins ?? []), g?.auth?.anonymousTenantRequired ?? !1, g?.auth?.resolveScopes, () => Be), Dt = [...g?.restRoutes ?? [], ...z ? Ve(z, (typeof R == "object" ? R.managementPath : void 0) ?? "/v1/api-keys") : []], B = g?.idempotency, kt = B ? {
990
+ store: Xe(N),
991
+ header: (typeof B == "object" ? B.header : void 0) ?? "Idempotency-Key",
992
+ ttlMs: (typeof B == "object" ? B.ttlMs : void 0) ?? 864e5
993
+ } : void 0, jt = Dt.length > 0 ? tn(Dt, {
994
+ store: N,
995
+ resolveSubject: (e) => Et({
996
+ headers: e,
997
+ clientId: -1
998
+ }),
999
+ ...kt ? { idempotency: kt } : {}
1000
+ }) : [], V = L.map((e) => e.services).filter((e) => e !== void 0), Nt = j.mergeAll(Ee({
1001
+ analyticsLayer: D.layer,
1002
+ cacheService: He,
1003
+ kvService: qe,
1004
+ pluginServices: V,
1005
+ userLayers: g?.layers ?? []
1006
+ }), ge(g?.http ?? {})), H = g?.scheduling ?? {}, Pt = H.trigger ?? "self", Ft = /* @__PURE__ */ new Set([
1007
+ "postgres",
1008
+ "mysql",
1009
+ "mariadb",
1010
+ "mssql"
1011
+ ]), It = H.coordination ?? (Ft.has(_) ? "advisoryLock" : "single"), U = It === "cluster" && Ft.has(_), W = U ? "cluster" : It === "advisoryLock" && Ft.has(_) ? "advisoryLock" : "single";
1012
+ It === "cluster" && !U && $.warn("scheduling.coordination=cluster needs a sql-backed store except sqlite — falling back to single"), It === "advisoryLock" && !Ft.has(_) && $.warn("scheduling.coordination=advisoryLock needs a SQL store (the claim-row gate) — falling back to single");
1013
+ let G, K = S.workflows.length > 0 || S.workflowWorkers.length > 0 || S.eventTriggers.length > 0 || (w?.outgoing.length ?? 0) > 0 || U, Lt;
1014
+ if (K) {
1015
+ if (_ === "mssql") {
1016
+ let e = await fe(process.cwd());
1017
+ e && $.warn(e);
1018
+ }
1019
+ let [{ WorkflowEngine: e }, { makeClusterCronLayer: t, workflowEngineLayer: r, resolveRunnerStorage: i }] = await Promise.all([import("@effect/workflow"), import("@voltro/workflow/cluster")]), a = U ? S.schedules.filter((e) => (e.trigger ?? Pt) === "self").map((e) => t({
1020
+ name: e.name,
1021
+ cron: Je(e),
1022
+ execute: async () => {
1023
+ await G?.fireFromCluster(e.name);
1024
+ }
1025
+ })) : [];
1026
+ Lt = _ === "memory" ? e.layerMemory : await (async () => {
1027
+ let e = await n(_), t = i({ sqliteFamily: e.id === "sqlite" || e.id === "turso" });
1028
+ return $.info(`workflow engine: cluster-${t}, dialect=${e.id}` + (t === "memory" ? " — single-process durable replay, no cross-pod shard handoff" + (e.id !== "sqlite" && e.id !== "turso" ? " (VOLTRO_WORKFLOW_RUNNER_STORAGE=memory: SqlRunnerStorage/cluster_runners + GET_LOCK skipped)" : "") : "")), r({
1029
+ sqlClientLayer: e.makeSqlLayer(T()),
1030
+ runnerStorage: t,
1031
+ dialectId: e.id,
1032
+ ...process.env.VOLTRO_WORKFLOW_RUNNER_PORT ? { runnerListenPort: Number(process.env.VOLTRO_WORKFLOW_RUNNER_PORT) } : {},
1033
+ ...a.length > 0 ? { extraShardingLayers: a } : {}
1034
+ });
1035
+ })();
1036
+ }
1037
+ let Rt = je(L, t()), zt = b.filter((e) => /\.subscribe\.tsx?$/.test(e)), q = zt.length > 0 ? await ae(zt, $) : [], Bt = b.filter((e) => /\.reaction\.tsx?$/.test(e)), Vt = Bt.length > 0 ? await se(Bt, $) : [], J = b.filter((e) => u.test(e)), Ht = J.length > 0 ? await Me(J, $) : [], Ut = b.filter((e) => /\.aggregate\.tsx?$/.test(e)), Y = Ut.length > 0 ? await v(Ut, $) : [], X = ye();
1038
+ if (Y.length > 0 && _ !== "memory") try {
1039
+ X = f((await n(_)).makeSqlLayer(T()));
1040
+ } catch (e) {
1041
+ $.warn("aggregate: SQL storage init failed — falling back to in-process", { err: String(e) });
1042
+ }
1043
+ let Wt = _ === "memory" ? Tt : tt(N, `aggregate@${process.pid}`, $), Z = [], Gt = [], Kt = b.filter((e) => l.test(e));
1044
+ if (Kt.length > 0) {
1045
+ let e = $.child("agent"), t = b.filter((e) => a.test(e));
1046
+ t.length > 0 && await o(t, e);
1047
+ let n = await c(Kt, e);
1048
+ for (let e of n.agents) for (let t of te(e)) (t.kind === "action" ? Z : Gt).push({
1049
+ file: t.file,
1050
+ descriptor: t.descriptor,
1051
+ executor: t.executor
1052
+ });
1053
+ n.agents.length > 0 && e.info("synthesized agent routes", { agents: n.agents.map((e) => e.descriptor.name) });
1054
+ }
1055
+ p.mark("workflow");
1056
+ let Jt = await Nn({
1057
+ bootTiming: p,
1058
+ discovered: {
1059
+ queries: [...S.queries, ...Gt],
1060
+ mutations: S.mutations,
1061
+ actions: [...S.actions, ...Z],
1062
+ streams: S.streams,
1063
+ workflows: S.workflows,
1064
+ workflowWorkers: S.workflowWorkers,
1065
+ eventTriggers: S.eventTriggers,
1066
+ schedules: S.schedules,
1067
+ subscribers: q,
1068
+ outboxHandlers: Ht,
1069
+ connections: S.connections,
1070
+ reactions: Vt,
1071
+ aggregates: Y,
1072
+ ...w === void 0 ? {} : { webhooks: w }
1073
+ },
1074
+ log: $,
1075
+ analytics: D.sink,
1076
+ aggregateStorage: X,
1077
+ aggregateCoordinator: Wt,
1078
+ store: N,
1079
+ kv: Ke,
1080
+ cache: F,
1081
+ snapshotCache: We,
1082
+ schemaRegistry: M,
1083
+ tenantScopedTables: S.tenantScopedTables,
1084
+ softDeleteScopedTables: S.softDeleteScopedTables,
1085
+ dataTransferSnapshot: Xt(O),
1086
+ dataTransferDialect: _,
1087
+ tenantIsolation: (process.env.VOLTRO_TENANT_ISOLATION ?? g?.tenancy?.isolation) === "namespace" ? "namespace" : "shared-schema",
1088
+ resolveSubject: (e, t) => Et({
1089
+ headers: e,
1090
+ clientId: t
1091
+ }),
1092
+ httpRoutes: [...L.flatMap((e) => e.httpRoutes ?? []), ...jt],
1093
+ getStore: () => Be,
1094
+ ...Nt ? { baseLayer: Nt } : {},
1095
+ ...Lt === void 0 ? {} : { workflowEngineLayer: Lt },
1096
+ scheduleDefaultTrigger: Pt,
1097
+ scheduleCoordination: W,
1098
+ scheduleArmSelf: !U,
1099
+ dormancy: process.env.VOLTRO_DORMANCY === "sleep" || process.env.VOLTRO_DORMANCY === "always-on" ? process.env.VOLTRO_DORMANCY : g?.dormancy ?? "always-on",
1100
+ scheduleReplicaId: process.env.HOSTNAME ?? `pid-${process.pid}`,
1101
+ ...Rt === void 0 ? {} : { scheduleFireInterceptor: Rt },
1102
+ onSchedulerReady: (e) => {
1103
+ G = e;
1104
+ },
1105
+ inspectRoute: { handle: (e, t, n, r) => d(e, {
1106
+ kind: "api",
1107
+ meta: {
1108
+ name: g?.name ?? "voltro-api",
1109
+ voltroVersion: Te,
1110
+ port: ne,
1111
+ mode: "start",
1112
+ store: _,
1113
+ cdc: ce ? "on" : "off"
1114
+ },
1115
+ rpc: C(S, m),
1116
+ workflows: Oe(S, m),
1117
+ inspectFireSchedule: async ({ name: e, trigger: t }) => {
1118
+ if (!G) throw Error("scheduler not started — this app registers no self-triggered schedules (all schedules are trigger:'external', or there are none).");
1119
+ return { runId: await G.fireNow(e, t) ?? null };
1120
+ }
1121
+ }, t, {
1122
+ method: n,
1123
+ ...r === void 0 ? {} : { body: r }
1124
+ }) ?? {
1125
+ status: 404,
1126
+ contentType: "application/json",
1127
+ body: JSON.stringify({ error: "not an inspect route" })
1128
+ } },
1129
+ observability: gt,
1130
+ port: ne,
1131
+ ...g?.transport?.wsPath ? { path: g.transport.wsPath } : {}
1132
+ });
1133
+ return E(oe([
1134
+ S.queries,
1135
+ S.mutations,
1136
+ S.actions,
1137
+ S.streams
1138
+ ]), (e) => {
1139
+ $.warn(e);
1140
+ }), $.info(`API listening on :${ne}`, {
1141
+ dialect: _,
1142
+ queries: S.queries.length,
1143
+ mutations: S.mutations.length,
1144
+ actions: S.actions.length,
1145
+ streams: S.streams.length,
1146
+ workflows: S.workflows.length,
1147
+ workflowWorkers: S.workflowWorkers.length,
1148
+ schedules: S.schedules.length,
1149
+ scheduleCoordination: W
1150
+ }), p.finish($), vt(async () => {
1151
+ for (let e of dt) e.stop();
1152
+ $e.detach(), et.stop(), I(), ct?.dispose();
1153
+ try {
1154
+ await ht.deactivate(), await _t?.close(), await D.dispose(), await Jt.close(), await N.close?.();
1155
+ } catch (e) {
1156
+ console.error("serve: shutdown step failed, exiting anyway:", e);
1157
+ }
1158
+ }), await new Promise(() => {}), 0;
1159
+ };
1160
+ //#endregion
1161
+ export { In as n, An as r, Ln as t };