@voltro/cli 0.20.2 → 0.22.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 (75) hide show
  1. package/CHANGELOG.md +398 -0
  2. package/THIRD-PARTY-NOTICES.md +61 -61
  3. package/dist/{apiBuild-qZBEu59d.js → apiBuild-2zRxj2hJ.js} +93 -80
  4. package/dist/apiBuild-sqNmWmY5.js +2 -0
  5. package/dist/bin.js +41 -20
  6. package/dist/{commands-kYbfVoPO.js → commands-DGaeTn2f.js} +3055 -2640
  7. package/dist/dbCommand-CO3eSAZR.js +2 -0
  8. package/dist/{dbCommand-BPp9R0Wc.js → dbCommand-DVASmZj2.js} +305 -249
  9. package/dist/dev-BEYBSGJ7.js +3 -0
  10. package/dist/{dev-OHLsAq4K.js → dev-DeHVUxQx.js} +1732 -1686
  11. package/dist/index.js +1 -1
  12. package/dist/inspect-BA67TF6v.js +2 -0
  13. package/dist/inspect-_ldwsAwH.js +945 -0
  14. package/dist/{inspectMetrics-DvPNXmGA.js → inspectMetrics-4AVPn6IS.js} +584 -571
  15. package/dist/{manifestBuild-P9yuCY2d.js → manifestBuild-Bs1Uw22_.js} +1 -1
  16. package/dist/manifestBuild-i-fRHg_H.js +2 -0
  17. package/dist/serveCommand-DEVTtnLy.js +1161 -0
  18. package/dist/serveEntry.js +2 -2
  19. package/dist/{start-CXQ7WL1W.js → start-BjGUIIvj.js} +389 -389
  20. package/dist/startEntry.js +2 -2
  21. package/package.json +27 -27
  22. package/templates/AGENTS.md +1 -1
  23. package/templates/agent-docs/_index.md +1 -1
  24. package/templates/agent-docs/cli.md +181 -5
  25. package/templates/agent-docs/data.md +58 -0
  26. package/templates/agent-docs/database/migrations.md +175 -31
  27. package/templates/agent-docs/database/schema.md +7 -0
  28. package/templates/agent-docs/database/seedsdialects.md +3 -3
  29. package/templates/agent-docs/plugins.md +1 -1
  30. package/templates/agent-docs/schema-driven-ui.md +2 -2
  31. package/templates/agent-docs/templates/apibackends.md +1 -1
  32. package/templates/agent-docs/whats-new.md +236 -9
  33. package/templates/apps/api-ai/package.json +12 -12
  34. package/templates/apps/api-auth/package.json +13 -13
  35. package/templates/apps/api-backend/package.json +12 -12
  36. package/templates/apps/api-backend-deactivation/package.json +12 -12
  37. package/templates/apps/api-backend-mail/package.json +11 -11
  38. package/templates/apps/api-backend-mariadb/package.json +14 -14
  39. package/templates/apps/api-backend-storage/package.json +11 -11
  40. package/templates/apps/api-data-advanced/package.json +13 -13
  41. package/templates/apps/api-durable/package.json +13 -13
  42. package/templates/apps/api-feature-flags/package.json +14 -14
  43. package/templates/apps/api-governance/package.json +13 -13
  44. package/templates/apps/api-kv/package.json +13 -13
  45. package/templates/apps/api-moderation/package.json +13 -13
  46. package/templates/apps/api-observability/package.json +13 -13
  47. package/templates/apps/api-ratelimit/package.json +13 -13
  48. package/templates/apps/api-rbac/package.json +13 -13
  49. package/templates/apps/api-rest/package.json +12 -12
  50. package/templates/apps/api-saas/package.json +16 -16
  51. package/templates/apps/api-search/package.json +13 -13
  52. package/templates/apps/api-versioning/package.json +13 -13
  53. package/templates/apps/api-webhooks/package.json +14 -14
  54. package/templates/apps/changelog/package.json +8 -8
  55. package/templates/apps/edge-functions/package.json +5 -5
  56. package/templates/apps/frontend-admin/package.json +10 -10
  57. package/templates/apps/frontend-app/package.json +10 -10
  58. package/templates/apps/frontend-blank/package.json +9 -9
  59. package/templates/apps/frontend-contact/package.json +11 -11
  60. package/templates/apps/frontend-dashboard/package.json +9 -9
  61. package/templates/apps/frontend-docs/package.json +9 -9
  62. package/templates/apps/frontend-i18n/package.json +8 -8
  63. package/templates/apps/frontend-landing/package.json +9 -9
  64. package/templates/apps/frontend-spa/package.json +9 -9
  65. package/templates/apps/frontend-ssr/package.json +9 -9
  66. package/templates/apps/frontend-ssr-api/package.json +10 -10
  67. package/templates/apps/frontend-static-blog/package.json +8 -8
  68. package/dist/apiBuild-C9aHz4Yh.js +0 -2
  69. package/dist/dbCommand-DtUe-0dM.js +0 -2
  70. package/dist/dev-2AvdzDg2.js +0 -3
  71. package/dist/inspect-DcZ04OME.js +0 -2
  72. package/dist/inspect-Dwx0_tUj.js +0 -921
  73. package/dist/manifestBuild-D1MzJAiQ.js +0 -2
  74. package/dist/serveCommand-BKqTKWTX.js +0 -1136
  75. /package/templates/patches/{@effect__cluster@0.59.0.patch → @effect__cluster@0.60.0.patch} +0 -0
@@ -0,0 +1,945 @@
1
+ import { lastWriteProvenance as e } from "@voltro/runtime";
2
+ import { timingSafeStringEqual as t } from "@voltro/protocol/session";
3
+ //#region src/inspect.ts
4
+ var n = "/_voltro/inspect", r = () => process.env.VOLTRO_INSPECT === "off", i = /* @__PURE__ */ new Set([
5
+ "GET",
6
+ "HEAD",
7
+ "OPTIONS"
8
+ ]), a = (e, n) => {
9
+ let r = process.env.VOLTRO_INSPECT_TOKEN;
10
+ if (!r || r.length === 0) return {
11
+ ok: !1,
12
+ reason: "inspect is closed: no VOLTRO_INSPECT_TOKEN configured. `voltro dev` mints one per project; for serve/start set it explicitly (it is never minted outside dev)."
13
+ };
14
+ let a = e.authorization ?? e.Authorization;
15
+ if (!a) return {
16
+ ok: !1,
17
+ reason: "missing Authorization header"
18
+ };
19
+ if (!a.startsWith("Bearer ")) return {
20
+ ok: !1,
21
+ reason: "expected \"Bearer <token>\" auth scheme"
22
+ };
23
+ if (!t(a.slice(7).trim(), r)) return {
24
+ ok: !1,
25
+ reason: "token mismatch"
26
+ };
27
+ if (!i.has(n.toUpperCase())) {
28
+ let r = process.env.VOLTRO_INSPECT_WRITE_TOKEN;
29
+ if (!r || r.length === 0) return {
30
+ ok: !1,
31
+ reason: `inspect: ${(n ?? "unknown-method").toUpperCase()} is refused — no VOLTRO_INSPECT_WRITE_TOKEN configured. Mutating inspect endpoints (GDPR erase/export, storage share/revoke, schedule fire) need their own secret; the read token is not enough. \`voltro dev\` mints one per project; outside dev set it explicitly.`
32
+ };
33
+ let i = (e["x-voltro-inspect-write"] ?? e["X-Voltro-Inspect-Write"] ?? "").trim();
34
+ if (i.length === 0) return {
35
+ ok: !1,
36
+ reason: `inspect: ${n.toUpperCase()} needs the write credential — send it as the \`x-voltro-inspect-write\` header alongside the bearer. The read token authorises reads only.`
37
+ };
38
+ if (!t(i, r)) return {
39
+ ok: !1,
40
+ reason: "inspect: write-credential mismatch"
41
+ };
42
+ }
43
+ return { ok: !0 };
44
+ }, o = (e) => {
45
+ if (!Array.isArray(e) || e.length === 0) return;
46
+ let t = [];
47
+ for (let n of e) {
48
+ if (typeof n != "object" || !n) continue;
49
+ if (typeof n.action == "string" && typeof n.resourceType == "string") {
50
+ t.push({
51
+ kind: "policy",
52
+ action: n.action,
53
+ resourceType: n.resourceType
54
+ });
55
+ continue;
56
+ }
57
+ let e = n.scope;
58
+ typeof e != "string" && !Array.isArray(e) || t.push({
59
+ kind: "scope",
60
+ scope: typeof e == "string" ? [e] : e.filter((e) => typeof e == "string"),
61
+ mode: n.mode === "any" ? "any" : "all",
62
+ resourceScoped: typeof n.resource == "function"
63
+ });
64
+ }
65
+ return t.length > 0 ? t : void 0;
66
+ }, s = (e, t, n = {}) => ({
67
+ status: e,
68
+ contentType: "application/json; charset=utf-8",
69
+ body: JSON.stringify(t),
70
+ headers: n
71
+ }), c = (e) => {
72
+ let t;
73
+ try {
74
+ t = new URL(e).hostname;
75
+ } catch {
76
+ return !1;
77
+ }
78
+ return t = t.replace(/^\[|\]$/g, ""), t === "localhost" || t.endsWith(".localhost") || t === "::1" ? !0 : /^127(?:\.\d{1,3}){3}$/.test(t);
79
+ }, l = (e) => !e || e.length === 0 ? {} : c(e) ? {
80
+ "access-control-allow-origin": e,
81
+ "access-control-allow-credentials": "true",
82
+ "access-control-allow-methods": "GET, POST, OPTIONS",
83
+ "access-control-allow-headers": "authorization, content-type, accept",
84
+ "access-control-expose-headers": "content-type, content-length",
85
+ vary: "Origin"
86
+ } : { vary: "Origin" }, u = (e, t = process.env.VOLTRO_DASHBOARD_APPS) => {
87
+ if (c(e)) return !0;
88
+ let n;
89
+ try {
90
+ n = new URL(e).origin;
91
+ } catch {
92
+ return !1;
93
+ }
94
+ if (!t || t.trim() === "") return !1;
95
+ try {
96
+ let e = JSON.parse(t);
97
+ return Array.isArray(e) ? e.some((e) => {
98
+ let t = e?.url;
99
+ if (typeof t != "string") return !1;
100
+ try {
101
+ return new URL(t).origin === n;
102
+ } catch {
103
+ return !1;
104
+ }
105
+ }) : !1;
106
+ } catch {
107
+ return !1;
108
+ }
109
+ }, d = (e, t, n = {}) => {
110
+ let r = (e ?? "GET").toUpperCase();
111
+ if (r === "GET" || r === "HEAD" || r === "OPTIONS") return null;
112
+ let i = t.origin ?? t.Origin;
113
+ return i === void 0 || i === "" || c(i) ? null : s(403, {
114
+ error: "cross-site write rejected",
115
+ reason: `a state-changing inspect request may not come from origin "${i}" — only same-machine (loopback) origins may write`
116
+ }, n);
117
+ }, f = (e) => {
118
+ let t = e.indexOf("?");
119
+ return t === -1 ? e : e.slice(0, t);
120
+ }, p = (e) => {
121
+ let t = e.indexOf("?");
122
+ return t === -1 ? new URLSearchParams() : new URLSearchParams(e.slice(t + 1));
123
+ }, m = (e) => e === "/_voltro/inspect" || e.startsWith("/_voltro/inspect/"), h = [
124
+ "text",
125
+ "textarea",
126
+ "number",
127
+ "checkbox",
128
+ "switch",
129
+ "select",
130
+ "radio",
131
+ "async-select",
132
+ "multi-select",
133
+ "date",
134
+ "datetime",
135
+ "daterange",
136
+ "file",
137
+ "hidden",
138
+ "custom"
139
+ ], g = (e, t, n = [], r = []) => ({
140
+ version: 2,
141
+ scopes: [...new Set(r.flatMap((e) => e.declaredScopes ?? []))].sort(),
142
+ procedures: [...e].sort((e, t) => e.tag.localeCompare(t.tag)).map((e) => ({
143
+ tag: e.tag,
144
+ kind: e.kind,
145
+ ...e.inputSchema === void 0 ? {} : { input: e.inputSchema },
146
+ ...e.outputSchema === void 0 ? {} : { output: e.outputSchema },
147
+ ...e.source === void 0 ? {} : { source: e.source },
148
+ ...e.targets === void 0 ? {} : { targets: e.targets },
149
+ ...e.guards === void 0 ? {} : { guards: e.guards },
150
+ ...e.publicApi === void 0 ? {} : { publicApi: e.publicApi },
151
+ ...e.exposeAsTool === void 0 ? {} : { exposeAsTool: e.exposeAsTool }
152
+ })),
153
+ workflows: [...t].sort((e, t) => e.tag.localeCompare(t.tag)).map((e) => ({ name: e.tag })),
154
+ widgets: h,
155
+ tables: [...n].filter((e) => !e.isFrameworkTable).sort((e, t) => e.name.localeCompare(t.name)).map((e) => ({
156
+ name: e.name,
157
+ reactive: e.isReactive,
158
+ framework: e.isFrameworkTable,
159
+ columns: e.columns.map((e) => ({
160
+ name: e.name,
161
+ type: String(e.type),
162
+ nullable: e.nullable,
163
+ ...e.referencesTable === void 0 ? {} : { refersTo: e.referencesTable },
164
+ ...e.oneOf === void 0 ? {} : { enum: e.oneOf }
165
+ }))
166
+ }))
167
+ }), _ = (e, t, n = {}, i = {}) => {
168
+ let o = f(e);
169
+ if (!m(o)) return null;
170
+ let c = l(n.origin ?? n.Origin), u = (i.method ?? "GET").toUpperCase();
171
+ if (u === "OPTIONS") return {
172
+ status: 204,
173
+ contentType: "text/plain",
174
+ body: "",
175
+ headers: c
176
+ };
177
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, c);
178
+ let d = (i.authResolver ?? a)(n, u);
179
+ if (!d.ok) return s(401, {
180
+ error: "unauthorized",
181
+ reason: d.reason
182
+ }, c);
183
+ if (o === "/_voltro/inspect" || o === "/_voltro/inspect/" || o === "/_voltro/inspect/app") return s(200, {
184
+ kind: t.kind,
185
+ ...t.meta
186
+ }, c);
187
+ if (o === "/_voltro/inspect/routes") return t.kind === "web" ? s(200, {
188
+ pages: t.routes,
189
+ dirs: t.dirs
190
+ }, c) : s(404, { error: "routes endpoint is web-only" }, c);
191
+ if (o === "/_voltro/inspect/cache") return t.kind === "web" ? s(200, t.cache(), c) : s(404, { error: "cache endpoint is web-only" }, c);
192
+ if (o === "/_voltro/inspect/rpc") return t.kind === "api" ? s(200, {
193
+ procedures: t.rpc,
194
+ workflows: t.workflows
195
+ }, c) : s(404, { error: "rpc endpoint is api-only" }, c);
196
+ if (o === "/_voltro/inspect/manifest") {
197
+ if (t.kind !== "api") return s(404, { error: "manifest endpoint is api-only" }, c);
198
+ let e = t.inspectTables?.().tables ?? [];
199
+ return s(200, g(t.rpc, t.workflows, e, t.plugins?.().plugins ?? []), c);
200
+ }
201
+ return o === "/_voltro/inspect/metrics" ? t.metrics === void 0 ? s(200, [], c) : s(200, t.metrics(), c) : o === "/_voltro/inspect/subscriptions" ? t.kind === "api" ? t.subscriptions === void 0 ? s(200, {
202
+ subscriptions: [],
203
+ matcherStats: [],
204
+ capturedAt: Date.now()
205
+ }, c) : s(200, t.subscriptions(), c) : s(404, { error: "subscriptions endpoint is api-only" }, c) : o === "/_voltro/inspect/data-cache" ? t.kind === "api" ? t.dataCache === void 0 ? s(200, {
206
+ backend: "memory",
207
+ engine: "memory",
208
+ driver: "resp",
209
+ hits: 0,
210
+ misses: 0,
211
+ hitRate: 0
212
+ }, c) : s(200, t.dataCache(), c) : s(404, { error: "data-cache endpoint is api-only" }, c) : o === "/_voltro/inspect/database" ? t.kind === "api" ? t.database === void 0 ? s(200, {
213
+ migrations: [],
214
+ seeds: []
215
+ }, c) : s(200, t.database(), c) : s(404, { error: "database endpoint is api-only" }, c) : o === "/_voltro/inspect/plugins" ? t.kind === "api" ? t.plugins === void 0 ? s(200, {
216
+ plugins: [],
217
+ capturedAt: Date.now()
218
+ }, c) : s(200, t.plugins(), c) : s(404, { error: "plugins endpoint is api-only" }, c) : o === "/_voltro/inspect/env" ? t.env === void 0 ? s(200, {
219
+ app: t.meta.name ?? "app",
220
+ entries: [],
221
+ summary: {
222
+ total: 0,
223
+ set: 0,
224
+ missingRequired: 0
225
+ }
226
+ }, c) : s(200, t.env(), c) : o === "/_voltro/inspect/data/tables" ? t.kind === "api" ? t.inspectTables === void 0 ? s(200, { tables: [] }, c) : s(200, t.inspectTables(), c) : s(404, { error: "data viewer is api-only" }, c) : o === "/_voltro/inspect/invoke" ? s(404, { error: "invoke not enabled here — use POST handler" }, c) : s(404, {
227
+ error: "unknown inspect endpoint",
228
+ path: o
229
+ }, c);
230
+ }, v = async (e, t, n, i = {}) => {
231
+ let o = l(t.origin ?? t.Origin);
232
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, o);
233
+ let c = (i.method ?? "POST").toUpperCase();
234
+ if (c !== "POST") return s(405, {
235
+ error: "method not allowed",
236
+ expected: "POST"
237
+ }, o);
238
+ let u = (i.authResolver ?? a)(t, c);
239
+ if (!u.ok) return s(401, {
240
+ error: "unauthorized",
241
+ reason: u.reason
242
+ }, o);
243
+ if (e.kind !== "api") return s(404, { error: "invoke endpoint is api-only" }, o);
244
+ if (!e.invokers || e.invokers.size === 0) return s(404, { error: "invoke not configured" }, o);
245
+ let d;
246
+ try {
247
+ d = JSON.parse(n || "{}");
248
+ } catch {
249
+ return s(400, { error: "body must be JSON" }, o);
250
+ }
251
+ let f = d;
252
+ if (typeof f.tag != "string") return s(400, { error: "body.tag must be a string" }, o);
253
+ let p = e.invokers.get(f.tag);
254
+ if (!p) return s(404, {
255
+ error: "unknown tag",
256
+ tag: f.tag
257
+ }, o);
258
+ let m = typeof f.headers == "object" && f.headers !== null ? f.headers : {}, h = {};
259
+ for (let [e, n] of Object.entries(t)) h[e.toLowerCase()] = n;
260
+ for (let [e, t] of Object.entries(m)) {
261
+ let n = e.toLowerCase();
262
+ n !== "cookie" && (h[n] = t);
263
+ }
264
+ return s(200, await p(f.input, h), o);
265
+ }, y = async (e, t, i, o, c = {}) => {
266
+ let u = f(e);
267
+ if (!m(u) || !u.startsWith("/_voltro/inspect/webhooks/")) return null;
268
+ let p = l(i.origin ?? i.Origin);
269
+ if ((c.method ?? "POST").toUpperCase() !== "POST") return null;
270
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, p);
271
+ let h = (c.authResolver ?? a)(i, c.method ?? "POST");
272
+ if (!h.ok) return s(401, {
273
+ error: "unauthorized",
274
+ reason: h.reason
275
+ }, p);
276
+ let g = d(c.method, i, p);
277
+ if (g) return g;
278
+ if (t.kind !== "api") return s(404, { error: "webhook actions are api-only" }, p);
279
+ if (!t.webhookActions) return s(404, { error: "webhook actions not configured — is @voltro/plugin-webhooks active?" }, p);
280
+ let _;
281
+ try {
282
+ _ = JSON.parse(o || "{}");
283
+ } catch {
284
+ return s(400, { error: "body must be JSON" }, p);
285
+ }
286
+ let v = u.slice(`${n}/webhooks/`.length);
287
+ try {
288
+ switch (v) {
289
+ case "subscribe": {
290
+ let e = _;
291
+ return typeof e.event != "string" || e.event.length === 0 ? s(400, { error: "event required" }, p) : typeof e.url != "string" || e.url.length === 0 ? s(400, { error: "url required" }, p) : s(200, await t.webhookActions.subscribe(e), p);
292
+ }
293
+ case "pause": {
294
+ let e = _.targetId;
295
+ return typeof e != "string" || e.length === 0 ? s(400, { error: "targetId required" }, p) : (await t.webhookActions.pause(e), s(200, { ok: !0 }, p));
296
+ }
297
+ case "resume": {
298
+ let e = _.targetId;
299
+ return typeof e != "string" || e.length === 0 ? s(400, { error: "targetId required" }, p) : (await t.webhookActions.resume(e), s(200, { ok: !0 }, p));
300
+ }
301
+ case "delete": {
302
+ let e = _.targetId;
303
+ return typeof e != "string" || e.length === 0 ? s(400, { error: "targetId required" }, p) : (await t.webhookActions.delete(e), s(200, { ok: !0 }, p));
304
+ }
305
+ case "rotateSecret": {
306
+ let e = _.targetId;
307
+ return typeof e != "string" || e.length === 0 ? s(400, { error: "targetId required" }, p) : s(200, await t.webhookActions.rotateSecret(e), p);
308
+ }
309
+ case "replay": {
310
+ let e = _.deliveryId;
311
+ return typeof e != "string" || e.length === 0 ? s(400, { error: "deliveryId required" }, p) : (await t.webhookActions.replay(e), s(200, { ok: !0 }, p));
312
+ }
313
+ case "repinVersion": {
314
+ let e = _.targetId, n = _.version;
315
+ return typeof e != "string" || e.length === 0 ? s(400, { error: "targetId required" }, p) : typeof n != "number" || !Number.isInteger(n) || n < 1 ? s(400, { error: "version must be a positive integer" }, p) : (await t.webhookActions.updateTargetPayloadVersion(e, n), s(200, { ok: !0 }, p));
316
+ }
317
+ default: return s(404, { error: `unknown webhook action: ${v}` }, p);
318
+ }
319
+ } catch (e) {
320
+ return s(500, {
321
+ error: "webhook action failed",
322
+ message: e?.message ?? String(e)
323
+ }, p);
324
+ }
325
+ }, b = async (e, t, i, o, c = {}) => {
326
+ let u = f(e);
327
+ if (!m(u)) return null;
328
+ let d = l(i.origin ?? i.Origin), p = (c.method ?? "POST").toUpperCase();
329
+ if (p !== "POST") return null;
330
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, d);
331
+ let h = (c.authResolver ?? a)(i, p);
332
+ if (!h.ok) return s(401, {
333
+ error: "unauthorized",
334
+ reason: h.reason
335
+ }, d);
336
+ if (t.kind !== "api") return s(404, { error: "framework-action endpoints are api-only" }, d);
337
+ let g = `${n}/seeds/run`, _ = `${n}/migrations/rollback`, v = `${n}/migrations/squash`, y = `${n}/migrations/restore-snapshot`;
338
+ if (u !== g && u !== _ && u !== v && u !== y && u !== "/_voltro/inspect/migrations/compare-env") return null;
339
+ let b;
340
+ try {
341
+ b = JSON.parse(o || "{}");
342
+ } catch {
343
+ return s(400, { error: "body must be JSON" }, d);
344
+ }
345
+ try {
346
+ if (u === g) return typeof b.id != "string" || b.id.length === 0 ? s(400, { error: "body.id must be a non-empty string" }, d) : t.runSeed ? s(200, await t.runSeed(b.id), d) : s(404, { error: "runSeed not configured" }, d);
347
+ if (u === _) return typeof b.id != "string" || b.id.length === 0 ? s(400, { error: "body.id must be a non-empty string" }, d) : t.rollbackMigration ? s(200, await t.rollbackMigration(b.id), d) : s(404, { error: "rollbackMigration not configured" }, d);
348
+ if (u === v) {
349
+ if (typeof b.before != "string" || b.before.length === 0) return s(400, { error: "body.before must be a non-empty ISO date string" }, d);
350
+ if (!t.squashMigrationHistory) return s(404, { error: "squashMigrationHistory not configured" }, d);
351
+ let e = typeof b.note == "string" ? b.note : void 0;
352
+ return s(200, await t.squashMigrationHistory({
353
+ before: b.before,
354
+ note: e
355
+ }), d);
356
+ }
357
+ return u === y ? typeof b.planId != "string" || b.planId.length === 0 ? s(400, { error: "body.planId must be a non-empty string" }, d) : t.restoreSnapshot ? s(200, await t.restoreSnapshot({ planId: b.planId }), d) : s(404, { error: "restoreSnapshot not configured" }, d) : typeof b.url != "string" || b.url.length === 0 ? s(400, { error: "body.url must be a non-empty URL string" }, d) : t.compareCrossEnv ? (await t.compareCrossEnv({
358
+ url: b.url,
359
+ label: typeof b.label == "string" ? b.label : void 0,
360
+ token: typeof b.token == "string" ? b.token : void 0
361
+ }), s(200, { ok: !0 }, d)) : s(404, { error: "compareCrossEnv not configured" }, d);
362
+ } catch (e) {
363
+ return s(500, {
364
+ error: "framework action failed",
365
+ message: e?.message ?? String(e)
366
+ }, d);
367
+ }
368
+ }, x = async (e, t, n, i = {}) => {
369
+ if (f(e) !== "/_voltro/inspect/data/rows") return null;
370
+ let o = l(n.origin ?? n.Origin), c = (i.method ?? "GET").toUpperCase();
371
+ if (c !== "GET") return s(405, {
372
+ error: "method not allowed",
373
+ expected: "GET"
374
+ }, o);
375
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, o);
376
+ let u = (i.authResolver ?? a)(n, c);
377
+ if (!u.ok) return s(401, {
378
+ error: "unauthorized",
379
+ reason: u.reason
380
+ }, o);
381
+ if (t.kind !== "api") return s(404, { error: "data viewer is api-only" }, o);
382
+ if (t.inspectRows === void 0) return s(404, { error: "inspectRows not configured" }, o);
383
+ let d = C(e), p = d.get("table");
384
+ if (!p) return s(400, { error: "query.table is required" }, o);
385
+ let m = w(d.get("offset")) ?? 0, h = w(d.get("limit")) ?? 50, g = {}, _ = d.get("q");
386
+ if (_) {
387
+ if (_.length > 8192) return s(400, { error: "query.q too large" }, o);
388
+ try {
389
+ g = JSON.parse(Buffer.from(_, "base64url").toString("utf8"));
390
+ } catch {
391
+ return s(400, { error: "query.q is not valid base64url JSON" }, o);
392
+ }
393
+ }
394
+ try {
395
+ return s(200, await t.inspectRows({
396
+ table: p,
397
+ offset: m,
398
+ limit: h,
399
+ ...g
400
+ }), o);
401
+ } catch (e) {
402
+ return e?.name === "InspectQueryError" ? s(400, {
403
+ error: "invalid query",
404
+ message: e.message
405
+ }, o) : s(500, {
406
+ error: "data-rows query failed",
407
+ message: e?.message ?? String(e)
408
+ }, o);
409
+ }
410
+ }, S = async (t, n, i, o = {}) => {
411
+ if (f(t) !== "/_voltro/inspect/provenance") return null;
412
+ let c = l(i.origin ?? i.Origin), u = (o.method ?? "GET").toUpperCase();
413
+ if (u !== "GET") return s(405, {
414
+ error: "method not allowed",
415
+ expected: "GET"
416
+ }, c);
417
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, c);
418
+ let p = (o.authResolver ?? a)(i, u);
419
+ if (!p.ok) return s(401, {
420
+ error: "unauthorized",
421
+ reason: p.reason
422
+ }, c);
423
+ let m = d(o.method, i, c);
424
+ if (m) return m;
425
+ if (n.kind !== "api") return s(404, { error: "provenance is api-only" }, c);
426
+ if (n.inspectRows === void 0) return s(404, { error: "inspectRows not configured" }, c);
427
+ let h = C(t), g = h.get("table"), _ = h.get("id"), v = h.get("column") ?? void 0;
428
+ if (!g || !_) return s(400, { error: "query.table and query.id are required" }, c);
429
+ try {
430
+ let t = (await n.inspectRows({
431
+ table: g,
432
+ limit: 1,
433
+ filter: {
434
+ kind: "leaf",
435
+ column: "id",
436
+ op: "eq",
437
+ value: _
438
+ }
439
+ })).rows[0];
440
+ return s(200, e(t, {
441
+ table: g,
442
+ id: _,
443
+ ...v === void 0 ? {} : { column: v }
444
+ }), c);
445
+ } catch (e) {
446
+ return e?.name === "InspectQueryError" ? s(400, {
447
+ error: "invalid query",
448
+ message: e.message
449
+ }, c) : s(500, {
450
+ error: "provenance query failed",
451
+ message: e?.message ?? String(e)
452
+ }, c);
453
+ }
454
+ }, C = (e) => {
455
+ let t = e.indexOf("?");
456
+ return t < 0 ? new URLSearchParams() : new URLSearchParams(e.slice(t + 1));
457
+ }, w = (e) => {
458
+ if (e === null || e === "") return;
459
+ let t = Number(e);
460
+ return Number.isFinite(t) && t >= 0 ? Math.floor(t) : void 0;
461
+ }, T = async (e, t, n, i = {}) => {
462
+ if (f(e) !== "/_voltro/inspect/workflows/runs") return null;
463
+ let o = l(n.origin ?? n.Origin), c = (i.method ?? "GET").toUpperCase();
464
+ if (c !== "GET") return s(405, {
465
+ error: "method not allowed",
466
+ expected: "GET"
467
+ }, o);
468
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, o);
469
+ let u = (i.authResolver ?? a)(n, c);
470
+ if (!u.ok) return s(401, {
471
+ error: "unauthorized",
472
+ reason: u.reason
473
+ }, o);
474
+ if (t.kind !== "api") return s(404, { error: "workflows endpoint is api-only" }, o);
475
+ if (t.inspectWorkflowRuns === void 0) return s(200, {
476
+ runs: [],
477
+ total: 0,
478
+ offset: 0,
479
+ limit: 50
480
+ }, o);
481
+ let d = C(e);
482
+ try {
483
+ return s(200, await t.inspectWorkflowRuns({
484
+ ...d.get("tag") === null ? {} : { tag: d.get("tag") },
485
+ ...d.get("status") === null ? {} : { status: d.get("status") },
486
+ offset: w(d.get("offset")) ?? 0,
487
+ limit: w(d.get("limit")) ?? 50
488
+ }), o);
489
+ } catch (e) {
490
+ return s(500, {
491
+ error: "workflow-runs query failed",
492
+ message: e?.message ?? String(e)
493
+ }, o);
494
+ }
495
+ }, E = async (e, t, n, i, o = {}) => {
496
+ let c = f(e).match(/^\/_voltro\/inspect\/workflows\/start\/([^/]+)$/);
497
+ if (!c) return null;
498
+ let u = decodeURIComponent(c[1] ?? ""), d = l(n.origin ?? n.Origin), p = (o.method ?? "POST").toUpperCase();
499
+ if (p !== "POST") return s(405, {
500
+ error: "method not allowed",
501
+ expected: "POST"
502
+ }, d);
503
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, d);
504
+ let m = (o.authResolver ?? a)(n, p);
505
+ if (!m.ok) return s(401, {
506
+ error: "unauthorized",
507
+ reason: m.reason
508
+ }, d);
509
+ if (t.kind !== "api") return s(404, { error: "workflow start is api-only" }, d);
510
+ if (t.inspectStartWorkflow === void 0) return s(404, { error: "inspectStartWorkflow not configured" }, d);
511
+ let h = {};
512
+ if (i.length > 0) try {
513
+ h = JSON.parse(i).payload ?? {};
514
+ } catch {
515
+ return s(400, { error: "start requires JSON body `{ payload?: unknown }`" }, d);
516
+ }
517
+ try {
518
+ return s(200, await t.inspectStartWorkflow({
519
+ name: u,
520
+ payload: h
521
+ }), d);
522
+ } catch (e) {
523
+ return s(500, {
524
+ error: "workflow start failed",
525
+ message: e?.message ?? String(e)
526
+ }, d);
527
+ }
528
+ }, D = async (e, t, n, i = {}) => {
529
+ let o = f(e);
530
+ if (!o.startsWith("/_voltro/inspect/schedules")) return null;
531
+ let c = l(n.origin ?? n.Origin);
532
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, c);
533
+ let u = (i.authResolver ?? a)(n, i.method ?? "POST");
534
+ if (!u.ok) return s(401, {
535
+ error: "unauthorized",
536
+ reason: u.reason
537
+ }, c);
538
+ let p = d(i.method, n, c);
539
+ if (p) return p;
540
+ if (t.kind !== "api") return s(404, { error: "schedules are api-only" }, c);
541
+ let m = (i.method ?? "GET").toUpperCase(), h = o.match(/^\/_voltro\/inspect\/schedules\/([^/]+)\/fire$/);
542
+ if (h) {
543
+ if (m !== "POST") return s(405, {
544
+ error: "method not allowed",
545
+ expected: "POST"
546
+ }, c);
547
+ if (!t.inspectFireSchedule) return s(404, { error: "inspectFireSchedule not configured" }, c);
548
+ let n = decodeURIComponent(h[1] ?? ""), r = C(e).get("trigger") === "external" ? "external" : "manual";
549
+ try {
550
+ return s(200, await t.inspectFireSchedule({
551
+ name: n,
552
+ trigger: r
553
+ }), c);
554
+ } catch (e) {
555
+ return s(500, {
556
+ error: "fire failed",
557
+ message: e?.message ?? String(e)
558
+ }, c);
559
+ }
560
+ }
561
+ if (o === "/_voltro/inspect/schedules/runs") {
562
+ if (m !== "GET") return s(405, {
563
+ error: "method not allowed",
564
+ expected: "GET"
565
+ }, c);
566
+ if (!t.inspectScheduleRuns) return s(200, {
567
+ runs: [],
568
+ total: 0,
569
+ offset: 0,
570
+ limit: 50
571
+ }, c);
572
+ let n = C(e);
573
+ try {
574
+ return s(200, await t.inspectScheduleRuns({
575
+ ...n.get("name") === null ? {} : { name: n.get("name") },
576
+ offset: w(n.get("offset")) ?? 0,
577
+ limit: w(n.get("limit")) ?? 50
578
+ }), c);
579
+ } catch (e) {
580
+ return s(500, {
581
+ error: "schedule-runs query failed",
582
+ message: e?.message ?? String(e)
583
+ }, c);
584
+ }
585
+ }
586
+ return o === "/_voltro/inspect/schedules" ? m === "GET" ? t.inspectSchedules ? s(200, t.inspectSchedules(), c) : s(200, {
587
+ schedules: [],
588
+ coordination: "single"
589
+ }, c) : s(405, {
590
+ error: "method not allowed",
591
+ expected: "GET"
592
+ }, c) : s(404, {
593
+ error: "unknown schedules endpoint",
594
+ path: o
595
+ }, c);
596
+ }, O = async (e, t, n, i = {}) => {
597
+ if (f(e) !== "/_voltro/inspect/cluster") return null;
598
+ let o = l(n.origin ?? n.Origin);
599
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, o);
600
+ let c = (i.authResolver ?? a)(n, i.method ?? "POST");
601
+ if (!c.ok) return s(401, {
602
+ error: "unauthorized",
603
+ reason: c.reason
604
+ }, o);
605
+ let u = d(i.method, n, o);
606
+ if (u) return u;
607
+ if (t.kind !== "api") return s(404, { error: "cluster is api-only" }, o);
608
+ if ((i.method ?? "GET").toUpperCase() !== "GET") return s(405, {
609
+ error: "method not allowed",
610
+ expected: "GET"
611
+ }, o);
612
+ if (!t.cluster) return s(200, {
613
+ instance: {
614
+ replicaId: process.env.POD_NAME ?? process.env.HOSTNAME ?? `dev-${process.pid}`,
615
+ dialect: "memory",
616
+ runnerHost: "localhost",
617
+ runnerPort: 0,
618
+ runnerStorage: "none",
619
+ shardLock: "none",
620
+ coordination: "single",
621
+ cdc: {
622
+ enabled: !1,
623
+ flavor: "none (single-process)"
624
+ },
625
+ tier: "none",
626
+ localhostRisk: !1
627
+ },
628
+ coordinationState: {
629
+ recentReplicaIds: [],
630
+ scheduleClaims: [],
631
+ runningScheduleRuns: 0,
632
+ runningWorkflowRuns: 0
633
+ },
634
+ capturedAt: Date.now()
635
+ }, o);
636
+ try {
637
+ return s(200, await t.cluster(), o);
638
+ } catch (e) {
639
+ return s(500, {
640
+ error: "cluster snapshot failed",
641
+ message: e?.message ?? String(e)
642
+ }, o);
643
+ }
644
+ }, k = async (e, t, n, i = {}) => {
645
+ let o = f(e).match(/^\/_voltro\/inspect\/workflows\/runs\/([^/]+)\/steps$/);
646
+ if (!o) return null;
647
+ let c = decodeURIComponent(o[1] ?? ""), u = l(n.origin ?? n.Origin), d = (i.method ?? "GET").toUpperCase();
648
+ if (d !== "GET") return s(405, {
649
+ error: "method not allowed",
650
+ expected: "GET"
651
+ }, u);
652
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, u);
653
+ let p = (i.authResolver ?? a)(n, d);
654
+ if (!p.ok) return s(401, {
655
+ error: "unauthorized",
656
+ reason: p.reason
657
+ }, u);
658
+ if (t.kind !== "api") return s(404, { error: "workflow steps are api-only" }, u);
659
+ if (t.inspectWorkflowRunSteps === void 0) return s(200, { steps: [] }, u);
660
+ try {
661
+ return s(200, await t.inspectWorkflowRunSteps({ runId: c }), u);
662
+ } catch (e) {
663
+ return s(500, {
664
+ error: "steps query failed",
665
+ message: e?.message ?? String(e)
666
+ }, u);
667
+ }
668
+ }, A = async (e, t, n, i = {}) => {
669
+ let o = f(e).match(/^\/_voltro\/inspect\/workflows\/runs\/([^/]+)\/events$/);
670
+ if (!o) return null;
671
+ let c = decodeURIComponent(o[1] ?? ""), u = l(n.origin ?? n.Origin), d = (i.method ?? "GET").toUpperCase();
672
+ if (d !== "GET") return s(405, {
673
+ error: "method not allowed",
674
+ expected: "GET"
675
+ }, u);
676
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, u);
677
+ let p = (i.authResolver ?? a)(n, d);
678
+ if (!p.ok) return s(401, {
679
+ error: "unauthorized",
680
+ reason: p.reason
681
+ }, u);
682
+ if (t.kind !== "api") return s(404, { error: "workflow events are api-only" }, u);
683
+ if (t.inspectWorkflowRunEvents === void 0) return s(200, { events: [] }, u);
684
+ try {
685
+ return s(200, await t.inspectWorkflowRunEvents({ runId: c }), u);
686
+ } catch (e) {
687
+ return s(500, {
688
+ error: "events query failed",
689
+ message: e?.message ?? String(e)
690
+ }, u);
691
+ }
692
+ }, j = async (e, t, n, i = {}) => {
693
+ if (f(t) !== "/_voltro/inspect/workflows/events") return null;
694
+ let o = l(n.origin ?? n.Origin), c = (i.method ?? "GET").toUpperCase();
695
+ if (c !== "GET") return s(405, {
696
+ error: "method not allowed",
697
+ expected: "GET"
698
+ }, o);
699
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, o);
700
+ let u = (i.authResolver ?? a)(n, c);
701
+ if (!u.ok) return s(401, {
702
+ error: "unauthorized",
703
+ reason: u.reason
704
+ }, o);
705
+ if (e.kind !== "api") return s(404, { error: "workflow domain events are api-only" }, o);
706
+ if (e.inspectWorkflowDomainEvents === void 0) return s(200, {
707
+ events: [],
708
+ total: 0,
709
+ offset: 0,
710
+ limit: 100
711
+ }, o);
712
+ let d = p(t), m = d.get("name") ?? void 0, h = Number(d.get("offset") ?? "0"), g = Number(d.get("limit") ?? "100");
713
+ try {
714
+ return s(200, await e.inspectWorkflowDomainEvents({
715
+ ...m !== void 0 && m !== "" ? { name: m } : {},
716
+ offset: Number.isFinite(h) ? h : 0,
717
+ limit: Number.isFinite(g) ? g : 100
718
+ }), o);
719
+ } catch (e) {
720
+ return s(500, {
721
+ error: "workflow domain events query failed",
722
+ message: e?.message ?? String(e)
723
+ }, o);
724
+ }
725
+ }, M = async (e, t, n, i = {}) => {
726
+ let o = f(t).match(/^\/_voltro\/inspect\/workflows\/events\/([^/]+)\/deliveries$/);
727
+ if (!o) return null;
728
+ let c = decodeURIComponent(o[1] ?? ""), u = l(n.origin ?? n.Origin), d = (i.method ?? "GET").toUpperCase();
729
+ if (d !== "GET") return s(405, {
730
+ error: "method not allowed",
731
+ expected: "GET"
732
+ }, u);
733
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, u);
734
+ let p = (i.authResolver ?? a)(n, d);
735
+ if (!p.ok) return s(401, {
736
+ error: "unauthorized",
737
+ reason: p.reason
738
+ }, u);
739
+ if (e.kind !== "api") return s(404, { error: "workflow event deliveries are api-only" }, u);
740
+ if (e.inspectWorkflowEventDeliveries === void 0) return s(200, { deliveries: [] }, u);
741
+ try {
742
+ return s(200, await e.inspectWorkflowEventDeliveries({ eventId: c }), u);
743
+ } catch (e) {
744
+ return s(500, {
745
+ error: "workflow event deliveries query failed",
746
+ message: e?.message ?? String(e)
747
+ }, u);
748
+ }
749
+ }, N = async (e, t, n, i = {}) => {
750
+ if (f(e) !== "/_voltro/inspect/workflows/children") return null;
751
+ let o = l(n.origin ?? n.Origin), c = (i.method ?? "GET").toUpperCase();
752
+ if (c !== "GET") return s(405, {
753
+ error: "method not allowed",
754
+ expected: "GET"
755
+ }, o);
756
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, o);
757
+ let u = (i.authResolver ?? a)(n, c);
758
+ if (!u.ok) return s(401, {
759
+ error: "unauthorized",
760
+ reason: u.reason
761
+ }, o);
762
+ if (t.kind !== "api") return s(404, { error: "workflow children are api-only" }, o);
763
+ let d = C(e).get("parentExecutionId");
764
+ if (d === null || d === "") return s(400, { error: "parentExecutionId query param required" }, o);
765
+ if (t.inspectWorkflowChildren === void 0) return s(200, {
766
+ runs: [],
767
+ total: 0,
768
+ offset: 0,
769
+ limit: 200
770
+ }, o);
771
+ try {
772
+ return s(200, await t.inspectWorkflowChildren({ parentExecutionId: d }), o);
773
+ } catch (e) {
774
+ return s(500, {
775
+ error: "children query failed",
776
+ message: e?.message ?? String(e)
777
+ }, o);
778
+ }
779
+ }, P = async (e, t, n, i, o = {}) => {
780
+ let c = f(e).match(/^\/_voltro\/inspect\/workflows\/runs\/([^/]+)\/(cancel|retry|suspend|resume|signal|update)$/);
781
+ if (!c) return null;
782
+ let u = decodeURIComponent(c[1] ?? ""), d = c[2], p = l(n.origin ?? n.Origin), m = (o.method ?? "POST").toUpperCase();
783
+ if (m !== "POST") return s(405, {
784
+ error: "method not allowed",
785
+ expected: "POST"
786
+ }, p);
787
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, p);
788
+ let h = (o.authResolver ?? a)(n, m);
789
+ if (!h.ok) return s(401, {
790
+ error: "unauthorized",
791
+ reason: h.reason
792
+ }, p);
793
+ if (t.kind !== "api") return s(404, { error: "workflow actions are api-only" }, p);
794
+ let g = {
795
+ cancel: t.inspectCancelWorkflowRun,
796
+ retry: t.inspectRetryWorkflowRun,
797
+ suspend: t.inspectSuspendWorkflowRun,
798
+ resume: t.inspectResumeWorkflowRun,
799
+ signal: t.inspectSignalWorkflowRun,
800
+ update: t.inspectUpdateWorkflowRun
801
+ }[d];
802
+ if (!g) return s(404, { error: `inspect${d[0]?.toUpperCase() ?? ""}${d.slice(1)}WorkflowRun not configured` }, p);
803
+ let _, v, y, b, x, S;
804
+ if (i.length > 0) try {
805
+ let e = JSON.parse(i);
806
+ d === "retry" && (_ = e.payloadOverride), d === "signal" && (typeof e.signalName == "string" && e.signalName.length > 0 && (v = e.signalName), y = e.payload), d === "update" && (typeof e.updateName == "string" && e.updateName.length > 0 && (b = e.updateName), x = e.payload, typeof e.timeoutMs == "number" && Number.isFinite(e.timeoutMs) && (S = e.timeoutMs));
807
+ } catch {}
808
+ if (d === "signal" && v === void 0) return s(400, { error: "signal requires JSON body `{ signalName: string, payload?: unknown }`" }, p);
809
+ if (d === "update" && b === void 0) return s(400, { error: "update requires JSON body `{ updateName: string, payload?: unknown, timeoutMs?: number }`" }, p);
810
+ try {
811
+ return s(200, d === "retry" && _ !== void 0 ? await g({
812
+ runId: u,
813
+ payloadOverride: _
814
+ }) : d === "signal" ? await g({
815
+ runId: u,
816
+ signalName: v,
817
+ payload: y
818
+ }) : d === "update" ? await g({
819
+ runId: u,
820
+ updateName: b,
821
+ payload: x,
822
+ ...S === void 0 ? {} : { timeoutMs: S }
823
+ }) : await g({ runId: u }), p);
824
+ } catch (e) {
825
+ return s(500, {
826
+ error: `${d} failed`,
827
+ message: e?.message ?? String(e)
828
+ }, p);
829
+ }
830
+ }, F = async (e, t, n, i, o = {}) => {
831
+ if (f(e) !== "/_voltro/inspect/data/import" || (o.method ?? "POST").toUpperCase() !== "POST") return null;
832
+ let c = l(n.origin ?? n.Origin);
833
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, c);
834
+ let u = (o.authResolver ?? a)(n, "POST");
835
+ if (!u.ok) return s(401, {
836
+ error: "unauthorized",
837
+ reason: u.reason
838
+ }, c);
839
+ let p = d(o.method, n, c);
840
+ if (p) return p;
841
+ if (t.kind !== "api") return s(404, { error: "data import is api-only" }, c);
842
+ if (!t.inspectImport) return s(404, { error: "inspectImport not configured" }, c);
843
+ let m;
844
+ try {
845
+ m = JSON.parse(i || "{}");
846
+ } catch {
847
+ return s(400, { error: "body must be JSON" }, c);
848
+ }
849
+ if (typeof m.bundleDir != "string" || !m.bundleDir) return s(400, { error: "body.bundleDir (string) is required" }, c);
850
+ try {
851
+ return s(200, await t.inspectImport({
852
+ bundleDir: m.bundleDir,
853
+ ...m.mode === "upsert" || m.mode === "append" || m.mode === "replace" ? { mode: m.mode } : {},
854
+ ...m.onConflict === "skip" || m.onConflict === "fail" ? { onConflict: m.onConflict } : {},
855
+ ...typeof m.atomic == "boolean" ? { atomic: m.atomic } : {}
856
+ }), c);
857
+ } catch (e) {
858
+ return s(500, {
859
+ error: "import failed",
860
+ message: e?.message ?? String(e)
861
+ }, c);
862
+ }
863
+ }, I = async (e, t, n, i, o = {}) => {
864
+ let c = f(e);
865
+ if (!c.startsWith("/_voltro/inspect/data/rows")) return null;
866
+ let u = (o.method ?? "POST").toUpperCase();
867
+ if (u === "GET" && c === "/_voltro/inspect/data/rows") return null;
868
+ let d = l(n.origin ?? n.Origin);
869
+ if (r()) return s(503, { error: "inspect disabled (VOLTRO_INSPECT=off)" }, d);
870
+ let p = (o.authResolver ?? a)(n, u);
871
+ if (!p.ok) return s(401, {
872
+ error: "unauthorized",
873
+ reason: p.reason
874
+ }, d);
875
+ if (t.kind !== "api") return s(404, { error: "data viewer is api-only" }, d);
876
+ if (u === "POST" && c === "/_voltro/inspect/data/rows") {
877
+ if (!t.inspectInsertRow) return s(404, { error: "inspectInsertRow not configured" }, d);
878
+ let e;
879
+ try {
880
+ e = JSON.parse(i || "{}");
881
+ } catch {
882
+ return s(400, { error: "body must be JSON" }, d);
883
+ }
884
+ if (typeof e.table != "string" || !e.row || typeof e.row != "object") return s(400, { error: "body must be { table: string, row: object }" }, d);
885
+ try {
886
+ return s(200, await t.inspectInsertRow({
887
+ table: e.table,
888
+ row: e.row
889
+ }), d);
890
+ } catch (e) {
891
+ return s(500, {
892
+ error: "insert failed",
893
+ message: e?.message ?? String(e)
894
+ }, d);
895
+ }
896
+ }
897
+ let m = c.match(/^\/_voltro\/inspect\/data\/rows\/([^/]+)$/);
898
+ if (!m) return null;
899
+ let h = decodeURIComponent(m[1] ?? "");
900
+ if (!h) return s(400, { error: "row id is required in URL" }, d);
901
+ let g = C(e).get("table") ?? "";
902
+ if (!g) return s(400, { error: "query.table is required" }, d);
903
+ if (u === "PATCH") {
904
+ if (!t.inspectUpdateRow) return s(404, { error: "inspectUpdateRow not configured" }, d);
905
+ let e;
906
+ try {
907
+ e = JSON.parse(i || "{}");
908
+ } catch {
909
+ return s(400, { error: "body must be JSON" }, d);
910
+ }
911
+ if (!e.patch || typeof e.patch != "object") return s(400, { error: "body.patch must be an object" }, d);
912
+ try {
913
+ return s(200, await t.inspectUpdateRow({
914
+ table: g,
915
+ id: h,
916
+ patch: e.patch
917
+ }), d);
918
+ } catch (e) {
919
+ return s(500, {
920
+ error: "update failed",
921
+ message: e?.message ?? String(e)
922
+ }, d);
923
+ }
924
+ }
925
+ if (u === "DELETE") {
926
+ if (!t.inspectDeleteRow) return s(404, { error: "inspectDeleteRow not configured" }, d);
927
+ try {
928
+ return s(200, await t.inspectDeleteRow({
929
+ table: g,
930
+ id: h
931
+ }), d);
932
+ } catch (e) {
933
+ return s(500, {
934
+ error: "delete failed",
935
+ message: e?.message ?? String(e)
936
+ }, d);
937
+ }
938
+ }
939
+ return s(405, {
940
+ error: "method not allowed",
941
+ expected: "POST | PATCH | DELETE"
942
+ }, d);
943
+ };
944
+ //#endregion
945
+ export { E as C, c as D, r as E, o as O, T as S, u as T, N as _, a, A as b, x as c, v as d, S as f, P as g, y as h, d as i, I as l, D as m, h as n, O as o, _ as p, g as r, F as s, n as t, b as u, j as v, l as w, k as x, M as y };