Skip to content

JasperFx.Aspire — JasperFx CLI verbs as Aspire dashboard commands (A1)#402

Merged
jeremydmiller merged 2 commits into
mainfrom
feat-jasperfx-aspire-commands
May 31, 2026
Merged

JasperFx.Aspire — JasperFx CLI verbs as Aspire dashboard commands (A1)#402
jeremydmiller merged 2 commits into
mainfrom
feat-jasperfx-aspire-commands

Conversation

@jeremydmiller
Copy link
Copy Markdown
Member

Implements A1 from the design doc (.claude/docs/jasperfx-aspire-command-integration-design.md): a new JasperFx.Aspire hosting package that surfaces a JasperFx app's command-line verbs as clickable custom commands on the resource tile in the .NET Aspire dashboard.

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

Because Marten, Wolverine, and Polecat all build on the same JasperFx command infrastructure, this lights up for the entire Critter Stack with no per-product code.

What's here (Phase 1)

  • WithJasperFxCommands / WithJasperFxCommand extensions + JasperFxCommandOptions / JasperFxCommandRegistration. Read-only verbs (check-env, describe, codegen preview) are added by default; mutating verbs (codegen write, resources, projections) require IncludeMutatingCommands and each get a confirmation prompt.
  • JasperFxVerbCatalog — curated static metadata for the standard verbs (zero runtime coupling to the target). Unknown/product-specific verbs are accepted and treated as mutating (safe-by-default).
  • JasperFxCommandExecutor — the dashboard callback runs in the AppHost, so it spawns a short-lived child of the same app (dotnet run --project <csproj> --no-build -- <verb>) with the resource's resolved environment (evaluated from its EnvironmentCallbackAnnotations — connection strings etc.) layered on the inherited AppHost env. Child stdout/stderr stream into the resource's dashboard logs via ResourceLoggerService; the exit code maps to the success/failure toast.

Aspire version

Targets net10.0 against Aspire.Hosting 13.3.1 (Aspire 13 is net10-first), using the 9.2+ CommandOptions WithCommand overload. The design doc said "pin to 9.x" — that predates Aspire's move to 13.x calendar versioning; 13.x is the current stable and the API is the same CommandOptions shape.

De-risking spike (design step 0)

The riskiest mechanic — resolving a resource's Aspire-managed environment inside the command callback — is validated at the API level: the whole surface (WithCommand/CommandOptions, EnvironmentCallbackContext evaluation, IValueProvider.GetValueAsync, ResourceLoggerService, KnownResourceStates) compiles against real Aspire 13.3.1, and the standalone sample (src/AspireSample) integrates it into a real AppHost.

Verification

  • dotnet build jasperfx.sln -c Release clean.
  • ✅ 16 unit tests (catalog selection/templating; executor ProcessStartInfo construction + exit-code mapping).
  • ✅ Sample AppHost + API compile against the package.
  • ⚠️ Manual step remaining: the dashboard click-through (dotnet run --project src/AspireSample/AspireSample.AppHost, click Check environment on the api tile) — the end-to-end env-resolution proof can't be automated headlessly. Steps in src/AspireSample/README.md.

The sample is intentionally out of jasperfx.sln so core CI isn't burdened with the Aspire AppHost SDK + Postgres hosting restore.

Deferred to follow-ups

  • Phase 2: a machine-readable describe --json in JasperFx core so the catalog is discovered dynamically from the target (incl. product-specific/custom verbs) instead of curated.
  • Downstream docs in Marten / Wolverine / Polecat (tracking issues filed separately).

🤖 Generated with Claude Code

…ands (A1)

New JasperFx.Aspire hosting package. One line of AppHost code adds clickable
custom commands to a resource tile in the .NET Aspire dashboard for a JasperFx
app's CLI verbs (check-env, describe, codegen, resources, projections):

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

Because Marten, Wolverine, and Polecat all build on the same JasperFx command
infrastructure, this lights up for the whole Critter Stack with no per-product code.

Implementation (Phase 1 — curated catalog, zero runtime coupling to the target):
- WithJasperFxCommands / WithJasperFxCommand extensions + JasperFxCommandOptions /
  JasperFxCommandRegistration. Read-only verbs (check-env, describe, codegen preview)
  are added by default; mutating verbs (codegen write, resources, projections) require
  IncludeMutatingCommands and each get a confirmation prompt.
- JasperFxVerbCatalog: static metadata (verb, mutating?, icon, display text, default
  confirmation) for the standard verbs; unknown verbs are treated as mutating.
- JasperFxCommandExecutor: the dashboard callback runs in the AppHost, so it spawns a
  short-lived child of the same app — `dotnet run --project <csproj> --no-build -- <verb>` —
  with the resource's *resolved* environment evaluated from its EnvironmentCallbackAnnotations
  (connection strings, etc.) layered on the inherited AppHost env. Child stdout/stderr stream
  into the resource's dashboard logs via ResourceLoggerService; exit code maps to the toast.

Targets net10.0 against Aspire.Hosting 13.3.1 (Aspire 13 is net10-first; uses the 9.2+
CommandOptions WithCommand overload). 16 unit tests cover the catalog selection/templating
and the executor's ProcessStartInfo construction + exit-code mapping. A standalone sample
under src/AspireSample (Postgres + a check-env that needs the injected connection string) is
kept out of jasperfx.sln for manual dashboard click-through. Wired into the NugetPack target.

Deferred (Phase 2, follow-up): a machine-readable `describe --json` so the catalog can be
discovered dynamically from the target instead of curated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New /cli/aspire page documenting WithJasperFxCommands — the curated read-only
verbs, mutating opt-in + confirmation, single-command registration, the
spawn-child-with-resolved-environment mechanic (with a mermaid sequence diagram),
safety, and requirements. Added under the Command Line sidebar section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jeremydmiller jeremydmiller merged commit ab8e38e into main May 31, 2026
1 check passed
jeremydmiller added a commit to JasperFx/marten that referenced this pull request Jun 1, 2026
…mp JasperFx.* 2.2.1 → 2.4.0 (#4593)

The new JasperFx.Aspire package (JasperFx/jasperfx#402) surfaces a JasperFx
app's CLI verbs as clickable custom commands on each resource tile in the
.NET Aspire dashboard. Marten apps inherit this for free because they build
on the JasperFx command layer.

New page: docs/configuration/aspire-commands.md
- Quick-start: WithJasperFxCommands() one-liner on the Marten service
  resource in the Aspire AppHost project.
- Highlights the four verbs that matter most for Marten: check-env,
  describe, resources, projections.
- Confirmation behavior for mutating verbs + per-verb customization
  (DisplayName, ConfirmationMessage, IconName, IsHighlighted, IsEnabled).
- WithJasperFxCommand single-verb registration with fixed-args (the
  "rebuild MyProjection only" recipe).
- Constraint notes: AppHost-layer only, child-process verb spawn picks
  up Aspire-injected env, requires ApplyJasperFxExtensions + RunJasperFxCommandsAsync
  wiring in the service's Program.cs.

Wired into the sidebar under "Command Line Tooling" in
docs/.vitepress/config.mts; reciprocal cross-link added at the top of
docs/configuration/cli.md so anyone landing on the CLI page sees the
Aspire entry-point too.

Dependency bump: JasperFx, JasperFx.Events, JasperFx.SourceGenerator,
JasperFx.Events.SourceGenerator 2.2.1 → 2.4.0 in Directory.Packages.props
to pull in the package referenced by the new docs.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant