@voltro/cli 0.11.4 → 0.13.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.
- package/CHANGELOG.md +356 -0
- package/dist/{apiBuild-DHHuiwXF.js → apiBuild-B6_ehbem.js} +9 -8
- package/dist/apiBuild-Bzpb383i.js +2 -0
- package/dist/appModuleLoader-C9r9mxZt.js +19 -0
- package/dist/bin.js +21 -10
- package/dist/cliArgs-qdZSElM3.js +28 -0
- package/dist/{commands-BwbMqR-1.js → commands-DYOuGlEC.js} +2903 -2647
- package/dist/dbCommand-ADD4mrTI.js +2 -0
- package/dist/dbCommand-DIOJQwsq.js +876 -0
- package/dist/{dev-Cvojvb_J.js → dev-Fb9BmavX.js} +1697 -2411
- package/dist/dev-xdijqojc.js +3 -0
- package/dist/frameworkTableAssembly-CYlrafoK.js +600 -0
- package/dist/frameworkTableAssembly-XvKO7wQt.js +2 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +3 -3
- package/dist/inspect-DcZ04OME.js +2 -0
- package/dist/inspect-Dwx0_tUj.js +921 -0
- package/dist/inspectMetrics-DOiiII34.js +3408 -0
- package/dist/manifestBuild-D1MzJAiQ.js +2 -0
- package/dist/manifestBuild-P9yuCY2d.js +39 -0
- package/dist/seedRunner-D6eu-u5U.js +229 -0
- package/dist/serveCommand-CqYxzBZR.js +1113 -0
- package/dist/serveEntry.js +4 -4
- package/dist/{start-DyJE6w1R.js → start-CjG_0xhR.js} +346 -343
- package/dist/startEntry.js +2 -2
- package/dist/startup.js +1 -1
- package/dist/{startupRunner-DhlX9nqd.js → startupRunner-DPGFchOa.js} +19 -33
- package/package.json +17 -17
- package/templates/AGENTS.md +1 -0
- package/templates/agent-docs/_index.md +1 -0
- package/templates/agent-docs/authentication.md +36 -0
- package/templates/agent-docs/cli.md +254 -14
- package/templates/agent-docs/configuration.md +48 -0
- package/templates/agent-docs/data.md +39 -0
- package/templates/agent-docs/database/migrations.md +32 -0
- package/templates/agent-docs/database/transactions.md +31 -0
- package/templates/agent-docs/scheduling.md +35 -1
- package/templates/agent-docs/security.md +48 -0
- package/templates/agent-docs/templates/apibackends.md +90 -17
- package/templates/agent-docs/testing.md +24 -0
- package/templates/agent-docs/whats-new.md +81 -0
- package/templates/apps/api-ai/package.json +7 -7
- package/templates/apps/api-auth/package.json +8 -8
- package/templates/apps/api-backend/package.json +7 -7
- package/templates/apps/api-backend-deactivation/package.json +7 -7
- package/templates/apps/api-backend-deactivation/tests/users.deactivate.test.ts +1 -1
- package/templates/apps/api-backend-mail/package.json +8 -8
- package/templates/apps/api-backend-mariadb/package.json +9 -9
- package/templates/apps/api-backend-storage/package.json +8 -8
- package/templates/apps/api-data-advanced/package.json +8 -8
- package/templates/apps/api-data-advanced/tests/queries.test.ts +6 -1
- package/templates/apps/api-durable/package.json +8 -8
- package/templates/apps/api-feature-flags/package.json +9 -9
- package/templates/apps/api-governance/app.config.ts +0 -1
- package/templates/apps/api-governance/package.json +8 -8
- package/templates/apps/api-kv/package.json +8 -8
- package/templates/apps/api-kv/tests/sync.test.ts +2 -2
- package/templates/apps/api-moderation/package.json +8 -8
- package/templates/apps/api-observability/package.json +8 -8
- package/templates/apps/api-ratelimit/package.json +8 -8
- package/templates/apps/api-rbac/README.md +53 -14
- package/templates/apps/api-rbac/app.config.ts +24 -26
- package/templates/apps/api-rbac/authz.ts +76 -0
- package/templates/apps/api-rbac/database/schema.ts +23 -6
- package/templates/apps/api-rbac/mutations/notes.create.mutation.server.ts +7 -5
- package/templates/apps/api-rbac/mutations/notes.create.mutation.ts +15 -8
- package/templates/apps/api-rbac/mutations/notes.delete.mutation.server.ts +54 -0
- package/templates/apps/api-rbac/mutations/notes.delete.mutation.ts +43 -0
- package/templates/apps/api-rbac/mutations/teams.rename.mutation.server.ts +19 -0
- package/templates/apps/api-rbac/mutations/teams.rename.mutation.ts +37 -0
- package/templates/apps/api-rbac/package.json +8 -8
- package/templates/apps/api-rbac/queries/notes.list.query.server.ts +12 -0
- package/templates/apps/api-rbac/queries/notes.list.query.ts +26 -0
- package/templates/apps/api-rbac/template.json +2 -2
- package/templates/apps/api-rbac/tests/authz.test.ts +233 -0
- package/templates/apps/api-rest/package.json +7 -7
- package/templates/apps/api-saas/package.json +11 -11
- package/templates/apps/api-search/package.json +8 -8
- package/templates/apps/api-versioning/package.json +8 -8
- package/templates/apps/api-webhooks/package.json +9 -8
- package/templates/apps/changelog/package.json +6 -6
- package/templates/apps/edge-functions/package.json +2 -2
- package/templates/apps/frontend-admin/package.json +8 -8
- package/templates/apps/frontend-app/package.json +8 -8
- package/templates/apps/frontend-blank/package.json +7 -7
- package/templates/apps/frontend-contact/package.json +7 -7
- package/templates/apps/frontend-dashboard/package.json +7 -7
- package/templates/apps/frontend-docs/package.json +7 -7
- package/templates/apps/frontend-i18n/package.json +6 -6
- package/templates/apps/frontend-landing/package.json +7 -7
- package/templates/apps/frontend-spa/package.json +7 -7
- package/templates/apps/frontend-ssr/package.json +7 -7
- package/templates/apps/frontend-ssr-api/package.json +8 -8
- package/templates/apps/frontend-static-blog/package.json +6 -6
- package/dist/apiBuild-D9MtlD02.js +0 -2
- package/dist/dev-BsBsIv93.js +0 -2
- package/dist/inspectMetrics-D4EJ8LTi.js +0 -4255
- package/dist/serveCommand-ARqSs73o.js +0 -1117
- package/templates/apps/api-rbac/tests/notes.create.test.ts +0 -80
|
@@ -0,0 +1,600 @@
|
|
|
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 f, _voltroWorkflowEventsTable as te, outboxAttemptsTable as ne, outboxTable as re, undoCaptureEnabled as ie } from "@voltro/runtime";
|
|
7
|
+
import { SqlClient as p } from "@effect/sql";
|
|
8
|
+
import { _voltroWorkflowRunEventsTable as ae, _voltroWorkflowRunStepsTable as oe, _voltroWorkflowRunsTable as se, _voltroWorkflowStartContextsTable as m } from "@voltro/workflow";
|
|
9
|
+
import { agentMessagesTable as ce, agentThreadsTable as le, aiBudgetTable as ue, aiUsageTable as de, isAgentDescriptor as fe, isAgentExecutor as pe, resolveToolModuleHandlers as me } from "@voltro/ai";
|
|
10
|
+
import { _voltroApiKeysTable as he, _voltroCdcOffsetsTable as ge, _voltroIdempotencyTable as _e, _voltroKvTable as ve, _voltroMigrationPlansTable as ye, _voltroMigrationsTable as be, _voltroMssqlCdcOffsetsTable as h, _voltroSeedsTable as g, lt as _ } from "@voltro/database";
|
|
11
|
+
import { _voltroWebhookDeliveriesTable as v, _voltroWebhookTargetsTable as y } from "@voltro/plugin-webhooks/mixin";
|
|
12
|
+
import { _voltroStorageBlobsTable as b, _voltroStorageGrantsTable as x, _voltroStorageRefsTable as S, _voltroStorageUsageTable as C } from "@voltro/plugin-storage";
|
|
13
|
+
import { defineAction as w, defineMutation as T, defineQuery as E } from "@voltro/protocol";
|
|
14
|
+
//#region src/frameworkTables.ts
|
|
15
|
+
var D = [
|
|
16
|
+
{
|
|
17
|
+
table: be,
|
|
18
|
+
when: "always"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
table: g,
|
|
22
|
+
when: "always"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
table: ye,
|
|
26
|
+
when: "always"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
table: se,
|
|
30
|
+
when: "workflows"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
table: oe,
|
|
34
|
+
when: "workflows"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
table: ae,
|
|
38
|
+
when: "workflows"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
table: m,
|
|
42
|
+
when: "workflows"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
table: te,
|
|
46
|
+
when: "workflows"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
table: f,
|
|
50
|
+
when: "workflows"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
table: l,
|
|
54
|
+
when: "schedules"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
table: c,
|
|
58
|
+
when: "schedules"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
table: y,
|
|
62
|
+
when: "webhooks"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
table: v,
|
|
66
|
+
when: "webhooks"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
table: u,
|
|
70
|
+
when: "traces"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
table: d,
|
|
74
|
+
when: "undo"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
table: re,
|
|
78
|
+
when: "outbox"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
table: ne,
|
|
82
|
+
when: "outbox"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
table: s,
|
|
86
|
+
when: "connections"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
table: o,
|
|
90
|
+
when: "connections"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
table: ee,
|
|
94
|
+
when: "always"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
table: S,
|
|
98
|
+
when: "always"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
table: x,
|
|
102
|
+
when: "always"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
table: b,
|
|
106
|
+
when: "always"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
table: C,
|
|
110
|
+
when: "always"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
table: _e,
|
|
114
|
+
when: "always"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
table: he,
|
|
118
|
+
when: "always"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
table: ve,
|
|
122
|
+
when: "always"
|
|
123
|
+
}
|
|
124
|
+
], O = (e) => {
|
|
125
|
+
let t = D.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);
|
|
126
|
+
return e.cdc === !0 && t.push(e.cdcDialect === "mssql" ? h : ge), t;
|
|
127
|
+
}, k = (e) => {
|
|
128
|
+
let t = e.startsWith("@") ? e.replace(/^@[^/]+\//, "") : e;
|
|
129
|
+
return (t.startsWith("plugin-") ? t.slice(7) : t).replace(/-([a-zA-Z0-9])/g, (e, t) => t.toUpperCase());
|
|
130
|
+
}, A = (e) => {
|
|
131
|
+
let t = e.startsWith("@") ? e.replace(/^@[^/]+\//, "") : e;
|
|
132
|
+
return (t.startsWith("plugin-") ? t.slice(7) : t).replace(/#/g, "--").replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
133
|
+
}, j = (e, t) => t.name.includes(".") ? t.name : `${k(e.name)}.${t.name}`, M = (e, t, n) => {
|
|
134
|
+
switch (e) {
|
|
135
|
+
case "query": return E({
|
|
136
|
+
name: t,
|
|
137
|
+
input: n.input,
|
|
138
|
+
output: n.output,
|
|
139
|
+
...n.error === void 0 ? {} : { error: n.error },
|
|
140
|
+
...n.source === void 0 ? {} : { source: n.source }
|
|
141
|
+
});
|
|
142
|
+
case "mutation": return T({
|
|
143
|
+
name: t,
|
|
144
|
+
input: n.input,
|
|
145
|
+
output: n.output,
|
|
146
|
+
...n.error === void 0 ? {} : { error: n.error }
|
|
147
|
+
});
|
|
148
|
+
case "action": return w({
|
|
149
|
+
name: t,
|
|
150
|
+
input: n.input,
|
|
151
|
+
output: n.output,
|
|
152
|
+
...n.error === void 0 ? {} : { error: n.error }
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}, N = (e) => (t, n) => i.suspend(() => {
|
|
156
|
+
let r = { request: {
|
|
157
|
+
subject: n.request.subject,
|
|
158
|
+
traceId: n.request.traceId
|
|
159
|
+
} };
|
|
160
|
+
return e.execute(t, r);
|
|
161
|
+
}), xe = (e) => {
|
|
162
|
+
let t = [];
|
|
163
|
+
for (let n of e) {
|
|
164
|
+
let e = n.routes ?? [];
|
|
165
|
+
for (let r of e) {
|
|
166
|
+
let e = j(n, r), i = M(r.kind, e, r);
|
|
167
|
+
t.push({
|
|
168
|
+
kind: r.kind,
|
|
169
|
+
file: `plugin:${n.name}`,
|
|
170
|
+
descriptor: i,
|
|
171
|
+
executor: N(r),
|
|
172
|
+
plugin: {
|
|
173
|
+
name: n.name,
|
|
174
|
+
version: n.version
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return t;
|
|
180
|
+
}, Se = (e, t) => {
|
|
181
|
+
let n = /* @__PURE__ */ new Map();
|
|
182
|
+
for (let e of t) n.set(e, "user-route");
|
|
183
|
+
for (let t of e) {
|
|
184
|
+
let e = t.descriptor.name, r = n.get(e);
|
|
185
|
+
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}"`}`);
|
|
186
|
+
n.set(e, t.plugin.name);
|
|
187
|
+
}
|
|
188
|
+
}, P = "_voltro_plugin_migrations", Ce = () => i.gen(function* () {
|
|
189
|
+
yield* (yield* p.SqlClient).unsafe(`
|
|
190
|
+
CREATE TABLE IF NOT EXISTS ${P} (
|
|
191
|
+
id TEXT PRIMARY KEY,
|
|
192
|
+
plugin_name TEXT NOT NULL,
|
|
193
|
+
migration_id TEXT NOT NULL,
|
|
194
|
+
description TEXT,
|
|
195
|
+
applied_at TEXT NOT NULL
|
|
196
|
+
);
|
|
197
|
+
`).pipe(i.orDie);
|
|
198
|
+
}), we = (e, t) => `${k(e)}__${t}`, Te = () => i.gen(function* () {
|
|
199
|
+
let e = yield* p.SqlClient, t = yield* e`SELECT id FROM ${e(P)}`.pipe(i.orDie);
|
|
200
|
+
return new Set(t.map((e) => e.id));
|
|
201
|
+
}), Ee = (e) => i.gen(function* () {
|
|
202
|
+
let t = yield* p.SqlClient, n = (/* @__PURE__ */ new Date()).toISOString();
|
|
203
|
+
yield* t`
|
|
204
|
+
INSERT INTO ${t(P)} (id, plugin_name, migration_id, description, applied_at)
|
|
205
|
+
VALUES (${e.key}, ${e.pluginName}, ${e.migration.id}, ${e.migration.description ?? null}, ${n})
|
|
206
|
+
`.pipe(i.orDie);
|
|
207
|
+
}), De = (e) => i.gen(function* () {
|
|
208
|
+
let t = e.flatMap((e) => (e.extendSchema?.migrations ?? []).map((t) => ({
|
|
209
|
+
plugin: e,
|
|
210
|
+
migration: t
|
|
211
|
+
})));
|
|
212
|
+
if (t.length === 0) return [];
|
|
213
|
+
yield* Ce();
|
|
214
|
+
let n = yield* Te(), r = [];
|
|
215
|
+
for (let { plugin: e, migration: a } of t) {
|
|
216
|
+
let t = we(e.name, a.id), o = Date.now();
|
|
217
|
+
if (n.has(t)) {
|
|
218
|
+
r.push({
|
|
219
|
+
pluginName: e.name,
|
|
220
|
+
migrationId: a.id,
|
|
221
|
+
status: "skipped",
|
|
222
|
+
durationMs: 0
|
|
223
|
+
});
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
let s = yield* p.SqlClient;
|
|
227
|
+
try {
|
|
228
|
+
yield* a.up(s).pipe(i.mapError((e) => e)), yield* Ee({
|
|
229
|
+
key: t,
|
|
230
|
+
pluginName: e.name,
|
|
231
|
+
migration: a
|
|
232
|
+
}), r.push({
|
|
233
|
+
pluginName: e.name,
|
|
234
|
+
migrationId: a.id,
|
|
235
|
+
status: "applied",
|
|
236
|
+
durationMs: Date.now() - o
|
|
237
|
+
});
|
|
238
|
+
} catch (t) {
|
|
239
|
+
return r.push({
|
|
240
|
+
pluginName: e.name,
|
|
241
|
+
migrationId: a.id,
|
|
242
|
+
status: "failed",
|
|
243
|
+
durationMs: Date.now() - o,
|
|
244
|
+
error: t
|
|
245
|
+
}), yield* i.fail(/* @__PURE__ */ Error(`Plugin migration failed: ${e.name} ${a.id} — ${t instanceof Error ? t.message : String(t)}`));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return r;
|
|
249
|
+
}), Oe = (e) => e.filter((e) => e.extendSchema && (e.extendSchema.tables?.length ?? 0) + (e.extendSchema.migrations?.length ?? 0) > 0).map((e) => ({
|
|
250
|
+
pluginName: e.name,
|
|
251
|
+
pluginAlias: k(e.name),
|
|
252
|
+
tables: e.extendSchema.tables?.length ?? 0,
|
|
253
|
+
migrations: e.extendSchema.migrations?.length ?? 0
|
|
254
|
+
})), ke = (e) => e.flatMap((e) => e.extendSchema?.tables ?? []), F = /(?<!\.server)\.agent\.tsx?$/, Ae = /\.agent\.server\.tsx?$/, I = /\.tool\.tsx?$/, L = async (t, n) => {
|
|
255
|
+
let r = 0;
|
|
256
|
+
for (let i of t) if (I.test(i)) try {
|
|
257
|
+
let t = await e(i);
|
|
258
|
+
r += me(t);
|
|
259
|
+
} catch (e) {
|
|
260
|
+
n.warn("tool: failed to import — handler not wired", { file: i }, e);
|
|
261
|
+
}
|
|
262
|
+
return r;
|
|
263
|
+
}, je = (e) => e.replace(/\.agent\.(tsx?)$/, ".agent.server.$1"), Me = async (t, n) => {
|
|
264
|
+
let r = [], i = /* @__PURE__ */ new Set();
|
|
265
|
+
for (let a of t) {
|
|
266
|
+
if (!F.test(a)) continue;
|
|
267
|
+
let t;
|
|
268
|
+
try {
|
|
269
|
+
t = await e(a);
|
|
270
|
+
} catch (e) {
|
|
271
|
+
n.warn("agent: failed to import descriptor", { file: a }, e);
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
let o = Object.values(t).find(fe);
|
|
275
|
+
if (o === void 0) {
|
|
276
|
+
n.warn("agent: no defineAgent() descriptor export found", { file: a });
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if (i.has(o.name)) {
|
|
280
|
+
n.warn("agent: duplicate name — skipping", {
|
|
281
|
+
file: a,
|
|
282
|
+
name: o.name
|
|
283
|
+
});
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
let s = je(a), c;
|
|
287
|
+
try {
|
|
288
|
+
c = await e(s);
|
|
289
|
+
} catch (e) {
|
|
290
|
+
n.warn("agent: no executor — expected a `*.agent.server.tsx` default-exporting defineAgentExecutor()", {
|
|
291
|
+
descriptor: a,
|
|
292
|
+
expected: s,
|
|
293
|
+
name: o.name
|
|
294
|
+
}, e);
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
let l = c.default;
|
|
298
|
+
if (!pe(l)) {
|
|
299
|
+
n.warn("agent: executor file must default-export defineAgentExecutor(descriptor, {...})", {
|
|
300
|
+
file: s,
|
|
301
|
+
name: o.name
|
|
302
|
+
});
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
i.add(o.name), r.push({
|
|
306
|
+
file: a,
|
|
307
|
+
serverFile: s,
|
|
308
|
+
descriptor: o,
|
|
309
|
+
executor: l
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
return { agents: r };
|
|
313
|
+
}, R = /\.connection\.tsx?$/, Ne = (e) => e.replace(R, ""), Pe = async (n, r) => {
|
|
314
|
+
let i = [], a = /* @__PURE__ */ new Map();
|
|
315
|
+
for (let t of n) {
|
|
316
|
+
let n;
|
|
317
|
+
try {
|
|
318
|
+
n = await e(t);
|
|
319
|
+
} catch (e) {
|
|
320
|
+
r.warn("connections: failed to import", { file: t }, e);
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
let o = n.default;
|
|
324
|
+
if (o === void 0 || typeof o != "object" || !o) {
|
|
325
|
+
r.warn("connections: missing or non-object default export — expected `defineConnection({...})`", { file: t });
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
let s = o;
|
|
329
|
+
if (typeof s.id != "string" || s.id.length === 0) {
|
|
330
|
+
r.warn("connections: invalid `id` field", { file: t });
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
if (s.kind !== "oauth2" && s.kind !== "pat") {
|
|
334
|
+
r.warn("connections: `kind` must be \"oauth2\" or \"pat\"", {
|
|
335
|
+
file: t,
|
|
336
|
+
kind: String(s.kind)
|
|
337
|
+
});
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
let c = a.get(s.id);
|
|
341
|
+
if (c !== void 0) {
|
|
342
|
+
r.error("connections: DUPLICATE id — only the first is registered", {
|
|
343
|
+
id: s.id,
|
|
344
|
+
registered: c,
|
|
345
|
+
ignored: t
|
|
346
|
+
});
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
a.set(s.id, t), i.push({
|
|
350
|
+
file: t,
|
|
351
|
+
definition: s
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
return i.length > 0 && r.info("discovered connections", {
|
|
355
|
+
connections: i.map((e) => `${e.definition.id} (${e.definition.kind})`),
|
|
356
|
+
files: i.map((e) => Ne(t(e.file)))
|
|
357
|
+
}), i;
|
|
358
|
+
}, z = (e) => typeof e.attributes["framework.kind"] == "string" && e.attributes["framework.kind"].startsWith("subscription."), B = (e) => {
|
|
359
|
+
if (e.name.includes("_voltro_traces")) return !0;
|
|
360
|
+
for (let t in e.attributes) {
|
|
361
|
+
let n = e.attributes[t];
|
|
362
|
+
if (typeof n == "string" && n.includes("_voltro_traces")) return !0;
|
|
363
|
+
}
|
|
364
|
+
return !1;
|
|
365
|
+
}, Fe = (e) => typeof e.attributes["framework.kind"] == "string" && e.attributes["framework.kind"].startsWith("subscription"), Ie = 1e3, Le = 500, Re = 50, V = class {
|
|
366
|
+
capacity;
|
|
367
|
+
buffer = [];
|
|
368
|
+
constructor(e = Ie) {
|
|
369
|
+
this.capacity = e;
|
|
370
|
+
}
|
|
371
|
+
append(e) {
|
|
372
|
+
this.buffer.push(e), this.buffer.length > this.capacity && this.buffer.shift();
|
|
373
|
+
}
|
|
374
|
+
query(e = {}) {
|
|
375
|
+
let t = e.since ?? 0, n = e.until ?? Date.now(), r = Math.min(e.max ?? Le, this.capacity), i = e.traceId, a = e.minDurationMs, o = e.status, s = e.name?.toLowerCase(), c = [];
|
|
376
|
+
for (let e = this.buffer.length - 1; e >= 0 && c.length < r; e--) {
|
|
377
|
+
let r = this.buffer[e];
|
|
378
|
+
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);
|
|
379
|
+
}
|
|
380
|
+
return c.reverse();
|
|
381
|
+
}
|
|
382
|
+
queryGrouped(e = {}) {
|
|
383
|
+
let t = e.since ?? 0, n = e.maxTraces ?? Re, r = e.onlyErrors ?? !1, i = /* @__PURE__ */ new Map();
|
|
384
|
+
for (let e of this.buffer) {
|
|
385
|
+
if (e.startMs < t) continue;
|
|
386
|
+
let n = i.get(e.traceId);
|
|
387
|
+
n ? n.push(e) : i.set(e.traceId, [e]);
|
|
388
|
+
}
|
|
389
|
+
let a = [];
|
|
390
|
+
for (let [e, t] of i) {
|
|
391
|
+
t.sort((e, t) => e.startMs - t.startMs);
|
|
392
|
+
let n = t.some((e) => e.status === "error");
|
|
393
|
+
if (r && !n) continue;
|
|
394
|
+
let i = t[0].startMs, o = t.reduce((e, t) => t.endMs > e ? t.endMs : e, i), s = t.filter(z), c = s.length > 0 || t.some(Fe), l = s.reduce((e, t) => e === void 0 || t.startMs > e.startMs ? t : e, void 0);
|
|
395
|
+
a.push({
|
|
396
|
+
traceId: e,
|
|
397
|
+
rootName: t[0].name,
|
|
398
|
+
startMs: i,
|
|
399
|
+
durationMs: o - i,
|
|
400
|
+
spanCount: t.length,
|
|
401
|
+
hasError: n,
|
|
402
|
+
kind: c ? "subscription" : "request",
|
|
403
|
+
...l === void 0 ? {} : { lastDeliveryMs: l.durationMs },
|
|
404
|
+
...s.length > 0 ? { deliveryCount: s.length } : {},
|
|
405
|
+
spans: t
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
return a.sort((e, t) => t.startMs - e.startMs), a.slice(0, n);
|
|
409
|
+
}
|
|
410
|
+
size() {
|
|
411
|
+
return this.buffer.length;
|
|
412
|
+
}
|
|
413
|
+
capacityHint() {
|
|
414
|
+
return this.capacity;
|
|
415
|
+
}
|
|
416
|
+
clear() {
|
|
417
|
+
this.buffer = [];
|
|
418
|
+
}
|
|
419
|
+
}, H = null, ze = () => (H === null && (H = new V()), H), Be = /* @__PURE__ */ new Set([
|
|
420
|
+
"off",
|
|
421
|
+
"errors",
|
|
422
|
+
"interesting",
|
|
423
|
+
"all"
|
|
424
|
+
]), U = (e, t, n, r) => {
|
|
425
|
+
let i = Number(e);
|
|
426
|
+
return Number.isFinite(i) ? Math.min(r, Math.max(n, i)) : t;
|
|
427
|
+
}, Ve = (e) => e !== void 0 && [
|
|
428
|
+
"1",
|
|
429
|
+
"true",
|
|
430
|
+
"yes",
|
|
431
|
+
"on"
|
|
432
|
+
].includes(e.toLowerCase()), He = (e) => {
|
|
433
|
+
let t = Number(e);
|
|
434
|
+
return Number.isFinite(t) && t > 0 ? t : 24;
|
|
435
|
+
}, W = (e = process.env) => {
|
|
436
|
+
let t = (e.VOLTRO_TRACING_BUFFER ?? "").toLowerCase() === "off", n = U(e.VOLTRO_TRACING_SAMPLE, 1, 0, 1), r = (e.VOLTRO_TRACING_PERSIST ?? "").toLowerCase(), i = e.NODE_ENV === "production" ? "off" : "interesting";
|
|
437
|
+
return {
|
|
438
|
+
mode: Be.has(r) ? r : n <= 0 ? "off" : i,
|
|
439
|
+
sampleRate: n,
|
|
440
|
+
slowMs: U(e.VOLTRO_TRACING_SLOW_MS, 500, 0, 2 ** 53 - 1),
|
|
441
|
+
ttlHours: He(e.VOLTRO_TRACING_TTL_HOURS),
|
|
442
|
+
persistDelivery: Ve(e.VOLTRO_TRACING_PERSIST_DELIVERY),
|
|
443
|
+
bufferDisabled: t
|
|
444
|
+
};
|
|
445
|
+
}, G = (e = process.env) => {
|
|
446
|
+
let t = W(e);
|
|
447
|
+
return !t.bufferDisabled && t.mode !== "off";
|
|
448
|
+
}, Ue = (e, t) => {
|
|
449
|
+
if (t >= 1) return !0;
|
|
450
|
+
if (t <= 0) return !1;
|
|
451
|
+
let n = 2166136261;
|
|
452
|
+
for (let t = 0; t < e.length; t++) n ^= e.charCodeAt(t), n = Math.imul(n, 16777619);
|
|
453
|
+
return (n >>> 0) % 1e3 < t * 1e3;
|
|
454
|
+
}, We = (e, t) => {
|
|
455
|
+
if (t.mode === "off" || B(e) || z(e) && !t.persistDelivery) return !1;
|
|
456
|
+
let n = e.status === "error";
|
|
457
|
+
if (t.mode === "errors") return n;
|
|
458
|
+
if (n) return !0;
|
|
459
|
+
if (!Ue(e.traceId, t.sampleRate)) return !1;
|
|
460
|
+
if (t.mode === "all") return !0;
|
|
461
|
+
let r = e.parentSpanId === null || e.parentSpanId === void 0 || e.parentSpanId === "", i = typeof e.durationMs == "number" && e.durationMs >= t.slowMs;
|
|
462
|
+
return r || i;
|
|
463
|
+
}, Ge = (e) => {
|
|
464
|
+
if (e.bufferDisabled) return "durable traces: OFF (VOLTRO_TRACING_BUFFER=off)";
|
|
465
|
+
if (e.mode === "off") return "durable traces: OFF — _voltro_traces not created (prod default; set VOLTRO_TRACING_PERSIST=interesting to enable, or use OTLP)";
|
|
466
|
+
let t = e.mode === "interesting" ? ` (errors + slow≥${e.slowMs}ms + roots)` : e.mode === "errors" ? " (errors only)" : "";
|
|
467
|
+
return `durable traces: mode=${e.mode}${t}` + (e.sampleRate < 1 ? ` · sample=${e.sampleRate}` : "") + (e.persistDelivery ? " · +delivery" : "") + ` · ttl=${e.ttlHours}h`;
|
|
468
|
+
}, Ke = (e = 30 * 6e4) => {
|
|
469
|
+
let t = /* @__PURE__ */ new Map();
|
|
470
|
+
return (n, r) => {
|
|
471
|
+
let i = t.get(n);
|
|
472
|
+
return i !== void 0 && r - i < e ? !1 : (t.set(n, r), !0);
|
|
473
|
+
};
|
|
474
|
+
}, qe = (e) => {
|
|
475
|
+
let { store: t, log: n } = e, r = e.policy ?? W();
|
|
476
|
+
n.info(Ge(r));
|
|
477
|
+
let i = Ke(), a = [], o = () => {};
|
|
478
|
+
if (r.mode !== "off") {
|
|
479
|
+
let e = [], s = 0;
|
|
480
|
+
o = (t) => {
|
|
481
|
+
We(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));
|
|
482
|
+
};
|
|
483
|
+
let c = async () => {
|
|
484
|
+
if (e.length === 0) return;
|
|
485
|
+
let n = e.splice(0, 200);
|
|
486
|
+
for (let e of n) try {
|
|
487
|
+
await t.insert("_voltro_traces", {
|
|
488
|
+
id: `${e.traceId}:${e.spanId}`,
|
|
489
|
+
traceId: e.traceId,
|
|
490
|
+
spanId: e.spanId,
|
|
491
|
+
parentSpanId: e.parentSpanId,
|
|
492
|
+
name: e.name,
|
|
493
|
+
kind: e.kind,
|
|
494
|
+
status: e.status,
|
|
495
|
+
statusMessage: e.statusMessage ?? null,
|
|
496
|
+
startedAt: new Date(e.startMs),
|
|
497
|
+
endedAt: new Date(e.endMs),
|
|
498
|
+
durationMs: Math.round(e.durationMs),
|
|
499
|
+
attributes: e.attributes,
|
|
500
|
+
events: e.events ?? null
|
|
501
|
+
});
|
|
502
|
+
} catch {}
|
|
503
|
+
}, l = setInterval(() => {
|
|
504
|
+
c();
|
|
505
|
+
}, 1e3);
|
|
506
|
+
l.unref?.(), a.push(l);
|
|
507
|
+
}
|
|
508
|
+
let s = r.ttlHours, c = 2e4, l = t.raw?.bind(t), u = async () => {
|
|
509
|
+
try {
|
|
510
|
+
let e = /* @__PURE__ */ new Date(Date.now() - s * 36e5), r = 0;
|
|
511
|
+
if (l) for (;;) {
|
|
512
|
+
let t = await l({
|
|
513
|
+
_tag: "RawSqlFragment",
|
|
514
|
+
strings: ["DELETE FROM \"_voltro_traces\" WHERE \"id\" IN (SELECT \"id\" FROM \"_voltro_traces\" WHERE \"startedAt\" < ", ` LIMIT ${c}) RETURNING "id"`],
|
|
515
|
+
values: [e]
|
|
516
|
+
});
|
|
517
|
+
if (r += t.length, t.length < c) break;
|
|
518
|
+
}
|
|
519
|
+
else for (;;) {
|
|
520
|
+
let n = await t.query({
|
|
521
|
+
table: "_voltro_traces",
|
|
522
|
+
order: [],
|
|
523
|
+
predicate: _("startedAt", e),
|
|
524
|
+
projection: ["id"],
|
|
525
|
+
skip: void 0,
|
|
526
|
+
take: c
|
|
527
|
+
});
|
|
528
|
+
if (n.length === 0) break;
|
|
529
|
+
for (let e of n) try {
|
|
530
|
+
await t.delete("_voltro_traces", e.id);
|
|
531
|
+
} catch {}
|
|
532
|
+
if (r += n.length, n.length < c) break;
|
|
533
|
+
}
|
|
534
|
+
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.`);
|
|
535
|
+
} catch (e) {
|
|
536
|
+
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)}`);
|
|
537
|
+
}
|
|
538
|
+
}, d = setInterval(() => {
|
|
539
|
+
u();
|
|
540
|
+
}, 5 * 6e4);
|
|
541
|
+
return d.unref?.(), a.push(d), {
|
|
542
|
+
persistTraceSpan: (e) => o(e),
|
|
543
|
+
stop: () => {
|
|
544
|
+
for (let e of a) clearInterval(e);
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
}, Je = /\.(query|mutation|action|stream)\.ts$/, Ye = /\.(query|mutation|action|stream)\.server\.ts$/, K = /\.workflow\.tsx$/, q = /\.workflow\.server\.tsx$/, J = /\.workflow\.tsx?$/, Y = /\.trigger\.tsx?$/, X = /\.cron\.tsx?$/, Z = /\.webhook\.tsx?$/, Q = /\.outbox\.tsx?$/, Xe = /\.subscribe\.tsx?$/, Ze = /\.reaction\.tsx?$/, Qe = /\.aggregate\.tsx?$/, $e = /\.startup\.tsx?$/, et = /\.seed\.ts$/, tt = /\.relations\.ts$/, nt = /\.entity\.ts$|\.schema\.ts$|^schema\.ts$/, rt = (e) => J.test(e) && !K.test(e) && !q.test(e), it = async (e) => {
|
|
548
|
+
let t = !1, r = !1, i = !1, o = !1, s = !1, c = !1, l = async (e) => {
|
|
549
|
+
let u = await a.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
550
|
+
for (let a of u) if (a.isDirectory()) {
|
|
551
|
+
if (a.name === "node_modules" || a.name === "dist" || a.name === ".framework" || a.name.startsWith(".")) continue;
|
|
552
|
+
await l(n(e, a.name));
|
|
553
|
+
} else {
|
|
554
|
+
let e = a.name;
|
|
555
|
+
(J.test(e) || Y.test(e)) && (t = !0), X.test(e) && (r = !0), Z.test(e) && (i = !0), F.test(e) && (o = !0), Q.test(e) && (s = !0), R.test(e) && (c = !0);
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
return await l(e), {
|
|
559
|
+
workflows: t,
|
|
560
|
+
schedules: r,
|
|
561
|
+
webhooks: i,
|
|
562
|
+
agents: o,
|
|
563
|
+
outbox: s,
|
|
564
|
+
connections: c
|
|
565
|
+
};
|
|
566
|
+
}, at = async (e) => {
|
|
567
|
+
try {
|
|
568
|
+
return (await import(r(n(e, "app.config.ts")).href)).default?.plugins ?? [];
|
|
569
|
+
} catch {
|
|
570
|
+
return [];
|
|
571
|
+
}
|
|
572
|
+
}, $ = (e) => {
|
|
573
|
+
let t = /* @__PURE__ */ new Map(), n = (e) => {
|
|
574
|
+
e?.tableName && !t.has(e.tableName) && t.set(e.tableName, e);
|
|
575
|
+
};
|
|
576
|
+
for (let t of O({
|
|
577
|
+
workflows: e.mix.workflows,
|
|
578
|
+
schedules: e.mix.schedules,
|
|
579
|
+
webhooks: e.mix.webhooks,
|
|
580
|
+
traces: G(),
|
|
581
|
+
cdc: e.cdc,
|
|
582
|
+
...e.cdcDialect ? { cdcDialect: e.cdcDialect } : {},
|
|
583
|
+
undo: ie(),
|
|
584
|
+
outbox: e.mix.outbox,
|
|
585
|
+
connections: e.mix.connections
|
|
586
|
+
})) n(t);
|
|
587
|
+
e.mix.agents && (n(le), n(ce), n(de), n(ue));
|
|
588
|
+
for (let t of ke(e.plugins)) n(t);
|
|
589
|
+
return [...t.values()];
|
|
590
|
+
}, ot = async (e) => {
|
|
591
|
+
let t = await it(e.root), n = await at(e.root), r = (process.env.DB_DIALECT ?? "postgres").toLowerCase(), i = r === "mariadb" ? "mariadb" : r === "mssql" ? "mssql" : void 0;
|
|
592
|
+
return $({
|
|
593
|
+
mix: t,
|
|
594
|
+
plugins: n,
|
|
595
|
+
cdc: e.cdc ?? (i !== void 0 && (process.env.CDC ?? "1") !== "0"),
|
|
596
|
+
...i ? { cdcDialect: i } : {}
|
|
597
|
+
});
|
|
598
|
+
};
|
|
599
|
+
//#endregion
|
|
600
|
+
export { Me as A, ze as C, F as D, Pe as E, xe as F, k as I, A as L, De as M, Oe as N, Ae as O, Se as P, O as R, V as S, R as T, J as _, Q as a, qe as b, Ze as c, et as d, $e as f, K as g, Z as h, X as i, L as j, I as k, tt as l, Y as m, $ as n, Je as o, Xe as p, Qe as r, Ye as s, ot as t, nt as u, q as v, B as w, G as x, rt as y };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
export declare const CLI_NAME: "framework";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* `voltro help` grouped by the job each command does, in the order a user meets
|
|
5
|
+
* them (scaffold → develop → data → build/run → deploy → observe → maintain).
|
|
6
|
+
*
|
|
7
|
+
* A FLAT list of 45 commands in registry order is unusable: most summaries run
|
|
8
|
+
* past 100 chars, so every line wraps and the whole thing reads as a paragraph
|
|
9
|
+
* wall. Here each line is one short lead sentence; the full summary is a
|
|
10
|
+
* `voltro <command> --help` away.
|
|
11
|
+
*
|
|
12
|
+
* Kept as one table rather than a `group` field on all 45 specs so the ordering
|
|
13
|
+
* is readable in one place. `commands.test.ts` asserts every visible command
|
|
14
|
+
* appears in exactly one group, so this can't drift when a command is added.
|
|
15
|
+
*/
|
|
16
|
+
export declare const COMMAND_GROUPS: ReadonlyArray<readonly [string, ReadonlyArray<string>]>;
|
|
17
|
+
|
|
3
18
|
export declare const COMMANDS: ReadonlyArray<CommandSpec>;
|
|
4
19
|
|
|
5
20
|
export declare type CommandSpec = {
|
|
@@ -24,6 +39,10 @@ export declare const listTemplates: () => Promise<ReadonlyArray<TemplateInfo>>;
|
|
|
24
39
|
|
|
25
40
|
export declare const printUsage: () => void;
|
|
26
41
|
|
|
42
|
+
/** Command names close enough to a typo to suggest. Also matches on prefix /
|
|
43
|
+
* substring, so `voltro work` suggests `workflows`. Exported for the test. */
|
|
44
|
+
export declare const suggestCommands: (input: string, limit?: number) => ReadonlyArray<string>;
|
|
45
|
+
|
|
27
46
|
export declare interface TemplateInfo extends TemplateManifest {
|
|
28
47
|
/** Absolute path to the template source directory. */
|
|
29
48
|
readonly path: string;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as e,
|
|
1
|
+
import { a as e, i as t, n, o as r, r as i, t as a } from "./commands-DYOuGlEC.js";
|
|
2
2
|
//#region src/index.ts
|
|
3
|
-
var
|
|
3
|
+
var o = "framework";
|
|
4
4
|
//#endregion
|
|
5
|
-
export {
|
|
5
|
+
export { o as CLI_NAME, a as COMMANDS, n as COMMAND_GROUPS, i as dispatch, r as listTemplates, t as printUsage, e as suggestCommands };
|