@voltro/cli 0.38.0 → 0.39.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 +224 -0
- package/THIRD-PARTY-NOTICES.md +80 -45
- package/dist/{addCommand-BNeoeSxe.js → addCommand-C05L9tZh.js} +2 -2
- package/dist/addCommand-C3MdJG-a.js +2 -0
- package/dist/{agentsMd-mhQMF1bx.js → agentsMd-7zI2h5l9.js} +3 -3
- package/dist/agentsMd-BFCXh2gl.js +2 -0
- package/dist/apiBuild-2GvK8CUB.js +2 -0
- package/dist/{apiBuild-CvacV4zA.js → apiBuild-DGalUk9v.js} +3 -3
- package/dist/baselineCommand-CXv680Dc.js +2 -0
- package/dist/{baselineCommand-C6NMt-oa.js → baselineCommand-Ck2Xm8M7.js} +18 -18
- package/dist/bin.js +1 -1
- package/dist/{build-_LoTC1s0.js → build-CfF6t0UM.js} +107 -100
- package/dist/{capabilitiesCommand-nq_pz5xd.js → capabilitiesCommand-D5gucwYa.js} +8 -8
- package/dist/{checkCommand-wibtQx-N.js → checkCommand-BV56Pcc1.js} +1 -1
- package/dist/{checkCommand-Pjk5sBl2.js → checkCommand-CBtynBKW.js} +34 -34
- package/dist/{cloudCmd-NQSwe_Qk.js → cloudCmd-C42gaO8s.js} +16 -16
- package/dist/{clusterCmd-D5wsCmA_.js → clusterCmd-DrVFCzSj.js} +8 -4
- package/dist/{codegen-GYYcdpCg.js → codegen-CbpGCWLG.js} +1 -1
- package/dist/codegen-i8QGcHsi.js +2 -0
- package/dist/codegenCommand-W7SDdiAQ.js +129 -0
- package/dist/{codemodRunner-CXgQ-ecJ.js → codemodRunner-D-jTyvWo.js} +622 -551
- package/dist/{commands-DaZVi9wi.js → commands-BD9eBRY3.js} +48 -48
- package/dist/{connectionConfig-UFlIEiys.js → connectionConfig-Bk9IC7D0.js} +1 -1
- package/dist/{dashboardCommand-Dxy_kmoW.js → dashboardCommand-7qGylm0F.js} +3 -3
- package/dist/{dataCommand-D6-Ha2lf.js → dataCommand-C_F2DYxe.js} +14 -11
- package/dist/{dbCommand-C4UW8cVN.js → dbCommand-DSwGv9wS.js} +50 -49
- package/dist/dbCommand-DcqEyxju.js +2 -0
- package/dist/dev-alhkKoEX.js +3 -0
- package/dist/{dev-E7Eo5GHc.js → dev-gqpnzVhI.js} +2260 -2184
- package/dist/{dialectDriver-CgXnDfec.js → dialectDriver-czCHYpeH.js} +2 -1
- package/dist/{doctorCommand-gmDyALFL.js → doctorCommand-Bvs-BQrM.js} +242 -238
- package/dist/doctorCommand-CVXfRrng.js +2 -0
- package/dist/{dormancyCommand-CE6wG8lj.js → dormancyCommand-B-PPHc9Q.js} +1 -1
- package/dist/{e2eCmd-BRabZww-.js → e2eCmd-uFHig1hV.js} +8 -2
- package/dist/{embeddingsCommand-C3uAuf6N.js → embeddingsCommand-OKY6XjUf.js} +6 -6
- package/dist/{envCommand-DzuWh8ya.js → envCommand-B1-Zm85H.js} +19 -19
- package/dist/{evolveCommand-DPLqcYb2.js → evolveCommand-C4-NlFbd.js} +6 -8
- package/dist/{generateCommand-DbgcUpGw.js → generateCommand-CcyvH2ve.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/{infoCommand-CmczGj_l.js → infoCommand-CTo8Jnhq.js} +7 -7
- package/dist/inspect-B7U7Cl_Z.js +1192 -0
- package/dist/inspect-DUze25t0.js +2 -0
- package/dist/{inspectCmd-EHFZ9yYu.js → inspectCmd-niF97fAq.js} +5 -5
- package/dist/inspectGateHint-BjnFubmH.js +7 -0
- package/dist/{logFileSink-C_D2wRN1.js → logFileSink-B4uP8pvf.js} +1 -1
- package/dist/{logsCmd-D36xK7Zu.js → logsCmd-B6oNsfaZ.js} +10 -7
- package/dist/{manifestBuild-hpPLaGxV.js → manifestBuild-BK42hu0k.js} +1 -1
- package/dist/manifestBuild-j0n109tt.js +2 -0
- package/dist/{metaCommands-CIoQNlaQ.js → metaCommands-DUYR--Ts.js} +1 -1
- package/dist/{migrate-RwgUWXfc.js → migrate-BnPw2zC8.js} +7 -4
- package/dist/{packageCommand-Cug_3Ogl.js → packageCommand-9SVyvsSo.js} +3 -2
- package/dist/{probeCommand-BPEpwT32.js → probeCommand-C9gazU0H.js} +35 -24
- package/dist/{projectScaffold-CxgtJvlb.js → projectScaffold-BEhhHjPr.js} +1 -1
- package/dist/{projectScaffold-DDgWbNLe.js → projectScaffold-BvhLOrLq.js} +17 -15
- package/dist/{runtimeTrace-6jfznSzr.js → runtimeTrace-DzZOCd94.js} +1 -1
- package/dist/{scheduleManifestCmd-D2x0CTTY.js → scheduleManifestCmd-kmWzrO_w.js} +6 -9
- package/dist/{sdkgen-CEJZZQUA.js → sdkgen-C4roLErM.js} +4 -4
- package/dist/{seedRunner-ZmLSqNe2.js → seedRunner-IdHEprqf.js} +1 -4
- package/dist/serveCommand-B6TATyCj.js +1770 -0
- package/dist/serveCommand-CNR0gI9V.js +2 -0
- package/dist/serveEntry.js +2 -2
- package/dist/{serverlessCommand-CfJZy6dS.js → serverlessCommand-DbJ7Plg9.js} +3 -3
- package/dist/{start-CidwCcjl.js → start-BNuTWdRd.js} +1 -1
- package/dist/{start-RCh6qKFe.js → start-ft_KzFTd.js} +257 -254
- package/dist/startEntry.js +1 -1
- package/dist/{test-DIQ0jlkQ.js → test-CLYXrZ2F.js} +1 -1
- package/dist/{tracesCmd-DStmCJPi.js → tracesCmd-DgtgOUdi.js} +7 -4
- package/dist/{typecheckCommand-BlsWiCNq.js → typecheckCommand-BuCtT92o.js} +7 -7
- package/dist/updateCommand-6FMU2klq.js +2 -0
- package/dist/{updateCommand-CmksX7m_.js → updateCommand-CHBmCB17.js} +5 -3
- package/dist/{webDev-BKdD7c_a.js → webDev-CTpSY-e_.js} +813 -775
- package/dist/webDev-id3I5PvG.js +2 -0
- package/dist/{webhookDiscovery-D7VaeMlz.js → webhookDiscovery-CphsQe59.js} +4 -6
- package/dist/{webhookDiscovery-CrGAfhIG.js → webhookDiscovery-il9ti-HE.js} +1 -1
- package/dist/{webhooksCommand-BHeaF1ZJ.js → webhooksCommand-BVvOtZ1B.js} +1 -1
- package/package.json +27 -21
- package/templates/AGENTS.md +2 -2
- package/templates/agent-docs/_index.md +2 -2
- package/templates/agent-docs/_manifest.json +2 -2
- package/templates/agent-docs/authentication.md +30 -0
- package/templates/agent-docs/cli.md +17 -13
- package/templates/agent-docs/data.md +44 -1
- package/templates/agent-docs/database/migrations.md +2 -2
- package/templates/agent-docs/database/seedsdialects.md +2 -2
- package/templates/agent-docs/deployment.md +21 -7
- package/templates/agent-docs/internationalization.md +10 -3
- package/templates/agent-docs/local-first-mobile.md +141 -20
- package/templates/agent-docs/plugins/mail.md +1 -1
- package/templates/agent-docs/plugins/ratelimit.md +1 -1
- package/templates/agent-docs/plugins.md +3 -1
- package/templates/agent-docs/releases.md +130 -1
- package/templates/agent-docs/routing.md +34 -2
- package/templates/agent-docs/templates/apibackends.md +1 -1
- package/templates/agent-docs/templates/mobile.md +1 -1
- package/templates/agent-docs/whats-new.md +181 -49
- 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-sqlite/package.json +8 -8
- package/templates/apps/api-backend-storage/package.json +8 -8
- package/templates/apps/api-cms/package.json +10 -10
- 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/authz.ts +16 -1
- 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-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-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 +9 -9
- package/templates/apps/frontend-auth/package.json +8 -8
- package/templates/apps/frontend-blank/package.json +7 -7
- package/templates/apps/frontend-cms/package.json +9 -9
- package/templates/apps/frontend-collab/package.json +10 -10
- 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-portal/package.json +8 -8
- package/templates/apps/frontend-saas/package.json +8 -8
- 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/templates/apps/frontend-status/package.json +8 -8
- package/templates/apps/mobile-app/README.md +41 -17
- package/templates/apps/mobile-app/app.config.ts +1 -1
- package/templates/apps/mobile-app/package.json +15 -11
- package/templates/apps/mobile-app/src/app/_layout.tsx +44 -13
- package/templates/apps/mobile-app/src/app/index.tsx +1 -1
- package/templates/apps/mobile-app/src/app/settings.tsx +4 -1
- package/templates/apps/mobile-app/src/client.ts +74 -57
- package/templates/apps/mobile-app/src/lib/api.ts +4 -4
- package/templates/apps/mobile-app/src/lib/deeplinks.ts +6 -6
- package/templates/apps/mobile-app/src/persistence.ts +24 -3
- package/templates/apps/mobile-app/tsconfig.json +17 -3
- package/dist/addCommand-aXSQveak.js +0 -2
- package/dist/agentsMd-BTchIZku.js +0 -2
- package/dist/apiBuild-ttSDDOGp.js +0 -2
- package/dist/baselineCommand-Cfw2Afwm.js +0 -2
- package/dist/codegen-uYrrDzQv.js +0 -2
- package/dist/codegenCommand-C60m_LCp.js +0 -30
- package/dist/dbCommand-CC-qNzpz.js +0 -2
- package/dist/dev-CAOoXOkc.js +0 -3
- package/dist/doctorCommand-Cjl8Yii8.js +0 -2
- package/dist/inspect-CjTYzAs_.js +0 -1190
- package/dist/inspect-P4pxoMaV.js +0 -2
- package/dist/inspectGateHint-BF6608UT.js +0 -4
- package/dist/manifestBuild-COkJoyAr.js +0 -2
- package/dist/serveCommand-DNRF2nDI.js +0 -2
- package/dist/serveCommand-DnY4VS3D.js +0 -1767
- package/dist/updateCommand-B0J_T9Vs.js +0 -2
- package/dist/webDev-CcJfdSjl2.js +0 -2
|
@@ -23,12 +23,10 @@ var r = /\.webhook\.tsx?$/, i = async (t, r) => {
|
|
|
23
23
|
descriptor: s
|
|
24
24
|
});
|
|
25
25
|
break;
|
|
26
|
-
case "webhookProvider":
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
});
|
|
31
|
-
break;
|
|
26
|
+
case "webhookProvider": o.push({
|
|
27
|
+
file: i,
|
|
28
|
+
descriptor: s
|
|
29
|
+
});
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
32
|
return {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as e, r as t, t as n } from "./webhookDiscovery-
|
|
1
|
+
import { i as e, r as t, t as n } from "./webhookDiscovery-CphsQe59.js";
|
|
2
2
|
export { n as WEBHOOK_PATTERN, t as loadWebhookFiles, e as outgoingFromEvents };
|
|
@@ -222,7 +222,7 @@ createVerifier({ secret: [process.env.WEBHOOK_SECRET, process.env.WEBHOOK_SECRET
|
|
|
222
222
|
...t === void 0 ? {} : { payload: t }
|
|
223
223
|
};
|
|
224
224
|
}, S = u({ scope: "voltro:webhooks" }), C = ["--out", "--name"], w = async (e) => {
|
|
225
|
-
let { walk: t, loadDiscovered: n } = await import("./dev-
|
|
225
|
+
let { walk: t, loadDiscovered: n } = await import("./dev-alhkKoEX.js"), { outgoingFromEvents: r } = await import("./webhookDiscovery-il9ti-HE.js");
|
|
226
226
|
return r((await n(await t(e))).events.map((e) => ({
|
|
227
227
|
file: e.file,
|
|
228
228
|
descriptor: e.descriptor
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.0",
|
|
4
4
|
"description": "The `voltro` CLI — dev server, codegen, migrations, project scaffolding, agent-docs seeding, and production serve.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -592,6 +592,12 @@
|
|
|
592
592
|
"title": "a `*.startup.ts` that fails refuses the boot (it used to warn and continue)",
|
|
593
593
|
"kind": "manual"
|
|
594
594
|
},
|
|
595
|
+
{
|
|
596
|
+
"version": "0.39.0",
|
|
597
|
+
"id": "0.39.0/01_empty-input-schema-rejects-every-field",
|
|
598
|
+
"title": "a procedure declaring `Schema.Struct({})` used to accept every field and now accepts none",
|
|
599
|
+
"kind": "manual"
|
|
600
|
+
},
|
|
595
601
|
{
|
|
596
602
|
"version": "0.4.0",
|
|
597
603
|
"id": "0.4.0/01_rbac-forbidden-to-scopeerror",
|
|
@@ -691,22 +697,22 @@
|
|
|
691
697
|
"@effect/platform-node": "^0.108.0",
|
|
692
698
|
"@effect/sql": "^0.52.0",
|
|
693
699
|
"@effect/workflow": "^0.19.0",
|
|
694
|
-
"@voltro/ai": "0.
|
|
695
|
-
"@voltro/cache": "0.
|
|
696
|
-
"@voltro/data-transfer": "0.
|
|
697
|
-
"@voltro/database": "0.
|
|
698
|
-
"@voltro/env": "0.
|
|
699
|
-
"@voltro/kv": "0.
|
|
700
|
-
"@voltro/logger": "0.
|
|
701
|
-
"@voltro/plugin-auth": "0.
|
|
702
|
-
"@voltro/plugin-broadcast": "0.
|
|
703
|
-
"@voltro/plugin-mail": "0.
|
|
704
|
-
"@voltro/plugin-storage": "0.
|
|
705
|
-
"@voltro/plugin-webhooks": "0.
|
|
706
|
-
"@voltro/protocol": "0.
|
|
707
|
-
"@voltro/runtime": "0.
|
|
708
|
-
"@voltro/serverless": "0.
|
|
709
|
-
"@voltro/workflow": "0.
|
|
700
|
+
"@voltro/ai": "0.39.0",
|
|
701
|
+
"@voltro/cache": "0.39.0",
|
|
702
|
+
"@voltro/data-transfer": "0.39.0",
|
|
703
|
+
"@voltro/database": "0.39.0",
|
|
704
|
+
"@voltro/env": "0.39.0",
|
|
705
|
+
"@voltro/kv": "0.39.0",
|
|
706
|
+
"@voltro/logger": "0.39.0",
|
|
707
|
+
"@voltro/plugin-auth": "0.39.0",
|
|
708
|
+
"@voltro/plugin-broadcast": "0.39.0",
|
|
709
|
+
"@voltro/plugin-mail": "0.39.0",
|
|
710
|
+
"@voltro/plugin-storage": "0.39.0",
|
|
711
|
+
"@voltro/plugin-webhooks": "0.39.0",
|
|
712
|
+
"@voltro/protocol": "0.39.0",
|
|
713
|
+
"@voltro/runtime": "0.39.0",
|
|
714
|
+
"@voltro/serverless": "0.39.0",
|
|
715
|
+
"@voltro/workflow": "0.39.0",
|
|
710
716
|
"chokidar": "^5.0.0",
|
|
711
717
|
"ioredis": "^5.11.1",
|
|
712
718
|
"tinyglobby": "^0.2.17",
|
|
@@ -715,10 +721,10 @@
|
|
|
715
721
|
"optionalDependencies": {
|
|
716
722
|
"@tailwindcss/vite": "^4.3.3",
|
|
717
723
|
"@vercel/nft": "^1.10.2",
|
|
718
|
-
"@vitejs/plugin-react": "^6.0.
|
|
719
|
-
"esbuild": "^0.28.
|
|
720
|
-
"tsx": "^4.23.
|
|
721
|
-
"vite": "^8.1
|
|
724
|
+
"@vitejs/plugin-react": "^6.0.5",
|
|
725
|
+
"esbuild": "^0.28.2",
|
|
726
|
+
"tsx": "^4.23.12",
|
|
727
|
+
"vite": "^8.2.1"
|
|
722
728
|
},
|
|
723
729
|
"peerDependencies": {
|
|
724
730
|
"@effect/platform": "^0.97.0",
|
package/templates/AGENTS.md
CHANGED
|
@@ -707,7 +707,7 @@ each plugin's own README.
|
|
|
707
707
|
|
|
708
708
|
| Topic | Open | Summary |
|
|
709
709
|
|---|---|---|
|
|
710
|
-
| **What's new in 0.
|
|
710
|
+
| **What's new in 0.39.0** | `node_modules/@voltro/cli/templates/agent-docs/whats-new.md` | Everything that changed in this version. Read it before hand-rolling something the framework may now ship. |
|
|
711
711
|
| AI | `node_modules/@voltro/cli/templates/agent-docs/ai.md` | How Voltro treats AI — agents, tools, streaming, RAG — all primitives over the same WebSocket as the rest of the framework. |
|
|
712
712
|
| Authentication | `node_modules/@voltro/cli/templates/agent-docs/authentication.md` | How @voltro/plugin-auth wires password + session-cookie auth across api + web, plus the pluggable identity-strategy protocol. |
|
|
713
713
|
| Caching | `node_modules/@voltro/cli/templates/agent-docs/caching.md` | Voltro's caching layer (@voltro/cache) — an always-on memory default, swappable Redis-compatible backends, a low-level wrap primitive, and automatic query-result invalidation. |
|
|
@@ -733,7 +733,7 @@ each plugin's own README.
|
|
|
733
733
|
| Observability | `node_modules/@voltro/cli/templates/agent-docs/observability.md` | OpenTelemetry tracing in Voltro — the auto-emitted spans for every primitive, span attributes and nesting, the three enabling modes (console / OTLP / buffer), and adding your own spans with Effect.withSpan. |
|
|
734
734
|
| Plugins | `node_modules/@voltro/cli/templates/agent-docs/plugins.md` | How Voltro plugins compose into the runtime, what they can intercept, the catalogue, and writing your own. |
|
|
735
735
|
| Reference | `node_modules/@voltro/cli/templates/agent-docs/reference.md` | The client-side hook surface, grouped by purpose. |
|
|
736
|
-
| Releases | `node_modules/@voltro/cli/templates/agent-docs/releases.md` |
|
|
736
|
+
| Releases | `node_modules/@voltro/cli/templates/agent-docs/releases.md` | 0.35 through 0.38 in one pass — the boot-breaking access declarations, the stricter input handling, and the runtime behaviour that moved underneath you. |
|
|
737
737
|
| Routing | `node_modules/@voltro/cli/templates/agent-docs/routing.md` | Voltro's file-based router — pages, layouts, render modes, loaders, navigation, islands. The web side of the framework. |
|
|
738
738
|
| Scheduling | `node_modules/@voltro/cli/templates/agent-docs/scheduling.md` | Deployment-agnostic scheduled jobs in Voltro — one *.cron.tsx definition that runs unchanged on a single box, a multi-instance fleet, or an external scheduler. |
|
|
739
739
|
| Schema-driven UI | `node_modules/@voltro/cli/templates/agent-docs/schema-driven-ui.md` | Project the typed descriptor graph into UI — forms, tables, pickers, and reactive components, all bound to a descriptor with near-zero glue. |
|
|
@@ -9,7 +9,7 @@ each plugin's own README.
|
|
|
9
9
|
|
|
10
10
|
| Topic | Open | Summary |
|
|
11
11
|
|---|---|---|
|
|
12
|
-
| **What's new in 0.
|
|
12
|
+
| **What's new in 0.39.0** | `node_modules/@voltro/cli/templates/agent-docs/whats-new.md` | Everything that changed in this version. Read it before hand-rolling something the framework may now ship. |
|
|
13
13
|
| AI | `node_modules/@voltro/cli/templates/agent-docs/ai.md` | How Voltro treats AI — agents, tools, streaming, RAG — all primitives over the same WebSocket as the rest of the framework. |
|
|
14
14
|
| Authentication | `node_modules/@voltro/cli/templates/agent-docs/authentication.md` | How @voltro/plugin-auth wires password + session-cookie auth across api + web, plus the pluggable identity-strategy protocol. |
|
|
15
15
|
| Caching | `node_modules/@voltro/cli/templates/agent-docs/caching.md` | Voltro's caching layer (@voltro/cache) — an always-on memory default, swappable Redis-compatible backends, a low-level wrap primitive, and automatic query-result invalidation. |
|
|
@@ -35,7 +35,7 @@ each plugin's own README.
|
|
|
35
35
|
| Observability | `node_modules/@voltro/cli/templates/agent-docs/observability.md` | OpenTelemetry tracing in Voltro — the auto-emitted spans for every primitive, span attributes and nesting, the three enabling modes (console / OTLP / buffer), and adding your own spans with Effect.withSpan. |
|
|
36
36
|
| Plugins | `node_modules/@voltro/cli/templates/agent-docs/plugins.md` | How Voltro plugins compose into the runtime, what they can intercept, the catalogue, and writing your own. |
|
|
37
37
|
| Reference | `node_modules/@voltro/cli/templates/agent-docs/reference.md` | The client-side hook surface, grouped by purpose. |
|
|
38
|
-
| Releases | `node_modules/@voltro/cli/templates/agent-docs/releases.md` |
|
|
38
|
+
| Releases | `node_modules/@voltro/cli/templates/agent-docs/releases.md` | 0.35 through 0.38 in one pass — the boot-breaking access declarations, the stricter input handling, and the runtime behaviour that moved underneath you. |
|
|
39
39
|
| Routing | `node_modules/@voltro/cli/templates/agent-docs/routing.md` | Voltro's file-based router — pages, layouts, render modes, loaders, navigation, islands. The web side of the framework. |
|
|
40
40
|
| Scheduling | `node_modules/@voltro/cli/templates/agent-docs/scheduling.md` | Deployment-agnostic scheduled jobs in Voltro — one *.cron.tsx definition that runs unchanged on a single box, a multi-instance fleet, or an external scheduler. |
|
|
41
41
|
| Schema-driven UI | `node_modules/@voltro/cli/templates/agent-docs/schema-driven-ui.md` | Project the typed descriptor graph into UI — forms, tables, pickers, and reactive components, all bound to a descriptor with near-zero glue. |
|
|
@@ -231,9 +231,9 @@
|
|
|
231
231
|
"title": "Releases",
|
|
232
232
|
"section": "Releases",
|
|
233
233
|
"group": null,
|
|
234
|
-
"description": "
|
|
234
|
+
"description": "0.35 through 0.38 in one pass — the boot-breaking access declarations, the stricter input handling, and the runtime behaviour that moved underneath you.",
|
|
235
235
|
"path": "agent-docs/releases.md",
|
|
236
|
-
"files":
|
|
236
|
+
"files": 2
|
|
237
237
|
},
|
|
238
238
|
{
|
|
239
239
|
"id": "routing",
|
|
@@ -2154,6 +2154,36 @@ that throws — each is a denial, not a pass. An authorization question nobody c
|
|
|
2154
2154
|
answer is a refusal; treating it as a pass is how a policy layer ends up
|
|
2155
2155
|
enforcing nothing while looking like it does.
|
|
2156
2156
|
|
|
2157
|
+
**A guard naming an unregistered `resourceType` refuses the BOOT.** Denying is
|
|
2158
|
+
correct per call and useless as a deployment outcome: the app comes up green and
|
|
2159
|
+
every guarded procedure is down, with a log line per refused call as the only
|
|
2160
|
+
sign. A consumer put a number on it — 39 procedures, team settings through role
|
|
2161
|
+
administration. So the two facts are compared once, after the startups have run,
|
|
2162
|
+
and a missing registration names the type and the procedures that demanded it.
|
|
2163
|
+
The commonest cause is a typo: the `resourceType` in a guard and the one in
|
|
2164
|
+
`defineResourcePolicy` are two strings, and nothing but that check compares them.
|
|
2165
|
+
|
|
2166
|
+
### The source sees the whole subject
|
|
2167
|
+
|
|
2168
|
+
`req.subject` is the caller, not just `req.subjectId`. That matters whenever a
|
|
2169
|
+
CREDENTIAL is narrower than the person holding it — an API key above all:
|
|
2170
|
+
|
|
2171
|
+
```ts
|
|
2172
|
+
setTupleSource(async (req) => {
|
|
2173
|
+
// A key minted for one team must not act on another. `req.subjectId` is the
|
|
2174
|
+
// OWNING USER, so a source reading only memberships passes an owner who
|
|
2175
|
+
// belongs to both teams.
|
|
2176
|
+
const boundTeam = req.subject.metadata?.teamId
|
|
2177
|
+
if (boundTeam !== undefined && boundTeam !== req.resourceId) return []
|
|
2178
|
+
return loadResourceTuples(store, req.subjectId, req.resourceType, req.resourceId)
|
|
2179
|
+
})
|
|
2180
|
+
```
|
|
2181
|
+
|
|
2182
|
+
Narrow it yourself: `Subject` is a union whose system and anonymous members carry
|
|
2183
|
+
no `metadata`. Without this a declared guard could not express the binding, so an
|
|
2184
|
+
app had to keep a hand-written check in the executor beside it — and a guard that
|
|
2185
|
+
must always run paired with a hand-written check is not a declaration.
|
|
2186
|
+
|
|
2157
2187
|
### Guards are re-checked on every subscription delivery
|
|
2158
2188
|
|
|
2159
2189
|
A subscription is a long-lived grant. Its guards — scope and relationship alike
|
|
@@ -33,7 +33,7 @@ The dispatcher routes `voltro <command> [args]` to the matching subcommand and p
|
|
|
33
33
|
| [Inspect & debug](/docs/cli/inspect) | `inspect`, `logs`, `traces`, `workflows`, `cluster`, `check` |
|
|
34
34
|
| [Health & surface](/docs/cli/build-and-start) | [`doctor`](/docs/cli/build-and-start) — serve preflight + the hand-roll detector (names the shipped primitive at the spot you're rebuilding it); [`capabilities`](/docs/cli/build-and-start) (`--json`) — the export surface read from your installed `@voltro/*`, so it can be verified instead of recalled; `info` (`--json`) — CLI / node / package-manager / dialect + every installed `@voltro/*` version, flagging lockstep skew (exits 1 on skew) |
|
|
35
35
|
| Harness | `test`, `e2e` |
|
|
36
|
-
| Cloud | `cloud` (`login` / `whoami` / `projects` / `env` / `import`) |
|
|
36
|
+
| Cloud | `cloud` (`login` / `whoami` / `projects` / `env` / `import`); `login` is a top-level alias of `cloud login` |
|
|
37
37
|
| Secrets | `secret` (`generate [purpose]` — the right var+format per secret; `generate` alone → a generic secret; `list`) |
|
|
38
38
|
| Meta | `agents-md`, `telemetry` (reports that Voltro collects none — no phone-home, nothing to opt out of), `version`, `help` |
|
|
39
39
|
|
|
@@ -44,7 +44,7 @@ to the reachable runtime set — the standalone Dockerfiles run it for you) and
|
|
|
44
44
|
version's codemods). Both are dispatchable; neither is something you invoke
|
|
45
45
|
directly.
|
|
46
46
|
|
|
47
|
-
Each command takes an optional path argument (the app directory) — defaults to `.` when run from inside an app. `voltro init` initialises the current directory as a workspace root — `pnpm-workspace.yaml`, a root `package.json` with `dev`/`build`/`test`/`typecheck`, a `.gitignore` and `git init`, idempotently and without scaffolding any apps (`voltro create-project <name>` does that, and bootstraps the same root when there isn't one). `voltro secret generate [purpose]` prints a cryptographically strong secret — with a purpose (`data-transfer`, `session`, `bundle-key`, `field-encryption`, `storage`, `inspect`) it emits the correct env var + length/format as a paste-ready `NAME=value` (`voltro secret list` shows them all); with no purpose, a generic base64url secret. `voltro telemetry` reports that Voltro collects none. `voltro deploy` shows the deploy paths — self-host via a [baseline](/docs/deployment/
|
|
47
|
+
Each command takes an optional path argument (the app directory) — defaults to `.` when run from inside an app. `voltro init` initialises the current directory as a workspace root — `pnpm-workspace.yaml`, a root `package.json` with `dev`/`build`/`test`/`typecheck`, a `.gitignore` and `git init`, idempotently and without scaffolding any apps (`voltro create-project <name>` does that, and bootstraps the same root when there isn't one). `voltro secret generate [purpose]` prints a cryptographically strong secret — with a purpose (`data-transfer`, `session`, `bundle-key`, `field-encryption`, `storage`, `inspect`) it emits the correct env var + length/format as a paste-ready `NAME=value` (`voltro secret list` shows them all); with no purpose, a generic base64url secret. `voltro telemetry` reports that Voltro collects none. `voltro deploy` shows the deploy paths — self-host via a [baseline](/docs/deployment/self-hosting) + CI, managed via the control-plane client `voltro cloud` (managed cloud deploy is coming soon — see [Voltro Cloud](/docs/deployment/voltro-cloud)), individual [serverless functions](/docs/deployment/serverless-functions) (`voltro serverless` → self-hosted Node, or Cloudflare / Scaleway), or a [static site](/docs/deployment/static-sites) (`voltro static` → Cloudflare Pages / S3 / Netlify).
|
|
48
48
|
|
|
49
49
|
## Help + version
|
|
50
50
|
|
|
@@ -620,7 +620,7 @@ is added with `voltro add-app`. Now `voltro list-templates` shows it; `voltro
|
|
|
620
620
|
create-project --web my-template` (or `--api`) uses it, and any kind is added
|
|
621
621
|
with `voltro add-app <name> --template my-template`.
|
|
622
622
|
|
|
623
|
-
For private templates (in your own repo), set `
|
|
623
|
+
For private templates (in your own repo), set `VOLTRO_TEMPLATES_DIR=/path/to/my/templates` and the CLI resolves templates from there instead of the default location. Point it at the templates **root** — the CLI appends `apps/`, so your templates live at `/path/to/my/templates/apps/<template-id>/`. When the variable is set it is authoritative: the CLI does not fall back to the bundled templates.
|
|
624
624
|
|
|
625
625
|
## Idempotency
|
|
626
626
|
|
|
@@ -1851,17 +1851,21 @@ voltro capabilities --json # the full machine-readable surface
|
|
|
1851
1851
|
```
|
|
1852
1852
|
|
|
1853
1853
|
```text
|
|
1854
|
-
voltro capabilities —
|
|
1855
|
-
@voltro/runtime@0.
|
|
1856
|
-
defineAggregate,
|
|
1857
|
-
@voltro/
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
*
|
|
1861
|
-
@voltro/
|
|
1854
|
+
voltro capabilities — 3856 exported symbols across 36 packages
|
|
1855
|
+
@voltro/runtime@0.38.0 — 12 primitives, 5 hooks, 100 components, 360 values, 388 types
|
|
1856
|
+
defineAggregate, defineConnection, defineCostBudget, defineEventTrigger, defineExecutor, …
|
|
1857
|
+
@voltro/database@0.38.0 — 3 primitives, 33 components, 333 values, 223 types
|
|
1858
|
+
defineMigration *, defineMixin, defineSeed *
|
|
1859
|
+
|
|
1860
|
+
* 9 primitive(s)/hook(s) appear nowhere in this project's agent guide:
|
|
1861
|
+
@voltro/database: defineMigration
|
|
1862
|
+
@voltro/plugin-flags: defineFlag
|
|
1862
1863
|
…
|
|
1863
1864
|
```
|
|
1864
1865
|
|
|
1866
|
+
The count is the packages **installed in that project**, not everything the
|
|
1867
|
+
framework publishes — a leaner app reports fewer.
|
|
1868
|
+
|
|
1865
1869
|
Every symbol reported was read out of an installed package a moment ago, so an
|
|
1866
1870
|
agent can **verify** the surface instead of recalling it. The `--json` form is
|
|
1867
1871
|
stable and locale-independent — the same tree produces byte-identical output on
|
|
@@ -2195,7 +2199,7 @@ gives the split no meaning.
|
|
|
2195
2199
|
|
|
2196
2200
|
A plugin mounting a non-GET inspect endpoint must also declare the
|
|
2197
2201
|
`inspect:write` permission, and the boot audit refuses it otherwise. That governs
|
|
2198
|
-
what a PLUGIN may mount; the write credential governs who may call it. The [Voltro Dashboard](/docs/observability/
|
|
2202
|
+
what a PLUGIN may mount; the write credential governs who may call it. The [Voltro Dashboard](/docs/observability/overview) consumes it to render the route sitemap, RPC list, subscription panel, workflow runs, and metrics. You can also hit the endpoints directly with `curl` (the `voltro inspect` subcommands above are the thin wrapper over exactly these).
|
|
2199
2203
|
|
|
2200
2204
|
```bash
|
|
2201
2205
|
PORT=4000 # from the app's app.config.ts
|
|
@@ -3785,4 +3789,4 @@ Emits the `globalEnv` / `globalPassThroughEnv` entries for `turbo.json`, so Turb
|
|
|
3785
3789
|
## Related
|
|
3786
3790
|
|
|
3787
3791
|
- [Secrets](/docs/cli/overview#common-env-vars) — generating secret values with `voltro secret`.
|
|
3788
|
-
- [Configuration](/docs/configuration) — declaring env vars with `envVar(...)`.
|
|
3792
|
+
- [Configuration](/docs/configuration/environment) — declaring env vars with `envVar(...)`.
|
|
@@ -970,7 +970,24 @@ const create = useMutation('app', 'notes.create')
|
|
|
970
970
|
await create.mutate({ title, body })
|
|
971
971
|
```
|
|
972
972
|
|
|
973
|
-
The client stages an optimistic patch, calls the server, then
|
|
973
|
+
The client stages an optimistic patch, calls the server, then retires the patch. Server-pushed deltas are still the source of truth.
|
|
974
|
+
|
|
975
|
+
**Retiring the patch has exactly two shapes, and they are not interchangeable:**
|
|
976
|
+
|
|
977
|
+
- **Rollback — only when the write FAILED.** The server did not write, so the
|
|
978
|
+
preview must go, immediately. Nothing else ever rolls a patch back: not a
|
|
979
|
+
timer, not an elapsed window, not a heuristic.
|
|
980
|
+
- **Hand-off — when the server's own state arrives and reflects the write.** A
|
|
981
|
+
delta always supersedes (it *is* the echo of committed writes); a fresh
|
|
982
|
+
snapshot supersedes only when it actually moved the base. Base gains the real
|
|
983
|
+
row and the placeholder goes in the same update, so there is no flash and no
|
|
984
|
+
optimistic+real duplicate.
|
|
985
|
+
|
|
986
|
+
If a confirmed write never gets its echo — reactivity is broken for that query's
|
|
987
|
+
source table — the client **re-issues the subscription and keeps the preview**,
|
|
988
|
+
and reports it on the error bus (visible in `voltro logs`). It does not fall back
|
|
989
|
+
to a base it knows does not reflect the write: a user watching their saved change
|
|
990
|
+
disappear will either redo it or plan on a state they believe was not stored.
|
|
974
991
|
|
|
975
992
|
For special shapes, override the patch:
|
|
976
993
|
|
|
@@ -1809,6 +1826,32 @@ first-paint optimization, never a correctness dependency. A failed preload is
|
|
|
1809
1826
|
likewise non-fatal — the live subscription still delivers the value on the
|
|
1810
1827
|
client, the only loss is the first-paint seed.
|
|
1811
1828
|
|
|
1829
|
+
### `preloadFailed` — "no data" vs "could not get data"
|
|
1830
|
+
|
|
1831
|
+
A preload that FAILED server-side and one that was never declared arrive the same
|
|
1832
|
+
way: as the absence of a seed. That makes an empty first paint ambiguous, and the
|
|
1833
|
+
ambiguity is not academic — a session cookie that has outlived the IdP's token
|
|
1834
|
+
lifetime makes EVERY preload on the page fail at once, so the page renders its
|
|
1835
|
+
empty state while the server log holds the only explanation.
|
|
1836
|
+
|
|
1837
|
+
`preloadFailed` separates the two:
|
|
1838
|
+
|
|
1839
|
+
```tsx
|
|
1840
|
+
const projects = usePreloadedSubscription<Project[]>('app', 'projects.list')
|
|
1841
|
+
|
|
1842
|
+
if (projects.loading) return <Skeleton/>
|
|
1843
|
+
if (projects.preloadFailed) return <Spinner label="Loading…"/> // not empty — unasked
|
|
1844
|
+
return <ProjectTable rows={projects.data}/>
|
|
1845
|
+
```
|
|
1846
|
+
|
|
1847
|
+
It is a boolean and says nothing about WHY. The server's failure text is a
|
|
1848
|
+
refused call's error message; it belongs in the server log, which is the one
|
|
1849
|
+
place a browser cannot read. It also says nothing about the LIVE subscription,
|
|
1850
|
+
which usually recovers on its own — the browser reconnects with a credential the
|
|
1851
|
+
SSR request did not have. Read it as "the first paint has no server data, and
|
|
1852
|
+
that was not for lack of asking", which is exactly enough to pick a spinner over
|
|
1853
|
+
an empty state.
|
|
1854
|
+
|
|
1812
1855
|
### Seeding by hand
|
|
1813
1856
|
|
|
1814
1857
|
`export const preload` is sugar over an explicit seed. When a loader ALREADY has
|
|
@@ -1835,7 +1835,7 @@ The token is the same one the remote app boots with:
|
|
|
1835
1835
|
VOLTRO_INSPECT_TOKEN=<secret> voltro start
|
|
1836
1836
|
```
|
|
1837
1837
|
|
|
1838
|
-
See [Introspection](/docs/
|
|
1838
|
+
See [Introspection](/docs/cli/inspect) for the full auth
|
|
1839
1839
|
configuration.
|
|
1840
1840
|
|
|
1841
1841
|
## URL shape
|
|
@@ -1861,7 +1861,7 @@ appends it. The trailing-slash variant works too.
|
|
|
1861
1861
|
|
|
1862
1862
|
- [Migration overview](/docs/database/migrations) — the
|
|
1863
1863
|
plan/apply lifecycle this slots into
|
|
1864
|
-
- [Introspection](/docs/
|
|
1864
|
+
- [Introspection](/docs/cli/inspect) — the
|
|
1865
1865
|
`/_voltro/inspect/*` surface this command consumes
|
|
1866
1866
|
- [Drift detection](/docs/database/migrations/drift) — fingerprint-based
|
|
1867
1867
|
drift surfacing the same inspect endpoint emits
|
|
@@ -1043,7 +1043,7 @@ MariaDB's GTID format differs from MySQL's: `0-1-100` (domain-server-sequence) v
|
|
|
1043
1043
|
- **`mariadb` schema package is wire-compatible with `mysql`**. If you migrate from MySQL → MariaDB, the framework re-emits DDL cleanly via `applySchema(..., 'mariadb')`. Production data round-trips through `mysqldump` without translation.
|
|
1044
1044
|
- **`sql_mode=NO_BACKSLASH_ESCAPES`** is sometimes set on MariaDB deploys. The framework's identifier escaping handles it, but user-written `unsafe()` strings that hand-escape backslashes may produce wrong output. Leave that mode off if you can.
|
|
1045
1045
|
- **Sequence-based ID columns**. MariaDB has true CREATE SEQUENCE; the framework doesn't use it (TypeID / ULID / Snowflake are client-side). If you reach for sequences for legacy reasons, they're outside the framework's auto-injection path.
|
|
1046
|
-
- **Hand-rolled `AUTO_INCREMENT` primary keys** work the same as on mysql: an `insert` / `insertMany` with no client-side `id` recovers the DB-generated id via `LAST_INSERT_ID()` (connection-pinned; `insertMany` recovers the whole consecutive range). See the [mysql page](/docs/
|
|
1046
|
+
- **Hand-rolled `AUTO_INCREMENT` primary keys** work the same as on mysql: an `insert` / `insertMany` with no client-side `id` recovers the DB-generated id via `LAST_INSERT_ID()` (connection-pinned; `insertMany` recovers the whole consecutive range). See the [mysql page](/docs/database/dialects/mysql#auto_increment-ids--last_insert_id-recovery) for the worked example — the recovery path is identical on both engines.
|
|
1047
1047
|
|
|
1048
1048
|
## Where it lives
|
|
1049
1049
|
|
|
@@ -1080,7 +1080,7 @@ SQL Server 2016 / 2017 work for the basic workflow path; some performance charac
|
|
|
1080
1080
|
```sh
|
|
1081
1081
|
DB_DIALECT=mssql
|
|
1082
1082
|
DB_URL=mssql://sa:<password>@localhost:11433/voltro_test
|
|
1083
|
-
# or discrete fields: DB_DIALECT + DB_HOST / DB_PORT / DB_USER / DB_PASSWORD /
|
|
1083
|
+
# or discrete fields: DB_DIALECT + DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_DATABASE
|
|
1084
1084
|
|
|
1085
1085
|
# Local Docker dev fixture defaults:
|
|
1086
1086
|
# container: mcr.microsoft.com/mssql/server:2022-latest
|
|
@@ -1248,21 +1248,35 @@ those do not come out of the pool budget, they come out of the DATABASE's.
|
|
|
1248
1248
|
|
|
1249
1249
|
Set `REPLICA_COUNT` from your deployment (Helm: `{{ .Values.replicaCount }}`) and
|
|
1250
1250
|
the line does the multiplication for you; without it the line still names the
|
|
1251
|
-
formula.
|
|
1251
|
+
formula.
|
|
1252
|
+
|
|
1253
|
+
**`voltro dev` prints it too, when the environment says it is not a laptop.**
|
|
1254
|
+
A bare `voltro dev` stays silent — one process, no replicas, nothing to
|
|
1255
|
+
multiply. But `voltro dev` is a supported way to RUN an app, and a deployment
|
|
1256
|
+
that uses it needs this line as much as any other. So it prints whenever
|
|
1257
|
+
`REPLICA_COUNT`, `DB_MAX_CONNECTIONS` / `PG_MAX_CONNECTIONS`, or
|
|
1258
|
+
`DB_REPLICA_URLS` is set — each of which means somebody has already decided
|
|
1259
|
+
something about the number.
|
|
1252
1260
|
|
|
1253
1261
|
**Some connections are not in the pool, and the count is per process.** A
|
|
1254
|
-
connection
|
|
1255
|
-
standalone one. There are
|
|
1256
|
-
|
|
1262
|
+
connection that speaks a long-lived protocol cannot be returned to a pool, so
|
|
1263
|
+
the driver opens a standalone one. There are four such places and a full
|
|
1264
|
+
deployment can hold several at once:
|
|
1257
1265
|
|
|
1258
1266
|
| Process | Connection | When |
|
|
1259
1267
|
|---|---|---|
|
|
1260
|
-
| api `voltro serve` | CDC `LISTEN` consumer | `changeStrategy: 'cdc'` (the default
|
|
1268
|
+
| api `voltro serve` / `dev` | CDC `LISTEN` consumer | postgres, `changeStrategy: 'cdc'` (the default) |
|
|
1269
|
+
| api `voltro serve` / `dev` | binlog CDC reader | mysql / mariadb, `changeStrategy: 'cdc'` |
|
|
1261
1270
|
| web `voltro start` | ISR invalidator `LISTEN` | any page declares `cacheInvalidatesOn` |
|
|
1262
1271
|
| web `voltro start` | postgres ISR cache client | `SSR_CACHE=postgres` |
|
|
1263
1272
|
|
|
1264
|
-
|
|
1265
|
-
|
|
1273
|
+
SQL Server is the one CDC dialect that costs nothing here: Change Tracking is
|
|
1274
|
+
read with ordinary queries through the pool, so its out-of-pool count is a
|
|
1275
|
+
verified zero rather than an omission.
|
|
1276
|
+
|
|
1277
|
+
Two of the four are not a `LISTEN` at all — the binlog reader speaks the
|
|
1278
|
+
replication protocol, and the ISR cache client is an ordinary client — which is
|
|
1279
|
+
why counting `LISTEN` rows in `pg_stat_activity` undercounts. Each process prints its own number in the boot
|
|
1266
1280
|
line above — including `No connections outside the pool in this process` when
|
|
1267
1281
|
there are none, so "counted, zero" is distinguishable from "not counted".
|
|
1268
1282
|
|
|
@@ -838,9 +838,16 @@ program.pipe(withTimezone('Europe/Berlin'))
|
|
|
838
838
|
```
|
|
839
839
|
|
|
840
840
|
`currentTimezone` never fails — an absent context is the documented `UTC`
|
|
841
|
-
default, so call sites don't handle a missing-service error.
|
|
842
|
-
|
|
843
|
-
|
|
841
|
+
default, so call sites don't handle a missing-service error.
|
|
842
|
+
|
|
843
|
+
> **What ships today is the SEAM, not the wiring.** `@voltro/datetime/context`
|
|
844
|
+
> exports `currentTimezone`, `withTimezone` and `resolvedTimezoneLayer`, and you
|
|
845
|
+
> provide the layer yourself. The framework does **not** yet install it per
|
|
846
|
+
> request, and there is **no `useTimezone()` hook** in the web layer — both are
|
|
847
|
+
> planned to land in `@voltro/runtime` + `@voltro/web`. Until then: resolve the
|
|
848
|
+
> zone yourself (`resolveTimezone`) and provide `resolvedTimezoneLayer` around
|
|
849
|
+
> the work that needs it, or pass an explicit `timeZone` argument. Without a
|
|
850
|
+
> provided layer every call reads the `UTC` default.
|
|
844
851
|
|
|
845
852
|
## Arithmetic — the DST split is in the names
|
|
846
853
|
|