@voltro/cli 0.11.4 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +263 -0
  2. package/dist/{apiBuild-DHHuiwXF.js → apiBuild-GefjNI5d.js} +9 -8
  3. package/dist/apiBuild-s7swuEU5.js +2 -0
  4. package/dist/appModuleLoader-C9r9mxZt.js +19 -0
  5. package/dist/bin.js +21 -10
  6. package/dist/cliArgs-qdZSElM3.js +28 -0
  7. package/dist/{commands-BwbMqR-1.js → commands-BmNi1RgZ.js} +2502 -2543
  8. package/dist/dbCommand-Bt6BCG7g.js +2 -0
  9. package/dist/dbCommand-DNrkb58g.js +862 -0
  10. package/dist/dev-YHbHmeXt.js +3 -0
  11. package/dist/{dev-Cvojvb_J.js → dev-d0LjACxE.js} +1574 -2357
  12. package/dist/index.d.ts +19 -0
  13. package/dist/index.js +3 -3
  14. package/dist/inspect-DcZ04OME.js +2 -0
  15. package/dist/inspect-Dwx0_tUj.js +921 -0
  16. package/dist/inspectMetrics-uEfIS1vp.js +3399 -0
  17. package/dist/manifestBuild-D1MzJAiQ.js +2 -0
  18. package/dist/manifestBuild-P9yuCY2d.js +39 -0
  19. package/dist/seedRunner-DZmhoqNt.js +821 -0
  20. package/dist/serveCommand-B2-YV9TU.js +1112 -0
  21. package/dist/serveEntry.js +4 -4
  22. package/dist/{start-DyJE6w1R.js → start-DKcQd52a.js} +346 -343
  23. package/dist/startEntry.js +2 -2
  24. package/dist/startup.js +1 -1
  25. package/dist/{startupRunner-DhlX9nqd.js → startupRunner-DPGFchOa.js} +19 -33
  26. package/package.json +17 -17
  27. package/templates/AGENTS.md +1 -0
  28. package/templates/agent-docs/_index.md +1 -0
  29. package/templates/agent-docs/cli.md +180 -14
  30. package/templates/agent-docs/data.md +39 -0
  31. package/templates/agent-docs/scheduling.md +35 -1
  32. package/templates/agent-docs/security.md +48 -0
  33. package/templates/agent-docs/templates/apibackends.md +90 -17
  34. package/templates/agent-docs/whats-new.md +177 -0
  35. package/templates/apps/api-ai/package.json +7 -7
  36. package/templates/apps/api-auth/package.json +8 -8
  37. package/templates/apps/api-backend/package.json +7 -7
  38. package/templates/apps/api-backend-deactivation/package.json +7 -7
  39. package/templates/apps/api-backend-mail/package.json +8 -8
  40. package/templates/apps/api-backend-mariadb/package.json +9 -9
  41. package/templates/apps/api-backend-storage/package.json +8 -8
  42. package/templates/apps/api-data-advanced/package.json +8 -8
  43. package/templates/apps/api-durable/package.json +8 -8
  44. package/templates/apps/api-feature-flags/package.json +9 -9
  45. package/templates/apps/api-governance/package.json +8 -8
  46. package/templates/apps/api-kv/package.json +8 -8
  47. package/templates/apps/api-moderation/package.json +8 -8
  48. package/templates/apps/api-observability/package.json +8 -8
  49. package/templates/apps/api-ratelimit/package.json +8 -8
  50. package/templates/apps/api-rbac/package.json +8 -8
  51. package/templates/apps/api-rest/package.json +7 -7
  52. package/templates/apps/api-saas/package.json +11 -11
  53. package/templates/apps/api-search/package.json +8 -8
  54. package/templates/apps/api-versioning/package.json +8 -8
  55. package/templates/apps/api-webhooks/package.json +8 -8
  56. package/templates/apps/changelog/package.json +6 -6
  57. package/templates/apps/edge-functions/package.json +2 -2
  58. package/templates/apps/frontend-admin/package.json +8 -8
  59. package/templates/apps/frontend-app/package.json +8 -8
  60. package/templates/apps/frontend-blank/package.json +7 -7
  61. package/templates/apps/frontend-contact/package.json +7 -7
  62. package/templates/apps/frontend-dashboard/package.json +7 -7
  63. package/templates/apps/frontend-docs/package.json +7 -7
  64. package/templates/apps/frontend-i18n/package.json +6 -6
  65. package/templates/apps/frontend-landing/package.json +7 -7
  66. package/templates/apps/frontend-spa/package.json +7 -7
  67. package/templates/apps/frontend-ssr/package.json +7 -7
  68. package/templates/apps/frontend-ssr-api/package.json +8 -8
  69. package/templates/apps/frontend-static-blog/package.json +6 -6
  70. package/dist/apiBuild-D9MtlD02.js +0 -2
  71. package/dist/dev-BsBsIv93.js +0 -2
  72. package/dist/inspectMetrics-D4EJ8LTi.js +0 -4255
  73. package/dist/serveCommand-ARqSs73o.js +0 -1117
@@ -0,0 +1,821 @@
1
+ import { n as e } from "./appModuleLoader-C9r9mxZt.js";
2
+ import { basename as t, join as n } from "node:path";
3
+ import { pathToFileURL as r } from "node:url";
4
+ import { Effect as i } from "effect";
5
+ import { promises as a } from "node:fs";
6
+ import { _voltroConnectionGrantsTable as o, _voltroConnectionsTable as s, _voltroScheduleClaimsTable as c, _voltroScheduleRunsTable as l, _voltroTracesTable as u, _voltroUndoLogTable as d, _voltroWakeupsTable as ee, _voltroWorkflowEventDeliveriesTable as te, _voltroWorkflowEventsTable as ne, outboxAttemptsTable as re, outboxTable as ie, undoCaptureEnabled as f } from "@voltro/runtime";
7
+ import { createRequire as ae } from "node:module";
8
+ import { SqlClient as p } from "@effect/sql";
9
+ import { _voltroWorkflowRunEventsTable as oe, _voltroWorkflowRunStepsTable as se, _voltroWorkflowRunsTable as ce, _voltroWorkflowStartContextsTable as le } from "@voltro/workflow";
10
+ import { agentMessagesTable as ue, agentThreadsTable as de, aiBudgetTable as fe, aiUsageTable as pe, isAgentDescriptor as me, isAgentExecutor as he, resolveToolModuleHandlers as ge } from "@voltro/ai";
11
+ import { _voltroApiKeysTable as _e, _voltroCdcOffsetsTable as ve, _voltroIdempotencyTable as ye, _voltroKvTable as be, _voltroMigrationPlansTable as xe, _voltroMigrationsTable as Se, _voltroMssqlCdcOffsetsTable as Ce, _voltroSeedsTable as m, and as we, eq as h, generateId as g, isSeedDefinition as _, lt as Te } from "@voltro/database";
12
+ import { _voltroWebhookDeliveriesTable as Ee, _voltroWebhookTargetsTable as De } from "@voltro/plugin-webhooks/mixin";
13
+ import { _voltroStorageBlobsTable as v, _voltroStorageGrantsTable as y, _voltroStorageRefsTable as b, _voltroStorageUsageTable as x } from "@voltro/plugin-storage";
14
+ import { defineAction as S, defineMutation as C, defineQuery as w } from "@voltro/protocol";
15
+ import { createHash as T } from "node:crypto";
16
+ //#region src/dialectDriver.ts
17
+ var E = {
18
+ postgres: "@voltro/sql-postgres",
19
+ sqlite: "@voltro/sql-sqlite",
20
+ mysql: "@voltro/sql-mysql",
21
+ mariadb: "@voltro/sql-mysql",
22
+ mssql: "@voltro/sql-mssql",
23
+ turso: "@voltro/sql-turso"
24
+ }, Oe = [...new Set(Object.values(E))], ke = {
25
+ postgres: "postgresDialect",
26
+ sqlite: "sqliteDialect",
27
+ mysql: "mysqlDialect",
28
+ mariadb: "mariadbDialect",
29
+ mssql: "mssqlDialect",
30
+ turso: "tursoDialect"
31
+ }, D = /* @__PURE__ */ new Map(), Ae = (e, t) => {
32
+ D.set(e, t);
33
+ }, O = async (e) => {
34
+ let t = D.get(e);
35
+ if (t) return t;
36
+ try {
37
+ return await import(r(ae(n(process.cwd(), "package.json")).resolve(e)).href);
38
+ } catch {
39
+ try {
40
+ return await import(e);
41
+ } catch {
42
+ throw Error(`The '${e}' database driver is not installed.\n\nEvery Voltro app declares the driver for its DB dialect as a dependency (a memory store needs none). Install it in the app:\n\n pnpm add ${e}\n`);
43
+ }
44
+ }
45
+ }, je = async (e) => {
46
+ let t = E[e];
47
+ if (!t) throw Error(`Unsupported DB_DIALECT='${e}'. Supported: memory, postgres, sqlite, mysql, mariadb, mssql, turso.`);
48
+ return (await O(t))[ke[e]];
49
+ }, Me = [
50
+ {
51
+ table: Se,
52
+ when: "always"
53
+ },
54
+ {
55
+ table: m,
56
+ when: "always"
57
+ },
58
+ {
59
+ table: xe,
60
+ when: "always"
61
+ },
62
+ {
63
+ table: ce,
64
+ when: "workflows"
65
+ },
66
+ {
67
+ table: se,
68
+ when: "workflows"
69
+ },
70
+ {
71
+ table: oe,
72
+ when: "workflows"
73
+ },
74
+ {
75
+ table: le,
76
+ when: "workflows"
77
+ },
78
+ {
79
+ table: ne,
80
+ when: "workflows"
81
+ },
82
+ {
83
+ table: te,
84
+ when: "workflows"
85
+ },
86
+ {
87
+ table: l,
88
+ when: "schedules"
89
+ },
90
+ {
91
+ table: c,
92
+ when: "schedules"
93
+ },
94
+ {
95
+ table: De,
96
+ when: "webhooks"
97
+ },
98
+ {
99
+ table: Ee,
100
+ when: "webhooks"
101
+ },
102
+ {
103
+ table: u,
104
+ when: "traces"
105
+ },
106
+ {
107
+ table: d,
108
+ when: "undo"
109
+ },
110
+ {
111
+ table: ie,
112
+ when: "outbox"
113
+ },
114
+ {
115
+ table: re,
116
+ when: "outbox"
117
+ },
118
+ {
119
+ table: s,
120
+ when: "connections"
121
+ },
122
+ {
123
+ table: o,
124
+ when: "connections"
125
+ },
126
+ {
127
+ table: ee,
128
+ when: "always"
129
+ },
130
+ {
131
+ table: b,
132
+ when: "always"
133
+ },
134
+ {
135
+ table: y,
136
+ when: "always"
137
+ },
138
+ {
139
+ table: v,
140
+ when: "always"
141
+ },
142
+ {
143
+ table: x,
144
+ when: "always"
145
+ },
146
+ {
147
+ table: ye,
148
+ when: "always"
149
+ },
150
+ {
151
+ table: _e,
152
+ when: "always"
153
+ },
154
+ {
155
+ table: be,
156
+ when: "always"
157
+ }
158
+ ], k = (e) => {
159
+ let t = Me.filter((t) => t.when === "always" || t.when === "workflows" && e.workflows || t.when === "schedules" && e.schedules || t.when === "webhooks" && e.webhooks || t.when === "traces" && e.traces || t.when === "undo" && e.undo === !0 || t.when === "outbox" && e.outbox === !0 || t.when === "connections" && e.connections === !0).map((e) => e.table);
160
+ return e.cdc === !0 && t.push(e.cdcDialect === "mssql" ? Ce : ve), t;
161
+ }, A = (e) => {
162
+ let t = e.startsWith("@") ? e.replace(/^@[^/]+\//, "") : e;
163
+ return (t.startsWith("plugin-") ? t.slice(7) : t).replace(/-([a-zA-Z0-9])/g, (e, t) => t.toUpperCase());
164
+ }, Ne = (e) => {
165
+ let t = e.startsWith("@") ? e.replace(/^@[^/]+\//, "") : e;
166
+ return (t.startsWith("plugin-") ? t.slice(7) : t).replace(/#/g, "--").replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
167
+ }, Pe = (e, t) => t.name.includes(".") ? t.name : `${A(e.name)}.${t.name}`, Fe = (e, t, n) => {
168
+ switch (e) {
169
+ case "query": return w({
170
+ name: t,
171
+ input: n.input,
172
+ output: n.output,
173
+ ...n.error === void 0 ? {} : { error: n.error },
174
+ ...n.source === void 0 ? {} : { source: n.source }
175
+ });
176
+ case "mutation": return C({
177
+ name: t,
178
+ input: n.input,
179
+ output: n.output,
180
+ ...n.error === void 0 ? {} : { error: n.error }
181
+ });
182
+ case "action": return S({
183
+ name: t,
184
+ input: n.input,
185
+ output: n.output,
186
+ ...n.error === void 0 ? {} : { error: n.error }
187
+ });
188
+ }
189
+ }, Ie = (e) => (t, n) => i.suspend(() => {
190
+ let r = { request: {
191
+ subject: n.request.subject,
192
+ traceId: n.request.traceId
193
+ } };
194
+ return e.execute(t, r);
195
+ }), Le = (e) => {
196
+ let t = [];
197
+ for (let n of e) {
198
+ let e = n.routes ?? [];
199
+ for (let r of e) {
200
+ let e = Pe(n, r), i = Fe(r.kind, e, r);
201
+ t.push({
202
+ kind: r.kind,
203
+ file: `plugin:${n.name}`,
204
+ descriptor: i,
205
+ executor: Ie(r),
206
+ plugin: {
207
+ name: n.name,
208
+ version: n.version
209
+ }
210
+ });
211
+ }
212
+ }
213
+ return t;
214
+ }, Re = (e, t) => {
215
+ let n = /* @__PURE__ */ new Map();
216
+ for (let e of t) n.set(e, "user-route");
217
+ for (let t of e) {
218
+ let e = t.descriptor.name, r = n.get(e);
219
+ if (r !== void 0) throw Error(`plugin route tag collision: "${e}" declared by plugin "${t.plugin.name}" but already claimed by ${r === "user-route" ? "a user-authored route" : `plugin "${r}"`}`);
220
+ n.set(e, t.plugin.name);
221
+ }
222
+ }, j = "_voltro_plugin_migrations", ze = () => i.gen(function* () {
223
+ yield* (yield* p.SqlClient).unsafe(`
224
+ CREATE TABLE IF NOT EXISTS ${j} (
225
+ id TEXT PRIMARY KEY,
226
+ plugin_name TEXT NOT NULL,
227
+ migration_id TEXT NOT NULL,
228
+ description TEXT,
229
+ applied_at TEXT NOT NULL
230
+ );
231
+ `).pipe(i.orDie);
232
+ }), Be = (e, t) => `${A(e)}__${t}`, Ve = () => i.gen(function* () {
233
+ let e = yield* p.SqlClient, t = yield* e`SELECT id FROM ${e(j)}`.pipe(i.orDie);
234
+ return new Set(t.map((e) => e.id));
235
+ }), He = (e) => i.gen(function* () {
236
+ let t = yield* p.SqlClient, n = (/* @__PURE__ */ new Date()).toISOString();
237
+ yield* t`
238
+ INSERT INTO ${t(j)} (id, plugin_name, migration_id, description, applied_at)
239
+ VALUES (${e.key}, ${e.pluginName}, ${e.migration.id}, ${e.migration.description ?? null}, ${n})
240
+ `.pipe(i.orDie);
241
+ }), Ue = (e) => i.gen(function* () {
242
+ let t = e.flatMap((e) => (e.extendSchema?.migrations ?? []).map((t) => ({
243
+ plugin: e,
244
+ migration: t
245
+ })));
246
+ if (t.length === 0) return [];
247
+ yield* ze();
248
+ let n = yield* Ve(), r = [];
249
+ for (let { plugin: e, migration: a } of t) {
250
+ let t = Be(e.name, a.id), o = Date.now();
251
+ if (n.has(t)) {
252
+ r.push({
253
+ pluginName: e.name,
254
+ migrationId: a.id,
255
+ status: "skipped",
256
+ durationMs: 0
257
+ });
258
+ continue;
259
+ }
260
+ let s = yield* p.SqlClient;
261
+ try {
262
+ yield* a.up(s).pipe(i.mapError((e) => e)), yield* He({
263
+ key: t,
264
+ pluginName: e.name,
265
+ migration: a
266
+ }), r.push({
267
+ pluginName: e.name,
268
+ migrationId: a.id,
269
+ status: "applied",
270
+ durationMs: Date.now() - o
271
+ });
272
+ } catch (t) {
273
+ return r.push({
274
+ pluginName: e.name,
275
+ migrationId: a.id,
276
+ status: "failed",
277
+ durationMs: Date.now() - o,
278
+ error: t
279
+ }), yield* i.fail(/* @__PURE__ */ Error(`Plugin migration failed: ${e.name} ${a.id} — ${t instanceof Error ? t.message : String(t)}`));
280
+ }
281
+ }
282
+ return r;
283
+ }), We = (e) => e.filter((e) => e.extendSchema && (e.extendSchema.tables?.length ?? 0) + (e.extendSchema.migrations?.length ?? 0) > 0).map((e) => ({
284
+ pluginName: e.name,
285
+ pluginAlias: A(e.name),
286
+ tables: e.extendSchema.tables?.length ?? 0,
287
+ migrations: e.extendSchema.migrations?.length ?? 0
288
+ })), Ge = (e) => e.flatMap((e) => e.extendSchema?.tables ?? []), M = /(?<!\.server)\.agent\.tsx?$/, Ke = /\.agent\.server\.tsx?$/, N = /\.tool\.tsx?$/, qe = async (t, n) => {
289
+ let r = 0;
290
+ for (let i of t) if (N.test(i)) try {
291
+ let t = await e(i);
292
+ r += ge(t);
293
+ } catch (e) {
294
+ n.warn("tool: failed to import — handler not wired", { file: i }, e);
295
+ }
296
+ return r;
297
+ }, Je = (e) => e.replace(/\.agent\.(tsx?)$/, ".agent.server.$1"), Ye = async (t, n) => {
298
+ let r = [], i = /* @__PURE__ */ new Set();
299
+ for (let a of t) {
300
+ if (!M.test(a)) continue;
301
+ let t;
302
+ try {
303
+ t = await e(a);
304
+ } catch (e) {
305
+ n.warn("agent: failed to import descriptor", { file: a }, e);
306
+ continue;
307
+ }
308
+ let o = Object.values(t).find(me);
309
+ if (o === void 0) {
310
+ n.warn("agent: no defineAgent() descriptor export found", { file: a });
311
+ continue;
312
+ }
313
+ if (i.has(o.name)) {
314
+ n.warn("agent: duplicate name — skipping", {
315
+ file: a,
316
+ name: o.name
317
+ });
318
+ continue;
319
+ }
320
+ let s = Je(a), c;
321
+ try {
322
+ c = await e(s);
323
+ } catch (e) {
324
+ n.warn("agent: no executor — expected a `*.agent.server.tsx` default-exporting defineAgentExecutor()", {
325
+ descriptor: a,
326
+ expected: s,
327
+ name: o.name
328
+ }, e);
329
+ continue;
330
+ }
331
+ let l = c.default;
332
+ if (!he(l)) {
333
+ n.warn("agent: executor file must default-export defineAgentExecutor(descriptor, {...})", {
334
+ file: s,
335
+ name: o.name
336
+ });
337
+ continue;
338
+ }
339
+ i.add(o.name), r.push({
340
+ file: a,
341
+ serverFile: s,
342
+ descriptor: o,
343
+ executor: l
344
+ });
345
+ }
346
+ return { agents: r };
347
+ }, P = /\.connection\.tsx?$/, Xe = (e) => e.replace(P, ""), Ze = async (n, r) => {
348
+ let i = [], a = /* @__PURE__ */ new Map();
349
+ for (let t of n) {
350
+ let n;
351
+ try {
352
+ n = await e(t);
353
+ } catch (e) {
354
+ r.warn("connections: failed to import", { file: t }, e);
355
+ continue;
356
+ }
357
+ let o = n.default;
358
+ if (o === void 0 || typeof o != "object" || !o) {
359
+ r.warn("connections: missing or non-object default export — expected `defineConnection({...})`", { file: t });
360
+ continue;
361
+ }
362
+ let s = o;
363
+ if (typeof s.id != "string" || s.id.length === 0) {
364
+ r.warn("connections: invalid `id` field", { file: t });
365
+ continue;
366
+ }
367
+ if (s.kind !== "oauth2" && s.kind !== "pat") {
368
+ r.warn("connections: `kind` must be \"oauth2\" or \"pat\"", {
369
+ file: t,
370
+ kind: String(s.kind)
371
+ });
372
+ continue;
373
+ }
374
+ let c = a.get(s.id);
375
+ if (c !== void 0) {
376
+ r.error("connections: DUPLICATE id — only the first is registered", {
377
+ id: s.id,
378
+ registered: c,
379
+ ignored: t
380
+ });
381
+ continue;
382
+ }
383
+ a.set(s.id, t), i.push({
384
+ file: t,
385
+ definition: s
386
+ });
387
+ }
388
+ return i.length > 0 && r.info("discovered connections", {
389
+ connections: i.map((e) => `${e.definition.id} (${e.definition.kind})`),
390
+ files: i.map((e) => Xe(t(e.file)))
391
+ }), i;
392
+ }, F = (e) => typeof e.attributes["framework.kind"] == "string" && e.attributes["framework.kind"].startsWith("subscription."), I = (e) => {
393
+ if (e.name.includes("_voltro_traces")) return !0;
394
+ for (let t in e.attributes) {
395
+ let n = e.attributes[t];
396
+ if (typeof n == "string" && n.includes("_voltro_traces")) return !0;
397
+ }
398
+ return !1;
399
+ }, Qe = (e) => typeof e.attributes["framework.kind"] == "string" && e.attributes["framework.kind"].startsWith("subscription"), $e = 1e3, et = 500, tt = 50, L = class {
400
+ capacity;
401
+ buffer = [];
402
+ constructor(e = $e) {
403
+ this.capacity = e;
404
+ }
405
+ append(e) {
406
+ this.buffer.push(e), this.buffer.length > this.capacity && this.buffer.shift();
407
+ }
408
+ query(e = {}) {
409
+ let t = e.since ?? 0, n = e.until ?? Date.now(), r = Math.min(e.max ?? et, this.capacity), i = e.traceId, a = e.minDurationMs, o = e.status, s = e.name?.toLowerCase(), c = [];
410
+ for (let e = this.buffer.length - 1; e >= 0 && c.length < r; e--) {
411
+ let r = this.buffer[e];
412
+ r.startMs < t || r.startMs > n || i !== void 0 && r.traceId !== i || a !== void 0 && r.durationMs < a || o !== void 0 && r.status !== o || s !== void 0 && !r.name.toLowerCase().includes(s) || c.push(r);
413
+ }
414
+ return c.reverse();
415
+ }
416
+ queryGrouped(e = {}) {
417
+ let t = e.since ?? 0, n = e.maxTraces ?? tt, r = e.onlyErrors ?? !1, i = /* @__PURE__ */ new Map();
418
+ for (let e of this.buffer) {
419
+ if (e.startMs < t) continue;
420
+ let n = i.get(e.traceId);
421
+ n ? n.push(e) : i.set(e.traceId, [e]);
422
+ }
423
+ let a = [];
424
+ for (let [e, t] of i) {
425
+ t.sort((e, t) => e.startMs - t.startMs);
426
+ let n = t.some((e) => e.status === "error");
427
+ if (r && !n) continue;
428
+ let i = t[0].startMs, o = t.reduce((e, t) => t.endMs > e ? t.endMs : e, i), s = t.filter(F), c = s.length > 0 || t.some(Qe), l = s.reduce((e, t) => e === void 0 || t.startMs > e.startMs ? t : e, void 0);
429
+ a.push({
430
+ traceId: e,
431
+ rootName: t[0].name,
432
+ startMs: i,
433
+ durationMs: o - i,
434
+ spanCount: t.length,
435
+ hasError: n,
436
+ kind: c ? "subscription" : "request",
437
+ ...l === void 0 ? {} : { lastDeliveryMs: l.durationMs },
438
+ ...s.length > 0 ? { deliveryCount: s.length } : {},
439
+ spans: t
440
+ });
441
+ }
442
+ return a.sort((e, t) => t.startMs - e.startMs), a.slice(0, n);
443
+ }
444
+ size() {
445
+ return this.buffer.length;
446
+ }
447
+ capacityHint() {
448
+ return this.capacity;
449
+ }
450
+ clear() {
451
+ this.buffer = [];
452
+ }
453
+ }, R = null, nt = () => (R === null && (R = new L()), R), rt = /* @__PURE__ */ new Set([
454
+ "off",
455
+ "errors",
456
+ "interesting",
457
+ "all"
458
+ ]), z = (e, t, n, r) => {
459
+ let i = Number(e);
460
+ return Number.isFinite(i) ? Math.min(r, Math.max(n, i)) : t;
461
+ }, it = (e) => e !== void 0 && [
462
+ "1",
463
+ "true",
464
+ "yes",
465
+ "on"
466
+ ].includes(e.toLowerCase()), at = (e) => {
467
+ let t = Number(e);
468
+ return Number.isFinite(t) && t > 0 ? t : 24;
469
+ }, B = (e = process.env) => {
470
+ let t = (e.VOLTRO_TRACING_BUFFER ?? "").toLowerCase() === "off", n = z(e.VOLTRO_TRACING_SAMPLE, 1, 0, 1), r = (e.VOLTRO_TRACING_PERSIST ?? "").toLowerCase(), i = e.NODE_ENV === "production" ? "off" : "interesting";
471
+ return {
472
+ mode: rt.has(r) ? r : n <= 0 ? "off" : i,
473
+ sampleRate: n,
474
+ slowMs: z(e.VOLTRO_TRACING_SLOW_MS, 500, 0, 2 ** 53 - 1),
475
+ ttlHours: at(e.VOLTRO_TRACING_TTL_HOURS),
476
+ persistDelivery: it(e.VOLTRO_TRACING_PERSIST_DELIVERY),
477
+ bufferDisabled: t
478
+ };
479
+ }, V = (e = process.env) => {
480
+ let t = B(e);
481
+ return !t.bufferDisabled && t.mode !== "off";
482
+ }, ot = (e, t) => {
483
+ if (t >= 1) return !0;
484
+ if (t <= 0) return !1;
485
+ let n = 2166136261;
486
+ for (let t = 0; t < e.length; t++) n ^= e.charCodeAt(t), n = Math.imul(n, 16777619);
487
+ return (n >>> 0) % 1e3 < t * 1e3;
488
+ }, st = (e, t) => {
489
+ if (t.mode === "off" || I(e) || F(e) && !t.persistDelivery) return !1;
490
+ let n = e.status === "error";
491
+ if (t.mode === "errors") return n;
492
+ if (n) return !0;
493
+ if (!ot(e.traceId, t.sampleRate)) return !1;
494
+ if (t.mode === "all") return !0;
495
+ let r = e.parentSpanId === null || e.parentSpanId === void 0 || e.parentSpanId === "", i = typeof e.durationMs == "number" && e.durationMs >= t.slowMs;
496
+ return r || i;
497
+ }, ct = (e) => {
498
+ if (e.bufferDisabled) return "durable traces: OFF (VOLTRO_TRACING_BUFFER=off)";
499
+ if (e.mode === "off") return "durable traces: OFF — _voltro_traces not created (prod default; set VOLTRO_TRACING_PERSIST=interesting to enable, or use OTLP)";
500
+ let t = e.mode === "interesting" ? ` (errors + slow≥${e.slowMs}ms + roots)` : e.mode === "errors" ? " (errors only)" : "";
501
+ return `durable traces: mode=${e.mode}${t}` + (e.sampleRate < 1 ? ` · sample=${e.sampleRate}` : "") + (e.persistDelivery ? " · +delivery" : "") + ` · ttl=${e.ttlHours}h`;
502
+ }, lt = (e = 30 * 6e4) => {
503
+ let t = /* @__PURE__ */ new Map();
504
+ return (n, r) => {
505
+ let i = t.get(n);
506
+ return i !== void 0 && r - i < e ? !1 : (t.set(n, r), !0);
507
+ };
508
+ }, ut = (e) => {
509
+ let { store: t, log: n } = e, r = e.policy ?? B();
510
+ n.info(ct(r));
511
+ let i = lt(), a = [], o = () => {};
512
+ if (r.mode !== "off") {
513
+ let e = [], s = 0;
514
+ o = (t) => {
515
+ st(t, r) && (e.length >= 5e3 && (e.shift(), s += 1, i("flush-drop", Date.now()) && (n.warn(`trace flush queue saturated — dropping durable spans (${s}+ since last warning). Durable inflow exceeds write throughput; reduce it with VOLTRO_TRACING_PERSIST=errors|interesting or VOLTRO_TRACING_SAMPLE<1.`), s = 0)), e.push(t));
516
+ };
517
+ let c = async () => {
518
+ if (e.length === 0) return;
519
+ let n = e.splice(0, 200);
520
+ for (let e of n) try {
521
+ await t.insert("_voltro_traces", {
522
+ id: `${e.traceId}:${e.spanId}`,
523
+ traceId: e.traceId,
524
+ spanId: e.spanId,
525
+ parentSpanId: e.parentSpanId,
526
+ name: e.name,
527
+ kind: e.kind,
528
+ status: e.status,
529
+ statusMessage: e.statusMessage ?? null,
530
+ startedAt: new Date(e.startMs),
531
+ endedAt: new Date(e.endMs),
532
+ durationMs: Math.round(e.durationMs),
533
+ attributes: e.attributes,
534
+ events: e.events ?? null
535
+ });
536
+ } catch {}
537
+ }, l = setInterval(() => {
538
+ c();
539
+ }, 1e3);
540
+ l.unref?.(), a.push(l);
541
+ }
542
+ let s = r.ttlHours, c = 2e4, l = t.raw?.bind(t), u = async () => {
543
+ try {
544
+ let e = /* @__PURE__ */ new Date(Date.now() - s * 36e5), r = 0;
545
+ if (l) for (;;) {
546
+ let t = await l({
547
+ _tag: "RawSqlFragment",
548
+ strings: ["DELETE FROM \"_voltro_traces\" WHERE \"id\" IN (SELECT \"id\" FROM \"_voltro_traces\" WHERE \"startedAt\" < ", ` LIMIT ${c}) RETURNING "id"`],
549
+ values: [e]
550
+ });
551
+ if (r += t.length, t.length < c) break;
552
+ }
553
+ else for (;;) {
554
+ let n = await t.query({
555
+ table: "_voltro_traces",
556
+ order: [],
557
+ predicate: Te("startedAt", e),
558
+ projection: ["id"],
559
+ skip: void 0,
560
+ take: c
561
+ });
562
+ if (n.length === 0) break;
563
+ for (let e of n) try {
564
+ await t.delete("_voltro_traces", e.id);
565
+ } catch {}
566
+ if (r += n.length, n.length < c) break;
567
+ }
568
+ r >= c && i("gc-volume", Date.now()) && n.warn(`trace GC pruned ${r} spans past the ${s}h TTL in one pass — high durable-trace volume. If _voltro_traces stays large, cut the inflow (VOLTRO_TRACING_PERSIST=errors|interesting, VOLTRO_TRACING_SAMPLE<1) or shorten VOLTRO_TRACING_TTL_HOURS.`);
569
+ } catch (e) {
570
+ i("gc-error", Date.now()) && n.warn(`trace GC pass failed — _voltro_traces may grow until this clears: ${e instanceof Error ? e.message : String(e)}`);
571
+ }
572
+ }, d = setInterval(() => {
573
+ u();
574
+ }, 5 * 6e4);
575
+ return d.unref?.(), a.push(d), {
576
+ persistTraceSpan: (e) => o(e),
577
+ stop: () => {
578
+ for (let e of a) clearInterval(e);
579
+ }
580
+ };
581
+ }, dt = /\.(query|mutation|action|stream)\.ts$/, ft = /\.(query|mutation|action|stream)\.server\.ts$/, H = /\.workflow\.tsx$/, U = /\.workflow\.server\.tsx$/, W = /\.workflow\.tsx?$/, G = /\.trigger\.tsx?$/, K = /\.cron\.tsx?$/, q = /\.webhook\.tsx?$/, J = /\.outbox\.tsx?$/, pt = /\.subscribe\.tsx?$/, mt = /\.reaction\.tsx?$/, ht = /\.aggregate\.tsx?$/, gt = /\.startup\.tsx?$/, _t = /\.seed\.ts$/, vt = /\.relations\.ts$/, yt = /\.entity\.ts$|\.schema\.ts$|^schema\.ts$/, bt = (e) => W.test(e) && !H.test(e) && !U.test(e), xt = async (e) => {
582
+ let t = !1, r = !1, i = !1, o = !1, s = !1, c = !1, l = async (e) => {
583
+ let u = await a.readdir(e, { withFileTypes: !0 }).catch(() => []);
584
+ for (let a of u) if (a.isDirectory()) {
585
+ if (a.name === "node_modules" || a.name === "dist" || a.name === ".framework" || a.name.startsWith(".")) continue;
586
+ await l(n(e, a.name));
587
+ } else {
588
+ let e = a.name;
589
+ (W.test(e) || G.test(e)) && (t = !0), K.test(e) && (r = !0), q.test(e) && (i = !0), M.test(e) && (o = !0), J.test(e) && (s = !0), P.test(e) && (c = !0);
590
+ }
591
+ };
592
+ return await l(e), {
593
+ workflows: t,
594
+ schedules: r,
595
+ webhooks: i,
596
+ agents: o,
597
+ outbox: s,
598
+ connections: c
599
+ };
600
+ }, St = async (e) => {
601
+ try {
602
+ return (await import(r(n(e, "app.config.ts")).href)).default?.plugins ?? [];
603
+ } catch {
604
+ return [];
605
+ }
606
+ }, Y = (e) => {
607
+ let t = /* @__PURE__ */ new Map(), n = (e) => {
608
+ e?.tableName && !t.has(e.tableName) && t.set(e.tableName, e);
609
+ };
610
+ for (let t of k({
611
+ workflows: e.mix.workflows,
612
+ schedules: e.mix.schedules,
613
+ webhooks: e.mix.webhooks,
614
+ traces: V(),
615
+ cdc: e.cdc,
616
+ ...e.cdcDialect ? { cdcDialect: e.cdcDialect } : {},
617
+ undo: f(),
618
+ outbox: e.mix.outbox,
619
+ connections: e.mix.connections
620
+ })) n(t);
621
+ e.mix.agents && (n(de), n(ue), n(pe), n(fe));
622
+ for (let t of Ge(e.plugins)) n(t);
623
+ return [...t.values()];
624
+ }, X = async (e) => {
625
+ let t = await xt(e.root), n = await St(e.root), r = (process.env.DB_DIALECT ?? "postgres").toLowerCase(), i = r === "mariadb" ? "mariadb" : r === "mssql" ? "mssql" : void 0;
626
+ return Y({
627
+ mix: t,
628
+ plugins: n,
629
+ cdc: e.cdc ?? (i !== void 0 && (process.env.CDC ?? "1") !== "0"),
630
+ ...i ? { cdcDialect: i } : {}
631
+ });
632
+ }, Ct = async (e, t) => {
633
+ let n = [];
634
+ for (let i of e) {
635
+ let e;
636
+ try {
637
+ e = await import(r(i).href);
638
+ } catch (e) {
639
+ t.warn("seed: failed to import", { file: i }, e);
640
+ continue;
641
+ }
642
+ let o = (e.default && _(e.default) ? e.default : void 0) ?? Object.values(e).find(_);
643
+ if (!o) {
644
+ t.warn("seed: no defineSeed export", { file: i });
645
+ continue;
646
+ }
647
+ let s = await a.readFile(i, "utf8").catch(() => ""), c = o.fingerprint ? o.fingerprint({ src: s }) : T("sha256").update(s).digest("hex").slice(0, 16);
648
+ n.push({
649
+ file: i,
650
+ definition: o,
651
+ fingerprint: c
652
+ });
653
+ }
654
+ return n;
655
+ }, wt = (e) => ({
656
+ query: (t) => e.query({
657
+ table: t.table,
658
+ order: t.order ?? [],
659
+ ...t.predicate ? { predicate: t.predicate } : {},
660
+ ...t.take === void 0 ? {} : { take: t.take },
661
+ ...t.skip === void 0 ? {} : { skip: t.skip },
662
+ ...t.projection ? { projection: t.projection } : {}
663
+ }),
664
+ insert: (t, n) => e.insert(t, n),
665
+ insertIgnore: (t, n, r) => e.insertIgnore(t, n, r),
666
+ update: (t, n, r) => e.update(t, n, r),
667
+ delete: (t, n) => e.delete(t, n)
668
+ }), Tt = (e) => async (t, n, r) => {
669
+ let i = Object.keys(n);
670
+ if (i.length === 0) throw Error("upsertByUnique: matchFields must have at least one key");
671
+ let a;
672
+ if (i.length === 1) {
673
+ let e = i[0];
674
+ a = h(e, n[e]);
675
+ } else a = we(...i.map((e) => h(e, n[e])));
676
+ let o = (await e.query({
677
+ table: t,
678
+ order: [],
679
+ predicate: a
680
+ }))[0];
681
+ if (o) {
682
+ let n = o.id;
683
+ return {
684
+ row: await e.update(t, n, r) ?? o,
685
+ created: !1
686
+ };
687
+ }
688
+ return {
689
+ row: await e.insert(t, r),
690
+ created: !0
691
+ };
692
+ }, Et = (e, t) => {
693
+ let n = Tt(e);
694
+ return {
695
+ store: wt(e),
696
+ upsertByUnique: n,
697
+ progress: (e, n) => t.debug("seed progress", {
698
+ done: e,
699
+ total: n
700
+ })
701
+ };
702
+ }, Z = "_voltro_seeds", Dt = () => {
703
+ let e = m.fields.id?.idScheme;
704
+ return (e ? g(e, Z) : null) ?? g({
705
+ kind: "typeid",
706
+ prefix: "seed"
707
+ }, Z);
708
+ }, Ot = {
709
+ isUnchanged: () => !1,
710
+ record: async () => {}
711
+ }, Q = async (e, t) => {
712
+ let n;
713
+ try {
714
+ n = await e.query({
715
+ table: Z,
716
+ order: [],
717
+ predicate: void 0,
718
+ projection: void 0,
719
+ skip: void 0,
720
+ take: void 0
721
+ });
722
+ } catch (e) {
723
+ return t.warn("seeds: ledger unreadable — every boot seed will run", {
724
+ table: Z,
725
+ error: String(e)
726
+ }), Ot;
727
+ }
728
+ let r = new Map(n.map((e) => [e.name, e]));
729
+ return {
730
+ isUnchanged: (e) => {
731
+ let t = r.get(e.definition.id);
732
+ return t?.lastRunStatus === "succeeded" && t.fingerprint === e.fingerprint;
733
+ },
734
+ record: async (n, i) => {
735
+ let a = {
736
+ name: n.definition.id,
737
+ lifecycle: n.definition.lifecycle,
738
+ fingerprint: n.fingerprint,
739
+ lastRunStatus: i.status,
740
+ lastRunAt: /* @__PURE__ */ new Date(),
741
+ lastRunDurationMs: i.durationMs,
742
+ lastRunRowsTouched: i.rowsTouched,
743
+ lastError: i.error?.message ?? null
744
+ };
745
+ try {
746
+ let t = r.get(n.definition.id);
747
+ t ? await e.update(Z, t.id, a) : await e.insert(Z, {
748
+ id: Dt(),
749
+ ...a
750
+ });
751
+ } catch (e) {
752
+ t.warn("seeds: could not record the ledger row — this seed will re-run on every boot", {
753
+ seedId: n.definition.id,
754
+ table: Z,
755
+ error: String(e)
756
+ });
757
+ }
758
+ }
759
+ };
760
+ }, $ = async (e, t, n) => {
761
+ let r = Date.now(), i = Et(t, n), a = 0;
762
+ for (let t of e.definition.steps) try {
763
+ let e = await t.body(i);
764
+ e && typeof e.rowsTouched == "number" && (a += e.rowsTouched);
765
+ } catch (i) {
766
+ let o = i;
767
+ return n.error(`seed "${e.definition.id}" failed at step "${t.name}"`, {
768
+ seedId: e.definition.id,
769
+ step: t.name
770
+ }, o), {
771
+ seedId: e.definition.id,
772
+ status: "failed",
773
+ durationMs: Date.now() - r,
774
+ rowsTouched: a,
775
+ error: {
776
+ message: o.message,
777
+ ...o.stack ? { stack: o.stack } : {},
778
+ stepName: t.name
779
+ }
780
+ };
781
+ }
782
+ return {
783
+ seedId: e.definition.id,
784
+ status: "succeeded",
785
+ durationMs: Date.now() - r,
786
+ rowsTouched: a
787
+ };
788
+ }, kt = async (e, t, n, r = {}) => {
789
+ let i = e.filter((e) => e.definition.lifecycle === "boot");
790
+ if (i.length === 0) return [];
791
+ let a = await Q(t, n), o = [], s = 0;
792
+ for (let e of i) {
793
+ if (!r.force && a.isUnchanged(e)) {
794
+ s++, n.debug(`seed "${e.definition.id}" unchanged — skipped`, { fingerprint: e.fingerprint }), o.push({
795
+ seedId: e.definition.id,
796
+ status: "skipped",
797
+ durationMs: 0,
798
+ rowsTouched: 0
799
+ });
800
+ continue;
801
+ }
802
+ let i = await $(e, t, n);
803
+ i.status === "succeeded" && n.info(`seed "${i.seedId}" applied`, {
804
+ durationMs: i.durationMs,
805
+ rowsTouched: i.rowsTouched,
806
+ fingerprint: e.fingerprint
807
+ }), await a.record(e, i), o.push(i);
808
+ }
809
+ return n.info("seeds: boot-lifecycle pass complete", {
810
+ ran: o.length - s,
811
+ skipped: s,
812
+ ...r.force ? { forced: !0 } : {}
813
+ }), o;
814
+ }, At = async (e, t, n, r) => {
815
+ let i = e.find((e) => e.definition.id === t);
816
+ if (!i) throw Error(`seed not found: ${t}`);
817
+ let a = await $(i, n, r);
818
+ return await (await Q(n, r)).record(i, a), a;
819
+ }, jt = /\.seed\.ts$/;
820
+ //#endregion
821
+ export { Ze as A, A as B, bt as C, nt as D, L as E, qe as F, je as G, k as H, Ue as I, Ae as K, We as L, Ke as M, N, I as O, Ye as P, Re as R, U as S, V as T, Oe as U, Ne as V, O as W, pt as _, X as a, H as b, K as c, ft as d, mt as f, gt as g, _t as h, At as i, M as j, P as k, J as l, yt as m, Ct as n, Y as o, vt as p, kt as r, ht as s, jt as t, dt as u, G as v, ut as w, W as x, q as y, Le as z };