@voltro/cli 0.2.2 → 0.4.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 (77) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/THIRD-PARTY-NOTICES.md +234 -1
  3. package/bin/voltro.mjs +71 -1
  4. package/dist/apiBuild-CvtQeBMs.js +190 -0
  5. package/dist/apiBuild-DQBNqNZ8.js +2 -0
  6. package/dist/bin.js +2 -2
  7. package/dist/{commands-DQy4812j.js → commands-DhyBIs1O.js} +2381 -1768
  8. package/dist/{dev--jHe1vcu.js → dev-CQxbrpDz.js} +1677 -1626
  9. package/dist/dev-DYjGqPGD.js +2 -0
  10. package/dist/index.d.ts +2 -0
  11. package/dist/index.js +1 -1
  12. package/dist/serveCommand-BZzUJIyo.js +1077 -0
  13. package/dist/serveEntry.js +2 -2
  14. package/package.json +22 -19
  15. package/templates/AGENTS.core.md +61 -0
  16. package/templates/AGENTS.md +61 -0
  17. package/templates/agent-docs/_manifest.json +4 -4
  18. package/templates/agent-docs/ai.md +28 -0
  19. package/templates/agent-docs/authentication.md +5 -2
  20. package/templates/agent-docs/cli.md +98 -0
  21. package/templates/agent-docs/data.md +193 -3
  22. package/templates/agent-docs/database/advancedqueries.md +29 -0
  23. package/templates/agent-docs/database/querying.md +2 -0
  24. package/templates/agent-docs/deployment.md +3 -1
  25. package/templates/agent-docs/internationalization.md +237 -2
  26. package/templates/agent-docs/observability.md +9 -0
  27. package/templates/agent-docs/plugins.md +2 -2
  28. package/templates/agent-docs/reference.md +76 -0
  29. package/templates/agent-docs/schema-driven-ui.md +551 -2
  30. package/templates/agent-docs/templates/apibackends.md +10 -8
  31. package/templates/agent-docs/templates/overview.md +1 -1
  32. package/templates/agent-docs/testing.md +177 -3
  33. package/templates/apps/api-ai/package.json +7 -7
  34. package/templates/apps/api-auth/package.json +8 -8
  35. package/templates/apps/api-backend/package.json +7 -7
  36. package/templates/apps/api-backend-deactivation/package.json +7 -7
  37. package/templates/apps/api-backend-mail/package.json +8 -8
  38. package/templates/apps/api-backend-mariadb/package.json +9 -9
  39. package/templates/apps/api-backend-storage/package.json +8 -8
  40. package/templates/apps/api-data-advanced/package.json +8 -8
  41. package/templates/apps/api-durable/package.json +8 -8
  42. package/templates/apps/api-feature-flags/package.json +9 -9
  43. package/templates/apps/api-governance/package.json +8 -8
  44. package/templates/apps/api-kv/package.json +8 -8
  45. package/templates/apps/api-moderation/package.json +8 -8
  46. package/templates/apps/api-observability/package.json +8 -8
  47. package/templates/apps/api-ratelimit/package.json +8 -8
  48. package/templates/apps/api-rbac/README.md +9 -4
  49. package/templates/apps/api-rbac/mutations/notes.create.mutation.server.ts +1 -1
  50. package/templates/apps/api-rbac/mutations/notes.create.mutation.ts +6 -6
  51. package/templates/apps/api-rbac/package.json +8 -8
  52. package/templates/apps/api-rbac/tests/notes.create.test.ts +8 -8
  53. package/templates/apps/api-rest/package.json +7 -7
  54. package/templates/apps/api-saas/package.json +11 -11
  55. package/templates/apps/api-search/package.json +8 -8
  56. package/templates/apps/api-versioning/package.json +8 -8
  57. package/templates/apps/api-webhooks/package.json +8 -8
  58. package/templates/apps/changelog/package.json +6 -6
  59. package/templates/apps/edge-functions/package.json +2 -2
  60. package/templates/apps/frontend-admin/package.json +8 -8
  61. package/templates/apps/frontend-app/package.json +8 -8
  62. package/templates/apps/frontend-blank/package.json +7 -7
  63. package/templates/apps/frontend-contact/package.json +7 -7
  64. package/templates/apps/frontend-dashboard/package.json +7 -7
  65. package/templates/apps/frontend-docs/package.json +7 -7
  66. package/templates/apps/frontend-i18n/package.json +6 -6
  67. package/templates/apps/frontend-landing/package.json +7 -7
  68. package/templates/apps/frontend-spa/package.json +7 -7
  69. package/templates/apps/frontend-ssr/package.json +7 -7
  70. package/templates/apps/frontend-ssr-api/package.json +8 -8
  71. package/templates/apps/frontend-static-blog/package.json +6 -6
  72. package/templates/baselines/compose/docker/api.Dockerfile +10 -5
  73. package/templates/baselines/compose-mariadb/docker/api.Dockerfile +10 -5
  74. package/dist/apiBuild-OpZROja5.js +0 -2
  75. package/dist/apiBuild-o70rjpVJ.js +0 -184
  76. package/dist/dev-BKkZglQV.js +0 -2
  77. package/dist/serveCommand-93rRdEp0.js +0 -1077
@@ -26,6 +26,7 @@ Everything in it is in-memory and synchronous-friendly — no docker, no running
26
26
  | `makeTestContext(options?)` | The request `ctx` a handler/tool sees at runtime — subject-scoped `ctx.store`, `clock`, `email`, optional `ai`. → [Unit testing](/docs/testing/unit-testing) |
27
27
  | `mockStore(seed)` | Seed rows: `makeTestContext({ store: mockStore({ todos: [...] }) })`. |
28
28
  | `MockClock` / `MockEmail` / `MockLLM` | Deterministic clock, captured email, queued LLM responses. |
29
+ | `makeVoltroTestClient(config)` | The frontend harness — render a component against mocked `useSubscription` / `useMutation`, from the `@voltro/testing/client` subpath. → [Component testing](/docs/testing/component-testing) |
29
30
  | `makeWorkflowRunner({ ctx, workflows })` | Drive a workflow in-process and assert on its steps. → [Workflows](/docs/testing/workflows) |
30
31
  | `runDialectParity(fixture)` | Run one fixture across a SQL dialect for portability — from the `@voltro/testing/dialect` subpath. → [Dialect parity](/docs/testing/dialect-parity) |
31
32
 
@@ -34,9 +35,10 @@ Everything in it is in-memory and synchronous-friendly — no docker, no running
34
35
  Voltro's primitives are designed so the cheapest test covers the most surface. Reach for the lowest layer that proves what you need:
35
36
 
36
37
  1. **Unit — handlers, tools, mutations, queries.** Call the executor directly with a `makeTestContext()` ctx. The store is the real mixin-wrapped store, so tenant scoping, soft-delete, and audit auto-fill all behave as in production — without a database. This is 90% of your tests. See [Unit testing](/docs/testing/unit-testing).
37
- 2. **Workflowdurable, multi-step logic.** `makeWorkflowRunner` drives a workflow end-to-end in-process and hands back the same step log the dashboard shows, including real retry counts. See [Workflows](/docs/testing/workflows).
38
- 3. **Parityhand-written SQL that must stay portable.** `runDialectParity` runs a fixed scenario suite against a dialect you stand up. Mostly for dialect-package authors and apps with `unsafe()` SQL. See [Dialect parity](/docs/testing/dialect-parity).
39
- 4. **End-to-endthe running stack.** `voltro e2e` boots the api + web siblings, runs your tests against the live processes, and tears them down.
38
+ 2. **Componentthe reactive frontend.** `makeVoltroTestClient` renders a component against mocked `useSubscription` / `useMutation`, so loading, empty, stream-error and failing-write branches are all assertable without a running server. See [Component testing](/docs/testing/component-testing).
39
+ 3. **Workflowdurable, multi-step logic.** `makeWorkflowRunner` drives a workflow end-to-end in-process and hands back the same step log the dashboard shows, including real retry counts. See [Workflows](/docs/testing/workflows).
40
+ 4. **Parityhand-written SQL that must stay portable.** `runDialectParity` runs a fixed scenario suite against a dialect you stand up. Mostly for dialect-package authors and apps with `unsafe()` SQL. See [Dialect parity](/docs/testing/dialect-parity).
41
+ 5. **End-to-end — the running stack.** `voltro e2e` boots the api + web siblings, runs your tests against the live processes, and tears them down.
40
42
 
41
43
  Agents are integration tests; tools are unit tests. Don't reach for an e2e harness to assert logic a `makeTestContext` test can prove.
42
44
 
@@ -231,6 +233,178 @@ mock.reset()
231
233
 
232
234
 
233
235
 
236
+ ---
237
+
238
+ <!-- source: en/testing/component-testing.md -->
239
+ ## Component testing
240
+
241
+ _makeVoltroTestClient — the frontend test harness. Render a component against mocked useSubscription / useMutation, inject a loading state, a stream error or a failing write, and assert on every recorded call._
242
+
243
+ ## Why this exists
244
+
245
+ A Voltro frontend is a **reactive-data app**. Its components don't take props and render — they call `useSubscription` for live data and `useMutation` / `useAction` to write. Without a way to render such a component against mocked hooks — and to inject a loading state, a stream error, or a failing write — a component is **structurally untestable**: there is no seam to hand it data, and nothing to assert against. That is exactly why real apps end up with zero frontend tests.
246
+
247
+ `makeVoltroTestClient` closes that gap. It builds a fake api context, hands you a `Provider` to wrap the component under test, and gives you the controls to drive it.
248
+
249
+ ```bash
250
+ pnpm --filter @my-app/web add -D @voltro/testing vitest jsdom react-dom
251
+ ```
252
+
253
+ Import from the **`/client` subpath**, so backend-only test files never pull React:
254
+
255
+ ```ts
256
+ import { makeVoltroTestClient } from '@voltro/testing/client'
257
+ ```
258
+
259
+ ## The surface
260
+
261
+ ```ts
262
+ const harness = makeVoltroTestClient({
263
+ apiName: 'app', // default 'app'
264
+ subscriptions: { 'todos.list': [{ id: '1', title: 'x' }] },
265
+ mutations: { 'todos.create': (input) => ({ id: '2' }) },
266
+ actions: { 'todos.export': async () => ({ url: '/x.csv' }) },
267
+ })
268
+ ```
269
+
270
+ | Config | Meaning |
271
+ |---|---|
272
+ | `apiName` | The api name your components pass to the hooks. Default `'app'`. Asking for a different one throws a loud, named error rather than rendering nothing. |
273
+ | `subscriptions` | Initial data per rpc tag. A tag that is **absent stays in the loading state**. |
274
+ | `mutations` | Handlers per tag. Throw (or reject) to exercise the failure path. |
275
+ | `actions` | Handlers per tag, same shape. |
276
+
277
+ | Returned | Use |
278
+ |---|---|
279
+ | `Provider` | Wrap the component under test. Takes `children`, returns an element. |
280
+ | `setSubscription(tag, data)` | Push new data for a tag — components re-render, exactly like a server delta. |
281
+ | `failSubscription(tag, error)` | Put a tag into the **cold-start error state** (no snapshot + an error). |
282
+ | `resetSubscription(tag)` | Return a tag to the loading state (no snapshot yet). |
283
+ | `calls` | Every mutation / action invoked so far, in order — `{ kind, tag, input }`. |
284
+
285
+ ### Absent tag = loading
286
+
287
+ This is the distinction most worth testing and the easiest to get wrong. A tag with **no fixture** renders the component's loading branch; a tag whose fixture is `[]` renders the *empty* branch. Real apps routinely conflate the two and ship a skeleton that never resolves. The harness makes both states one line apart.
288
+
289
+ ### It is deliberately not a renderer
290
+
291
+ The harness hands you a `Provider` and nothing else about rendering. It works with `react-dom/client` + `act`, with testing-library, or with your own harness, and locks you into none of them. This repo's own tests use `react-dom/client` directly — there is no `@testing-library` dependency anywhere in the framework.
292
+
293
+ ## A worked example
294
+
295
+ Two things React needs before any of this runs: a **DOM environment** (the `// @vitest-environment jsdom` docblock, per file) and **`IS_REACT_ACT_ENVIRONMENT = true`**, without which React refuses to honour `act()` outside a runner it recognises.
296
+
297
+ ```tsx
298
+ // @vitest-environment jsdom
299
+ import { describe, expect, it } from 'vitest'
300
+ import { act, createElement, type ReactElement } from 'react'
301
+ import { createRoot } from 'react-dom/client'
302
+ import { useSubscription, useMutation } from '@voltro/client'
303
+ import { makeVoltroTestClient } from '@voltro/testing/client'
304
+
305
+ // React requires this flag before it will honour act().
306
+ ;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true
307
+
308
+ // The component under test — ordinary app code, no test seams of its own.
309
+ const TodoList = (): ReactElement => {
310
+ const { data, loading, isEmpty } = useSubscription<Array<{ id: string; title: string }>>('app', 'todos.list', {})
311
+ const create = useMutation<{ title: string }, { id: string }>('app', 'todos.create')
312
+ if (loading) return <p>loading</p>
313
+ if (isEmpty) return <p>empty</p>
314
+ return (
315
+ <div>
316
+ <ul>{(data ?? []).map((t) => <li key={t.id}>{t.title}</li>)}</ul>
317
+ <button onClick={() => { void create.mutate({ title: 'new' }, {}) }}>add</button>
318
+ </div>
319
+ )
320
+ }
321
+
322
+ const mount = (harness: ReturnType<typeof makeVoltroTestClient>) => {
323
+ const host = document.createElement('div')
324
+ const root = createRoot(host)
325
+ act(() => { root.render(createElement(harness.Provider, null, createElement(TodoList))) })
326
+ return {
327
+ html: () => host.innerHTML,
328
+ find: <E extends Element>(selector: string): E | null => host.querySelector<E>(selector),
329
+ unmount: () => act(() => { root.unmount() }),
330
+ }
331
+ }
332
+
333
+ describe('TodoList', () => {
334
+ it('renders the loading state when the tag has no data yet', () => {
335
+ const h = makeVoltroTestClient() // no fixture for todos.list
336
+ const view = mount(h)
337
+ expect(view.html()).toContain('loading')
338
+ view.unmount()
339
+ })
340
+
341
+ it('distinguishes EMPTY from loading', () => {
342
+ const h = makeVoltroTestClient({ subscriptions: { 'todos.list': [] } })
343
+ const view = mount(h)
344
+ expect(view.html()).toContain('empty')
345
+ expect(view.html()).not.toContain('loading')
346
+ view.unmount()
347
+ })
348
+
349
+ it('re-renders when a server delta arrives', () => {
350
+ const h = makeVoltroTestClient({ subscriptions: { 'todos.list': [{ id: '1', title: 'first' }] } })
351
+ const view = mount(h)
352
+ expect(view.html()).toContain('first')
353
+
354
+ act(() => { h.setSubscription('todos.list', [{ id: '1', title: 'first' }, { id: '2', title: 'second' }]) })
355
+ expect(view.html()).toContain('second')
356
+ view.unmount()
357
+ })
358
+
359
+ it('handles a dead stream', () => {
360
+ const h = makeVoltroTestClient({ subscriptions: { 'todos.list': [{ id: '1', title: 'x' }] } })
361
+ const view = mount(h)
362
+ act(() => { h.failSubscription('todos.list', new Error('stream died')) })
363
+ expect(view.html()).toContain('loading') // no snapshot → the loading branch
364
+ view.unmount()
365
+ })
366
+
367
+ it('records the write with its input', async () => {
368
+ const h = makeVoltroTestClient({
369
+ subscriptions: { 'todos.list': [{ id: '1', title: 'x' }] },
370
+ mutations: { 'todos.create': () => ({ id: '2' }) },
371
+ })
372
+ const view = mount(h)
373
+ await act(async () => { view.find<HTMLButtonElement>('button')?.click() })
374
+ expect(h.calls).toEqual([{ kind: 'mutation', tag: 'todos.create', input: { title: 'new' } }])
375
+ view.unmount()
376
+ })
377
+ })
378
+ ```
379
+
380
+ ## Testing the failure paths
381
+
382
+ The three failure modes a reactive frontend actually ships broken:
383
+
384
+ - **The infinite skeleton.** `failSubscription(tag, error)` drops the snapshot and sets an error — the cold-start case where data never arrived at all. If your component only branches on `data`, this is the test that catches it.
385
+ - **The write that rejects.** A `mutations` handler that throws surfaces through the component's own error handling. Pass an `onError` to `mutate` and the promise resolves instead of rejecting — assert both that the handler saw the error and that the component still rendered.
386
+ - **The wrong api.** A component asking for an api the harness wasn't built for throws a named error telling you to pass `{ apiName }`, instead of silently rendering an empty tree.
387
+
388
+ ```tsx
389
+ const seen: unknown[] = []
390
+ const h = makeVoltroTestClient({
391
+ subscriptions: { 'todos.list': [{ id: '1', title: 'x' }] },
392
+ mutations: { 'todos.create': () => { throw new Error('nope') } },
393
+ })
394
+ // … click the button, with onError: (e) => { seen.push(e) } …
395
+ expect(h.calls).toHaveLength(1) // the write was attempted
396
+ expect(seen).toHaveLength(1) // handled, not an unhandled rejection
397
+ expect(view.html()).toContain('x') // and the component survived
398
+ ```
399
+
400
+ ## What NOT to do
401
+
402
+ - **Don't mock `@voltro/client` yourself.** Module-mocking the hooks gives you a component that renders but proves nothing about subscription lifecycle — loading, delta, error. The harness drives the real hooks against a fake cache.
403
+ - **Don't reach for e2e to assert a render branch.** Booting api + web to check that an empty list shows "empty" is minutes of runtime for something a `makeVoltroTestClient` test proves in milliseconds. Keep e2e for the flows that genuinely cross the wire.
404
+ - **Don't forget the docblock.** Without `// @vitest-environment jsdom` on the file, `document` doesn't exist and the failure message points at React, not at the missing environment.
405
+
406
+
407
+
234
408
  ---
235
409
 
236
410
  <!-- source: en/testing/workflows.md -->
@@ -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.2.2",
15
- "@voltro/cli": "0.2.2",
16
- "@voltro/database": "0.2.2",
17
- "@voltro/env": "0.2.2",
18
- "@voltro/protocol": "0.2.2",
19
- "@voltro/runtime": "0.2.2",
14
+ "@voltro/ai": "0.4.0",
15
+ "@voltro/cli": "0.4.0",
16
+ "@voltro/database": "0.4.0",
17
+ "@voltro/env": "0.4.0",
18
+ "@voltro/protocol": "0.4.0",
19
+ "@voltro/runtime": "0.4.0",
20
20
  "effect": "^3.21.2"
21
21
  },
22
22
  "devDependencies": {
23
- "@voltro/testing": "0.2.2",
23
+ "@voltro/testing": "0.4.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.2.2",
16
- "@voltro/database": "0.2.2",
17
- "@voltro/env": "0.2.2",
18
- "@voltro/plugin-auth": "0.2.2",
19
- "@voltro/protocol": "0.2.2",
20
- "@voltro/runtime": "0.2.2",
21
- "@voltro/sql-postgres": "0.2.2",
15
+ "@voltro/cli": "0.4.0",
16
+ "@voltro/database": "0.4.0",
17
+ "@voltro/env": "0.4.0",
18
+ "@voltro/plugin-auth": "0.4.0",
19
+ "@voltro/protocol": "0.4.0",
20
+ "@voltro/runtime": "0.4.0",
21
+ "@voltro/sql-postgres": "0.4.0",
22
22
  "effect": "^3.21.2"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.2.2",
25
+ "@voltro/testing": "0.4.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.2.2",
16
- "@voltro/database": "0.2.2",
17
- "@voltro/env": "0.2.2",
18
- "@voltro/plugin-multitenancy": "0.2.2",
19
- "@voltro/protocol": "0.2.2",
20
- "@voltro/runtime": "0.2.2",
15
+ "@voltro/cli": "0.4.0",
16
+ "@voltro/database": "0.4.0",
17
+ "@voltro/env": "0.4.0",
18
+ "@voltro/plugin-multitenancy": "0.4.0",
19
+ "@voltro/protocol": "0.4.0",
20
+ "@voltro/runtime": "0.4.0",
21
21
  "effect": "^3.21.2"
22
22
  },
23
23
  "devDependencies": {
24
- "@voltro/testing": "0.2.2",
24
+ "@voltro/testing": "0.4.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.2.2",
16
- "@voltro/database": "0.2.2",
17
- "@voltro/env": "0.2.2",
18
- "@voltro/plugin-deactivation": "0.2.2",
19
- "@voltro/protocol": "0.2.2",
20
- "@voltro/runtime": "0.2.2",
15
+ "@voltro/cli": "0.4.0",
16
+ "@voltro/database": "0.4.0",
17
+ "@voltro/env": "0.4.0",
18
+ "@voltro/plugin-deactivation": "0.4.0",
19
+ "@voltro/protocol": "0.4.0",
20
+ "@voltro/runtime": "0.4.0",
21
21
  "effect": "^3.21.2"
22
22
  },
23
23
  "devDependencies": {
24
- "@voltro/testing": "0.2.2",
24
+ "@voltro/testing": "0.4.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.2.2",
16
- "@voltro/database": "0.2.2",
17
- "@voltro/env": "0.2.2",
18
- "@voltro/plugin-mail": "0.2.2",
19
- "@voltro/plugin-multitenancy": "0.2.2",
20
- "@voltro/protocol": "0.2.2",
21
- "@voltro/runtime": "0.2.2",
15
+ "@voltro/cli": "0.4.0",
16
+ "@voltro/database": "0.4.0",
17
+ "@voltro/env": "0.4.0",
18
+ "@voltro/plugin-mail": "0.4.0",
19
+ "@voltro/plugin-multitenancy": "0.4.0",
20
+ "@voltro/protocol": "0.4.0",
21
+ "@voltro/runtime": "0.4.0",
22
22
  "effect": "^3.21.2",
23
23
  "react": "^19.0.0"
24
24
  },
25
25
  "devDependencies": {
26
- "@voltro/testing": "0.2.2",
26
+ "@voltro/testing": "0.4.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.2.2",
16
- "@voltro/database": "0.2.2",
17
- "@voltro/env": "0.2.2",
18
- "@voltro/plugin-multitenancy": "0.2.2",
19
- "@voltro/plugin-storage": "0.2.2",
20
- "@voltro/protocol": "0.2.2",
21
- "@voltro/runtime": "0.2.2",
22
- "@voltro/sql-mysql": "0.2.2",
15
+ "@voltro/cli": "0.4.0",
16
+ "@voltro/database": "0.4.0",
17
+ "@voltro/env": "0.4.0",
18
+ "@voltro/plugin-multitenancy": "0.4.0",
19
+ "@voltro/plugin-storage": "0.4.0",
20
+ "@voltro/protocol": "0.4.0",
21
+ "@voltro/runtime": "0.4.0",
22
+ "@voltro/sql-mysql": "0.4.0",
23
23
  "effect": "^3.21.2"
24
24
  },
25
25
  "devDependencies": {
26
- "@voltro/testing": "0.2.2",
26
+ "@voltro/testing": "0.4.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.2.2",
14
- "@voltro/database": "0.2.2",
15
- "@voltro/env": "0.2.2",
16
- "@voltro/plugin-multitenancy": "0.2.2",
17
- "@voltro/plugin-storage": "0.2.2",
18
- "@voltro/protocol": "0.2.2",
19
- "@voltro/runtime": "0.2.2",
13
+ "@voltro/cli": "0.4.0",
14
+ "@voltro/database": "0.4.0",
15
+ "@voltro/env": "0.4.0",
16
+ "@voltro/plugin-multitenancy": "0.4.0",
17
+ "@voltro/plugin-storage": "0.4.0",
18
+ "@voltro/protocol": "0.4.0",
19
+ "@voltro/runtime": "0.4.0",
20
20
  "effect": "^3.21.2"
21
21
  },
22
22
  "devDependencies": {
23
- "@voltro/testing": "0.2.2",
23
+ "@voltro/testing": "0.4.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.2.2",
15
- "@voltro/database": "0.2.2",
16
- "@voltro/env": "0.2.2",
17
- "@voltro/plugin-governance": "0.2.2",
18
- "@voltro/plugin-multitenancy": "0.2.2",
19
- "@voltro/protocol": "0.2.2",
20
- "@voltro/runtime": "0.2.2",
14
+ "@voltro/cli": "0.4.0",
15
+ "@voltro/database": "0.4.0",
16
+ "@voltro/env": "0.4.0",
17
+ "@voltro/plugin-governance": "0.4.0",
18
+ "@voltro/plugin-multitenancy": "0.4.0",
19
+ "@voltro/protocol": "0.4.0",
20
+ "@voltro/runtime": "0.4.0",
21
21
  "effect": "^3.21.2"
22
22
  },
23
23
  "devDependencies": {
24
- "@voltro/testing": "0.2.2",
24
+ "@voltro/testing": "0.4.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.2.2",
15
- "@voltro/database": "0.2.2",
16
- "@voltro/env": "0.2.2",
17
- "@voltro/plugin-multitenancy": "0.2.2",
18
- "@voltro/protocol": "0.2.2",
19
- "@voltro/runtime": "0.2.2",
20
- "@voltro/workflow": "0.2.2",
14
+ "@voltro/cli": "0.4.0",
15
+ "@voltro/database": "0.4.0",
16
+ "@voltro/env": "0.4.0",
17
+ "@voltro/plugin-multitenancy": "0.4.0",
18
+ "@voltro/protocol": "0.4.0",
19
+ "@voltro/runtime": "0.4.0",
20
+ "@voltro/workflow": "0.4.0",
21
21
  "effect": "^3.21.2"
22
22
  },
23
23
  "devDependencies": {
24
- "@voltro/testing": "0.2.2",
24
+ "@voltro/testing": "0.4.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.2.2",
16
- "@voltro/database": "0.2.2",
17
- "@voltro/env": "0.2.2",
18
- "@voltro/plugin-flags": "0.2.2",
19
- "@voltro/plugin-multitenancy": "0.2.2",
20
- "@voltro/protocol": "0.2.2",
21
- "@voltro/runtime": "0.2.2",
22
- "@voltro/sql-postgres": "0.2.2",
15
+ "@voltro/cli": "0.4.0",
16
+ "@voltro/database": "0.4.0",
17
+ "@voltro/env": "0.4.0",
18
+ "@voltro/plugin-flags": "0.4.0",
19
+ "@voltro/plugin-multitenancy": "0.4.0",
20
+ "@voltro/protocol": "0.4.0",
21
+ "@voltro/runtime": "0.4.0",
22
+ "@voltro/sql-postgres": "0.4.0",
23
23
  "effect": "^3.21.2"
24
24
  },
25
25
  "devDependencies": {
26
- "@voltro/testing": "0.2.2",
26
+ "@voltro/testing": "0.4.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.2.2",
16
- "@voltro/database": "0.2.2",
17
- "@voltro/env": "0.2.2",
18
- "@voltro/plugin-audit": "0.2.2",
19
- "@voltro/plugin-governance": "0.2.2",
20
- "@voltro/protocol": "0.2.2",
21
- "@voltro/runtime": "0.2.2",
15
+ "@voltro/cli": "0.4.0",
16
+ "@voltro/database": "0.4.0",
17
+ "@voltro/env": "0.4.0",
18
+ "@voltro/plugin-audit": "0.4.0",
19
+ "@voltro/plugin-governance": "0.4.0",
20
+ "@voltro/protocol": "0.4.0",
21
+ "@voltro/runtime": "0.4.0",
22
22
  "effect": "^3.21.2"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.2.2",
25
+ "@voltro/testing": "0.4.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.2.2",
15
- "@voltro/database": "0.2.2",
16
- "@voltro/env": "0.2.2",
17
- "@voltro/kv": "0.2.2",
18
- "@voltro/plugin-multitenancy": "0.2.2",
19
- "@voltro/protocol": "0.2.2",
20
- "@voltro/runtime": "0.2.2",
14
+ "@voltro/cli": "0.4.0",
15
+ "@voltro/database": "0.4.0",
16
+ "@voltro/env": "0.4.0",
17
+ "@voltro/kv": "0.4.0",
18
+ "@voltro/plugin-multitenancy": "0.4.0",
19
+ "@voltro/protocol": "0.4.0",
20
+ "@voltro/runtime": "0.4.0",
21
21
  "effect": "^3.21.2"
22
22
  },
23
23
  "devDependencies": {
24
- "@voltro/testing": "0.2.2",
24
+ "@voltro/testing": "0.4.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.2.2",
16
- "@voltro/database": "0.2.2",
17
- "@voltro/env": "0.2.2",
18
- "@voltro/plugin-moderation": "0.2.2",
19
- "@voltro/plugin-multitenancy": "0.2.2",
20
- "@voltro/protocol": "0.2.2",
21
- "@voltro/runtime": "0.2.2",
15
+ "@voltro/cli": "0.4.0",
16
+ "@voltro/database": "0.4.0",
17
+ "@voltro/env": "0.4.0",
18
+ "@voltro/plugin-moderation": "0.4.0",
19
+ "@voltro/plugin-multitenancy": "0.4.0",
20
+ "@voltro/protocol": "0.4.0",
21
+ "@voltro/runtime": "0.4.0",
22
22
  "effect": "^3.21.2"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.2.2",
25
+ "@voltro/testing": "0.4.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.2.2",
16
- "@voltro/database": "0.2.2",
17
- "@voltro/plugin-multitenancy": "0.2.2",
18
- "@voltro/plugin-prometheus": "0.2.2",
19
- "@voltro/plugin-sentry": "0.2.2",
20
- "@voltro/protocol": "0.2.2",
21
- "@voltro/runtime": "0.2.2",
15
+ "@voltro/cli": "0.4.0",
16
+ "@voltro/database": "0.4.0",
17
+ "@voltro/plugin-multitenancy": "0.4.0",
18
+ "@voltro/plugin-prometheus": "0.4.0",
19
+ "@voltro/plugin-sentry": "0.4.0",
20
+ "@voltro/protocol": "0.4.0",
21
+ "@voltro/runtime": "0.4.0",
22
22
  "effect": "^3.21.2"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.2.2",
25
+ "@voltro/testing": "0.4.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.2.2",
16
- "@voltro/database": "0.2.2",
17
- "@voltro/env": "0.2.2",
18
- "@voltro/plugin-multitenancy": "0.2.2",
19
- "@voltro/plugin-ratelimit": "0.2.2",
20
- "@voltro/protocol": "0.2.2",
21
- "@voltro/runtime": "0.2.2",
15
+ "@voltro/cli": "0.4.0",
16
+ "@voltro/database": "0.4.0",
17
+ "@voltro/env": "0.4.0",
18
+ "@voltro/plugin-multitenancy": "0.4.0",
19
+ "@voltro/plugin-ratelimit": "0.4.0",
20
+ "@voltro/protocol": "0.4.0",
21
+ "@voltro/runtime": "0.4.0",
22
22
  "effect": "^3.21.2"
23
23
  },
24
24
  "devDependencies": {
25
- "@voltro/testing": "0.2.2",
25
+ "@voltro/testing": "0.4.0",
26
26
  "typescript": "^5.7.0",
27
27
  "vitest": "^3.0.0"
28
28
  }