@voltro/cli 0.25.0 → 0.26.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 +244 -0
- package/dist/{apiBuild-BqhCSytw.js → apiBuild-BtrTyKnF.js} +2 -2
- package/dist/apiBuild-DDJ0It4j.js +2 -0
- package/dist/bin.js +3 -3
- package/dist/{commands-7EmYJ9Xg.js → commands-D-9iYF2D.js} +185 -84
- package/dist/dbCommand-DrzXimKf.js +2 -0
- package/dist/{dbCommand-FUU12FvD.js → dbCommand-uuNCrFAb.js} +238 -238
- package/dist/{dev-BvHT7WZa.js → dev-BnWq4jeA.js} +1 -1
- package/dist/{dev-MacSQ1Ll.js → dev-Dbm6SWtn.js} +1665 -1463
- package/dist/{frameworkTableAssembly-Cw5zJz6n.js → frameworkTableAssembly-BwHU9Euq.js} +10 -6
- package/dist/frameworkTableAssembly-lrjZtk0G.js +2 -0
- package/dist/index.js +1 -1
- package/dist/{inspect-DuLUrZp9.js → inspect-CUCCzw2I.js} +6 -3
- package/dist/inspect-gt8bq-Tz.js +2 -0
- package/dist/{inspectMetrics-EQwH7BI4.js → inspectMetrics-BU90mvJN.js} +1 -1
- package/dist/{manifestBuild-Dneq4_Jx.js → manifestBuild-BnzAxp2O.js} +1 -1
- package/dist/manifestBuild-ifczArzr.js +2 -0
- package/dist/serveCommand-XBXuwJty.js +1294 -0
- package/dist/serveEntry.js +2 -2
- package/dist/{start-C-ZWSDpg.js → start-BGXIf6zT.js} +2 -2
- package/dist/startEntry.js +2 -2
- package/package.json +17 -17
- package/templates/agent-docs/data.md +35 -2
- package/templates/agent-docs/database/schema.md +47 -0
- package/templates/agent-docs/deployment.md +19 -0
- package/templates/agent-docs/plugins.md +25 -3
- package/templates/agent-docs/whats-new.md +19 -3
- package/templates/agent-docs/workflows.md +116 -22
- 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-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-durable/package.json +8 -8
- package/templates/apps/api-feature-flags/package.json +9 -9
- package/templates/apps/api-governance/package.json +8 -8
- package/templates/apps/api-kv/package.json +8 -8
- 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/package.json +8 -8
- 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 -9
- 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-N1R4V792.js +0 -2
- package/dist/dbCommand-CIrdFLp9.js +0 -2
- package/dist/frameworkTableAssembly-BsnCKzQ6.js +0 -2
- package/dist/inspect-C9gjHwBk.js +0 -2
- package/dist/manifestBuild-BVwS1Z_6.js +0 -2
- package/dist/serveCommand-5ZFiNO1R.js +0 -1241
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { A as e, E as t, I as n, L as r, M as i, N as a, O as o, P as s, S as c, T as l, _t as u, a as d, at as f, b as p, c as m, ct as h, d as g, f as _, ft as v, gt as y, ht as b, it as ee, j as te, k as ne, lt as re, n as ie, o as ae, ot as oe, p as se, q as ce, s as le, st as ue, u as de, ut as fe, v as pe, y as me } from "./inspectMetrics-
|
|
1
|
+
import { A as e, E as t, I as n, L as r, M as i, N as a, O as o, P as s, S as c, T as l, _t as u, a as d, at as f, b as p, c as m, ct as h, d as g, f as _, ft as v, gt as y, ht as b, it as ee, j as te, k as ne, lt as re, n as ie, o as ae, ot as oe, p as se, q as ce, s as le, st as ue, u as de, ut as fe, v as pe, y as me } from "./inspectMetrics-BU90mvJN.js";
|
|
2
2
|
import { s as he } from "./seedRunner-D6eu-u5U.js";
|
|
3
3
|
import { a as x, c as ge, i as _e, o as ve, s as ye } from "./devActivity-BhIu6ncs.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { C as ze,
|
|
7
|
-
import { i as Qe, n as $e, o as et, r as tt, s as nt, u as rt } from "./apiBuild-
|
|
8
|
-
import { t as it } from "./start-
|
|
4
|
+
import { C as be, Q as xe, at as Se, c as Ce, f as we, i as Te, it as Ee, l as De, o as Oe, ot as ke, rt as Ae, st as je, yt as Me } from "./dev-Dbm6SWtn.js";
|
|
5
|
+
import { i as Ne, x as Pe } from "./frameworkTableAssembly-BwHU9Euq.js";
|
|
6
|
+
import { A as Fe, C as Ie, E as Le, O as Re, S as ze, T as Be, b as Ve, c as He, d as Ue, f as We, i as Ge, l as Ke, n as qe, o as Je, r as Ye, s as Xe, w as Ze } from "./fileConventions-3bffWssN.js";
|
|
7
|
+
import { i as Qe, n as $e, o as et, r as tt, s as nt, u as rt } from "./apiBuild-BtrTyKnF.js";
|
|
8
|
+
import { t as it } from "./start-BGXIf6zT.js";
|
|
9
9
|
import { a as at, i as ot, n as st, r as ct, t as lt } from "./cliArgs-qdZSElM3.js";
|
|
10
|
-
import { n as ut, r as dt } from "./serveCommand-
|
|
11
|
-
import { c as ft, r as pt, s as mt } from "./dbCommand-
|
|
10
|
+
import { n as ut, r as dt } from "./serveCommand-XBXuwJty.js";
|
|
11
|
+
import { c as ft, r as pt, s as mt } from "./dbCommand-uuNCrFAb.js";
|
|
12
12
|
import { basename as S, dirname as C, isAbsolute as ht, join as w, relative as T, resolve as E, sep as gt } from "node:path";
|
|
13
13
|
import { fileURLToPath as _t, pathToFileURL as vt } from "node:url";
|
|
14
14
|
import { FileSystem as yt } from "@effect/platform";
|
|
@@ -600,7 +600,7 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
600
600
|
if (hr.has(a.name)) continue;
|
|
601
601
|
let i = w(e, a.name);
|
|
602
602
|
if (a.isDirectory()) await r(i);
|
|
603
|
-
else if (a.isFile() &&
|
|
603
|
+
else if (a.isFile() && Ue.test(a.name)) {
|
|
604
604
|
let e = T(t, i), r = await Wt(i, "utf8");
|
|
605
605
|
n.push({
|
|
606
606
|
file: e,
|
|
@@ -992,10 +992,10 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
992
992
|
}, Mr = async (e) => {
|
|
993
993
|
let t = await le(e);
|
|
994
994
|
if (!t) {
|
|
995
|
-
let { loadApiConfig: t } = await import("./dev-
|
|
995
|
+
let { loadApiConfig: t } = await import("./dev-BnWq4jeA.js"), n = await t(e);
|
|
996
996
|
if (n) {
|
|
997
997
|
U.info("building api app", { app: n.name ?? "(unnamed)" });
|
|
998
|
-
let { runApiBuild: t, runServeBundleBuild: r } = await import("./apiBuild-
|
|
998
|
+
let { runApiBuild: t, runServeBundleBuild: r } = await import("./apiBuild-DDJ0It4j.js");
|
|
999
999
|
await t(e);
|
|
1000
1000
|
try {
|
|
1001
1001
|
await r(e);
|
|
@@ -1175,7 +1175,7 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
1175
1175
|
}).pipe(D.orDie);
|
|
1176
1176
|
return t.ran ? t.exitCode : (yield* D.logError("no web app found at this path", { hint: "looked for app.config.ts with `type: 'web'`" }), 1);
|
|
1177
1177
|
}), Pr = async (e) => {
|
|
1178
|
-
let t = e.find((e) => !e.startsWith("-")) ?? process.cwd(), n = await u(Nr(t), { scope: "voltro:build" }), r =
|
|
1178
|
+
let t = e.find((e) => !e.startsWith("-")) ?? process.cwd(), n = await u(Nr(t), { scope: "voltro:build" }), r = Me(t);
|
|
1179
1179
|
return r.warning !== void 0 && U.warn(r.warning), n;
|
|
1180
1180
|
}, Fr = (e) => e.source === void 0 ? [] : typeof e.source == "string" ? [e.source] : e.source, Ir = (e) => ({
|
|
1181
1181
|
tables: new Set(e.tables),
|
|
@@ -1421,9 +1421,9 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
1421
1421
|
}
|
|
1422
1422
|
})).status === "accepted" ? 0 : 1;
|
|
1423
1423
|
}, $r = async (e) => {
|
|
1424
|
-
let t = E(e.find((e) => !e.startsWith("-")) ?? process.cwd()), { config: n, present: r, error: i } = await
|
|
1424
|
+
let t = E(e.find((e) => !e.startsWith("-")) ?? process.cwd()), { config: n, present: r, error: i } = await De(t);
|
|
1425
1425
|
if (r && n === null) return console.error("voltro codegen: app.config.ts exists but could not be loaded — refusing to write."), console.error(" The generated file would omit every plugin's error union and client routes, and would typecheck, so the omission would only surface as a missing error tag at runtime."), i !== void 0 && console.error(` cause: ${i instanceof Error ? i.message : String(i)}`), 1;
|
|
1426
|
-
let a = n?.plugins ?? [], { pluginContributions: o, pluginErrorImports: s, pluginRpcImports: c } = await
|
|
1426
|
+
let a = n?.plugins ?? [], { pluginContributions: o, pluginErrorImports: s, pluginRpcImports: c } = await be(a, n?.name ?? S(t), t), l = await Ae({
|
|
1427
1427
|
root: t,
|
|
1428
1428
|
...o.length > 0 ? { pluginContributions: o } : {},
|
|
1429
1429
|
...s.length > 0 ? { pluginErrorImports: s } : {},
|
|
@@ -1566,45 +1566,45 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
1566
1566
|
}, ci = (e, t) => t.some((t) => e === t.dir || e.startsWith(`${t.dir}${gt}`)), li = (e, t) => t.map((t) => `${T(e, t.dir) || "."} (${t.source})`), ui = [
|
|
1567
1567
|
{
|
|
1568
1568
|
id: "component.ui",
|
|
1569
|
-
re:
|
|
1569
|
+
re: Ye,
|
|
1570
1570
|
needsTest: !0
|
|
1571
1571
|
},
|
|
1572
1572
|
{
|
|
1573
1573
|
id: "component",
|
|
1574
|
-
re:
|
|
1574
|
+
re: qe,
|
|
1575
1575
|
needsTest: !0
|
|
1576
1576
|
},
|
|
1577
1577
|
{
|
|
1578
1578
|
id: "hook",
|
|
1579
|
-
re:
|
|
1579
|
+
re: Xe,
|
|
1580
1580
|
needsTest: !0
|
|
1581
1581
|
},
|
|
1582
1582
|
{
|
|
1583
1583
|
id: "tracking",
|
|
1584
|
-
re:
|
|
1584
|
+
re: Ie,
|
|
1585
1585
|
needsTest: !0
|
|
1586
1586
|
},
|
|
1587
1587
|
{
|
|
1588
1588
|
id: "store",
|
|
1589
|
-
re:
|
|
1589
|
+
re: Ve,
|
|
1590
1590
|
needsTest: !0
|
|
1591
1591
|
},
|
|
1592
1592
|
{
|
|
1593
1593
|
id: "internal",
|
|
1594
|
-
re:
|
|
1594
|
+
re: He,
|
|
1595
1595
|
needsTest: !0
|
|
1596
1596
|
},
|
|
1597
1597
|
{
|
|
1598
1598
|
id: "fixture",
|
|
1599
|
-
re:
|
|
1599
|
+
re: Je,
|
|
1600
1600
|
needsTest: !1
|
|
1601
1601
|
},
|
|
1602
1602
|
{
|
|
1603
1603
|
id: "types",
|
|
1604
|
-
re:
|
|
1604
|
+
re: Be,
|
|
1605
1605
|
needsTest: !1
|
|
1606
1606
|
}
|
|
1607
|
-
], di = (e) => ui.find((t) => t.re.test(e))?.id ?? null, fi = (e) =>
|
|
1607
|
+
], di = (e) => ui.find((t) => t.re.test(e))?.id ?? null, fi = (e) => ze.test(e), pi = /* @__PURE__ */ new Set([
|
|
1608
1608
|
"useMutation",
|
|
1609
1609
|
"useAction",
|
|
1610
1610
|
"useUpload",
|
|
@@ -1893,7 +1893,7 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
1893
1893
|
});
|
|
1894
1894
|
let n = f(e), i = n.filter((e) => {
|
|
1895
1895
|
let t = di(e);
|
|
1896
|
-
return t === "component" || t === "component.ui" ||
|
|
1896
|
+
return t === "component" || t === "component.ui" || Ue.test(e) || We.has(e.slice(e.lastIndexOf(gt) + 1));
|
|
1897
1897
|
});
|
|
1898
1898
|
n.length === 0 ? a.push({
|
|
1899
1899
|
rule: "ui/orphaned",
|
|
@@ -2969,7 +2969,7 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
2969
2969
|
let t = to.get(e);
|
|
2970
2970
|
if (t !== void 0) return t;
|
|
2971
2971
|
let n = (async () => {
|
|
2972
|
-
let { walk: t, loadDiscovered: n } = await import("./dev-
|
|
2972
|
+
let { walk: t, loadDiscovered: n } = await import("./dev-BnWq4jeA.js"), r = await t(e);
|
|
2973
2973
|
return {
|
|
2974
2974
|
files: r,
|
|
2975
2975
|
discovered: await n(r)
|
|
@@ -3046,7 +3046,7 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
3046
3046
|
}) => /* @__PURE__ */ new Set([...Qi, ...$i(Ma(e).map(t))]), uo = async (e) => {
|
|
3047
3047
|
let { discovered: t } = await no(e), n = [];
|
|
3048
3048
|
try {
|
|
3049
|
-
let { loadApiConfig: t } = await import("./dev-
|
|
3049
|
+
let { loadApiConfig: t } = await import("./dev-BnWq4jeA.js");
|
|
3050
3050
|
n = ((await t(e))?.plugins ?? []).map((e) => {
|
|
3051
3051
|
let t = (e.extendSchema?.tables ?? []).map((e) => {
|
|
3052
3052
|
let t = e;
|
|
@@ -3248,7 +3248,7 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
3248
3248
|
} catch {
|
|
3249
3249
|
continue;
|
|
3250
3250
|
}
|
|
3251
|
-
a.isDirectory() ? yo(r, t, n + 1) : a.isFile() &&
|
|
3251
|
+
a.isDirectory() ? yo(r, t, n + 1) : a.isFile() && Ee.test(i) && t.push(r);
|
|
3252
3252
|
}
|
|
3253
3253
|
return t;
|
|
3254
3254
|
}, bo = /* @__PURE__ */ new Set(["actors", "tenants"]), xo = async (e) => {
|
|
@@ -3282,12 +3282,12 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
3282
3282
|
let t = e.severity === "error" ? "✗ error" : "⚠ warn", n = e.file ? ` (${e.file})` : "";
|
|
3283
3283
|
return `${t} ${e.rule} ${e.node}${n}\n ${e.breaks.join("; ")}\n fix: ${e.fix}`;
|
|
3284
3284
|
}).join("\n"), To = async (e) => {
|
|
3285
|
-
let { walk: t, loadDiscovered: n, loadApiConfig: r } = await import("./dev-
|
|
3285
|
+
let { walk: t, loadDiscovered: n, loadApiConfig: r } = await import("./dev-BnWq4jeA.js"), { buildRpcEntry: i } = await import("./manifestBuild-ifczArzr.js"), { buildCapabilityManifest: a } = await import("./inspect-gt8bq-Tz.js"), { relative: o } = await import("node:path"), s = await n(await t(e)), c = (t, n, r) => i(t, n, o(e, r)), l = [
|
|
3286
3286
|
...s.queries.map((e) => c(e.descriptor, "query", e.file)),
|
|
3287
3287
|
...s.mutations.map((e) => c(e.descriptor, "mutation", e.file)),
|
|
3288
3288
|
...s.actions.map((e) => c(e.descriptor, "action", e.file)),
|
|
3289
3289
|
...s.streams.map((e) => c(e.descriptor, "stream", e.file))
|
|
3290
|
-
], { assembleFrameworkTables: u } = await import("./frameworkTableAssembly-
|
|
3290
|
+
], { assembleFrameworkTables: u } = await import("./frameworkTableAssembly-lrjZtk0G.js"), d = await u({ root: e }).catch(() => []), f = new Set(s.tables.map((e) => e.tableName)), p = [...[...f].map((e) => ({ name: e })), ...d.map((e) => e.tableName).filter((e) => !f.has(e)).map((e) => ({
|
|
3291
3291
|
name: e,
|
|
3292
3292
|
framework: !0
|
|
3293
3293
|
}))], m = await r(e).then((e) => e?.plugins ?? []).catch(() => []);
|
|
@@ -3346,7 +3346,7 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
3346
3346
|
breaks: [e.kind === "suffixed-outside-pages" ? "a page.tsx outside src/pages/ never routes" : "no test beside it"],
|
|
3347
3347
|
fix: e.kind === "suffixed-outside-pages" ? "move it under src/pages/ into the directory whose route it serves, or rename it — page.tsx is reserved" : "write the test with the file — the name is derivable",
|
|
3348
3348
|
severity: e.kind === "suffixed-outside-pages" ? "error" : "warn"
|
|
3349
|
-
}))], m = (await
|
|
3349
|
+
}))], m = (await Se(o, yo(o))).map((e) => ({
|
|
3350
3350
|
rule: "client/not-browser-safe",
|
|
3351
3351
|
node: e.file,
|
|
3352
3352
|
file: e.file,
|
|
@@ -3382,7 +3382,7 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
3382
3382
|
from: n,
|
|
3383
3383
|
mode: r ? "start" : "dev",
|
|
3384
3384
|
apps: process.env.VOLTRO_DASHBOARD_APPS ? "configured" : "none (set VOLTRO_DASHBOARD_APPS)"
|
|
3385
|
-
}), r ? it([n]) :
|
|
3385
|
+
}), r ? it([n]) : we([n]);
|
|
3386
3386
|
}, Ao = (e, t) => t ? "type" : e.startsWith("define") ? "primitive" : /^use[A-Z]/.test(e) ? "hook" : /^[A-Z]/.test(e) ? "component" : "value", jo = (e) => {
|
|
3387
3387
|
let t = /* @__PURE__ */ new Map(), n = (e, n) => {
|
|
3388
3388
|
(!t.has(e) || !n) && t.set(e, n);
|
|
@@ -3506,9 +3506,9 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
3506
3506
|
let t = A({ scope: "dormancy" }), n = {
|
|
3507
3507
|
info: (e, n) => t.info(e, n ?? {}),
|
|
3508
3508
|
warn: (e, n) => t.warn(e, n ?? {})
|
|
3509
|
-
}, r = E(e.find((e) => !e.startsWith("-")) ?? process.cwd()), i = await
|
|
3509
|
+
}, r = E(e.find((e) => !e.startsWith("-")) ?? process.cwd()), i = await Ce(r), a = (process.env.DB_DIALECT ?? i?.store ?? "memory").toLowerCase();
|
|
3510
3510
|
if (a === "memory") return t.error("voltro dormancy needs a SQL store (postgres/mysql/mariadb/mssql) — the orchestrator and the app share the `_voltro_wakeups` table, which an in-process `memory` store cannot do. Set DB_DIALECT or the app.config `store` field."), 2;
|
|
3511
|
-
let o = Number(process.env.PORT ?? Lo(e, "--port") ?? 4e3), s = Number(Lo(e, "--app-port") ?? o + 1), c = Number(Lo(e, "--idle-grace-ms") ?? 6e4), l = Number(Lo(e, "--tick-ms") ?? 1e3), u = await
|
|
3511
|
+
let o = Number(process.env.PORT ?? Lo(e, "--port") ?? 4e3), s = Number(Lo(e, "--app-port") ?? o + 1), c = Number(Lo(e, "--idle-grace-ms") ?? 6e4), l = Number(Lo(e, "--tick-ms") ?? 1e3), u = await Te(i, void 0), d = Et({
|
|
3512
3512
|
command: process.execPath,
|
|
3513
3513
|
args: [
|
|
3514
3514
|
process.argv[1],
|
|
@@ -3654,7 +3654,7 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
3654
3654
|
]
|
|
3655
3655
|
});
|
|
3656
3656
|
c.push(i), await Bo(o, "web"), W.info(`running ${s.length} test file(s)`, { count: s.length });
|
|
3657
|
-
let l = 0, u =
|
|
3657
|
+
let l = 0, u = ke(), d = je(u);
|
|
3658
3658
|
d !== void 0 && W.warn(d);
|
|
3659
3659
|
for (let e of s) {
|
|
3660
3660
|
let t = await new Promise((t) => {
|
|
@@ -3969,7 +3969,7 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
3969
3969
|
await i.dispose();
|
|
3970
3970
|
}
|
|
3971
3971
|
}, G = A({ scope: "voltro:env" }), ls = "# Environment for this app", us = async (e) => {
|
|
3972
|
-
let t = await
|
|
3972
|
+
let t = await Ce(e).catch(() => null);
|
|
3973
3973
|
if (!t) return null;
|
|
3974
3974
|
let n = Vt(t.env) ? t.env : void 0, r = t.type === "api" ? t.plugins ?? [] : void 0;
|
|
3975
3975
|
return {
|
|
@@ -4001,7 +4001,7 @@ never mint — inspect stays closed until an operator opens it.`);
|
|
|
4001
4001
|
}
|
|
4002
4002
|
return await N.writeFile(i, r, "utf8"), G.info("wrote .env.example", { app: n.name }), 0;
|
|
4003
4003
|
}, hs = async (e) => {
|
|
4004
|
-
let t = await
|
|
4004
|
+
let t = await Ce(e).catch(() => null);
|
|
4005
4005
|
if (!t) return G.error("no app.config.ts found in the current directory"), 1;
|
|
4006
4006
|
let n = Vt(t.env) ? t.env : void 0;
|
|
4007
4007
|
return n ? (t.type === "web" ? (await ue(e, n), G.info("wrote src/voltro-env.d.ts (publicEnv augmentation)", { app: t.name ?? "app" })) : (await h(e, n), G.info("wrote env.generated.d.ts (serverEnv augmentation)", { app: t.name ?? "app" })), 0) : (G.warn("no `defineEnv` declared in app.config.ts — nothing to generate", { hint: "add `env: defineEnv({ ... })` to app.config.ts (see @voltro/env)" }), 0);
|
|
@@ -4117,7 +4117,7 @@ DB_DIALECT=mssql
|
|
|
4117
4117
|
let r = w(e, n);
|
|
4118
4118
|
(n === ".env.example" || j(r)) && await Ms(r) && t.push(`DB_DIALECT=mssql → ${n}`);
|
|
4119
4119
|
}
|
|
4120
|
-
for (let n of await
|
|
4120
|
+
for (let n of await xe(e)) t.push(n);
|
|
4121
4121
|
return t;
|
|
4122
4122
|
}, Fs = async (e) => {
|
|
4123
4123
|
let t = await Ps(e);
|
|
@@ -4190,7 +4190,7 @@ DB_DIALECT=mssql
|
|
|
4190
4190
|
}, Hs = async (e) => {
|
|
4191
4191
|
let t = Vs(e);
|
|
4192
4192
|
if ("error" in t) return console.error(t.error), 1;
|
|
4193
|
-
let n = await
|
|
4193
|
+
let n = await Te(await Ce(process.cwd()), void 0), r = {
|
|
4194
4194
|
all: (e) => n.query({ table: e }).then((e) => e.map((e) => ({
|
|
4195
4195
|
...e,
|
|
4196
4196
|
id: String(e.id)
|
|
@@ -4645,9 +4645,11 @@ DB_DIALECT=mssql
|
|
|
4645
4645
|
"retry",
|
|
4646
4646
|
"cancel",
|
|
4647
4647
|
"suspend",
|
|
4648
|
-
"resume"
|
|
4648
|
+
"resume",
|
|
4649
|
+
"discard",
|
|
4650
|
+
"redrive"
|
|
4649
4651
|
], hc = () => {
|
|
4650
|
-
console.log("voltro workflows — inspect + operate workflow runs on every running api"), console.log(""), console.log("Usage:"), console.log(" voltro workflows list [--status S] [--tag T] [--tail N] [--process NAME] [--format pretty|json]"), console.log(" voltro workflows start <workflowName> [--payload <json>] [--process NAME] [--format pretty|json]"), console.log(" voltro workflows show <runId> [--process NAME] [--format pretty|json]"), console.log(" voltro workflows retry|cancel|suspend|resume <runId> [--process NAME] [--format pretty|json]"), console.log(" voltro workflows signal <runId> --name <signalName> [--payload <json>] [--process NAME]"), console.log(" voltro workflows update <runId> --name <updateName> [--payload <json>] [--timeout-ms N] [--process NAME]"), console.log(" voltro workflows children <parentExecutionId> [--process NAME] [--format pretty|json]"), console.log(""), console.log("Examples:"), console.log(" voltro workflows list --status running --tail 50"), console.log(" voltro workflows start notes.summarise --payload '{\"noteId\":\"n_1\"}'"), console.log(" voltro workflows show wf_01H..."), console.log(" voltro workflows signal wf_01H... --name approve --payload '{\"by\":\"alice\"}'"), console.log(" voltro workflows update wf_01H... --name approve --payload '{\"decision\":true}'");
|
|
4652
|
+
console.log("voltro workflows — inspect + operate workflow runs on every running api"), console.log(""), console.log("Usage:"), console.log(" voltro workflows list [--status S | --dead-letter] [--tag T] [--tail N] [--process NAME] [--format pretty|json]"), console.log(" voltro workflows start <workflowName> [--payload <json>] [--process NAME] [--format pretty|json]"), console.log(" voltro workflows show <runId> [--process NAME] [--format pretty|json]"), console.log(" voltro workflows retry|cancel|suspend|resume|discard|redrive <runId> [--process NAME] [--format pretty|json]"), console.log(" voltro workflows signal <runId> --name <signalName> [--payload <json>] [--process NAME]"), console.log(" voltro workflows update <runId> --name <updateName> [--payload <json>] [--timeout-ms N] [--process NAME]"), console.log(" voltro workflows children <parentExecutionId> [--process NAME] [--format pretty|json]"), console.log(""), console.log("Examples:"), console.log(" voltro workflows list --status running --tail 50"), console.log(" voltro workflows list --dead-letter # failed runs not yet discarded"), console.log(" voltro workflows discard wf_01H... # acknowledge a failed run"), console.log(" voltro workflows redrive wf_01H... # re-drive a failed run from where it died"), console.log(" voltro workflows start notes.summarise --payload '{\"noteId\":\"n_1\"}'"), console.log(" voltro workflows show wf_01H..."), console.log(" voltro workflows signal wf_01H... --name approve --payload '{\"by\":\"alice\"}'"), console.log(" voltro workflows update wf_01H... --name approve --payload '{\"decision\":true}'");
|
|
4651
4653
|
}, gc, _c = async (e) => {
|
|
4652
4654
|
let t = await sr(e, gc);
|
|
4653
4655
|
return t.length === 0 ? (console.error(e === void 0 ? "voltro workflows: no live api processes found (start one with `voltro dev`)" : `voltro workflows: no live api named '${e}'`), 1) : t;
|
|
@@ -4696,7 +4698,7 @@ DB_DIALECT=mssql
|
|
|
4696
4698
|
for (let e of s) e.kind === "err" && console.error(k.dim(` # ${e.name}: ${e.error}`));
|
|
4697
4699
|
return 1;
|
|
4698
4700
|
}, bc = async (e, t, n) => {
|
|
4699
|
-
let r, i, a = 20;
|
|
4701
|
+
let r, i, a = !1, o = 20;
|
|
4700
4702
|
for (let t = 0; t < e.length; t++) {
|
|
4701
4703
|
let n = e[t];
|
|
4702
4704
|
if (n === "--status") {
|
|
@@ -4707,41 +4709,45 @@ DB_DIALECT=mssql
|
|
|
4707
4709
|
i = e[++t];
|
|
4708
4710
|
continue;
|
|
4709
4711
|
}
|
|
4712
|
+
if (n === "--dead-letter" || n === "--failed") {
|
|
4713
|
+
a = !0;
|
|
4714
|
+
continue;
|
|
4715
|
+
}
|
|
4710
4716
|
if (n === "--tail") {
|
|
4711
4717
|
let n = e[++t], r = n === void 0 ? NaN : Number(n);
|
|
4712
4718
|
if (!Number.isFinite(r) || r <= 0) return console.error(`voltro workflows list: --tail expects a positive number, got '${n ?? ""}'`), 2;
|
|
4713
|
-
|
|
4719
|
+
o = Math.floor(r);
|
|
4714
4720
|
continue;
|
|
4715
4721
|
}
|
|
4716
4722
|
return console.error(`voltro workflows list: unknown flag '${n}'`), 2;
|
|
4717
4723
|
}
|
|
4718
|
-
let
|
|
4719
|
-
if (typeof
|
|
4720
|
-
let
|
|
4721
|
-
r !== void 0 &&
|
|
4722
|
-
let
|
|
4723
|
-
for (let e of
|
|
4724
|
+
let s = await _c(t);
|
|
4725
|
+
if (typeof s == "number") return s;
|
|
4726
|
+
let c = new URLSearchParams();
|
|
4727
|
+
a ? c.set("deadLettered", "1") : r !== void 0 && c.set("status", r), i !== void 0 && c.set("tag", i), c.set("limit", String(o));
|
|
4728
|
+
let l = `/_voltro/inspect/workflows/runs?${c.toString()}`, u = await Promise.all(s.map((e) => H(e, l))), d = [], f = [];
|
|
4729
|
+
for (let e of u) if (e.kind === "ok") {
|
|
4724
4730
|
let t = e.data?.runs;
|
|
4725
|
-
Array.isArray(t) &&
|
|
4731
|
+
Array.isArray(t) && d.push(...t.map((t) => ({
|
|
4726
4732
|
...t,
|
|
4727
4733
|
process: e.name
|
|
4728
4734
|
})));
|
|
4729
|
-
} else
|
|
4735
|
+
} else f.push({
|
|
4730
4736
|
name: e.name,
|
|
4731
4737
|
error: e.error
|
|
4732
4738
|
});
|
|
4733
|
-
let
|
|
4734
|
-
if (n === "json") return vc(
|
|
4735
|
-
runs:
|
|
4736
|
-
fetchErrors:
|
|
4737
|
-
} : { runs:
|
|
4738
|
-
for (let e of
|
|
4739
|
-
let t = String(e.runId ?? e.id ?? "?"), n = String(e.workflowName ?? e.workflow ?? e.tag ?? "?"), r = String(e.status ?? "?"), i = typeof e.source == "string" && e.source.length > 0 ? ` ${k.dim(String(e.source))}` : "", a = r === "failed" || r === "cancelled" ? k.red(r) : r === "completed" ? k.green(r) : r === "running" ? k.cyan(r) : r
|
|
4740
|
-
console.log(`${t.padEnd(28).slice(0, 28)} ${a.padEnd(12)} ${n}${i} ${k.dim(`@${e.process}`)}`);
|
|
4741
|
-
}
|
|
4742
|
-
|
|
4743
|
-
for (let e of
|
|
4744
|
-
return +!!
|
|
4739
|
+
let p = d.slice(0, o);
|
|
4740
|
+
if (n === "json") return vc(f.length > 0 ? {
|
|
4741
|
+
runs: p,
|
|
4742
|
+
fetchErrors: f
|
|
4743
|
+
} : { runs: p }, +!!u.every((e) => e.kind === "err"));
|
|
4744
|
+
for (let e of p) {
|
|
4745
|
+
let t = String(e.runId ?? e.id ?? "?"), n = String(e.workflowName ?? e.workflow ?? e.tag ?? "?"), r = String(e.status ?? "?"), i = typeof e.source == "string" && e.source.length > 0 ? ` ${k.dim(String(e.source))}` : "", a = r === "failed" || r === "cancelled" ? k.red(r) : r === "completed" ? k.green(r) : r === "running" ? k.cyan(r) : r, o = e.discardedAt == null ? "" : ` ${k.dim("discarded")}`;
|
|
4746
|
+
console.log(`${t.padEnd(28).slice(0, 28)} ${a.padEnd(12)} ${n}${i}${o} ${k.dim(`@${e.process}`)}`);
|
|
4747
|
+
}
|
|
4748
|
+
p.length === 0 && console.error("voltro workflows: no runs matched.");
|
|
4749
|
+
for (let e of f) console.error(k.dim(`# fetch failed: ${e.name}: ${e.error}`));
|
|
4750
|
+
return +!!u.every((e) => e.kind === "err");
|
|
4745
4751
|
}, xc = async (e, t, n) => {
|
|
4746
4752
|
let r = await _c(t);
|
|
4747
4753
|
if (typeof r == "number") return r;
|
|
@@ -4889,7 +4895,13 @@ DB_DIALECT=mssql
|
|
|
4889
4895
|
process: i.name,
|
|
4890
4896
|
result: i.data
|
|
4891
4897
|
}, 0);
|
|
4892
|
-
if (i !== void 0)
|
|
4898
|
+
if (i !== void 0) {
|
|
4899
|
+
if (e === "redrive" && i.data !== null && typeof i.data == "object") {
|
|
4900
|
+
let e = i.data;
|
|
4901
|
+
return e.redriven === !1 ? (console.error(`${k.yellow("skipped")} redrive ${t} @${i.name} — ${e.reason ?? "not re-drivable"}`), 1) : (console.log(`${k.green("ok")} redrive ${t} @${i.name} ` + k.dim(`(reset ${e.activitiesReset ?? 0} failed step(s); completed steps replay)`)), 0);
|
|
4902
|
+
}
|
|
4903
|
+
return console.log(`${k.green("ok")} ${e} ${t} @${i.name}`), 0;
|
|
4904
|
+
}
|
|
4893
4905
|
console.error(`voltro workflows: ${e} ${t} failed on every api`);
|
|
4894
4906
|
for (let e of n) e.kind === "err" && console.error(k.dim(` # ${e.name}: ${e.error}`));
|
|
4895
4907
|
return 1;
|
|
@@ -6237,7 +6249,7 @@ replicas = 1
|
|
|
6237
6249
|
for (let c of s) {
|
|
6238
6250
|
if (zu.has(c)) continue;
|
|
6239
6251
|
let s = w(e, c), l = yield* t.stat(s).pipe(D.orElseSucceed(() => null));
|
|
6240
|
-
l && (l.type === "Directory" ? yield* o(s) : l.type === "File" && (Bu.test(c) && n.push(s), (
|
|
6252
|
+
l && (l.type === "Directory" ? yield* o(s) : l.type === "File" && (Bu.test(c) && n.push(s), (Re.test(c) || Ze.test(c)) && (r = !0), Ge.test(c) && (i = !0), Le.test(c) && (a = !0)));
|
|
6241
6253
|
}
|
|
6242
6254
|
});
|
|
6243
6255
|
return yield* o(e), {
|
|
@@ -6261,11 +6273,11 @@ replicas = 1
|
|
|
6261
6273
|
root: e
|
|
6262
6274
|
}), 1;
|
|
6263
6275
|
yield* D.logInfo(`discovered ${t.length} schema file(s)`, { files: t.map((t) => T(e, t)) });
|
|
6264
|
-
let a = yield* Uu(t), o = (process.env.DB_DIALECT ?? "postgres").toLowerCase() === "mariadb" && (process.env.CDC ?? "1") !== "0", s =
|
|
6276
|
+
let a = yield* Uu(t), o = (process.env.DB_DIALECT ?? "postgres").toLowerCase() === "mariadb" && (process.env.CDC ?? "1") !== "0", s = Pe({
|
|
6265
6277
|
workflows: n,
|
|
6266
6278
|
schedules: r,
|
|
6267
6279
|
webhooks: i,
|
|
6268
|
-
traces:
|
|
6280
|
+
traces: Ne(),
|
|
6269
6281
|
cdc: o,
|
|
6270
6282
|
undo: Ot()
|
|
6271
6283
|
}), c = [...a, ...s];
|
|
@@ -6303,7 +6315,7 @@ replicas = 1
|
|
|
6303
6315
|
return he(e);
|
|
6304
6316
|
}, qu = async (e) => {
|
|
6305
6317
|
if (e.includes("--create-only")) return u(Wu(E(e.find((e) => !e.startsWith("-")) ?? process.cwd())), { scope: "voltro:migrate" });
|
|
6306
|
-
let { runDbCommand: t } = await import("./dbCommand-
|
|
6318
|
+
let { runDbCommand: t } = await import("./dbCommand-DrzXimKf.js");
|
|
6307
6319
|
return t(["apply", ...e]);
|
|
6308
6320
|
}, Ju = "voltro-backup-stamp.json", Yu = (e) => ({
|
|
6309
6321
|
stampVersion: 1,
|
|
@@ -6416,13 +6428,13 @@ replicas = 1
|
|
|
6416
6428
|
}, cd = async (e, t) => {
|
|
6417
6429
|
let n = (await he(e)).makeSqlLayer(t);
|
|
6418
6430
|
return D.runPromise(Mt.SqlClient.pipe(D.flatMap(Qt), D.provide(n)));
|
|
6419
|
-
}, ld = (e) => cd(e,
|
|
6420
|
-
let e =
|
|
6431
|
+
}, ld = (e) => cd(e, Oe()), ud = () => {
|
|
6432
|
+
let e = Oe(), t = [];
|
|
6421
6433
|
return e.url && t.push(Qu(e.url)), (e.host || e.database) && t.push(`${(e.host ?? "localhost").toLowerCase()}:${e.port ?? "(default)"}/${e.database ?? ""}`), t;
|
|
6422
6434
|
}, dd = async () => {
|
|
6423
|
-
let e = await
|
|
6435
|
+
let e = await Ce(process.cwd());
|
|
6424
6436
|
if (!e) throw new ft("voltro data: no app.config.ts found in the current directory.");
|
|
6425
|
-
let t = await
|
|
6437
|
+
let t = await Te(e, void 0), n = sd();
|
|
6426
6438
|
return {
|
|
6427
6439
|
store: t,
|
|
6428
6440
|
snapshot: await ld(n),
|
|
@@ -6686,7 +6698,7 @@ replicas = 1
|
|
|
6686
6698
|
assets: d.assets.count
|
|
6687
6699
|
}), 0;
|
|
6688
6700
|
}, Td = () => {
|
|
6689
|
-
let e =
|
|
6701
|
+
let e = Oe();
|
|
6690
6702
|
return {
|
|
6691
6703
|
...e.url ? { url: e.url } : {},
|
|
6692
6704
|
...e.host ? { host: e.host } : {},
|
|
@@ -8759,7 +8771,7 @@ replicas = 1
|
|
|
8759
8771
|
}, $p = /\.page\.tsx$/, em = (e) => {
|
|
8760
8772
|
let t = e.includes("\\src\\pages\\") ? "\\src\\pages\\" : "/src/pages/", n = e.indexOf(t);
|
|
8761
8773
|
return n === -1 ? null : e.slice(0, n);
|
|
8762
|
-
}, tm = (e) => e.endsWith(".tsx") && !
|
|
8774
|
+
}, tm = (e) => e.endsWith(".tsx") && !We.has(e) && !n(e) && !/\.island\.tsx$/.test(e) && !$p.test(e), nm = Z({
|
|
8763
8775
|
version: "0.14.0",
|
|
8764
8776
|
id: "0.14.0/03_pages-suffix",
|
|
8765
8777
|
title: "Pages are declared with a .page.tsx suffix",
|
|
@@ -8809,18 +8821,18 @@ replicas = 1
|
|
|
8809
8821
|
}
|
|
8810
8822
|
}), rm = [
|
|
8811
8823
|
/\.page\.tsx$/,
|
|
8812
|
-
|
|
8824
|
+
Ke,
|
|
8825
|
+
Ye,
|
|
8826
|
+
qe,
|
|
8827
|
+
Xe,
|
|
8828
|
+
Be,
|
|
8829
|
+
He,
|
|
8830
|
+
Je,
|
|
8813
8831
|
Ie,
|
|
8814
|
-
|
|
8815
|
-
Le,
|
|
8816
|
-
De,
|
|
8817
|
-
ke,
|
|
8818
|
-
Fe,
|
|
8819
|
-
Ce,
|
|
8820
|
-
Ee
|
|
8832
|
+
ze
|
|
8821
8833
|
], im = (e) => {
|
|
8822
8834
|
let t = S(e);
|
|
8823
|
-
return !/\.tsx?$/.test(t) ||
|
|
8835
|
+
return !/\.tsx?$/.test(t) || We.has(t) || Fe(t) || t === "index.ts" || t === "index.tsx" || t === "app.config.ts" ? !1 : !rm.some((e) => e.test(t));
|
|
8824
8836
|
}, am = (e) => {
|
|
8825
8837
|
let t = [], n = [], r = [], i = [];
|
|
8826
8838
|
for (let [a, o] of e.getExportedDeclarations()) {
|
|
@@ -8950,7 +8962,7 @@ replicas = 1
|
|
|
8950
8962
|
].join("\n")
|
|
8951
8963
|
}), um = (e) => {
|
|
8952
8964
|
let t = e.replace(/\.component(\.ui)?(\.tsx?)$/, "$2");
|
|
8953
|
-
return t === e ? null :
|
|
8965
|
+
return t === e ? null : Fe(t) ? t : null;
|
|
8954
8966
|
}, dm = (e) => {
|
|
8955
8967
|
for (let [, t] of e.getExportedDeclarations()) if (t[0] !== void 0) return !1;
|
|
8956
8968
|
return e.getExportDeclarations().length === 0 && e.getExportAssignments().length === 0;
|
|
@@ -9726,6 +9738,95 @@ replicas = 1
|
|
|
9726
9738
|
for (let e of i) t(` ! ${e} — carried verbatim; CHECK IT: the value is now a PREFIX the framework`), t(" appends ':changes' / ':events:<name>' / ':members' / ':presence' to.");
|
|
9727
9739
|
}
|
|
9728
9740
|
}
|
|
9741
|
+
}),
|
|
9742
|
+
Z({
|
|
9743
|
+
version: "0.26.0",
|
|
9744
|
+
id: "0.26.0/01_event-webhook-retry-removed",
|
|
9745
|
+
title: "`defineEvent({ webhook: { retry } })` is gone — it never did anything",
|
|
9746
|
+
kind: "manual",
|
|
9747
|
+
appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => {
|
|
9748
|
+
let t = e.getFullText();
|
|
9749
|
+
return t.includes("defineEvent") && t.includes("webhook") && t.includes("retry");
|
|
9750
|
+
}),
|
|
9751
|
+
note: [
|
|
9752
|
+
"The `retry` field on an event's `webhook` spec has been REMOVED from the type.",
|
|
9753
|
+
"",
|
|
9754
|
+
"It was declared, documented as \"default retry policy for new subscriptions\",",
|
|
9755
|
+
"and read by nothing. Setting it produced no error, no warning and no effect —",
|
|
9756
|
+
"the value was dropped where the event descriptor is projected into an outgoing",
|
|
9757
|
+
"webhook descriptor, and there was a comment there explaining why. The comment",
|
|
9758
|
+
"was a reasonable argument (the plugin's RetryPolicy is a richer shape than the",
|
|
9759
|
+
"two numbers the protocol carried, and inventing the missing fields would put a",
|
|
9760
|
+
"policy in place nobody wrote) but it did not change what a user experienced:",
|
|
9761
|
+
"a typed option that silently does nothing.",
|
|
9762
|
+
"",
|
|
9763
|
+
"This is the third instance of that shape in this feature — `broadcast({ channel })`",
|
|
9764
|
+
"and an event's `guards` were the first two — so the field is deleted rather than",
|
|
9765
|
+
"explained.",
|
|
9766
|
+
"",
|
|
9767
|
+
"WHAT TO DO: if you set it, delete it. Nothing changes at runtime, because",
|
|
9768
|
+
"nothing was reading it. To actually configure retry, set it on the SUBSCRIPTION",
|
|
9769
|
+
"(the webhook target), where the full RetryPolicy shape is available and typed:",
|
|
9770
|
+
"",
|
|
9771
|
+
" webhooks.subscribe({ event: \"order.paid\", url, retry: { maxAttempts: 5, ... } })",
|
|
9772
|
+
"",
|
|
9773
|
+
"If you were relying on the declared value to take effect, note that it never",
|
|
9774
|
+
"did — your deliveries have been using the target default all along."
|
|
9775
|
+
].join("\n")
|
|
9776
|
+
}),
|
|
9777
|
+
Z({
|
|
9778
|
+
version: "0.26.0",
|
|
9779
|
+
id: "0.26.0/02_step-retry-enforced",
|
|
9780
|
+
title: "workflow step `retry:` is now ENFORCED (was metadata) — drop any redundant manual retry",
|
|
9781
|
+
kind: "manual",
|
|
9782
|
+
appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => {
|
|
9783
|
+
let t = e.getFullText();
|
|
9784
|
+
return t.includes("retry:") ? t.includes("step(") || t.includes("stepModule.retry") || t.includes("Effect.retry") : !1;
|
|
9785
|
+
}),
|
|
9786
|
+
note: [
|
|
9787
|
+
"The `retry:` field on a workflow `step({...})` is now ENFORCED. The framework",
|
|
9788
|
+
"compiles it to an Effect `Schedule` (backoff, jitter, attempt cap, time budget,",
|
|
9789
|
+
"error classification, provider `Retry-After`) and retries `execute` accordingly.",
|
|
9790
|
+
"It used to be metadata only — recorded for the dashboard, applied by nothing.",
|
|
9791
|
+
"",
|
|
9792
|
+
"THE PART TO CHECK FIRST, even if you never wrote a manual retry: a step that",
|
|
9793
|
+
"declared `retry:` and nothing else ran ONCE. It now runs up to `maxAttempts`",
|
|
9794
|
+
"times. If `execute` is not idempotent — a charge, an email, an outbound POST —",
|
|
9795
|
+
"that is real duplicate work that starts on this upgrade, and nothing in your",
|
|
9796
|
+
"code changed to cause it. The 0.25.0 type said so plainly (\"Pure metadata —",
|
|
9797
|
+
"does NOT change retry behavior on its own\"), so trusting it was correct.",
|
|
9798
|
+
"",
|
|
9799
|
+
"Go through every step that declares `retry:` and decide, per step:",
|
|
9800
|
+
" - side effect is idempotent (or guarded by an idempotency key) → keep the",
|
|
9801
|
+
" policy; this is the behaviour you wanted when you wrote it;",
|
|
9802
|
+
" - side effect is NOT idempotent → make it so, or set `maxAttempts: 1`, or",
|
|
9803
|
+
" narrow with `retryableErrors: [...]` so only transient failures retry.",
|
|
9804
|
+
"",
|
|
9805
|
+
"If you followed the old docs and wrapped a step in your OWN retry as well as",
|
|
9806
|
+
"declaring `retry:`, that step now retries TWICE. Fix it — keep ONE:",
|
|
9807
|
+
"",
|
|
9808
|
+
" // before (retry: was metadata; the real retry was the wrapper)",
|
|
9809
|
+
" yield* stepModule.retry(",
|
|
9810
|
+
" step({ name: 'call-provider', retry: { maxAttempts: 5 }, execute }),",
|
|
9811
|
+
" Schedule.exponential('500 millis').pipe(Schedule.recurs(4)),",
|
|
9812
|
+
" )",
|
|
9813
|
+
"",
|
|
9814
|
+
" // after — the declarative policy IS the retry now",
|
|
9815
|
+
" yield* step({",
|
|
9816
|
+
" name: 'call-provider',",
|
|
9817
|
+
" retry: { maxAttempts: 5, strategy: 'exponential', baseDelay: '500 millis' },",
|
|
9818
|
+
" execute,",
|
|
9819
|
+
" })",
|
|
9820
|
+
"",
|
|
9821
|
+
"The declarative form is the one to keep in almost every case — it also drives the",
|
|
9822
|
+
"dashboard. Keep a hand-written `stepModule.retry(…, Schedule)` ONLY when your",
|
|
9823
|
+
"Schedule does something the policy can't express, and then DROP the `retry:` field",
|
|
9824
|
+
"from that step so it is not applied on top.",
|
|
9825
|
+
"",
|
|
9826
|
+
"New conditions worth adopting while you are here: `retryableErrors: ['ProviderDown']`",
|
|
9827
|
+
"(retry transient, fail permanent), `maxElapsed: '5 minutes'` (a total time budget,",
|
|
9828
|
+
"not just a count), `jitter` (on by default), and `respectRetryAfter` (honor a 429)."
|
|
9829
|
+
].join("\n")
|
|
9729
9830
|
})
|
|
9730
9831
|
], $m = /* @__PURE__ */ new Set([
|
|
9731
9832
|
"node_modules",
|
|
@@ -11459,7 +11560,7 @@ image, use \`voltro serverless serve\` from the project root.
|
|
|
11459
11560
|
name: "dev",
|
|
11460
11561
|
summary: "Start the local development server (auto-discovers routes / mutations).",
|
|
11461
11562
|
status: "wired",
|
|
11462
|
-
run:
|
|
11563
|
+
run: we
|
|
11463
11564
|
},
|
|
11464
11565
|
{
|
|
11465
11566
|
name: "dashboard",
|