@voltro/cli 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/apiBuild-CmtI6Ygh.js +2 -0
  3. package/dist/{apiBuild-deIjJKJm.js → apiBuild-OrDkXGFX.js} +2 -2
  4. package/dist/bin.js +2 -2
  5. package/dist/{commands-BHdc71DG.js → commands-DT4PipBz.js} +666 -526
  6. package/dist/dev-Ca1jdwnt.js +2 -0
  7. package/dist/{dev-Bqyq62Ak.js → dev-Ga65K4jc.js} +469 -469
  8. package/dist/index.js +1 -1
  9. package/dist/{inspectMetrics-BLUBAWLb.js → inspectMetrics-EK0CcHyu.js} +977 -759
  10. package/dist/{serveCommand-Dn6--0Bv.js → serveCommand-CR5xnYZt.js} +5 -5
  11. package/dist/serveEntry.js +3 -3
  12. package/dist/{start-CWZW_4Et.js → start-DuyBQxW3.js} +332 -296
  13. package/dist/startEntry.js +2 -2
  14. package/package.json +17 -17
  15. package/templates/AGENTS.core.md +15 -4
  16. package/templates/AGENTS.md +15 -4
  17. package/templates/agent-docs/authentication.md +7 -4
  18. package/templates/agent-docs/cli.md +35 -4
  19. package/templates/agent-docs/data.md +94 -70
  20. package/templates/agent-docs/database/schema.md +1 -1
  21. package/templates/agent-docs/reference.md +20 -0
  22. package/templates/agent-docs/routing.md +158 -24
  23. package/templates/agent-docs/testing.md +24 -0
  24. package/templates/apps/api-ai/package.json +7 -7
  25. package/templates/apps/api-auth/package.json +8 -8
  26. package/templates/apps/api-backend/package.json +7 -7
  27. package/templates/apps/api-backend-deactivation/package.json +7 -7
  28. package/templates/apps/api-backend-mail/package.json +8 -8
  29. package/templates/apps/api-backend-mariadb/package.json +9 -9
  30. package/templates/apps/api-backend-storage/package.json +8 -8
  31. package/templates/apps/api-data-advanced/package.json +8 -8
  32. package/templates/apps/api-durable/package.json +8 -8
  33. package/templates/apps/api-feature-flags/package.json +9 -9
  34. package/templates/apps/api-governance/package.json +8 -8
  35. package/templates/apps/api-kv/package.json +8 -8
  36. package/templates/apps/api-moderation/package.json +8 -8
  37. package/templates/apps/api-observability/package.json +8 -8
  38. package/templates/apps/api-ratelimit/package.json +8 -8
  39. package/templates/apps/api-rbac/package.json +8 -8
  40. package/templates/apps/api-rest/package.json +7 -7
  41. package/templates/apps/api-saas/package.json +11 -11
  42. package/templates/apps/api-search/package.json +8 -8
  43. package/templates/apps/api-versioning/package.json +8 -8
  44. package/templates/apps/api-webhooks/package.json +8 -8
  45. package/templates/apps/changelog/package.json +6 -6
  46. package/templates/apps/edge-functions/package.json +2 -2
  47. package/templates/apps/frontend-admin/package.json +8 -8
  48. package/templates/apps/frontend-app/package.json +8 -8
  49. package/templates/apps/frontend-blank/package.json +7 -7
  50. package/templates/apps/frontend-contact/package.json +7 -7
  51. package/templates/apps/frontend-dashboard/package.json +7 -7
  52. package/templates/apps/frontend-docs/package.json +7 -7
  53. package/templates/apps/frontend-i18n/package.json +6 -6
  54. package/templates/apps/frontend-landing/package.json +7 -7
  55. package/templates/apps/frontend-spa/package.json +7 -7
  56. package/templates/apps/frontend-ssr/package.json +7 -7
  57. package/templates/apps/frontend-ssr-api/package.json +8 -8
  58. package/templates/apps/frontend-static-blog/package.json +6 -6
  59. package/dist/apiBuild-CSM74oEZ.js +0 -2
  60. package/dist/dev-BYfrYwrT.js +0 -2
@@ -537,29 +537,39 @@ Cost: every request triggers a fresh render. For very high-traffic pages, prefer
537
537
 
538
538
  ### Streaming SSR
539
539
 
540
- By default an `ssr` page renders with `renderToString` — the whole document is built in memory, then sent. The server-side SSR helpers in `@voltro/web/ssr` also expose a **streaming** path, `renderPageToStream`, built on React's `renderToPipeableStream`. It flushes the shell (and each `<Suspense>` boundary as it resolves) instead of buffering the whole page, so the browser gets the first bytes sooner:
541
-
542
- ```ts
543
- import { renderPageToStream } from '@voltro/web/ssr'
544
-
545
- const { stream, meta } = renderPageToStream({
546
- descriptor,
547
- params,
548
- pathname,
549
- loaderData,
550
- bootstrapModules: ['/assets/client.js'],
551
- onShellReady: () => {
552
- // meta is resolved synchronously write <head> before piping the body.
553
- res.setHeader('content-type', 'text/html')
554
- res.write(`<!doctype html><html><head>${renderMetaToHtml(meta)}</head><body><div id="root">`)
555
- stream.pipe(res)
556
- },
557
- onAllReady: () => res.end('</div></body></html>'),
558
- onShellError: (err) => { res.statusCode = 500; res.end('Internal error') },
559
- })
560
- ```
561
-
562
- `renderPageToStream` takes the same options as `renderPageToHtml` plus the stream callbacks (`onShellReady` / `onAllReady` / `onShellError`) and `bootstrapModules`. Both paths compose the same providers and resolve `meta` synchronously, so the sync string render and the streaming render produce the same tree — the difference is time-to-first-byte and native Suspense streaming. Most apps never call these directly; the `voltro start` pipeline uses them under the hood.
540
+ An `ssr` page is **streamed**, on both boot paths (`voltro dev` and `voltro
541
+ start`). The server sends the `<head>` and the page shell as soon as they are
542
+ rendered, then flushes each `<Suspense>` boundary as its data settles, inside
543
+ the same response.
544
+
545
+ For a page with no deferred data this is a time-to-first-byte win and nothing
546
+ else — React's render loop still runs to completion in one pass, so a slow
547
+ render is still a slow render. The lever that matters is `defer()`: it puts a
548
+ real `<Suspense>` boundary in the tree, which is what lets the server return to
549
+ the event loop while a slow value is still pending. See
550
+ [Deferring slow data](/docs/routing/loaders-and-meta#deferring-slow-data-defer--await).
551
+
552
+ Measured against a real server rendering a page with one 400ms deferred field:
553
+ first body byte at 7ms, the deferred chunk at 408ms — and a probe firing every
554
+ 10ms for the duration of that request was served 30 times with a 3ms median and
555
+ a 7ms maximum. The request does not occupy the event loop while it waits.
556
+
557
+ Two consequences worth knowing:
558
+
559
+ - **The entry script is emitted as a bootstrap module.** A plain
560
+ `<script type="module">` is deferred until the document finishes parsing,
561
+ which on a streamed response is *after the last deferred boundary* — the
562
+ framework hands the URL to React instead, so it goes out `async` at the end
563
+ of the shell and hydration starts immediately.
564
+ - **`isr` and `static` are still buffered**, because both produce a stored
565
+ artefact rather than a response. That is also why `defer()` is an error on
566
+ those modes.
567
+
568
+ Apps do not call the renderer directly. If you are building your own server on
569
+ top of `@voltro/web/ssr`, `renderPageToStream` is the entry point — it takes the
570
+ same options as `renderPageToHtml` plus `bootstrapModules` and the stream
571
+ callbacks, resolves `meta` synchronously so the `<head>` can go out first, and
572
+ returns a Node pipeable stream.
563
573
 
564
574
  ## isr (incremental static regeneration)
565
575
 
@@ -660,7 +670,7 @@ That last case is how dynamic `static` routes work in dev / when `getStaticPaths
660
670
  ## What doesn't work
661
671
 
662
672
  - **Switching `renderMode` per request.** It's a static module export — one value per build.
663
- - **`renderMode: 'ssr'` without `voltro start`.** SSR requires the production server. Dev mode runs everything client-side regardless.
673
+ - **Assuming `ssr` is client-only in dev.** It is not: `voltro dev` runs the same SSR path `voltro start` does, streaming included, so cookie-driven gates and `useServerRequest()` behave the same in both. What dev does NOT do is pre-render `static` pages — those fall through to the SPA shell.
664
674
  - **`isr` with `cacheInvalidatesOn` against memory cache.** Memory cache is per-process; CDC events fire across processes. Use `SSR_CACHE=postgres`.
665
675
 
666
676
  ## Where to read next
@@ -730,6 +740,130 @@ export default function NotePage(): ReactNode {
730
740
 
731
741
  For `static` pages with `getStaticPaths`, the loader runs once per enumerated path.
732
742
 
743
+ ### Server-rendered data reaches the first client render
744
+
745
+ For `static`, `ssr` and `isr` pages the framework inlines the loader's result
746
+ into the HTML document (a `<script type="application/json"
747
+ id="__voltro_state__">` tag) and the browser adopts it before React hydrates.
748
+ Two consequences worth designing around:
749
+
750
+ - **`useLoaderData()` returns real data on the very first client render.** It is
751
+ not `undefined` until an effect has run, so a page can dereference its loader
752
+ data directly (`data.title`) without a guard, and a layout renders its
753
+ loader's value identically on the server and on the client — no hydration
754
+ mismatch, no flash of fallback content.
755
+ - **The loader does NOT re-run on that initial hydration.** It already ran on
756
+ the server; running it again in the browser would just re-fetch what the page
757
+ is already showing. If you need work to happen after mount (refreshing data,
758
+ a side effect), put it in an effect or use `useSubscription` — do not rely on
759
+ the loader firing a second time.
760
+
761
+ Client-side navigation is unchanged: moving to another route runs that route's
762
+ loaders in the browser as usual. A `spa` page has no server render, so its
763
+ loader runs on the client on first mount.
764
+
765
+ Layout loaders are inlined the same way, keyed per layout, so each layout reads
766
+ its OWN data on the first render. The one exception is `voltro build`'s static
767
+ prerender, which runs page loaders but not layout loaders — a `static` page's
768
+ layouts resolve their data on the client after mount. The PAGE keeps its own
769
+ inlined data for the whole of that window, however slow those layout loaders
770
+ are, so the no-guard promise above holds on a prerendered page too: only the
771
+ layout shows its no-data fallback until its loader settles.
772
+
773
+
774
+ ## Deferring slow data: `defer()` + `<Await>`
775
+
776
+ A loader blocks the whole response. One slow field therefore costs every byte
777
+ of the page — the user stares at nothing while a report query runs. `defer()`
778
+ splits the loader's result into data that blocks the shell and data that
779
+ **streams in after it**, behind a `<Suspense>` boundary the server flushes as
780
+ soon as the promise settles.
781
+
782
+ ```tsx
783
+ // src/pages/dashboard.tsx
784
+ import { Await, defer, useLoaderData } from '@voltro/web'
785
+
786
+ export const renderMode = 'ssr' as const // required — see below
787
+
788
+ export const loader = async ({ query }: { query?: <T>(tag: string, input?: Record<string, unknown>) => Promise<T> }) => defer(
789
+ // EAGER — awaited before the shell renders. Keep this fast.
790
+ { user: await query?.<User>('users.me') },
791
+ // DEFERRED — NOT awaited. Each becomes a promise on useLoaderData().
792
+ { report: query!<Report>('reports.quarterly') },
793
+ )
794
+
795
+ export default function Dashboard() {
796
+ const { user, report } = useLoaderData<Awaited<ReturnType<typeof loader>>>()
797
+ return (
798
+ <main>
799
+ <h1>Hello {user?.name}</h1>
800
+
801
+ <Await value={report} fallback={<ReportSkeleton />}>
802
+ {(report) => <ReportTable rows={report.rows} />}
803
+ </Await>
804
+ </main>
805
+ )
806
+ }
807
+ ```
808
+
809
+ What the browser sees: the full page with `<ReportSkeleton />` in place,
810
+ immediately — then the real table, injected in a later chunk of the same
811
+ response. No second request, no client-side fetch, no loading spinner driven by
812
+ `useEffect`.
813
+
814
+ **Two explicit buckets, not one object.** `defer(eager, deferred)` takes them
815
+ separately rather than treating any promise-valued field as deferred. Deferral
816
+ is then something you wrote down, not something inferred from a value's runtime
817
+ shape — and `useLoaderData()` can type it: eager fields come back as values,
818
+ deferred fields as `Promise<T>`, so the compiler tells you which ones need an
819
+ `<Await>`.
820
+
821
+ ### `<Await>`
822
+
823
+ | Prop | Meaning |
824
+ |---|---|
825
+ | `value` | A deferred field off `useLoaderData()`. |
826
+ | `fallback` | Rendered until the value arrives. **This is what ships in the streamed shell** — keep it cheap and layout-stable. |
827
+ | `children` | `(value) => ReactNode` — rendered with the resolved value. |
828
+ | `errorFallback` | Rendered if the deferred promise rejects. Without it, a rejection renders nothing in that subtree. |
829
+
830
+ `<Await>` owns the `<Suspense>` boundary and the hydration handoff for the
831
+ streamed value. Do not hand-roll it with `<Suspense>` + `use()` — the server
832
+ and the client would then have to agree on a wire format that the framework
833
+ otherwise guarantees by construction.
834
+
835
+ A rejected deferred value never takes the page down: it renders
836
+ `errorFallback` in place, on the server and on the client alike.
837
+
838
+ ### `defer()` requires `renderMode: 'ssr'` and full interactivity
839
+
840
+ Every other combination is a **hard error at boot or build**, naming the page —
841
+ because each one fails silently otherwise:
842
+
843
+ | Combination | Why it is rejected |
844
+ |---|---|
845
+ | `renderMode: 'static'` | The static prerender uses `renderToString`, which does not support Suspense. It emits an errored boundary and a "switched to client rendering" template with no warning — the artefact would ship a permanent fallback. |
846
+ | `renderMode: 'isr'` | ISR caches a completed HTML string. Filling it in would make `defer()` a silent no-op that still reads like it streams. |
847
+ | `interactive: 'none'` | Revealing a streamed boundary needs React's inline reveal scripts, and this mode ships no JS. The fallback would be permanent. |
848
+ | `interactive: 'islands'` | The page's React root never hydrates, so nothing consumes the streamed value. |
849
+
850
+ In all four cases the fix is the same: put the value in the eager bucket (or
851
+ return it directly) and let the page render as it did before.
852
+
853
+ ### Layout loaders can defer too
854
+
855
+ A `layout.tsx` loader may return `defer()` under the same rules. Its deferred
856
+ fields are keyed per layout, so a layout reads its own promises via
857
+ `useLoaderData()` exactly as a page does.
858
+
859
+ ### Client-side navigation
860
+
861
+ On a client-side navigation there is no server render, so the loader runs in the
862
+ browser and its deferred fields are ordinary promises. `<Await>` renders the
863
+ fallback and swaps in the content when they settle — the same code, driven by
864
+ React alone.
865
+
866
+
733
867
  ## Loader arguments
734
868
 
735
869
  ```ts
@@ -383,6 +383,30 @@ expect(rows.map((r) => r.id)).not.toContain('bobs-ticket') // the rule, asserte
383
383
 
384
384
  Pass `rowFilter:` — as above — to scope a filter to **this context only**. `setRowFilter` is process-global: registered in one test it silently constrains every later test in the same worker, and a forgotten `afterEach` surfaces as a failure in an unrelated file. Either way the resolution is the runtime's own, so the retry schedule, the system bypass and the `onLoadError` policy behave identically: a filter whose `load` fails refuses the read (with `RowFilterUnavailable`, or zero rows under `onLoadError: 'deny'`) rather than quietly returning everything.
385
385
 
386
+ ### Filters over SHARED resources
387
+
388
+ A filter over rows the user *owns* needs no database — the subject carries the id. A filter over rows *shared with* the user must read a membership table, and `load` is `Effect<Ctx, unknown>` with `R = never`, so it cannot `yield*` a store service. Its only route is [`runAsSystem`](/docs/multi-tenancy/edge-cases), and `makeTestContext` wires its seeded store into that, so this resolves under test exactly as it does at runtime:
389
+
390
+ ```ts
391
+ const sharedLists: RowFilter<{ listIds: ReadonlyArray<string> }> = {
392
+ load: (subject) =>
393
+ Effect.promise(() =>
394
+ runAsSystem(async (sys) => {
395
+ const rows = await sys.store.select('listMembers').where('userId', String(subject.id)).all()
396
+ return { listIds: rows.map((r) => String(r.listId)) }
397
+ }),
398
+ ),
399
+ predicate: (ctx, table) => (table === 'lists' ? inSet('id', ctx.listIds) : undefined),
400
+ }
401
+
402
+ const bob = makeTestContext({ subject: bobSubject, store: mockStore(seed), rowFilter: sharedLists })
403
+ expect((await bob.store.select('lists').all()).map((r) => r.id)).not.toContain('alices-list')
404
+ ```
405
+
406
+ `makeTestContext` registers the **raw** data store + schema registry, so nothing is double-wrapped (`runAsSystem` applies the system-subject mixin wrap itself), and it is the outer store rather than a transactional view — matching production, where a `runAsSystem` block inside a mutation reads outside that mutation's transaction.
407
+
408
+ The handle is a process global, and the harness handles that in two layers. Registration is last-wins, so a bare `await runAsSystem(...)` written directly in a test also resolves. On top of that, each context re-points the handle at **its own** store for the span of its `load` and restores the previous value — necessary because two `makeTestContext` calls allocate two separate in-memory stores even from one seed object, so filter resolution must not depend on build order. Nothing leaks across test files (vitest gives each file a fresh module registry). Only the harness registers: an app that registers no handle still gets `runAsSystem: no data store available`, unchanged. If a test in the same file needs that refusal back, call `clearSystemStoreHandle()` from `@voltro/runtime`.
409
+
386
410
  ## The deterministic mocks
387
411
 
388
412
  ### `ctx.clock` — `MockClock`
@@ -11,16 +11,16 @@
11
11
  "dependencies": {
12
12
  "@effect/platform": "^0.96.1",
13
13
  "@effect/rpc": "^0.75.1",
14
- "@voltro/ai": "0.7.0",
15
- "@voltro/cli": "0.7.0",
16
- "@voltro/database": "0.7.0",
17
- "@voltro/env": "0.7.0",
18
- "@voltro/protocol": "0.7.0",
19
- "@voltro/runtime": "0.7.0",
14
+ "@voltro/ai": "0.8.0",
15
+ "@voltro/cli": "0.8.0",
16
+ "@voltro/database": "0.8.0",
17
+ "@voltro/env": "0.8.0",
18
+ "@voltro/protocol": "0.8.0",
19
+ "@voltro/runtime": "0.8.0",
20
20
  "effect": "^3.21.2"
21
21
  },
22
22
  "devDependencies": {
23
- "@voltro/testing": "0.7.0",
23
+ "@voltro/testing": "0.8.0",
24
24
  "typescript": "^5.7.0",
25
25
  "vitest": "^3.0.0"
26
26
  }
@@ -12,17 +12,17 @@
12
12
  "dependencies": {
13
13
  "@effect/platform": "^0.96.1",
14
14
  "@effect/rpc": "^0.75.1",
15
- "@voltro/cli": "0.7.0",
16
- "@voltro/database": "0.7.0",
17
- "@voltro/env": "0.7.0",
18
- "@voltro/plugin-auth": "0.7.0",
19
- "@voltro/protocol": "0.7.0",
20
- "@voltro/runtime": "0.7.0",
21
- "@voltro/sql-postgres": "0.7.0",
15
+ "@voltro/cli": "0.8.0",
16
+ "@voltro/database": "0.8.0",
17
+ "@voltro/env": "0.8.0",
18
+ "@voltro/plugin-auth": "0.8.0",
19
+ "@voltro/protocol": "0.8.0",
20
+ "@voltro/runtime": "0.8.0",
21
+ "@voltro/sql-postgres": "0.8.0",
22
22
  "effect": "^3.21.2"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.7.0",
25
+ "@voltro/testing": "0.8.0",
26
26
  "typescript": "^5.7.0",
27
27
  "vitest": "^3.0.0"
28
28
  }
@@ -12,16 +12,16 @@
12
12
  "dependencies": {
13
13
  "@effect/platform": "^0.96.1",
14
14
  "@effect/rpc": "^0.75.1",
15
- "@voltro/cli": "0.7.0",
16
- "@voltro/database": "0.7.0",
17
- "@voltro/env": "0.7.0",
18
- "@voltro/plugin-multitenancy": "0.7.0",
19
- "@voltro/protocol": "0.7.0",
20
- "@voltro/runtime": "0.7.0",
15
+ "@voltro/cli": "0.8.0",
16
+ "@voltro/database": "0.8.0",
17
+ "@voltro/env": "0.8.0",
18
+ "@voltro/plugin-multitenancy": "0.8.0",
19
+ "@voltro/protocol": "0.8.0",
20
+ "@voltro/runtime": "0.8.0",
21
21
  "effect": "^3.21.2"
22
22
  },
23
23
  "devDependencies": {
24
- "@voltro/testing": "0.7.0",
24
+ "@voltro/testing": "0.8.0",
25
25
  "typescript": "^5.7.0",
26
26
  "vitest": "^3.0.0"
27
27
  }
@@ -12,16 +12,16 @@
12
12
  "dependencies": {
13
13
  "@effect/platform": "^0.96.1",
14
14
  "@effect/rpc": "^0.75.1",
15
- "@voltro/cli": "0.7.0",
16
- "@voltro/database": "0.7.0",
17
- "@voltro/env": "0.7.0",
18
- "@voltro/plugin-deactivation": "0.7.0",
19
- "@voltro/protocol": "0.7.0",
20
- "@voltro/runtime": "0.7.0",
15
+ "@voltro/cli": "0.8.0",
16
+ "@voltro/database": "0.8.0",
17
+ "@voltro/env": "0.8.0",
18
+ "@voltro/plugin-deactivation": "0.8.0",
19
+ "@voltro/protocol": "0.8.0",
20
+ "@voltro/runtime": "0.8.0",
21
21
  "effect": "^3.21.2"
22
22
  },
23
23
  "devDependencies": {
24
- "@voltro/testing": "0.7.0",
24
+ "@voltro/testing": "0.8.0",
25
25
  "typescript": "^5.7.0",
26
26
  "vitest": "^3.0.0"
27
27
  }
@@ -12,18 +12,18 @@
12
12
  "dependencies": {
13
13
  "@react-email/components": "^1.0.12",
14
14
  "@react-email/render": "^1.4.0",
15
- "@voltro/cli": "0.7.0",
16
- "@voltro/database": "0.7.0",
17
- "@voltro/env": "0.7.0",
18
- "@voltro/plugin-mail": "0.7.0",
19
- "@voltro/plugin-multitenancy": "0.7.0",
20
- "@voltro/protocol": "0.7.0",
21
- "@voltro/runtime": "0.7.0",
15
+ "@voltro/cli": "0.8.0",
16
+ "@voltro/database": "0.8.0",
17
+ "@voltro/env": "0.8.0",
18
+ "@voltro/plugin-mail": "0.8.0",
19
+ "@voltro/plugin-multitenancy": "0.8.0",
20
+ "@voltro/protocol": "0.8.0",
21
+ "@voltro/runtime": "0.8.0",
22
22
  "effect": "^3.21.2",
23
23
  "react": "^19.0.0"
24
24
  },
25
25
  "devDependencies": {
26
- "@voltro/testing": "0.7.0",
26
+ "@voltro/testing": "0.8.0",
27
27
  "typescript": "^5.7.0",
28
28
  "vitest": "^3.0.0"
29
29
  }
@@ -12,18 +12,18 @@
12
12
  "dependencies": {
13
13
  "@effect/platform": "^0.96.1",
14
14
  "@effect/rpc": "^0.75.1",
15
- "@voltro/cli": "0.7.0",
16
- "@voltro/database": "0.7.0",
17
- "@voltro/env": "0.7.0",
18
- "@voltro/plugin-multitenancy": "0.7.0",
19
- "@voltro/plugin-storage": "0.7.0",
20
- "@voltro/protocol": "0.7.0",
21
- "@voltro/runtime": "0.7.0",
22
- "@voltro/sql-mysql": "0.7.0",
15
+ "@voltro/cli": "0.8.0",
16
+ "@voltro/database": "0.8.0",
17
+ "@voltro/env": "0.8.0",
18
+ "@voltro/plugin-multitenancy": "0.8.0",
19
+ "@voltro/plugin-storage": "0.8.0",
20
+ "@voltro/protocol": "0.8.0",
21
+ "@voltro/runtime": "0.8.0",
22
+ "@voltro/sql-mysql": "0.8.0",
23
23
  "effect": "^3.21.2"
24
24
  },
25
25
  "devDependencies": {
26
- "@voltro/testing": "0.7.0",
26
+ "@voltro/testing": "0.8.0",
27
27
  "typescript": "^5.7.0",
28
28
  "vitest": "^3.0.0"
29
29
  }
@@ -10,17 +10,17 @@
10
10
  "test": "voltro test"
11
11
  },
12
12
  "dependencies": {
13
- "@voltro/cli": "0.7.0",
14
- "@voltro/database": "0.7.0",
15
- "@voltro/env": "0.7.0",
16
- "@voltro/plugin-multitenancy": "0.7.0",
17
- "@voltro/plugin-storage": "0.7.0",
18
- "@voltro/protocol": "0.7.0",
19
- "@voltro/runtime": "0.7.0",
13
+ "@voltro/cli": "0.8.0",
14
+ "@voltro/database": "0.8.0",
15
+ "@voltro/env": "0.8.0",
16
+ "@voltro/plugin-multitenancy": "0.8.0",
17
+ "@voltro/plugin-storage": "0.8.0",
18
+ "@voltro/protocol": "0.8.0",
19
+ "@voltro/runtime": "0.8.0",
20
20
  "effect": "^3.21.2"
21
21
  },
22
22
  "devDependencies": {
23
- "@voltro/testing": "0.7.0",
23
+ "@voltro/testing": "0.8.0",
24
24
  "typescript": "^5.7.0",
25
25
  "vitest": "^3.0.0"
26
26
  }
@@ -11,17 +11,17 @@
11
11
  "dependencies": {
12
12
  "@effect/platform": "^0.96.1",
13
13
  "@effect/rpc": "^0.75.1",
14
- "@voltro/cli": "0.7.0",
15
- "@voltro/database": "0.7.0",
16
- "@voltro/env": "0.7.0",
17
- "@voltro/plugin-governance": "0.7.0",
18
- "@voltro/plugin-multitenancy": "0.7.0",
19
- "@voltro/protocol": "0.7.0",
20
- "@voltro/runtime": "0.7.0",
14
+ "@voltro/cli": "0.8.0",
15
+ "@voltro/database": "0.8.0",
16
+ "@voltro/env": "0.8.0",
17
+ "@voltro/plugin-governance": "0.8.0",
18
+ "@voltro/plugin-multitenancy": "0.8.0",
19
+ "@voltro/protocol": "0.8.0",
20
+ "@voltro/runtime": "0.8.0",
21
21
  "effect": "^3.21.2"
22
22
  },
23
23
  "devDependencies": {
24
- "@voltro/testing": "0.7.0",
24
+ "@voltro/testing": "0.8.0",
25
25
  "typescript": "^5.7.0",
26
26
  "vitest": "^3.0.0"
27
27
  }
@@ -11,17 +11,17 @@
11
11
  "dependencies": {
12
12
  "@effect/platform": "^0.96.1",
13
13
  "@effect/rpc": "^0.75.1",
14
- "@voltro/cli": "0.7.0",
15
- "@voltro/database": "0.7.0",
16
- "@voltro/env": "0.7.0",
17
- "@voltro/plugin-multitenancy": "0.7.0",
18
- "@voltro/protocol": "0.7.0",
19
- "@voltro/runtime": "0.7.0",
20
- "@voltro/workflow": "0.7.0",
14
+ "@voltro/cli": "0.8.0",
15
+ "@voltro/database": "0.8.0",
16
+ "@voltro/env": "0.8.0",
17
+ "@voltro/plugin-multitenancy": "0.8.0",
18
+ "@voltro/protocol": "0.8.0",
19
+ "@voltro/runtime": "0.8.0",
20
+ "@voltro/workflow": "0.8.0",
21
21
  "effect": "^3.21.2"
22
22
  },
23
23
  "devDependencies": {
24
- "@voltro/testing": "0.7.0",
24
+ "@voltro/testing": "0.8.0",
25
25
  "typescript": "^5.7.0",
26
26
  "vitest": "^3.0.0"
27
27
  }
@@ -12,18 +12,18 @@
12
12
  "dependencies": {
13
13
  "@effect/platform": "^0.96.1",
14
14
  "@effect/rpc": "^0.75.1",
15
- "@voltro/cli": "0.7.0",
16
- "@voltro/database": "0.7.0",
17
- "@voltro/env": "0.7.0",
18
- "@voltro/plugin-flags": "0.7.0",
19
- "@voltro/plugin-multitenancy": "0.7.0",
20
- "@voltro/protocol": "0.7.0",
21
- "@voltro/runtime": "0.7.0",
22
- "@voltro/sql-postgres": "0.7.0",
15
+ "@voltro/cli": "0.8.0",
16
+ "@voltro/database": "0.8.0",
17
+ "@voltro/env": "0.8.0",
18
+ "@voltro/plugin-flags": "0.8.0",
19
+ "@voltro/plugin-multitenancy": "0.8.0",
20
+ "@voltro/protocol": "0.8.0",
21
+ "@voltro/runtime": "0.8.0",
22
+ "@voltro/sql-postgres": "0.8.0",
23
23
  "effect": "^3.21.2"
24
24
  },
25
25
  "devDependencies": {
26
- "@voltro/testing": "0.7.0",
26
+ "@voltro/testing": "0.8.0",
27
27
  "typescript": "^5.7.0",
28
28
  "vitest": "^3.0.0"
29
29
  }
@@ -12,17 +12,17 @@
12
12
  "dependencies": {
13
13
  "@effect/platform": "^0.96.1",
14
14
  "@effect/rpc": "^0.75.1",
15
- "@voltro/cli": "0.7.0",
16
- "@voltro/database": "0.7.0",
17
- "@voltro/env": "0.7.0",
18
- "@voltro/plugin-audit": "0.7.0",
19
- "@voltro/plugin-governance": "0.7.0",
20
- "@voltro/protocol": "0.7.0",
21
- "@voltro/runtime": "0.7.0",
15
+ "@voltro/cli": "0.8.0",
16
+ "@voltro/database": "0.8.0",
17
+ "@voltro/env": "0.8.0",
18
+ "@voltro/plugin-audit": "0.8.0",
19
+ "@voltro/plugin-governance": "0.8.0",
20
+ "@voltro/protocol": "0.8.0",
21
+ "@voltro/runtime": "0.8.0",
22
22
  "effect": "^3.21.2"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.7.0",
25
+ "@voltro/testing": "0.8.0",
26
26
  "typescript": "^5.7.0",
27
27
  "vitest": "^3.0.0"
28
28
  }
@@ -11,17 +11,17 @@
11
11
  "dependencies": {
12
12
  "@effect/platform": "^0.96.1",
13
13
  "@effect/rpc": "^0.75.1",
14
- "@voltro/cli": "0.7.0",
15
- "@voltro/database": "0.7.0",
16
- "@voltro/env": "0.7.0",
17
- "@voltro/kv": "0.7.0",
18
- "@voltro/plugin-multitenancy": "0.7.0",
19
- "@voltro/protocol": "0.7.0",
20
- "@voltro/runtime": "0.7.0",
14
+ "@voltro/cli": "0.8.0",
15
+ "@voltro/database": "0.8.0",
16
+ "@voltro/env": "0.8.0",
17
+ "@voltro/kv": "0.8.0",
18
+ "@voltro/plugin-multitenancy": "0.8.0",
19
+ "@voltro/protocol": "0.8.0",
20
+ "@voltro/runtime": "0.8.0",
21
21
  "effect": "^3.21.2"
22
22
  },
23
23
  "devDependencies": {
24
- "@voltro/testing": "0.7.0",
24
+ "@voltro/testing": "0.8.0",
25
25
  "typescript": "^5.7.0",
26
26
  "vitest": "^3.0.0"
27
27
  }
@@ -12,17 +12,17 @@
12
12
  "dependencies": {
13
13
  "@effect/platform": "^0.96.1",
14
14
  "@effect/rpc": "^0.75.1",
15
- "@voltro/cli": "0.7.0",
16
- "@voltro/database": "0.7.0",
17
- "@voltro/env": "0.7.0",
18
- "@voltro/plugin-moderation": "0.7.0",
19
- "@voltro/plugin-multitenancy": "0.7.0",
20
- "@voltro/protocol": "0.7.0",
21
- "@voltro/runtime": "0.7.0",
15
+ "@voltro/cli": "0.8.0",
16
+ "@voltro/database": "0.8.0",
17
+ "@voltro/env": "0.8.0",
18
+ "@voltro/plugin-moderation": "0.8.0",
19
+ "@voltro/plugin-multitenancy": "0.8.0",
20
+ "@voltro/protocol": "0.8.0",
21
+ "@voltro/runtime": "0.8.0",
22
22
  "effect": "^3.21.2"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.7.0",
25
+ "@voltro/testing": "0.8.0",
26
26
  "typescript": "^5.7.0",
27
27
  "vitest": "^3.0.0"
28
28
  }
@@ -12,17 +12,17 @@
12
12
  "dependencies": {
13
13
  "@effect/platform": "^0.96.1",
14
14
  "@effect/rpc": "^0.75.1",
15
- "@voltro/cli": "0.7.0",
16
- "@voltro/database": "0.7.0",
17
- "@voltro/plugin-multitenancy": "0.7.0",
18
- "@voltro/plugin-prometheus": "0.7.0",
19
- "@voltro/plugin-sentry": "0.7.0",
20
- "@voltro/protocol": "0.7.0",
21
- "@voltro/runtime": "0.7.0",
15
+ "@voltro/cli": "0.8.0",
16
+ "@voltro/database": "0.8.0",
17
+ "@voltro/plugin-multitenancy": "0.8.0",
18
+ "@voltro/plugin-prometheus": "0.8.0",
19
+ "@voltro/plugin-sentry": "0.8.0",
20
+ "@voltro/protocol": "0.8.0",
21
+ "@voltro/runtime": "0.8.0",
22
22
  "effect": "^3.21.2"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.7.0",
25
+ "@voltro/testing": "0.8.0",
26
26
  "typescript": "^5.7.0",
27
27
  "vitest": "^3.0.0"
28
28
  }