@voltro/cli 0.32.0 → 0.33.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 (80) hide show
  1. package/CHANGELOG.md +205 -0
  2. package/THIRD-PARTY-NOTICES.md +1 -29
  3. package/dist/apiBuild-C-x9YacA.js +2 -0
  4. package/dist/{apiBuild-C4uEbs3s.js → apiBuild-h9VHtnlw.js} +2 -2
  5. package/dist/bin.js +3 -3
  6. package/dist/checkCommand-DRovTKza.js +2 -0
  7. package/dist/{checkCommand-dm7OHtPt.js → checkCommand-xGhRFFg2.js} +15 -15
  8. package/dist/{commands-C0nEePif.js → commands-CJfepbm4.js} +97 -13
  9. package/dist/{dbCommand-ifOMafuG.js → dbCommand-DTLKAfbA.js} +401 -241
  10. package/dist/dbCommand-b1gum4td.js +2 -0
  11. package/dist/{dev-5ficNnvF.js → dev-C_P8FLSx.js} +1539 -1487
  12. package/dist/{dev-rc3fwPSZ.js → dev-iiMtlkfs.js} +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/{inspectMetrics-BqO4E9G0.js → inspectMetrics-1xzTKAFx.js} +573 -550
  15. package/dist/{sdkgen-B_5mHQS2.js → sdkgen-C81QIkiL.js} +1 -1
  16. package/dist/serveCommand-DdaM4Hup.js +1608 -0
  17. package/dist/serveEntry.js +2 -2
  18. package/dist/{start-D1-8eKrO.js → start-C0koT0UO.js} +1 -1
  19. package/dist/startEntry.js +2 -2
  20. package/package.json +31 -18
  21. package/templates/AGENTS.md +1 -1
  22. package/templates/agent-docs/_index.md +1 -1
  23. package/templates/agent-docs/database/misc.md +37 -0
  24. package/templates/agent-docs/database/schema.md +4 -2
  25. package/templates/agent-docs/deployment.md +87 -1
  26. package/templates/agent-docs/plugins.md +50 -0
  27. package/templates/agent-docs/scheduling.md +4 -1
  28. package/templates/agent-docs/security.md +23 -2
  29. package/templates/agent-docs/whats-new.md +128 -86
  30. package/templates/apps/api-ai/package.json +7 -7
  31. package/templates/apps/api-auth/package.json +8 -8
  32. package/templates/apps/api-backend/package.json +7 -7
  33. package/templates/apps/api-backend-deactivation/package.json +7 -7
  34. package/templates/apps/api-backend-mail/package.json +8 -8
  35. package/templates/apps/api-backend-mariadb/package.json +9 -9
  36. package/templates/apps/api-backend-sqlite/package.json +8 -8
  37. package/templates/apps/api-backend-storage/package.json +8 -8
  38. package/templates/apps/api-cms/package.json +10 -10
  39. package/templates/apps/api-collab/package.json +8 -8
  40. package/templates/apps/api-data-advanced/package.json +8 -8
  41. package/templates/apps/api-durable/package.json +8 -8
  42. package/templates/apps/api-feature-flags/package.json +9 -9
  43. package/templates/apps/api-governance/package.json +8 -8
  44. package/templates/apps/api-kv/package.json +8 -8
  45. package/templates/apps/api-moderation/package.json +8 -8
  46. package/templates/apps/api-observability/package.json +8 -8
  47. package/templates/apps/api-ratelimit/package.json +8 -8
  48. package/templates/apps/api-rbac/package.json +8 -8
  49. package/templates/apps/api-rest/package.json +7 -7
  50. package/templates/apps/api-saas/package.json +11 -11
  51. package/templates/apps/api-saas-starter/package.json +10 -10
  52. package/templates/apps/api-search/package.json +8 -8
  53. package/templates/apps/api-status/package.json +8 -8
  54. package/templates/apps/api-versioning/package.json +8 -8
  55. package/templates/apps/api-webhooks/package.json +9 -9
  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-auth/package.json +8 -8
  61. package/templates/apps/frontend-blank/package.json +7 -7
  62. package/templates/apps/frontend-cms/package.json +9 -9
  63. package/templates/apps/frontend-collab/package.json +9 -9
  64. package/templates/apps/frontend-contact/package.json +7 -7
  65. package/templates/apps/frontend-dashboard/package.json +7 -7
  66. package/templates/apps/frontend-docs/package.json +7 -7
  67. package/templates/apps/frontend-i18n/package.json +6 -6
  68. package/templates/apps/frontend-landing/package.json +7 -7
  69. package/templates/apps/frontend-portal/package.json +8 -8
  70. package/templates/apps/frontend-saas/package.json +8 -8
  71. package/templates/apps/frontend-spa/package.json +7 -7
  72. package/templates/apps/frontend-ssr/package.json +7 -7
  73. package/templates/apps/frontend-ssr-api/package.json +8 -8
  74. package/templates/apps/frontend-static-blog/package.json +6 -6
  75. package/templates/apps/frontend-status/package.json +8 -8
  76. package/templates/apps/mobile-app/package.json +2 -2
  77. package/dist/apiBuild-OJEjtwcn.js +0 -2
  78. package/dist/checkCommand-CwMrzAgV.js +0 -2
  79. package/dist/dbCommand-By__Ev0R.js +0 -2
  80. package/dist/serveCommand-PxMmn96o.js +0 -1578
@@ -1,1578 +0,0 @@
1
- import { _t as e, ht as t, ot as n, t as r } from "./inspectMetrics-BqO4E9G0.js";
2
- import { n as i, s as a, t as o } from "./seedRunner-Bqxgp7HZ.js";
3
- import { r as s, t as c } from "./appModuleLoader-C9r9mxZt.js";
4
- import { $ as l, $t as u, A as d, At as f, B as p, Bt as ee, C as te, Ct as ne, D as m, Dt as h, E as re, Et as ie, F as g, Ft as ae, G as _, H as oe, I as v, J as y, Jt as se, K as ce, Kt as le, L as ue, Lt as de, M as fe, Mt as pe, N as b, Nt as x, O as me, Ot as he, P as ge, Pt as _e, Q as S, Qt as ve, R as ye, Rt as be, S as C, St as xe, T as Se, Tt as Ce, U as w, V as we, W as Te, X as Ee, Xt as De, Y as Oe, Yt as ke, Z as Ae, Zt as je, _ as Me, _t as T, an as Ne, at as E, b as Pe, bt as Fe, c as D, ct as Ie, d as Le, dt as Re, en as ze, et as Be, ft as Ve, g as He, gt as Ue, h as O, ht as We, i as k, in as Ge, it as Ke, j as qe, jt as Je, k as Ye, kt as Xe, lt as Ze, mt as Qe, nn as $e, nt as et, o as A, on as tt, ot as nt, pt as rt, q as it, qt as j, r as M, rt as at, st as ot, t as st, tn as ct, tt as lt, u as ut, ut as dt, v as ft, vt as pt, w as mt, wt as ht, x as gt, xt as _t, y as vt, yt as N, zt as yt } from "./dev-5ficNnvF.js";
5
- import { b as bt, f as xt, g as P, h as F, m as St, r as Ct, y as wt } from "./frameworkTableAssembly-BwIrO5nv.js";
6
- import { S as Tt, c as Et, n as Dt, p as Ot, s as kt } from "./fileConventions-Cof68_BL.js";
7
- import { m as I } from "./inspect-BUUjt773.js";
8
- import { n as At, t as jt } from "./startupRunner-DPGFchOa.js";
9
- import { r as Mt, u as L } from "./apiBuild-C4uEbs3s.js";
10
- import { t as Nt } from "./bootTiming-BdyP9nYw.js";
11
- import { n as R } from "./cliArgs-qdZSElM3.js";
12
- import { basename as Pt, join as Ft } from "node:path";
13
- import { pathToFileURL as It } from "node:url";
14
- import { Cause as Lt, Effect as z, Layer as B, ManagedRuntime as Rt } from "effect";
15
- import { createLogger as V } from "@voltro/logger";
16
- import { existsSync as zt } from "node:fs";
17
- import { AggregateRegistry as Bt, CostRegistry as Vt, Dispatcher as Ht, ExpectationRegistry as Ut, ExperimentRegistry as H, apiKeyManagementRoutes as Wt, attachAnalyticsMirror as Gt, attachExpectations as Kt, attachExperiments as qt, attachFinops as Jt, awaitServerListening as Yt, bindMutation as U, bindStream as Xt, bindSubscription as W, buildTracingLayer as Zt, cancelWakeup as Qt, compileCron as $t, dataStoreApiKeyStore as en, dataStoreIdempotencyStore as tn, formatServerOnlyLeaks as nn, formatUnresolvedSources as rn, frameworkApiKeyStrategy as an, getCredentialExpiry as on, installPolicyGuardResolver as sn, loadResourceTuples as cn, makeActionRunner as ln, makeAdvisoryLockCoordinator as un, makeApiKeyService as dn, makeApiKeyUsageBuffer as fn, makeApiKeyUsageFlusher as pn, makeAsyncKv as mn, makeCoordinatedScheduler as hn, makeEffectStoreLayer as gn, makeLazyWorkflowFacade as _n, makeMutationOutputCodec as vn, makeMutationRunner as yn, makeOneShotQueryRunner as bn, makeQueryDescriptorProducer as xn, makeQueryFinalizer as Sn, makeQueryReauthorizer as Cn, makeQuerySubscriber as wn, makeSchemaRegistry as Tn, makeWorkflowFacade as En, makeWorkflowFacadeWithCallerContext as G, makeWorkflowLayers as Dn, noopKv as K, onProcessShutdown as On, recordCredentialExpiry as kn, recordSubscriptionDelivery as An, recordWorkflowRun as jn, registerWakeup as Mn, resolveSecretsBackend as Nn, runProvidedEffect as Pn, setSecretsBackend as Fn, setSystemStoreHandle as In, setTupleSource as Ln, singleCoordinator as Rn, startRpcServer as zn, startScheduler as Bn, stripForbiddenForWire as Vn, unresolvedSources as Hn, workflowToRpc as Un, wrapStoreWithBootCodec as Wn } from "@voltro/runtime";
18
- import { RpcGroup as Gn } from "@effect/rpc";
19
- import { SqlClient as Kn } from "@effect/sql";
20
- import { allRegisteredTables as qn, and as Jn, ensureTableRegistered as Yn, eq as q, or as Xn } from "@voltro/database";
21
- import { appStorageProvider as Zn, fromNodeReadable as Qn, getObjectStream as $n, putObjectStream as er, toNodeReadable as tr } from "@voltro/plugin-storage";
22
- import { AuthMiddleware as nr, ConnectionInfoMiddleware as rr, actionToRpc as J, anonymousSubject as ir, isWireReachable as ar, mutationToRpc as Y, queryToRpc as X, streamToRpc as or, workflowCancelDescriptor as Z, workflowDomainEventsQueryDescriptor as sr, workflowEventDeliveriesQueryDescriptor as cr, workflowResumeDescriptor as lr, workflowRunEventsQueryDescriptor as ur, workflowRunQueryDescriptor as dr, workflowRunStepsQueryDescriptor as fr, workflowRunsQueryDescriptor as pr, workflowSignalDescriptor as mr, workflowUpdateDescriptor as hr } from "@voltro/protocol";
23
- import { isEnvContract as gr } from "@voltro/env";
24
- import { assertProductionSessionSecret as _r, sessionExpiryFromHeaders as vr } from "@voltro/protocol/session";
25
- import { createHash as yr, timingSafeEqual as br } from "node:crypto";
26
- import { declaredSnapshot as xr, describeOutcome as Sr, runPlannedMigrations as Cr } from "@voltro/database/sql";
27
- import { buildDeliverWebhookExecute as wr, buildWebhooksService as Tr, defaultIncomingPath as Er, deliverWebhookWorkflow as Dr, makeDeferredEmitHandler as Or, mountIncomingWebhook as kr } from "@voltro/plugin-webhooks";
28
- import { getAuthSessionStrategy as Ar } from "@voltro/plugin-auth";
29
- import { collectPublicApiRoutes as jr, restRoutesToHttpRoutes as Mr } from "@voltro/protocol/rest";
30
- import { registerEmailTemplates as Nr } from "@voltro/plugin-mail";
31
- import { channelFor as Pr, getBroadcastPlugin as Fr } from "@voltro/plugin-broadcast";
32
- import { packBundle as Ir, runExport as Lr, runImport as Rr, storageBlobSink as zr, storageRefsBlobSource as Br, unpackBundle as Vr, unpackBundleToDir as Hr } from "@voltro/data-transfer";
33
- //#region src/dbPoolReport.ts
34
- var Ur = (e, t) => {
35
- let n = e !== void 0 && t !== void 0 ? e * t : void 0;
36
- return e === void 0 ? "db pool: max per replica UNSET (DB_MAX_CONNECTIONS) — each replica opens the driver's default pool, so the fleet total is that default × replicas. Set DB_MAX_CONNECTIONS so the total stays under your database's connection limit; the pool scales with replicaCount and the database does not." : `db pool: max=${e} per replica (DB_MAX_CONNECTIONS)` + (n === void 0 ? " — the fleet opens up to max × replicas connections. Check that against your database's limit before raising replicaCount." : ` × ${t} replicas = up to ${n} connections. Check that against your database's limit.`);
37
- }, Wr = (e = process.env) => {
38
- let t = e.REPLICA_COUNT;
39
- if (t === void 0 || t === "") return;
40
- let n = Number(t);
41
- return Number.isInteger(n) && n > 0 ? n : void 0;
42
- }, Gr = "/_voltro/admin/import", Kr = "/_voltro/admin/export", Q = (e, t) => ({
43
- status: e,
44
- contentType: "application/json; charset=utf-8",
45
- body: JSON.stringify(t)
46
- }), qr = (e) => {
47
- let t = e.authorization ?? e.Authorization, n = t ? /^Bearer\s+(.+)$/i.exec(t) : null;
48
- return n ? n[1] : null;
49
- }, Jr = (e, t) => br(yr("sha256").update(e).digest(), yr("sha256").update(t).digest()), Yr = (e, t) => {
50
- if (e.method.toUpperCase() !== "POST") return Q(405, { error: "method not allowed" });
51
- if (!t || t.length < 16) return Q(503, { error: "data transfer misconfigured (no/weak secret)" });
52
- let n = qr(e.headers);
53
- return !n || !Jr(n, t) ? Q(401, { error: "unauthorized" }) : null;
54
- }, Xr = V({ scope: "voltro:admin-import" }), Zr = "VBUNDLE2", Qr = async function* (e) {
55
- yield e;
56
- }, $r = (e) => async (t) => {
57
- let n = Yr(t, e.secret);
58
- if (n) return n;
59
- 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") === Zr, c, l;
60
- if (s) c = Qr(t.rawBody), l = "upload";
61
- else {
62
- let n;
63
- try {
64
- n = JSON.parse(Buffer.from(t.rawBody).toString("utf8") || "{}");
65
- } catch {
66
- return Q(400, { error: "body must be a packed bundle archive or { bundleKey } JSON" });
67
- }
68
- if (typeof n.bundleKey != "string" || !n.bundleKey) return Q(400, { error: "body.bundleKey (string) is required for the storage transport" });
69
- if (!e.openArchive) return Q(501, { error: "storage transport not configured on this instance" });
70
- c = e.openArchive(n.bundleKey), l = "storage";
71
- }
72
- 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-"));
73
- try {
74
- e.assetSink ? await Vr(c, {
75
- dir: p,
76
- blobs: e.assetSink
77
- }) : await Hr(c, p);
78
- let t = await z.runPromiseExit(Rr({
79
- store: e.store,
80
- bundleDir: p,
81
- ...r ? { mode: r } : {},
82
- ...i ? { onConflict: i } : {},
83
- ...a ? { atomic: a } : {},
84
- ...e.snapshot ? { targetSnapshot: e.snapshot } : {},
85
- force: o,
86
- onWarn: (e) => Xr.warn("admin.import", { message: e }),
87
- ...e.assetSink ? { assetsAlreadyRestored: !0 } : {}
88
- }));
89
- if (t._tag === "Failure") {
90
- let e = t.cause._tag === "Fail" ? t.cause.error : void 0;
91
- if (e && e._tag === "SchemaDriftError") {
92
- let t = e;
93
- return Xr.warn("admin.import refused (schema drift)", {
94
- transport: l,
95
- bundle: t.bundleFingerprint.slice(0, 16),
96
- target: t.targetFingerprint.slice(0, 16)
97
- }), Q(409, {
98
- error: "schema drift",
99
- bundleFingerprint: t.bundleFingerprint,
100
- targetFingerprint: t.targetFingerprint,
101
- diff: t.diff,
102
- hint: "re-export against the current schema, or resend with x-import-force: 1"
103
- });
104
- }
105
- throw Error(String(e?.message ?? e ?? "import failed"));
106
- }
107
- let n = t.value, s = n.tables.reduce((e, t) => e + t.rowCount, 0);
108
- return Xr.info("admin.import", {
109
- transport: l,
110
- tables: n.tables.length,
111
- rows: s,
112
- mode: r ?? "upsert",
113
- atomic: a
114
- }), Q(200, {
115
- tables: n.tables.length,
116
- rows: s,
117
- transport: l
118
- });
119
- } catch (e) {
120
- return Xr.warn("admin.import failed", {
121
- transport: l,
122
- error: e?.message ?? String(e)
123
- }), Q(500, {
124
- error: "import failed",
125
- message: e?.message ?? String(e)
126
- });
127
- } finally {
128
- await d.rm(p, {
129
- recursive: !0,
130
- force: !0
131
- });
132
- }
133
- }, ei = V({ scope: "voltro:admin-export" }), ti = async (e) => {
134
- let t = [];
135
- for await (let n of e) t.push(Buffer.from(n));
136
- return new Uint8Array(Buffer.concat(t));
137
- }, ni = (e) => typeof e.tenant == "string" && e.tenant ? {
138
- kind: "tenant",
139
- tenantId: e.tenant
140
- } : Array.isArray(e.tables) && e.tables.length ? {
141
- kind: "tables",
142
- tables: e.tables.filter((e) => typeof e == "string")
143
- } : { kind: "all" }, ri = (e) => async (t) => {
144
- let n = Yr(t, e.secret);
145
- if (n) return n;
146
- let r;
147
- try {
148
- r = JSON.parse(Buffer.from(t.rawBody).toString("utf8") || "{}");
149
- } catch {
150
- return Q(400, { error: "body must be JSON: { profile?, tenant?, tables?, consistency?, compression?, bundleKey? }" });
151
- }
152
- let i = {};
153
- if (typeof r.profile == "string" && r.profile) {
154
- if (!e.loadProfile) return Q(501, { error: "server-side profiles not configured on this instance" });
155
- try {
156
- i = await e.loadProfile(r.profile);
157
- } catch (e) {
158
- return Q(400, {
159
- error: `profile '${r.profile}' could not be loaded`,
160
- message: e?.message ?? String(e)
161
- });
162
- }
163
- }
164
- let a = r.consistency === "snapshot" ? "snapshot" : i.consistency ?? "live", o = (typeof r.compression == "string" ? r.compression : void 0) ?? i.compression, s = i.scope ?? ni(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-"));
165
- try {
166
- let t = await z.runPromise(Lr({
167
- store: e.store,
168
- snapshot: e.snapshot,
169
- dialect: e.dialect,
170
- outDir: p,
171
- ...i.subset ? { subset: i.subset } : {
172
- scope: s,
173
- ...e.tenantTables && e.tenantTables.length > 0 ? { tenantTables: e.tenantTables } : {}
174
- },
175
- consistency: a,
176
- ...o ? { compression: o } : {},
177
- ...i.masking ? { masking: i.masking } : {}
178
- })), n = t.tables.reduce((e, t) => e + t.rowCount, 0), u = t.masking?.transformed.length ?? 0;
179
- if (c) {
180
- if (!e.putArchive) return Q(501, { error: "storage transport not configured on this instance" });
181
- let i = r.bundleKey;
182
- return await e.putArchive(i, () => Ir({
183
- dir: p,
184
- ...l
185
- })), ei.info("admin.export", {
186
- transport: "storage",
187
- tables: t.tables.length,
188
- rows: n,
189
- masked: u,
190
- bundleKey: i
191
- }), Q(200, {
192
- bundleKey: i,
193
- tables: t.tables.length,
194
- rows: n,
195
- masked: u,
196
- transport: "storage"
197
- });
198
- }
199
- let d = await ti(Ir({
200
- dir: p,
201
- ...l
202
- }));
203
- return ei.info("admin.export", {
204
- transport: "download",
205
- tables: t.tables.length,
206
- rows: n,
207
- masked: u,
208
- bytes: d.byteLength
209
- }), {
210
- status: 200,
211
- contentType: "application/octet-stream",
212
- body: d,
213
- headers: {
214
- "x-export-tables": String(t.tables.length),
215
- "x-export-rows": String(n),
216
- "x-export-masked": String(u)
217
- }
218
- };
219
- } catch (e) {
220
- return ei.warn("admin.export failed", { error: e?.message ?? String(e) }), Q(500, {
221
- error: "export failed",
222
- message: e?.message ?? String(e)
223
- });
224
- } finally {
225
- await d.rm(p, {
226
- recursive: !0,
227
- force: !0
228
- });
229
- }
230
- }, ii = async (e) => {
231
- let { resolve: t } = await import("node:path"), { existsSync: n } = await import("node:fs"), r = [
232
- e,
233
- `${e}.profile.ts`,
234
- `data-profiles/${e}.ts`,
235
- `data-profiles/${e}.profile.ts`
236
- ].map((e) => t(process.cwd(), e)), i = r.find((e) => n(e));
237
- if (!i) throw Error(`data profile '${e}' not found (looked for: ${r.join(", ")})`);
238
- let a = await import(i), o = a.default ?? a.profile;
239
- if (!o) throw Error(`data profile '${i}' has no default export`);
240
- return o;
241
- }, ai = (e, t, n = {}) => (async function* () {
242
- let r = await tr((await z.runPromise($n(e, t).pipe(z.timeout(n.openTimeout ?? "30 seconds")))).stream), i = n.stallMs ?? 12e4, a, o = () => {
243
- a && clearTimeout(a), a = setTimeout(() => r.destroy(/* @__PURE__ */ Error(`storage read stalled for ${i}ms reading '${t}'`)), i);
244
- };
245
- try {
246
- o();
247
- for await (let e of r) o(), yield e instanceof Uint8Array ? e : new Uint8Array(e);
248
- } finally {
249
- a && clearTimeout(a), r.destroy();
250
- }
251
- })(), oi = {
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
- }, si = async (e) => {
261
- In({
262
- dataStore: e.store,
263
- schemaRegistry: e.schemaRegistry
264
- });
265
- let t = (e.discovered.budgets?.length ?? 0) > 0, n, i = new Ht({
266
- store: e.store,
267
- ...e.snapshotCache ? { cache: e.snapshotCache } : {},
268
- ...t ? { recordCost: (e) => n?.record(e) } : {},
269
- recordDelivery: (e) => An({
270
- label: e.label,
271
- kind: e.kind,
272
- durationMs: e.durationMs,
273
- rowCount: e.rowCount
274
- })
275
- }), a = e.cache ?? oi, o = e.kv ?? K, s, c = () => void 0, l, u, d, ee, te, ne, m, h = /* @__PURE__ */ new Map(), re = () => `wfctx_${globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`}`, ie = async (t, n, r) => {
276
- let i = {
277
- ...r,
278
- source: r.source ?? `workflow:${t}`
279
- };
280
- h.set(n, i);
281
- try {
282
- let r = await e.store.query({
283
- table: "_voltro_workflow_start_contexts",
284
- order: [],
285
- predicate: q("executionId", n),
286
- projection: ["id"],
287
- skip: void 0,
288
- take: 1
289
- }), a = {
290
- workflowName: t,
291
- executionId: n,
292
- subject: i.subject ?? null,
293
- traceId: i.traceId ?? null,
294
- source: i.source ?? null,
295
- parentExecutionId: i.parentExecutionId ?? null,
296
- parentClosePolicy: i.parentClosePolicy ?? null,
297
- createdAt: /* @__PURE__ */ new Date()
298
- };
299
- r[0] === void 0 ? await e.store.insert("_voltro_workflow_start_contexts", {
300
- id: re(),
301
- ...a
302
- }) : await e.store.update("_voltro_workflow_start_contexts", r[0].id, a);
303
- } catch (e) {
304
- process.stderr.write(`[workflow] failed to persist start context for ${t}/${n}: ${e?.message ?? String(e)}\n`);
305
- }
306
- }, ae = async (t, n) => {
307
- let r = h.get(n);
308
- if (r !== void 0) return r;
309
- try {
310
- let t = (await e.store.query({
311
- table: "_voltro_workflow_start_contexts",
312
- order: [],
313
- predicate: q("executionId", n),
314
- projection: void 0,
315
- skip: void 0,
316
- take: 1
317
- }))[0];
318
- if (t === void 0) return;
319
- let r = {
320
- ...t.subject === null ? {} : { subject: t.subject },
321
- ...t.traceId === null ? {} : { traceId: t.traceId },
322
- ...t.source === null ? {} : { source: t.source },
323
- ...t.parentExecutionId === null ? {} : { parentExecutionId: t.parentExecutionId },
324
- ...t.parentClosePolicy === null ? {} : { parentClosePolicy: t.parentClosePolicy }
325
- };
326
- return h.set(n, r), r;
327
- } catch (e) {
328
- process.stderr.write(`[workflow] failed to load start context for ${n}: ${e?.message ?? String(e)}\n`);
329
- return;
330
- }
331
- }, _ = (e.discovered.workflows?.length ?? 0) > 0 ? _n(() => s) : void 0, se = (e.discovered.workflows?.length ?? 0) > 0 || (e.discovered.eventTriggers?.length ?? 0) > 0, ue = se || (e.discovered.workflowWorkers?.length ?? 0) > 0 || e.scheduleCoordination === "cluster", de = e.tenantIsolation === "namespace", pe = (e.log ?? V({ scope: "voltro:serve" })).child("webhooks"), me, he, S = e.discovered.webhooks;
332
- if (S && S.outgoing.length > 0 && e.workflowEngineLayer !== void 0) {
333
- e.workflowEngineLayer;
334
- let t = je({
335
- store: e.store,
336
- schemaRegistry: e.schemaRegistry,
337
- cache: a,
338
- kv: o
339
- }), n = S.outgoing.map((e) => e.descriptor);
340
- he = Dr.toLayer(wr(t, { events: n })), me = Tr(t, async (e) => {
341
- let t = d;
342
- if (t === void 0) {
343
- pe.error("webhook delivery skipped — the workflow runtime was never built. This is a framework defect, not a configuration problem: report it with your engine setting. Deliveries are NOT queued and will not be retried.", {
344
- deliveryId: e.deliveryId,
345
- targetId: e.targetId
346
- });
347
- return;
348
- }
349
- t.runPromise(Dr.execute(e)).catch((t) => {
350
- pe.error("deliverWebhook workflow crashed", {
351
- deliveryId: e.deliveryId,
352
- targetId: e.targetId
353
- }, t);
354
- });
355
- }, { events: n });
356
- }
357
- let ve = /* @__PURE__ */ new Map();
358
- if (S) for (let e of S.incoming) {
359
- let t = e.descriptor.path ?? Er(e.descriptor.id), n = `VOLTRO_WEBHOOK_SECRET_${e.descriptor.id.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`, r = kr(e.descriptor, {
360
- resolveSecret: async () => process.env[n] ?? null,
361
- resolveWorkflows: () => _ === void 0 ? void 0 : G(_, {
362
- traceId: `incoming:${e.descriptor.id}`,
363
- source: `incoming:${e.descriptor.id}`
364
- }),
365
- log: (e) => {
366
- let t = {
367
- webhookId: e.webhookId,
368
- status: e.status,
369
- signatureOk: String(e.signatureOk),
370
- idempotency: e.idempotency,
371
- durationMs: e.durationMs
372
- };
373
- e.status >= 500 ? pe.error("incoming delivery failed", t) : e.status >= 400 ? pe.warn("incoming delivery rejected", t) : pe.info("incoming delivery handled", t);
374
- }
375
- });
376
- ve.set(t, { handle: r });
377
- }
378
- sn(), Ln((t) => cn(e.store, t.subjectId, t.resourceType, t.resourceId));
379
- let ye = [...e.discovered.outboxHandlers ?? [], ...dt((S?.outgoing.length ?? 0) + (S?.incoming.length ?? 0) + (S?.providers.length ?? 0), []) ? [{
380
- file: "<framework>/webhooks",
381
- id: "voltro-webhook-emit",
382
- definition: Or(() => me)
383
- }] : []], be = ye.length > 0 ? x({
384
- handlers: ye,
385
- store: e.store,
386
- log: (e.log ?? V({ scope: "voltro:serve" })).child("outbox")
387
- }) : void 0, C = Je({
388
- definitions: (e.discovered.connections ?? []).map((e) => e.definition),
389
- store: e.store,
390
- publicUrl: f(e.port ?? 4e3),
391
- log: (e.log ?? V({ scope: "voltro:serve" })).child("connections")
392
- });
393
- fe({
394
- events: e.discovered.events ?? [],
395
- rpcTags: [
396
- ...e.discovered.queries.map((e) => e.descriptor.name),
397
- ...e.discovered.mutations.map((e) => e.descriptor.name),
398
- ...e.discovered.actions.map((e) => e.descriptor.name),
399
- ...(e.discovered.streams ?? []).map((e) => e.descriptor.name)
400
- ]
401
- });
402
- let xe = (e.log ?? V({ scope: "voltro:serve" })).child("events"), Se = e.broadcastNamespace ?? ft(e.plugins, void 0), Ee = vt(e.plugins, Se, xe), Ae = e.membership?.instanceId ?? process.env.POD_NAME ?? process.env.HOSTNAME ?? `serve-${process.pid}`, Me = e.membership ?? Pe(e.plugins, {
403
- instanceId: Ae,
404
- namespace: Se,
405
- meta: { mode: "serve" },
406
- logger: xe
407
- }), T = b({
408
- events: e.discovered.events ?? [],
409
- origin: Ae,
410
- ...Ee.publishRemote === void 0 ? {} : { publishRemote: Ee.publishRemote }
411
- }), Ne = (e.discovered.events ?? []).length > 0 ? await Ee.attach(T.bus) : null, D = De({
412
- store: e.store,
413
- schemaRegistry: e.schemaRegistry,
414
- cache: a,
415
- kv: o,
416
- ...me === void 0 ? {} : { webhooksService: me },
417
- ..._ === void 0 ? {} : { workflowsProxy: _ },
418
- eventTriggers: e.discovered.eventTriggers ?? [],
419
- namespaceIsolationOn: de,
420
- ...be === void 0 ? {} : { outbox: { nudge: be.nudge } },
421
- ...C.active ? { connections: { registry: C.registry } } : {},
422
- eventBus: T.bus
423
- }), Le = B.succeed(Bt, Fe), Re = B.succeed(Ut, Qe), ze = B.succeed(Vt, rt), Ve = B.succeed(H, We), He = (t, n) => {
424
- let r = t.pipe(z.provide(gn(n)));
425
- return (e.baseLayer ? r.pipe(z.provide(e.baseLayer)) : r).pipe(z.provide(Le)).pipe(z.provide(Re)).pipe(z.provide(ze)).pipe(z.provide(Ve));
426
- }, Ue = (e, t) => Pn(He(e, t)), O = r(), k = ce(e.plugins ?? [], O), Ge = Te(e.plugins ?? [], O), qe = yn({
427
- store: e.store,
428
- recordMetric: (e) => {
429
- O.record(e);
430
- },
431
- ...k.mutation === void 0 ? {} : { interceptor: k.mutation },
432
- buildContext: (e, t, n) => D(e, t, n),
433
- runEffect: Ue,
434
- undoCapture: Oe()
435
- }), Ye = y(), Xe = ln({
436
- buildContext: (e) => D(e),
437
- runEffect: Ue,
438
- recordMetric: (e) => {
439
- O.record(e);
440
- },
441
- ...k.action === void 0 ? {} : { interceptor: k.action }
442
- }), Ze = Sn({
443
- tenantScopedTables: e.tenantScopedTables,
444
- softDeleteScopedTables: e.softDeleteScopedTables
445
- }), $e = {
446
- buildContext: (e) => D(e),
447
- finalize: (e, t) => Ze(e, t.subject),
448
- provideEffect: He,
449
- ...k.query === void 0 ? {} : { interceptor: k.query }
450
- }, A = xn($e), nt = bn({
451
- ...$e,
452
- queryRows: (t, n) => e.store.query(t).then((e) => Vn(t.table, e, n.subject))
453
- }), it = wn({
454
- ...$e,
455
- subscribeDescriptor: (e, t, n) => i.subscribe(e, t, n),
456
- subscribeComputed: (e, t, n) => i.subscribeComputed(e, t, n)
457
- }), j = (e) => e.filter((e) => ar(e.descriptor)), M = {};
458
- for (let t of [
459
- ...j(e.discovered.queries),
460
- ...Ye.queries,
461
- ...C.queries
462
- ]) M[t.descriptor.name] = (e) => W(A(t, e), i, `subscription.${t.descriptor.name}`, void 0, void 0, Cn(t, e));
463
- for (let t of [
464
- ...j(e.discovered.mutations),
465
- ...Ye.mutations,
466
- ...C.mutations
467
- ]) {
468
- let n = vn(t.descriptor.output);
469
- M[t.descriptor.name] = (r) => U(async (e, n) => qe(t, e, n), r, `mutation.${t.descriptor.name}`, n, e.idempotency, t.descriptor.error);
470
- }
471
- for (let t of [...j(e.discovered.actions), ...C.actions]) {
472
- let n = vn(t.descriptor.output);
473
- M[t.descriptor.name] = (r) => U(async (e, n) => Xe(t, e, n), r, `action.${t.descriptor.name}`, n, e.idempotency, t.descriptor.error);
474
- }
475
- let at = () => `public-${Math.random().toString(36).slice(2, 10)}`, ot = [
476
- ...e.discovered.queries.filter((e) => e.descriptor.publicApi !== void 0).map((e) => ({
477
- descriptor: e.descriptor,
478
- invoke: (t, n) => nt(e, t, {
479
- subject: n.subject,
480
- traceId: at()
481
- }),
482
- subscribe: (t, n, r) => it(e, t, {
483
- subject: n.subject,
484
- traceId: at()
485
- }, r)
486
- })),
487
- ...e.discovered.mutations.filter((e) => e.descriptor.publicApi !== void 0).map((e) => ({
488
- descriptor: e.descriptor,
489
- invoke: (t, n) => qe(e, t, {
490
- subject: n.subject,
491
- traceId: at()
492
- })
493
- })),
494
- ...e.discovered.actions.filter((e) => e.descriptor.publicApi !== void 0).map((e) => ({
495
- descriptor: e.descriptor,
496
- invoke: (t, n) => Xe(e, t, {
497
- subject: n.subject,
498
- traceId: at()
499
- })
500
- }))
501
- ], st = ot.length > 0 ? Mr(jr(ot), {
502
- store: e.store,
503
- resolveSubject: (t) => e.resolveSubject(t, -1)
504
- }) : [], ct = e.dataTransferSecret ?? process.env.VOLTRO_DATA_TRANSFER_SECRET, ut = ct && ct.length >= 16 ? [{
505
- method: "POST",
506
- path: Gr,
507
- handle: $r({
508
- secret: ct,
509
- store: e.store,
510
- ...e.dataTransferSnapshot ? { snapshot: e.dataTransferSnapshot } : {},
511
- assetSink: zr(Zn()),
512
- openArchive: (e) => ai(Zn(), e)
513
- })
514
- }, {
515
- method: "POST",
516
- path: Kr,
517
- handle: ri({
518
- secret: ct,
519
- store: e.store,
520
- snapshot: e.dataTransferSnapshot ?? { tables: [] },
521
- dialect: e.dataTransferDialect ?? "memory",
522
- tenantTables: [...e.tenantScopedTables],
523
- loadProfile: ii,
524
- assetSource: Br(Zn(), e.store),
525
- putArchive: async (e, t) => {
526
- let { Readable: n } = await import("node:stream"), r = Zn(), i = Qn("storage", () => n.from(t()));
527
- await z.runPromise(er(r, e, i, { contentType: "application/octet-stream" }));
528
- }
529
- })
530
- }] : [], pt = [
531
- ...e.httpRoutes ?? [],
532
- ...st,
533
- ...ut,
534
- ...C.httpRoutes
535
- ];
536
- Object.assign(M, T.handlers);
537
- for (let t of j(e.discovered.streams ?? [])) M[t.descriptor.name] = (n) => Xt((r) => {
538
- let i = D(r), a = t.executor(n, i);
539
- if (z.isEffect(a)) {
540
- let t = a.pipe(z.provide(gn(i.store)));
541
- return (e.baseLayer ? t.pipe(z.provide(e.baseLayer)) : t).pipe(z.provide(Le)).pipe(z.provide(Re)).pipe(z.provide(ze)).pipe(z.provide(Ve));
542
- }
543
- return typeof a == "object" && a && typeof a.then == "function" ? z.promise(() => a) : a;
544
- }, `stream.${t.descriptor.name}`);
545
- for (let t of e.discovered.workflows ?? []) M[t.definition.name] = (e) => U(async (e, n) => {
546
- let r = n;
547
- return G(_, {
548
- subject: r.subject,
549
- traceId: r.traceId,
550
- source: "workflow-rpc"
551
- }).start(t.definition.name, e);
552
- }, e, `workflow.${t.definition.name}`);
553
- se && (M[dr.name] = (e) => W(A({
554
- descriptor: dr,
555
- executor: (e) => {
556
- let t = e.id;
557
- return {
558
- table: "_voltro_workflow_runs",
559
- order: [{
560
- column: "startedAt",
561
- direction: "desc"
562
- }],
563
- predicate: Xn(q("id", t), q("executionId", t)),
564
- take: 1,
565
- skip: void 0,
566
- projection: void 0
567
- };
568
- }
569
- }, e), i, `subscription.${dr.name}`), M[pr.name] = (e) => W(A({
570
- descriptor: pr,
571
- executor: (e) => {
572
- let t = e, n = [...t.tag === void 0 ? [] : [q("tag", t.tag)], ...t.status === void 0 ? [] : [q("status", t.status)]], r = Number.isFinite(t.limit) && t.limit !== void 0 ? Math.min(Math.max(Math.floor(t.limit), 1), 500) : 100;
573
- return {
574
- table: "_voltro_workflow_runs",
575
- order: [{
576
- column: "startedAt",
577
- direction: "desc"
578
- }],
579
- predicate: n.length === 0 ? void 0 : n.length === 1 ? n[0] : Jn(...n),
580
- take: r,
581
- skip: void 0,
582
- projection: void 0
583
- };
584
- }
585
- }, e), i, `subscription.${pr.name}`), M[fr.name] = (e) => W(A({
586
- descriptor: fr,
587
- executor: (e) => {
588
- let t = e.runId;
589
- return {
590
- table: "_voltro_workflow_run_steps",
591
- order: [{
592
- column: "startedAt",
593
- direction: "asc"
594
- }],
595
- predicate: q("runId", t),
596
- take: 1e3,
597
- skip: void 0,
598
- projection: void 0
599
- };
600
- }
601
- }, e), i, `subscription.${fr.name}`), M[ur.name] = (e) => W(A({
602
- descriptor: ur,
603
- executor: (e) => {
604
- let t = e.runId;
605
- return {
606
- table: "_voltro_workflow_run_events",
607
- order: [{
608
- column: "occurredAt",
609
- direction: "asc"
610
- }],
611
- predicate: q("runId", t),
612
- take: 1e3,
613
- skip: void 0,
614
- projection: void 0
615
- };
616
- }
617
- }, e), i, `subscription.${ur.name}`), M[sr.name] = (e) => W(A({
618
- descriptor: sr,
619
- executor: (e) => {
620
- let t = e;
621
- return {
622
- table: "_voltro_workflow_events",
623
- order: [{
624
- column: "occurredAt",
625
- direction: "desc"
626
- }],
627
- predicate: t.name === void 0 ? void 0 : q("name", t.name),
628
- take: Math.max(1, Math.min(500, t.limit ?? 100)),
629
- skip: void 0,
630
- projection: void 0
631
- };
632
- }
633
- }, e), i, `subscription.${sr.name}`), M[cr.name] = (e) => W(A({
634
- descriptor: cr,
635
- executor: (e) => {
636
- let t = e.eventId;
637
- return {
638
- table: "_voltro_workflow_event_deliveries",
639
- order: [{
640
- column: "createdAt",
641
- direction: "asc"
642
- }],
643
- predicate: q("eventId", t),
644
- take: 500,
645
- skip: void 0,
646
- projection: void 0
647
- };
648
- }
649
- }, e), i, `subscription.${cr.name}`), M[Z.name] = (t) => U(async (t, n) => {
650
- let r = t;
651
- return await ke(e.store, n.subject, { executionId: r.executionId }), await _.cancel(r.workflowName, r.executionId), await Ct(r.workflowName, r.executionId, "workflow.cancel"), { ok: !0 };
652
- }, t, `action.${Z.name}`), M[lr.name] = (t) => U(async (t, n) => {
653
- let r = t;
654
- return await ke(e.store, n.subject, { executionId: r.executionId }), await _.resume(r.workflowName, r.executionId), { ok: !0 };
655
- }, t, `action.${lr.name}`), M[mr.name] = (t) => U(async (t, n) => {
656
- let r = t;
657
- return await ke(e.store, n.subject, { id: r.id }), _.signal({ id: r.id }, r.signalName, r.payload);
658
- }, t, `action.${mr.name}`), M[hr.name] = (t) => U(async (t, n) => {
659
- let r = t;
660
- return await ke(e.store, n.subject, { id: r.id }), _.update({ id: r.id }, r.updateName, r.payload, r.timeoutMs === void 0 ? void 0 : { timeoutMs: r.timeoutMs });
661
- }, t, `action.${hr.name}`));
662
- let mt = [
663
- ...j(e.discovered.queries).map((e) => X(e.descriptor)),
664
- ...j(e.discovered.mutations).map((e) => Y(e.descriptor)),
665
- ...j(e.discovered.actions).map((e) => J(e.descriptor)),
666
- ...Ye.queries.map((e) => X(e.descriptor)),
667
- ...Ye.mutations.map((e) => Y(e.descriptor)),
668
- ...C.queries.map((e) => X(e.descriptor)),
669
- ...C.mutations.map((e) => Y(e.descriptor)),
670
- ...C.actions.map((e) => J(e.descriptor)),
671
- ...j(e.discovered.streams ?? []).map((e) => or(e.descriptor)),
672
- ...T.rpcs,
673
- ...(e.discovered.workflows ?? []).map((e) => Un(e.definition)),
674
- ...se ? [
675
- X(dr),
676
- X(pr),
677
- X(fr),
678
- X(ur),
679
- X(sr),
680
- X(cr),
681
- J(Z),
682
- J(lr),
683
- J(mr),
684
- J(hr)
685
- ] : []
686
- ], gt = Gn.make(...mt).middleware(nr).middleware(rr), _t = B.succeed(nr, nr.of(({ headers: t, clientId: n }) => z.promise(() => e.resolveSubject(t, n)))), yt = B.succeed(rr, rr.of(({ headers: e, clientId: t }) => z.sync(() => {
687
- let n = on(t) ?? vr(e);
688
- return {
689
- clientId: t,
690
- ...e["idempotency-key"] ? { idempotencyKey: e["idempotency-key"] } : {},
691
- ...n === void 0 ? {} : { credentialExpiresAt: n }
692
- };
693
- }))), bt = e.dormancyTenantId ?? "default", xt = e.dormancy === "sleep" ? {
694
- register: (t, n, r) => Mn(e.store, {
695
- tenantId: r ?? bt,
696
- kind: "workflow",
697
- refId: t,
698
- wakeAt: n
699
- }),
700
- cancel: (t, n) => Qt(e.store, {
701
- tenantId: n ?? bt,
702
- kind: "workflow",
703
- refId: t
704
- }).then(() => {})
705
- } : void 0, P = ue ? await import("@voltro/workflow") : void 0, F = P?.makeWorkflowRunRecorder({
706
- store: e.store,
707
- ...xt === void 0 ? {} : { wakeups: xt }
708
- }), St = async (t, n) => {
709
- await P.closeWorkflowChildrenForParent({
710
- store: e.store,
711
- parentExecutionId: t,
712
- parentStatus: n,
713
- recorder: F,
714
- log: { warn: (e, t) => {
715
- process.stderr.write(`[workflow] ${e} ${t ? JSON.stringify(t) : ""}\n`);
716
- } },
717
- interruptChild: async (t, n) => {
718
- let r = (e.discovered.workflows ?? []).find((e) => e.definition.name === t);
719
- if (!r) throw Error(`Unknown child workflow: ${t}`);
720
- if (!d) throw Error("Workflow runtime is not ready");
721
- await d.runPromise(r.definition.interrupt(n));
722
- }
723
- });
724
- }, Ct = async (t, n, r) => {
725
- let i = (await e.store.query({
726
- table: "_voltro_workflow_runs",
727
- order: [],
728
- predicate: q("executionId", n),
729
- projection: void 0,
730
- skip: void 0,
731
- take: 1
732
- }))[0];
733
- if (i === void 0) return;
734
- let a = await e.store.update("_voltro_workflow_runs", i.id, {
735
- status: "cancelled",
736
- cancelled: !0,
737
- completedAt: /* @__PURE__ */ new Date()
738
- }), o = i.subject?.tenantId ?? void 0;
739
- a && await F.recordEvent({
740
- runId: i.id,
741
- eventType: "run-cancelled",
742
- payload: {
743
- reason: r,
744
- workflowName: t,
745
- executionId: n,
746
- ...o == null ? {} : { tenantId: o }
747
- }
748
- }), a && await St(n, "cancelled");
749
- }, wt = [
750
- ...Dn(e.discovered.workflows ?? [], {
751
- buildContext: (t, n) => e.buildContextForWorkflow?.(t, n) ?? D({
752
- subject: t.subject,
753
- traceId: t.traceId
754
- }, e.store, void 0, `workflow:${n.workflowName}`, { parentExecutionId: n.executionId }),
755
- resolveStartContext: ae
756
- }, (t, n, r) => {
757
- let i = P.getWorkflowVersionMetadata(t.definition);
758
- return P.wrapWorkflowExecuteWithRunRecording({
759
- name: t.definition.name,
760
- store: e.store,
761
- subject: r.subject,
762
- source: r.source ?? null,
763
- traceId: r.traceId,
764
- workflowVersion: i.version,
765
- workflowCompatibleVersions: i.compatibleWith,
766
- workflowPatches: i.patches,
767
- parentExecutionId: r?.parentExecutionId ?? null,
768
- parentClosePolicy: r?.parentClosePolicy ?? null,
769
- onParentClose: ({ executionId: e, status: t }) => St(e, t),
770
- ...lt(t.definition),
771
- onTerminal: async ({ executionId: e }) => {
772
- await u?.gate.release(e);
773
- },
774
- recorder: F,
775
- pluginWorkflowStepLayer: Ge,
776
- recordRun: jn
777
- }, n);
778
- }),
779
- ...e.discovered.workflowWorkers ?? [],
780
- ...he === void 0 ? [] : [he]
781
- ], Tt = [...(e.discovered.workflows ?? []).map((e) => e.definition.name).filter(Boolean), ...he === void 0 ? [] : ["voltro.deliverWebhook"]], Et = wt.length > 0 ? B.mergeAll(...wt) : B.empty;
782
- if (((e.discovered.workflows?.length ?? 0) > 0 || (e.discovered.workflowWorkers?.length ?? 0) > 0 || e.scheduleCoordination === "cluster" || he !== void 0) && e.workflowEngineLayer !== void 0) {
783
- let t = Et.pipe(B.provideMerge(e.workflowEngineLayer));
784
- d = Rt.make(e.baseLayer === void 0 ? t : t.pipe(B.provideMerge(e.baseLayer))), await d.runPromise(z.void), (e.log ?? V({ scope: "voltro:serve" })).child("workflow").info(`workflow runtime ready — ${Tt.length} entity type(s) registered`, { entities: Tt });
785
- let n = await import("@voltro/workflow/cluster"), r = (e) => d.runPromise(n.redriveFailedRun(e)), i = (e) => d.runPromise(n.resumeRunFromStep(e));
786
- ne = await tt({
787
- provider: Fr(e.plugins ?? [])?.broadcast?.provider,
788
- crossReplica: Fr(e.plugins ?? [])?.broadcast?.crossReplica ?? !1,
789
- namespace: Se,
790
- replicaId: crypto.randomUUID(),
791
- pollStorage: () => d.runPromise(n.pollWorkflowStorage),
792
- log: (e.log ?? V({ scope: "voltro:serve" })).child("workflow")
793
- }), ee = async (t) => {
794
- let n = await we({
795
- store: e.store,
796
- workflows: e.discovered.workflows ?? [],
797
- runRedrive: r
798
- }, t.runId);
799
- return n.statusReset && await F.recordEvent({
800
- runId: t.runId,
801
- eventType: "run-redriven",
802
- payload: {
803
- reason: "inspect.redrive",
804
- activitiesReset: n.outcome.activitiesReset
805
- }
806
- }), {
807
- redriven: n.outcome.redriven,
808
- activitiesReset: n.outcome.activitiesReset,
809
- reason: n.outcome.reason
810
- };
811
- }, te = async (t) => {
812
- let n = await oe({
813
- store: e.store,
814
- workflows: e.discovered.workflows ?? [],
815
- runResume: i
816
- }, t.runId, t.step);
817
- return n.statusReset && await F.recordEvent({
818
- runId: t.runId,
819
- eventType: "run-redriven",
820
- payload: {
821
- reason: "inspect.resume-from-step",
822
- step: n.stepName,
823
- activitiesReset: n.outcome.activitiesReset
824
- }
825
- }), {
826
- redriven: n.outcome.redriven,
827
- stepName: n.stepName,
828
- activitiesReset: n.outcome.activitiesReset,
829
- reason: n.outcome.reason
830
- };
831
- };
832
- let a = hn({
833
- coordinator: (e.scheduleCoordination ?? "single") === "advisoryLock" ? un(e.store, e.scheduleReplicaId ?? `pid-${process.pid}`) : Rn,
834
- replicaId: e.scheduleReplicaId ?? `pid-${process.pid}`
835
- }), o = {
836
- info: (e, t) => {
837
- process.stdout.write(`[flow-control] ${e} ${t ? JSON.stringify(t) : ""}\n`);
838
- },
839
- warn: (e, t) => {
840
- process.stderr.write(`[flow-control] ${e} ${t ? JSON.stringify(t) : ""}\n`);
841
- },
842
- error: (e, t) => {
843
- process.stderr.write(`[flow-control] ERROR ${e} ${t ? JSON.stringify(t) : ""}\n`);
844
- }
845
- }, f, m = () => {
846
- if (f !== void 0) return f;
847
- if (!(s === void 0 || F === void 0)) return f = g({
848
- store: e.store,
849
- log: R,
850
- workflows: e.discovered.workflows ?? [],
851
- workflowsProxy: s,
852
- workflowRuntime: d,
853
- workflowRunRecorder: F,
854
- closeChildrenForParent: St
855
- }), f;
856
- };
857
- c = m, u = Ie({
858
- store: e.store,
859
- workflows: e.discovered.workflows ?? [],
860
- facade: () => s,
861
- cancelRunWithReason: m,
862
- scheduleCoordinated: a,
863
- onAbandoned: async (t) => {
864
- await Be({
865
- workflows: e.discovered.workflows ?? [],
866
- facade: () => s,
867
- log: o,
868
- ...t
869
- });
870
- },
871
- log: o
872
- });
873
- let h = u;
874
- h !== void 0 && On(() => h.stop()), l = E({
875
- store: e.store,
876
- enabled: (e.discovered.workflows?.length ?? 0) > 0,
877
- resumeSignal: () => d === void 0 || P === void 0 ? void 0 : async ({ executionId: t, workflowName: n, signalName: r, payload: i }) => {
878
- await d.runPromise(P.completeSuspendingSignal({
879
- store: e.store,
880
- target: Ke(t, n),
881
- signalName: r,
882
- payload: i
883
- }));
884
- },
885
- runEffect: (e) => d.runPromise(e),
886
- scheduleCoordinated: a,
887
- log: o
888
- });
889
- let re = l;
890
- re !== void 0 && On(() => re.stop()), s = (e.discovered.workflows?.length ?? 0) > 0 ? En({
891
- workflows: e.discovered.workflows ?? [],
892
- runEffect: (e) => d.runPromise(e),
893
- onEnqueue: () => ne?.publishWake(),
894
- ...h === void 0 ? {} : {
895
- admitStart: h.gate.admitStart,
896
- startPayloadSchema: h.gate.startPayloadSchema
897
- },
898
- rememberStartContext: ie,
899
- signal: async (t, n, r) => {
900
- let i = await P.sendWorkflowSignal({
901
- store: e.store,
902
- recorder: F,
903
- target: t,
904
- signalName: n,
905
- payload: r
906
- });
907
- return await d.runPromise(P.completeSuspendingSignal({
908
- store: e.store,
909
- target: t,
910
- signalName: n,
911
- payload: r
912
- })).catch(() => {}), i;
913
- },
914
- update: (t, n, r, i) => P.sendWorkflowUpdate({
915
- store: e.store,
916
- recorder: F,
917
- target: t,
918
- updateName: n,
919
- payload: r,
920
- ...i === void 0 ? {} : { options: i }
921
- }),
922
- listRuns: (t) => p(e.store, t),
923
- retry: (t, n) => w({
924
- store: e.store,
925
- workflows: e.discovered.workflows ?? [],
926
- runPromise: (e) => d.runPromise(e)
927
- }, t, n),
928
- redrive: (t) => we({
929
- store: e.store,
930
- workflows: e.discovered.workflows ?? [],
931
- runRedrive: r
932
- }, t).then((e) => e.outcome)
933
- }) : void 0;
934
- }
935
- let Dt = B.mergeAll(gt.toLayer(M), _t, yt), Ot = le(M, e.discovered.queries.map((e) => e.descriptor.name), se), kt = B.mergeAll(gt.toLayer(Ot), _t, yt), I = e.observability, At = await Zt({
936
- ...e.appName === void 0 ? {} : { serviceName: e.appName },
937
- ...I && I.spanProcessors.length > 0 ? { extraSpanProcessors: I.spanProcessors } : {},
938
- ...I && I.metricReaders.length > 0 ? { extraMetricReaders: I.metricReaders } : {},
939
- ...I && Object.keys(I.resourceAttributes).length > 0 ? { resourceAttributes: I.resourceAttributes } : {},
940
- ...I && I.sampler !== void 0 ? { sampler: I.sampler } : {}
941
- }), jt = !1, Mt = e.store.ping ? () => e.store.ping().then(() => !0).catch(() => !1) : void 0, { server: L, shutdown: Nt } = zn({
942
- group: gt,
943
- handlersLayer: Dt,
944
- httpHandlersLayer: kt,
945
- port: e.port ?? 4e3,
946
- ...e.host === void 0 ? {} : { host: e.host },
947
- path: e.path ?? "/ws",
948
- tracerLayer: At.layer,
949
- healthCheck: {
950
- isReady: () => jt,
951
- ...Mt ? { ping: Mt } : {}
952
- },
953
- ...pt.length > 0 ? { httpRoutes: pt } : {},
954
- ...e.getStore === void 0 ? {} : { getStore: e.getStore },
955
- ...ve.size > 0 ? { webhookRoutes: ve } : {},
956
- ...e.inspectRoute === void 0 ? {} : { inspectRoute: e.inspectRoute }
957
- });
958
- if (await Yt(L), (e.discovered.schedules?.length ?? 0) > 0) {
959
- let t = (e.scheduleCoordination ?? "single") === "advisoryLock" ? un(e.store, e.scheduleReplicaId ?? `pid-${process.pid}`) : Rn;
960
- m = await Bn(e.discovered.schedules ?? [], {
961
- store: e.store,
962
- coordinator: t,
963
- defaultTrigger: e.scheduleDefaultTrigger ?? "self",
964
- replicaId: e.scheduleReplicaId ?? `pid-${process.pid}`,
965
- armSelf: e.scheduleArmSelf ?? !0,
966
- dormancy: e.dormancy ?? "always-on",
967
- ...e.dormancyTenantId === void 0 ? {} : { dormancyTenantId: e.dormancyTenantId },
968
- buildContext: ({ traceId: t, scheduleName: n, subject: r }) => D({
969
- subject: r,
970
- traceId: t
971
- }, e.store, void 0, `schedule:${n}`),
972
- log: {
973
- info: (e, t) => {
974
- process.stdout.write(`[schedule] ${e} ${t ? JSON.stringify(t) : ""}\n`);
975
- },
976
- warn: (e, t) => {
977
- process.stderr.write(`[schedule] ${e} ${t ? JSON.stringify(t) : ""}\n`);
978
- },
979
- error: (e, t) => {
980
- process.stderr.write(`[schedule] ERROR ${e} ${t ? JSON.stringify(t) : ""}\n`);
981
- },
982
- debug: () => {}
983
- },
984
- ...e.scheduleFireInterceptor === void 0 ? {} : { interceptFire: e.scheduleFireInterceptor },
985
- ...e.onScheduleRunEvent === void 0 ? {} : { onRunEvent: e.onScheduleRunEvent }
986
- }), e.onSchedulerReady?.(m);
987
- }
988
- let R = e.log ?? V({ scope: "voltro:serve" }), Pt, Ft;
989
- if ((e.discovered.subscribers?.length ?? 0) > 0 && (Pt = _e(e.discovered.subscribers ?? [], e.store, R.child("subscribe"), e.schemaRegistry, T.bus)), (e.discovered.reactions?.length ?? 0) > 0) {
990
- let t = R.child("reaction"), n = async (n, r) => {
991
- if (n.kind === "workflow") {
992
- if (_ === void 0) {
993
- t.warn("reaction workflow act skipped — no workflow engine in this app", { workflow: n.workflow });
994
- return;
995
- }
996
- let e = n.payload === void 0 ? r.new ?? r.old ?? {} : n.payload(r);
997
- await G(_, {
998
- traceId: `reaction:${n.workflow}`,
999
- source: `reaction:${n.workflow}`
1000
- }).start(n.workflow, e);
1001
- return;
1002
- }
1003
- await Ce(n.agent, r, {
1004
- findAgentSend: (t) => e.discovered.actions.find((e) => e.descriptor.name === `${t}.send`),
1005
- runAction: (e, t, n) => Promise.resolve(Xe(e, t, n)),
1006
- makeSubject: (e) => ir(e),
1007
- now: () => Date.now(),
1008
- log: t
1009
- });
1010
- }, r = async (n, r) => {
1011
- try {
1012
- let { requireAiBudget: t } = await import("@voltro/ai");
1013
- return (await z.runPromise(z.either(t(e.store, {
1014
- tenantId: n,
1015
- limitUsd: r
1016
- }))))._tag === "Right";
1017
- } catch (e) {
1018
- return t.warn("reaction budget check failed — refusing the act", { tenantId: n }, e), !1;
1019
- }
1020
- }, i = et(e.store, { onError: (e) => t.warn("reaction: rate-slot claim failed; refusing the act", { cause: String(e) }) });
1021
- Ft = ht(e.discovered.reactions ?? [], e.store, {
1022
- runAct: n,
1023
- checkBudget: r,
1024
- claimRateSlot: (e) => i.claim(e)
1025
- }, t);
1026
- }
1027
- let It;
1028
- (e.discovered.aggregates?.length ?? 0) > 0 && (It = await N({
1029
- discovered: e.discovered.aggregates ?? [],
1030
- store: e.store,
1031
- log: R.child("aggregate"),
1032
- ...e.analytics === void 0 ? {} : { analytics: e.analytics },
1033
- ...e.aggregateStorage === void 0 ? {} : { storage: e.aggregateStorage },
1034
- ...e.aggregateCoordinator === void 0 ? {} : { coordinator: e.aggregateCoordinator }
1035
- }), Le = B.succeed(Bt, It.registry));
1036
- let Lt;
1037
- (e.discovered.expectations?.length ?? 0) > 0 && (Lt = Kt({
1038
- discovered: e.discovered.expectations ?? [],
1039
- store: e.store,
1040
- log: R.child("expectation")
1041
- }), Re = B.succeed(Ut, Lt.registry)), (e.discovered.budgets?.length ?? 0) > 0 && (n = Jt({
1042
- discovered: e.discovered.budgets ?? [],
1043
- log: R.child("finops")
1044
- }), ze = B.succeed(Vt, n.registry));
1045
- let zt;
1046
- return (e.discovered.experiments?.length ?? 0) > 0 && (zt = qt({
1047
- discovered: e.discovered.experiments ?? [],
1048
- store: e.store,
1049
- log: R.child("experiment")
1050
- }), Ve = B.succeed(H, zt.registry)), jt = !0, e.bootTiming?.mark("ready"), {
1051
- dispatcher: i,
1052
- server: L,
1053
- scheduler: m,
1054
- eventsSnapshot: ge(T.bus, T.declared),
1055
- membersSnapshot: () => ({
1056
- members: Me.membership.list(),
1057
- capturedAt: Date.now()
1058
- }),
1059
- rpcMetrics: () => O,
1060
- webhooksService: () => me,
1061
- runCanceller: () => c(),
1062
- flowControlHealth: () => u?.cancelHealth(),
1063
- inferenceHealth: () => l?.health(),
1064
- workflowWriteActions: () => _ === void 0 || F === void 0 ? void 0 : v({
1065
- store: e.store,
1066
- log: R,
1067
- workflows: e.discovered.workflows ?? [],
1068
- workflowsProxy: s,
1069
- workflowRuntime: d,
1070
- workflowRunRecorder: F,
1071
- closeChildrenForParent: St
1072
- }),
1073
- redriveWorkflowRun: (e) => ee ? ee(e) : Promise.reject(/* @__PURE__ */ Error("redrive: this app registers no workflows")),
1074
- resumeWorkflowRunFromStep: (e) => te ? te(e) : Promise.reject(/* @__PURE__ */ Error("resume-from-step: this app registers no workflows")),
1075
- close: async () => {
1076
- jt = !1, await Ne?.detach(), await Me.detach(), It?.detach(), Lt?.detach(), n?.detach(), zt?.detach(), Ft?.(), Pt?.(), await m?.shutdown(), i.close(), await ne?.detach(), await d?.dispose(), await new Promise((e) => L.close(() => e())), await Nt();
1077
- }
1078
- };
1079
- }, $ = V({ scope: "voltro:serve" }), ci = (e, t, n) => (e === "production" || e === "staging") && t !== "memory" && n !== "0", li = R, ui = async (e) => {
1080
- let t = L(process.cwd());
1081
- if (zt(t)) {
1082
- let n;
1083
- try {
1084
- let e = await import(It(t).href);
1085
- typeof e.runServe == "function" ? n = e.runServe : $.warn("serve bundle has no runServe export — using the standard serve path");
1086
- } catch (e) {
1087
- $.warn("serve bundle failed to load — using the standard serve path", {}, e);
1088
- }
1089
- if (n) return $.info("serve: booting from the precompiled serve bundle"), n(e);
1090
- }
1091
- return di(e);
1092
- }, di = async (f) => {
1093
- let p = Nt();
1094
- process.env.NODE_ENV || (process.env.NODE_ENV = "production");
1095
- try {
1096
- _r();
1097
- } catch (e) {
1098
- throw n(e instanceof Error ? e.message : String(e));
1099
- }
1100
- let g = process.cwd(), oe = Number(process.env.PORT ?? li(f, "--port") ?? 4e3), v = await D(g);
1101
- Fn(Nn(v?.secrets)), await e({
1102
- rawEnv: v?.env,
1103
- appType: "api",
1104
- root: g,
1105
- log: $,
1106
- generateTypes: !1
1107
- }), p.mark("config");
1108
- let y = (process.env.DB_DIALECT ?? v?.store ?? "memory").toLowerCase(), ce = (y === "mariadb" || y === "postgres" || y === "mssql") && (process.env.CDC ?? "1") !== "0", le = y === "mariadb" ? "mariadb" : y === "mssql" ? "mssql" : void 0, fe = Mt(g);
1109
- if (!c() && zt(fe)) try {
1110
- let e = await import(It(fe).href);
1111
- if (e.modules) {
1112
- let t = {};
1113
- for (let [n, r] of Object.entries(e.modules)) t[Ft(g, n)] = r;
1114
- s(t), $.info("precompiled api bundle loaded", { modules: Object.keys(t).length });
1115
- }
1116
- } catch (e) {
1117
- $.warn("precompiled api bundle failed to load — falling back to source", {}, e);
1118
- }
1119
- let b = await O(g), x = await ut(b, { cdc: ce && le !== void 0 });
1120
- {
1121
- let e = /* @__PURE__ */ new Set([
1122
- ...x.queries.filter((e) => e.descriptor.overridesPlugin === !0).map((e) => e.descriptor.name),
1123
- ...x.mutations.filter((e) => e.descriptor.overridesPlugin === !0).map((e) => e.descriptor.name),
1124
- ...x.actions.filter((e) => e.descriptor.overridesPlugin === !0).map((e) => e.descriptor.name)
1125
- ]);
1126
- wt(bt(v?.plugins ?? []), [
1127
- ...x.queries.map((e) => e.descriptor.name),
1128
- ...x.mutations.map((e) => e.descriptor.name),
1129
- ...x.actions.map((e) => e.descriptor.name),
1130
- ...x.streams.map((e) => e.descriptor.name)
1131
- ], e);
1132
- let t = Xe(x.serverOnlyLeaks, he(process.env, "strict"), nn, "`voltro serve`");
1133
- if (t.action === "fail") throw n(t.message ?? "");
1134
- t.action === "warn" && $.warn(t.message ?? "");
1135
- }
1136
- let ge = b.filter((e) => Ze.test(e)), _e = ge.length > 0 ? await Re(ge, $.child("webhooks")) : {
1137
- outgoing: [],
1138
- incoming: [],
1139
- providers: []
1140
- }, Ce = Ve(x.events), w = _e.outgoing.length + _e.incoming.length + _e.providers.length + Ce.length === 0 ? void 0 : {
1141
- ..._e,
1142
- outgoing: [..._e.outgoing, ...Ce]
1143
- }, we = Ct({
1144
- mix: x.featureMix,
1145
- plugins: v?.plugins ?? [],
1146
- cdc: ce && le !== void 0,
1147
- ...le ? { cdcDialect: le } : {}
1148
- }), Te = v?.analytics !== void 0 && v.analytics.kind !== "noop" && y !== "memory" ? (await a(y)).makeSqlLayer(A()) : void 0, De = await be({
1149
- spec: v?.analytics,
1150
- sqlLayer: Te,
1151
- log: $
1152
- }), Oe = (() => {
1153
- let e = new Set(x.tables.map((e) => e.tableName)), t = [...x.tables];
1154
- for (let n of [...we, ...De.tables]) e.has(n.tableName) || (e.add(n.tableName), t.push(n));
1155
- return t;
1156
- })();
1157
- for (let e of Oe) Yn(e);
1158
- {
1159
- let e = rn(Hn(x.queries.map((e) => ({
1160
- name: e.descriptor.name,
1161
- source: e.descriptor.source
1162
- })), new Set(Oe.flatMap((e) => {
1163
- let t = e.tableName;
1164
- return t === void 0 ? [] : [t];
1165
- }))));
1166
- e !== void 0 && $.warn(e);
1167
- }
1168
- let ke = (process.env.NODE_ENV ?? "").toLowerCase();
1169
- if (ci(ke, y, process.env.VOLTRO_AUTO_MIGRATE)) {
1170
- let e = (await a(y)).makeSqlLayer(A()), t = await z.runPromise(Kn.SqlClient.pipe(z.flatMap((e) => Cr(e, Oe, {
1171
- appliedBy: `serve:${ke}`,
1172
- environment: "prod",
1173
- dialectId: y
1174
- })), z.provide(e)));
1175
- t.kind === "prod-mismatch" && ($.error(Sr(t, y)), $.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(Sr(t, y));
1176
- }
1177
- let je = Tn(Oe);
1178
- p.mark("discover");
1179
- let E = await k(v, void 0), Fe = Wn(E, y);
1180
- for (let e of $e({
1181
- dialect: String(v?.store ?? process.env.DB_DIALECT ?? "postgres"),
1182
- changeStrategy: (process.env.CDC ?? "1") === "0" ? "inline" : "cdc",
1183
- dbUrl: process.env.DB_URL,
1184
- tables: x.tables.map((e) => ({
1185
- tableName: e.tableName,
1186
- isReactive: e.isReactive === !0
1187
- })),
1188
- querySources: x.queries.flatMap((e) => {
1189
- let t = e.descriptor.source;
1190
- return t === void 0 ? [] : typeof t == "string" ? [t] : [...t];
1191
- })
1192
- })) e.level === "warn" ? $.warn(e.message) : $.info(e.message);
1193
- {
1194
- let e = ct(ze({
1195
- tables: qn().map((e) => ({ tableName: e.tableName })),
1196
- queries: x.queries.map((e) => ({
1197
- name: e.descriptor.name,
1198
- source: e.descriptor.source
1199
- }))
1200
- }));
1201
- e !== void 0 && $.warn(e);
1202
- }
1203
- v?.cache && !process.env.CACHE_BACKEND && (process.env.CACHE_BACKEND = v.cache), v?.cacheRedisUrl && !process.env.CACHE_REDIS_URL && (process.env.CACHE_REDIS_URL = v.cacheRedisUrl), v?.cacheRedisDriver && !process.env.CACHE_REDIS_DRIVER && (process.env.CACHE_REDIS_DRIVER = v.cacheRedisDriver), v?.cacheKeyPrefix && !process.env.CACHE_KEY_PREFIX && (process.env.CACHE_KEY_PREFIX = v.cacheKeyPrefix);
1204
- let { service: Ie, invalidationBus: Be, snapshotCache: We, cache: Ke, semantic: Je, evictSource: Qe, backend: et, stats: tt, dispose: rt } = await u({
1205
- env: process.env,
1206
- semantic: v?.cacheSemantic ?? !1
1207
- });
1208
- Je !== void 0 && $.info("semantic cache enabled — reactive eviction on live writes"), $.info(`cache backend resolved: ${et}` + (et === "redis" ? ` (driver ${process.env.CACHE_REDIS_DRIVER ?? "resp"})` : " — in-process, not cross-instance")), E.onChange((e) => {
1209
- if (z.runFork(Be.publish(e.table)), Qe !== void 0) {
1210
- let t = (e.new ?? e.old)?.id;
1211
- Qe({
1212
- table: e.table,
1213
- op: e.op,
1214
- ...t === void 0 ? {} : { id: t }
1215
- });
1216
- }
1217
- }), v?.kv && !process.env.KV_BACKEND && (process.env.KV_BACKEND = v.kv), v?.kvRedisUrl && !process.env.KV_REDIS_URL && (process.env.KV_REDIS_URL = v.kvRedisUrl), v?.kvKeyPrefix && !process.env.KV_KEY_PREFIX && (process.env.KV_KEY_PREFIX = v.kvKeyPrefix);
1218
- let { kv: lt, service: dt } = await mn({ store: E });
1219
- $.info(Ur(Le(), Wr())), p.mark("store");
1220
- let ht = Gt({
1221
- store: E,
1222
- sink: De.sink,
1223
- log: $
1224
- }), vt = ve({
1225
- store: E,
1226
- dialect: y,
1227
- log: { info: (e) => $.info(e) }
1228
- }), N = v?.plugins ?? [], L = process.env.POD_NAME ?? process.env.HOSTNAME ?? `serve-${process.pid}`, R, V;
1229
- y !== "memory" && (R = Rt.make((await a(y)).makeSqlLayer(A())), V = await R.runPromise(Kn.SqlClient));
1230
- let Bt = hn({
1231
- coordinator: [
1232
- "postgres",
1233
- "mariadb",
1234
- "mysql",
1235
- "mssql"
1236
- ].includes(y) ? un(E, L, $) : Rn,
1237
- replicaId: L,
1238
- log: $
1239
- }), Vt = [], Ht = process.env.POD_NAME ?? process.env.HOSTNAME ?? `serve-${process.pid}`, Ut = Fr(v?.plugins ?? [])?.broadcast?.provider, H = ft(v?.plugins, v?.name ?? Pt(g));
1240
- {
1241
- let e = Me(v?.plugins, v?.name ?? Pt(g));
1242
- e !== void 0 && $.warn(e);
1243
- }
1244
- let Kt = Pe(v?.plugins, {
1245
- instanceId: Ht,
1246
- namespace: H,
1247
- meta: { mode: "serve" },
1248
- logger: $
1249
- }), qt = {
1250
- ...V ? { sql: V } : {},
1251
- instanceId: Ht,
1252
- membership: Kt.membership,
1253
- ...Ut === void 0 ? {} : { broadcast: Ut },
1254
- broadcastChannels: { presence: Pr(H, "presence") },
1255
- scheduleCoordinated: (e, t, n) => {
1256
- let r = Bt(e, t, n);
1257
- return Vt.push(r), r;
1258
- }
1259
- };
1260
- for (let e of N) e.bindDataStore?.(E, qt);
1261
- qe({
1262
- store: E,
1263
- ...d(),
1264
- log: $
1265
- });
1266
- let Jt = N.filter((e) => typeof e.onChangeEvent == "function");
1267
- if (Jt.length > 0) {
1268
- let e = E.changeScope ?? "local";
1269
- E.onChange((t) => {
1270
- let n = h(t, e);
1271
- for (let e of Jt) z.runFork(e.onChangeEvent(n).pipe(z.catchAllCause((t) => z.sync(() => $.warn(`plugin ${e.name} onChangeEvent failed`, { error: Lt.pretty(t) })))));
1272
- });
1273
- }
1274
- let Yt = it({
1275
- plugins: N,
1276
- appName: v?.name ?? "voltro-api",
1277
- appType: "api",
1278
- voltroVersion: process.env.npm_package_version ?? "0.0.0",
1279
- log: $
1280
- });
1281
- N.length && await Yt.activate(), p.mark("plugins");
1282
- let U = await Yt.gatherObservability(), Xt = {
1283
- info: (e, t) => process.stdout.write(`[broadcast] ${e} ${t ? JSON.stringify(t) : ""}\n`),
1284
- warn: (e, t) => process.stderr.write(`[broadcast] ${e} ${t ? JSON.stringify(t) : ""}\n`),
1285
- debug: () => {}
1286
- }, W, Zt = await He(E, v, y, H, Xt, (e, t) => {
1287
- W?.refreshAll(`broadcast gap: missed ${t} change(s) from ${e}`);
1288
- }), Qt = v?.apiKeys, on = (typeof Qt == "object" ? Qt.prefix : void 0) ?? "voltro_", sn = Qt ? en(E) : void 0, cn = sn ? fn({ flush: pn(sn) }) : void 0;
1289
- cn && On(() => cn.shutdown());
1290
- let ln = sn ? dn(sn, {
1291
- prefix: on,
1292
- ...cn ? { usage: cn } : {}
1293
- }) : void 0, gn = ln ? [an(ln, { prefix: on })] : [], _n = M([...v?.auth?.strategies ?? [], ...gn], Ar(v?.plugins ?? []), v?.auth?.anonymousTenantRequired ?? !1, v?.auth?.resolveScopes, () => Fe), vn = [...v?.restRoutes ?? [], ...ln ? Wt(ln, (typeof Qt == "object" ? Qt.managementPath : void 0) ?? "/v1/api-keys") : []], yn = v?.idempotency, bn = yn ? {
1294
- store: tn(E),
1295
- header: (typeof yn == "object" ? yn.header : void 0) ?? "Idempotency-Key",
1296
- ttlMs: (typeof yn == "object" ? yn.ttlMs : void 0) ?? 864e5
1297
- } : void 0, xn = vn.length > 0 ? Mr(vn, {
1298
- store: E,
1299
- resolveSubject: async (e) => (await _n({
1300
- headers: e,
1301
- clientId: -1
1302
- })).subject,
1303
- ...bn ? { idempotency: bn } : {}
1304
- }) : [], Sn = N.map((e) => e.services).filter((e) => e !== void 0), Cn = B.mergeAll(se({
1305
- analyticsLayer: De.layer,
1306
- cacheService: Ie,
1307
- kvService: dt,
1308
- ...Je === void 0 ? {} : { semanticCache: Je },
1309
- pluginServices: Sn,
1310
- userLayers: v?.layers ?? []
1311
- }), j(v?.http ?? {})), wn = v?.scheduling ?? {}, En = wn.trigger ?? "self", G = /* @__PURE__ */ new Set([
1312
- "postgres",
1313
- "mysql",
1314
- "mariadb",
1315
- "mssql"
1316
- ]), Dn = wn.coordination ?? (G.has(y) ? "advisoryLock" : "single"), K = Dn === "cluster" && G.has(y), An = K ? "cluster" : Dn === "advisoryLock" && G.has(y) ? "advisoryLock" : "single";
1317
- Dn === "cluster" && !K && $.warn("scheduling.coordination=cluster needs a sql-backed store except sqlite — falling back to single"), Dn === "advisoryLock" && !G.has(y) && $.warn("scheduling.coordination=advisoryLock needs a SQL store (the claim-row gate) — falling back to single");
1318
- let jn, Mn = x.workflows.length > 0 || x.workflowWorkers.length > 0 || x.eventTriggers.length > 0 || (w?.outgoing.length ?? 0) > 0 || K, Pn;
1319
- if (Mn) {
1320
- if (y === "mssql") {
1321
- let e = await de(process.cwd());
1322
- e && $.warn(e);
1323
- }
1324
- let [{ WorkflowEngine: e }, { makeClusterCronLayer: t, workflowEngineLayer: n, resolveRunnerStorage: r, resolveFailoverTuning: i }] = await Promise.all([import("@effect/workflow"), import("@voltro/workflow/cluster")]), o = K ? x.schedules.filter((e) => (e.trigger ?? En) === "self").map((e) => t({
1325
- name: e.name,
1326
- cron: $t(e),
1327
- execute: async () => {
1328
- await jn?.fireFromCluster(e.name);
1329
- }
1330
- })) : [];
1331
- Pn = y === "memory" ? e.layerMemory : await (async () => {
1332
- let e = await a(y), t = r({ sqliteFamily: e.id === "sqlite" || e.id === "turso" });
1333
- 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({
1334
- sqlClientLayer: e.makeSqlLayer(A()),
1335
- runnerStorage: t,
1336
- dialectId: e.id,
1337
- ...process.env.VOLTRO_WORKFLOW_RUNNER_PORT ? { runnerListenPort: Number(process.env.VOLTRO_WORKFLOW_RUNNER_PORT) } : {},
1338
- ...i(),
1339
- ...o.length > 0 ? { extraShardingLayers: o } : {}
1340
- });
1341
- })();
1342
- }
1343
- let In = _(N, r()), Ln = b.filter((e) => /\.subscribe\.tsx?$/.test(e)), zn = Ln.length > 0 ? await ae(Ln, $) : [], Bn = b.filter((e) => /\.reaction\.tsx?$/.test(e)), Vn = Bn.length > 0 ? await ie(Bn, $) : [], Un = b.filter((e) => Ot.test(e)), Gn = Un.length > 0 ? await pe(Un, $) : [], Jn = b.filter((e) => /\.aggregate\.tsx?$/.test(e)), q = Jn.length > 0 ? await _t(Jn, $) : [], Xn = xe();
1344
- if (q.length > 0 && y !== "memory") try {
1345
- Xn = ne((await a(y)).makeSqlLayer(A()));
1346
- } catch (e) {
1347
- $.warn("aggregate: SQL storage init failed — falling back to in-process", { err: String(e) });
1348
- }
1349
- let Zn = y === "memory" ? Rn : un(E, `aggregate@${process.pid}`, $), Qn = b.filter((e) => kt.test(e)), $n = Qn.length > 0 ? await T(Qn, $) : [], er = b.filter((e) => Dt.test(e)), tr = er.length > 0 ? await Ue(er, $) : [], nr = b.filter((e) => Et.test(e)), rr = nr.length > 0 ? await pt(nr, $) : [], J = [], ir = [], ar = b.filter((e) => xt.test(e));
1350
- if (ar.length > 0) {
1351
- let e = $.child("agent"), t = b.filter((e) => St.test(e));
1352
- t.length > 0 && await P(t, e);
1353
- let n = await F(ar, e);
1354
- for (let e of n.agents) for (let t of Ee(e)) (t.kind === "action" ? J : ir).push({
1355
- file: t.file,
1356
- descriptor: t.descriptor,
1357
- executor: t.executor
1358
- });
1359
- n.agents.length > 0 && e.info("synthesized agent routes", { agents: n.agents.map((e) => e.descriptor.name) });
1360
- }
1361
- p.mark("workflow");
1362
- let Y = () => {
1363
- let e = Z.workflowWriteActions();
1364
- if (e === void 0) throw Error("workflow actions: this app registers no workflows");
1365
- return e;
1366
- }, X = await Ae({
1367
- files: b,
1368
- store: E,
1369
- log: $,
1370
- seedPolicy: "report",
1371
- seedPattern: o,
1372
- loadSeedFiles: i,
1373
- startupPattern: Tt,
1374
- loadStartupFiles: jt,
1375
- runStartups: At,
1376
- emailPattern: S,
1377
- loadEmailFiles: l,
1378
- registerEmailTemplates: Nr
1379
- });
1380
- (X.startupCount > 0 || X.emailCount > 0) && $.info("boot lifecycle", {
1381
- startups: X.startupCount,
1382
- emailTemplates: X.emailCount
1383
- }), X.startups !== void 0 && On(async () => {
1384
- await X.startups.stop();
1385
- });
1386
- let or = {
1387
- kind: "api",
1388
- meta: {
1389
- name: v?.name ?? "voltro-api",
1390
- voltroVersion: st,
1391
- port: oe,
1392
- mode: "start",
1393
- store: y,
1394
- cdc: ce ? "on" : "off"
1395
- },
1396
- rpc: Ge(x, g),
1397
- workflows: Ne(x, g),
1398
- events: () => Z.eventsSnapshot(),
1399
- members: () => Z.membersSnapshot(),
1400
- inspectFireSchedule: async ({ name: e, trigger: t }) => {
1401
- if (!jn) throw Error("scheduler not started — this app registers no self-triggered schedules (all schedules are trigger:'external', or there are none).");
1402
- return { runId: await jn.fireNow(e, t) ?? null };
1403
- },
1404
- ...w === void 0 ? {} : { webhooks: () => Ye({
1405
- store: E,
1406
- discoveredWebhooks: w
1407
- }) },
1408
- plugins: () => ({
1409
- plugins: Yt.snapshot(),
1410
- capturedAt: Date.now()
1411
- }),
1412
- env: () => t(v?.name ?? Pt(g), {
1413
- ...v?.env !== void 0 && gr(v.env) ? { contract: v.env } : {},
1414
- plugins: v?.plugins ?? []
1415
- }),
1416
- dataCache: () => C({
1417
- stats: tt,
1418
- backendKind: et
1419
- }),
1420
- subscriptions: () => te(() => W),
1421
- inspectTables: () => ue(x.tables),
1422
- inspectRows: ye({
1423
- store: E,
1424
- tables: x.tables,
1425
- mask: !0
1426
- }),
1427
- metrics: (e) => Z.rpcMetrics().snapshot(e),
1428
- cluster: () => gt({
1429
- store: E,
1430
- dialect: y,
1431
- useClusterCron: K,
1432
- scheduleCoordChoice: Dn
1433
- }),
1434
- inspectSchedules: () => m({
1435
- schedules: x.schedules,
1436
- defaultTrigger: En,
1437
- coordination: An
1438
- }),
1439
- inspectScheduleRuns: (e) => re(E, e),
1440
- ...Se(E, {
1441
- controls: ot(x.workflows ?? []),
1442
- active: (x.workflows?.length ?? 0) > 0,
1443
- cancellation: () => Z.flowControlHealth()
1444
- }),
1445
- webhookActions: mt(() => Z.webhooksService()),
1446
- inspectStartWorkflow: (e) => Y().inspectStartWorkflow(e),
1447
- inspectCancelWorkflowRun: (e) => Y().inspectCancelWorkflowRun(e),
1448
- inspectSuspendWorkflowRun: (e) => Y().inspectSuspendWorkflowRun(e),
1449
- inspectResumeWorkflowRun: (e) => Y().inspectResumeWorkflowRun(e),
1450
- inspectDiscardWorkflowRun: (e) => Y().inspectDiscardWorkflowRun(e),
1451
- inspectRetryWorkflowRun: (e) => Y().inspectRetryWorkflowRun(e),
1452
- inspectSignalWorkflowRun: (e) => Y().inspectSignalWorkflowRun(e),
1453
- inspectUpdateWorkflowRun: (e) => Y().inspectUpdateWorkflowRun(e),
1454
- inspectInferences: (e) => at({
1455
- store: E,
1456
- active: (x.workflows?.length ?? 0) > 0,
1457
- dispatcher: () => Z.inferenceHealth()
1458
- }, e.limit === void 0 ? {} : { limit: e.limit }),
1459
- ...nt({
1460
- store: E,
1461
- cancelRun: async (e) => await Z.runCanceller()?.(e) ?? !1,
1462
- retryRun: async (e) => Y().inspectRetryWorkflowRun({ runId: e }),
1463
- redriveRun: async (e) => Z.redriveWorkflowRun({ runId: e }),
1464
- log: $
1465
- }),
1466
- inspectRedriveWorkflowRun: (e) => Z.redriveWorkflowRun(e),
1467
- inspectResumeWorkflowRunFromStep: (e) => Z.resumeWorkflowRunFromStep(e)
1468
- }, Z = await si({
1469
- bootTiming: p,
1470
- broadcastNamespace: H,
1471
- membership: {
1472
- ...Kt,
1473
- instanceId: Ht
1474
- },
1475
- ...v?.plugins === void 0 ? {} : { plugins: v.plugins },
1476
- ...bn ? { idempotency: {
1477
- store: bn.store,
1478
- ttlMs: bn.ttlMs
1479
- } } : {},
1480
- discovered: {
1481
- queries: [...x.queries, ...ir],
1482
- mutations: x.mutations,
1483
- actions: [...x.actions, ...J],
1484
- streams: x.streams,
1485
- events: x.events,
1486
- workflows: x.workflows,
1487
- workflowWorkers: x.workflowWorkers,
1488
- eventTriggers: x.eventTriggers,
1489
- schedules: x.schedules,
1490
- subscribers: zn,
1491
- outboxHandlers: Gn,
1492
- connections: x.connections,
1493
- reactions: Vn,
1494
- aggregates: q,
1495
- expectations: $n,
1496
- budgets: tr,
1497
- experiments: rr,
1498
- ...w === void 0 ? {} : { webhooks: w }
1499
- },
1500
- log: $,
1501
- analytics: De.sink,
1502
- aggregateStorage: Xn,
1503
- aggregateCoordinator: Zn,
1504
- store: E,
1505
- kv: lt,
1506
- cache: Ke,
1507
- snapshotCache: We,
1508
- schemaRegistry: je,
1509
- tenantScopedTables: x.tenantScopedTables,
1510
- softDeleteScopedTables: x.softDeleteScopedTables,
1511
- dataTransferSnapshot: xr(Oe),
1512
- dataTransferDialect: y,
1513
- tenantIsolation: (process.env.VOLTRO_TENANT_ISOLATION ?? v?.tenancy?.isolation) === "namespace" ? "namespace" : "shared-schema",
1514
- resolveSubject: async (e, t) => {
1515
- let n = await _n({
1516
- headers: e,
1517
- clientId: t
1518
- });
1519
- return kn(t, n.credentialExpiresAt), n.subject;
1520
- },
1521
- httpRoutes: [...N.flatMap((e) => e.httpRoutes ?? []), ...xn],
1522
- getStore: () => Fe,
1523
- ...Cn ? { baseLayer: Cn } : {},
1524
- ...Pn === void 0 ? {} : { workflowEngineLayer: Pn },
1525
- scheduleDefaultTrigger: En,
1526
- scheduleCoordination: An,
1527
- scheduleArmSelf: !K,
1528
- dormancy: process.env.VOLTRO_DORMANCY === "sleep" || process.env.VOLTRO_DORMANCY === "always-on" ? process.env.VOLTRO_DORMANCY : v?.dormancy ?? "always-on",
1529
- scheduleReplicaId: process.env.HOSTNAME ?? `pid-${process.pid}`,
1530
- ...In === void 0 ? {} : { scheduleFireInterceptor: In },
1531
- onSchedulerReady: (e) => {
1532
- jn = e;
1533
- },
1534
- inspectRoute: { handle: async (e, t, n, r) => await me(e, or, t, {
1535
- method: n,
1536
- ...r === void 0 ? {} : { body: r }
1537
- }) || (I(e, or, t, {
1538
- method: n,
1539
- ...r === void 0 ? {} : { body: r }
1540
- }) ?? {
1541
- status: 404,
1542
- contentType: "application/json",
1543
- body: JSON.stringify({ error: "not an inspect route" })
1544
- }) },
1545
- ...v?.name === void 0 ? {} : { appName: v.name },
1546
- observability: U,
1547
- port: oe,
1548
- ...v?.transport?.wsPath ? { path: v.transport.wsPath } : {}
1549
- });
1550
- return W = Z.dispatcher, ee(yt([
1551
- x.queries,
1552
- x.mutations,
1553
- x.actions,
1554
- x.streams
1555
- ]), (e) => {
1556
- $.warn(e);
1557
- }), $.info(`API listening on :${oe}`, {
1558
- dialect: y,
1559
- queries: x.queries.length,
1560
- mutations: x.mutations.length,
1561
- actions: x.actions.length,
1562
- streams: x.streams.length,
1563
- workflows: x.workflows.length,
1564
- workflowWorkers: x.workflowWorkers.length,
1565
- schedules: x.schedules.length,
1566
- scheduleCoordination: An
1567
- }), p.finish($), On(async () => {
1568
- for (let e of Vt) e.stop();
1569
- ht.detach(), vt.stop(), rt(), R?.dispose();
1570
- try {
1571
- await Yt.deactivate(), await Zt?.close(), await De.dispose(), await Z.close(), await E.close?.();
1572
- } catch (e) {
1573
- console.error("serve: shutdown step failed, exiting anyway:", e);
1574
- }
1575
- }), await new Promise(() => {}), 0;
1576
- };
1577
- //#endregion
1578
- export { ui as n, ii as r, di as t };