@voltro/cli 0.51.0 → 0.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +356 -0
- package/THIRD-PARTY-NOTICES.md +8311 -3318
- package/dist/{agentsMd-D6yD7IQv.js → agentsMd-0l980yhL.js} +4 -1
- package/dist/agentsMd-SDDSkyl4.js +2 -0
- package/dist/{apiBuild-CPDHXF72.js → apiBuild-CaPfoWku.js} +11 -5
- package/dist/apiBuild-DHtLXYx9.js +2 -0
- package/dist/bin.js +1 -1
- package/dist/build-D-OnvNMf.js +843 -0
- package/dist/{checkCommand-DNuPiWMc.js → checkCommand-C5elt0tW.js} +92 -46
- package/dist/checkCommand-D2ZduVlh.js +2 -0
- package/dist/{cloudCmd-F4YJeqM3.js → cloudCmd-QUXh-b5w.js} +1 -1
- package/dist/codegen-BWpt3VgF.js +2 -0
- package/dist/{codegen-CrMXs4hb.js → codegen-FEk8AZHb.js} +2 -2
- package/dist/{codegenCommand-BNBHcNNj.js → codegenCommand-BOiWQ5hz.js} +12 -12
- package/dist/{codemodRunner-BDVixlSw.js → codemodRunner-BjtB2lq6.js} +691 -545
- package/dist/{commands-B1OiS9bX.js → commands-DyxAmhP0.js} +36 -36
- package/dist/{dashboardCommand-C-vvPY1B.js → dashboardCommand-BdKTyT13.js} +3 -3
- package/dist/{dataCommand-C1GxXW5q.js → dataCommand-Bab9X7s8.js} +27 -27
- package/dist/{dbCommand-If4Y1xQ-.js → dbCommand-06O2finM.js} +277 -236
- package/dist/dbCommand-B1EXBC6f.js +2 -0
- package/dist/{dev-kdAg9Q7l.js → dev-C6LGF4iY.js} +2998 -2379
- package/dist/dev-GjJWAYo2.js +3 -0
- package/dist/doctorCommand-B0hX0tdz.js +2 -0
- package/dist/{doctorCommand-nKmeW78u.js → doctorCommand-etMkflRc.js} +332 -220
- package/dist/{dormancyCommand-CY3wa_SW.js → dormancyCommand-UwZ1AZzB.js} +1 -1
- package/dist/{embeddingsCommand-BDLIgje_.js → embeddingsCommand-C70zWHwo.js} +1 -1
- package/dist/{envCommand-C6V_xVlT.js → envCommand-dSyKvRkM.js} +15 -15
- package/dist/{evolveCommand-D3c4DSfN.js → evolveCommand-CG0_ebO5.js} +2 -2
- package/dist/fileConventions-DASGEmj-.js +35 -0
- package/dist/{fileTaxonomy-CJfgOllU.js → fileTaxonomy-B7uxipWS.js} +55 -55
- package/dist/fontPipeline-LxIHa1vo.js +2 -0
- package/dist/fontPipeline-Tsh8kZfA.js +152 -0
- package/dist/frameworkTableAssembly-C_7Z-rMs.js +2 -0
- package/dist/{frameworkTableAssembly-BwJVEKLr.js → frameworkTableAssembly-DKx3ba3S.js} +5 -5
- package/dist/imagePipeline-B_GVJgm6.js +2 -0
- package/dist/imagePipeline-CBZmjT4i.js +127 -0
- package/dist/index.js +1 -1
- package/dist/{infoCommand-BnRFEF1o.js → infoCommand-_53iOc_j.js} +1 -1
- package/dist/{inspect-CtL_xTbu.js → inspect-Bd8-9wsi.js} +1 -1
- package/dist/inspect-CuoDInfZ.js +2 -0
- package/dist/{inspectGateHint-BjnFubmH.js → inspectGateHint-4LxkNtrz.js} +1 -1
- package/dist/inspectMetrics-CGF94puw.js +143 -0
- package/dist/manifestBuild-C4-J1-m_.js +2 -0
- package/dist/{manifestBuild-CuU1VrSm.js → manifestBuild-Cqgsx2bM.js} +1 -1
- package/dist/{metaCommands-CfRLra0s.js → metaCommands-Cn2oboG4.js} +9 -3
- package/dist/{migrate-DehuBakM.js → migrate-Cko9rswM.js} +2 -2
- package/dist/{pageConvention-cEiRxdab.js → pageConvention-C938S8oC.js} +1 -1
- package/dist/{privacyCommand-XejDMvmu.js → privacyCommand-DWTQMC6R.js} +2 -2
- package/dist/{probeCommand-C9gazU0H.js → probeCommand-DkGGLknv.js} +83 -24
- package/dist/{projectScaffold-mIX_DpSe.js → projectScaffold-B4dmTlwT.js} +1 -1
- package/dist/{projectScaffold-BIl97_E6.js → projectScaffold-EzlErR4E.js} +1 -1
- package/dist/{renderModeScan-D7J1B7Kw.js → renderModeScan-CUbOeOAg.js} +28 -11
- package/dist/{renderProfile-1OWWAAtx.js → renderProfile-CskIgAfn.js} +2 -2
- package/dist/{runtimeTrace-ZsBU7Tkx.js → runtimeTrace-c0APJz7E.js} +1 -1
- package/dist/{sdkgen-O4XqWOjM.js → sdkgen-BiQCgIEr.js} +1 -1
- package/dist/serveCommand-CueKQgzl.js +2443 -0
- package/dist/serveCommand-DsnrVN3U.js +2 -0
- package/dist/serveEntry.js +1 -1
- package/dist/start-BJzZLbt8.js +3 -0
- package/dist/start-ekPan8BT.js +1510 -0
- package/dist/startEntry.js +1 -1
- package/dist/{staticCommand-Dr2M6tpU.js → staticCommand-xlSL-IWk.js} +1 -1
- package/dist/{test-rXFq4S76.js → test-BWPQcRoB.js} +1 -1
- package/dist/updateCommand-Bqql_rsQ.js +2 -0
- package/dist/{updateCommand-Bs322Q78.js → updateCommand-C_8I8Rzo.js} +139 -115
- package/dist/webDev-C7jWJ5dX.js +2 -0
- package/dist/{webDev-B-ubQEMX.js → webDev-oczpugbx.js} +1767 -913
- package/dist/{webhooksCommand-FLYY9IXh.js → webhooksCommand-4SVPDjKg.js} +1 -1
- package/package.json +72 -18
- package/templates/AGENTS.core.md +11 -0
- package/templates/AGENTS.md +19 -6
- package/templates/agent-docs/_index.md +8 -6
- package/templates/agent-docs/_manifest.json +31 -15
- package/templates/agent-docs/ai.md +2 -2
- package/templates/agent-docs/authentication.md +1 -1
- package/templates/agent-docs/cli.md +97 -15
- package/templates/agent-docs/configuration.md +17 -0
- package/templates/agent-docs/data.md +680 -33
- package/templates/agent-docs/database/advancedqueries.md +7 -7
- package/templates/agent-docs/database/columntypes.md +2 -2
- package/templates/agent-docs/database/querying.md +1 -1
- package/templates/agent-docs/database/schema.md +2 -2
- package/templates/agent-docs/database/seedsdialects.md +2 -2
- package/templates/agent-docs/database/transactions.md +3 -3
- package/templates/agent-docs/deployment.md +30 -3
- package/templates/agent-docs/internationalization.md +2 -2
- package/templates/agent-docs/introduction.md +52 -0
- package/templates/agent-docs/local-first-mobile.md +132 -7
- package/templates/agent-docs/observability.md +2 -0
- package/templates/agent-docs/plugins/ai-flows.md +1 -1
- package/templates/agent-docs/plugins/audit.md +5 -5
- package/templates/agent-docs/plugins/auth.md +1 -1
- package/templates/agent-docs/plugins/cdc-out.md +2 -2
- package/templates/agent-docs/plugins/comments.md +142 -0
- package/templates/agent-docs/plugins/notifications.md +47 -4
- package/templates/agent-docs/plugins/presence.md +16 -3
- package/templates/agent-docs/plugins/prometheus.md +1 -1
- package/templates/agent-docs/plugins/queue.md +129 -0
- package/templates/agent-docs/plugins/{versioning.md → row-history.md} +22 -22
- package/templates/agent-docs/plugins/storage.md +2 -2
- package/templates/agent-docs/plugins.md +38 -12
- package/templates/agent-docs/reference.md +54 -5
- package/templates/agent-docs/routing.md +868 -50
- package/templates/agent-docs/schema-driven-ui.md +292 -5
- package/templates/agent-docs/security.md +125 -8
- package/templates/agent-docs/templates/apibackends.md +14 -14
- package/templates/agent-docs/templates/overview.md +1 -1
- package/templates/agent-docs/whats-new.md +171 -54
- package/templates/apps/api-ai/package.json +6 -7
- package/templates/apps/api-ai/tests/summarize.test.ts +1 -1
- 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 -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/package.json +8 -8
- package/templates/apps/api-rest/package.json +7 -7
- package/templates/apps/{api-versioning → api-row-history}/README.md +3 -3
- package/templates/apps/{api-versioning → api-row-history}/actions/documents.asOf.action.server.ts +1 -1
- package/templates/apps/{api-versioning → api-row-history}/actions/documents.history.action.server.ts +1 -1
- package/templates/apps/{api-versioning → api-row-history}/app.config.ts +3 -3
- package/templates/apps/{api-versioning → api-row-history}/database/schema.ts +1 -1
- package/templates/apps/{api-versioning → api-row-history}/mutations/documents.create.mutation.server.ts +1 -1
- package/templates/apps/{api-versioning → api-row-history}/mutations/documents.create.mutation.ts +1 -1
- package/templates/apps/{api-versioning → api-row-history}/mutations/documents.update.mutation.ts +1 -1
- package/templates/apps/{api-versioning → api-row-history}/package.json +8 -8
- package/templates/apps/api-row-history/template.json +6 -0
- package/templates/apps/{api-versioning → api-row-history}/tests/documents.create.test.ts +1 -1
- package/templates/apps/api-saas/app.config.ts +1 -0
- package/templates/apps/api-saas/package.json +10 -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/app.config.ts +26 -2
- package/templates/apps/changelog/content/releases/{0.1.0.mdx → v0-1-0.mdx} +0 -1
- package/templates/apps/changelog/content/releases/{0.2.0.mdx → v0-2-0.mdx} +0 -1
- package/templates/apps/changelog/package.json +8 -8
- package/templates/apps/changelog/src/collections/releases.collection.ts +48 -0
- package/templates/apps/changelog/src/globals.d.ts +1 -1
- package/templates/apps/changelog/src/locales/de.ts +1 -1
- package/templates/apps/changelog/src/locales/en.ts +1 -1
- package/templates/apps/changelog/src/pages/[locale]/[slug]/page.tsx +7 -4
- package/templates/apps/changelog/src/pages/[locale]/mirrors.test.tsx +13 -41
- package/templates/apps/changelog/src/pages/[slug]/page.test.tsx +26 -51
- package/templates/apps/changelog/src/pages/[slug]/page.tsx +21 -19
- package/templates/apps/changelog/src/pages/page.test.tsx +14 -37
- package/templates/apps/changelog/src/pages/page.tsx +18 -12
- 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-collab/src/pages/page.test.tsx +10 -9
- package/templates/apps/frontend-collab/src/pages/page.tsx +42 -65
- package/templates/apps/frontend-contact/package.json +7 -7
- package/templates/apps/frontend-dashboard/package.json +7 -7
- package/templates/apps/frontend-docs/content/docs/de/guides/first-page.md +4 -0
- package/templates/apps/frontend-docs/content/docs/de/intro/getting-started.md +4 -0
- package/templates/apps/frontend-docs/content/docs/en/guides/first-page.md +4 -0
- package/templates/apps/frontend-docs/content/docs/en/intro/getting-started.md +4 -0
- package/templates/apps/frontend-docs/package.json +8 -7
- package/templates/apps/frontend-docs/src/collections/docs.collection.ts +21 -0
- package/templates/apps/frontend-docs/src/locales/de.ts +0 -5
- package/templates/apps/frontend-docs/src/locales/en.ts +0 -5
- package/templates/apps/frontend-docs/src/pages/[locale]/docs/[...slug]/page.tsx +17 -9
- package/templates/apps/frontend-docs/src/pages/[locale]/mirrors.test.tsx +10 -5
- package/templates/apps/frontend-docs/src/pages/[locale]/page.tsx +8 -0
- package/templates/apps/frontend-docs/src/pages/docs/[...slug]/page.test.tsx +53 -15
- package/templates/apps/frontend-docs/src/pages/docs/[...slug]/page.tsx +27 -33
- package/templates/apps/frontend-docs/src/pages/page.test.tsx +17 -3
- package/templates/apps/frontend-docs/src/pages/page.tsx +16 -12
- package/templates/apps/frontend-i18n/package.json +6 -6
- package/templates/apps/frontend-landing/package.json +6 -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/content/posts/cms-to-ssg.md +12 -0
- package/templates/apps/frontend-static-blog/content/posts/hello-static.md +12 -0
- package/templates/apps/frontend-static-blog/content/posts/islands-not-hydration.md +14 -0
- package/templates/apps/frontend-static-blog/package.json +8 -6
- package/templates/apps/frontend-static-blog/src/collections/posts.collection.ts +27 -0
- package/templates/apps/frontend-static-blog/src/pages/[locale]/blog/[slug]/page.tsx +7 -4
- package/templates/apps/frontend-static-blog/src/pages/[locale]/mirrors.test.tsx +7 -1
- package/templates/apps/frontend-static-blog/src/pages/blog/[slug]/page.test.tsx +19 -9
- package/templates/apps/frontend-static-blog/src/pages/blog/[slug]/page.tsx +19 -21
- package/templates/apps/frontend-static-blog/src/pages/page.test.tsx +18 -5
- package/templates/apps/frontend-static-blog/src/pages/page.tsx +21 -14
- package/templates/apps/frontend-status/package.json +8 -8
- package/templates/apps/mobile-app/package.json +4 -4
- package/dist/agentsMd-Bu_XQgVf.js +0 -2
- package/dist/apiBuild-GDKuGOMV.js +0 -2
- package/dist/build-DETLZAFt.js +0 -752
- package/dist/checkCommand-CWcnDArJ.js +0 -2
- package/dist/codegen-DiMn2KkZ.js +0 -2
- package/dist/dbCommand-C27HIsGE.js +0 -2
- package/dist/dev-CK522MV5.js +0 -3
- package/dist/doctorCommand-BK4l18eG.js +0 -2
- package/dist/fileConventions-Cof68_BL.js +0 -33
- package/dist/frameworkTableAssembly-CVDB2hCq.js +0 -2
- package/dist/inspect-CuGDYES0.js +0 -2
- package/dist/inspectMetrics-CfdKLh6t.js +0 -72
- package/dist/manifestBuild-CPjhvM62.js +0 -2
- package/dist/serveCommand-BRnPCxVd.js +0 -2
- package/dist/serveCommand-DdiYNBBu.js +0 -2362
- package/dist/start-BLNmWkLa.js +0 -1154
- package/dist/start-Dzicuyw8.js +0 -3
- package/dist/updateCommand-eXB35SEv.js +0 -2
- package/dist/webDev-DposiF3j.js +0 -2
- package/templates/apps/api-versioning/template.json +0 -6
- package/templates/apps/changelog/scripts/generate-rss.mjs +0 -38
- package/templates/apps/changelog/src/lib/releases.ts +0 -21
- package/templates/apps/frontend-static-blog/src/content/posts.ts +0 -64
- /package/templates/apps/{api-versioning → api-row-history}/actions/documents.asOf.action.ts +0 -0
- /package/templates/apps/{api-versioning → api-row-history}/actions/documents.history.action.ts +0 -0
- /package/templates/apps/{api-versioning → api-row-history}/mutations/documents.update.mutation.server.ts +0 -0
- /package/templates/apps/{api-versioning → api-row-history}/tsconfig.json +0 -0
|
@@ -27,7 +27,7 @@ The framework ships some plugins; you write your own; the contract is small enou
|
|
|
27
27
|
- [plugin-billing](/docs/plugins/billing) — subscriptions, plans, entitlements + usage metering (Stripe + mock provider); seat-based billing on Stripe's own proration, retries, tax and checkout; money as integer minor units
|
|
28
28
|
- [plugin-licensing](/docs/plugins/licensing) — offline-verified EdDSA license keys + cloud-issued entitlement snapshots that feed plugin-billing; plan entitlements + pricing decided server-side, never baked into a published version
|
|
29
29
|
- [plugin-mail](/docs/plugins/mail) — transactional email (Resend / Postmark / SendGrid / SES / Mailgun / SMTP, templates, suppression, scheduling, batch, idempotency)
|
|
30
|
-
- [plugin-storage](/docs/plugins/storage) — file storage: public (CDN-direct) + private (access policy + per-object grants), S3 / R2
|
|
30
|
+
- [plugin-storage](/docs/plugins/storage) — file storage: public (CDN-direct) + private (access policy + per-object grants), S3 / MinIO (R2 and GCS via their S3 interop) / Azure / database / filesystem
|
|
31
31
|
- [plugin-ai-flows](/docs/plugins/ai-flows) — durable multi-step AI pipelines (deterministic + agentic) with human-in-the-loop, chaining, and cadence; code-first `defineFlow` or data-driven rows
|
|
32
32
|
- [plugin-postgis](/docs/plugins/postgis) — postgres-native `geography` / `geometry` columns + spatial operators
|
|
33
33
|
- [plugin-broadcast](/docs/plugins/broadcast) — cross-replica reactivity over a pub/sub bus (Redis / NATS) for non-postgres dialects
|
|
@@ -42,10 +42,12 @@ The framework ships some plugins; you write your own; the contract is small enou
|
|
|
42
42
|
- [plugin-logship](/docs/plugins/logship) — ship structured logs to Better Stack / Axiom / Loki / any HTTP sink; batched, redacted, fail-soft
|
|
43
43
|
- [plugin-moderation](/docs/plugins/moderation) — moderate user content before commit: keyword or AI provider, block / flag via interceptor + in-handler redact
|
|
44
44
|
- [plugin-search](/docs/plugins/search) — keep an external index (Typesense / Meilisearch / Algolia) in sync via the ChangeEvent tap; tenant-scoped `search.query` + hook
|
|
45
|
-
- [plugin-cdc-out](/docs/plugins/cdc-out) — declarative reverse-ETL: mirror table changes outward to a webhook
|
|
45
|
+
- [plugin-cdc-out](/docs/plugins/cdc-out) — declarative reverse-ETL: mirror table changes outward to a webhook or Kafka sink (or any custom `CdcSink`) through a durable outbox; ordered per pipe, at-least-once from enqueue, dead-lettered
|
|
46
|
+
- [plugin-queue](/docs/plugins/queue) — Kafka interop: Schema-decoded consumers (`*.consumer.ts`; at-least-once, serial per partition, retry + dead-letter), batched producing via a service or transactionally through the outbox, and a `kafkaSink` for cdc-out
|
|
47
|
+
- [plugin-comments](/docs/plugins/comments) — comment threads on any app entity: replies, resolve/reopen, tenant-safe @-mentions with notifications, reactions, unread — live over the reactive engine, with the ejectable `<CommentsThread>` UI
|
|
46
48
|
- [plugin-governance](/docs/plugins/governance) — data governance: retention TTL sweep, GDPR export + erasure, consent ledger, field encryption
|
|
47
49
|
- [plugin-openapi](/docs/plugins/openapi) — OpenAPI 3.1 spec + Swagger-UI docs generated from your `defineRestRoute` descriptors and (opt-in) rpc procedures
|
|
48
|
-
- [plugin-
|
|
50
|
+
- [plugin-row-history](/docs/plugins/row-history) — full row history + time-travel (`rowHistory` / `rowAsOf` / `restoreAsOf` / `diffVersions`); what-changed-to-what on every write
|
|
49
51
|
- [plugin-presence](/docs/plugins/presence) — ephemeral realtime presence: heartbeat roster per channel + `usePresence` / `useTyping` hooks, held in memory; cross-instance with [plugin-broadcast](/docs/plugins/broadcast)
|
|
50
52
|
- [plugin-auth-social](/docs/plugins/auth-social) — first-party Sign in with Google / GitHub / Apple: mandatory PKCE + state, JWKS-verified ID tokens, a deliberate account-linking policy, sessions issued through plugin-auth
|
|
51
53
|
- [plugin-scim](/docs/plugins/scim) — SCIM 2.0 provisioning (Users + Groups at `/scim/v2`) so an enterprise IdP can create/deactivate users
|
|
@@ -70,17 +72,19 @@ Status legend: ✓ shipped · ◐ partial · — planned.
|
|
|
70
72
|
| `@voltro/plugin-licensing` | ✓ | Offline-verified EdDSA license keys + cloud-issued entitlement snapshots that feed plugin-billing; plan entitlements + pricing decided server-side, never baked into a published version. [→ details](/docs/plugins/licensing) |
|
|
71
73
|
| `@voltro/plugin-ai-flows` | ✓ | Durable multi-step AI pipelines — deterministic or agentic, with human-in-the-loop, chaining and cadence; author flows in code (`defineFlow`) or as data (visual-editor rows), one engine runs both. [→ details](/docs/plugins/ai-flows) |
|
|
72
74
|
| `@voltro/plugin-mail` | ✓ | Transactional email — Resend / Postmark / SendGrid / SES / Mailgun / SMTP, *.email.tsx templates, per-tenant suppression, send-time scheduling, bulk/batch send, per-send idempotency, durable via workflows |
|
|
73
|
-
| `@voltro/plugin-storage` | ✓ | File storage — public (CDN-direct) + private (access policy + per-object grants), S3 / R2
|
|
75
|
+
| `@voltro/plugin-storage` | ✓ | File storage — public (CDN-direct) + private (access policy + per-object grants), S3 / MinIO (R2 and GCS via their S3 interop) / Azure / database / filesystem providers, presigned URLs, `listRefs` browse/search, HTTP Range (206) serving, dashboard browser |
|
|
74
76
|
| `@voltro/plugin-postgis` | ✓ | Postgres-native `geography` / `geometry` columns + spatial predicates (`ST_DWithin`, `ST_Contains`, `ST_Intersects`); GiST indexes via `.expressionIndex(..., { kind: 'gist' })`. No `ST_Distance` projection yet. Postgres-only by design (fails loud elsewhere). [→ details](/docs/plugins/postgis) |
|
|
75
77
|
| `@voltro/plugin-broadcast` | ✓ | Cross-replica reactivity — fans out app-mutation change events to every replica over a pub/sub bus (Redis / NATS). Closes the single-instance gap for every non-postgres dialect. [→ details](/docs/plugins/broadcast) |
|
|
76
78
|
| `@voltro/plugin-webhooks` | ✓ | Incoming + outgoing webhooks — `defineIncomingWebhook` (signature verify + idempotency, Stripe/GitHub/Slack presets) and `defineEvent` (durable delivery workflow, HMAC signing, retries, filters). [→ details](/docs/plugins/webhooks) |
|
|
79
|
+
| `@voltro/plugin-comments` | ✓ | Comment threads anchored to any entity — fail-closed access delegation (`viaEntity`/`scope`), replies, resolve/reopen, tenant-safe mentions (validated twice, delivered via plugin-notifications incl. digests), reactions, per-subject unread, live `comments.list`, `<CommentsThread>` in `@voltro/ui`. [→ details](/docs/plugins/comments) |
|
|
80
|
+
| `@voltro/plugin-queue` | ✓ | Kafka interop — `defineQueueConsumer` (`*.consumer.ts`, Schema-decoded, at-least-once, serial per partition, retry + DLQ with reason headers), batched producing via `QueueService` or transactionally through the outbox (`queueOutboxHandler`), `kafkaSink` for cdc-out, per-topic counters in the dashboards. [→ details](/docs/plugins/queue) |
|
|
77
81
|
| `@voltro/plugin-auth-social` | ✓ | First-party social login — Sign in with Google / GitHub / Apple with no identity vendor: authorize URL + code exchange + JWKS-verified ID tokens, mandatory PKCE (S256) and `state`, an explicit account-linking policy (`never` by default), Apple's signed-JWT client secret / one-time name / private-relay email all handled; sessions via `issueUserSession`. [→ details](/docs/plugins/auth-social) |
|
|
78
82
|
| `@voltro/plugin-auth-{workos,kinde,clerk,auth0,supabase,oidc}` | ✓ | Six IdP adapters over the shared `jwtBearerStrategy` — JWKS verify + claims→tenant mapping; WorkOS additionally ships hosted-login OAuth primitives (`workosAuthorizationUrl` / `workosAuthenticateWithCode`) for a redirect-based SSO login flow. [→ details](/docs/authentication/external-idp) |
|
|
79
|
-
| `@voltro/plugin-analytics-postgres` | ✓ | First-party lite — events on the main DataStore, cross-dialect (postgres / mysql / mariadb / mssql / sqlite / turso). [→ details](/docs/plugins/analytics
|
|
80
|
-
| `@voltro/plugin-duckdb` | ✓ | Embedded DuckDB sidecar — real OLAP performance, no external service. [→ details](/docs/plugins/analytics
|
|
81
|
-
| `@voltro/plugin-clickhouse` | ✓ | Production OLAP via the official ClickHouse client. [→ details](/docs/plugins/analytics
|
|
82
|
-
| `@voltro/plugin-tinybird` | ✓ | Hosted ClickHouse via Events API + Pipes. [→ details](/docs/plugins/analytics
|
|
83
|
-
| `@voltro/plugin-posthog` | ✓ | Product analytics — track-only; compose with another sink for reads. [→ details](/docs/plugins/analytics
|
|
83
|
+
| `@voltro/plugin-analytics-postgres` | ✓ | First-party lite — events on the main DataStore, cross-dialect (postgres / mysql / mariadb / mssql / sqlite / turso). [→ details](/docs/plugins/analytics) |
|
|
84
|
+
| `@voltro/plugin-duckdb` | ✓ | Embedded DuckDB sidecar — real OLAP performance, no external service. [→ details](/docs/plugins/analytics) |
|
|
85
|
+
| `@voltro/plugin-clickhouse` | ✓ | Production OLAP via the official ClickHouse client. [→ details](/docs/plugins/analytics) |
|
|
86
|
+
| `@voltro/plugin-tinybird` | ✓ | Hosted ClickHouse via Events API + Pipes. [→ details](/docs/plugins/analytics) |
|
|
87
|
+
| `@voltro/plugin-posthog` | ✓ | Product analytics — track-only; compose with another sink for reads. [→ details](/docs/plugins/analytics) |
|
|
84
88
|
| `@voltro/plugin-atlassian` | ✓ | `JiraService` + `ConfluenceService` over the Atlassian REST / Greenhopper / Agile APIs — PAT **or** OAuth 2.0 (3LO) auth, transient retry, SSRF guard, comment-write, signature-verified inbound webhooks, avatar proxy, per-tenant cache. [→ details](/docs/plugins/atlassian) |
|
|
85
89
|
| `@voltro/plugin-deactivation` | ✓ | `deactivation()` schema mixin — `deactivatedAt` + `deactivatedBy` (→ Actor); subject can't log in but data stays visible. [→ details](/docs/plugins/deactivation) |
|
|
86
90
|
| `@voltro/plugin-prometheus` | ✓ | Prometheus exporter — `GET /metrics` in text exposition format over the unified Metrics-API (Effect `MetricRegistry`); counters / histograms / gauges + custom metrics, optional bearer gate + node process metrics. [→ details](/docs/plugins/prometheus) |
|
|
@@ -91,10 +95,10 @@ Status legend: ✓ shipped · ◐ partial · — planned.
|
|
|
91
95
|
| `@voltro/plugin-logship` | ✓ | Ship structured logs to Better Stack / Axiom / Loki / any HTTP sink — rides the log-sink hook, batched + redacted + fail-soft, trace-correlated. [→ details](/docs/plugins/logship) |
|
|
92
96
|
| `@voltro/plugin-moderation` | ✓ | Content moderation — keyword denylist or AI provider (fails open), block (typed `ContentRejected`) / flag via rpc interceptor + in-handler `moderate()` redact helper. [→ details](/docs/plugins/moderation) |
|
|
93
97
|
| `@voltro/plugin-search` | ✓ | External search index sync — rides the ChangeEvent tap to mirror tables into Typesense / Meilisearch / Algolia (memory default), tenant-scoped `search.query` action (facets · highlighting · fuzziness · range/negation filters · engine-param passthrough) + `useSearch` hook + `backfillIndex` + durable cross-replica sync stats. [→ details](/docs/plugins/search) |
|
|
94
|
-
| `@voltro/plugin-cdc-out` | ◐ | Declarative reverse-ETL — mirror table changes outward to external sinks (webhook
|
|
98
|
+
| `@voltro/plugin-cdc-out` | ◐ | Declarative reverse-ETL — mirror table changes outward to external sinks (webhook, plus a `CdcSink` interface for custom sinks) through a durable outbox; ordered per pipe, at-least-once from enqueue, retried with backoff, dead-lettered. Engine + memory/webhook sinks shipped; anything else implements the `CdcSink` interface. |
|
|
95
99
|
| `@voltro/plugin-governance` | ✓ | Data governance — retention TTL sweep (delete / anonymise), GDPR subject export + erasure (admin-gated routes + `GovernanceService`), consent ledger, field encryption. [→ details](/docs/plugins/governance) |
|
|
96
100
|
| `@voltro/plugin-openapi` | ✓ | OpenAPI 3.1 spec (`GET /openapi.json`) + Swagger-UI (`GET /docs`) generated from `defineRestRoute` descriptors AND (opt-in) rpc procedures (queries/mutations/actions/streams → `POST /rpc/<name>`) — input/output/error Schemas via `JSONSchema.make`. [→ details](/docs/plugins/openapi) |
|
|
97
|
-
| `@voltro/plugin-
|
|
101
|
+
| `@voltro/plugin-row-history` | ✓ | Full row history + time-travel — value snapshot of every insert/update/delete (every table by default; narrow with include/exclude) into `_voltro_row_history` (rides the ChangeEvent tap); `rowHistory` / `rowAsOf` queries + `restoreAsOf` / `diffVersions`; TTL + per-row cap retention. [→ details](/docs/plugins/row-history) |
|
|
98
102
|
| `@voltro/plugin-presence` | ✓ | Ephemeral realtime presence — heartbeat roster per channel (`presence.heartbeat`/`list`/`leave` + `usePresence`), a `useTyping` typing indicator. Held **in memory**, owner-partitioned — no table is written; cross-instance requires [`@voltro/plugin-broadcast`](/docs/plugins/broadcast), and without a broker each replica sees only its own clients. [→ details](/docs/plugins/presence) |
|
|
99
103
|
| `@voltro/plugin-scim` | ✓ | SCIM 2.0 provisioning — Users + Groups REST at `/scim/v2` (bearer-gated) incl. group-membership PATCH/PUT + the RFC 7644 discovery trio (ServiceProviderConfig/Schemas/ResourceTypes), `userName`/`externalId`/`displayName eq` filters, pagination, unique `userName`, `active:false` deactivation; `_voltro_scim_users`/`_voltro_scim_groups`. [→ details](/docs/plugins/scim) |
|
|
100
104
|
| `@voltro/plugin-sso-saml` | ✓ | Enterprise SAML 2.0 SSO — SP-initiated login + Single Logout (both directions) + ACS + SP metadata under `/saml`; IdP-metadata-URL auto cert rotation, encrypted assertions, clock-skew, SP request signing. Signature verify via `@node-saml/node-saml` (optional+lazy), mints a framework session. [→ details](/docs/plugins/sso-saml) |
|
|
@@ -746,7 +750,7 @@ A package can ship BOTH a schema mixin AND a runtime plugin (`@voltro/plugin-aud
|
|
|
746
750
|
|
|
747
751
|
## More extension surfaces
|
|
748
752
|
|
|
749
|
-
The plugin contract carries
|
|
753
|
+
The plugin contract carries the additional surfaces below, beyond the
|
|
750
754
|
interceptors + lifecycle + manifest fields covered above:
|
|
751
755
|
|
|
752
756
|
### `inspectEndpoints: PluginInspectEndpoint[]` — plugin-mounted HTTP endpoints
|
|
@@ -874,6 +878,17 @@ plugin-provided template is scaffolded exactly like a built-in one —
|
|
|
874
878
|
`scaffoldFromTemplate` copies the declared tree and substitutes the
|
|
875
879
|
`{{…}}` tokens in both file content AND file/directory names.
|
|
876
880
|
|
|
881
|
+
### `httpRoutes: PluginHttpRoute[]` — raw HTTP endpoints on the framework listener
|
|
882
|
+
|
|
883
|
+
A plugin can mount plain HTTP routes beside the rpc surface (`@voltro/plugin-storage`'s upload/download routes, an IdP callback). The request/response shape is transport-honest, and four properties are worth pinning:
|
|
884
|
+
|
|
885
|
+
- **The full method union is first-class.** `method` is `'*' | 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'`. **HEAD is admitted wherever GET is** (RFC 9110) — the GET handler runs and the transport drops the body; you never mount a second route for it. A wrong method stays a precise `405` with an `Allow:` header, including when several routes share one path.
|
|
886
|
+
- **The body read is capped** — 8 MiB by default, the same cap as every other surface (`http.maxBodyBytes` in `app.config.ts`, env `VOLTRO_MAX_BODY_BYTES`), and the read is binary-clean. A route that takes more declares its own `maxBodyBytes`; routes **sharing a path share one body read**, so the widest override in the group applies to the group. Oversize answers `413` for both `Content-Length` and chunked requests.
|
|
887
|
+
- **Binary streaming responses** return `byteStream` on the `PluginHttpRouteResult` — a `ReadableStream<Uint8Array>` (or lazy thunk) with optional `contentLength` / `contentDisposition`, piped without buffering and never compressed. It is the plugin-route spelling of the REST surface's [`bytes()`](/docs/data/rest-routes#binary-downloads-bytes).
|
|
888
|
+
- **Buffered responses are compression-negotiated** (brotli/gzip, compressible types only) by the listener — nothing to declare; see [Security → compression](/docs/security/overview).
|
|
889
|
+
|
|
890
|
+
A state-changing plugin route is origin-checked unless it declares `originGuard: 'exempt'`, and `req.remoteAddr` is the trusted-proxy-resolved client address — both covered with examples in [Security](/docs/security/overview#routes-that-a-third-party-legitimately-posts-to).
|
|
891
|
+
|
|
877
892
|
### `onHttpRequest: HttpRequestInterceptor` — pre-auth HTTP-pipeline hook
|
|
878
893
|
|
|
879
894
|
Fires at the **very top** of every HTTP request — BEFORE auth resolution,
|
|
@@ -937,6 +952,17 @@ is deliberate: `GET /internal/liveness` and `GET /internal/readiness` are
|
|
|
937
952
|
answered before the interceptor, so a rate-limit or geo-block plugin cannot 503
|
|
938
953
|
a Kubernetes probe and take the replica out of rotation.
|
|
939
954
|
|
|
955
|
+
**The chain is FAIL-CLOSED.** An interceptor that throws is a `500` plus a log
|
|
956
|
+
line — the request does NOT continue. It used to: the failure was swallowed and
|
|
957
|
+
the request flowed on, which meant a crashed security gate was an open one.
|
|
958
|
+
That polarity puts a decision on every interceptor author: if your hook is a
|
|
959
|
+
GATE (geo-block, bot detection), let a failure propagate — refusing is the
|
|
960
|
+
correct degraded behaviour. If it is protection with a DEPENDENCY (a rate-limit
|
|
961
|
+
counter in Redis), catch your own failure inside the hook and **degrade
|
|
962
|
+
loudly** — `@voltro/plugin-ratelimit`'s `httpShield` does exactly that: a Redis
|
|
963
|
+
outage means unlimited-with-a-warning, never a self-inflicted API outage.
|
|
964
|
+
What no interceptor gets to do anymore is fail silently and stay in the chain.
|
|
965
|
+
|
|
940
966
|
### `extendSchema: { tables, migrations }` — contribute schema + migrations
|
|
941
967
|
|
|
942
968
|
A plugin contributes BOTH declarative table descriptors AND custom SQL
|
|
@@ -225,6 +225,18 @@ const { data } = useSubscription(
|
|
|
225
225
|
)
|
|
226
226
|
```
|
|
227
227
|
|
|
228
|
+
### Offline semantics with the local-first mirror
|
|
229
|
+
|
|
230
|
+
With `@voltro/local-first`'s query mirror bound (see
|
|
231
|
+
[the sync engine](/docs/local-first/overview#the-sync-engine-query-mirror--durable-outbox)),
|
|
232
|
+
`useSubscription`'s behaviour extends offline WITHOUT a second API: a cold
|
|
233
|
+
start seeds `data` (and `revision`) from the device's mirrored rows for the
|
|
234
|
+
subject's partition, so `loading` resolves against local data when the server
|
|
235
|
+
is unreachable; the first live event replaces it, and a reconnect inside the
|
|
236
|
+
resume window continues with deltas from the mirrored revision. Offline
|
|
237
|
+
WRITES ride [`useOutbox`](/docs/ui/client-utilities/use-outbox) — durable
|
|
238
|
+
with `outboxPersistence()`, conflict resolution via `resolveConflict`.
|
|
239
|
+
|
|
228
240
|
## `useMutation(apiName, rpcTag)`
|
|
229
241
|
|
|
230
242
|
Calls a `defineMutation` RPC.
|
|
@@ -581,6 +593,7 @@ Returns a function `(to: string, options?) => void`.
|
|
|
581
593
|
|---|---|
|
|
582
594
|
| `replace: true` | Replace the history entry (no back-button entry). |
|
|
583
595
|
| `scroll: false` | Don't scroll to top after navigation. |
|
|
596
|
+
| `transition: true / false` | Run (or suppress) this navigation's swap through `document.startViewTransition`, overriding the app-wide `router.viewTransitions` default. `<Link transition>` is the declarative mirror. See [View transitions](/docs/routing/navigation#view-transitions). |
|
|
584
597
|
|
|
585
598
|
`navigate` takes a path string only — there is no numeric history overload. For back / forward, reach for the browser API:
|
|
586
599
|
|
|
@@ -591,7 +604,7 @@ window.history.forward() // forward
|
|
|
591
604
|
|
|
592
605
|
## `useBlocker()`
|
|
593
606
|
|
|
594
|
-
Hold a pending navigation so you can prompt before the user leaves — the unsaved-changes guard.
|
|
607
|
+
Hold a pending navigation so you can prompt before the user leaves — the unsaved-changes guard. It guards SPA navigations, the browser's **Back/Forward gestures** (popstate: the router reverts the already-moved URL and offers `retry`/`reset` — this also covers ESC inside an [intercepting-route overlay](/docs/routing/intercepting-routes)), and full-page unloads via `beforeunload`.
|
|
595
608
|
|
|
596
609
|
```tsx
|
|
597
610
|
import { useBlocker } from '@voltro/web'
|
|
@@ -607,12 +620,22 @@ Pass `true`/`false` or a predicate `({ to, opts }) => boolean` (to allow some de
|
|
|
607
620
|
|
|
608
621
|
## `useSearchParams()` + `useSetSearchParams()`
|
|
609
622
|
|
|
610
|
-
Read the query string
|
|
623
|
+
Read the query string. Two overloads, both SSR-aware (the request URL on the server, `window.location.search` on the client):
|
|
624
|
+
|
|
625
|
+
- `useSearchParams()` — the raw `URLSearchParams`, for routes without a schema.
|
|
626
|
+
- `useSearchParams(searchParams)` — pass the page's own `searchParams` schema export to get the decoded, typed shape. Defaults applied; an invalid query falls back to the defaults instead of crashing.
|
|
611
627
|
|
|
612
628
|
```tsx
|
|
629
|
+
import { Schema } from 'effect'
|
|
613
630
|
import { useSearchParams } from '@voltro/web'
|
|
614
631
|
|
|
615
|
-
const
|
|
632
|
+
export const searchParams = Schema.Struct({
|
|
633
|
+
tab: Schema.optionalWith(Schema.String, { default: () => 'overview' }),
|
|
634
|
+
page: Schema.optionalWith(Schema.NumberFromString, { default: () => 1 }),
|
|
635
|
+
})
|
|
636
|
+
|
|
637
|
+
const { tab, page } = useSearchParams(searchParams) // tab: string · page: number
|
|
638
|
+
const raw = useSearchParams() // URLSearchParams (schema-less routes)
|
|
616
639
|
```
|
|
617
640
|
|
|
618
641
|
Write it with `useSetSearchParams()` — the setter updates the query via `navigate`, so readers re-render immediately:
|
|
@@ -626,7 +649,29 @@ setParams((p) => { p.set('page', '2'); return p }) // patch one param
|
|
|
626
649
|
setParams({ page: '2' }, { push: true }) // distinct history entry
|
|
627
650
|
```
|
|
628
651
|
|
|
629
|
-
Writes default to a history replace; pass `{ push: true }` for a Back entry or `{ scroll: false }` to keep scroll. See [Navigation](/docs/routing/navigation#reading
|
|
652
|
+
Writes default to a history replace; pass `{ push: true }` for a Back entry or `{ scroll: false }` to keep scroll. See [Navigation](/docs/routing/navigation#reading-writing-search-params).
|
|
653
|
+
|
|
654
|
+
`useSetSearchParams(searchParams)` — pass the schema to get the **typed** setter. Object form replaces the query (a left-out field decodes to its default on the next read); the updater form receives the current **decoded** params, so a merge is an explicit spread:
|
|
655
|
+
|
|
656
|
+
```tsx
|
|
657
|
+
const setTyped = useSetSearchParams(searchParams)
|
|
658
|
+
setTyped({ page: 2 }) // replaces → ?page=2
|
|
659
|
+
setTyped((p) => ({ ...p, page: p.page + 1 })) // keeps every other param — typed merge
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
## Typed `withQuery()`
|
|
663
|
+
|
|
664
|
+
Not a hook, but the link-side half of the same contract: for a route whose page exports a `searchParams` schema, the generated `routes` builder brands the URL with the schema's shape (through a type-only import — no page code enters the routes module), and `withQuery` type-checks the params against it — a misspelt key or a wrong value type is a compile error:
|
|
665
|
+
|
|
666
|
+
```tsx
|
|
667
|
+
import { withQuery } from '@voltro/web'
|
|
668
|
+
import { routes } from './.framework/routes'
|
|
669
|
+
|
|
670
|
+
withQuery(routes['/notes'](), { page: 2 }) // OK — typed against the schema
|
|
671
|
+
// withQuery(routes['/notes'](), { pgae: 2 }) // compile error (unknown key)
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
The encode is canonical: strings pass through, numbers/booleans via `String()`, arrays as repeated keys, `undefined` omitted; a `Date` (or any object) is refused loudly — declare the field as a string/number transform in the schema instead. See [Navigation → typed `withQuery`](/docs/routing/navigation#typed-withquery).
|
|
630
675
|
|
|
631
676
|
## `usePrefetch()`
|
|
632
677
|
|
|
@@ -682,7 +727,7 @@ Precisely, it returns `LoaderData<T>`. For every ordinary loader that IS `T`. Fo
|
|
|
682
727
|
a loader that returned `defer()`, `LoaderData<T>` flattens the two buckets into
|
|
683
728
|
one object — eager fields as values, deferred fields as `Promise<T>` — so the
|
|
684
729
|
compiler tells you which fields have to be rendered through
|
|
685
|
-
[`<Await>`](/docs/routing/loaders-and-meta#deferring-slow-data-defer
|
|
730
|
+
[`<Await>`](/docs/routing/loaders-and-meta#deferring-slow-data-defer):
|
|
686
731
|
|
|
687
732
|
```tsx
|
|
688
733
|
export const loader = async ({ query }) => defer(
|
|
@@ -821,6 +866,10 @@ export default function SearchPage() {
|
|
|
821
866
|
that must react to router-pushed query changes without a reload re-render through the router
|
|
822
867
|
(`useNavigate`/`useLocation`); the hook then re-resolves on that render.
|
|
823
868
|
|
|
869
|
+
Prefer the typed form where the page declares a `searchParams` schema export —
|
|
870
|
+
`useSearchParams(searchParams)` returns the decoded shape instead of a raw
|
|
871
|
+
`URLSearchParams`. See [Routing hooks](/docs/reference/hooks-routing#usesearchparams-usesetsearchparams).
|
|
872
|
+
|
|
824
873
|
## Reading cookies
|
|
825
874
|
|
|
826
875
|
```ts
|