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