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