@voltro/cli 0.55.0 → 0.57.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 (175) hide show
  1. package/CHANGELOG.md +691 -0
  2. package/bin/voltro.mjs +24 -0
  3. package/dist/apiBuild-B83Cb2Rv.js +2 -0
  4. package/dist/{apiBuild-CMvLJM_K.js → apiBuild-DDr2aNFd.js} +119 -88
  5. package/dist/bin.js +1 -1
  6. package/dist/{build-S0QOzqPT.js → build-QKP6Bm0J.js} +308 -279
  7. package/dist/buildReport-52gHKgfO.js +64 -0
  8. package/dist/{checkCommand-DNkY5kwF.js → checkCommand-BISqx1OJ.js} +1 -1
  9. package/dist/{checkCommand-fbj9GDjN.js → checkCommand-DUtMWjcR.js} +6 -6
  10. package/dist/{clusterCmd-DrVFCzSj.js → clusterCmd-CdLB1GkT.js} +1 -1
  11. package/dist/{codegen-SIepQtUl.js → codegen-Bth5lUTU.js} +2 -1
  12. package/dist/codegen-DbH7NbCR.js +2 -0
  13. package/dist/{codegenCommand-3TDJezom.js → codegenCommand-DnVuDxwT.js} +11 -11
  14. package/dist/{codemodRunner-C2zxZUIw.js → codemodRunner-BlQPfjzA.js} +222 -0
  15. package/dist/{commands-BBYJ7Q3B.js → commands-CRbxgxv0.js} +35 -35
  16. package/dist/{dashboardCommand-D2kmyCLL.js → dashboardCommand-Bf_-Ne3P.js} +5 -5
  17. package/dist/{dataCommand-BEPPQiTl.js → dataCommand-BoBJJ-Gb.js} +3 -3
  18. package/dist/{dbCommand-DZTmOFT4.js → dbCommand-CMAIz-Bf.js} +457 -441
  19. package/dist/dbCommand-DHi_RuDl.js +2 -0
  20. package/dist/dev-Bl9HqtV7.js +3 -0
  21. package/dist/{dev-Ca_A_S9v.js → dev-DOEJXicj.js} +2623 -2485
  22. package/dist/{doctorCommand-CGZJK_4o.js → doctorCommand-BrWu67JZ.js} +524 -280
  23. package/dist/doctorCommand-DrQv9SL3.js +2 -0
  24. package/dist/{dormancyCommand-DY2rYpTa.js → dormancyCommand-xn2y-pJm.js} +1 -1
  25. package/dist/{embeddingsCommand-BoCqZsgp.js → embeddingsCommand-Cn5MbRDM.js} +1 -1
  26. package/dist/emptyResultHeadline-Csa5fZOF.js +18 -0
  27. package/dist/{envCommand-Bxy2fOjc.js → envCommand-UJmJIbs9.js} +8 -8
  28. package/dist/{evolveCommand-BsbZ-XDg.js → evolveCommand-Db30twUy.js} +2 -2
  29. package/dist/frameworkTableAssembly-B96WCNJA.js +2 -0
  30. package/dist/{frameworkTableAssembly-Do-cf6RJ.js → frameworkTableAssembly-vfkzuzEo.js} +131 -104
  31. package/dist/index.js +1 -1
  32. package/dist/{infoCommand-EmM3jPKD.js → infoCommand-BjVXpMlP.js} +1 -1
  33. package/dist/inspect-B0hL41s0.js +2 -0
  34. package/dist/inspect-DZnan87F.js +1500 -0
  35. package/dist/{inspectCmd-niF97fAq.js → inspectCmd-CP-G0sVK.js} +1 -1
  36. package/dist/{inspectFetch-EMuhTG_9.js → inspectFetch-BU1NyzxV.js} +36 -24
  37. package/dist/{inspectMetrics-CGF94puw.js → inspectMetrics-BY0Sjb2F.js} +19 -19
  38. package/dist/{logsCmd-B6oNsfaZ.js → logsCmd-C5y9HyrG.js} +59 -54
  39. package/dist/{manifestBuild-DjX5MoXy.js → manifestBuild-DnbFKF6w.js} +1 -1
  40. package/dist/manifestBuild-UXrnUcXP.js +2 -0
  41. package/dist/{migrate-CGFZS-1a.js → migrate-DtC3lu7H.js} +4 -4
  42. package/dist/precompressAssets-YhTi1aWp.js +40 -0
  43. package/dist/{probeCommand-Bs3iVBSL.js → probeCommand-C5fuN6Z2.js} +2 -2
  44. package/dist/{runtimeTrace-C1BTpHGQ.js → runtimeTrace-BQL_lfz6.js} +1 -1
  45. package/dist/{scheduleCmd-DQRu6BZC.js → scheduleCmd-DYBUfo_T.js} +1 -1
  46. package/dist/{sdkgen-CXMwLg9n.js → sdkgen-CMUPrDjH.js} +1 -1
  47. package/dist/{seedRunner-Dgsiwk_e.js → seedRunner-DISBKow-.js} +16 -16
  48. package/dist/serveCommand-B_w-Mpb_.js +2544 -0
  49. package/dist/serveCommand-Dtb48ffg.js +2 -0
  50. package/dist/serveEntry.js +1 -1
  51. package/dist/{start-EOV7s1NZ.js → start-YaUehtDV.js} +580 -558
  52. package/dist/{start-DH7cat4-.js → start-s25GAIgn.js} +1 -1
  53. package/dist/startEntry.js +1 -1
  54. package/dist/staticCachePolicy-CIyj6DbS.js +15 -0
  55. package/dist/{test-DO27-x2P.js → test-jipIQ5Mx.js} +1 -1
  56. package/dist/{tracesCmd-DgtgOUdi.js → tracesCmd-C1qKa94g.js} +69 -64
  57. package/dist/{updateCommand-C_jN1w18.js → updateCommand-C9n_Z_oG.js} +8 -2
  58. package/dist/updateCommand-DsXEAHbd.js +2 -0
  59. package/dist/webDev-B6ZMX42w.js +2 -0
  60. package/dist/{webDev-B7vNj4Bq.js → webDev-BgdkyjP6.js} +1379 -1303
  61. package/dist/{webhooksCommand-B1LVcyO3.js → webhooksCommand-CYXTNvXq.js} +2 -2
  62. package/dist/{workflowsCmd-BGF-mRZ5.js → workflowsCmd-g-DNpaUc.js} +1 -1
  63. package/package.json +55 -19
  64. package/templates/AGENTS.core.md +20 -1
  65. package/templates/AGENTS.md +21 -2
  66. package/templates/agent-docs/_index.md +1 -1
  67. package/templates/agent-docs/_manifest.json +2 -2
  68. package/templates/agent-docs/ai.md +1 -1
  69. package/templates/agent-docs/authentication.md +34 -19
  70. package/templates/agent-docs/cli.md +170 -0
  71. package/templates/agent-docs/configuration.md +29 -4
  72. package/templates/agent-docs/data.md +145 -5
  73. package/templates/agent-docs/database/scaling.md +50 -2
  74. package/templates/agent-docs/deployment.md +75 -1
  75. package/templates/agent-docs/internationalization.md +32 -0
  76. package/templates/agent-docs/local-first-mobile.md +9 -2
  77. package/templates/agent-docs/observability.md +227 -0
  78. package/templates/agent-docs/plugins/audit.md +21 -5
  79. package/templates/agent-docs/plugins/billing.md +17 -0
  80. package/templates/agent-docs/plugins/broadcast.md +2 -1
  81. package/templates/agent-docs/plugins/ratelimit.md +6 -1
  82. package/templates/agent-docs/plugins/row-history.md +11 -0
  83. package/templates/agent-docs/plugins.md +19 -0
  84. package/templates/agent-docs/reference.md +1 -0
  85. package/templates/agent-docs/scheduling.md +23 -0
  86. package/templates/agent-docs/schema-driven-ui.md +81 -0
  87. package/templates/agent-docs/templates/appshells.md +3 -3
  88. package/templates/agent-docs/whats-new.md +133 -77
  89. package/templates/apps/api-ai/package.json +6 -6
  90. package/templates/apps/api-auth/package.json +8 -8
  91. package/templates/apps/api-backend/package.json +7 -7
  92. package/templates/apps/api-backend-deactivation/package.json +7 -7
  93. package/templates/apps/api-backend-mail/package.json +8 -8
  94. package/templates/apps/api-backend-mariadb/package.json +9 -9
  95. package/templates/apps/api-backend-sqlite/package.json +8 -8
  96. package/templates/apps/api-backend-storage/package.json +8 -8
  97. package/templates/apps/api-cms/package.json +9 -9
  98. package/templates/apps/api-collab/package.json +8 -8
  99. package/templates/apps/api-data-advanced/package.json +8 -8
  100. package/templates/apps/api-durable/package.json +8 -8
  101. package/templates/apps/api-feature-flags/package.json +9 -9
  102. package/templates/apps/api-governance/package.json +8 -8
  103. package/templates/apps/api-kv/package.json +8 -8
  104. package/templates/apps/api-moderation/package.json +8 -8
  105. package/templates/apps/api-observability/package.json +8 -8
  106. package/templates/apps/api-ratelimit/package.json +8 -8
  107. package/templates/apps/api-rbac/package.json +8 -8
  108. package/templates/apps/api-rest/package.json +7 -7
  109. package/templates/apps/api-row-history/package.json +8 -8
  110. package/templates/apps/api-saas/package.json +11 -11
  111. package/templates/apps/api-saas-starter/package.json +10 -10
  112. package/templates/apps/api-search/package.json +8 -8
  113. package/templates/apps/api-status/package.json +8 -8
  114. package/templates/apps/api-webhooks/package.json +9 -9
  115. package/templates/apps/changelog/package.json +7 -7
  116. package/templates/apps/changelog/src/pages/[locale]/page.tsx +7 -1
  117. package/templates/apps/edge-functions/package.json +2 -2
  118. package/templates/apps/frontend-admin/package.json +7 -8
  119. package/templates/apps/frontend-admin/src/pages/(marketing)/layout.tsx +1 -2
  120. package/templates/apps/frontend-admin/src/pages/admin/layout.tsx +1 -2
  121. package/templates/apps/frontend-app/package.json +8 -9
  122. package/templates/apps/frontend-app/src/pages/layout.tsx +1 -2
  123. package/templates/apps/frontend-auth/package.json +7 -8
  124. package/templates/apps/frontend-auth/src/components/AuthShell.tsx +1 -2
  125. package/templates/apps/frontend-blank/package.json +6 -7
  126. package/templates/apps/frontend-blank/src/pages/layout.tsx +1 -2
  127. package/templates/apps/frontend-cms/package.json +8 -9
  128. package/templates/apps/frontend-cms/src/pages/(app)/layout.tsx +1 -2
  129. package/templates/apps/frontend-collab/README.md +7 -2
  130. package/templates/apps/frontend-collab/package.json +9 -10
  131. package/templates/apps/frontend-collab/src/pages/layout.tsx +1 -2
  132. package/templates/apps/frontend-collab/src/pages/page.test.tsx +8 -4
  133. package/templates/apps/frontend-collab/src/pages/page.tsx +10 -5
  134. package/templates/apps/frontend-contact/package.json +7 -7
  135. package/templates/apps/frontend-contact/src/components/ContactForm.island.tsx +1 -1
  136. package/templates/apps/frontend-dashboard/package.json +6 -7
  137. package/templates/apps/frontend-dashboard/src/pages/(marketing)/layout.tsx +1 -2
  138. package/templates/apps/frontend-dashboard/src/pages/dashboard/layout.tsx +1 -2
  139. package/templates/apps/frontend-docs/package.json +8 -8
  140. package/templates/apps/frontend-i18n/package.json +6 -6
  141. package/templates/apps/frontend-landing/package.json +7 -7
  142. package/templates/apps/frontend-portal/package.json +7 -8
  143. package/templates/apps/frontend-portal/src/pages/(portal)/layout.tsx +1 -2
  144. package/templates/apps/frontend-saas/package.json +7 -8
  145. package/templates/apps/frontend-saas/src/pages/(marketing)/layout.tsx +1 -2
  146. package/templates/apps/frontend-saas/src/pages/dashboard/layout.tsx +1 -2
  147. package/templates/apps/frontend-spa/package.json +6 -7
  148. package/templates/apps/frontend-spa/src/pages/layout.tsx +1 -2
  149. package/templates/apps/frontend-ssr/package.json +6 -7
  150. package/templates/apps/frontend-ssr/src/pages/layout.tsx +1 -2
  151. package/templates/apps/frontend-ssr-api/package.json +7 -8
  152. package/templates/apps/frontend-ssr-api/src/pages/layout.tsx +1 -2
  153. package/templates/apps/frontend-static-blog/package.json +8 -8
  154. package/templates/apps/frontend-static-blog/src/components/ReadingProgress.island.tsx +1 -1
  155. package/templates/apps/frontend-static-blog/src/pages/[locale]/page.tsx +7 -1
  156. package/templates/apps/frontend-status/package.json +7 -8
  157. package/templates/apps/frontend-status/src/pages/layout.tsx +1 -2
  158. package/templates/apps/mobile-app/package.json +4 -4
  159. package/templates/baselines/compose/docker/api.Dockerfile +61 -5
  160. package/templates/baselines/compose/docker/web.Dockerfile +55 -10
  161. package/templates/baselines/compose-mariadb/docker/api.Dockerfile +61 -5
  162. package/templates/baselines/compose-mariadb/docker/web.Dockerfile +55 -10
  163. package/dist/apiBuild-Cl0IDx8c.js +0 -2
  164. package/dist/codegen-CN6vMM4J.js +0 -2
  165. package/dist/dbCommand-BTyBGhIA.js +0 -2
  166. package/dist/dev-DfVZaoys.js +0 -3
  167. package/dist/doctorCommand-djmqEcDC.js +0 -2
  168. package/dist/frameworkTableAssembly-Df2Ymp2f.js +0 -2
  169. package/dist/inspect-DCqILJ1G.js +0 -1197
  170. package/dist/inspect-DGJwpOAb.js +0 -2
  171. package/dist/manifestBuild-CJ2zvPvT.js +0 -2
  172. package/dist/serveCommand-C7IrCD58.js +0 -2445
  173. package/dist/serveCommand-Cjt5S9hD.js +0 -2
  174. package/dist/updateCommand-nnFjDbl4.js +0 -2
  175. package/dist/webDev-1XpVnYkW.js +0 -2
@@ -1,2445 +0,0 @@
1
- import { t as e } from "./nodeEnvironment-cGFAj1J8.js";
2
- import { t } from "./frameworkInspectState-CX2250XB.js";
3
- import { r as n, t as r } from "./appModuleLoader-C9r9mxZt.js";
4
- import { t as i } from "./bootRefusal-pgvDxlrU.js";
5
- import { n as a, r as o } from "./startupRunner-CEqQq7ax.js";
6
- import { n as s, t as c } from "./interruptedReplace-CwnkBb2X.js";
7
- import { $ as l, $t as u, A as d, An as f, At as ee, Bt as te, C as ne, Cn as p, Ct as m, D as re, Dt as h, E as ie, En as ae, Et as oe, F as se, Ft as ce, G as le, Gt as g, H as ue, I as _, It as de, J as fe, Jt as pe, K as me, Kt as he, L as ge, Lt as v, M as y, Mt as _e, N as ve, Nt as ye, O as be, On as xe, Ot as Se, P as Ce, Pt as we, Q as Te, Qt as Ee, R as b, Rt as De, S as Oe, Sn as ke, St as Ae, T as je, Tn as x, Tt as Me, U as Ne, Ut as Pe, Vt as Fe, W as Ie, X as Le, Xt as S, Y as Re, Yt as ze, Z as Be, Zt as Ve, _ as He, _n as C, _t as w, an as Ue, at as We, b as Ge, bt as Ke, c as qe, cn as Je, ct as Ye, d as Xe, dn as Ze, dt as Qe, en as $e, et, fn as tt, ft as nt, g as rt, gn as it, gt as at, h as ot, hn as st, ht as ct, i as lt, in as ut, it as dt, j as ft, jn as pt, jt as T, k as mt, kn as ht, kt as E, ln as gt, lt as _t, m as D, mn as vt, mt as yt, nn as bt, nt as xt, o as O, on as St, ot as Ct, p as wt, pn as Tt, pt as Et, q as Dt, qt as Ot, r as kt, rn as At, rt as jt, sn as Mt, st as Nt, t as k, tn as A, tt as Pt, u as Ft, un as It, ut as j, v as Lt, vn as Rt, vt as zt, w as Bt, wn as Vt, wt as Ht, x as Ut, xn as Wt, xt as Gt, y as Kt, yn as qt, yt as Jt, z as M, zt as Yt } from "./dev-Ca_A_S9v.js";
8
- import { n as Xt } from "./cliArgs-D4p8n7EE.js";
9
- import { r as Zt } from "./appPort-B_HpJ_ck.js";
10
- import { Ut as Qt, Vt as $t } from "./webDev-B7vNj4Bq.js";
11
- import { r as N } from "./dialectDriver-czCHYpeH.js";
12
- import { i as P, n as en } from "./connectionConfig-Bk9IC7D0.js";
13
- import { c as tn, n as nn, o as rn } from "./seedRunner-Dgsiwk_e.js";
14
- import { d as an, h as on, m as sn, p as cn, r as ln } from "./frameworkTableAssembly-Do-cf6RJ.js";
15
- import { n as un, r as dn, t as fn } from "./declaredSchemaGates-BlcwObhb.js";
16
- import { C as pn, a as mn, h as hn, l as gn, n as _n, u as vn, w as yn } from "./fileConventions-l-RIXbx8.js";
17
- import { h as bn, o as xn } from "./inspect-DCqILJ1G.js";
18
- import { i as Sn, n as Cn, t as wn } from "./inspectMetrics-CGF94puw.js";
19
- import { n as Tn } from "./mssqlClusterPatch-_4cE_nun.js";
20
- import { i as En, n as Dn, r as On, t as kn } from "./webhookDiscovery-CphsQe59.js";
21
- import { r as An, u as jn } from "./apiBuild-CMvLJM_K.js";
22
- import { t as Mn } from "./bootTiming-BdyP9nYw.js";
23
- import { a as Nn, o as Pn, t as Fn } from "./dataProfile-Du3ztYxv.js";
24
- import F, { basename as In, join as Ln } from "node:path";
25
- import { createWriteStream as Rn, existsSync as zn } from "node:fs";
26
- import { pathToFileURL as Bn } from "node:url";
27
- import { LoggerLayer as Vn, createLogger as I } from "@voltro/logger";
28
- import { AuthMiddleware as Hn, ConnectionInfoMiddleware as Un, actionToRpc as L, anonymousSubject as Wn, isWireReachable as Gn, mutationToRpc as Kn, queryToRpc as R, streamToRpc as qn, wireErrorUnion as Jn, workflowCancelDescriptor as Yn, workflowDomainEventsQueryDescriptor as z, workflowEventDeliveriesQueryDescriptor as B, workflowResumeDescriptor as Xn, workflowRunEventsQueryDescriptor as Zn, workflowRunQueryDescriptor as Qn, workflowRunStepsQueryDescriptor as $n, workflowRunsQueryDescriptor as er, workflowSignalDescriptor as tr, workflowUpdateDescriptor as nr } from "@voltro/protocol";
29
- import { DATA_TRANSFERS_TABLE as V, _voltroDataTransfersTable as rr, allRegisteredTables as ir, and as ar, connectionIdentity as or, derivedRowId as sr, describeTransferRun as cr, ensureTableRegistered as lr, eq as H, or as ur } from "@voltro/database";
30
- import { Cause as dr, Effect as U, Layer as W, ManagedRuntime as fr } from "effect";
31
- import { SqlClient as pr } from "@effect/sql";
32
- import { declaredSnapshot as mr, describeOutcome as hr, pendingFileMigrationIds as gr, runPlannedMigrations as _r } from "@voltro/database/sql";
33
- import { AggregateRegistry as vr, CostRegistry as yr, DORMANCY_WAKEUP_TENANT as br, Dispatcher as xr, ExpectationRegistry as Sr, ExperimentRegistry as Cr, apiKeyManagementRoutes as wr, attachAnalyticsMirror as Tr, attachExpectations as Er, attachExperiments as Dr, attachFinops as Or, awaitServerListening as kr, bindMutation as G, bindStream as Ar, bindSubscription as K, buildTracingLayer as jr, cancelWakeup as Mr, compileCron as Nr, dataStoreApiKeyStore as Pr, formatServerOnlyLeaks as Fr, formatUnresolvedSources as Ir, frameworkApiKeyStrategy as Lr, getResourcePolicy as Rr, installPolicyGuardResolver as zr, loadResourceTuples as Br, makeActionRunner as Vr, makeAdvisoryLockCoordinator as Hr, makeApiKeyService as Ur, makeApiKeyUsageBuffer as Wr, makeApiKeyUsageFlusher as Gr, makeAsyncKv as Kr, makeAuthMiddlewareLayers as qr, makeCoordinatedScheduler as Jr, makeEffectStoreLayer as Yr, makeLazyWorkflowFacade as Xr, makeMutationOutputCodec as Zr, makeMutationRunner as Qr, makeOneShotQueryRunner as $r, makeQueryDescriptorProducer as q, makeQueryFinalizer as ei, makeQueryReauthorizer as ti, makeQuerySubscriber as ni, makeSchemaRegistry as ri, makeWorkflowFacade as ii, makeWorkflowFacadeWithCallerContext as ai, makeWorkflowLayers as oi, noopKv as si, onProcessShutdown as J, recordSubscriptionDelivery as Y, recordWorkflowRun as ci, registerDefaultTupleSource as li, registerWakeup as ui, resolveSecretsBackend as di, runProvidedEffect as fi, setSecretsBackend as pi, setSystemStoreHandle as mi, shutdownGraceMsFromEnv as hi, singleCoordinator as gi, startRpcServer as _i, startScheduler as vi, stripForbiddenForWire as yi, undoCaptureEnabled as bi, unresolvedSources as xi, withScopedRequest as Si, workflowToRpc as Ci, wrapStoreWithBootCodec as wi } from "@voltro/runtime";
34
- import Ti, { tmpdir as Ei } from "node:os";
35
- import { RpcGroup as Di } from "@effect/rpc";
36
- import { appStorageProvider as Oi, durabilityNotice as ki, fromNodeReadable as Ai, getObjectStream as ji, putObjectStream as Mi, toNodeReadable as Ni } from "@voltro/plugin-storage";
37
- import { isEnvContract as Pi } from "@voltro/env";
38
- import { assertProductionSessionSecret as Fi } from "@voltro/protocol/session";
39
- import X from "node:fs/promises";
40
- import { createHash as Ii, timingSafeEqual as Li } from "node:crypto";
41
- import { channelFor as Ri, getBroadcastPlugin as zi } from "@voltro/plugin-broadcast";
42
- import { buildDeliverWebhookExecute as Bi, buildWebhooksService as Vi, defaultIncomingPath as Hi, deliverWebhookWorkflow as Ui, makeDeferredEmitHandler as Wi, mountIncomingWebhook as Gi } from "@voltro/plugin-webhooks";
43
- import { getAuthSessionStrategy as Ki } from "@voltro/plugin-auth";
44
- import { registerEmailTemplates as qi } from "@voltro/plugin-mail";
45
- import { checkSchemaDrift as Ji, decideStaging as Yi, isEnvironmentLocal as Xi, packBundle as Zi, peekBundle as Qi, runExport as $i, runImport as ea, storageBlobSink as ta, storageRefsBlobSource as na, unpackBundle as ra, unpackBundleToDir as ia } from "@voltro/data-transfer";
46
- //#region \0rolldown/runtime.js
47
- var aa = /* @__PURE__ */ ((e) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(e, { get: (e, t) => (typeof require < "u" ? require : e)[t] }) : e)(function(e) {
48
- if (typeof require < "u") return require.apply(this, arguments);
49
- throw Error("Calling `require` for \"" + e + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
50
- }), oa = () => Math.max(500, Math.floor(hi() * .6)), sa = (e) => new Promise((t) => setTimeout(t, e)), ca = (e) => {
51
- let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), r = 0;
52
- e.on("connection", (e) => {
53
- t.add(e), e.once("close", () => {
54
- t.delete(e), n.delete(e);
55
- });
56
- }), e.on("upgrade", (e, t) => {
57
- n.add(t);
58
- }), e.on("request", (e, t) => {
59
- r += 1, t.once("close", () => {
60
- --r;
61
- });
62
- });
63
- let i, a = async (t = {}) => {
64
- let n = t.budgetMs ?? oa();
65
- i ??= new Promise((t) => {
66
- e.close(() => {
67
- t();
68
- });
69
- }), e.closeIdleConnections();
70
- let a = Date.now() + n;
71
- for (; r > 0 && Date.now() < a;) await sa(25), e.closeIdleConnections();
72
- e.closeIdleConnections();
73
- }, o = async () => {
74
- i ??= new Promise((t) => {
75
- e.close(() => {
76
- t();
77
- });
78
- });
79
- for (let e of t) if (n.has(e)) try {
80
- e.write(Buffer.from([
81
- 136,
82
- 2,
83
- 3,
84
- 233
85
- ]));
86
- } catch {}
87
- else e.destroy();
88
- for (let e = 0; t.size > 0 && e < 250; e += 25) await sa(25);
89
- for (let e of t) e.destroy();
90
- await i;
91
- };
92
- return {
93
- activeRequests: () => r,
94
- drainRequests: a,
95
- finish: o,
96
- drain: async (e = {}) => {
97
- await a(e), await o();
98
- }
99
- };
100
- }, la = "/_voltro/admin/import", ua = "/_voltro/admin/import/start", da = "/_voltro/admin/export", fa = "/_voltro/admin/export/download", pa = "/_voltro/admin/transfers", Z = (e, t) => ({
101
- status: e,
102
- contentType: "application/json; charset=utf-8",
103
- body: JSON.stringify(t)
104
- }), ma = (e) => {
105
- let t = e.authorization ?? e.Authorization, n = t ? /^Bearer\s+(.+)$/i.exec(t) : null;
106
- return n ? n[1] : null;
107
- }, ha = (e, t) => Li(Ii("sha256").update(e).digest(), Ii("sha256").update(t).digest()), ga = (e, t, n = "POST") => {
108
- if (e.method.toUpperCase() !== n) return Z(405, { error: "method not allowed" });
109
- if (!t || t.length < 16) return Z(503, { error: "data transfer misconfigured (no/weak secret)" });
110
- let r = ma(e.headers);
111
- return !r || !ha(r, t) ? Z(401, { error: "unauthorized" }) : null;
112
- }, _a = /^[A-Za-z0-9_-]{8,64}$/, va = (e) => _a.test(e), ya = () => process.env.VOLTRO_IMPORT_UPLOAD_DIR ?? F.join(Ti.tmpdir(), "voltro-import-uploads"), ba = (e) => F.join(ya(), e), xa = (e) => F.join(ba(e), "archive.bin"), Sa = (e) => F.join(ba(e), "meta.json"), Ca = async (e = Date.now()) => {
113
- let t = 0;
114
- try {
115
- for (let n of await X.readdir(ya())) {
116
- if (n === ".runs") continue;
117
- let r = await X.stat(ba(n)).catch(() => null);
118
- r !== null && (e - r.mtimeMs <= 864e5 || (await X.rm(ba(n), {
119
- recursive: !0,
120
- force: !0
121
- }).catch(() => void 0), t++));
122
- }
123
- } catch {}
124
- return t;
125
- }, wa = async (e) => {
126
- if (!va(e)) return {
127
- bytes: 0,
128
- key: null,
129
- runId: null
130
- };
131
- let t = await X.stat(xa(e)).catch(() => null);
132
- if (t === null) return {
133
- bytes: 0,
134
- key: null,
135
- runId: null
136
- };
137
- let n = await Ta(e);
138
- return {
139
- bytes: t.size,
140
- key: n.key ?? null,
141
- runId: n.runId ?? null
142
- };
143
- }, Ta = async (e) => {
144
- try {
145
- let t = await X.readFile(Sa(e), "utf8");
146
- return JSON.parse(t);
147
- } catch {
148
- return {};
149
- }
150
- }, Ea = async (e, t) => {
151
- let n = Sa(e), r = `${n}.${process.pid}.${Math.random().toString(36).slice(2, 8)}.tmp`;
152
- await X.writeFile(r, JSON.stringify(t)), await X.rename(r, n);
153
- }, Da = async (e, t, n) => {
154
- if (!va(e)) return t;
155
- await X.mkdir(ba(e), { recursive: !0 });
156
- let r = await Ta(e), i = typeof r.runId == "string" && r.runId.length > 0 ? r.runId : null;
157
- return i !== null && n?.takeOver !== !0 ? i : (await Ea(e, {
158
- ...r,
159
- runId: t
160
- }), t);
161
- }, Oa = async (e) => {
162
- if (!va(e)) return;
163
- let t = await Ta(e);
164
- if (t.runId === void 0) return;
165
- let { runId: n, ...r } = t;
166
- await Ea(e, r).catch(() => void 0);
167
- }, ka = async (e, t, n) => (await X.mkdir(ba(e), { recursive: !0 }), await X.writeFile(xa(e), Buffer.from(t)), await Ea(e, {
168
- ...await Ta(e),
169
- key: n,
170
- startedAt: (/* @__PURE__ */ new Date()).toISOString()
171
- }), t.byteLength), Aa = (e) => `up-${Ii("sha256").update(e).digest("hex").slice(0, 32)}`, ja = async (e) => {
172
- if (!va(e.id)) return {
173
- reason: "bad-id",
174
- message: `upload id must match ${String(_a)}`
175
- };
176
- let t = await wa(e.id);
177
- if (t.key !== null && t.key !== e.key) return {
178
- reason: "key-mismatch",
179
- message: "this upload id already holds a different bundle. Use a new upload id, or delete the partial upload."
180
- };
181
- if (e.offset !== t.bytes) return {
182
- reason: "offset-mismatch",
183
- message: `chunk starts at ${e.offset} but the server holds ${t.bytes} byte(s)`,
184
- expectedOffset: t.bytes
185
- };
186
- if (await X.mkdir(ba(e.id), { recursive: !0 }), t.key === null) {
187
- let t = await Ta(e.id);
188
- await Ea(e.id, {
189
- ...t,
190
- key: e.key,
191
- startedAt: (/* @__PURE__ */ new Date()).toISOString()
192
- });
193
- }
194
- return await new Promise((t, n) => {
195
- let r = Rn(xa(e.id), { flags: "a" });
196
- r.on("error", n), r.on("finish", () => t()), r.end(Buffer.from(e.bytes));
197
- }), { total: t.bytes + e.bytes.byteLength };
198
- }, Ma = async (e) => {
199
- let t = await X.stat(xa(e));
200
- return {
201
- path: xa(e),
202
- bytes: t.size
203
- };
204
- }, Na = () => F.join(ya(), ".runs"), Pa = (e) => F.join(Na(), `${e}.bin`), Fa = async (e, t) => {
205
- if (!va(e)) return null;
206
- let n = xa(e), r = await X.stat(n).catch(() => null);
207
- if (r === null || r.size === 0) return null;
208
- await X.mkdir(Na(), { recursive: !0 });
209
- let i = Pa(t);
210
- return await X.rename(n, i), i;
211
- }, Ia = async (e) => {
212
- await X.rm(Pa(e), { force: !0 }).catch(() => void 0);
213
- }, Q = I({ scope: "voltro:admin-import" }), La = "VBUNDLE2", Ra = (e) => {
214
- let t = e.req.headers["x-import-rollback-key"];
215
- if (e.mode !== "replace") return { options: {} };
216
- if (typeof t != "string" || t.length === 0) return Q.warn("admin.import: no rollback capture — this run empties the target first, and nothing was asked to be kept. Send `x-import-rollback-key: <storage key>` (voltro data import --rollback-key <key>) to have the instance store the target's current rows before deleting them."), { options: {} };
217
- if (e.deps.putArchive === void 0) return {
218
- options: {},
219
- refusal: Z(409, {
220
- error: "rollback capture requested but this instance has no object storage configured",
221
- hint: "A capture written to the pod would not survive the failure it exists for. Configure storage (the same one the storage-push export uses), or re-send without `x-import-rollback-key` to accept that a run which does not finish can leave the target emptied. Note that CONFIGURED is not the same question as SURVIVES: a `filesystem` provider pointed at a container directory with no volume behind it passes this check and dies with the pod. The run says so when it can observe it — the capture path being on the same filesystem as `/`."
222
- })
223
- };
224
- let n = Ln(Ei(), `voltro-rollback-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`), r = e.deps.putArchive;
225
- return {
226
- key: t,
227
- options: {
228
- rollbackDir: n,
229
- onRollbackCaptured: async () => {
230
- let e = ki(n);
231
- e !== void 0 && Q.warn(`admin.import: ${e}`), await r(t, () => Zi({ dir: n })), Q.info("admin.import: rollback capture stored", { bundleKey: t });
232
- }
233
- }
234
- };
235
- }, za = (e) => {
236
- let t = e["x-import-mode"], n = e["x-import-atomic"];
237
- return {
238
- mode: t,
239
- onConflict: e["x-import-on-conflict"],
240
- atomic: n === "0" || n === "false" ? !1 : n === "1" || n === "true" || t === "replace",
241
- force: e["x-import-force"] === "1" || e["x-import-force"] === "true",
242
- dryRun: e["x-import-dry-run"] === "1" || e["x-import-dry-run"] === "true",
243
- tables: (e["x-import-tables"] ?? "").split(",").map((e) => e.trim()).filter(Boolean)
244
- };
245
- }, Ba = async (e, t) => {
246
- if (typeof t.bundleKey == "string" && t.bundleKey !== "") {
247
- if (!e.openArchive) return { refusal: Z(501, { error: "storage transport not configured on this instance" }) };
248
- let n = e.openArchive, r = t.bundleKey;
249
- return {
250
- source: () => n(r),
251
- transport: "storage",
252
- uploadId: Aa(r)
253
- };
254
- }
255
- let n = t.uploadId;
256
- if (typeof n != "string" || !va(n)) return { refusal: Z(400, { error: "start needs { uploadId } from an upload, or { bundleKey } for the storage transport" }) };
257
- let r = await Ma(n).catch(() => null);
258
- return r === null || r.bytes === 0 ? { refusal: Z(409, {
259
- error: "no such upload",
260
- message: `this instance holds no bytes for upload '${n}'. Upload the bundle first, or re-upload if it has expired.`
261
- }) } : {
262
- source: () => Va(r.path),
263
- transport: "upload",
264
- uploadId: n
265
- };
266
- }, Va = (e) => {
267
- let { createReadStream: t } = aa("node:fs");
268
- return t(e);
269
- }, Ha = (e) => async (t) => {
270
- let n = ga(t, e.secret);
271
- if (n) return n;
272
- let r = za(t.headers), i = Ra({
273
- req: t,
274
- mode: r.mode,
275
- deps: e
276
- });
277
- if (i.refusal !== void 0) return i.refusal;
278
- if (t.headers["x-import-preflight"] === "1" || t.headers["x-import-preflight"] === "true") {
279
- let n;
280
- try {
281
- n = JSON.parse(Buffer.from(t.rawBody).toString("utf8") || "{}");
282
- } catch {
283
- return Z(400, { error: "a preflight body must be JSON: { tables: string[] } or { bundleKey: string }" });
284
- }
285
- let a = Array.isArray(n.tables) ? n.tables.filter((e) => typeof e == "string") : [];
286
- if (a.length === 0 && typeof n.bundleKey == "string" && n.bundleKey !== "" && e.openArchive && (a = [...await Ua(e.openArchive(n.bundleKey))]), a.length === 0) return Z(400, {
287
- error: "a preflight needs { tables: string[] } — the bundle's table names, so the staging decision can be made against them",
288
- hint: "or { bundleKey } on an instance with storage configured, where this endpoint reads the table list out of the archive itself"
289
- });
290
- let o = Yi({
291
- mode: r.mode ?? "upsert",
292
- ...e.dialect === void 0 ? {} : { targetDialect: e.dialect },
293
- ...e.snapshot === void 0 ? {} : { targetSnapshot: e.snapshot },
294
- bundleTables: a,
295
- isSkipped: Xi,
296
- canRunSql: !0
297
- });
298
- return Z(200, {
299
- preflight: !0,
300
- mode: r.mode ?? "upsert",
301
- atomic: r.atomic,
302
- staged: o.active,
303
- ...o.blocker === void 0 ? {} : { reason: o.blocker },
304
- stagedTables: o.tables.length,
305
- rollback: i.key === void 0 ? { taken: !1 } : {
306
- taken: !0,
307
- key: i.key
308
- },
309
- dialect: e.dialect ?? null
310
- });
311
- }
312
- let a = t.headers["x-import-upload-id"];
313
- if (a !== void 0 && a !== "") {
314
- if (Ca(), t.headers["x-import-probe"] === "1") {
315
- let e = await wa(a);
316
- return Z(200, {
317
- uploadId: a,
318
- bytes: e.bytes,
319
- ...e.runId === null ? {} : { runId: e.runId }
320
- });
321
- }
322
- let e = t.headers["x-import-upload-key"] ?? "", n = Number(t.headers["x-import-chunk-offset"] ?? "0");
323
- if (e === "" || !Number.isFinite(n) || n < 0) return Z(400, { error: "a chunked upload needs x-import-upload-key and a numeric x-import-chunk-offset" });
324
- let r = await ja({
325
- id: a,
326
- key: e,
327
- offset: n,
328
- bytes: t.rawBody
329
- });
330
- if ("reason" in r) return Q.warn("admin.import chunk refused", {
331
- uploadId: a,
332
- reason: r.reason
333
- }), Z(409, {
334
- error: "chunk refused",
335
- reason: r.reason,
336
- message: r.message,
337
- ...r.expectedOffset === void 0 ? {} : { expectedOffset: r.expectedOffset }
338
- });
339
- let i = t.headers["x-import-chunk-final"] === "1";
340
- return Z(202, {
341
- uploadId: a,
342
- bytes: r.total,
343
- complete: i
344
- });
345
- }
346
- if (t.rawBody.byteLength >= 8 && Buffer.from(t.rawBody.subarray(0, 8)).toString("latin1") === La) {
347
- Ca();
348
- let e = Ii("sha256").update(Buffer.from(t.rawBody)).digest("hex"), n = Aa(e);
349
- return Z(202, {
350
- uploadId: n,
351
- bytes: await ka(n, t.rawBody, e),
352
- complete: !0
353
- });
354
- }
355
- let o;
356
- try {
357
- o = JSON.parse(Buffer.from(t.rawBody).toString("utf8") || "{}");
358
- } catch {
359
- return Z(400, { error: "body must be a packed bundle archive or { bundleKey } JSON" });
360
- }
361
- return typeof o.bundleKey != "string" || !o.bundleKey ? Z(400, { error: "body.bundleKey (string) is required for the storage transport" }) : e.openArchive ? Z(202, {
362
- uploadId: Aa(o.bundleKey),
363
- bundleKey: o.bundleKey,
364
- complete: !0
365
- }) : Z(501, { error: "storage transport not configured on this instance" });
366
- }, Ua = async (e) => {
367
- let t = await Qi(e, ["manifest.json"]).then((e) => e.get("manifest.json"), () => void 0);
368
- if (t === void 0) return [];
369
- try {
370
- return (JSON.parse(Buffer.from(t).toString("utf8")).tables ?? []).map((e) => e.name).filter((e) => typeof e == "string");
371
- } catch {
372
- return [];
373
- }
374
- }, Wa = (e) => async (t) => {
375
- let n = ga(t, e.secret);
376
- if (n) return n;
377
- let r = za(t.headers), i = Ra({
378
- req: t,
379
- mode: r.mode,
380
- deps: e
381
- });
382
- if (i.refusal !== void 0) return i.refusal;
383
- let a;
384
- try {
385
- a = JSON.parse(Buffer.from(t.rawBody).toString("utf8") || "{}");
386
- } catch {
387
- return Z(400, { error: "body must be JSON: { uploadId } or { bundleKey }" });
388
- }
389
- let o = typeof a.bundleKey == "string" && a.bundleKey !== "" ? Aa(a.bundleKey) : typeof a.uploadId == "string" ? a.uploadId : "";
390
- if (!va(o)) return Z(400, { error: "start needs { uploadId } from an upload, or { bundleKey } for the storage transport" });
391
- let s = sr("dimp", `${o}-${Date.now()}-${Math.random()}`), c = await Da(o, s);
392
- if (c !== s) {
393
- let t = await Nn(e.store, c);
394
- if (Pn(t) === void 0 && t !== null) return Q.info("admin.import start: already running", {
395
- uploadId: o,
396
- runId: c
397
- }), Z(202, {
398
- runId: c,
399
- uploadId: o,
400
- alreadyStarted: !0
401
- });
402
- Q.info("admin.import start: taking over a claim whose run is not running", {
403
- uploadId: o,
404
- staleRunId: c,
405
- outcome: Pn(t) ?? "no record"
406
- }), c = await Da(o, s, { takeOver: !0 });
407
- }
408
- let l = async (e) => (await Oa(o).catch(() => void 0), e), u = await Ba(e, {
409
- ...typeof a.uploadId == "string" ? { uploadId: a.uploadId } : {},
410
- ...typeof a.bundleKey == "string" ? { bundleKey: a.bundleKey } : {}
411
- });
412
- if ("refusal" in u) return l(u.refusal);
413
- if (e.snapshot !== void 0 && !r.force) {
414
- let t = await Ga(u.source());
415
- if (t !== null) {
416
- let n = Ji(t.source?.schemaFingerprint ?? "", e.snapshot, Ka(t));
417
- if (n.drifted) return Q.warn("admin.import refused (schema drift)", {
418
- transport: u.transport,
419
- bundle: n.bundleFingerprint.slice(0, 16),
420
- target: n.targetFingerprint.slice(0, 16)
421
- }), l(Z(409, {
422
- error: "schema drift",
423
- bundleFingerprint: n.bundleFingerprint,
424
- targetFingerprint: n.targetFingerprint,
425
- diff: n.diff,
426
- hint: "each line above would break the load: a table or column the bundle carries that the target cannot take, or a column the target requires that the bundle has no value for. Fix the target schema, re-export against it, or resend with x-import-force: 1 to write anyway."
427
- }));
428
- }
429
- }
430
- let d = null;
431
- if (u.transport === "upload" && (d = await Fa(u.uploadId, c), d === null)) return l(Z(409, {
432
- error: "no such upload",
433
- message: `the bytes for upload '${u.uploadId}' are gone. Re-upload the bundle.`
434
- }));
435
- let f = await qa(e.store, {
436
- runId: c,
437
- mode: r.mode ?? "upsert",
438
- via: "api",
439
- bundle: u.transport === "storage" ? String(a.bundleKey) : u.uploadId
440
- });
441
- return Ja({
442
- deps: e,
443
- opts: r,
444
- rollback: i,
445
- runId: c,
446
- traced: f,
447
- resolved: d === null ? u : {
448
- ...u,
449
- source: () => Va(d)
450
- }
451
- }), Q.info("admin.import started", {
452
- runId: c,
453
- uploadId: u.uploadId,
454
- transport: u.transport,
455
- mode: r.mode ?? "upsert",
456
- atomic: r.atomic,
457
- dryRun: r.dryRun
458
- }), Z(202, {
459
- runId: c,
460
- uploadId: u.uploadId,
461
- transport: u.transport,
462
- mode: r.mode ?? "upsert",
463
- atomic: r.atomic,
464
- ...r.dryRun ? { dryRun: !0 } : {},
465
- recorded: f,
466
- outcome: "poll /_voltro/admin/transfers for this runId — a 202 means started, not finished"
467
- });
468
- }, Ga = async (e) => {
469
- let t = await Qi(e, ["manifest.json"]).then((e) => e.get("manifest.json"), () => null);
470
- if (t == null) return null;
471
- try {
472
- return JSON.parse(Buffer.from(t).toString("utf8"));
473
- } catch {
474
- return null;
475
- }
476
- }, Ka = (e) => ({ tables: (e.tables ?? []).map((e) => ({
477
- name: e.name,
478
- indexes: [],
479
- columns: Object.entries(e.columnTypes ?? {}).map(([e, t]) => ({
480
- name: e,
481
- type: t,
482
- nullable: !0,
483
- unique: !1,
484
- hasDefault: !1
485
- }))
486
- })) }), qa = async (e, t) => {
487
- try {
488
- return lr(rr), await e.insert(V, {
489
- id: t.runId,
490
- direction: "import",
491
- startedAt: /* @__PURE__ */ new Date(),
492
- finishedAt: null,
493
- failure: null,
494
- mode: t.mode,
495
- via: t.via,
496
- bundle: t.bundle,
497
- sourceFingerprint: null,
498
- tablesWritten: 0,
499
- rowsWritten: 0,
500
- staged: null
501
- }), !0;
502
- } catch (e) {
503
- return Q.warn("admin.import: the run could not be recorded", {
504
- runId: t.runId,
505
- error: e?.message ?? String(e)
506
- }), !1;
507
- }
508
- }, Ja = async (e) => {
509
- let { deps: t, opts: n, rollback: r, resolved: i, runId: a } = e, o = await import("node:os"), s = await import("node:fs/promises"), c = await import("node:path"), l = await s.mkdtemp(c.join(o.tmpdir(), "voltro-admin-import-")), u = async (n) => {
510
- Q.warn("admin.import failed", {
511
- runId: a,
512
- transport: i.transport,
513
- error: n
514
- }), e.traced && await t.store.update(V, a, {
515
- failure: n,
516
- finishedAt: null
517
- }).then(() => void 0, () => void 0);
518
- };
519
- try {
520
- t.assetSink ? await ra(i.source(), {
521
- dir: l,
522
- blobs: t.assetSink
523
- }) : await ia(i.source(), l);
524
- let o = await U.runPromiseExit(ea({
525
- store: t.store,
526
- bundleDir: l,
527
- ...n.mode ? { mode: n.mode } : {},
528
- ...n.onConflict ? { onConflict: n.onConflict } : {},
529
- atomic: n.atomic,
530
- ...r.options,
531
- recordInterruption: !0,
532
- via: "api",
533
- ...e.traced ? { traceId: a } : {},
534
- ...n.dryRun ? { dryRun: n.dryRun } : {},
535
- ...n.tables.length > 0 ? { tables: [...n.tables] } : {},
536
- ...t.snapshot ? { targetSnapshot: t.snapshot } : {},
537
- ...t.dialect ? { targetDialect: t.dialect } : {},
538
- force: n.force,
539
- onWarn: (e) => Q.warn("admin.import", {
540
- runId: a,
541
- message: e
542
- }),
543
- ...t.assetSink ? { assetsAlreadyRestored: !0 } : {}
544
- }));
545
- if (o._tag === "Failure") {
546
- let e = o.cause._tag === "Fail" ? o.cause.error : void 0, t = typeof e?.reason == "string" ? e.reason : void 0, n = e?.diff;
547
- await u(t ?? (Array.isArray(n) ? `schema drift: ${n.join("; ")}` : void 0) ?? String(e?.message ?? e ?? "import failed"));
548
- return;
549
- }
550
- let s = o.value;
551
- Q.info(n.dryRun ? "admin.import (dry run — nothing written)" : "admin.import complete", {
552
- runId: a,
553
- transport: i.transport,
554
- tables: s.tablesWritten,
555
- rows: s.rowsWritten,
556
- mode: n.mode ?? "upsert",
557
- atomic: n.atomic,
558
- ...s.tablesSkipped > 0 ? {
559
- skippedTables: s.tablesSkipped,
560
- skippedRows: s.rowsSkipped
561
- } : {}
562
- }), n.dryRun || t.refreshSubscriptions?.(`data import: ${s.tablesWritten} table(s), mode ${n.mode ?? "upsert"}`);
563
- } catch (e) {
564
- await u(e?.message ?? String(e));
565
- } finally {
566
- await s.rm(l, {
567
- recursive: !0,
568
- force: !0
569
- }).catch(() => void 0), await Ia(a).catch(() => void 0), await Oa(i.uploadId).catch(() => void 0);
570
- }
571
- }, Ya = /^[A-Za-z0-9_-]{8,64}$/, Xa = (e) => Ya.test(e), Za = () => process.env.VOLTRO_EXPORT_ARTIFACT_DIR ?? F.join(Ti.tmpdir(), "voltro-export-artifacts"), Qa = (e) => F.join(Za(), e), $a = (e) => F.join(Qa(e), "archive.bin"), eo = async (e = Date.now()) => {
572
- let t = 0;
573
- try {
574
- for (let n of await X.readdir(Za())) {
575
- let r = await X.stat(Qa(n)).catch(() => null);
576
- r !== null && (e - r.mtimeMs <= 864e5 || (await X.rm(Qa(n), {
577
- recursive: !0,
578
- force: !0
579
- }).catch(() => void 0), t++));
580
- }
581
- } catch {}
582
- return t;
583
- }, to = async (e, t) => {
584
- if (!Xa(e)) throw Error(`invalid run id: ${e}`);
585
- await X.mkdir(Qa(e), { recursive: !0 });
586
- let { createWriteStream: n } = await import("node:fs"), r = n($a(e)), i = 0;
587
- try {
588
- for await (let e of t) i += e.byteLength, r.write(Buffer.from(e)) || await new Promise((e, t) => {
589
- r.once("drain", e), r.once("error", t);
590
- });
591
- } finally {
592
- await new Promise((e, t) => {
593
- r.end(() => e()), r.once("error", t);
594
- });
595
- }
596
- return i;
597
- }, no = async (e) => {
598
- if (!Xa(e)) return null;
599
- let t = await X.stat($a(e)).catch(() => null);
600
- return t === null ? null : t.size;
601
- }, ro = async (e, t, n) => {
602
- let r = await no(e);
603
- if (r === null) return null;
604
- if (t >= r) return {
605
- bytes: Buffer.alloc(0),
606
- total: r
607
- };
608
- let i = await X.open($a(e), "r");
609
- try {
610
- let e = Math.max(0, Math.min(n, r - t)), a = Buffer.alloc(e);
611
- return await i.read(a, 0, e, t), {
612
- bytes: a,
613
- total: r
614
- };
615
- } finally {
616
- await i.close();
617
- }
618
- }, io = async (e) => {
619
- Xa(e) && await X.rm(Qa(e), {
620
- recursive: !0,
621
- force: !0
622
- }).catch(() => void 0);
623
- }, ao = I({ scope: "voltro:admin-export" }), oo = (e) => Array.isArray(e) ? e.filter((e) => typeof e == "string") : [], so = (e) => {
624
- if (typeof e.tenant == "string" && e.tenant) return {
625
- kind: "tenant",
626
- tenantId: e.tenant
627
- };
628
- if (Array.isArray(e.tables) && e.tables.length) return {
629
- kind: "tables",
630
- tables: oo(e.tables)
631
- };
632
- let t = oo(e.exclude);
633
- return t.length > 0 ? {
634
- kind: "all",
635
- exclude: t
636
- } : { kind: "all" };
637
- }, co = (e) => async (t) => {
638
- let n = ga(t, e.secret);
639
- if (n) return n;
640
- let r;
641
- try {
642
- r = JSON.parse(Buffer.from(t.rawBody).toString("utf8") || "{}");
643
- } catch {
644
- return Z(400, { error: "body must be JSON: { profile?, tenant?, tables?, consistency?, compression?, bundleKey? }" });
645
- }
646
- let i = {};
647
- if (typeof r.profile == "string" && r.profile) {
648
- if (!e.loadProfile) return Z(501, { error: "server-side profiles not configured on this instance" });
649
- try {
650
- i = await e.loadProfile(r.profile);
651
- } catch (e) {
652
- return Z(400, {
653
- error: `profile '${r.profile}' could not be loaded`,
654
- message: e?.message ?? String(e)
655
- });
656
- }
657
- }
658
- let a = r.consistency === "snapshot" ? "snapshot" : i.consistency ?? "live", o = (typeof r.compression == "string" ? r.compression : void 0) ?? i.compression, s = i.scope ?? so(r), c = typeof r.bundleKey == "string" && r.bundleKey.length > 0, l = r.assets === !0 && e.assetSource ? { blobs: e.assetSource } : {}, u = sr("dexp", `${Date.now()}-${Math.random()}`), d = await lo(e.store, {
659
- runId: u,
660
- mode: i.subset ? "subset" : s.kind,
661
- bundle: c ? String(r.bundleKey) : null
662
- });
663
- return uo({
664
- deps: e,
665
- runId: u,
666
- recorded: d,
667
- profile: i,
668
- scope: s,
669
- consistency: a,
670
- blobs: l,
671
- ...o ? { compression: o } : {},
672
- ...c ? { bundleKey: String(r.bundleKey) } : {}
673
- }), eo(), ao.info("admin.export started", {
674
- runId: u,
675
- scope: s.kind,
676
- storage: c
677
- }), Z(202, {
678
- runId: u,
679
- transport: c ? "storage" : "download",
680
- ...c ? { bundleKey: r.bundleKey } : {},
681
- recorded: d,
682
- outcome: "poll /_voltro/admin/transfers for this runId; fetch the bytes from /_voltro/admin/export/download"
683
- });
684
- }, lo = async (e, t) => {
685
- try {
686
- return lr(rr), await e.insert(V, {
687
- id: t.runId,
688
- direction: "export",
689
- startedAt: /* @__PURE__ */ new Date(),
690
- finishedAt: null,
691
- failure: null,
692
- mode: t.mode,
693
- via: "api",
694
- bundle: t.bundle,
695
- sourceFingerprint: null,
696
- tablesWritten: 0,
697
- rowsWritten: 0,
698
- staged: null
699
- }), !0;
700
- } catch (e) {
701
- return ao.warn("admin.export: the run could not be recorded", {
702
- runId: t.runId,
703
- error: e?.message ?? String(e)
704
- }), !1;
705
- }
706
- }, uo = async (e) => {
707
- let { deps: t, runId: n } = e, r = await import("node:os"), i = await import("node:fs/promises"), a = await import("node:path"), o = await i.mkdtemp(a.join(r.tmpdir(), "voltro-admin-export-")), s = async (r) => {
708
- e.recorded && await t.store.update(V, n, r).then(() => void 0, () => void 0);
709
- };
710
- try {
711
- let r = await U.runPromise($i({
712
- store: t.store,
713
- snapshot: t.snapshot,
714
- dialect: t.dialect,
715
- outDir: o,
716
- ...e.profile.subset ? { subset: e.profile.subset } : {
717
- scope: e.scope,
718
- ...t.tenantTables && t.tenantTables.length > 0 ? { tenantTables: t.tenantTables } : {}
719
- },
720
- consistency: e.consistency,
721
- ...e.compression ? { compression: e.compression } : {},
722
- ...e.profile.masking ? { masking: e.profile.masking } : {}
723
- })), i = r.tables.reduce((e, t) => e + t.rowCount, 0), a = r.masking?.transformed.length ?? 0;
724
- if (e.bundleKey !== void 0) {
725
- if (!t.putArchive) throw Error("storage transport not configured on this instance");
726
- await t.putArchive(e.bundleKey, () => Zi({
727
- dir: o,
728
- ...e.blobs
729
- }));
730
- }
731
- let c = await to(n, Zi({
732
- dir: o,
733
- ...e.blobs
734
- }));
735
- ao.info("admin.export complete", {
736
- runId: n,
737
- tables: r.tables.length,
738
- rows: i,
739
- masked: a,
740
- bytes: c,
741
- ...e.bundleKey === void 0 ? {} : { bundleKey: e.bundleKey }
742
- }), await s({
743
- finishedAt: /* @__PURE__ */ new Date(),
744
- failure: null,
745
- tablesWritten: r.tables.length,
746
- rowsWritten: i,
747
- sourceFingerprint: r.source?.schemaFingerprint ?? null
748
- });
749
- } catch (e) {
750
- let t = e?.message ?? String(e);
751
- ao.warn("admin.export failed", {
752
- runId: n,
753
- error: t
754
- }), await s({
755
- failure: t,
756
- finishedAt: null
757
- }), await io(n);
758
- } finally {
759
- await i.rm(o, {
760
- recursive: !0,
761
- force: !0
762
- }).catch(() => void 0);
763
- }
764
- }, fo = (e) => async (t) => {
765
- let n = ga(t, e.secret, "GET");
766
- if (n) return n;
767
- let r = new URLSearchParams(t.query ?? ""), i = r.get("runId") ?? "";
768
- if (!Xa(i)) return Z(400, { error: "download needs ?runId=<id> from the 202 the export answered with" });
769
- let a = Math.max(0, Number(r.get("offset") ?? "0") || 0), o = Number(r.get("length") ?? "8388608"), s = await ro(i, a, Number.isFinite(o) && o > 0 ? Math.min(o, mo) : po);
770
- return s === null ? Z(404, {
771
- error: "no artefact",
772
- message: `this instance holds no produced bundle for run '${i}'. It may have expired, or the export may still be running — poll the run first.`
773
- }) : {
774
- status: 200,
775
- contentType: "application/octet-stream",
776
- body: new Uint8Array(s.bytes),
777
- headers: {
778
- "x-export-total-bytes": String(s.total),
779
- "x-export-offset": String(a),
780
- "x-export-length": String(s.bytes.byteLength)
781
- }
782
- };
783
- }, po = 8388608, mo = 33554432, ho = async (e, t) => await e.query({
784
- table: V,
785
- order: [{
786
- column: "startedAt",
787
- direction: "desc"
788
- }],
789
- predicate: void 0,
790
- projection: void 0,
791
- skip: 0,
792
- take: t
793
- }), go = (e) => {
794
- let t = new Date(e);
795
- return Number.isFinite(t.getTime()) ? t : /* @__PURE__ */ new Date(0);
796
- }, _o = (e) => ({
797
- ...e,
798
- startedAt: go(e.startedAt),
799
- finishedAt: e.finishedAt === null || e.finishedAt === void 0 ? null : go(e.finishedAt)
800
- }), vo = (e) => async (t) => {
801
- let n = ga(t, e.secret, "GET");
802
- if (n) return n;
803
- let r = Number(new URLSearchParams(t.query ?? "").get("limit") ?? "20"), i = Number.isFinite(r) ? Math.max(1, Math.min(200, Math.trunc(r))) : 20, a;
804
- try {
805
- a = (await ho(e.store, i)).map(_o);
806
- } catch (e) {
807
- return Z(409, {
808
- error: "no import history",
809
- message: `this instance has no \`${V}\` table, so no import has been recorded. Run \`voltro db apply\` against it; imports themselves are unaffected.`,
810
- detail: e?.message ?? String(e)
811
- });
812
- }
813
- return Z(200, {
814
- running: a.filter((e) => e.finishedAt === null && e.failure === null).length,
815
- runs: a.map((e) => ({
816
- id: e.id,
817
- startedAt: e.startedAt.toISOString(),
818
- finishedAt: e.finishedAt === null ? null : e.finishedAt.toISOString(),
819
- mode: e.mode,
820
- via: e.via,
821
- bundle: e.bundle,
822
- sourceFingerprint: e.sourceFingerprint,
823
- tablesWritten: e.tablesWritten,
824
- rowsWritten: e.rowsWritten,
825
- direction: e.direction,
826
- failure: e.failure,
827
- staged: e.staged,
828
- line: cr(e)
829
- }))
830
- });
831
- }, yo = (e, t, n = {}) => (async function* () {
832
- let r = await U.runPromise(ji(e, t).pipe(U.timeout(n.openTimeout ?? "30 seconds"))), i = await Ni(r.stream), a = n.stallMs ?? 12e4, o, s = () => {
833
- o && clearTimeout(o), o = setTimeout(() => i.destroy(/* @__PURE__ */ Error(`storage read stalled for ${a}ms reading '${t}'`)), a);
834
- };
835
- try {
836
- s();
837
- for await (let e of i) s(), yield e instanceof Uint8Array ? e : new Uint8Array(e);
838
- } finally {
839
- o && clearTimeout(o), i.destroy();
840
- }
841
- })(), bo = {
842
- get: async () => void 0,
843
- set: async () => {},
844
- setWithTags: async () => {},
845
- remove: async () => !1,
846
- has: async () => !1,
847
- clear: async () => {},
848
- invalidateTag: async () => 0,
849
- wrap: async (e, t, n) => n()
850
- }, xo = async (e) => {
851
- Fe(e.appProcedures ?? e.discovered, {
852
- defaultDeny: e.security?.defaultDeny ?? !0,
853
- commandHint: "`voltro serve`"
854
- }), mi({
855
- dataStore: e.store,
856
- schemaRegistry: e.schemaRegistry
857
- });
858
- let t = (e.discovered.budgets?.length ?? 0) > 0, n, r = new xr({
859
- crdtColumnsOf: (t) => e.schemaRegistry.crdtColumns(t),
860
- store: e.store,
861
- ...e.snapshotCache ? { cache: e.snapshotCache } : {},
862
- ...e.reactive === void 0 ? {} : { reactive: e.reactive },
863
- ...t ? { recordCost: (e) => n?.record(e) } : {},
864
- recordDelivery: (e) => Y({
865
- label: e.label,
866
- kind: e.kind,
867
- durationMs: e.durationMs,
868
- rowCount: e.rowCount
869
- })
870
- }), i = e.cache ?? bo, a = e.kv ?? si, o, s = () => void 0, c, d, f, ee, te, ne, p, re = I({ scope: "voltro:workflow" }), ie = I({ scope: "voltro:schedule" }), ae = Ot({
871
- store: e.store,
872
- warn: (e, t) => re.warn(e, t)
873
- }), oe = ae.remember, se = ae.resolve, ce = pe({
874
- authority: e.authority,
875
- getStore: () => e.store
876
- }), g = (e.discovered.workflows?.length ?? 0) > 0 ? Xr(() => o) : void 0, fe = (e.discovered.workflows?.length ?? 0) > 0 || (e.discovered.eventTriggers?.length ?? 0) > 0, he = fe || (e.discovered.workflowWorkers?.length ?? 0) > 0 || e.scheduleCoordination === "cluster", be = e.tenantIsolation === "namespace", xe = (e.log ?? I({ scope: "voltro:serve" })).child("webhooks"), we, Ee, b = e.discovered.webhooks;
877
- if (b && b.outgoing.length > 0 && e.workflowEngineLayer !== void 0) {
878
- e.workflowEngineLayer;
879
- let t = Ze({
880
- store: e.store,
881
- schemaRegistry: e.schemaRegistry,
882
- cache: i,
883
- kv: a
884
- }), n = b.outgoing.map((e) => e.descriptor);
885
- Ee = Ui.toLayer(Bi(t, { events: n })), we = Vi(t, async (e) => {
886
- let t = f;
887
- if (t === void 0) {
888
- xe.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.", {
889
- deliveryId: e.deliveryId,
890
- targetId: e.targetId
891
- });
892
- return;
893
- }
894
- t.runPromise(Ui.execute(e)).catch((t) => {
895
- xe.error("deliverWebhook workflow crashed", {
896
- deliveryId: e.deliveryId,
897
- targetId: e.targetId
898
- }, t);
899
- });
900
- }, { events: n });
901
- }
902
- let De = /* @__PURE__ */ new Map();
903
- if (b) for (let e of b.incoming) {
904
- let t = e.descriptor.path ?? Hi(e.descriptor.id), n = `VOLTRO_WEBHOOK_SECRET_${e.descriptor.id.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`, r = Gi(e.descriptor, {
905
- resolveSecret: async () => process.env[n] ?? null,
906
- resolveWorkflows: () => g === void 0 ? void 0 : ai(g, {
907
- traceId: `incoming:${e.descriptor.id}`,
908
- source: `incoming:${e.descriptor.id}`
909
- }),
910
- log: (e) => {
911
- let t = {
912
- webhookId: e.webhookId,
913
- status: e.status,
914
- signatureOk: String(e.signatureOk),
915
- idempotency: e.idempotency,
916
- durationMs: e.durationMs
917
- };
918
- e.status >= 500 ? xe.error("incoming delivery failed", t) : e.status >= 400 ? xe.warn("incoming delivery rejected", t) : xe.info("incoming delivery handled", t);
919
- }
920
- });
921
- De.set(t, { handle: r });
922
- }
923
- zr(), li((t) => Br(e.store, t.subjectId, t.resourceType, t.resourceId)) || I({ scope: "voltro:serve" }).info("policy guards: using the app-registered tuple source");
924
- let Oe = [], ke = [...e.discovered.outboxHandlers ?? [], ...Dn((b?.outgoing.length ?? 0) + (b?.incoming.length ?? 0) + (b?.providers.length ?? 0), []) ? [{
925
- file: "<framework>/webhooks",
926
- id: "voltro-webhook-emit",
927
- definition: Wi(() => we)
928
- }] : []], je = ke.length > 0 ? u({
929
- handlers: ke,
930
- store: e.store,
931
- log: (e.log ?? I({ scope: "voltro:serve" })).child("outbox"),
932
- onChange: (t) => e.store.onChange((e) => t({
933
- table: e.table,
934
- op: e.op
935
- })),
936
- onShutdown: (e) => {
937
- Oe.push(e);
938
- }
939
- }) : void 0, x = S({
940
- definitions: (e.discovered.connections ?? []).map((e) => e.definition),
941
- store: e.store,
942
- publicUrl: ze(e.port ?? 4e3),
943
- log: (e.log ?? I({ scope: "voltro:serve" })).child("connections")
944
- });
945
- y({
946
- events: e.discovered.events ?? [],
947
- rpcTags: [
948
- ...e.discovered.queries.map((e) => e.descriptor.name),
949
- ...e.discovered.mutations.map((e) => e.descriptor.name),
950
- ...e.discovered.actions.map((e) => e.descriptor.name),
951
- ...(e.discovered.streams ?? []).map((e) => e.descriptor.name)
952
- ]
953
- });
954
- let Me = (e.log ?? I({ scope: "voltro:serve" })).child("events"), Pe = e.broadcastNamespace ?? He(e.plugins, void 0), Le = Lt(e.plugins, Pe, Me), Be = e.membership?.instanceId ?? process.env.POD_NAME ?? process.env.HOSTNAME ?? `serve-${process.pid}`, Ve = e.membership ?? Kt(e.plugins, {
955
- instanceId: Be,
956
- namespace: Pe,
957
- meta: { mode: "serve" },
958
- logger: Me
959
- }), C = ve({
960
- events: e.discovered.events ?? [],
961
- origin: Be,
962
- ...Le.publishRemote === void 0 ? {} : { publishRemote: Le.publishRemote }
963
- }), Ue = (e.discovered.events ?? []).length > 0 ? await Le.attach(C.bus) : null, We = It({
964
- store: e.store,
965
- schemaRegistry: e.schemaRegistry,
966
- cache: i,
967
- kv: a,
968
- ...we === void 0 ? {} : { webhooksService: we },
969
- ...g === void 0 ? {} : { workflowsProxy: g },
970
- eventTriggers: e.discovered.eventTriggers ?? [],
971
- namespaceIsolationOn: be,
972
- ...e.ensureTenantProvisioned === void 0 ? {} : { ensureTenantProvisioned: e.ensureTenantProvisioned },
973
- ...e.resolveResidentStore === void 0 ? {} : { resolveResidentStore: e.resolveResidentStore },
974
- ...je === void 0 ? {} : { outbox: { nudge: je.nudge } },
975
- ...x.active ? { connections: { registry: x.registry } } : {},
976
- eventBus: C.bus
977
- }), Ge = W.succeed(vr, Se), Ke = W.succeed(Sr, Ae), qe = W.succeed(yr, Gt), Je = W.succeed(Cr, m), Ye = (t, n) => {
978
- let r = t.pipe(U.provide(Yr(n)));
979
- return (e.baseLayer ? r.pipe(U.provide(e.baseLayer)) : r).pipe(U.provide(Ge)).pipe(U.provide(Ke)).pipe(U.provide(qe)).pipe(U.provide(Je));
980
- }, Xe = (e, t) => {
981
- let n = Ye(e, t);
982
- return fi(n);
983
- }, tt = wn(), rt = Re(e.plugins ?? [], tt), it = ue({
984
- plugins: e.plugins ?? [],
985
- metrics: tt,
986
- log: e.log ?? I({ scope: "voltro:serve" })
987
- }), at = Dt(e.plugins ?? [], tt), ot = e.security?.defaultDeny ?? !0, st = Qr({
988
- store: e.store,
989
- defaultDeny: ot,
990
- recordMetric: (e) => {
991
- tt.record(e);
992
- },
993
- ...rt.mutation === void 0 ? {} : { interceptor: rt.mutation },
994
- buildContext: (e, t, n) => We(e, t, n),
995
- runEffect: Xe,
996
- undoCapture: et((t) => e.schemaRegistry.crdtColumns(t))
997
- }), ct = l();
998
- {
999
- let t = Pt();
1000
- t !== void 0 && (e.log ?? I({ scope: "voltro:serve" })).info(t);
1001
- }
1002
- let lt = Te({
1003
- store: e.store,
1004
- ...e.approvals === void 0 ? {} : { defaultExpiryMs: e.approvals.defaultExpiryMs }
1005
- }), dt = Vr({
1006
- defaultDeny: ot,
1007
- buildContext: (e) => We(e),
1008
- runEffect: Xe,
1009
- recordMetric: (e) => {
1010
- tt.record(e);
1011
- },
1012
- ...rt.action === void 0 ? {} : { interceptor: rt.action }
1013
- }), ft = ei({
1014
- tenantScopedTables: e.tenantScopedTables,
1015
- softDeleteScopedTables: e.softDeleteScopedTables
1016
- }), pt = {
1017
- defaultDeny: ot,
1018
- buildContext: (e) => We(e),
1019
- finalize: (e, t) => ft(e, t.subject),
1020
- provideEffect: Ye,
1021
- ...rt.query === void 0 ? {} : { interceptor: rt.query }
1022
- }, T = q(pt), mt = $r({
1023
- ...pt,
1024
- queryRows: (t, n) => e.store.query(t).then((e) => yi(t.table, e, n.subject))
1025
- }), ht = ni({
1026
- ...pt,
1027
- subscribeDescriptor: (e, t, n, i, a) => r.subscribe(e, t, n, void 0, void 0, void 0, i, a),
1028
- subscribeComputed: (e, t, n) => r.subscribeComputed(e, t, n)
1029
- }), E = (e) => e.filter((e) => Gn(e.descriptor)), D = {};
1030
- for (let t of [
1031
- ...E(e.discovered.queries),
1032
- ...ct.queries,
1033
- ...lt.queries,
1034
- ...x.queries
1035
- ]) D[t.descriptor.name] = (e) => K(T(t, e), r, `subscription.${t.descriptor.name}`, void 0, void 0, ti(t, e));
1036
- for (let t of [
1037
- ...E(e.discovered.mutations),
1038
- ...ct.mutations,
1039
- ...lt.mutations,
1040
- ...x.mutations
1041
- ]) {
1042
- let n = Zr(t.descriptor.output);
1043
- D[t.descriptor.name] = (r) => G(async (e, n) => st(t, e, n), r, `mutation.${t.descriptor.name}`, n, e.idempotency, Jn(t.descriptor, "mutation"));
1044
- }
1045
- for (let t of [...E(e.discovered.actions), ...x.actions]) {
1046
- let n = Zr(t.descriptor.output);
1047
- D[t.descriptor.name] = (r) => G(async (e, n) => dt(t, e, n), r, `action.${t.descriptor.name}`, n, e.idempotency, Jn(t.descriptor, "action"));
1048
- }
1049
- let vt = () => `public-${Math.random().toString(36).slice(2, 10)}`, yt = [
1050
- ...e.discovered.queries.filter((e) => e.descriptor.publicApi !== void 0).map((e) => ({
1051
- descriptor: e.descriptor,
1052
- invoke: (t, n) => mt(e, t, {
1053
- subject: n.subject,
1054
- traceId: vt()
1055
- }),
1056
- subscribe: (t, n, r) => ht(e, t, {
1057
- subject: n.subject,
1058
- traceId: vt()
1059
- }, r)
1060
- })),
1061
- ...e.discovered.mutations.filter((e) => e.descriptor.publicApi !== void 0).map((e) => ({
1062
- descriptor: e.descriptor,
1063
- invoke: (t, n) => st(e, t, {
1064
- subject: n.subject,
1065
- traceId: vt()
1066
- })
1067
- })),
1068
- ...e.discovered.actions.filter((e) => e.descriptor.publicApi !== void 0).map((e) => ({
1069
- descriptor: e.descriptor,
1070
- invoke: (t, n) => dt(e, t, {
1071
- subject: n.subject,
1072
- traceId: vt()
1073
- })
1074
- }))
1075
- ], bt = {
1076
- candidates: v({
1077
- queries: e.discovered.queries,
1078
- mutations: e.discovered.mutations,
1079
- actions: e.discovered.actions,
1080
- descriptorOf: (e) => e.descriptor,
1081
- runQuery: (e, t, n) => Promise.resolve(mt(e, t, n)),
1082
- runMutation: (e, t, n) => Promise.resolve(st(e, t, n)),
1083
- runAction: (e, t, n) => Promise.resolve(dt(e, t, n))
1084
- }),
1085
- policy: e.agents?.tools ?? {},
1086
- mcpEnabled: e.agents?.mcp === !0,
1087
- resolveSubject: (t) => e.resolveSubject(t, -1).then((e) => e.subject)
1088
- };
1089
- if (e.grpc !== void 0) {
1090
- let t = () => `grpc-${Math.random().toString(36).slice(2, 10)}`, n = [
1091
- ...e.discovered.queries.map((e) => ({
1092
- tag: e.descriptor.name,
1093
- kind: "query",
1094
- input: e.descriptor.input,
1095
- output: e.descriptor.output,
1096
- invoke: (n, r, i) => mt(e, n, {
1097
- subject: r.subject,
1098
- traceId: t(),
1099
- signal: i
1100
- }),
1101
- subscribe: (n, r, i) => ht(e, n, {
1102
- subject: r.subject,
1103
- traceId: t()
1104
- }, i)
1105
- })),
1106
- ...e.discovered.mutations.map((e) => ({
1107
- tag: e.descriptor.name,
1108
- kind: "mutation",
1109
- input: e.descriptor.input,
1110
- output: e.descriptor.output,
1111
- invoke: (n, r, i) => st(e, n, {
1112
- subject: r.subject,
1113
- traceId: t(),
1114
- signal: i
1115
- })
1116
- })),
1117
- ...e.discovered.actions.map((e) => ({
1118
- tag: e.descriptor.name,
1119
- kind: "action",
1120
- input: e.descriptor.input,
1121
- output: e.descriptor.output,
1122
- invoke: async (n, r, i) => dt(e, n, {
1123
- subject: r.subject,
1124
- traceId: t(),
1125
- signal: i
1126
- })
1127
- }))
1128
- ];
1129
- await Wt({
1130
- config: e.grpc.config,
1131
- candidates: n,
1132
- resolveSubject: async (t) => {
1133
- let { subject: n } = await e.resolveSubject(t, -1), r = n;
1134
- return r.type === "anonymous" && r.credentialRejected !== void 0 ? null : {
1135
- subject: n,
1136
- anonymous: r.type === "anonymous"
1137
- };
1138
- },
1139
- store: e.store,
1140
- root: e.grpc.root,
1141
- log: e.log ?? I({ scope: "voltro:serve" }),
1142
- onShutdown: (e) => J(e)
1143
- });
1144
- }
1145
- let xt = ut({
1146
- ...e.restRoutes === void 0 ? {} : { restRoutes: e.restRoutes },
1147
- publicApiEntries: yt,
1148
- store: e.store,
1149
- resolveSubject: (t) => e.resolveSubject(t, -1).then((e) => e.subject),
1150
- ...e.idempotency === void 0 ? {} : { idempotency: e.idempotency },
1151
- log: e.log ?? I({ scope: "voltro:serve" })
1152
- }), O = e.dataTransferSecret ?? process.env.VOLTRO_DATA_TRANSFER_SECRET, Ct = async (e, t) => {
1153
- let { Readable: n } = await import("node:stream"), r = Oi(), i = Ai("storage", () => n.from(t()));
1154
- await U.runPromise(Mi(r, e, i, { contentType: "application/octet-stream" }));
1155
- }, wt = O && O.length >= 16 ? [
1156
- {
1157
- method: "POST",
1158
- path: la,
1159
- handle: Ha({
1160
- secret: O,
1161
- store: e.store,
1162
- ...e.dataTransferSnapshot ? { snapshot: e.dataTransferSnapshot } : {},
1163
- ...e.dataTransferDialect ? { dialect: e.dataTransferDialect } : {},
1164
- assetSink: ta(Oi()),
1165
- openArchive: (e) => yo(Oi(), e),
1166
- refreshSubscriptions: (e) => {
1167
- r.refreshAll(e);
1168
- },
1169
- putArchive: Ct,
1170
- ...e.dataTransferDialect ? { dialect: e.dataTransferDialect } : {}
1171
- })
1172
- },
1173
- {
1174
- method: "POST",
1175
- path: ua,
1176
- handle: Wa({
1177
- secret: O,
1178
- store: e.store,
1179
- ...e.dataTransferSnapshot ? { snapshot: e.dataTransferSnapshot } : {},
1180
- ...e.dataTransferDialect ? { dialect: e.dataTransferDialect } : {},
1181
- assetSink: ta(Oi()),
1182
- openArchive: (e) => yo(Oi(), e),
1183
- refreshSubscriptions: (e) => {
1184
- r.refreshAll(e);
1185
- },
1186
- putArchive: Ct
1187
- })
1188
- },
1189
- {
1190
- method: "GET",
1191
- path: pa,
1192
- handle: vo({
1193
- secret: O,
1194
- store: e.store
1195
- })
1196
- },
1197
- {
1198
- method: "GET",
1199
- path: fa,
1200
- handle: fo({ secret: O })
1201
- },
1202
- {
1203
- method: "POST",
1204
- path: da,
1205
- handle: co({
1206
- secret: O,
1207
- store: e.store,
1208
- snapshot: e.dataTransferSnapshot ?? { tables: [] },
1209
- dialect: e.dataTransferDialect ?? "memory",
1210
- tenantTables: [...e.tenantScopedTables],
1211
- loadProfile: Fn,
1212
- assetSource: na(Oi(), e.store),
1213
- putArchive: Ct
1214
- })
1215
- }
1216
- ] : [], Tt = [
1217
- ...e.httpRoutes ?? [],
1218
- ...xt.httpRoutes,
1219
- ...wt,
1220
- ...x.httpRoutes
1221
- ];
1222
- Object.assign(D, C.handlers);
1223
- for (let t of E(e.discovered.streams ?? [])) D[t.descriptor.name] = (n) => Ar((r) => Si(r, (r) => {
1224
- let i = We(r), a = t.executor(n, i);
1225
- if (U.isEffect(a)) {
1226
- let t = a.pipe(U.provide(Yr(i.store)));
1227
- return (e.baseLayer ? t.pipe(U.provide(e.baseLayer)) : t).pipe(U.provide(Ge)).pipe(U.provide(Ke)).pipe(U.provide(qe)).pipe(U.provide(Je));
1228
- }
1229
- return typeof a == "object" && a && typeof a.then == "function" ? U.promise(() => a) : a;
1230
- }), `stream.${t.descriptor.name}`);
1231
- for (let t of e.discovered.workflows ?? []) D[t.definition.name] = (e) => G(async (e, n) => {
1232
- let r = n;
1233
- return ai(g, {
1234
- subject: r.subject,
1235
- traceId: r.traceId,
1236
- source: "workflow-rpc"
1237
- }).start(t.definition.name, e);
1238
- }, e, `workflow.${t.definition.name}`);
1239
- fe && (D[Qn.name] = (e) => K(T({
1240
- descriptor: Qn,
1241
- executor: (e) => {
1242
- let t = e.id;
1243
- return {
1244
- table: "_voltro_workflow_runs",
1245
- order: [{
1246
- column: "startedAt",
1247
- direction: "desc"
1248
- }],
1249
- predicate: ur(H("id", t), H("executionId", t)),
1250
- take: 1,
1251
- skip: void 0,
1252
- projection: void 0
1253
- };
1254
- }
1255
- }, e), r, `subscription.${Qn.name}`), D[er.name] = (e) => K(T({
1256
- descriptor: er,
1257
- executor: (e) => {
1258
- let t = e, n = [...t.tag === void 0 ? [] : [H("tag", t.tag)], ...t.status === void 0 ? [] : [H("status", t.status)]], r = Number.isFinite(t.limit) && t.limit !== void 0 ? Math.min(Math.max(Math.floor(t.limit), 1), 500) : 100;
1259
- return {
1260
- table: "_voltro_workflow_runs",
1261
- order: [{
1262
- column: "startedAt",
1263
- direction: "desc"
1264
- }],
1265
- predicate: n.length === 0 ? void 0 : n.length === 1 ? n[0] : ar(...n),
1266
- take: r,
1267
- skip: void 0,
1268
- projection: void 0
1269
- };
1270
- }
1271
- }, e), r, `subscription.${er.name}`), D[$n.name] = (e) => K(T({
1272
- descriptor: $n,
1273
- executor: (e) => {
1274
- let t = e.runId;
1275
- return {
1276
- table: "_voltro_workflow_run_steps",
1277
- order: [{
1278
- column: "startedAt",
1279
- direction: "asc"
1280
- }],
1281
- predicate: H("runId", t),
1282
- take: 1e3,
1283
- skip: void 0,
1284
- projection: void 0
1285
- };
1286
- }
1287
- }, e), r, `subscription.${$n.name}`), D[Zn.name] = (e) => K(T({
1288
- descriptor: Zn,
1289
- executor: (e) => {
1290
- let t = e.runId;
1291
- return {
1292
- table: "_voltro_workflow_run_events",
1293
- order: [{
1294
- column: "occurredAt",
1295
- direction: "asc"
1296
- }],
1297
- predicate: H("runId", t),
1298
- take: 1e3,
1299
- skip: void 0,
1300
- projection: void 0
1301
- };
1302
- }
1303
- }, e), r, `subscription.${Zn.name}`), D[z.name] = (e) => K(T({
1304
- descriptor: z,
1305
- executor: (e) => {
1306
- let t = e;
1307
- return {
1308
- table: "_voltro_workflow_events",
1309
- order: [{
1310
- column: "occurredAt",
1311
- direction: "desc"
1312
- }],
1313
- predicate: t.name === void 0 ? void 0 : H("name", t.name),
1314
- take: Math.max(1, Math.min(500, t.limit ?? 100)),
1315
- skip: void 0,
1316
- projection: void 0
1317
- };
1318
- }
1319
- }, e), r, `subscription.${z.name}`), D[B.name] = (e) => K(T({
1320
- descriptor: B,
1321
- executor: (e) => {
1322
- let t = e.eventId;
1323
- return {
1324
- table: "_voltro_workflow_event_deliveries",
1325
- order: [{
1326
- column: "createdAt",
1327
- direction: "asc"
1328
- }],
1329
- predicate: H("eventId", t),
1330
- take: 500,
1331
- skip: void 0,
1332
- projection: void 0
1333
- };
1334
- }
1335
- }, e), r, `subscription.${B.name}`), D[Yn.name] = (t) => G(async (t, n) => {
1336
- let r = t;
1337
- return await gt(e.store, n.subject, { executionId: r.executionId }), await g.cancel(r.workflowName, r.executionId), await Rt(r.workflowName, r.executionId, "workflow.cancel"), { ok: !0 };
1338
- }, t, `action.${Yn.name}`), D[Xn.name] = (t) => G(async (t, n) => {
1339
- let r = t;
1340
- return await gt(e.store, n.subject, { executionId: r.executionId }), await g.resume(r.workflowName, r.executionId), { ok: !0 };
1341
- }, t, `action.${Xn.name}`), D[tr.name] = (t) => G(async (t, n) => {
1342
- let r = t;
1343
- return await gt(e.store, n.subject, { id: r.id }), g.signal({ id: r.id }, r.signalName, r.payload);
1344
- }, t, `action.${tr.name}`), D[nr.name] = (t) => G(async (t, n) => {
1345
- let r = t;
1346
- return await gt(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 });
1347
- }, t, `action.${nr.name}`));
1348
- let kt = [
1349
- ...E(e.discovered.queries).map((e) => R(e.descriptor)),
1350
- ...E(e.discovered.mutations).map((e) => Kn(e.descriptor)),
1351
- ...E(e.discovered.actions).map((e) => L(e.descriptor)),
1352
- ...ct.queries.map((e) => R(e.descriptor)),
1353
- ...ct.mutations.map((e) => Kn(e.descriptor)),
1354
- ...lt.queries.map((e) => R(e.descriptor)),
1355
- ...lt.mutations.map((e) => Kn(e.descriptor)),
1356
- ...x.queries.map((e) => R(e.descriptor)),
1357
- ...x.mutations.map((e) => Kn(e.descriptor)),
1358
- ...x.actions.map((e) => L(e.descriptor)),
1359
- ...E(e.discovered.streams ?? []).map((e) => qn(e.descriptor)),
1360
- ...C.rpcs,
1361
- ...(e.discovered.workflows ?? []).map((e) => Ci(e.definition)),
1362
- ...fe ? [
1363
- R(Qn),
1364
- R(er),
1365
- R($n),
1366
- R(Zn),
1367
- R(z),
1368
- R(B),
1369
- L(Yn),
1370
- L(Xn),
1371
- L(tr),
1372
- L(nr)
1373
- ] : []
1374
- ], At = Di.make(...kt).middleware(Hn).middleware(Un), jt = qr({ resolveSubject: ({ headers: t, clientId: n }) => e.resolveSubject(t, n) }), Mt = e.dormancyTenantId ?? br, Nt = e.dormancy === "sleep" ? {
1375
- register: (t, n, r) => ui(e.store, {
1376
- tenantId: r ?? Mt,
1377
- kind: "workflow",
1378
- refId: t,
1379
- wakeAt: n
1380
- }),
1381
- cancel: (t, n) => Mr(e.store, {
1382
- tenantId: n ?? Mt,
1383
- kind: "workflow",
1384
- refId: t
1385
- }).then(() => {})
1386
- } : void 0, k = he ? await import("@voltro/workflow") : void 0, A = k?.makeWorkflowRunRecorder({
1387
- store: e.store,
1388
- ...e.workflowRecording === void 0 ? {} : { recording: e.workflowRecording },
1389
- ...Nt === void 0 ? {} : { wakeups: Nt }
1390
- }), Ft = async (t, n) => {
1391
- await k.closeWorkflowChildrenForParent({
1392
- store: e.store,
1393
- parentExecutionId: t,
1394
- parentStatus: n,
1395
- recorder: A,
1396
- log: { warn: (e, t) => re.warn(e, t ?? {}) },
1397
- interruptChild: async (t, n) => {
1398
- let r = (e.discovered.workflows ?? []).find((e) => e.definition.name === t);
1399
- if (!r) throw Error(`Unknown child workflow: ${t}`);
1400
- if (!f) throw Error("Workflow runtime is not ready");
1401
- await f.runPromise(r.definition.interrupt(n));
1402
- }
1403
- });
1404
- }, Rt = async (t, n, r) => {
1405
- let i = (await e.store.query({
1406
- table: "_voltro_workflow_runs",
1407
- order: [],
1408
- predicate: H("executionId", n),
1409
- projection: void 0,
1410
- skip: void 0,
1411
- take: 1
1412
- }))[0];
1413
- if (i === void 0) return;
1414
- let a = await e.store.update("_voltro_workflow_runs", i.id, {
1415
- status: "cancelled",
1416
- cancelled: !0,
1417
- completedAt: /* @__PURE__ */ new Date()
1418
- }), o = i.subject?.tenantId ?? void 0;
1419
- a && await A.recordEvent({
1420
- runId: i.id,
1421
- eventType: "run-cancelled",
1422
- payload: {
1423
- reason: r,
1424
- workflowName: t,
1425
- executionId: n,
1426
- ...o == null ? {} : { tenantId: o }
1427
- }
1428
- }), a && await Ft(n, "cancelled");
1429
- }, zt = [
1430
- ...oi(e.discovered.workflows ?? [], {
1431
- buildContext: (t, n) => e.buildContextForWorkflow?.(t, n) ?? We({
1432
- subject: t.subject,
1433
- traceId: t.traceId
1434
- }, e.store, void 0, `workflow:${n.workflowName}`, { parentExecutionId: n.executionId }),
1435
- resolveStartContext: se,
1436
- ...ce === void 0 ? {} : { resolveAuthority: ce }
1437
- }, (t, n, r) => {
1438
- let i = k.getWorkflowVersionMetadata(t.definition);
1439
- return k.wrapWorkflowExecuteWithRunRecording({
1440
- name: t.definition.name,
1441
- store: e.store,
1442
- subject: r.subject,
1443
- source: r.source ?? null,
1444
- traceId: r.traceId,
1445
- workflowVersion: i.version,
1446
- workflowCompatibleVersions: i.compatibleWith,
1447
- workflowPatches: i.patches,
1448
- parentExecutionId: r?.parentExecutionId ?? null,
1449
- parentClosePolicy: r?.parentClosePolicy ?? null,
1450
- onParentClose: ({ executionId: e, status: t }) => Ft(e, t),
1451
- ...j(t.definition),
1452
- onTerminal: async ({ executionId: e }) => {
1453
- await d?.gate.release(e);
1454
- },
1455
- recorder: A,
1456
- pluginWorkflowStepLayer: at,
1457
- recordRun: ci
1458
- }, n);
1459
- }),
1460
- ...e.discovered.workflowWorkers ?? [],
1461
- ...Ee === void 0 ? [] : [Ee]
1462
- ], Bt = [...(e.discovered.workflows ?? []).map((e) => e.definition.name).filter(Boolean), ...Ee === void 0 ? [] : ["voltro.deliverWebhook"]], Ht = zt.length > 0 ? W.mergeAll(...zt) : W.empty;
1463
- if (((e.discovered.workflows?.length ?? 0) > 0 || (e.discovered.workflowWorkers?.length ?? 0) > 0 || e.scheduleCoordination === "cluster" || Ee !== void 0) && e.workflowEngineLayer !== void 0) {
1464
- let t = Ht.pipe(W.provideMerge(e.workflowEngineLayer));
1465
- f = fr.make((e.baseLayer === void 0 ? t : t.pipe(W.provideMerge(e.baseLayer))).pipe(W.provideMerge(Vn({})))), await f.runPromise(U.void), (e.log ?? I({ scope: "voltro:serve" })).child("workflow").info(`workflow runtime ready — ${Bt.length} entity type(s) registered`, { entities: Bt });
1466
- let n = await import("@voltro/workflow/cluster"), r = (e) => f.runPromise(n.redriveFailedRun(e)), i = (e) => f.runPromise(n.resumeRunFromStep(e));
1467
- ne = await Vt({
1468
- provider: zi(e.plugins ?? [])?.broadcast?.provider,
1469
- crossReplica: zi(e.plugins ?? [])?.broadcast?.crossReplica ?? !1,
1470
- namespace: Pe,
1471
- replicaId: crypto.randomUUID(),
1472
- pollStorage: () => f.runPromise(n.pollWorkflowStorage),
1473
- onChange: (t) => e.store.onChange((e) => t({
1474
- table: e.table,
1475
- op: e.op,
1476
- ...e.origin === void 0 ? {} : { origin: e.origin }
1477
- })),
1478
- log: (e.log ?? I({ scope: "voltro:serve" })).child("workflow")
1479
- }), ee = async (t) => {
1480
- let n = await Ie({
1481
- store: e.store,
1482
- workflows: e.discovered.workflows ?? [],
1483
- runRedrive: r
1484
- }, t.runId);
1485
- return n.statusReset && await A.recordEvent({
1486
- runId: t.runId,
1487
- eventType: "run-redriven",
1488
- payload: {
1489
- reason: "inspect.redrive",
1490
- activitiesReset: n.outcome.activitiesReset
1491
- }
1492
- }), {
1493
- redriven: n.outcome.redriven,
1494
- activitiesReset: n.outcome.activitiesReset,
1495
- reason: n.outcome.reason
1496
- };
1497
- }, te = async (t) => {
1498
- let n = await le({
1499
- store: e.store,
1500
- workflows: e.discovered.workflows ?? [],
1501
- runResume: i
1502
- }, t.runId, t.step);
1503
- return n.statusReset && await A.recordEvent({
1504
- runId: t.runId,
1505
- eventType: "run-redriven",
1506
- payload: {
1507
- reason: "inspect.resume-from-step",
1508
- step: n.stepName,
1509
- activitiesReset: n.outcome.activitiesReset
1510
- }
1511
- }), {
1512
- redriven: n.outcome.redriven,
1513
- stepName: n.stepName,
1514
- activitiesReset: n.outcome.activitiesReset,
1515
- reason: n.outcome.reason
1516
- };
1517
- };
1518
- let a = (e.scheduleCoordination ?? "single") === "advisoryLock" ? Hr(e.store, e.scheduleReplicaId ?? `pid-${process.pid}`) : gi, l = Jr({
1519
- coordinator: a,
1520
- replicaId: e.scheduleReplicaId ?? `pid-${process.pid}`
1521
- }), u = I({ scope: "voltro:flow-control" }), p = {
1522
- info: (e, t) => {
1523
- u.info(e, t);
1524
- },
1525
- warn: (e, t) => {
1526
- u.warn(e, t);
1527
- },
1528
- error: (e, t) => {
1529
- u.error(e, t ?? {});
1530
- }
1531
- }, m, re = () => {
1532
- if (m !== void 0) return m;
1533
- if (o !== void 0 && A !== void 0) return m = _({
1534
- store: e.store,
1535
- log: P,
1536
- workflows: e.discovered.workflows ?? [],
1537
- workflowsProxy: o,
1538
- workflowRuntime: f,
1539
- workflowRunRecorder: A,
1540
- closeChildrenForParent: Ft
1541
- }), m;
1542
- };
1543
- s = re, d = w({
1544
- store: e.store,
1545
- onChange: (t) => e.store.onChange((e) => t({
1546
- table: e.table,
1547
- op: e.op
1548
- })),
1549
- ...e.scheduling === void 0 ? {} : {
1550
- disarmWhenIdle: e.scheduling.disarmWhenIdle,
1551
- drainIntervalMs: e.scheduling.admissionDrainMs,
1552
- cancelSweepIntervalMs: e.scheduling.cancelSweepMs,
1553
- stalenessSweepIntervalMs: e.scheduling.stalenessSweepMs
1554
- },
1555
- workflows: e.discovered.workflows ?? [],
1556
- facade: () => o,
1557
- cancelRunWithReason: re,
1558
- recordRunEvent: () => A?.recordEvent,
1559
- ...e.workflowStaleness === void 0 ? {} : { staleness: e.workflowStaleness },
1560
- ...e.workflowSuspendSignalHintMs === void 0 ? {} : { suspendSignalHintMs: e.workflowSuspendSignalHintMs },
1561
- scheduleCoordinated: l,
1562
- onAbandoned: async (t) => {
1563
- await _t({
1564
- workflows: e.discovered.workflows ?? [],
1565
- facade: () => o,
1566
- log: p,
1567
- ...t
1568
- });
1569
- },
1570
- log: p
1571
- });
1572
- let h = d;
1573
- h !== void 0 && J(() => h.stop()), c = Et({
1574
- store: e.store,
1575
- onChange: (t) => e.store.onChange((e) => t({
1576
- table: e.table,
1577
- op: e.op
1578
- })),
1579
- ...e.scheduling === void 0 ? {} : {
1580
- disarmWhenIdle: e.scheduling.disarmWhenIdle,
1581
- tickIntervalMs: e.scheduling.inferenceTickMs
1582
- },
1583
- enabled: (e.discovered.workflows?.length ?? 0) > 0,
1584
- resumeSignal: () => f === void 0 || k === void 0 ? void 0 : async ({ executionId: t, workflowName: n, signalName: r, payload: i }) => {
1585
- await f.runPromise(k.completeSuspendingSignal({
1586
- store: e.store,
1587
- target: nt(t, n),
1588
- signalName: r,
1589
- payload: i
1590
- }));
1591
- },
1592
- runEffect: (e) => f.runPromise(e),
1593
- scheduleCoordinated: l,
1594
- log: p
1595
- });
1596
- let ie = c;
1597
- ie !== void 0 && J(() => ie.stop()), o = (e.discovered.workflows?.length ?? 0) > 0 ? ii({
1598
- workflows: e.discovered.workflows ?? [],
1599
- runEffect: (e) => f.runPromise(e),
1600
- onEnqueue: () => ne?.publishWake(),
1601
- ...h === void 0 ? {} : {
1602
- admitStart: h.gate.admitStart,
1603
- startPayloadSchema: h.gate.startPayloadSchema,
1604
- parkDelayedStart: h.gate.parkDelayed
1605
- },
1606
- rememberStartContext: oe,
1607
- signal: async (t, n, r) => {
1608
- let i = await k.sendWorkflowSignal({
1609
- store: e.store,
1610
- recorder: A,
1611
- target: t,
1612
- signalName: n,
1613
- payload: r
1614
- });
1615
- return await f.runPromise(k.completeSuspendingSignal({
1616
- store: e.store,
1617
- target: t,
1618
- signalName: n,
1619
- payload: r
1620
- })).catch(() => {}), i;
1621
- },
1622
- update: (t, n, r, i) => k.sendWorkflowUpdate({
1623
- store: e.store,
1624
- recorder: A,
1625
- target: t,
1626
- updateName: n,
1627
- payload: r,
1628
- ...i === void 0 ? {} : { options: i }
1629
- }),
1630
- listRuns: (t) => Ne(e.store, t),
1631
- retry: (t, n) => me({
1632
- store: e.store,
1633
- workflows: e.discovered.workflows ?? [],
1634
- runPromise: (e) => f.runPromise(e)
1635
- }, t, n),
1636
- redrive: (t) => Ie({
1637
- store: e.store,
1638
- workflows: e.discovered.workflows ?? [],
1639
- runRedrive: r
1640
- }, t).then((e) => e.outcome)
1641
- }) : void 0;
1642
- }
1643
- let Ut = W.mergeAll(At.toLayer(D), jt), qt = St(D, e.discovered.queries.map((e) => e.descriptor.name), fe), Jt = W.mergeAll(At.toLayer(qt), jt), M = e.observability, Yt = await jr({
1644
- ...e.appName === void 0 ? {} : { serviceName: e.appName },
1645
- ...M && M.spanProcessors.length > 0 ? { extraSpanProcessors: M.spanProcessors } : {},
1646
- ...M && M.metricReaders.length > 0 ? { extraMetricReaders: M.metricReaders } : {},
1647
- ...M && Object.keys(M.resourceAttributes).length > 0 ? { resourceAttributes: M.resourceAttributes } : {},
1648
- ...M && M.sampler !== void 0 ? { sampler: M.sampler } : {}
1649
- }), Xt = !1, Zt = e.store.ping ? () => e.store.ping().then(() => !0).catch(() => !1) : void 0, { server: Qt, shutdown: $t } = _i({
1650
- group: At,
1651
- handlersLayer: Ut,
1652
- httpHandlersLayer: Jt,
1653
- port: e.port ?? 4e3,
1654
- ...e.host === void 0 ? {} : { host: e.host },
1655
- path: e.path ?? "/ws",
1656
- tracerLayer: Yt.layer,
1657
- security: de(e),
1658
- ...Cn(e),
1659
- ...e.discovered.wsGateways !== void 0 && e.discovered.wsGateways.length > 0 ? { webSocketGateways: e.discovered.wsGateways } : {},
1660
- resolveGatewaySubject: async (t) => {
1661
- let n = await e.resolveSubject(t, -1);
1662
- return n.subject.type === "anonymous" ? null : {
1663
- subject: n.subject,
1664
- ...n.credentialExpiresAt === void 0 ? {} : { credentialExpiresAt: n.credentialExpiresAt * 1e3 }
1665
- };
1666
- },
1667
- ...it,
1668
- healthCheck: {
1669
- isReady: () => Xt,
1670
- ...Zt ? { ping: Zt } : {}
1671
- },
1672
- ...Tt.length > 0 ? { httpRoutes: Tt } : {},
1673
- ...e.getStore === void 0 ? {} : { getStore: e.getStore },
1674
- ...De.size > 0 ? { webhookRoutes: De } : {},
1675
- ...e.inspectRoute === void 0 ? {} : { inspectRoute: e.inspectRoute }
1676
- }), N = ca(Qt);
1677
- if (await kr(Qt), (e.discovered.schedules?.length ?? 0) > 0) {
1678
- let t = (e.scheduleCoordination ?? "single") === "advisoryLock" ? Hr(e.store, e.scheduleReplicaId ?? `pid-${process.pid}`) : gi;
1679
- p = await vi(e.discovered.schedules ?? [], {
1680
- store: e.store,
1681
- coordinator: t,
1682
- defaultTrigger: e.scheduleDefaultTrigger ?? "self",
1683
- replicaId: e.scheduleReplicaId ?? `pid-${process.pid}`,
1684
- armSelf: e.scheduleArmSelf ?? !0,
1685
- dormancy: e.dormancy ?? "always-on",
1686
- ...e.dormancyTenantId === void 0 ? {} : { dormancyTenantId: e.dormancyTenantId },
1687
- buildContext: ({ traceId: t, scheduleName: n, subject: r }) => We({
1688
- subject: r,
1689
- traceId: t
1690
- }, e.store, void 0, `schedule:${n}`),
1691
- log: {
1692
- info: (e, t) => {
1693
- ie.info(e, t);
1694
- },
1695
- warn: (e, t) => {
1696
- ie.warn(e, t);
1697
- },
1698
- error: (e, t) => {
1699
- ie.error(e, t ?? {});
1700
- },
1701
- debug: () => {}
1702
- },
1703
- ...e.scheduleFireInterceptor === void 0 ? {} : { interceptFire: e.scheduleFireInterceptor },
1704
- ...e.onScheduleRunEvent === void 0 ? {} : { onRunEvent: e.onScheduleRunEvent }
1705
- }), e.onSchedulerReady?.(p);
1706
- }
1707
- let P = e.log ?? I({ scope: "voltro:serve" }), en, tn;
1708
- if ((e.discovered.subscribers?.length ?? 0) > 0 && (en = $e(e.discovered.subscribers ?? [], e.store, P.child("subscribe"), e.schemaRegistry, C.bus)), (e.discovered.reactions?.length ?? 0) > 0) {
1709
- let t = P.child("reaction"), n = async (n, r) => {
1710
- if (n.kind === "workflow") {
1711
- if (g === void 0) {
1712
- t.warn("reaction workflow act skipped — no workflow engine in this app", { workflow: n.workflow });
1713
- return;
1714
- }
1715
- let e = n.payload === void 0 ? r.new ?? r.old ?? {} : n.payload(r);
1716
- await ai(g, {
1717
- traceId: `reaction:${n.workflow}`,
1718
- source: `reaction:${n.workflow}`
1719
- }).start(n.workflow, e);
1720
- return;
1721
- }
1722
- await ye(n.agent, r, {
1723
- findAgentSend: (t) => e.discovered.actions.find((e) => e.descriptor.name === `${t}.send`),
1724
- runAction: (e, t, n) => Promise.resolve(dt(e, t, n)),
1725
- makeSubject: (e) => Wn(e),
1726
- now: () => Date.now(),
1727
- log: t
1728
- });
1729
- }, r = async (n, r) => {
1730
- try {
1731
- let { requireAiBudget: t } = await import("@voltro/ai");
1732
- return (await U.runPromise(U.either(t(e.store, {
1733
- tenantId: n,
1734
- limitUsd: r
1735
- }))))._tag === "Right";
1736
- } catch (e) {
1737
- return t.warn("reaction budget check failed — refusing the act", { tenantId: n }, e), !1;
1738
- }
1739
- }, i = Qe(e.store, { onError: (e) => t.warn("reaction: rate-slot claim failed; refusing the act", { cause: String(e) }) });
1740
- tn = _e(e.discovered.reactions ?? [], e.store, {
1741
- runAct: n,
1742
- checkBudget: r,
1743
- claimRateSlot: (e) => i.claim(e)
1744
- }, t);
1745
- }
1746
- let nn;
1747
- (e.discovered.aggregates?.length ?? 0) > 0 && (nn = await h({
1748
- discovered: e.discovered.aggregates ?? [],
1749
- store: e.store,
1750
- log: P.child("aggregate"),
1751
- ...e.analytics === void 0 ? {} : { analytics: e.analytics },
1752
- ...e.aggregateStorage === void 0 ? {} : { storage: e.aggregateStorage },
1753
- ...e.aggregateCoordinator === void 0 ? {} : { coordinator: e.aggregateCoordinator }
1754
- }), Ge = W.succeed(vr, nn.registry));
1755
- let rn;
1756
- (e.discovered.expectations?.length ?? 0) > 0 && (rn = Er({
1757
- discovered: e.discovered.expectations ?? [],
1758
- store: e.store,
1759
- log: P.child("expectation")
1760
- }), Ke = W.succeed(Sr, rn.registry)), (e.discovered.budgets?.length ?? 0) > 0 && (n = Or({
1761
- discovered: e.discovered.budgets ?? [],
1762
- log: P.child("finops")
1763
- }), qe = W.succeed(yr, n.registry));
1764
- let an;
1765
- return (e.discovered.experiments?.length ?? 0) > 0 && (an = Dr({
1766
- discovered: e.discovered.experiments ?? [],
1767
- store: e.store,
1768
- log: P.child("experiment")
1769
- }), Je = W.succeed(Cr, an.registry)), Xt = !0, e.bootTiming?.mark("ready"), {
1770
- dispatcher: r,
1771
- server: Qt,
1772
- scheduler: p,
1773
- eventsSnapshot: Ce(C.bus, C.declared),
1774
- membersSnapshot: () => ({
1775
- members: Ve.membership.list(),
1776
- capturedAt: Date.now()
1777
- }),
1778
- agentTools: () => bt,
1779
- rpcMetrics: () => tt,
1780
- webhooksService: () => we,
1781
- runCanceller: () => s(),
1782
- flowControlHealth: () => d?.cancelHealth(),
1783
- inferenceHealth: () => c?.health(),
1784
- workflowWriteActions: () => g === void 0 || A === void 0 ? void 0 : ge({
1785
- store: e.store,
1786
- log: P,
1787
- workflows: e.discovered.workflows ?? [],
1788
- workflowsProxy: o,
1789
- workflowRuntime: f,
1790
- workflowRunRecorder: A,
1791
- closeChildrenForParent: Ft
1792
- }),
1793
- redriveWorkflowRun: (e) => ee ? ee(e) : Promise.reject(/* @__PURE__ */ Error("redrive: this app registers no workflows")),
1794
- resumeWorkflowRunFromStep: (e) => te ? te(e) : Promise.reject(/* @__PURE__ */ Error("resume-from-step: this app registers no workflows")),
1795
- close: async () => {
1796
- Xt = !1, await N.drainRequests();
1797
- for (let e of Oe) try {
1798
- await e();
1799
- } catch (e) {
1800
- P.warn("serve: teardown step failed", {}, e);
1801
- }
1802
- await Ue?.detach(), await Ve.detach(), nn?.detach(), rn?.detach(), n?.detach(), an?.detach(), tn?.(), en?.(), await p?.shutdown(), r.close(), await ne?.detach(), await f?.dispose(), await $t(), await N.finish();
1803
- }
1804
- };
1805
- }, $ = I({ scope: "voltro:serve" }), So = (e, t, n) => (e === "production" || e === "staging") && t !== "memory" && n !== "0", Co = Xt, wo = async (e) => {
1806
- let t = jn(process.cwd());
1807
- if (zn(t)) {
1808
- let n;
1809
- try {
1810
- let e = await import(Bn(t).href);
1811
- typeof e.runServe == "function" ? n = e.runServe : $.warn("serve bundle has no runServe export — using the standard serve path");
1812
- } catch (e) {
1813
- $.warn("serve bundle failed to load — using the standard serve path", {}, e);
1814
- }
1815
- if (n) return $.info("serve: booting from the precompiled serve bundle"), n(e);
1816
- }
1817
- return To(e);
1818
- }, To = async (l) => {
1819
- let u = Mn();
1820
- e("serve");
1821
- try {
1822
- Fi();
1823
- } catch (e) {
1824
- throw i(e instanceof Error ? e.message : String(e));
1825
- }
1826
- let m = process.cwd(), h = await qe(m), le = Zt({
1827
- kind: "api",
1828
- configPort: h?.port,
1829
- env: process.env,
1830
- flagPort: Co(l, "--port")
1831
- });
1832
- for (let e of le.warnings) $.warn(e);
1833
- let ue = le.port;
1834
- pi(di(h?.secrets)), await Qt({
1835
- rawEnv: h?.env,
1836
- appType: "api",
1837
- root: m,
1838
- log: $,
1839
- generateTypes: !1
1840
- }), u.mark("config");
1841
- let _ = (process.env.DB_DIALECT ?? h?.store ?? "memory").toLowerCase(), pe = (_ === "mariadb" || _ === "postgres" || _ === "mssql") && (process.env.CDC ?? "1") !== "0", me = _ === "mariadb" ? "mariadb" : _ === "mssql" ? "mssql" : void 0, ge = An(m);
1842
- if (!r() && zn(ge)) try {
1843
- let e = await import(Bn(ge).href);
1844
- if (e.modules) {
1845
- let t = {};
1846
- for (let [n, r] of Object.entries(e.modules)) t[Ln(m, n)] = r;
1847
- n(t), $.info("precompiled api bundle loaded", { modules: Object.keys(t).length });
1848
- }
1849
- } catch (e) {
1850
- $.warn("precompiled api bundle failed to load — falling back to source", {}, e);
1851
- }
1852
- let v = await wt(m), y = await Ft(v, { cdc: pe && me !== void 0 }), _e = te(y);
1853
- {
1854
- Xe({
1855
- plugins: h?.plugins ?? [],
1856
- queries: y.queries,
1857
- mutations: y.mutations,
1858
- actions: y.actions,
1859
- streams: y.streams,
1860
- log: $
1861
- });
1862
- let e = he(y.serverOnlyLeaks, g(process.env, "strict"), Fr, "`voltro serve`");
1863
- if (e.action === "fail") throw i(e.message ?? "");
1864
- e.action === "warn" && $.warn(e.message ?? "");
1865
- }
1866
- let ve = v.filter((e) => kn.test(e)), ye = ve.length > 0 ? await On(ve, $.child("webhooks")) : {
1867
- outgoing: [],
1868
- incoming: [],
1869
- providers: []
1870
- }, Se = En(y.events), Ce = ye.outgoing.length + ye.incoming.length + ye.providers.length + Se.length === 0 ? void 0 : {
1871
- ...ye,
1872
- outgoing: [...ye.outgoing, ...Se]
1873
- }, Te = un({
1874
- nodeEnv: process.env.NODE_ENV,
1875
- cdcDialect: me,
1876
- declared: h?.schema
1877
- }), Ae = dn({
1878
- gates: Te,
1879
- runtime: {
1880
- traces: se(),
1881
- undo: bi()
1882
- }
1883
- });
1884
- if (Ae !== void 0) throw i(`serve: ${Ae}`);
1885
- let Ne = ln({
1886
- mix: y.featureMix,
1887
- plugins: h?.plugins ?? [],
1888
- gates: Te,
1889
- ...me ? { cdcDialect: me } : {}
1890
- }), Fe = h?.analytics !== void 0 && h.analytics.kind !== "noop" && _ !== "memory" ? (await N(_)).makeSqlLayer(O()) : void 0, Ie = await bt({
1891
- spec: h?.analytics,
1892
- sqlLayer: Fe,
1893
- log: $
1894
- }), S = (() => {
1895
- let e = new Set(y.tables.map((e) => e.tableName)), t = [...y.tables];
1896
- for (let n of [...Ne, ...Ie.tables]) e.has(n.tableName) || (e.add(n.tableName), t.push(n));
1897
- return t;
1898
- })();
1899
- for (let e of S) lr(e);
1900
- {
1901
- let e = Ir(xi(x(y), ae(S)));
1902
- e !== void 0 && $.warn(e);
1903
- }
1904
- let Re = (process.env.NODE_ENV ?? "").toLowerCase();
1905
- if (So(Re, _, process.env.VOLTRO_AUTO_MIGRATE)) {
1906
- let e = (await N(_)).makeSqlLayer(O()), t = await U.runPromise(pr.SqlClient.pipe(U.flatMap((e) => gr(e, m)), U.provide(e), U.catchAll(() => U.succeed([]))));
1907
- t.length > 0 && ($.error(`serve: refusing to boot — ${t.length} pending file-based migration(s) have never run against this database. They perform the changes a schema diff cannot infer (data moves, backfills, table splits), so the declarative fingerprint check below cannot see them and would have let this process serve un-migrated data.`, { pending: t }), $.error("Run them from your pre-deploy job — `voltro db migrate .` (schema + files) or `voltro db files .` (files alone) — or set VOLTRO_AUTO_MIGRATE=0 to bypass every boot schema check. `voltro serve` never applies them itself: a rolling deploy would start N replicas and each would try."), process.exit(1));
1908
- let n = await U.runPromise(pr.SqlClient.pipe(U.flatMap((e) => _r(e, S, {
1909
- appliedBy: `serve:${Re}`,
1910
- environment: "prod",
1911
- dialectId: _
1912
- })), U.provide(e)));
1913
- n.kind === "prod-mismatch" && ($.error(hr(n, _)), $.error(fn({
1914
- gates: Te,
1915
- nodeEnv: process.env.NODE_ENV,
1916
- cdcDialect: me,
1917
- declared: h?.schema
1918
- })), $.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(hr(n, _));
1919
- }
1920
- await rn({
1921
- dialectId: _,
1922
- tables: S,
1923
- mode: tn(h?.reactiveTriggers),
1924
- lockSchema: O().schema,
1925
- makeLayer: async () => (await N(_)).makeSqlLayer(O()),
1926
- log: {
1927
- info: (e, t) => $.info(e, t ?? {}),
1928
- warn: (e, t) => $.warn(e, t ?? {})
1929
- }
1930
- });
1931
- let ze = ri(S);
1932
- u.mark("discover");
1933
- let w = await lt(h, void 0);
1934
- {
1935
- let e = await c(w);
1936
- if (e !== void 0) throw i(`serve: ${e}`);
1937
- let t = await s(w, _, h);
1938
- t !== void 0 && $.warn(t);
1939
- }
1940
- let Ze = wi(w, _);
1941
- for (let e of qt({
1942
- dialect: String(h?.store ?? process.env.DB_DIALECT ?? "postgres"),
1943
- changeStrategy: (process.env.CDC ?? "1") === "0" ? "inline" : "cdc",
1944
- dbUrl: process.env.DB_URL,
1945
- crossReplicaBus: zi(h?.plugins ?? [])?.broadcast.crossReplica === !0,
1946
- tables: y.tables.map((e) => ({
1947
- tableName: e.tableName,
1948
- isReactive: e.isReactive === !0
1949
- })),
1950
- querySources: y.queries.flatMap((e) => {
1951
- let t = e.descriptor.source;
1952
- return t === void 0 ? [] : typeof t == "string" ? [t] : [...t];
1953
- })
1954
- })) e.level === "warn" ? $.warn(e.message) : $.info(e.message);
1955
- {
1956
- let e = C({
1957
- tables: ir().map((e) => ({ tableName: e.tableName })),
1958
- queries: y.queries.map((e) => ({
1959
- name: e.descriptor.name,
1960
- source: e.descriptor.source
1961
- }))
1962
- }), t = Rt(e);
1963
- t !== void 0 && $.warn(t);
1964
- }
1965
- h?.cache && !process.env.CACHE_BACKEND && (process.env.CACHE_BACKEND = h.cache), h?.cacheRedisUrl && !process.env.CACHE_REDIS_URL && (process.env.CACHE_REDIS_URL = h.cacheRedisUrl), h?.cacheRedisDriver && !process.env.CACHE_REDIS_DRIVER && (process.env.CACHE_REDIS_DRIVER = h.cacheRedisDriver), h?.cacheKeyPrefix && !process.env.CACHE_KEY_PREFIX && (process.env.CACHE_KEY_PREFIX = h.cacheKeyPrefix);
1966
- let { service: Qe, invalidationBus: $e, snapshotCache: et, cache: nt, semantic: ut, evictSource: gt, backend: _t, stats: St, dispose: Et } = await it({
1967
- env: process.env,
1968
- semantic: h?.cacheSemantic ?? !1
1969
- });
1970
- ut !== void 0 && $.info("semantic cache enabled — reactive eviction on live writes"), $.info(`cache backend resolved: ${_t}` + (_t === "redis" ? ` (driver ${process.env.CACHE_REDIS_DRIVER ?? "resp"})` : " — in-process, not cross-instance")), w.onChange((e) => {
1971
- if (U.runFork($e.publish(e.table)), gt !== void 0) {
1972
- let t = (e.new ?? e.old)?.id;
1973
- gt({
1974
- table: e.table,
1975
- op: e.op,
1976
- ...t === void 0 ? {} : { id: t }
1977
- });
1978
- }
1979
- }), h?.kv && !process.env.KV_BACKEND && (process.env.KV_BACKEND = h.kv), h?.kvRedisUrl && !process.env.KV_REDIS_URL && (process.env.KV_REDIS_URL = h.kvRedisUrl), h?.kvKeyPrefix && !process.env.KV_KEY_PREFIX && (process.env.KV_KEY_PREFIX = h.kvKeyPrefix);
1980
- let { kv: Dt, service: Ot } = await Kr({ store: w });
1981
- ht({
1982
- log: $,
1983
- max: en(),
1984
- outOfPool: xe(_, (process.env.CDC ?? "1") !== "0"),
1985
- readPools: t.replicationSnapshot()?.replicaCount ?? 0,
1986
- always: !0
1987
- }), u.mark("store");
1988
- let Pt = Tr({
1989
- store: w,
1990
- sink: Ie.sink,
1991
- log: $
1992
- }), It = st({
1993
- store: w,
1994
- dialect: _,
1995
- log: { info: (e) => $.info(e) }
1996
- }), j = h?.plugins ?? [], Lt = process.env.POD_NAME ?? process.env.HOSTNAME ?? `serve-${process.pid}`, Vt, Wt;
1997
- _ !== "memory" && (Vt = fr.make((await N(_)).makeSqlLayer(O()).pipe(W.provideMerge(Vn({})))), Wt = await Vt.runPromise(pr.SqlClient));
1998
- let Gt = [
1999
- "postgres",
2000
- "mariadb",
2001
- "mysql",
2002
- "mssql"
2003
- ].includes(_) ? Hr(w, Lt, $) : gi, Xt = Jt(h?.scheduling), Cn = Jr({
2004
- maxIdleIntervalMs: Xt.pollCeilingMs,
2005
- coordinator: Gt,
2006
- replicaId: Lt,
2007
- log: $
2008
- }), Dn = [], jn = process.env.POD_NAME ?? process.env.HOSTNAME ?? `serve-${process.pid}`, Nn = zi(h?.plugins ?? [])?.broadcast?.provider, Pn = He(h?.plugins, h?.name ?? In(m));
2009
- {
2010
- let e = rt(h?.plugins, h?.name ?? In(m));
2011
- e !== void 0 && $.warn(e);
2012
- }
2013
- let Fn = Kt(h?.plugins, {
2014
- instanceId: jn,
2015
- namespace: Pn,
2016
- meta: { mode: "serve" },
2017
- logger: $
2018
- }), F = Sn({
2019
- mode: "serve",
2020
- dialect: _,
2021
- ...Nn === void 0 ? {} : { provider: Nn },
2022
- logger: $
2023
- });
2024
- J(async () => {
2025
- await F.stop();
2026
- }), vt(h?.reactive), Tt(h);
2027
- let Rn = {
2028
- ...Wt ? { sql: Wt } : {},
2029
- instanceId: jn,
2030
- membership: Fn.membership,
2031
- ...Nn === void 0 ? {} : { broadcast: Nn },
2032
- broadcastChannels: { presence: Ri(Pn, "presence") },
2033
- scheduleCoordinated: (e, t, n) => {
2034
- let r = Cn(e, t, n);
2035
- return Dn.push(r), r;
2036
- }
2037
- };
2038
- for (let e of j) e.bindDataStore?.(Ze, Rn);
2039
- ft({
2040
- store: w,
2041
- ...d(),
2042
- log: $
2043
- });
2044
- let Hn = j.filter((e) => typeof e.onChangeEvent == "function");
2045
- if (Hn.length > 0) {
2046
- let e = w.changeScope ?? "local";
2047
- w.onChange((t) => {
2048
- let n = ce(t, e);
2049
- for (let e of Hn) U.runFork(e.onChangeEvent(n).pipe(U.catchAllCause((t) => U.sync(() => $.warn(`plugin ${e.name} onChangeEvent failed`, { error: dr.pretty(t) })))));
2050
- });
2051
- }
2052
- let Un = v.filter((e) => mn.test(e));
2053
- Un.length > 0 && (await Ve(Un, $), $.info(`queue: ${Un.length} consumer file(s) loaded`));
2054
- let L = Le({
2055
- plugins: j,
2056
- appName: h?.name ?? "voltro-api",
2057
- appType: "api",
2058
- voltroVersion: process.env.npm_package_version ?? "0.0.0",
2059
- log: $
2060
- });
2061
- j.length && await L.activate(), u.mark("plugins");
2062
- let Wn = await L.gatherObservability(), Gn = I({ scope: "voltro:broadcast" }), Kn = {
2063
- info: (e, t) => {
2064
- Gn.info(e, t);
2065
- },
2066
- warn: (e, t) => {
2067
- Gn.warn(e, t);
2068
- },
2069
- debug: () => {}
2070
- }, R, qn = await D(w, h, _, Pn, Kn, (e, t) => {
2071
- R?.refreshAll(`broadcast gap: missed ${t} change(s) from ${e}`);
2072
- }), Jn = h?.apiKeys, Yn = (typeof Jn == "object" ? Jn.prefix : void 0) ?? "voltro_", z = Jn ? Pr(w) : void 0, B = z ? Wr({ flush: Gr(z) }) : void 0;
2073
- B && J(() => B.shutdown());
2074
- let Xn = z ? Ur(z, {
2075
- prefix: Yn,
2076
- ...B ? { usage: B } : {}
2077
- }) : void 0, Zn = Xn ? [Lr(Xn, { prefix: Yn })] : [], Qn = kt([...h?.auth?.strategies ?? [], ...Zn], Ki(h?.plugins ?? []), h?.auth?.anonymousTenantRequired ?? !1, h?.auth, () => Ze), $n = [...h?.restRoutes ?? [], ...Xn ? wr(Xn, (typeof Jn == "object" ? Jn.managementPath : void 0) ?? "/v1/api-keys") : []], er = Ue(h?.idempotency, w), tr = j.map((e) => e.services).filter((e) => e !== void 0), nr = W.mergeAll(Je({
2078
- analyticsLayer: Ie.layer,
2079
- cacheService: Qe,
2080
- kvService: Ot,
2081
- ...ut === void 0 ? {} : { semanticCache: ut },
2082
- pluginServices: tr,
2083
- userLayers: h?.layers ?? []
2084
- }), Mt(h?.http ?? {})), V = await Ct({
2085
- files: v,
2086
- store: w,
2087
- log: $,
2088
- seedPolicy: "report",
2089
- seedPattern: pn,
2090
- loadSeedFiles: nn,
2091
- startupPattern: yn,
2092
- loadStartupFiles: a,
2093
- runStartups: o,
2094
- emailPattern: Nt,
2095
- loadEmailFiles: Ye,
2096
- registerEmailTemplates: qi
2097
- });
2098
- (V.startupCount > 0 || V.emailCount > 0) && $.info("boot lifecycle", {
2099
- startups: V.startupCount,
2100
- emailTemplates: V.emailCount
2101
- }), V.startups !== void 0 && J(async () => {
2102
- await V.startups.stop();
2103
- }), De({
2104
- demands: Yt(_e),
2105
- isRegistered: (e) => Rr(e) !== void 0
2106
- });
2107
- let rr = dt({
2108
- schedules: We({
2109
- schedules: y.schedules,
2110
- seeds: V.seeds,
2111
- store: w,
2112
- log: $.child("seeds")
2113
- }),
2114
- workflows: y.workflows ?? [],
2115
- log: $.child("workflow-schedules")
2116
- }), ar = h?.scheduling ?? {}, sr = ar.trigger ?? "self", cr = /* @__PURE__ */ new Set([
2117
- "postgres",
2118
- "mysql",
2119
- "mariadb",
2120
- "mssql"
2121
- ]), H = ar.coordination ?? (cr.has(_) ? "advisoryLock" : "single"), ur = H === "cluster" && cr.has(_), vr = ur ? "cluster" : H === "advisoryLock" && cr.has(_) ? "advisoryLock" : "single";
2122
- H === "cluster" && !ur && $.warn("scheduling.coordination=cluster needs a sql-backed store except sqlite — falling back to single"), H === "advisoryLock" && !cr.has(_) && $.warn("scheduling.coordination=advisoryLock needs a SQL store (the claim-row gate) — falling back to single");
2123
- let yr, br = y.workflows.length > 0 || y.workflowWorkers.length > 0 || y.eventTriggers.length > 0 || (Ce?.outgoing.length ?? 0) > 0 || ur, xr;
2124
- if (br) {
2125
- if (_ === "mssql") {
2126
- let e = await Tn(process.cwd());
2127
- e && $.warn(e);
2128
- }
2129
- let [{ WorkflowEngine: e }, { makeClusterCronLayer: t, workflowEngineLayer: n, resolveRunnerStorage: r, resolveFailoverTuning: i }] = await Promise.all([import("@effect/workflow"), import("@voltro/workflow/cluster")]), a = ur ? rr.filter((e) => (e.trigger ?? sr) === "self").map((e) => t({
2130
- name: e.name,
2131
- cron: Nr(e),
2132
- execute: async () => {
2133
- await yr?.fireFromCluster(e.name);
2134
- }
2135
- })) : [];
2136
- xr = _ === "memory" ? e.layerMemory : await (async () => {
2137
- let e = await N(_), t = r({ sqliteFamily: e.id === "sqlite" || e.id === "turso" });
2138
- 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({
2139
- sqlClientLayer: e.makeSqlLayer(O()),
2140
- runnerStorage: t,
2141
- dialectId: e.id,
2142
- ...process.env.VOLTRO_WORKFLOW_RUNNER_PORT ? { runnerListenPort: Number(process.env.VOLTRO_WORKFLOW_RUNNER_PORT) } : {},
2143
- ...i(),
2144
- ...a.length > 0 ? { extraShardingLayers: a } : {}
2145
- });
2146
- })();
2147
- }
2148
- let Sr = fe(j, wn()), Cr = v.filter((e) => /\.subscribe\.tsx?$/.test(e)), Er = Cr.length > 0 ? await A(Cr, $) : [], Dr = v.filter((e) => /\.reaction\.tsx?$/.test(e)), Or = Dr.length > 0 ? await we(Dr, $) : [], kr = v.filter((e) => hn.test(e)), G = kr.length > 0 ? await Ee(kr, $) : [], Ar = v.filter((e) => /\.aggregate\.tsx?$/.test(e)), K = Ar.length > 0 ? await E(Ar, $) : [];
2149
- {
2150
- let e = Ir(xi(x({ aggregates: K.map((e) => e.definition) }), ae(S)));
2151
- e !== void 0 && $.warn(e);
2152
- }
2153
- let jr = ee();
2154
- if (K.length > 0 && _ !== "memory") try {
2155
- let e = (await N(_)).makeSqlLayer(O());
2156
- jr = T(e);
2157
- } catch (e) {
2158
- $.warn("aggregate: SQL storage init failed — falling back to in-process", { err: String(e) });
2159
- }
2160
- let Mr = _ === "memory" ? gi : Hr(w, `aggregate@${process.pid}`, $), zr = v.filter((e) => gn.test(e)), Br = zr.length > 0 ? await Me(zr, $) : [], Vr = v.filter((e) => _n.test(e)), qr = Vr.length > 0 ? await Ht(Vr, $) : [], Yr = v.filter((e) => vn.test(e)), Xr = Yr.length > 0 ? await oe(Yr, $) : [], Zr = [], Qr = [], $r = v.filter((e) => an.test(e));
2161
- if ($r.length > 0) {
2162
- let e = $.child("agent"), t = v.filter((e) => cn.test(e));
2163
- t.length > 0 && await on(t, e);
2164
- let n = await sn($r, e);
2165
- for (let e of n.agents) for (let t of xt(e)) (t.kind === "action" ? Zr : Qr).push({
2166
- file: t.file,
2167
- descriptor: t.descriptor,
2168
- executor: t.executor
2169
- });
2170
- n.agents.length > 0 && e.info("synthesized agent routes", { agents: n.agents.map((e) => e.descriptor.name) });
2171
- }
2172
- u.mark("workflow");
2173
- let q = () => {
2174
- let e = Y.workflowWriteActions();
2175
- if (e === void 0) throw Error("workflow actions: this app registers no workflows");
2176
- return e;
2177
- }, ei = or({
2178
- dialect: _,
2179
- ...O()
2180
- }), ti = _ === "memory" ? void 0 : (await N(_)).makeSqlLayer(O()), ni = async () => jt({
2181
- sqlLayer: ti,
2182
- declared: S,
2183
- log: $
2184
- }), ii = {
2185
- kind: "api",
2186
- meta: {
2187
- name: h?.name ?? "voltro-api",
2188
- voltroVersion: k,
2189
- port: ue,
2190
- mode: "start",
2191
- store: _,
2192
- cdc: pe ? "on" : "off",
2193
- ...ei === void 0 ? {} : { databaseId: ei }
2194
- },
2195
- rpc: ke(y, m),
2196
- workflows: p(y, m),
2197
- migrations: ni,
2198
- events: () => Y.eventsSnapshot(),
2199
- agentTools: () => Y.agentTools(),
2200
- invariantChecks: () => ({
2201
- mode: "serve",
2202
- accessGate: _e,
2203
- config: h,
2204
- serverOnlyLeaks: y.serverOnlyLeaks,
2205
- migrations: ni
2206
- }),
2207
- members: () => Y.membersSnapshot(),
2208
- inspectFireSchedule: async ({ name: e, trigger: t }) => {
2209
- if (!yr) throw Error("scheduler not started — this app registers no self-triggered schedules (all schedules are trigger:'external', or there are none).");
2210
- return { runId: await yr.fireNow(e, t) ?? null };
2211
- },
2212
- inspectBackfillSchedule: re({
2213
- getHandle: () => yr,
2214
- getSchedules: () => rr
2215
- }),
2216
- ...Ce === void 0 ? {} : { webhooks: () => mt({
2217
- store: w,
2218
- discoveredWebhooks: Ce
2219
- }) },
2220
- plugins: () => ({
2221
- plugins: L.snapshot(),
2222
- capturedAt: Date.now()
2223
- }),
2224
- env: () => $t(h?.name ?? In(m), {
2225
- ...h?.env !== void 0 && Pi(h.env) ? { contract: h.env } : {},
2226
- plugins: h?.plugins ?? []
2227
- }),
2228
- dataCache: () => Ut({
2229
- stats: St,
2230
- backendKind: _t
2231
- }),
2232
- subscriptions: () => Oe(() => R),
2233
- inspectTables: () => b(S),
2234
- inspectRows: M({
2235
- store: w,
2236
- tables: S,
2237
- mask: !0
2238
- }),
2239
- metrics: (e) => Y.rpcMetrics().snapshot(e),
2240
- cluster: () => Ge({
2241
- store: w,
2242
- dialect: _,
2243
- useClusterCron: ur,
2244
- scheduleCoordChoice: H
2245
- }),
2246
- inspectSchedules: () => ie({
2247
- schedules: rr,
2248
- defaultTrigger: sr,
2249
- coordination: vr
2250
- }),
2251
- inspectScheduleRuns: (e) => je(w, e),
2252
- ...Bt(w, {
2253
- controls: at(y.workflows ?? []),
2254
- active: (y.workflows?.length ?? 0) > 0,
2255
- cancellation: () => Y.flowControlHealth()
2256
- }),
2257
- webhookActions: ne(() => Y.webhooksService()),
2258
- inspectStartWorkflow: (e) => q().inspectStartWorkflow(e),
2259
- inspectCancelWorkflowRun: (e) => q().inspectCancelWorkflowRun(e),
2260
- inspectSuspendWorkflowRun: (e) => q().inspectSuspendWorkflowRun(e),
2261
- inspectResumeWorkflowRun: (e) => q().inspectResumeWorkflowRun(e),
2262
- inspectDiscardWorkflowRun: (e) => q().inspectDiscardWorkflowRun(e),
2263
- inspectRetryWorkflowRun: (e) => q().inspectRetryWorkflowRun(e),
2264
- inspectSignalWorkflowRun: (e) => q().inspectSignalWorkflowRun(e),
2265
- inspectUpdateWorkflowRun: (e) => q().inspectUpdateWorkflowRun(e),
2266
- inspectInferences: (e) => yt({
2267
- store: w,
2268
- active: (y.workflows?.length ?? 0) > 0,
2269
- dispatcher: () => Y.inferenceHealth()
2270
- }, e.limit === void 0 ? {} : { limit: e.limit }),
2271
- ...ct({
2272
- store: w,
2273
- cancelRun: async (e) => await Y.runCanceller()?.(e) ?? !1,
2274
- retryRun: async (e) => q().inspectRetryWorkflowRun({ runId: e }),
2275
- redriveRun: async (e) => Y.redriveWorkflowRun({ runId: e }),
2276
- log: $
2277
- }),
2278
- inspectRedriveWorkflowRun: (e) => Y.redriveWorkflowRun(e),
2279
- inspectResumeWorkflowRunFromStep: (e) => Y.resumeWorkflowRunFromStep(e)
2280
- }, ai = (process.env.VOLTRO_TENANT_ISOLATION ?? h?.tenancy?.isolation) === "namespace", oi = ai && _ !== "memory" ? await (async () => {
2281
- let e = await N(_);
2282
- return tt({
2283
- tables: S,
2284
- sqlLayer: e.makeSqlLayer(O()),
2285
- dialect: _,
2286
- options: { retryFilter: e.retryFilter },
2287
- log: {
2288
- info: (e, t) => $.info(e, t),
2289
- error: (e, t, n) => $.error(e, t ?? {}, n)
2290
- }
2291
- });
2292
- })() : void 0, si = await ot({
2293
- input: h?.tenancy?.residency,
2294
- namespaceIsolationOn: ai,
2295
- makeStoreForUrl: (e, t) => lt(h, void 0, P(O(), t)),
2296
- log: {
2297
- info: (e, t) => $.info(e, t),
2298
- warn: (e, t) => $.warn(e, t)
2299
- }
2300
- });
2301
- si !== void 0 && J(async () => {
2302
- await si.close();
2303
- });
2304
- let Y = await xo({
2305
- bootTiming: u,
2306
- broadcastNamespace: Pn,
2307
- scheduling: (() => {
2308
- let e = Xt;
2309
- return {
2310
- admissionDrainMs: e.admissionDrainMs,
2311
- inferenceTickMs: e.inferenceTickMs,
2312
- cancelSweepMs: e.cancelSweepMs,
2313
- stalenessSweepMs: e.stalenessSweepMs,
2314
- disarmWhenIdle: zt({
2315
- changeScope: w.changeScope,
2316
- broadcastAttached: qn !== void 0
2317
- })
2318
- };
2319
- })(),
2320
- ...h?.workflows?.staleness === void 0 ? {} : { workflowStaleness: h.workflows.staleness },
2321
- ...h?.workflows?.suspendSignalHintMs === void 0 ? {} : { workflowSuspendSignalHintMs: h.workflows.suspendSignalHintMs },
2322
- workflowRecording: Ke(h?.workflows?.recording),
2323
- membership: {
2324
- ...Fn,
2325
- instanceId: jn
2326
- },
2327
- security: {
2328
- defaultDeny: Pe(h),
2329
- ...de(h)
2330
- },
2331
- approvals: { defaultExpiryMs: Be(h) },
2332
- ...h?.plugins === void 0 ? {} : { plugins: h.plugins },
2333
- ...er ? { idempotency: er } : {},
2334
- restRoutes: $n,
2335
- ...h?.grpc === void 0 ? {} : { grpc: {
2336
- config: h.grpc,
2337
- root: m
2338
- } },
2339
- appProcedures: _e,
2340
- discovered: {
2341
- wsGateways: y.wsGateways,
2342
- queries: [...y.queries, ...Qr],
2343
- mutations: y.mutations,
2344
- actions: [...y.actions, ...Zr],
2345
- streams: y.streams,
2346
- events: y.events,
2347
- workflows: y.workflows,
2348
- workflowWorkers: y.workflowWorkers,
2349
- eventTriggers: y.eventTriggers,
2350
- schedules: rr,
2351
- subscribers: Er,
2352
- outboxHandlers: G,
2353
- connections: y.connections,
2354
- reactions: Or,
2355
- aggregates: K,
2356
- expectations: Br,
2357
- budgets: qr,
2358
- experiments: Xr,
2359
- ...Ce === void 0 ? {} : { webhooks: Ce }
2360
- },
2361
- log: $,
2362
- analytics: Ie.sink,
2363
- aggregateStorage: jr,
2364
- aggregateCoordinator: Mr,
2365
- store: w,
2366
- kv: Dt,
2367
- cache: nt,
2368
- snapshotCache: et,
2369
- ...h?.reactive === void 0 ? {} : { reactive: h.reactive },
2370
- schemaRegistry: ze,
2371
- tenantScopedTables: y.tenantScopedTables,
2372
- softDeleteScopedTables: y.softDeleteScopedTables,
2373
- dataTransferSnapshot: mr(S, _),
2374
- dataTransferDialect: _,
2375
- ...oi === void 0 ? {} : { ensureTenantProvisioned: oi.ensure },
2376
- ...si === void 0 ? {} : { resolveResidentStore: si.resolveStore },
2377
- tenantIsolation: (process.env.VOLTRO_TENANT_ISOLATION ?? h?.tenancy?.isolation) === "namespace" ? "namespace" : "shared-schema",
2378
- resolveSubject: (e, t) => Qn({
2379
- headers: e,
2380
- clientId: t
2381
- }),
2382
- ...h?.auth === void 0 ? {} : { authority: h.auth },
2383
- ...h?.agents === void 0 ? {} : { agents: h.agents },
2384
- httpRoutes: j.flatMap((e) => e.httpRoutes ?? []),
2385
- getStore: () => Ze,
2386
- ...nr ? { baseLayer: nr } : {},
2387
- ...xr === void 0 ? {} : { workflowEngineLayer: xr },
2388
- scheduleDefaultTrigger: sr,
2389
- scheduleCoordination: vr,
2390
- scheduleArmSelf: !ur,
2391
- dormancy: process.env.VOLTRO_DORMANCY === "sleep" || process.env.VOLTRO_DORMANCY === "always-on" ? process.env.VOLTRO_DORMANCY : h?.dormancy ?? "always-on",
2392
- scheduleReplicaId: process.env.HOSTNAME ?? `pid-${process.pid}`,
2393
- ...Sr === void 0 ? {} : { scheduleFireInterceptor: Sr },
2394
- onSchedulerReady: (e) => {
2395
- yr = e;
2396
- },
2397
- inspectRoute: { handle: async (e, t, n, r) => await be(e, ii, t, {
2398
- method: n,
2399
- ...r === void 0 ? {} : { body: r }
2400
- }) || ((n === "GET" ? await xn(e, ii, t, { method: n }) : null) ?? bn(e, ii, t, {
2401
- method: n,
2402
- ...r === void 0 ? {} : { body: r }
2403
- }) ?? {
2404
- status: 404,
2405
- contentType: "application/json",
2406
- body: JSON.stringify({ error: "not an inspect route" })
2407
- }) },
2408
- ...h?.name === void 0 ? {} : { appName: h.name },
2409
- observability: Wn,
2410
- port: ue,
2411
- ...h?.transport?.wsPath ? { path: h.transport.wsPath } : {},
2412
- ...h?.http === void 0 ? {} : { http: h.http }
2413
- });
2414
- return R = Y.dispatcher, pt(f([
2415
- y.queries,
2416
- y.mutations,
2417
- y.actions,
2418
- y.streams
2419
- ]), (e) => {
2420
- $.warn(e);
2421
- }), $.info(`API listening on :${ue}`, {
2422
- dialect: _,
2423
- queries: y.queries.length,
2424
- mutations: y.mutations.length,
2425
- actions: y.actions.length,
2426
- streams: y.streams.length,
2427
- workflows: y.workflows.length,
2428
- workflowWorkers: y.workflowWorkers.length,
2429
- schedules: rr.length,
2430
- scheduleCoordination: vr
2431
- }), u.finish($), J(async () => {
2432
- for (let e of Dn) e.stop();
2433
- It.stop();
2434
- try {
2435
- await Y.close(), Et(), Vt?.dispose(), await L.deactivate(), await qn?.close(), await At({
2436
- mirror: Pt,
2437
- log: $
2438
- }), await Ie.dispose(), await w.close?.();
2439
- } catch (e) {
2440
- console.error("serve: shutdown step failed, exiting anyway:", e);
2441
- }
2442
- }), await new Promise(() => {}), 0;
2443
- };
2444
- //#endregion
2445
- export { wo as n, So as r, To as t };