@voltro/cli 0.7.0 → 0.9.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 +40 -0
- package/THIRD-PARTY-NOTICES.md +2 -2
- package/dist/apiBuild-Ba4njm9m.js +2 -0
- package/dist/{apiBuild-deIjJKJm.js → apiBuild-eInHm_bJ.js} +2 -2
- package/dist/bin.js +2 -2
- package/dist/{commands-BHdc71DG.js → commands-Cxs97AFp.js} +1897 -1664
- package/dist/{dev-Bqyq62Ak.js → dev-63Ehpw2p.js} +475 -475
- package/dist/dev-CXsR8Zgo.js +2 -0
- package/dist/index.js +1 -1
- package/dist/{inspectMetrics-BLUBAWLb.js → inspectMetrics-DVCKKSPk.js} +819 -510
- package/dist/{serveCommand-Dn6--0Bv.js → serveCommand-Cq7BhtpB.js} +3 -3
- package/dist/serveEntry.js +3 -3
- package/dist/{start-CWZW_4Et.js → start-CYe-7ueh.js} +371 -306
- package/dist/startEntry.js +2 -2
- package/package.json +18 -17
- package/templates/AGENTS.core.md +15 -4
- package/templates/AGENTS.md +15 -4
- package/templates/agent-docs/authentication.md +7 -4
- package/templates/agent-docs/cli.md +84 -5
- package/templates/agent-docs/data.md +94 -70
- package/templates/agent-docs/database/schema.md +1 -1
- package/templates/agent-docs/reference.md +20 -0
- package/templates/agent-docs/routing.md +183 -25
- package/templates/agent-docs/testing.md +24 -0
- package/templates/apps/api-ai/package.json +7 -7
- package/templates/apps/api-auth/package.json +8 -8
- package/templates/apps/api-backend/package.json +7 -7
- package/templates/apps/api-backend-deactivation/package.json +7 -7
- package/templates/apps/api-backend-mail/package.json +8 -8
- package/templates/apps/api-backend-mariadb/package.json +9 -9
- package/templates/apps/api-backend-storage/package.json +8 -8
- package/templates/apps/api-data-advanced/package.json +8 -8
- package/templates/apps/api-durable/package.json +8 -8
- package/templates/apps/api-feature-flags/package.json +9 -9
- package/templates/apps/api-governance/package.json +8 -8
- package/templates/apps/api-kv/package.json +8 -8
- package/templates/apps/api-moderation/package.json +8 -8
- package/templates/apps/api-observability/package.json +8 -8
- package/templates/apps/api-ratelimit/package.json +8 -8
- package/templates/apps/api-rbac/package.json +8 -8
- package/templates/apps/api-rest/package.json +7 -7
- package/templates/apps/api-saas/package.json +11 -11
- package/templates/apps/api-search/package.json +8 -8
- package/templates/apps/api-versioning/package.json +8 -8
- package/templates/apps/api-webhooks/package.json +8 -8
- package/templates/apps/changelog/package.json +6 -6
- package/templates/apps/edge-functions/package.json +2 -2
- package/templates/apps/frontend-admin/package.json +8 -8
- package/templates/apps/frontend-app/package.json +8 -8
- package/templates/apps/frontend-blank/package.json +7 -7
- package/templates/apps/frontend-contact/package.json +7 -7
- package/templates/apps/frontend-dashboard/package.json +7 -7
- package/templates/apps/frontend-docs/package.json +7 -7
- package/templates/apps/frontend-i18n/package.json +6 -6
- package/templates/apps/frontend-landing/package.json +7 -7
- package/templates/apps/frontend-spa/package.json +7 -7
- package/templates/apps/frontend-ssr/package.json +7 -7
- package/templates/apps/frontend-ssr-api/package.json +8 -8
- package/templates/apps/frontend-static-blog/package.json +6 -6
- package/dist/apiBuild-CSM74oEZ.js +0 -2
- 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
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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
|
|
|
@@ -615,6 +625,20 @@ The framework reads Postgres logical replication; writes to `posts` or `comments
|
|
|
615
625
|
|
|
616
626
|
Requires `SSR_CACHE=postgres` and a `wal_level=logical` Postgres.
|
|
617
627
|
|
|
628
|
+
## spa (client-only, with an optional SSR layout shell)
|
|
629
|
+
|
|
630
|
+
```tsx
|
|
631
|
+
export const renderMode = 'spa' as const
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
A `spa` page renders entirely in the browser — the page itself is never server-rendered. Reach for it when a page genuinely needs a fresh client render every load (most reactive dashboards) and doesn't need its own first-paint HTML or SEO.
|
|
635
|
+
|
|
636
|
+
**If the page's route has a layout, that layout is still server-rendered.** The server renders the layout chain — running its layout loaders — around an empty page slot (`<div data-voltro-page-slot>`), inlines the layout data, and marks the page client-only. The browser hydrates that shell and mounts the page into the slot after hydration. So the shell (nav, sidebar, auth gate) gets an instant first paint while the page stays client-only. The page's own `loader` still runs in the browser.
|
|
637
|
+
|
|
638
|
+
Because a layout now runs on the server for spa routes too, a layout used **only** by spa pages must be SSR-safe — no unguarded `window` / `document` in its render or its `loader`. Layouts shared with any `static` / `ssr` / `isr` page already render server-side (and `static` is the default), so they are unaffected. A spa page with **no** layout is a pure client mount, unchanged.
|
|
639
|
+
|
|
640
|
+
> **Deferred (follow-ups, not yet shipped):** `voltro build` does not prerender the spa layout shell to a file — `voltro start` renders it on demand. `defer()` / streaming inside a spa-shell layout is unsupported (the shell is buffered). Fast Refresh of the shell path is not yet specialised.
|
|
641
|
+
|
|
618
642
|
## Picking between them
|
|
619
643
|
|
|
620
644
|
| You have… | Use |
|
|
@@ -653,14 +677,15 @@ A request to `/foo`:
|
|
|
653
677
|
1. **Pre-rendered HTML exists at `dist/foo/index.html`?** Serve it. (static + isr-already-cached.)
|
|
654
678
|
2. **No pre-render, page is `ssr`?** Render fresh, serve.
|
|
655
679
|
3. **No pre-render, page is `isr`?** Cache lookup → MISS → render → store → serve.
|
|
656
|
-
4. **No pre-render, page is `
|
|
680
|
+
4. **No pre-render, page is `spa` with a layout?** Render the SSR layout shell (layouts + an empty page slot) on demand; the client mounts the page into the slot.
|
|
681
|
+
5. **No pre-render, page is `spa` with no layout, or `static`?** Serve the SPA shell — the client router takes over.
|
|
657
682
|
|
|
658
683
|
That last case is how dynamic `static` routes work in dev / when `getStaticPaths` didn't include the URL.
|
|
659
684
|
|
|
660
685
|
## What doesn't work
|
|
661
686
|
|
|
662
687
|
- **Switching `renderMode` per request.** It's a static module export — one value per build.
|
|
663
|
-
-
|
|
688
|
+
- **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
689
|
- **`isr` with `cacheInvalidatesOn` against memory cache.** Memory cache is per-process; CDC events fire across processes. Use `SSR_CACHE=postgres`.
|
|
665
690
|
|
|
666
691
|
## Where to read next
|
|
@@ -730,6 +755,130 @@ export default function NotePage(): ReactNode {
|
|
|
730
755
|
|
|
731
756
|
For `static` pages with `getStaticPaths`, the loader runs once per enumerated path.
|
|
732
757
|
|
|
758
|
+
### Server-rendered data reaches the first client render
|
|
759
|
+
|
|
760
|
+
For `static`, `ssr` and `isr` pages the framework inlines the loader's result
|
|
761
|
+
into the HTML document (a `<script type="application/json"
|
|
762
|
+
id="__voltro_state__">` tag) and the browser adopts it before React hydrates.
|
|
763
|
+
Two consequences worth designing around:
|
|
764
|
+
|
|
765
|
+
- **`useLoaderData()` returns real data on the very first client render.** It is
|
|
766
|
+
not `undefined` until an effect has run, so a page can dereference its loader
|
|
767
|
+
data directly (`data.title`) without a guard, and a layout renders its
|
|
768
|
+
loader's value identically on the server and on the client — no hydration
|
|
769
|
+
mismatch, no flash of fallback content.
|
|
770
|
+
- **The loader does NOT re-run on that initial hydration.** It already ran on
|
|
771
|
+
the server; running it again in the browser would just re-fetch what the page
|
|
772
|
+
is already showing. If you need work to happen after mount (refreshing data,
|
|
773
|
+
a side effect), put it in an effect or use `useSubscription` — do not rely on
|
|
774
|
+
the loader firing a second time.
|
|
775
|
+
|
|
776
|
+
Client-side navigation is unchanged: moving to another route runs that route's
|
|
777
|
+
loaders in the browser as usual. A `spa` page has no server render, so its
|
|
778
|
+
loader runs on the client on first mount.
|
|
779
|
+
|
|
780
|
+
Layout loaders are inlined the same way, keyed per layout, so each layout reads
|
|
781
|
+
its OWN data on the first render. The one exception is `voltro build`'s static
|
|
782
|
+
prerender, which runs page loaders but not layout loaders — a `static` page's
|
|
783
|
+
layouts resolve their data on the client after mount. The PAGE keeps its own
|
|
784
|
+
inlined data for the whole of that window, however slow those layout loaders
|
|
785
|
+
are, so the no-guard promise above holds on a prerendered page too: only the
|
|
786
|
+
layout shows its no-data fallback until its loader settles.
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+
## Deferring slow data: `defer()` + `<Await>`
|
|
790
|
+
|
|
791
|
+
A loader blocks the whole response. One slow field therefore costs every byte
|
|
792
|
+
of the page — the user stares at nothing while a report query runs. `defer()`
|
|
793
|
+
splits the loader's result into data that blocks the shell and data that
|
|
794
|
+
**streams in after it**, behind a `<Suspense>` boundary the server flushes as
|
|
795
|
+
soon as the promise settles.
|
|
796
|
+
|
|
797
|
+
```tsx
|
|
798
|
+
// src/pages/dashboard.tsx
|
|
799
|
+
import { Await, defer, useLoaderData } from '@voltro/web'
|
|
800
|
+
|
|
801
|
+
export const renderMode = 'ssr' as const // required — see below
|
|
802
|
+
|
|
803
|
+
export const loader = async ({ query }: { query?: <T>(tag: string, input?: Record<string, unknown>) => Promise<T> }) => defer(
|
|
804
|
+
// EAGER — awaited before the shell renders. Keep this fast.
|
|
805
|
+
{ user: await query?.<User>('users.me') },
|
|
806
|
+
// DEFERRED — NOT awaited. Each becomes a promise on useLoaderData().
|
|
807
|
+
{ report: query!<QuarterlyReport>('reports.quarterly') },
|
|
808
|
+
)
|
|
809
|
+
|
|
810
|
+
export default function Dashboard() {
|
|
811
|
+
const { user, report } = useLoaderData<Awaited<ReturnType<typeof loader>>>()
|
|
812
|
+
return (
|
|
813
|
+
<main>
|
|
814
|
+
<h1>Hello {user?.name}</h1>
|
|
815
|
+
|
|
816
|
+
<Await value={report} fallback={<ReportSkeleton />}>
|
|
817
|
+
{(report) => <ReportTable rows={report.rows} />}
|
|
818
|
+
</Await>
|
|
819
|
+
</main>
|
|
820
|
+
)
|
|
821
|
+
}
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
What the browser sees: the full page with `<ReportSkeleton />` in place,
|
|
825
|
+
immediately — then the real table, injected in a later chunk of the same
|
|
826
|
+
response. No second request, no client-side fetch, no loading spinner driven by
|
|
827
|
+
`useEffect`.
|
|
828
|
+
|
|
829
|
+
**Two explicit buckets, not one object.** `defer(eager, deferred)` takes them
|
|
830
|
+
separately rather than treating any promise-valued field as deferred. Deferral
|
|
831
|
+
is then something you wrote down, not something inferred from a value's runtime
|
|
832
|
+
shape — and `useLoaderData()` can type it: eager fields come back as values,
|
|
833
|
+
deferred fields as `Promise<T>`, so the compiler tells you which ones need an
|
|
834
|
+
`<Await>`.
|
|
835
|
+
|
|
836
|
+
### `<Await>`
|
|
837
|
+
|
|
838
|
+
| Prop | Meaning |
|
|
839
|
+
|---|---|
|
|
840
|
+
| `value` | A deferred field off `useLoaderData()`. |
|
|
841
|
+
| `fallback` | Rendered until the value arrives. **This is what ships in the streamed shell** — keep it cheap and layout-stable. |
|
|
842
|
+
| `children` | `(value) => ReactNode` — rendered with the resolved value. |
|
|
843
|
+
| `errorFallback` | Rendered if the deferred promise rejects. Without it, a rejection renders nothing in that subtree. |
|
|
844
|
+
|
|
845
|
+
`<Await>` owns the `<Suspense>` boundary and the hydration handoff for the
|
|
846
|
+
streamed value. Do not hand-roll it with `<Suspense>` + `use()` — the server
|
|
847
|
+
and the client would then have to agree on a wire format that the framework
|
|
848
|
+
otherwise guarantees by construction.
|
|
849
|
+
|
|
850
|
+
A rejected deferred value never takes the page down: it renders
|
|
851
|
+
`errorFallback` in place, on the server and on the client alike.
|
|
852
|
+
|
|
853
|
+
### `defer()` requires `renderMode: 'ssr'` and full interactivity
|
|
854
|
+
|
|
855
|
+
Every other combination is a **hard error at boot or build**, naming the page —
|
|
856
|
+
because each one fails silently otherwise:
|
|
857
|
+
|
|
858
|
+
| Combination | Why it is rejected |
|
|
859
|
+
|---|---|
|
|
860
|
+
| `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. |
|
|
861
|
+
| `renderMode: 'isr'` | ISR caches a completed HTML string. Filling it in would make `defer()` a silent no-op that still reads like it streams. |
|
|
862
|
+
| `interactive: 'none'` | Revealing a streamed boundary needs React's inline reveal scripts, and this mode ships no JS. The fallback would be permanent. |
|
|
863
|
+
| `interactive: 'islands'` | The page's React root never hydrates, so nothing consumes the streamed value. |
|
|
864
|
+
|
|
865
|
+
In all four cases the fix is the same: put the value in the eager bucket (or
|
|
866
|
+
return it directly) and let the page render as it did before.
|
|
867
|
+
|
|
868
|
+
### Layout loaders can defer too
|
|
869
|
+
|
|
870
|
+
A `layout.tsx` loader may return `defer()` under the same rules. Its deferred
|
|
871
|
+
fields are keyed per layout, so a layout reads its own promises via
|
|
872
|
+
`useLoaderData()` exactly as a page does.
|
|
873
|
+
|
|
874
|
+
### Client-side navigation
|
|
875
|
+
|
|
876
|
+
On a client-side navigation there is no server render, so the loader runs in the
|
|
877
|
+
browser and its deferred fields are ordinary promises. `<Await>` renders the
|
|
878
|
+
fallback and swaps in the content when they settle — the same code, driven by
|
|
879
|
+
React alone.
|
|
880
|
+
|
|
881
|
+
|
|
733
882
|
## Loader arguments
|
|
734
883
|
|
|
735
884
|
```ts
|
|
@@ -797,6 +946,15 @@ Two rules that fall out of this:
|
|
|
797
946
|
|
|
798
947
|
Under the hood, `ctx.query` is a one-shot `POST /rpc` call (see [Wire protocol](/docs/data/wire-protocol#http-one-shot-rpc-post-rpc)).
|
|
799
948
|
|
|
949
|
+
### Authentication in loaders
|
|
950
|
+
|
|
951
|
+
Auth is resolved by the **api**, never the web app. Two rules follow:
|
|
952
|
+
|
|
953
|
+
- **Strategies live on the `type:'api'` app.** A `type:'web'` app has no auth middleware, so `auth.strategies` in a web `app.config.ts` does nothing. Configure your IdP (`supabaseStrategy`, `workosStrategy`, the built-in password strategy, …) on the api's `app.config.ts`.
|
|
954
|
+
- **`ctx.query` forwards the request's cookie automatically.** A server-side loader's `ctx.query` sends the browser's `Cookie` header on the one-shot `POST /rpc`, so the api resolves the SAME Subject + tenant it would over the WebSocket. You never thread a token through by hand — a logged-in user's cookie-mode session (e.g. `@supabase/ssr`'s `sb-<ref>-auth-token`) is verified by the api's strategies, and tenant-scoped queries return that user's rows during SSR.
|
|
955
|
+
|
|
956
|
+
So a cookie-mode Supabase app configures `supabaseStrategy({ cookieName: 'sb-<ref>-auth-token' })` on the **api**; the web loader's `ctx.query` then authenticates for free. See [Supabase Auth](/docs/plugins/auth-supabase).
|
|
957
|
+
|
|
800
958
|
## Errors from loaders
|
|
801
959
|
|
|
802
960
|
If the loader throws, the framework:
|
|
@@ -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.
|
|
15
|
-
"@voltro/cli": "0.
|
|
16
|
-
"@voltro/database": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/protocol": "0.
|
|
19
|
-
"@voltro/runtime": "0.
|
|
14
|
+
"@voltro/ai": "0.9.0",
|
|
15
|
+
"@voltro/cli": "0.9.0",
|
|
16
|
+
"@voltro/database": "0.9.0",
|
|
17
|
+
"@voltro/env": "0.9.0",
|
|
18
|
+
"@voltro/protocol": "0.9.0",
|
|
19
|
+
"@voltro/runtime": "0.9.0",
|
|
20
20
|
"effect": "^3.21.2"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@voltro/testing": "0.
|
|
23
|
+
"@voltro/testing": "0.9.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.
|
|
16
|
-
"@voltro/database": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/plugin-auth": "0.
|
|
19
|
-
"@voltro/protocol": "0.
|
|
20
|
-
"@voltro/runtime": "0.
|
|
21
|
-
"@voltro/sql-postgres": "0.
|
|
15
|
+
"@voltro/cli": "0.9.0",
|
|
16
|
+
"@voltro/database": "0.9.0",
|
|
17
|
+
"@voltro/env": "0.9.0",
|
|
18
|
+
"@voltro/plugin-auth": "0.9.0",
|
|
19
|
+
"@voltro/protocol": "0.9.0",
|
|
20
|
+
"@voltro/runtime": "0.9.0",
|
|
21
|
+
"@voltro/sql-postgres": "0.9.0",
|
|
22
22
|
"effect": "^3.21.2"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@voltro/testing": "0.
|
|
25
|
+
"@voltro/testing": "0.9.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.
|
|
16
|
-
"@voltro/database": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/plugin-multitenancy": "0.
|
|
19
|
-
"@voltro/protocol": "0.
|
|
20
|
-
"@voltro/runtime": "0.
|
|
15
|
+
"@voltro/cli": "0.9.0",
|
|
16
|
+
"@voltro/database": "0.9.0",
|
|
17
|
+
"@voltro/env": "0.9.0",
|
|
18
|
+
"@voltro/plugin-multitenancy": "0.9.0",
|
|
19
|
+
"@voltro/protocol": "0.9.0",
|
|
20
|
+
"@voltro/runtime": "0.9.0",
|
|
21
21
|
"effect": "^3.21.2"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@voltro/testing": "0.
|
|
24
|
+
"@voltro/testing": "0.9.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.
|
|
16
|
-
"@voltro/database": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/plugin-deactivation": "0.
|
|
19
|
-
"@voltro/protocol": "0.
|
|
20
|
-
"@voltro/runtime": "0.
|
|
15
|
+
"@voltro/cli": "0.9.0",
|
|
16
|
+
"@voltro/database": "0.9.0",
|
|
17
|
+
"@voltro/env": "0.9.0",
|
|
18
|
+
"@voltro/plugin-deactivation": "0.9.0",
|
|
19
|
+
"@voltro/protocol": "0.9.0",
|
|
20
|
+
"@voltro/runtime": "0.9.0",
|
|
21
21
|
"effect": "^3.21.2"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@voltro/testing": "0.
|
|
24
|
+
"@voltro/testing": "0.9.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.
|
|
16
|
-
"@voltro/database": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/plugin-mail": "0.
|
|
19
|
-
"@voltro/plugin-multitenancy": "0.
|
|
20
|
-
"@voltro/protocol": "0.
|
|
21
|
-
"@voltro/runtime": "0.
|
|
15
|
+
"@voltro/cli": "0.9.0",
|
|
16
|
+
"@voltro/database": "0.9.0",
|
|
17
|
+
"@voltro/env": "0.9.0",
|
|
18
|
+
"@voltro/plugin-mail": "0.9.0",
|
|
19
|
+
"@voltro/plugin-multitenancy": "0.9.0",
|
|
20
|
+
"@voltro/protocol": "0.9.0",
|
|
21
|
+
"@voltro/runtime": "0.9.0",
|
|
22
22
|
"effect": "^3.21.2",
|
|
23
23
|
"react": "^19.0.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@voltro/testing": "0.
|
|
26
|
+
"@voltro/testing": "0.9.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.
|
|
16
|
-
"@voltro/database": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/plugin-multitenancy": "0.
|
|
19
|
-
"@voltro/plugin-storage": "0.
|
|
20
|
-
"@voltro/protocol": "0.
|
|
21
|
-
"@voltro/runtime": "0.
|
|
22
|
-
"@voltro/sql-mysql": "0.
|
|
15
|
+
"@voltro/cli": "0.9.0",
|
|
16
|
+
"@voltro/database": "0.9.0",
|
|
17
|
+
"@voltro/env": "0.9.0",
|
|
18
|
+
"@voltro/plugin-multitenancy": "0.9.0",
|
|
19
|
+
"@voltro/plugin-storage": "0.9.0",
|
|
20
|
+
"@voltro/protocol": "0.9.0",
|
|
21
|
+
"@voltro/runtime": "0.9.0",
|
|
22
|
+
"@voltro/sql-mysql": "0.9.0",
|
|
23
23
|
"effect": "^3.21.2"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@voltro/testing": "0.
|
|
26
|
+
"@voltro/testing": "0.9.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.
|
|
14
|
-
"@voltro/database": "0.
|
|
15
|
-
"@voltro/env": "0.
|
|
16
|
-
"@voltro/plugin-multitenancy": "0.
|
|
17
|
-
"@voltro/plugin-storage": "0.
|
|
18
|
-
"@voltro/protocol": "0.
|
|
19
|
-
"@voltro/runtime": "0.
|
|
13
|
+
"@voltro/cli": "0.9.0",
|
|
14
|
+
"@voltro/database": "0.9.0",
|
|
15
|
+
"@voltro/env": "0.9.0",
|
|
16
|
+
"@voltro/plugin-multitenancy": "0.9.0",
|
|
17
|
+
"@voltro/plugin-storage": "0.9.0",
|
|
18
|
+
"@voltro/protocol": "0.9.0",
|
|
19
|
+
"@voltro/runtime": "0.9.0",
|
|
20
20
|
"effect": "^3.21.2"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@voltro/testing": "0.
|
|
23
|
+
"@voltro/testing": "0.9.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.
|
|
15
|
-
"@voltro/database": "0.
|
|
16
|
-
"@voltro/env": "0.
|
|
17
|
-
"@voltro/plugin-governance": "0.
|
|
18
|
-
"@voltro/plugin-multitenancy": "0.
|
|
19
|
-
"@voltro/protocol": "0.
|
|
20
|
-
"@voltro/runtime": "0.
|
|
14
|
+
"@voltro/cli": "0.9.0",
|
|
15
|
+
"@voltro/database": "0.9.0",
|
|
16
|
+
"@voltro/env": "0.9.0",
|
|
17
|
+
"@voltro/plugin-governance": "0.9.0",
|
|
18
|
+
"@voltro/plugin-multitenancy": "0.9.0",
|
|
19
|
+
"@voltro/protocol": "0.9.0",
|
|
20
|
+
"@voltro/runtime": "0.9.0",
|
|
21
21
|
"effect": "^3.21.2"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@voltro/testing": "0.
|
|
24
|
+
"@voltro/testing": "0.9.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.
|
|
15
|
-
"@voltro/database": "0.
|
|
16
|
-
"@voltro/env": "0.
|
|
17
|
-
"@voltro/plugin-multitenancy": "0.
|
|
18
|
-
"@voltro/protocol": "0.
|
|
19
|
-
"@voltro/runtime": "0.
|
|
20
|
-
"@voltro/workflow": "0.
|
|
14
|
+
"@voltro/cli": "0.9.0",
|
|
15
|
+
"@voltro/database": "0.9.0",
|
|
16
|
+
"@voltro/env": "0.9.0",
|
|
17
|
+
"@voltro/plugin-multitenancy": "0.9.0",
|
|
18
|
+
"@voltro/protocol": "0.9.0",
|
|
19
|
+
"@voltro/runtime": "0.9.0",
|
|
20
|
+
"@voltro/workflow": "0.9.0",
|
|
21
21
|
"effect": "^3.21.2"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@voltro/testing": "0.
|
|
24
|
+
"@voltro/testing": "0.9.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.
|
|
16
|
-
"@voltro/database": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/plugin-flags": "0.
|
|
19
|
-
"@voltro/plugin-multitenancy": "0.
|
|
20
|
-
"@voltro/protocol": "0.
|
|
21
|
-
"@voltro/runtime": "0.
|
|
22
|
-
"@voltro/sql-postgres": "0.
|
|
15
|
+
"@voltro/cli": "0.9.0",
|
|
16
|
+
"@voltro/database": "0.9.0",
|
|
17
|
+
"@voltro/env": "0.9.0",
|
|
18
|
+
"@voltro/plugin-flags": "0.9.0",
|
|
19
|
+
"@voltro/plugin-multitenancy": "0.9.0",
|
|
20
|
+
"@voltro/protocol": "0.9.0",
|
|
21
|
+
"@voltro/runtime": "0.9.0",
|
|
22
|
+
"@voltro/sql-postgres": "0.9.0",
|
|
23
23
|
"effect": "^3.21.2"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@voltro/testing": "0.
|
|
26
|
+
"@voltro/testing": "0.9.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.
|
|
16
|
-
"@voltro/database": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/plugin-audit": "0.
|
|
19
|
-
"@voltro/plugin-governance": "0.
|
|
20
|
-
"@voltro/protocol": "0.
|
|
21
|
-
"@voltro/runtime": "0.
|
|
15
|
+
"@voltro/cli": "0.9.0",
|
|
16
|
+
"@voltro/database": "0.9.0",
|
|
17
|
+
"@voltro/env": "0.9.0",
|
|
18
|
+
"@voltro/plugin-audit": "0.9.0",
|
|
19
|
+
"@voltro/plugin-governance": "0.9.0",
|
|
20
|
+
"@voltro/protocol": "0.9.0",
|
|
21
|
+
"@voltro/runtime": "0.9.0",
|
|
22
22
|
"effect": "^3.21.2"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@voltro/testing": "0.
|
|
25
|
+
"@voltro/testing": "0.9.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.
|
|
15
|
-
"@voltro/database": "0.
|
|
16
|
-
"@voltro/env": "0.
|
|
17
|
-
"@voltro/kv": "0.
|
|
18
|
-
"@voltro/plugin-multitenancy": "0.
|
|
19
|
-
"@voltro/protocol": "0.
|
|
20
|
-
"@voltro/runtime": "0.
|
|
14
|
+
"@voltro/cli": "0.9.0",
|
|
15
|
+
"@voltro/database": "0.9.0",
|
|
16
|
+
"@voltro/env": "0.9.0",
|
|
17
|
+
"@voltro/kv": "0.9.0",
|
|
18
|
+
"@voltro/plugin-multitenancy": "0.9.0",
|
|
19
|
+
"@voltro/protocol": "0.9.0",
|
|
20
|
+
"@voltro/runtime": "0.9.0",
|
|
21
21
|
"effect": "^3.21.2"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@voltro/testing": "0.
|
|
24
|
+
"@voltro/testing": "0.9.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.
|
|
16
|
-
"@voltro/database": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/plugin-moderation": "0.
|
|
19
|
-
"@voltro/plugin-multitenancy": "0.
|
|
20
|
-
"@voltro/protocol": "0.
|
|
21
|
-
"@voltro/runtime": "0.
|
|
15
|
+
"@voltro/cli": "0.9.0",
|
|
16
|
+
"@voltro/database": "0.9.0",
|
|
17
|
+
"@voltro/env": "0.9.0",
|
|
18
|
+
"@voltro/plugin-moderation": "0.9.0",
|
|
19
|
+
"@voltro/plugin-multitenancy": "0.9.0",
|
|
20
|
+
"@voltro/protocol": "0.9.0",
|
|
21
|
+
"@voltro/runtime": "0.9.0",
|
|
22
22
|
"effect": "^3.21.2"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@voltro/testing": "0.
|
|
25
|
+
"@voltro/testing": "0.9.0",
|
|
26
26
|
"typescript": "^5.7.0",
|
|
27
27
|
"vitest": "^3.0.0"
|
|
28
28
|
}
|