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