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