Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
<PackageVersion Include="FSharp.Core" Version="9.0.100" />
<PackageVersion Include="FSharp.SystemTextJson" Version="1.3.13" />
<PackageVersion Include="JasperFx" Version="2.2.1" />
<PackageVersion Include="JasperFx.Events" Version="2.2.1" />
<PackageVersion Include="JasperFx.Events.SourceGenerator" Version="2.2.1">
<PackageVersion Include="JasperFx" Version="2.4.0" />
<PackageVersion Include="JasperFx.Events" Version="2.4.0" />
<PackageVersion Include="JasperFx.Events.SourceGenerator" Version="2.4.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
<PackageVersion Include="JasperFx.SourceGenerator" Version="2.2.1" />
<PackageVersion Include="JasperFx.SourceGenerator" Version="2.4.0" />
<PackageVersion Include="Jil" Version="3.0.0-alpha2" />
<PackageVersion Include="Lamar" Version="7.1.1" />
<PackageVersion Include="Lamar.Microsoft.DependencyInjection" Version="15.0.0" />
Expand Down
1 change: 1 addition & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ const config: UserConfig<DefaultTheme.Config> = {
{ text: 'Json Serialization', link: '/configuration/json' },
{ text: 'Resiliency Policies', link: '/configuration/retries' },
{ text: 'Command Line Tooling', link: '/configuration/cli' },
{ text: 'JasperFx Commands in the Aspire Dashboard', link: '/configuration/aspire-commands' },
{ text: 'Optimized Development Workflow', link: '/configuration/optimized_artifact_workflow' },
{ text: 'Publishing with Native AOT', link: '/configuration/aot-publishing' },
{ text: 'Multi-Tenancy with Database per Tenant', link: '/configuration/multitenancy' },
Expand Down
129 changes: 129 additions & 0 deletions docs/configuration/aspire-commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# JasperFx Commands in the Aspire Dashboard <Badge type="tip" text="9.4" />

The optional **`JasperFx.Aspire`** package adds Marten's command-line verbs as
clickable **custom commands** on each resource tile in the
[.NET Aspire dashboard](https://learn.microsoft.com/en-us/dotnet/aspire/fundamentals/dashboard).
With one extension call in your AppHost project, an operator running the
Aspire dashboard against a local or staging environment can run
**`check-env`**, **`describe`**, **`projections`**, or **`resources`** against
a live Marten service without dropping to a terminal — output streams back
into the dashboard's resource console.

Marten apps inherit this for free because they build on the shared JasperFx
command layer. See also the page on [Command Line Tooling](/configuration/cli)
for the local-terminal workflow and the
[JasperFx.Aspire package README](https://github.com/JasperFx/jasperfx/tree/master/src/JasperFx.Aspire).

## Quick start

Add the package to your **Aspire AppHost** project (not the Marten service
project itself):

```shell
dotnet add package JasperFx.Aspire
```

Then opt in on the Marten service resource:

```csharp
using JasperFx.Aspire;

var builder = DistributedApplication.CreateBuilder(args);

builder.AddProject<Projects.MartenApi>("api")
.WithJasperFxCommands();
```

That adds the **safe-by-default** command buttons — `check-env`, `describe`,
and `codegen` (preview only) — to the `api` resource tile. Click any of them
in the dashboard, the verb runs against the live service with the same
environment Aspire injects, and the output streams into the resource's log
view.

## The verbs that matter for Marten users

- **`check-env`** *(read-only)* — runs every registered
[environment check](/configuration/environment-checks). Confirms the Marten
service can reach its Postgres database, that all projection dependencies
are wired, that required schemas exist, etc.
- **`describe`** *(read-only)* — dumps the resolved Marten `StoreOptions`
(document mappings, event store config, projections, retry policies,
tenancy strategy, …). Useful for verifying composite configuration.
- **`resources`** *(mutating)* — applies / patches Marten's schema objects
(`mt_events`, document tables, indexes, functions, projection tables).
Equivalent to `IDocumentStore.Storage.ApplyAllConfiguredChangesToDatabaseAsync()`.
- **`projections`** *(mutating)* — runs or **rebuilds** async projections.
The rebuild path reprocesses the event store — long-running and
disruptive on a populated store.

## Opting in to mutating verbs

Mutating verbs are off by default. Adding them is a one-liner:

```csharp
builder.AddProject<Projects.MartenApi>("api")
.WithJasperFxCommands(opts =>
{
// Adds resources + projections + codegen-write buttons.
opts.IncludeMutatingCommands = true;
});
```

When `IncludeMutatingCommands = true`, every mutating verb requires an
explicit **confirmation dialog** in the Aspire dashboard before it runs.
The default confirmation copy is generic ("Run `projections` on `api`?");
customize per-verb when the impact is non-obvious:

```csharp
builder.AddProject<Projects.MartenApi>("api")
.WithJasperFxCommands(opts =>
{
opts.IncludeMutatingCommands = true;

opts.For("projections").ConfirmationMessage =
"Rebuild ALL projections for 'api'? This reprocesses the entire event store.";

opts.For("resources").ConfirmationMessage =
"Apply pending schema changes to the 'api' database?";
});
```

## Per-verb tweaks

`opts.For("verb")` returns a `JasperFxCommandRegistration` that lets you
override the dashboard presentation per verb:

| Property | Use |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DisplayName` | Button label (defaults to a humanized verb name). |
| `DisplayDescription` | Tooltip / extended description. |
| `IconName` | Fluent UI icon name; sensible defaults per verb. |
| `ConfirmationMessage` | Required for mutating verbs; setting this opts a non-mutating verb into confirmation too. |
| `IsHighlighted` | Pins the button to the front of the strip. |
| `IsEnabled` | Predicate over the resource's current `ResourceState` — useful for gating verbs to `Running` (or `Running` + the migration-resource-completed state for `projections`). |

## Adding a single verb

When the curated default set isn't quite what you want, register verbs
one-at-a-time with `WithJasperFxCommand` instead of the batch helper:

```csharp
builder.AddProject<Projects.MartenApi>("api")
.WithJasperFxCommand("projections", "rebuild MyProjection", registration =>
{
registration.DisplayName = "Rebuild MyProjection";
registration.ConfirmationMessage =
"Rebuild MyProjection for 'api'? This reprocesses the event store.";
registration.IsHighlighted = true;
});
```

The second argument is the verb's fixed argument string — handy for
locking a button down to one specific projection rather than exposing the
full `projections` surface.

## Constraints

- **`JasperFx.Aspire` runs at the AppHost project layer**, not inside the Marten service itself. Adding it as a `<ProjectReference>` of the service project is a no-op.
- The verbs run in a **child process** of the Marten service, with the same environment Aspire injects into the resource. If `check-env`, `resources`, or `projections` fail to reach Aspire-managed dependencies, verify the dashboard shows the resource as `Running` first.
- Buttons require `ApplyJasperFxExtensions()` + `RunJasperFxCommandsAsync(args)` to already be wired in the Marten service's `Program.cs` (see [Command Line Tooling](/configuration/cli)). Without that wiring the verb spawn succeeds but the child process won't recognize the verb.
7 changes: 7 additions & 0 deletions docs/configuration/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ libraries. For the full reference of available commands, extensibility points, a
see the [JasperFx shared libraries documentation](https://shared-libs.jasperfx.net/).
:::

::: tip
Running an AppHost with .NET Aspire? The optional `JasperFx.Aspire` package
surfaces these same verbs as clickable buttons on each resource tile in the
Aspire dashboard — see
[JasperFx Commands in the Aspire Dashboard](/configuration/aspire-commands).
:::

::: warning
The usage of JasperFx commands shown in this document are only valid for applications bootstrapped with the
[generic host builder](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host) with Marten registered in the application's IoC container.
Expand Down
Loading