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