@voltro/cli 0.29.0 → 0.30.1

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