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