@voltro/cli 0.59.0 → 0.60.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 +58 -0
- package/dist/bin.js +1 -1
- package/dist/{build-uRMZrT8z.js → build-BxAsLzyU.js} +14 -10
- package/dist/{codemodRunner-kNnh1I7_.js → codemodRunner-ClUqkhvR.js} +86 -37
- package/dist/{commands-cu34ENUT.js → commands-Ro4hYBHD.js} +7 -7
- package/dist/{dashboardCommand-gG1y4PFG.js → dashboardCommand-t8Qsebjr.js} +1 -1
- package/dist/{evolveCommand-8CuFBlbQ.js → evolveCommand-CThb0EZZ.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/{infoCommand-D02A4WI2.js → infoCommand-a0WkKcUY.js} +1 -1
- package/dist/{start-C75w6ftA.js → start-BhoDQ25C.js} +1 -1
- package/dist/{start-DNtIlBcn.js → start-CcdPRG8L.js} +418 -367
- package/dist/startEntry.js +1 -1
- package/dist/{updateCommand-Bw3mCUDT.js → updateCommand-D9avpQFT.js} +1 -1
- package/dist/updateCommand-QMOirvXC.js +2 -0
- package/package.json +25 -19
- package/templates/AGENTS.md +1 -1
- package/templates/agent-docs/_index.md +1 -1
- package/templates/agent-docs/plugins/sentry.md +93 -6
- package/templates/agent-docs/whats-new.md +29 -26
- package/templates/apps/api-ai/package.json +6 -6
- 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-sqlite/package.json +8 -8
- package/templates/apps/api-backend-storage/package.json +8 -8
- package/templates/apps/api-cms/package.json +9 -9
- package/templates/apps/api-collab/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-row-history/package.json +8 -8
- package/templates/apps/api-saas/package.json +11 -11
- package/templates/apps/api-saas-starter/package.json +10 -10
- package/templates/apps/api-search/package.json +8 -8
- package/templates/apps/api-status/package.json +8 -8
- package/templates/apps/api-webhooks/package.json +9 -9
- package/templates/apps/changelog/package.json +7 -7
- package/templates/apps/edge-functions/package.json +2 -2
- package/templates/apps/frontend-admin/package.json +7 -7
- package/templates/apps/frontend-app/package.json +8 -8
- package/templates/apps/frontend-auth/package.json +7 -7
- package/templates/apps/frontend-blank/package.json +6 -6
- package/templates/apps/frontend-cms/package.json +8 -8
- package/templates/apps/frontend-collab/package.json +9 -9
- package/templates/apps/frontend-contact/package.json +7 -7
- package/templates/apps/frontend-dashboard/package.json +6 -6
- package/templates/apps/frontend-docs/package.json +8 -8
- package/templates/apps/frontend-i18n/package.json +6 -6
- package/templates/apps/frontend-landing/package.json +7 -7
- package/templates/apps/frontend-portal/package.json +7 -7
- package/templates/apps/frontend-saas/package.json +7 -7
- package/templates/apps/frontend-spa/package.json +6 -6
- package/templates/apps/frontend-ssr/package.json +6 -6
- package/templates/apps/frontend-ssr-api/package.json +7 -7
- package/templates/apps/frontend-static-blog/package.json +8 -8
- package/templates/apps/frontend-status/package.json +7 -7
- package/templates/apps/mobile-app/package.json +4 -4
- package/dist/updateCommand-inInBIAh.js +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -39,6 +39,64 @@ _Changes staged for the next release accumulate here (rolled up from
|
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
+
## [0.60.0] — 2026-08-31
|
|
43
|
+
|
|
44
|
+
### ⚠ BREAKING
|
|
45
|
+
|
|
46
|
+
- **@voltro/plugin-sentry** — **A declared failure no longer reaches Sentry by default, and the source-map upload now injects debug ids.** Two separate defects, both found by the same deployment on its first day of real server-side events.
|
|
47
|
+
|
|
48
|
+
**1. The contract was being reported as an incident.** The rpc interceptor skipped only clean interrupts; everything else went to `captureException`. So a failure declared in a procedure's `error:` union — the thing the client gets typed and branches on — arrived as `level: error`, `handled: yes`. The first server-side issue a deployment ever received was a person clicking a team they are not a member of.
|
|
49
|
+
|
|
50
|
+
Effect separates a failure from a defect, this framework leans on that split deliberately (a store refusal was made typed so an app could branch on it; an unlookupable conflict key was deliberately left a defect, because it is a broken call rather than a condition in the data), and a descriptor carries it in `error:`. Reporting both as an incident discarded that one layer up.
|
|
51
|
+
|
|
52
|
+
`shouldCapture` now skips a cause that is failures-ONLY. A defect is reported as before, including a defect that travelled beside a failure — the rule is failures-only rather than "any failure present" precisely so one cannot hide the other. `captureFailures: true` restores the old behaviour; a predicate keeps the ones that are signal.
|
|
53
|
+
|
|
54
|
+
**The browser half moved with it**, or the option would have been half-wired: a rejected call is an rpc error on the client too, published to the client error bus and captured by the browser bridge. `initSentryBrowser` takes the same option and applies it to `rpc.*` events carrying a `_tag`. Route render failures and `reportClientError` calls are never filtered — nobody declared those.
|
|
55
|
+
|
|
56
|
+
**2. `sentry-cli sourcemaps upload` does NOT write debug ids.** `inject` is a separate subcommand; `upload` only uses ids that are already present, and falls back to matching on the artifact NAME when they are not. That fallback cannot work for a server bundle: the artifact is named from `--url-prefix` (`~/chunk- ABC.js`) while the frame carries the absolute path the node process loaded, and nothing rewrites either side.
|
|
57
|
+
|
|
58
|
+
Measured downstream: 4300 artifacts uploaded, release finalised, every frame still minified. Nothing was red — the exact shape this code's own header warns about, an upload that matched nothing looking like one that worked. The comment above the uploader asserted the injection happened, which made it a description standing where a check belonged.
|
|
59
|
+
|
|
60
|
+
`inject` now runs first, over the same directories, and `sourcemapDebugIds.test.ts` drives the real binary to assert an id lands in both the JS and the map. `--url-prefix` stays as the fallback for the browser bundle, whose frames really are URLs.
|
|
61
|
+
|
|
62
|
+
The boot line names the new setting (`sentry active … captureFailures=false`), because a default the framework picks for you is one nobody finds again.
|
|
63
|
+
|
|
64
|
+
**`voltro update` carries you across this** — codemod `0.60.0/01_declared_failures_are_not_incidents`. If you pin versions by hand and never run it, print the notes without changing anything: `voltro update --codemods-only --from <your current version> --dry-run` (this one ships in 0.60.0).
|
|
65
|
+
|
|
66
|
+
### Added
|
|
67
|
+
|
|
68
|
+
- **@voltro/cli, @voltro/plugin-sentry** — **The web server process now initialises Sentry and reports its own errors.**
|
|
69
|
+
|
|
70
|
+
A framework app runs two server processes. `voltro serve` is the api, where `sentryPlugin()` initialises the SDK through the plugin lifecycle. `voltro start` is the web server — SSR, loaders, ISR, the revalidation legs — and it has no plugin lifecycle, so it had none.
|
|
71
|
+
|
|
72
|
+
That was not a cosmetic difference in boot output. A web pod legitimately logs less than an api pod, because it has no store, no rpc, no scheduler, no workflows and no plugins. What it also had was **no error reporting**: an SSR shell throw is caught, logged and answered with a 500, so no browser ever renders it and the client-side ErrorBoundary bridge cannot see it either. Both ends of the integration worked and the middle was dark — while the docs' "React render error ✅ auto" row, true of the client path, read as covering all of them.
|
|
73
|
+
|
|
74
|
+
Set `SENTRY_DSN` on the web deployment and the boot says `sentry active` with the same message and the same field names as the api half, from the same function — `initSentryServer` in `@voltro/plugin-sentry/server`, which the api plugin now calls too. One init, because a copy of `skipOpenTelemetrySetup`, the traces default, the overrides-first spread and the degrade-on-missing-SDK path would have drifted the moment either half gained a case.
|
|
75
|
+
|
|
76
|
+
Three deliberate asymmetries, each because the two processes are not the same thing:
|
|
77
|
+
|
|
78
|
+
- **`traces: false` on the web side.** The api contributes a span processor to the framework's tracer; the web server has no tracer at all, so tracing on would put `traces: true` in a boot line while nothing produces a span. - **No DSN is SILENT here.** On the api side `sentryPlugin()` is a declaration and an inert one contradicts it. There is no declaration here. - **`@voltro/plugin-sentry` must be installed in the WEB app.** With a DSN set and the package missing, the boot names the command rather than failing — monitoring must never be what stops a deploy.
|
|
79
|
+
|
|
80
|
+
Measured against a real production `voltro start`, both branches. Note that production `voltro start` loads the app's precompiled start bundle, so a web deployment picks this up when that bundle is rebuilt — the framework version alone is not enough.
|
|
81
|
+
|
|
82
|
+
### Fixed
|
|
83
|
+
|
|
84
|
+
- **@voltro/workflow, @voltro/runtime, @voltro/database, @voltro/cli, @voltro/plugin-sentry** — **Six raw writes removed from production log streams — and the guard that was supposed to catch them rewritten, because it was green for two independent reasons.**
|
|
85
|
+
|
|
86
|
+
A pod tail showed `[voltro:workflow] shard-lock coordination: row-based (dialect=mariadb, mode=row)` sitting between JSON records. `@voltro/logger` is what makes a line JSON in a pod and pretty on a TTY; a `process.stderr.write` bypasses that decision at exactly the place nobody looks, because a dev terminal renders both the same.
|
|
87
|
+
|
|
88
|
+
Fixed at the source: the workflow cluster layer (2), `rpcServer`'s computed-cache warning, the subscription outbox's and the RYW store's `warn`/`onError` defaults — those two are not fallbacks, the callers pass nothing, so the default IS the production path — and the migration file discovery's skip notice, which lands in the migrate job's stream.
|
|
89
|
+
|
|
90
|
+
**The guard is the part worth reading.** `prodLogDiscipline.test.ts` existed for this exact class and reported clean, for two reasons that had to be fixed separately:
|
|
91
|
+
|
|
92
|
+
- Its file set was a hand-written list of five. A guard that opts files IN says nothing about any file added after it was written. - Its matcher was LINE-LOCAL, so `process.stderr.write(` on one line and the `` `[tag] `` on the next never matched — 4 of the 9 call sites in the repo are written that way, including one in a file that WAS on the list. The guard had been pointed straight at an offender and called it clean.
|
|
93
|
+
|
|
94
|
+
It is opt-OUT now: every server-side package's source is scanned, exceptions carry a reason, and a second test fails if an exception's call site disappears — an allowlist entry for code that is gone reads as a rule with a hole in it.
|
|
95
|
+
|
|
96
|
+
Verified against a real `voltro serve` under `NODE_ENV=production`: 35 records, zero framework lines that are not JSON.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
42
100
|
## [0.59.0] — 2026-08-30
|
|
43
101
|
|
|
44
102
|
### ⚠ BREAKING
|
package/dist/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { r as e } from "./commands-
|
|
2
|
+
import { r as e } from "./commands-Ro4hYBHD.js";
|
|
3
3
|
import { a as t } from "./nodeEnvironment-cGFAj1J8.js";
|
|
4
4
|
import { t as n } from "./loadEnv-D9nEOClM.js";
|
|
5
5
|
import { n as r } from "./cliError-BmdYnghb.js";
|
|
@@ -118,21 +118,25 @@ var X = W({ scope: "voltro:build" }), ie = async (e, t = {}) => {
|
|
|
118
118
|
n.set(e, [...n.get(e) ?? [], r.dir]);
|
|
119
119
|
}
|
|
120
120
|
return [...n];
|
|
121
|
-
}, ce = (e) => async (
|
|
122
|
-
let
|
|
123
|
-
authToken:
|
|
124
|
-
org:
|
|
125
|
-
project:
|
|
126
|
-
...
|
|
121
|
+
}, ce = (e, t = ue) => async (n, r, i) => {
|
|
122
|
+
let a = new (await (t(e)))(null, {
|
|
123
|
+
authToken: n.authToken,
|
|
124
|
+
org: n.org,
|
|
125
|
+
project: n.project,
|
|
126
|
+
...n.url === void 0 ? {} : { url: n.url },
|
|
127
127
|
silent: !1
|
|
128
128
|
});
|
|
129
|
-
await
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
await a.execute([
|
|
130
|
+
"sourcemaps",
|
|
131
|
+
"inject",
|
|
132
|
+
...i.map((e) => e.dir)
|
|
133
|
+
], !0), await a.releases.new(n.release);
|
|
134
|
+
for (let [e, t] of Q(i, n.urlPrefix)) await a.releases.uploadSourceMaps(n.release, {
|
|
135
|
+
include: t,
|
|
132
136
|
urlPrefix: e,
|
|
133
137
|
rewrite: !0
|
|
134
138
|
});
|
|
135
|
-
await
|
|
139
|
+
await a.releases.finalize(n.release);
|
|
136
140
|
}, le = (e) => {
|
|
137
141
|
let t = e, n = [
|
|
138
142
|
t?.SentryCli,
|
|
@@ -6550,7 +6550,55 @@ var C = (e, t, n) => {
|
|
|
6550
6550
|
}
|
|
6551
6551
|
n > 0 && (t?.(`sourcemaps: moved out of \`web:\` in ${n} config file(s)`), t?.(" → it now covers the SSR, start and serve bundles too, not only the browser bundle")), r > 0 && t?.(`sourcemaps: ${r} case(s) left for you — listed above`), n === 0 && r === 0 && t?.("sourcemaps: no `web.sourcemaps` found — nothing to move");
|
|
6552
6552
|
}
|
|
6553
|
-
}), pa = (e) => /\
|
|
6553
|
+
}), pa = (e) => /\bsentryPlugin\b|@voltro\/plugin-sentry/.test(e.getFullText()), ma = T({
|
|
6554
|
+
version: "0.60.0",
|
|
6555
|
+
id: "0.60.0/01_declared_failures_are_not_incidents",
|
|
6556
|
+
title: "Sentry no longer reports declared failures by default",
|
|
6557
|
+
kind: "manual",
|
|
6558
|
+
appliesTo: ({ project: e }) => e.getSourceFiles().some(pa),
|
|
6559
|
+
note: [
|
|
6560
|
+
"A DECLARED FAILURE IS NO LONGER A SENTRY ISSUE BY DEFAULT.",
|
|
6561
|
+
"",
|
|
6562
|
+
"WHAT CHANGED. The rpc interceptor skipped only clean interrupts; every",
|
|
6563
|
+
"other cause went to `captureException`, so a failure declared in a",
|
|
6564
|
+
"procedure's `error:` union arrived as `level: error`. It now skips a cause",
|
|
6565
|
+
"that is failures-ONLY. Defects are reported exactly as before, including a",
|
|
6566
|
+
"defect that travelled beside a failure.",
|
|
6567
|
+
"",
|
|
6568
|
+
"WHY. A declared failure is a contract: somebody wrote the outcome down, the",
|
|
6569
|
+
"client gets it typed and branches on it, and it describes a state of the",
|
|
6570
|
+
"world. `AccessDeniedError` on a team you are not in is the system working.",
|
|
6571
|
+
"A defect is the opposite — nobody foresaw it — and that is what Sentry is",
|
|
6572
|
+
"built for. Effect separates the two, this framework leans on that split",
|
|
6573
|
+
"deliberately, and a descriptor carries it in `error:`; reporting both as an",
|
|
6574
|
+
"incident discarded it one layer up. A deployment measured the result: its",
|
|
6575
|
+
"first server-side issue was a person clicking a team they are not in.",
|
|
6576
|
+
"",
|
|
6577
|
+
"THE BROWSER HALF MOVED WITH IT. A rejected call is an rpc error on the",
|
|
6578
|
+
"client too, so `initSentryBrowser` applies the same rule to `rpc.*` events",
|
|
6579
|
+
"that carry a `_tag`. Route render failures and `reportClientError` calls",
|
|
6580
|
+
"are never filtered — nobody declared those.",
|
|
6581
|
+
"",
|
|
6582
|
+
"WHAT TO DO — one of these, deliberately:",
|
|
6583
|
+
"",
|
|
6584
|
+
"1) NOTHING, if Sentry is where you look for the unforeseen. Your issue list",
|
|
6585
|
+
" gets quieter; the trace still shows the failure.",
|
|
6586
|
+
"",
|
|
6587
|
+
"2) KEEP THEM, if Sentry is where you see errors at all:",
|
|
6588
|
+
"",
|
|
6589
|
+
" sentryPlugin({ captureFailures: true })",
|
|
6590
|
+
" initSentryBrowser({ captureFailures: true })",
|
|
6591
|
+
"",
|
|
6592
|
+
"3) KEEP THE ONES THAT ARE SIGNAL:",
|
|
6593
|
+
"",
|
|
6594
|
+
" sentryPlugin({",
|
|
6595
|
+
" captureFailures: (e) => e._tag === 'PaymentDeclined',",
|
|
6596
|
+
" })",
|
|
6597
|
+
"",
|
|
6598
|
+
"The boot line now names the setting — `sentry active … captureFailures=false`",
|
|
6599
|
+
"— so the choice is visible where the decision takes effect."
|
|
6600
|
+
].join("\n")
|
|
6601
|
+
}), ha = (e) => /\bcostSource\b|\bCostBreakdown\b|\bestimateCostUsd\b|\b_voltro_ai_usage\b|\bMeteredUsage\b/.test(e.getFullText()), ga = [
|
|
6554
6602
|
he,
|
|
6555
6603
|
ge,
|
|
6556
6604
|
ve,
|
|
@@ -6694,12 +6742,13 @@ var C = (e, t, n) => {
|
|
|
6694
6742
|
oa,
|
|
6695
6743
|
ca,
|
|
6696
6744
|
fa,
|
|
6745
|
+
ma,
|
|
6697
6746
|
T({
|
|
6698
6747
|
version: "0.59.0",
|
|
6699
6748
|
id: "0.59.0/02_costsource_gained_unpriced",
|
|
6700
6749
|
title: "`costSource` gained `unpriced`, and AI usage is counted in a unit",
|
|
6701
6750
|
kind: "manual",
|
|
6702
|
-
appliesTo: ({ project: e }) => e.getSourceFiles().some(
|
|
6751
|
+
appliesTo: ({ project: e }) => e.getSourceFiles().some(ha),
|
|
6703
6752
|
note: [
|
|
6704
6753
|
"AI COST NOW HAS A THIRD SOURCE, AND USAGE HAS A UNIT.",
|
|
6705
6754
|
"",
|
|
@@ -6736,12 +6785,12 @@ var C = (e, t, n) => {
|
|
|
6736
6785
|
".turbo",
|
|
6737
6786
|
".cache",
|
|
6738
6787
|
".output"
|
|
6739
|
-
]),
|
|
6788
|
+
]), _a = () => [...[...J].map((e) => `**/${e}/**`), "**/.voltro-*/**"], Y = /(?:from|import)\s*\(?\s*['"]([^'"]+)['"]|require\s*\(\s*['"]([^'"]+)['"]\s*\)/g, X = /\.(?:tsx?|jsx?|mjs|cjs)$/, va = (e) => g(e).replace(X, ""), ya = (e) => {
|
|
6740
6789
|
let t = e.split("/").filter((e) => e.length > 0).pop();
|
|
6741
6790
|
if (t === void 0 || t === "." || t === "..") return;
|
|
6742
6791
|
let n = t.replace(X, "");
|
|
6743
6792
|
return n.length > 0 ? n : void 0;
|
|
6744
|
-
},
|
|
6793
|
+
}, ba = (e) => {
|
|
6745
6794
|
let t = /* @__PURE__ */ new Map();
|
|
6746
6795
|
for (let n of e) {
|
|
6747
6796
|
let e;
|
|
@@ -6752,24 +6801,24 @@ var C = (e, t, n) => {
|
|
|
6752
6801
|
}
|
|
6753
6802
|
Y.lastIndex = 0;
|
|
6754
6803
|
for (let r = Y.exec(e); r !== null; r = Y.exec(e)) {
|
|
6755
|
-
let e =
|
|
6804
|
+
let e = ya(r[1] ?? r[2] ?? "");
|
|
6756
6805
|
if (e === void 0) continue;
|
|
6757
6806
|
let i = t.get(e);
|
|
6758
6807
|
i === void 0 ? t.set(e, /* @__PURE__ */ new Set([n])) : i.add(n);
|
|
6759
6808
|
}
|
|
6760
6809
|
}
|
|
6761
6810
|
return t;
|
|
6762
|
-
},
|
|
6811
|
+
}, xa = (e, t) => {
|
|
6763
6812
|
let n = new Set(e);
|
|
6764
|
-
for (let r of e) for (let e of [
|
|
6813
|
+
for (let r of e) for (let e of [va(r), g(_(r))]) {
|
|
6765
6814
|
let r = t.get(e);
|
|
6766
6815
|
if (r !== void 0) for (let e of r) n.add(e);
|
|
6767
6816
|
}
|
|
6768
6817
|
return n;
|
|
6769
|
-
},
|
|
6818
|
+
}, Sa = /* @__PURE__ */ ".ts,.tsx,.mts,.cts,.js,.jsx,.mjs,.cjs,.yml,.yaml,.toml,.json,.jsonc,.ini,.cfg,.conf,.sh,.bash,.zsh,.fish,.ps1,.bat,.cmd,.md,.mdx,.rst,.txt,.adoc,Makefile,makefile,GNUmakefile,Justfile,justfile,Dockerfile,Containerfile,Procfile,Jenkinsfile,Rakefile,Taskfile".split(","), Ca = 2097152, wa = 4e4, Ta = (e) => {
|
|
6770
6819
|
let t = e.slice(e.lastIndexOf("/") + 1);
|
|
6771
|
-
return
|
|
6772
|
-
},
|
|
6820
|
+
return Sa.some((e) => e.startsWith(".") ? t.endsWith(e) : t === e);
|
|
6821
|
+
}, Ea = (e) => {
|
|
6773
6822
|
try {
|
|
6774
6823
|
let t = b("git", [
|
|
6775
6824
|
"ls-files",
|
|
@@ -6790,19 +6839,19 @@ var C = (e, t, n) => {
|
|
|
6790
6839
|
} catch {
|
|
6791
6840
|
return;
|
|
6792
6841
|
}
|
|
6793
|
-
}, Z = (e, t =
|
|
6842
|
+
}, Z = (e, t = Ea) => {
|
|
6794
6843
|
let n = t(e);
|
|
6795
|
-
if (n === void 0) return
|
|
6844
|
+
if (n === void 0) return Da;
|
|
6796
6845
|
let r = /* @__PURE__ */ new Map(), i = [];
|
|
6797
6846
|
for (let t of n) {
|
|
6798
|
-
if (t.split("/").some((e) => J.has(e)) || !
|
|
6799
|
-
if (r.size >=
|
|
6847
|
+
if (t.split("/").some((e) => J.has(e)) || !Ta(t)) continue;
|
|
6848
|
+
if (r.size >= wa) {
|
|
6800
6849
|
i.push(t);
|
|
6801
6850
|
continue;
|
|
6802
6851
|
}
|
|
6803
6852
|
let n = v(e, t);
|
|
6804
6853
|
try {
|
|
6805
|
-
if (ne(n).size >
|
|
6854
|
+
if (ne(n).size > Ca) {
|
|
6806
6855
|
i.push(t);
|
|
6807
6856
|
continue;
|
|
6808
6857
|
}
|
|
@@ -6826,45 +6875,45 @@ var C = (e, t, n) => {
|
|
|
6826
6875
|
scanned: r.size,
|
|
6827
6876
|
skipped: i
|
|
6828
6877
|
};
|
|
6829
|
-
},
|
|
6878
|
+
}, Da = {
|
|
6830
6879
|
find: () => [],
|
|
6831
6880
|
scanned: 0,
|
|
6832
6881
|
skipped: []
|
|
6833
|
-
},
|
|
6882
|
+
}, Oa = [
|
|
6834
6883
|
"**/*.ts",
|
|
6835
6884
|
"**/*.tsx",
|
|
6836
6885
|
"!**/node_modules/**",
|
|
6837
6886
|
"!**/dist/**",
|
|
6838
6887
|
"!**/.framework/**",
|
|
6839
6888
|
"!**/*.d.ts"
|
|
6840
|
-
], Q = (e, t, n =
|
|
6889
|
+
], Q = (e, t, n = ja) => {
|
|
6841
6890
|
let r = /* @__PURE__ */ new Set();
|
|
6842
|
-
for (let e of t) for (let t of e.scope ??
|
|
6891
|
+
for (let e of t) for (let t of e.scope ?? Oa) r.add(t);
|
|
6843
6892
|
let i = n(e);
|
|
6844
6893
|
if (i !== void 0) {
|
|
6845
|
-
let t = [...r].filter((e) => !e.startsWith("!")).map((e) =>
|
|
6894
|
+
let t = [...r].filter((e) => !e.startsWith("!")).map((e) => Aa(e)), n = [...r].filter((e) => e.startsWith("!")).map((e) => Aa(e.slice(1))), a = [...J], o = [];
|
|
6846
6895
|
for (let r of i) {
|
|
6847
6896
|
if (a.some((e) => r === e || r.startsWith(`${e}/`) || r.includes(`/${e}/`)) || !t.some((e) => e(r)) || n.some((e) => e(r))) continue;
|
|
6848
6897
|
let i = v(e, r);
|
|
6849
6898
|
y(i) && o.push(i);
|
|
6850
6899
|
}
|
|
6851
|
-
return
|
|
6900
|
+
return ka(o.length, e), o;
|
|
6852
6901
|
}
|
|
6853
6902
|
let a = ae([...r], {
|
|
6854
6903
|
cwd: e,
|
|
6855
6904
|
absolute: !0,
|
|
6856
6905
|
expandDirectories: !1,
|
|
6857
6906
|
followSymbolicLinks: !1,
|
|
6858
|
-
ignore: [...
|
|
6907
|
+
ignore: [..._a()]
|
|
6859
6908
|
});
|
|
6860
|
-
return
|
|
6861
|
-
},
|
|
6862
|
-
let n =
|
|
6909
|
+
return ka(a.length, e), a;
|
|
6910
|
+
}, ka = (e, t) => {
|
|
6911
|
+
let n = Ma();
|
|
6863
6912
|
if (!(e <= n)) throw Error(`voltro update: the codemod scan matched ${e} files under ${t}, past the ${n} ceiling.\n Every matched file is parsed into one ts-morph project, so the heap needed grows with\n this number — past the ceiling it runs out of memory, and V8 aborts without naming a\n limit, which is why this stops here instead. Three ways out, in order:\n • put non-source directories in .gitignore (inside a git repo the scan then never\n sees them at all — a build cache, a data dump, a virtualenv),\n • run \`voltro update\` from the app directory rather than the workspace root, or\n • take one codemod at a time: \`voltro update --dry-run\` lists the ids, then\n \`voltro update --codemods-only --only <id>\` runs a single one.\n If every one of those files really is source this pass must rewrite, raise the ceiling\n with VOLTRO_CODEMOD_MAX_FILES and give node room: NODE_OPTIONS=--max-old-space-size=8192.`);
|
|
6864
|
-
},
|
|
6913
|
+
}, Aa = (e) => {
|
|
6865
6914
|
let t = e.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*\//g, "\0").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\u0000/g, "(?:.*/)?").replace(/\\\{([^}]*)\\\}/g, (e, t) => `(?:${t.split(",").join("|")})`);
|
|
6866
6915
|
return (e) => RegExp(`^${t}$`).test(e);
|
|
6867
|
-
},
|
|
6916
|
+
}, ja = (e) => {
|
|
6868
6917
|
try {
|
|
6869
6918
|
let t = b("git", [
|
|
6870
6919
|
"ls-files",
|
|
@@ -6885,7 +6934,7 @@ var C = (e, t, n) => {
|
|
|
6885
6934
|
} catch {
|
|
6886
6935
|
return;
|
|
6887
6936
|
}
|
|
6888
|
-
},
|
|
6937
|
+
}, Ma = () => {
|
|
6889
6938
|
let e = Number(process.env.VOLTRO_CODEMOD_MAX_FILES);
|
|
6890
6939
|
return Number.isInteger(e) && e > 0 ? e : 2e4;
|
|
6891
6940
|
}, $ = (e, t) => {
|
|
@@ -6895,7 +6944,7 @@ var C = (e, t, n) => {
|
|
|
6895
6944
|
if (t !== 0) return t;
|
|
6896
6945
|
}
|
|
6897
6946
|
return 0;
|
|
6898
|
-
},
|
|
6947
|
+
}, Na = (e, t, n = ga) => n.filter((n) => $(e, n.version) < 0 && $(n.version, t) <= 0).slice().sort(me), Pa = (e, t, n = () => {}, r = Da) => {
|
|
6899
6948
|
let i = [], a = [], o = [];
|
|
6900
6949
|
for (let s of t) {
|
|
6901
6950
|
let t = !s.appliesTo || s.appliesTo({
|
|
@@ -6946,8 +6995,8 @@ var C = (e, t, n) => {
|
|
|
6946
6995
|
manual: a,
|
|
6947
6996
|
skipped: o
|
|
6948
6997
|
};
|
|
6949
|
-
},
|
|
6950
|
-
let t = e.log ?? (() => {}), n =
|
|
6998
|
+
}, Fa = async (e) => {
|
|
6999
|
+
let t = e.log ?? (() => {}), n = Na(e.from, e.to, e.codemods ?? ga), r = e.only === void 0 || e.only.length === 0 ? n : (() => {
|
|
6951
7000
|
let t = n.filter((t) => e.only.includes(t.id)), r = e.only.filter((e) => !n.some((t) => t.id === e));
|
|
6952
7001
|
if (r.length > 0) throw Error(`voltro update --only: no codemod in ${e.from} → ${e.to} has id ${r.map((e) => `"${e}"`).join(", ")}.\n Available for this jump:\n${n.map((e) => ` ${e.id}`).join("\n")}`);
|
|
6953
7002
|
return t;
|
|
@@ -6974,15 +7023,15 @@ var C = (e, t, n) => {
|
|
|
6974
7023
|
get skipped() {
|
|
6975
7024
|
return (p ??= Z(e.root)).skipped;
|
|
6976
7025
|
}
|
|
6977
|
-
}, h = c.length > 0 ?
|
|
7026
|
+
}, h = c.length > 0 ? ba(Q(e.root, [{
|
|
6978
7027
|
...c[0],
|
|
6979
|
-
scope:
|
|
7028
|
+
scope: Oa
|
|
6980
7029
|
}])) : void 0;
|
|
6981
7030
|
for (let n of r) {
|
|
6982
7031
|
if (c.includes(n)) {
|
|
6983
7032
|
let r = a(), i = Q(e.root, [n]);
|
|
6984
|
-
for (let e of
|
|
6985
|
-
let s =
|
|
7033
|
+
for (let e of xa(i, h)) y(e) && r.addSourceFileAtPath(e);
|
|
7034
|
+
let s = Pa(r, [n], t, m);
|
|
6986
7035
|
e.dryRun || await r.save(), l.push(...s.applied), u.push(...s.manual), d.push(...s.skipped), o = void 0;
|
|
6987
7036
|
continue;
|
|
6988
7037
|
}
|
|
@@ -6991,7 +7040,7 @@ var C = (e, t, n) => {
|
|
|
6991
7040
|
for (let t of s) y(t) && e.addSourceFileAtPath(t);
|
|
6992
7041
|
return e;
|
|
6993
7042
|
})();
|
|
6994
|
-
let r =
|
|
7043
|
+
let r = Pa(o, [n], t, m);
|
|
6995
7044
|
e.dryRun || await o.save(), l.push(...r.applied), u.push(...r.manual), d.push(...r.skipped);
|
|
6996
7045
|
}
|
|
6997
7046
|
return {
|
|
@@ -7001,4 +7050,4 @@ var C = (e, t, n) => {
|
|
|
7001
7050
|
};
|
|
7002
7051
|
};
|
|
7003
7052
|
//#endregion
|
|
7004
|
-
export { T as i,
|
|
7053
|
+
export { T as i, Fa as n, J as r, $ as t };
|
|
@@ -109,7 +109,7 @@ var u = () => {
|
|
|
109
109
|
name: "dashboard",
|
|
110
110
|
summary: "Serve the DevTools dashboard standalone (from @voltro/dashboard). Targets via VOLTRO_DASHBOARD_APPS; --port to override.",
|
|
111
111
|
status: "wired",
|
|
112
|
-
run: (e) => import("./dashboardCommand-
|
|
112
|
+
run: (e) => import("./dashboardCommand-t8Qsebjr.js").then((t) => t.runDashboardCommand(e)),
|
|
113
113
|
help: {
|
|
114
114
|
usage: "[--port <n>]",
|
|
115
115
|
flags: [["--port <n>", "port to serve the dashboard on"]],
|
|
@@ -171,7 +171,7 @@ var u = () => {
|
|
|
171
171
|
name: "evolve",
|
|
172
172
|
summary: "Schema-evolution copilot: propose an observed-graph-driven codemod + a branch-verified backfill for a schema change (rename/retype/split/drop a column, rename a table). Dry-run by default; --write applies. Usage: voltro evolve rename-column <table>.<col> --to <newName> [--write] [--json].",
|
|
173
173
|
status: "wired",
|
|
174
|
-
run: (e) => import("./evolveCommand-
|
|
174
|
+
run: (e) => import("./evolveCommand-CThb0EZZ.js").then((t) => t.runEvolveCommand(e)),
|
|
175
175
|
help: {
|
|
176
176
|
usage: "<rename-column|rename-table|retype-column|split-column|drop-column> <target> [--to <new>] [--write]",
|
|
177
177
|
flags: [
|
|
@@ -281,7 +281,7 @@ var u = () => {
|
|
|
281
281
|
name: "info",
|
|
282
282
|
summary: "Report versions (CLI, node, every installed @voltro/* — flags lockstep skew), package manager, and dialect. --json for CI. Exits 1 on version skew.",
|
|
283
283
|
status: "wired",
|
|
284
|
-
run: (e) => import("./infoCommand-
|
|
284
|
+
run: (e) => import("./infoCommand-a0WkKcUY.js").then((t) => t.runInfoCommand(e)),
|
|
285
285
|
help: {
|
|
286
286
|
usage: "[--json]",
|
|
287
287
|
flags: [["--json", "machine-readable report"]],
|
|
@@ -370,7 +370,7 @@ var u = () => {
|
|
|
370
370
|
name: "build",
|
|
371
371
|
summary: "Production build for a web app (vite build + per-page SSG pre-render).",
|
|
372
372
|
status: "wired",
|
|
373
|
-
run: (e) => import("./build-
|
|
373
|
+
run: (e) => import("./build-BxAsLzyU.js").then((t) => t.runBuildCommand(e)),
|
|
374
374
|
help: {
|
|
375
375
|
usage: "[app] [--target <t>]",
|
|
376
376
|
flags: [["--target <t>", "build target"], ["--report", "print what a visitor downloads: first load, chunks, server artefacts"]],
|
|
@@ -421,7 +421,7 @@ var u = () => {
|
|
|
421
421
|
name: "start",
|
|
422
422
|
summary: "Production runtime: serves dist + SSR-on-demand for ssr/isr pages.",
|
|
423
423
|
status: "wired",
|
|
424
|
-
run: (e) => import("./start-
|
|
424
|
+
run: (e) => import("./start-BhoDQ25C.js").then((t) => t.runStartCommand(e)),
|
|
425
425
|
help: {
|
|
426
426
|
usage: "[app]",
|
|
427
427
|
examples: [["voltro start", "serve a built web app (dist + SSR-on-demand)"]],
|
|
@@ -555,14 +555,14 @@ var u = () => {
|
|
|
555
555
|
handlesHelp: !0,
|
|
556
556
|
summary: "Upgrade the app to the latest framework: bump every @voltro/* dependency (across ALL workspace members, install once at the workspace root), then run the codemods shipped with the target version. Flags: --to <version>, --from <version>, --codemods-only, --dry-run, --force, --exact, --help. After: run `voltro db apply`.",
|
|
557
557
|
status: "wired",
|
|
558
|
-
run: (e) => import("./updateCommand-
|
|
558
|
+
run: (e) => import("./updateCommand-QMOirvXC.js").then((t) => t.runUpdateCommand(e))
|
|
559
559
|
},
|
|
560
560
|
{
|
|
561
561
|
name: "_apply-codemods",
|
|
562
562
|
summary: "Internal: apply shipped codemods for a framework version jump (re-exec target of `voltro update`).",
|
|
563
563
|
status: "wired",
|
|
564
564
|
hidden: !0,
|
|
565
|
-
run: (e) => import("./updateCommand-
|
|
565
|
+
run: (e) => import("./updateCommand-QMOirvXC.js").then((t) => t.runApplyCodemods(e))
|
|
566
566
|
},
|
|
567
567
|
{
|
|
568
568
|
name: "embeddings",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { p as e } from "./dev-Ce2gEziv.js";
|
|
2
2
|
import { it as t, st as n } from "./webDev-CBN9KkyQ.js";
|
|
3
|
-
import { t as r } from "./start-
|
|
3
|
+
import { t as r } from "./start-CcdPRG8L.js";
|
|
4
4
|
import { join as i } from "node:path";
|
|
5
5
|
import { existsSync as a } from "node:fs";
|
|
6
6
|
import { createLogger as o } from "@voltro/logger";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as e } from "./cliOutput-D1tSBoRM.js";
|
|
2
2
|
import { i as t } from "./checkCommand-DC7k1_hP.js";
|
|
3
|
-
import { i as n, n as r } from "./codemodRunner-
|
|
3
|
+
import { i as n, n as r } from "./codemodRunner-ClUqkhvR.js";
|
|
4
4
|
import { basename as i, join as a, resolve as o } from "node:path";
|
|
5
5
|
import { branchNamespaceName as s, planBranchProvision as c } from "@voltro/database";
|
|
6
6
|
import { readFile as l } from "node:fs/promises";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as e, r as t, t as n } from "./cliOutput-D1tSBoRM.js";
|
|
2
|
-
import { o as r } from "./updateCommand-
|
|
2
|
+
import { o as r } from "./updateCommand-D9avpQFT.js";
|
|
3
3
|
import { join as i, resolve as a } from "node:path";
|
|
4
4
|
import { readFileSync as o, readdirSync as s, statSync as c } from "node:fs";
|
|
5
5
|
//#region src/infoCommand.ts
|