From a0e4ad137039ca5213f1d6e77fb9979d8baf33f8 Mon Sep 17 00:00:00 2001 From: David Pine <7679720+IEvangelist@users.noreply.github.com> Date: Fri, 17 Jul 2026 12:11:33 -0500 Subject: [PATCH 1/5] Split Dapr DAB and LavinMQ integration docs Create get-started, host, and connect suites with source-verified AppHost APIs, connection properties, polyglot clients, navigation, mappings, and redirects. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 239a58a9-4a99-4706-bd16-dfbe22da34ea --- src/frontend/config/redirects.mjs | 3 + .../config/sidebar/integrations.topics.ts | 57 +++- .../docs/integrations/devtools/dab.mdx | 307 ------------------ .../integrations/devtools/dab/dab-connect.mdx | 148 +++++++++ .../devtools/dab/dab-get-started.mdx | 83 +++++ .../integrations/devtools/dab/dab-host.mdx | 213 ++++++++++++ .../docs/integrations/frameworks/dapr.mdx | 256 --------------- .../frameworks/dapr/dapr-connect.mdx | 172 ++++++++++ .../frameworks/dapr/dapr-get-started.mdx | 93 ++++++ .../frameworks/dapr/dapr-host.mdx | 219 +++++++++++++ .../docs/integrations/messaging/lavinmq.mdx | 237 -------------- .../messaging/lavinmq/lavinmq-connect.mdx | 175 ++++++++++ .../messaging/lavinmq/lavinmq-get-started.mdx | 87 +++++ .../messaging/lavinmq/lavinmq-host.mdx | 193 +++++++++++ src/frontend/src/data/integration-docs.json | 16 +- 15 files changed, 1448 insertions(+), 811 deletions(-) delete mode 100644 src/frontend/src/content/docs/integrations/devtools/dab.mdx create mode 100644 src/frontend/src/content/docs/integrations/devtools/dab/dab-connect.mdx create mode 100644 src/frontend/src/content/docs/integrations/devtools/dab/dab-get-started.mdx create mode 100644 src/frontend/src/content/docs/integrations/devtools/dab/dab-host.mdx delete mode 100644 src/frontend/src/content/docs/integrations/frameworks/dapr.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-connect.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-get-started.mdx create mode 100644 src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-host.mdx delete mode 100644 src/frontend/src/content/docs/integrations/messaging/lavinmq.mdx create mode 100644 src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-connect.mdx create mode 100644 src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-get-started.mdx create mode 100644 src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-host.mdx diff --git a/src/frontend/config/redirects.mjs b/src/frontend/config/redirects.mjs index 64c11cbe1..dd62c474a 100644 --- a/src/frontend/config/redirects.mjs +++ b/src/frontend/config/redirects.mjs @@ -178,11 +178,14 @@ export const redirects = { '/integrations/devtools/flagd/': '/integrations/devtools/flagd/flagd-get-started/', '/integrations/devtools/goff/': '/integrations/devtools/goff/goff-get-started/', '/integrations/devtools/mailpit/': '/integrations/devtools/mailpit/mailpit-get-started/', + '/integrations/devtools/dab/': '/integrations/devtools/dab/dab-get-started/', + '/integrations/frameworks/dapr/': '/integrations/frameworks/dapr/dapr-get-started/', '/integrations/frameworks/go/': '/integrations/frameworks/go/go-get-started/', '/integrations/frameworks/go-apps/': '/integrations/frameworks/go/go-get-started/', '/ja/integrations/frameworks/go-apps/': '/integrations/frameworks/go/go-get-started/', '/integrations/frameworks/csharp-file-based-apps/': '/integrations/dotnet/csharp-file-based-apps/', '/integrations/frameworks/maui/': '/integrations/dotnet/maui/', + '/integrations/messaging/lavinmq/': '/integrations/messaging/lavinmq/lavinmq-get-started/', '/fundamentals/service-defaults/': '/get-started/csharp-service-defaults/', '/fundamentals/launch-profiles/': '/integrations/dotnet/launch-profiles/', '/ja/fundamentals/service-defaults/': '/ja/get-started/csharp-service-defaults/', diff --git a/src/frontend/config/sidebar/integrations.topics.ts b/src/frontend/config/sidebar/integrations.topics.ts index 9003ee9e4..027273135 100644 --- a/src/frontend/config/sidebar/integrations.topics.ts +++ b/src/frontend/config/sidebar/integrations.topics.ts @@ -1346,7 +1346,24 @@ export const integrationTopics: StarlightSidebarTopicsUserConfig = { { label: 'Orleans', slug: 'integrations/frameworks/orleans' }, ], }, - { label: 'Dapr', slug: 'integrations/frameworks/dapr' }, + { + label: 'Dapr', + collapsed: true, + items: [ + { + label: 'Get started', + slug: 'integrations/frameworks/dapr/dapr-get-started', + }, + { + label: 'Set up Dapr resources in the AppHost', + slug: 'integrations/frameworks/dapr/dapr-host', + }, + { + label: 'Connect to Dapr', + slug: 'integrations/frameworks/dapr/dapr-connect', + }, + ], + }, { label: 'Go', collapsed: true, @@ -1434,7 +1451,24 @@ export const integrationTopics: StarlightSidebarTopicsUserConfig = { }, ], }, - { label: 'LavinMQ', slug: 'integrations/messaging/lavinmq' }, + { + label: 'LavinMQ', + collapsed: true, + items: [ + { + label: 'Get started', + slug: 'integrations/messaging/lavinmq/lavinmq-get-started', + }, + { + label: 'Set up LavinMQ in the AppHost', + slug: 'integrations/messaging/lavinmq/lavinmq-host', + }, + { + label: 'Connect to LavinMQ', + slug: 'integrations/messaging/lavinmq/lavinmq-connect', + }, + ], + }, { label: 'NATS', collapsed: true, @@ -1605,7 +1639,24 @@ export const integrationTopics: StarlightSidebarTopicsUserConfig = { }, slug: 'integrations/devtools/browser-logs', }, - { label: 'Data API Builder', slug: 'integrations/devtools/dab' }, + { + label: 'Data API Builder', + collapsed: true, + items: [ + { + label: 'Get started', + slug: 'integrations/devtools/dab/dab-get-started', + }, + { + label: 'Set up Data API Builder in the AppHost', + slug: 'integrations/devtools/dab/dab-host', + }, + { + label: 'Connect to Data API Builder', + slug: 'integrations/devtools/dab/dab-connect', + }, + ], + }, { label: 'Dev Tunnels', slug: 'integrations/devtools/dev-tunnels' }, { label: 'flagd', diff --git a/src/frontend/src/content/docs/integrations/devtools/dab.mdx b/src/frontend/src/content/docs/integrations/devtools/dab.mdx deleted file mode 100644 index 64b7cc2f6..000000000 --- a/src/frontend/src/content/docs/integrations/devtools/dab.mdx +++ /dev/null @@ -1,307 +0,0 @@ ---- -title: Data API builder integration -seoTitle: Data API builder integration for Aspire AppHost projects -description: Learn how to use the Aspire Data API Builder hosting integration to orchestrate and configure a Data API Builder resource in an Aspire solution. ---- - -import { Image } from 'astro:assets'; -import { Badge, Tabs, TabItem } from '@astrojs/starlight/components'; -import LearnMore from '@components/LearnMore.astro'; -import dabIcon from '@assets/icons/data-api-builder-icon.png'; - - - -Data API builder logo - -This article is the reference for the Aspire Data API Builder hosting integration. It enumerates the AppHost APIs that you use to model a [Data API Builder](https://learn.microsoft.com/azure/data-api-builder/overview) (DAB) resource in your [`AppHost`](/get-started/app-host/) project. DAB is an open-source tool that generates REST and GraphQL APIs directly from your database schema. - -## Installation - -To start building an Aspire app that uses Data API Builder, install the [📦 CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder) NuGet package: - - - - -```bash title="Terminal" -aspire add CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder -``` - - - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. - - -Or, choose a manual installation approach: - -```csharp title="AppHost.cs" -#:package CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder@* -``` - -```xml title="AppHost.csproj" - -``` - - - - -```bash title="Terminal" -aspire add CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder -``` - - - Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) in the command reference. - - -This updates your `aspire.config.json` with the Data API Builder hosting integration package: - -```json title="aspire.config.json" ins={3} -{ - "packages": { - "CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder": "*" - } -} -``` - -The TypeScript AppHost bindings for Data API Builder are provided by the Community Toolkit package. After installation, the `.aspire/modules/aspire.mjs` file in your project includes `addDataAPIBuilder` and related APIs. - - - - -## Add Data API Builder resource - -Once you've installed the hosting integration in your AppHost project, you can add a Data API Builder resource and reference a database as shown in the following example: - - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var sqldb = builder.AddSqlServer("sql") - .AddDatabase("sqldb"); - -var dab = builder.AddDataAPIBuilder("dab") - .WithReference(sqldb); - -builder.AddProject("example-project") - .WithReference(dab); - -// After adding all resources, run the app... -builder.Build().Run(); -``` - - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const sqldb = await (await builder.addSqlServer("sql")).addDatabase("sqldb"); - -const dab = await builder.addDataAPIBuilder("dab"); -await dab.withReference(sqldb); - -const exampleProject = await builder.addProject( - "example-project", - "../ExampleProject/ExampleProject.csproj"); -await exampleProject.withReference(dab); - -// After adding all resources, run the app... -``` - - - - -The Data API Builder integration automatically discovers and uses `dab-config.json` configuration files in your project. - -## Multiple configuration files - -Data API Builder supports multiple configuration files for different databases. To specify multiple configuration files, pass an array of config file paths to `AddDataAPIBuilder` or `addDataAPIBuilder`: - - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var sql = builder.AddSqlServer("sql") - .AddDatabase("sqldb"); - -var postgres = builder.AddPostgres("postgres") - .AddDatabase("postgresdb"); - -var dab = builder.AddDataAPIBuilder("dab", ["dab-config.SqlServer.json", "dab-config.PostgreSQL.json"]) - .WithReference(sql) - .WithReference(postgres); - -// After adding all resources, run the app... -builder.Build().Run(); -``` - - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const sql = await (await builder.addSqlServer("sql")).addDatabase("sqldb"); -const postgres = await (await builder.addPostgres("postgres")).addDatabase("postgresdb"); - -const dab = await builder.addDataAPIBuilder("dab", { - configFilePaths: ["dab-config.SqlServer.json", "dab-config.PostgreSQL.json"], -}); -await dab.withReference(sql); -await dab.withReference(postgres); - -// After adding all resources, run the app... -``` - - - - -## Custom container images - -To use a custom Data API Builder container image, use the container image methods: - - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var dab = builder.AddDataAPIBuilder("dab") - .WithImageRegistry("myregistry.azurecr.io") - .WithImage("custom-dab") - .WithImageTag("1.0.0"); - -// After adding all resources, run the app... -builder.Build().Run(); -``` - - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const dab = await builder.addDataAPIBuilder("dab"); -await dab.withImageRegistry("myregistry.azurecr.io"); -await dab.withImage("custom-dab"); -await dab.withImageTag("1.0.0"); - -// After adding all resources, run the app... -``` - - - - -## Database references - -Data API Builder requires references to the databases it exposes. Use `WithReference` or `withReference` to connect Data API Builder to your databases: - - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var sql = builder.AddSqlServer("sql") - .AddDatabase("sqldb"); - -var cosmos = builder.AddAzureCosmosDB("cosmos") - .AddDatabase("cosmosdb"); - -var dab = builder.AddDataAPIBuilder("dab") - .WithReference(sql) - .WithReference(cosmos); - -// After adding all resources, run the app... -builder.Build().Run(); -``` - - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const sql = await (await builder.addSqlServer("sql")).addDatabase("sqldb"); -const cosmos = await (await builder.addAzureCosmosDB("cosmos")).addCosmosDatabase("cosmosdb"); - -const dab = await builder.addDataAPIBuilder("dab"); -await dab.withReference(sql); -await dab.withReference(cosmos); - -// After adding all resources, run the app... -``` - - - - -## Configuration file structure - -Data API Builder uses `dab-config.json` files to define the API. The following is an example configuration: - -```json title="dab-config.json" -{ - "$schema": "https://github.com/Azure/data-api-builder/releases/download/v0.10.23/dab.draft.schema.json", - "data-source": { - "database-type": "mssql", - "connection-string": "@env('DATABASE_CONNECTION_STRING')" - }, - "runtime": { - "rest": { - "enabled": true, - "path": "/api" - }, - "graphql": { - "enabled": true, - "path": "/graphql" - } - }, - "entities": { - "Product": { - "source": "dbo.Products", - "permissions": [ - { - "role": "anonymous", - "actions": ["read"] - } - ] - } - } -} -``` - -The Aspire integration automatically injects the database connection strings from the referenced resources into the running container. - -## Endpoints - -Data API Builder exposes two endpoints: - -- **REST API**: Available at `/api` by default -- **GraphQL API**: Available at `/graphql` by default - -Both endpoints are configured in the `dab-config.json` file. - -## See also - -- [Data API Builder documentation](https://learn.microsoft.com/azure/data-api-builder/) -- [Data API Builder GitHub repository](https://github.com/Azure/data-api-builder) -- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) -- [Aspire integrations overview](/integrations/overview/) -- [Aspire GitHub repo](https://github.com/microsoft/aspire) diff --git a/src/frontend/src/content/docs/integrations/devtools/dab/dab-connect.mdx b/src/frontend/src/content/docs/integrations/devtools/dab/dab-connect.mdx new file mode 100644 index 000000000..b0a92bcf8 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/devtools/dab/dab-connect.mdx @@ -0,0 +1,148 @@ +--- +title: Connect Aspire apps to Data API Builder +description: Resolve Data API Builder through Aspire service discovery and call its REST or GraphQL endpoints from C#, TypeScript, Python, and Go. +next: false +--- + +import { Image } from 'astro:assets'; +import { Aside, Badge, Tabs, TabItem } from '@astrojs/starlight/components'; +import dabIcon from '@assets/icons/data-api-builder-icon.png'; + + + +Data API Builder logo + +This page describes how consuming apps connect to a Data API Builder resource. For configuration files, database references, image settings, and health checks, see [Set up Data API Builder in the AppHost](../dab-host/). + +DAB has no dedicated Community Toolkit client package. It exposes standard REST and GraphQL endpoints, so use the HTTP or GraphQL client for your app's language. + +## Connection values + +`DataApiBuilderContainerResource` implements service discovery rather than a connection string. For a DAB resource named `dab`, `.WithReference(dab)` or `.withReference(dab)` injects: + +| Environment variable | Description | +| ------------------------ | ------------------------------------------------------------ | +| `services__dab__http__0` | Service-discovery endpoint used by Aspire-aware HTTP clients | +| `DAB_HTTP` | Direct URL for the DAB HTTP endpoint | + +The AppHost resource also exposes `PrimaryEndpoint`, `Host`, `Port`, and `UriExpression` for building custom AppHost expressions. These are AppHost properties, not additional consuming-app environment variables. + + + +## Connect from your app + +Each example calls the REST route `/api/Product`. Use `/graphql` for GraphQL requests. + + + + +Apps that use Aspire service defaults can address the resource by name: + +```csharp title="Program.cs" +builder.Services.AddHttpClient("dab", client => +{ + client.BaseAddress = new Uri("https+http://dab"); +}); +``` + +Or use the direct endpoint variable: + +```csharp title="Program.cs" +var endpoint = Environment.GetEnvironmentVariable("DAB_HTTP") + ?? throw new InvalidOperationException("DAB_HTTP is not set."); + +using var client = new HttpClient +{ + BaseAddress = new Uri(endpoint) +}; + +var products = await client.GetStringAsync("/api/Product"); +``` + + + + +Node.js includes `fetch`, so no DAB-specific package is required: + +```typescript title="index.ts" +const endpoint = process.env.DAB_HTTP; +if (!endpoint) { + throw new Error('DAB_HTTP is not set.'); +} + +const response = await fetch(new URL('/api/Product', endpoint)); +if (!response.ok) { + throw new Error(`DAB request failed: ${response.status}`); +} + +const products = await response.json(); +``` + + + + +Use `urllib.request` from the Python standard library: + +```python title="app.py" +import json +import os +from urllib.request import urlopen + +endpoint = os.environ["DAB_HTTP"].rstrip("/") + +with urlopen(f"{endpoint}/api/Product") as response: + products = json.load(response) +``` + + + + +Use Go's standard `net/http` package: + +```go title="main.go" +package main + +import ( + "fmt" + "io" + "net/http" + "os" + "strings" +) + +func main() { + endpoint := strings.TrimRight(os.Getenv("DAB_HTTP"), "/") + response, err := http.Get(endpoint + "/api/Product") + if err != nil { + panic(err) + } + defer response.Body.Close() + + body, err := io.ReadAll(response.Body) + if err != nil { + panic(err) + } + + fmt.Println(string(body)) +} +``` + + + + +## See also + +- [REST API in Data API Builder](https://learn.microsoft.com/azure/data-api-builder/concept/rest/overview) +- [GraphQL in Data API Builder](https://learn.microsoft.com/azure/data-api-builder/concept/graphql/overview) +- [Service discovery in Aspire](/fundamentals/service-discovery/) +- [Set up Data API Builder in the AppHost](../dab-host/) diff --git a/src/frontend/src/content/docs/integrations/devtools/dab/dab-get-started.mdx b/src/frontend/src/content/docs/integrations/devtools/dab/dab-get-started.mdx new file mode 100644 index 000000000..3e732a806 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/devtools/dab/dab-get-started.mdx @@ -0,0 +1,83 @@ +--- +title: Get started with Data API Builder +description: Learn how Aspire hosts Data API Builder, connects it to databases, and exposes REST or GraphQL APIs to C#, TypeScript, Python, and Go. +prev: false +--- + +import { Image } from 'astro:assets'; +import { Badge, LinkButton, Steps } from '@astrojs/starlight/components'; +import dabIcon from '@assets/icons/data-api-builder-icon.png'; + + + +Data API Builder logo + +[Data API Builder](https://learn.microsoft.com/azure/data-api-builder/overview) (DAB) generates REST and GraphQL endpoints from a database schema and a declarative configuration file. The Aspire hosting integration runs DAB as a container, passes database connections to it, and exposes its HTTP endpoint to consuming apps. + +## Why use Data API Builder with Aspire + +- **One application model.** Model DAB, its databases, and its consuming apps in the same AppHost. +- **Configuration-file mounting.** Aspire mounts one or more DAB configuration files into the container. +- **Database reference injection.** Referenced database resources provide the connection strings that DAB reads from its configuration. +- **Service discovery.** Consuming apps can resolve the DAB HTTP endpoint by resource name or read its endpoint environment variable. +- **Language-neutral APIs.** C#, TypeScript, Python, and Go apps can use any standard HTTP or GraphQL client. + +## How the pieces fit together + +```mermaid +architecture-beta + + group apphost(server)[AppHost] + group consumer(server)[Consuming app] + + service database(database)[Database] in apphost + service dab(server)[Data API Builder] in apphost + service app(server)[Application] in consumer + + database:R --> L:dab + dab:R --> L:app +``` + + + +1. ### Model Data API Builder in the AppHost + + Add the hosting integration, provide a DAB configuration file, and reference each database that the API exposes. + + + Set up Data API Builder + + +2. ### Connect from an app + + Reference DAB from the consuming app, then call its REST or GraphQL endpoint with the HTTP client for your language. + + + Connect to Data API Builder + + + + +## See also + +- [Data API Builder documentation](https://learn.microsoft.com/azure/data-api-builder/) +- [Data API Builder GitHub repository](https://github.com/Azure/data-api-builder) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) +- [Aspire integrations overview](/integrations/overview/) diff --git a/src/frontend/src/content/docs/integrations/devtools/dab/dab-host.mdx b/src/frontend/src/content/docs/integrations/devtools/dab/dab-host.mdx new file mode 100644 index 000000000..624cdf242 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/devtools/dab/dab-host.mdx @@ -0,0 +1,213 @@ +--- +title: Set up Data API Builder in the AppHost +description: Install the Data API Builder hosting integration, mount configuration files, reference databases, customize the image, and inspect health. +--- + +import { Image } from 'astro:assets'; +import { Aside, Badge, Tabs, TabItem } from '@astrojs/starlight/components'; +import LearnMore from '@components/LearnMore.astro'; +import dabIcon from '@assets/icons/data-api-builder-icon.png'; + + + +Data API Builder logo + +This article is the AppHost API reference for the [📦 CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder) package. Start with [Get started with Data API Builder](../dab-get-started/) for the integration workflow, or see [Connect Aspire apps to Data API Builder](../dab-connect/) for consuming-app examples. + +## Installation + + + + +```bash title="Terminal" +aspire add CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder +``` + +Or add the package manually: + +```csharp title="AppHost.cs" +#:package CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder@* +``` + +```xml title="AppHost.csproj" + +``` + + + + +```bash title="Terminal" +aspire add CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder +``` + +This adds the package to `aspire.config.json`. After `aspire restore`, `.aspire/modules/aspire.mjs` includes `addDataAPIBuilder` and the exported resource properties. + + + + + + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) and + [`aspire restore`](/reference/cli/commands/aspire-restore/). + + +## Add a Data API Builder resource + +The integration uses `dab-config.json` by default. The file must exist when the AppHost builds the application model. + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var database = builder.AddSqlServer("sql") + .AddDatabase("catalog"); + +var dab = builder.AddDataAPIBuilder("dab") + .WithReference(database); + +builder.AddProject("web") + .WithReference(dab); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const sql = await builder.addSqlServer('sql'); +const database = await sql.addDatabase('catalog'); + +const dab = await builder + .addDataAPIBuilder('dab', { + configFilePaths: ['./dab-config.json'], + }) + .withReference(database); + +await builder.addNodeApp('web', './web', 'index.js').withReference(dab); + +await builder.build().run(); +``` + + + + +The integration runs `mcr.microsoft.com/azure-databases/data-api-builder:1.6.77`, maps the container's port `5000` to an Aspire-managed HTTP endpoint, enables OTLP export, and checks `/health`. + + + +## Configure database connections + +Reference each database resource from DAB, then read the Aspire-injected connection string in `dab-config.json`. For a database resource named `catalog`, use `ConnectionStrings__catalog`: + +```json title="dab-config.json" +{ + "$schema": "https://github.com/Azure/data-api-builder/releases/download/v1.6.77/dab.draft.schema.json", + "data-source": { + "database-type": "mssql", + "connection-string": "@env('ConnectionStrings__catalog')" + }, + "runtime": { + "rest": { + "enabled": true, + "path": "/api" + }, + "graphql": { + "enabled": true, + "path": "/graphql" + } + }, + "entities": { + "Product": { + "source": "dbo.Products", + "permissions": [ + { + "role": "anonymous", + "actions": ["read"] + } + ] + } + } +} +``` + +The REST route for this entity is `/api/Product`; GraphQL requests use `/graphql`. + +## Mount multiple configuration files + +Pass every configuration path to `AddDataAPIBuilder` or `addDataAPIBuilder`. Each file is mounted read-only under `/App` in the container. + + + + +```csharp title="AppHost.cs" +var dab = builder.AddDataAPIBuilder( + "dab", + ["dab-config.json", "dab-config.admin.json"]); +``` + + + + +```typescript title="apphost.mts" +const dab = await builder.addDataAPIBuilder('dab', { + configFilePaths: ['./dab-config.json', './dab-config.admin.json'], + httpPort: 5001, +}); +``` + + + + +## Customize the container image + +The DAB resource is a standard container resource, so you can replace the registry, image, or tag: + + + + +```csharp title="AppHost.cs" +var dab = builder.AddDataAPIBuilder("dab") + .WithImageRegistry("myregistry.azurecr.io") + .WithImage("custom-dab") + .WithImageTag("1.0.0"); +``` + + + + +```typescript title="apphost.mts" +const dab = await builder.addDataAPIBuilder('dab'); +await dab.withImageRegistry('myregistry.azurecr.io'); +await dab.withImage('custom-dab'); +await dab.withImageTag('1.0.0'); +``` + + + + +## Hosting integration health checks + +The hosting integration automatically adds an HTTP health check for `/health`. Aspire uses it to report when the DAB resource is ready. + +## See also + +- [Connect Aspire apps to Data API Builder](../dab-connect/) +- [Data API Builder configuration](https://learn.microsoft.com/azure/data-api-builder/configuration/) +- [REST API in Data API Builder](https://learn.microsoft.com/azure/data-api-builder/concept/rest/overview) +- [GraphQL in Data API Builder](https://learn.microsoft.com/azure/data-api-builder/concept/graphql/overview) diff --git a/src/frontend/src/content/docs/integrations/frameworks/dapr.mdx b/src/frontend/src/content/docs/integrations/frameworks/dapr.mdx deleted file mode 100644 index 5f3dbd5f4..000000000 --- a/src/frontend/src/content/docs/integrations/frameworks/dapr.mdx +++ /dev/null @@ -1,256 +0,0 @@ ---- -title: Dapr framework integration -seoTitle: Dapr framework integration for Aspire AppHost projects -description: Learn how to use the Aspire Community Toolkit Dapr hosting integration to add Dapr sidecars, state stores, pub/sub components, and more to your Aspire AppHost project. ---- - -import { Image } from 'astro:assets'; -import { Badge, Aside } from '@astrojs/starlight/components'; -import InstallPackage from '@components/InstallPackage.astro'; -import InstallDotNetPackage from '@components/InstallDotNetPackage.astro'; -import daprIcon from '@assets/icons/dapr-icon.png'; - - - -Dapr logo - -[Dapr](https://dapr.io/) (Distributed Application Runtime) is a portable, event-driven runtime that makes it easy to build resilient, stateless and stateful microservice applications. The Aspire Dapr integration enables you to add [Dapr sidecars](https://docs.dapr.io/concepts/dapr-services/sidecar/) to your Aspire project resources and wire in state store, pub/sub, and component resources. - -:::note -TypeScript AppHost support for this integration isn't yet available. All examples on this page are for C# AppHosts only. -::: - -:::note -This integration requires the Dapr CLI to be installed on your machine. For installation instructions, see [Install the Dapr CLI](https://docs.dapr.io/getting-started/install-dapr-cli/). - -After installing the CLI, run `dapr init` to initialize Dapr on your local machine before using this integration. -::: - -## Hosting integration - - - -### Add Dapr sidecar - -Add a Dapr sidecar to any project resource by calling `WithDaprSidecar`: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -builder.AddProject("exampleproject") - .WithDaprSidecar(); - -builder.Build().Run(); -``` - -By default, the sidecar uses the resource name as the Dapr app ID. To customize the app ID and ports, pass a `DaprSidecarOptions` instance: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -builder.AddProject("exampleproject") - .WithDaprSidecar(new DaprSidecarOptions - { - AppId = "my-app-id", - DaprGrpcPort = 50001, - DaprHttpPort = 3500, - MetricsPort = 9090 - }); - -builder.Build().Run(); -``` - -### Add Dapr state store - -Add a Dapr state store component with `AddDaprStateStore` and reference it from the sidecar: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var stateStore = builder.AddDaprStateStore("statestore"); - -builder.AddProject("exampleproject") - .WithDaprSidecar(sidecar => sidecar - .WithReference(stateStore)); - -builder.Build().Run(); -``` - -### Add Dapr pub/sub - -Add a Dapr pub/sub component with `AddDaprPubSub` and reference it from the sidecar: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var pubSub = builder.AddDaprPubSub("pubsub"); - -builder.AddProject("exampleproject") - .WithDaprSidecar(sidecar => sidecar - .WithReference(pubSub)); - -builder.Build().Run(); -``` - -### Add Dapr component - -Use `AddDaprComponent` to add any Dapr component by type: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var binding = builder.AddDaprComponent("binding", "bindings.http"); - -builder.AddProject("exampleproject") - .WithDaprSidecar(sidecar => sidecar - .WithReference(binding)); - -builder.Build().Run(); -``` - -### Configure an actor state store - -To use an actor state store, add the `actorStateStore` metadata to a component YAML file. Create a `components` directory in your AppHost and add a component configuration file: - -```yaml title="components/statestore.yaml" -apiVersion: dapr.io/v1alpha1 -kind: Component -metadata: - name: statestore -spec: - type: state.redis - version: v1 - metadata: - - name: redisHost - value: localhost:6379 - - name: actorStateStore - # Setting actorStateStore to "true" designates this state store - # as the actor state store. Dapr actors require exactly one state - # store to be configured with this flag. - value: "true" -``` - -Reference the components directory from `DaprSidecarOptions`: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -builder.AddProject("actorservice") - .WithDaprSidecar(new DaprSidecarOptions - { - ResourcesPaths = ["./components"] - }); - -builder.Build().Run(); -``` - -### Dashboard integration - -When you add Dapr sidecars to your projects, they appear as separate resources in the Aspire dashboard. Each sidecar is displayed with a unique name derived from the project name and includes the configured ports. - -## Client integration - -To connect from a consuming project to services that have Dapr sidecars, install the [📦 Dapr.AspNetCore](https://www.nuget.org/packages/Dapr.AspNetCore) package: - - - -For non-ASP.NET Core applications, install [📦 Dapr.Client](https://www.nuget.org/packages/Dapr.Client) instead: - -```bash title="Terminal" -dotnet add package Dapr.Client -``` - -### Use the Dapr client - -In the `Program.cs` file of your consuming project, register the Dapr client with the dependency injection container: - -```csharp title="Program.cs" -builder.Services.AddDaprClient(); -``` - -Retrieve the `DaprClient` instance using dependency injection: - -```csharp title="ExampleService.cs" -public class ExampleService(DaprClient daprClient) -{ - public async Task CallServiceAsync() - { - var response = await daprClient.InvokeMethodAsync( - HttpMethod.Get, - "exampleproject", - "api/data"); - } -} -``` - -### Service-to-service invocation - -Dapr enables service-to-service invocation using the app ID. The following example invokes an endpoint on the service identified by the Dapr app ID `exampleproject`: - -```csharp title="Program.cs" -var builder = WebApplication.CreateBuilder(args); -builder.Services.AddDaprClient(); - -var app = builder.Build(); - -app.MapGet("/call-service", async (DaprClient daprClient) => -{ - var result = await daprClient.InvokeMethodAsync( - HttpMethod.Get, - "exampleproject", - "api/data"); - - return Results.Ok(result); -}); - -app.Run(); -``` - -For more information, see [Dapr service invocation](https://docs.dapr.io/developing-applications/building-blocks/service-invocation/). - -## Deploy with Azure Container Apps - -The Dapr integration configures Dapr sidecars for local development. When deploying to Azure Container Apps (ACA), Dapr sidecar settings are part of the container app configuration and must be preserved on each deployment. - -:::caution -When you redeploy a container app that previously had Dapr enabled, Azure Container Apps does **not** automatically retain Dapr settings from the previous deployment. If Dapr appears disabled in the Azure portal after redeployment, re-enable it by configuring the Dapr settings in the ACA environment or by using `PublishAsAzureContainerApp` with explicit Dapr configuration. -::: - -To ensure Dapr settings are preserved, configure the sidecar explicitly using `PublishAsAzureContainerApp`: - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -builder.AddProject("exampleproject") - .WithDaprSidecar() - .PublishAsAzureContainerApp((infra, app) => - { - app.Configuration.Dapr = new() - { - IsEnabled = true, - AppId = "exampleproject", - AppPort = 8080, - }; - }); - -builder.Build().Run(); -``` - -For more information, see [Configure Azure Container Apps](/integrations/cloud/azure/configure-container-apps/). - -## See also - -- [📦 CommunityToolkit.Aspire.Hosting.Dapr](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Dapr) NuGet package -- [Dapr documentation](https://docs.dapr.io/) -- [Dapr .NET SDK](https://docs.dapr.io/developing-applications/sdks/dotnet/) -- [Dapr service invocation](https://docs.dapr.io/developing-applications/building-blocks/service-invocation/) -- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) -- [Aspire integrations overview](/integrations/overview/) -- [Configure Azure Container Apps](/integrations/cloud/azure/configure-container-apps/) diff --git a/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-connect.mdx b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-connect.mdx new file mode 100644 index 000000000..839a84789 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-connect.mdx @@ -0,0 +1,172 @@ +--- +title: Connect Aspire apps to Dapr sidecars +description: Use Aspire-injected Dapr HTTP and gRPC endpoints from C#, TypeScript, Python, and Go apps with the official Dapr SDKs. +next: false +--- + +import { Image } from 'astro:assets'; +import { Badge, Tabs, TabItem } from '@astrojs/starlight/components'; +import InstallDotNetPackage from '@components/InstallDotNetPackage.astro'; +import daprIcon from '@assets/icons/dapr-icon.png'; + + + +Dapr logo + +This page describes how an app connects to the Dapr sidecar attached to it. For sidecar and component configuration in the AppHost, see [Set up Dapr resources in the AppHost](../dapr-host/). + +## Connection properties + +The hosting integration injects these environment variables into an app resource that has a Dapr sidecar: + +| Environment variable | Description | +| -------------------- | ---------------------------------------- | +| `DAPR_HTTP_PORT` | Port for the sidecar's HTTP API | +| `DAPR_GRPC_PORT` | Port for the sidecar's gRPC API | +| `DAPR_HTTP_ENDPOINT` | Full endpoint for the sidecar's HTTP API | +| `DAPR_GRPC_ENDPOINT` | Full endpoint for the sidecar's gRPC API | + +These variables are added in run mode. Pick the HTTP or gRPC endpoint that matches the SDK transport you configure. + +## Connect from your app + +Each example uses the sidecar endpoint injected into the app resource. + + + + +Install the official [📦 Dapr.Client](https://www.nuget.org/packages/Dapr.Client) package: + + + +```csharp title="Program.cs" +using Dapr.Client; + +var endpoint = Environment.GetEnvironmentVariable("DAPR_GRPC_ENDPOINT") + ?? throw new InvalidOperationException("DAPR_GRPC_ENDPOINT is not set."); + +using var daprClient = new DaprClientBuilder() + .UseGrpcEndpoint(endpoint) + .Build(); + +var product = await daprClient.GetStateAsync( + "statestore", + "product-1"); +``` + +ASP.NET Core apps can instead install [📦 Dapr.AspNetCore](https://www.nuget.org/packages/Dapr.AspNetCore) and register `DaprClient` with dependency injection. + + + + +Install the official Dapr JavaScript SDK: + +```bash title="Terminal" +npm install @dapr/dapr +``` + +```typescript title="index.ts" +import { CommunicationProtocolEnum, DaprClient, HttpMethod } from '@dapr/dapr'; + +const endpoint = new URL(process.env.DAPR_HTTP_ENDPOINT!); +const client = new DaprClient({ + daprHost: endpoint.origin, + daprPort: endpoint.port, + communicationProtocol: CommunicationProtocolEnum.HTTP, +}); + +const response = await client.invoker.invoke( + 'catalog-api', + 'api/data', + HttpMethod.GET +); +``` + + + + +Install the official Dapr Python SDK: + +```bash title="Terminal" +pip install dapr +``` + +```python title="app.py" +import os +from urllib.parse import urlparse + +from dapr.clients import DaprClient + +endpoint = urlparse(os.environ["DAPR_GRPC_ENDPOINT"]) + +with DaprClient(address=endpoint.netloc) as client: + response = client.invoke_method( + app_id="catalog-api", + method_name="api/data", + http_verb="GET", + ) + print(response.text()) +``` + + + + +Install the official Dapr Go SDK: + +```bash title="Terminal" +go get github.com/dapr/go-sdk/client +``` + +```go title="main.go" +package main + +import ( + "context" + "fmt" + "net/url" + "os" + + dapr "github.com/dapr/go-sdk/client" +) + +func main() { + endpoint, err := url.Parse(os.Getenv("DAPR_GRPC_ENDPOINT")) + if err != nil { + panic(err) + } + + client, err := dapr.NewClientWithAddress(endpoint.Host) + if err != nil { + panic(err) + } + defer client.Close() + + response, err := client.InvokeMethod( + context.Background(), + "catalog-api", + "api/data", + "get", + ) + if err != nil { + panic(err) + } + + fmt.Println(string(response)) +} +``` + + + + +## See also + +- [Dapr service invocation](https://docs.dapr.io/developing-applications/building-blocks/service-invocation/) +- [Dapr SDKs](https://docs.dapr.io/developing-applications/sdks/) +- [Set up Dapr resources in the AppHost](../dapr-host/) diff --git a/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-get-started.mdx new file mode 100644 index 000000000..115fbf342 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-get-started.mdx @@ -0,0 +1,93 @@ +--- +title: Get started with Dapr and Aspire +description: Learn how Aspire models Dapr sidecars and components, then connects C#, TypeScript, Python, and Go apps through Dapr SDKs. +prev: false +--- + +import { Image } from 'astro:assets'; +import { Badge, LinkButton, Steps } from '@astrojs/starlight/components'; +import daprIcon from '@assets/icons/dapr-icon.png'; + + + +Dapr logo + +[Dapr](https://dapr.io/) is a portable runtime for building distributed applications with APIs for service invocation, state, messaging, secrets, and more. The Aspire Dapr integration models Dapr sidecars and component resources alongside the apps that use them. + +## Why use Dapr with Aspire + +- **Sidecars in the application model.** Add and configure a Dapr sidecar next to an app resource instead of managing a separate `dapr run` command. +- **Reusable component resources.** Model state stores, pub/sub brokers, and other Dapr components once, then reference them from sidecars. +- **Automatic endpoint injection.** Aspire passes the sidecar HTTP and gRPC ports and endpoints to each app resource. +- **Dashboard visibility.** Sidecars appear as resources with logs, endpoints, and lifecycle status in the Aspire dashboard. +- **Dapr SDK support.** C#, TypeScript, Python, and Go apps can use the official Dapr SDK for their language. + +## Prerequisites + +Install the [Dapr CLI](https://docs.dapr.io/getting-started/install-dapr-cli/) and run: + +```bash title="Terminal" +dapr init +``` + +The Community Toolkit package is tested with the most recent stable Dapr release identified in its source. At the audited release, that is Dapr runtime 1.15.3 and Dapr CLI 1.15.0. + +## How the pieces fit together + +```mermaid +architecture-beta + + group apphost(server)[AppHost] + group consumer(server)[App resource] + + service component(database)[Dapr component] in apphost + service sidecar(server)[Dapr sidecar] in apphost + service app(server)[Application] in consumer + + component:R --> L:sidecar + sidecar:R --> L:app +``` + + + +1. ### Model Dapr in the AppHost + + Install the hosting integration, add component resources, and attach a sidecar to each app that uses Dapr. + + + Set up Dapr in the AppHost + + +2. ### Connect from an app + + Use the injected Dapr HTTP or gRPC endpoint with the official SDK for your app's language. + + + Connect to Dapr + + + + +## See also + +- [Dapr documentation](https://docs.dapr.io/) +- [Dapr SDKs](https://docs.dapr.io/developing-applications/sdks/) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) +- [Aspire integrations overview](/integrations/overview/) diff --git a/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-host.mdx new file mode 100644 index 000000000..85455a485 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-host.mdx @@ -0,0 +1,219 @@ +--- +title: Set up Dapr resources in the AppHost +description: Install the Community Toolkit Dapr hosting integration and configure sidecars, state stores, pub/sub, metadata, and Azure deployment. +--- + +import { Image } from 'astro:assets'; +import { Aside, Badge, Tabs, TabItem } from '@astrojs/starlight/components'; +import LearnMore from '@components/LearnMore.astro'; +import daprIcon from '@assets/icons/dapr-icon.png'; + + + +Dapr logo + +This article is the AppHost API reference for the [📦 CommunityToolkit.Aspire.Hosting.Dapr](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Dapr) package. If you're new to the integration, start with [Get started with Dapr and Aspire](../dapr-get-started/). For app-side endpoint variables and SDK examples, see [Connect Aspire apps to Dapr sidecars](../dapr-connect/). + +## Installation + + + + +```bash title="Terminal" +aspire add CommunityToolkit.Aspire.Hosting.Dapr +``` + +Or add the package manually: + +```csharp title="AppHost.cs" +#:package CommunityToolkit.Aspire.Hosting.Dapr@* +``` + +```xml title="AppHost.csproj" + +``` + + + + +```bash title="Terminal" +aspire add CommunityToolkit.Aspire.Hosting.Dapr +``` + +This adds the package to `aspire.config.json`. After `aspire restore`, `.aspire/modules/aspire.mjs` includes the Dapr APIs. + + + + + + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) and + [`aspire restore`](/reference/cli/commands/aspire-restore/). + + +:::caution[TypeScript limitation] +The Dapr TypeScript exports are available, but the source test for referencing Dapr components from **project resources** is skipped at the audited Community Toolkit commit because of a capability-dispatch issue. The TypeScript examples below use container app resources, which match the checked-in validation AppHost. +::: + +## Add a sidecar and component resources + +Add Dapr, create state-store and pub/sub component resources, then reference the components from a sidecar: + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +builder.AddDapr(); + +var stateStore = builder.AddDaprStateStore("statestore"); +var pubSub = builder.AddDaprPubSub("pubsub"); + +builder.AddProject("api") + .WithDaprSidecar(sidecar => sidecar + .WithReference(stateStore) + .WithReference(pubSub)); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +await builder.addDapr(); + +const stateStore = builder.addDaprStateStore('statestore'); +const pubSub = builder.addDaprPubSub('pubsub'); + +await builder + .addContainer('api', 'nginx') + .withEndpoint({ name: 'http', scheme: 'http', targetPort: 80 }) + .configureDaprSidecar(async (sidecar) => { + await sidecar.withOptions({ + appId: 'api', + appPort: 80, + appProtocol: 'http', + }); + await sidecar.withReference(await stateStore); + await sidecar.withReference(await pubSub); + }); + +await builder.build().run(); +``` + + + + +`AddDaprStateStore` and `AddDaprPubSub` create generic component resources. Use `AddDaprComponent(name, type)` when you need another Dapr component type. + +## Configure sidecar options + +Use `DaprSidecarOptions` or its TypeScript equivalent to configure the app ID, app endpoint, Dapr endpoints, health probes, logging, metrics, component paths, and other `dapr run` settings: + + + + +```csharp title="AppHost.cs" +using CommunityToolkit.Aspire.Hosting.Dapr; + +builder.AddProject("api") + .WithDaprSidecar(new DaprSidecarOptions + { + AppId = "catalog-api", + AppPort = 8080, + AppProtocol = "http", + EnableApiLogging = true, + ResourcesPaths = ["./components"] + }); +``` + + + + +```typescript title="apphost.mts" +await builder + .addContainer('api', 'nginx') + .withEndpoint({ name: 'http', scheme: 'http', targetPort: 80 }) + .withDaprSidecar({ + sidecarOptions: { + appId: 'catalog-api', + appPort: 80, + appProtocol: 'http', + enableApiLogging: true, + resourcesPaths: ['./components'], + }, + }); +``` + + + + +## Configure component metadata + +Use `WithMetadata` or `withMetadata` for static values. The hosting integration also exposes overloads for endpoint references, reference expressions, and parameters so metadata can follow Aspire-managed resources. + + + + +```csharp title="AppHost.cs" +var redis = builder.AddRedis("redis"); +var redisPassword = builder.AddParameter("redis-password", secret: true); + +var stateStore = builder.AddDaprStateStore("statestore") + .WithMetadata("actorStateStore", "true") + .WithMetadata("redisHost", redis.GetEndpoint("tcp")) + .WithMetadata("redisPassword", redisPassword.Resource); +``` + + + + +```typescript title="apphost.mts" +const redis = builder + .addContainer('redis', 'redis') + .withEndpoint({ name: 'tcp', targetPort: 6379 }); +const redisEndpoint = await redis.getEndpoint('tcp'); +const redisPassword = await builder.addParameter('redis-password', { + secret: true, +}); + +const stateStore = builder + .addDaprStateStore('statestore') + .withMetadata('actorStateStore', 'true') + .withMetadataEndpoint('redisHost', redisEndpoint) + .withMetadataParameter('redisPassword', redisPassword); +``` + + + + +## Dashboard integration + +Each Dapr sidecar is a hidden resource named from its app resource, such as `api-dapr`. The Aspire dashboard displays the sidecar's state, endpoints, logs, traces, and metrics with the rest of the application model. + +## Deploy to Azure Container Apps + +Install [📦 CommunityToolkit.Aspire.Hosting.Azure.Dapr](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Azure.Dapr), then call `WithDaprComponents` or `withDaprComponents` on the Azure Container Apps environment. The integration translates local Dapr component and sidecar settings into Azure Container Apps Dapr configuration during publish. + +:::note +The core Dapr integration injects local sidecar endpoints only in run mode. Azure Container Apps provides the sidecar endpoints after deployment. +::: + +## See also + +- [Connect Aspire apps to Dapr sidecars](../dapr-connect/) +- [Dapr components](https://docs.dapr.io/concepts/components-concept/) +- [Configure Azure Container Apps](/integrations/cloud/azure/configure-container-apps/) +- [📦 CommunityToolkit.Aspire.Hosting.Dapr](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Dapr) diff --git a/src/frontend/src/content/docs/integrations/messaging/lavinmq.mdx b/src/frontend/src/content/docs/integrations/messaging/lavinmq.mdx deleted file mode 100644 index 8dc0209e7..000000000 --- a/src/frontend/src/content/docs/integrations/messaging/lavinmq.mdx +++ /dev/null @@ -1,237 +0,0 @@ ---- -title: LavinMQ integration -seoTitle: LavinMQ integration for Aspire AppHost and apps -description: Learn how to use the Aspire LavinMQ Hosting integration to orchestrate and configure a LavinMQ resource in an Aspire solution. ---- - -import { Image } from 'astro:assets'; -import { Badge, Tabs, TabItem } from '@astrojs/starlight/components'; -import lavinmqIcon from '@assets/icons/lavinmq-icon.png'; - - - -LavinMQ logo - -This article is the reference for the Aspire LavinMQ Hosting integration. It enumerates the AppHost APIs that you use to model a LavinMQ resource in your [`AppHost`](/get-started/app-host/) project. [LavinMQ](https://lavinmq.com/) is a high-performance message broker that implements the AMQP 0.9.1 protocol and is wire-compatible with RabbitMQ. The integration provisions a LavinMQ instance using the `docker.io/cloudamqp/lavinmq` container image. - -## Installation - -To start building an Aspire app that uses LavinMQ, install the [📦 CommunityToolkit.Aspire.Hosting.LavinMQ](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.LavinMQ) NuGet package in the AppHost project: - - - - -```bash title="Terminal" -aspire add lavinmq -``` - -Or, choose a manual installation approach: - -```csharp title="AppHost.cs" -#:package CommunityToolkit.Aspire.Hosting.LavinMQ@* -``` - -```xml title="AppHost.csproj" - -``` - - - - -```bash title="Terminal" -aspire add lavinmq -``` - -This updates your `aspire.config.json` with the LavinMQ hosting integration package: - -```json title="aspire.config.json" ins={3} -{ - "packages": { - "CommunityToolkit.Aspire.Hosting.LavinMQ": "*" - } -} -``` - -The TypeScript AppHost bindings for LavinMQ are provided by the Community Toolkit package. After installation, the `.aspire/modules/aspire.mjs` file in your project includes `addLavinMQ` and related APIs. - - - - -## Add LavinMQ resource - -Once you've installed the hosting integration in your AppHost project, you can add a LavinMQ server resource as shown in the following examples: - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var lavinmq = builder.AddLavinMQ("lavinmq"); - -builder.AddProject() - .WithReference(lavinmq); - -// After adding all resources, run the app... -``` - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const lavinmq = await builder.addLavinMQ("lavinmq"); - -const exampleProject = await builder.addProject( - "example-project", - "../ExampleProject/ExampleProject.csproj"); -await exampleProject.withReference(lavinmq); - -// After adding all resources, run the app... -``` - - - - -When Aspire adds a container image to the AppHost, as shown in the preceding example with the `docker.io/cloudamqp/lavinmq` image, it creates a new LavinMQ instance. The default username is `guest`, and the password is a randomly generated string. - -## Add LavinMQ resource with data volume - -To add data volumes for persisting LavinMQ data, call the `WithDataVolume` or `withDataVolume` method: - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var lavinmq = builder.AddLavinMQ("lavinmq") - .WithDataVolume(); - -builder.AddProject() - .WithReference(lavinmq); - -// After adding all resources, run the app... -``` - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const lavinmq = await builder.addLavinMQ("lavinmq"); -await lavinmq.withDataVolume("lavinmq-data"); - -const exampleProject = await builder.addProject( - "example-project", - "../ExampleProject/ExampleProject.csproj"); -await exampleProject.withReference(lavinmq); - -// After adding all resources, run the app... -``` - - - - -The data volume is used to persist the LavinMQ data outside the lifecycle of the container. - -## Add LavinMQ resource with data bind mount - -For development scenarios, you may want to use bind mounts instead of data volumes. To add a data bind mount, call the `WithDataBindMount` or `withDataBindMount` method: - - - -```csharp title="AppHost.cs" -var builder = DistributedApplication.CreateBuilder(args); - -var lavinmq = builder.AddLavinMQ("lavinmq") - .WithDataBindMount(source: @"C:\LavinMQ\Data"); - -builder.AddProject() - .WithReference(lavinmq); - -// After adding all resources, run the app... -``` - - - -```typescript title="apphost.mts" -import { createBuilder } from "./.aspire/modules/aspire.mjs"; - -const builder = await createBuilder(); - -const lavinmq = await builder.addLavinMQ("lavinmq"); -await lavinmq.withDataBindMount("/LavinMQ/Data"); - -const exampleProject = await builder.addProject( - "example-project", - "../ExampleProject/ExampleProject.csproj"); -await exampleProject.withReference(lavinmq); - -// After adding all resources, run the app... -``` - - - - -## Management UI - -LavinMQ provides a management UI that you can use to monitor and manage your LavinMQ instance. The management UI is automatically exposed when you add a LavinMQ resource and is accessible through the Aspire dashboard. - -## Client integration - -LavinMQ is wire-compatible with RabbitMQ and uses the AMQP 0.9.1 protocol. To connect to LavinMQ from your client application, install the [📦 Aspire.RabbitMQ.Client](https://www.nuget.org/packages/Aspire.RabbitMQ.Client) NuGet package: - -```bash title="Terminal" -dotnet add package Aspire.RabbitMQ.Client -``` - -### Add RabbitMQ client API - -In the `Program.cs` file of your client-consuming project, call the `AddRabbitMQClient` extension method to register an `IConnection` for use through dependency injection. The method takes a connection name parameter: - -```csharp -builder.AddRabbitMQClient(connectionName: "lavinmq"); -``` - -You can then retrieve the `IConnection` instance using dependency injection. For example, to retrieve the connection object from an example service: - -```csharp -public class ExampleService(IConnection connection) -{ - // Use connection... -} -``` - -For more information on using the RabbitMQ client with LavinMQ, see the [RabbitMQ integration documentation](/integrations/messaging/rabbitmq/rabbitmq-get-started/). - -### Configuration - -Because LavinMQ is wire-compatible with RabbitMQ, you can use the same configuration options as the RabbitMQ client integration. The Aspire RabbitMQ client integration supports `Microsoft.Extensions.Configuration`. It loads the `RabbitMQClientSettings` from configuration using the `Aspire:RabbitMQ:Client` key. - -For more information about configuration options, see the [RabbitMQ integration documentation](/integrations/messaging/rabbitmq/rabbitmq-client/#configuration). - -## Health checks - -By default, the Aspire RabbitMQ client integration handles health checks using the [AspNetCore.HealthChecks.RabbitMQ](https://www.nuget.org/packages/AspNetCore.HealthChecks.RabbitMQ) package. Since LavinMQ is wire-compatible with RabbitMQ, the same health checks work for LavinMQ connections. - -## Observability and telemetry - -The LavinMQ integration uses the RabbitMQ client, which provides observability features. For more information about tracing, metrics, and logging with the RabbitMQ client, see the [RabbitMQ integration documentation](/integrations/messaging/rabbitmq/rabbitmq-client/#observability-and-telemetry). - -## See also - -- [LavinMQ documentation](https://lavinmq.com/documentation) -- [RabbitMQ integration](/integrations/messaging/rabbitmq/rabbitmq-get-started/) -- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) -- [Aspire integrations overview](/integrations/overview/) -- [Aspire GitHub repo](https://github.com/microsoft/aspire) diff --git a/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-connect.mdx b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-connect.mdx new file mode 100644 index 000000000..fb42ea9da --- /dev/null +++ b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-connect.mdx @@ -0,0 +1,175 @@ +--- +title: Connect Aspire apps to LavinMQ +description: Use LavinMQ connection properties from C#, TypeScript, Python, and Go apps with RabbitMQ-compatible AMQP 0-9-1 clients. +next: false +--- + +import { Image } from 'astro:assets'; +import { Aside, Badge, Tabs, TabItem } from '@astrojs/starlight/components'; +import InstallDotNetPackage from '@components/InstallDotNetPackage.astro'; +import lavinmqIcon from '@assets/icons/lavinmq-icon.png'; + + + +LavinMQ logo + +This page describes how consuming apps connect to a LavinMQ resource. For broker ports, storage, management, and health checks, see [Set up LavinMQ in the Aspire AppHost](../lavinmq-host/). + +LavinMQ implements AMQP 0-9-1 and is wire-compatible with RabbitMQ. There is no LavinMQ-specific Community Toolkit client package; use a RabbitMQ-compatible client. + +## Connection properties + +Aspire exposes each property as an environment variable named `[RESOURCE]_[PROPERTY]`. A resource named `lavinmq` provides: + +| Property | Environment variable | Description | +| ---------- | -------------------- | --------------------------------------------- | +| `Host` | `LAVINMQ_HOST` | Broker hostname or IP address | +| `Port` | `LAVINMQ_PORT` | AMQP endpoint port | +| `Username` | `LAVINMQ_USERNAME` | Username; defaults to `guest` | +| `Password` | `LAVINMQ_PASSWORD` | Password; defaults to `guest` | +| `Uri` | `LAVINMQ_URI` | `amqp://{Username}:{Password}@{Host}:{Port}/` | + +Unlike the Aspire RabbitMQ resource, the LavinMQ resource doesn't expose a `VirtualHost` property. Its URI uses `/`. + + + +## Connect from your app + + + + +C# apps can use the Aspire RabbitMQ client integration because LavinMQ is wire-compatible with RabbitMQ. Install: + + + +Register the client with the LavinMQ resource name: + +```csharp title="Program.cs" +builder.AddRabbitMQClient(connectionName: "lavinmq"); +``` + +Then resolve `RabbitMQ.Client.IConnection` through dependency injection. + +To use the URI directly with the RabbitMQ .NET client: + +```csharp title="Program.cs" +using RabbitMQ.Client; + +var uri = Environment.GetEnvironmentVariable("LAVINMQ_URI") + ?? throw new InvalidOperationException("LAVINMQ_URI is not set."); + +var factory = new ConnectionFactory { Uri = new Uri(uri) }; +using var connection = await factory.CreateConnectionAsync(); +using var channel = await connection.CreateChannelAsync(); +``` + + + + +Install `amqplib` and its TypeScript declarations: + +```bash title="Terminal" +npm install amqplib +npm install --save-dev @types/amqplib +``` + +```typescript title="index.ts" +import amqp from 'amqplib'; + +const uri = process.env.LAVINMQ_URI; +if (!uri) { + throw new Error('LAVINMQ_URI is not set.'); +} + +const connection = await amqp.connect(uri); +const channel = await connection.createChannel(); + +// Publish or consume messages with channel. + +await channel.close(); +await connection.close(); +``` + + + + +Install `pika`: + +```bash title="Terminal" +pip install pika +``` + +```python title="app.py" +import os + +import pika + +parameters = pika.URLParameters(os.environ["LAVINMQ_URI"]) +connection = pika.BlockingConnection(parameters) +channel = connection.channel() + +# Publish or consume messages with channel. + +connection.close() +``` + + + + +Install the official RabbitMQ AMQP 0-9-1 Go client: + +```bash title="Terminal" +go get github.com/rabbitmq/amqp091-go +``` + +```go title="main.go" +package main + +import ( + "os" + + amqp "github.com/rabbitmq/amqp091-go" +) + +func main() { + connection, err := amqp.Dial(os.Getenv("LAVINMQ_URI")) + if err != nil { + panic(err) + } + defer connection.Close() + + channel, err := connection.Channel() + if err != nil { + panic(err) + } + defer channel.Close() + + // Publish or consume messages with channel. +} +``` + + + + +## Health checks and telemetry + +`Aspire.RabbitMQ.Client` adds a connection health check and RabbitMQ client tracing for C# apps. Other language clients provide their own logging, recovery, and instrumentation options. + +## See also + +- [RabbitMQ client integration](/integrations/messaging/rabbitmq/rabbitmq-connect/) +- [LavinMQ documentation](https://lavinmq.com/documentation) +- [AMQP 0-9-1 model](https://www.rabbitmq.com/tutorials/amqp-concepts/) +- [Set up LavinMQ in the Aspire AppHost](../lavinmq-host/) diff --git a/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-get-started.mdx b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-get-started.mdx new file mode 100644 index 000000000..927d1e5aa --- /dev/null +++ b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-get-started.mdx @@ -0,0 +1,87 @@ +--- +title: Get started with LavinMQ and Aspire +description: Learn how Aspire hosts LavinMQ and connects C#, TypeScript, Python, and Go apps with RabbitMQ-compatible AMQP 0-9-1 clients. +prev: false +--- + +import { Image } from 'astro:assets'; +import { Badge, LinkButton, Steps } from '@astrojs/starlight/components'; +import lavinmqIcon from '@assets/icons/lavinmq-icon.png'; + + + +LavinMQ logo + +[LavinMQ](https://lavinmq.com/) is a message broker that implements AMQP 0-9-1 and is wire-compatible with RabbitMQ. The Aspire hosting integration runs LavinMQ as a container and exposes its AMQP connection properties to consuming apps. + +## Why use LavinMQ with Aspire + +- **Container orchestration.** Aspire runs `docker.io/cloudamqp/lavinmq` with AMQP and management endpoints. +- **Connection-property injection.** Referencing the resource provides the host, port, credentials, and AMQP URI to an app. +- **Persistent storage options.** Store broker data in a named volume or a host bind mount. +- **Built-in health checks.** The hosting integration checks the broker through a RabbitMQ-compatible connection. +- **Multi-language clients.** C#, TypeScript, Python, and Go can use established RabbitMQ-compatible AMQP 0-9-1 libraries. + +LavinMQ has no dedicated Community Toolkit client package. Use the Aspire RabbitMQ client integration for C# or a RabbitMQ-compatible client for your language. + +## How the pieces fit together + +```mermaid +architecture-beta + + group apphost(server)[AppHost] + group consumer(server)[Consuming app] + + service hosting(server)[Hosting integration] in apphost + service lavinmq(server)[LavinMQ broker] in apphost + service client(iconoir:server-connection)[AMQP client] in consumer + service app(server)[Application] in consumer + + hosting:R --> L:lavinmq + lavinmq:R --> L:client + client:R --> L:app +``` + + + +1. ### Model LavinMQ in the AppHost + + Install the hosting integration, add the broker resource, and configure ports or persistent storage. + + + Set up LavinMQ + + +2. ### Connect from an app + + Reference the broker from an app and use the injected AMQP URI with a RabbitMQ-compatible client. + + + Connect to LavinMQ + + + + +## See also + +- [LavinMQ documentation](https://lavinmq.com/documentation) +- [AMQP 0-9-1 model](https://www.rabbitmq.com/tutorials/amqp-concepts/) +- [RabbitMQ integration](/integrations/messaging/rabbitmq/rabbitmq-get-started/) +- [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire) diff --git a/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-host.mdx b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-host.mdx new file mode 100644 index 000000000..6bee73e64 --- /dev/null +++ b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-host.mdx @@ -0,0 +1,193 @@ +--- +title: Set up LavinMQ in the Aspire AppHost +description: Install the Community Toolkit LavinMQ hosting integration, configure broker ports, persist data, and open the management endpoint. +--- + +import { Image } from 'astro:assets'; +import { Aside, Badge, Tabs, TabItem } from '@astrojs/starlight/components'; +import LearnMore from '@components/LearnMore.astro'; +import lavinmqIcon from '@assets/icons/lavinmq-icon.png'; + + + +LavinMQ logo + +This article is the AppHost API reference for the [📦 CommunityToolkit.Aspire.Hosting.LavinMQ](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.LavinMQ) package. Start with [Get started with LavinMQ and Aspire](../lavinmq-get-started/) for the integration workflow, or see [Connect Aspire apps to LavinMQ](../lavinmq-connect/) for client examples. + +## Installation + + + + +```bash title="Terminal" +aspire add lavinmq +``` + +Or add the package manually: + +```csharp title="AppHost.cs" +#:package CommunityToolkit.Aspire.Hosting.LavinMQ@* +``` + +```xml title="AppHost.csproj" + +``` + + + + +```bash title="Terminal" +aspire add lavinmq +``` + +This adds the package to `aspire.config.json`. After `aspire restore`, `.aspire/modules/aspire.mjs` includes `addLavinMQ`, the persistence APIs, and the exported endpoint properties. + + + + + + Learn more about [`aspire add`](/reference/cli/commands/aspire-add/) and + [`aspire restore`](/reference/cli/commands/aspire-restore/). + + +## Add a LavinMQ resource + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var lavinmq = builder.AddLavinMQ("lavinmq"); + +builder.AddProject("worker") + .WithReference(lavinmq); + +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const lavinmq = await builder.addLavinMQ('lavinmq'); + +await builder + .addNodeApp('worker', './worker', 'index.js') + .withReference(lavinmq); + +await builder.build().run(); +``` + + + + +The integration runs `docker.io/cloudamqp/lavinmq:2.1.0`. The AMQP endpoint uses container port `5672`, and the management endpoint uses `15672`. The default username and password are both `guest`. + + + +## Configure host ports + +Pass fixed host ports when another process needs stable endpoints: + + + + +```csharp title="AppHost.cs" +var lavinmq = builder.AddLavinMQ( + "lavinmq", + amqpPort: 5672, + managementPort: 15672); +``` + + + + +```typescript title="apphost.mts" +const lavinmq = await builder.addLavinMQ('lavinmq', { + amqpPort: 5672, + managementPort: 15672, +}); +``` + + + + +Omit the parameters to let Aspire select available host ports. + +## Persist data in a volume + +`WithDataVolume` and `withDataVolume` require a volume name and mount it at `/var/lib/lavinmq`: + + + + +```csharp title="AppHost.cs" +var lavinmq = builder.AddLavinMQ("lavinmq") + .WithDataVolume("lavinmq-data"); +``` + + + + +```typescript title="apphost.mts" +const lavinmq = await builder.addLavinMQ('lavinmq'); +await lavinmq.withDataVolume('lavinmq-data'); +``` + + + + +## Persist data in a bind mount + +Use a bind mount when you need direct access to broker files on the host: + + + + +```csharp title="AppHost.cs" +var lavinmq = builder.AddLavinMQ("lavinmq") + .WithDataBindMount(@"C:\LavinMQ\Data"); +``` + + + + +```typescript title="apphost.mts" +const lavinmq = await builder.addLavinMQ('lavinmq'); +await lavinmq.withDataBindMount('./lavinmq-data'); +``` + + + + +Both persistence methods accept an optional `isReadOnly` value. A read-only mount isn't suitable for a broker that needs to write data. + +## Management UI + +The management endpoint is added automatically. Open the `management` HTTP endpoint from the Aspire dashboard, then sign in with the broker credentials. + +## Hosting integration health checks + +The hosting integration registers a RabbitMQ-compatible health check against the AMQP endpoint. The dashboard reports the resource healthy after a client connection succeeds. + +## See also + +- [Connect Aspire apps to LavinMQ](../lavinmq-connect/) +- [LavinMQ documentation](https://lavinmq.com/documentation) +- [Persist data using volumes](/fundamentals/persist-data-volumes/) +- [📦 CommunityToolkit.Aspire.Hosting.LavinMQ](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.LavinMQ) diff --git a/src/frontend/src/data/integration-docs.json b/src/frontend/src/data/integration-docs.json index e7c67f277..6d524f324 100644 --- a/src/frontend/src/data/integration-docs.json +++ b/src/frontend/src/data/integration-docs.json @@ -373,15 +373,15 @@ }, { "match": "CommunityToolkit.Aspire.Hosting.Azure.Dapr", - "href": "/integrations/frameworks/dapr/" + "href": "/integrations/frameworks/dapr/dapr-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.Azure.Dapr.Redis", - "href": "/integrations/frameworks/dapr/" + "href": "/integrations/frameworks/dapr/dapr-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder", - "href": "/integrations/devtools/dab/" + "href": "/integrations/devtools/dab/dab-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.Bun", @@ -389,11 +389,11 @@ }, { "match": "CommunityToolkit.Aspire.Hosting.Dapr", - "href": "/integrations/frameworks/dapr/" + "href": "/integrations/frameworks/dapr/dapr-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.Dapr.AzureRedis", - "href": "/integrations/frameworks/dapr/" + "href": "/integrations/frameworks/dapr/dapr-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.Deno", @@ -429,7 +429,7 @@ }, { "match": "CommunityToolkit.Aspire.Hosting.LavinMQ", - "href": "/integrations/messaging/lavinmq/" + "href": "/integrations/messaging/lavinmq/lavinmq-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.MailPit", @@ -525,7 +525,7 @@ }, { "match": "CommunityToolkit.Aspire.Hosting.Azure.Dapr.Redis", - "href": "/integrations/frameworks/dapr/" + "href": "/integrations/frameworks/dapr/dapr-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.Azure.StaticWebApps", @@ -533,7 +533,7 @@ }, { "match": "CommunityToolkit.Aspire.Hosting.Dapr.AzureRedis", - "href": "/integrations/frameworks/dapr/" + "href": "/integrations/frameworks/dapr/dapr-get-started/" }, { "match": "CommunityToolkit.Aspire.Hosting.Flagd", From 0f5387b92cc5110591dae6bca3563866529d1c04 Mon Sep 17 00:00:00 2001 From: David Pine <7679720+IEvangelist@users.noreply.github.com> Date: Fri, 17 Jul 2026 12:18:49 -0500 Subject: [PATCH 2/5] Correct Dapr and LavinMQ connection guidance Use the Dapr endpoint hostname expected by the JavaScript SDK and document LavinMQ's fixed default host ports. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 239a58a9-4a99-4706-bd16-dfbe22da34ea --- .../content/docs/integrations/frameworks/dapr/dapr-connect.mdx | 2 +- .../docs/integrations/messaging/lavinmq/lavinmq-host.mdx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-connect.mdx b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-connect.mdx index 839a84789..fab2ee61f 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-connect.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-connect.mdx @@ -77,7 +77,7 @@ import { CommunicationProtocolEnum, DaprClient, HttpMethod } from '@dapr/dapr'; const endpoint = new URL(process.env.DAPR_HTTP_ENDPOINT!); const client = new DaprClient({ - daprHost: endpoint.origin, + daprHost: endpoint.hostname, daprPort: endpoint.port, communicationProtocol: CommunicationProtocolEnum.HTTP, }); diff --git a/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-host.mdx b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-host.mdx index 6bee73e64..e34c1c60f 100644 --- a/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-host.mdx +++ b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-host.mdx @@ -127,7 +127,8 @@ const lavinmq = await builder.addLavinMQ('lavinmq', { -Omit the parameters to let Aspire select available host ports. +When you omit these parameters, the integration binds host ports `5672` and +`15672`. Pass alternative values when either port is already occupied. ## Persist data in a volume From 3e6c046c4762dc3537feeb9e3ddd9a3a04a20721 Mon Sep 17 00:00:00 2001 From: David Pine <7679720+IEvangelist@users.noreply.github.com> Date: Fri, 17 Jul 2026 13:05:23 -0500 Subject: [PATCH 3/5] Preserve integration logo artwork Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 239a58a9-4a99-4706-bd16-dfbe22da34ea --- src/frontend/src/components/ThemeImage.astro | 3 ++- .../docs/integrations/devtools/dab/dab-connect.mdx | 1 + .../integrations/devtools/dab/dab-get-started.mdx | 1 + .../docs/integrations/devtools/dab/dab-host.mdx | 1 + .../integrations/frameworks/dapr/dapr-connect.mdx | 14 ++++++++------ .../frameworks/dapr/dapr-get-started.mdx | 14 ++++++++------ .../integrations/frameworks/dapr/dapr-host.mdx | 14 ++++++++------ .../messaging/lavinmq/lavinmq-connect.mdx | 1 + .../messaging/lavinmq/lavinmq-get-started.mdx | 1 + .../messaging/lavinmq/lavinmq-host.mdx | 1 + .../tests/unit/custom-components.vitest.test.ts | 2 +- 11 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/frontend/src/components/ThemeImage.astro b/src/frontend/src/components/ThemeImage.astro index fa91bcaa0..57ac98864 100644 --- a/src/frontend/src/components/ThemeImage.astro +++ b/src/frontend/src/components/ThemeImage.astro @@ -29,7 +29,7 @@ const { const imageWidth = width ?? dark.width; const imageHeight = height ?? dark.height; const imageClass = [classOverride, 'theme-image'].filter(Boolean).join(' '); -const imageOptions = { width: imageWidth, height: imageHeight }; +const imageOptions = { width: imageWidth, height: imageHeight, fit: 'contain' as const }; const optimizedLight = await getImage({ src: light, ...imageOptions }); const optimizedDark = await getImage({ src: dark, ...imageOptions }); const themedImageProps = { @@ -41,6 +41,7 @@ const themedImageProps = { 'data-dark-srcset': optimizedDark.srcSet.attribute, width: imageWidth, height: imageHeight, + fit: 'contain' as const, decoding: 'async' as const, loading: 'lazy' as const, }; diff --git a/src/frontend/src/content/docs/integrations/devtools/dab/dab-connect.mdx b/src/frontend/src/content/docs/integrations/devtools/dab/dab-connect.mdx index b0a92bcf8..f56559252 100644 --- a/src/frontend/src/content/docs/integrations/devtools/dab/dab-connect.mdx +++ b/src/frontend/src/content/docs/integrations/devtools/dab/dab-connect.mdx @@ -15,6 +15,7 @@ import dabIcon from '@assets/icons/data-api-builder-icon.png'; alt="Data API Builder logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/devtools/dab/dab-get-started.mdx b/src/frontend/src/content/docs/integrations/devtools/dab/dab-get-started.mdx index 3e732a806..510abf94c 100644 --- a/src/frontend/src/content/docs/integrations/devtools/dab/dab-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/devtools/dab/dab-get-started.mdx @@ -15,6 +15,7 @@ import dabIcon from '@assets/icons/data-api-builder-icon.png'; alt="Data API Builder logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/devtools/dab/dab-host.mdx b/src/frontend/src/content/docs/integrations/devtools/dab/dab-host.mdx index 624cdf242..1bc43b45f 100644 --- a/src/frontend/src/content/docs/integrations/devtools/dab/dab-host.mdx +++ b/src/frontend/src/content/docs/integrations/devtools/dab/dab-host.mdx @@ -15,6 +15,7 @@ import dabIcon from '@assets/icons/data-api-builder-icon.png'; alt="Data API Builder logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-connect.mdx b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-connect.mdx index fab2ee61f..943ad3975 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-connect.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-connect.mdx @@ -4,20 +4,22 @@ description: Use Aspire-injected Dapr HTTP and gRPC endpoints from C#, TypeScrip next: false --- -import { Image } from 'astro:assets'; import { Badge, Tabs, TabItem } from '@astrojs/starlight/components'; import InstallDotNetPackage from '@components/InstallDotNetPackage.astro'; -import daprIcon from '@assets/icons/dapr-icon.png'; +import ThemeImage from '@components/ThemeImage.astro'; +import daprLightIcon from '@assets/icons/dapr-light-icon.png'; +import daprDarkIcon from '@assets/icons/dapr-icon.png'; -Dapr logo This page describes how an app connects to the Dapr sidecar attached to it. For sidecar and component configuration in the AppHost, see [Set up Dapr resources in the AppHost](../dapr-host/). diff --git a/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-get-started.mdx b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-get-started.mdx index 115fbf342..79b2eb7a4 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-get-started.mdx @@ -4,19 +4,21 @@ description: Learn how Aspire models Dapr sidecars and components, then connects prev: false --- -import { Image } from 'astro:assets'; import { Badge, LinkButton, Steps } from '@astrojs/starlight/components'; -import daprIcon from '@assets/icons/dapr-icon.png'; +import ThemeImage from '@components/ThemeImage.astro'; +import daprLightIcon from '@assets/icons/dapr-light-icon.png'; +import daprDarkIcon from '@assets/icons/dapr-icon.png'; -Dapr logo [Dapr](https://dapr.io/) is a portable runtime for building distributed applications with APIs for service invocation, state, messaging, secrets, and more. The Aspire Dapr integration models Dapr sidecars and component resources alongside the apps that use them. diff --git a/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-host.mdx b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-host.mdx index 85455a485..dafc28285 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-host.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/dapr/dapr-host.mdx @@ -3,20 +3,22 @@ title: Set up Dapr resources in the AppHost description: Install the Community Toolkit Dapr hosting integration and configure sidecars, state stores, pub/sub, metadata, and Azure deployment. --- -import { Image } from 'astro:assets'; import { Aside, Badge, Tabs, TabItem } from '@astrojs/starlight/components'; import LearnMore from '@components/LearnMore.astro'; -import daprIcon from '@assets/icons/dapr-icon.png'; +import ThemeImage from '@components/ThemeImage.astro'; +import daprLightIcon from '@assets/icons/dapr-light-icon.png'; +import daprDarkIcon from '@assets/icons/dapr-icon.png'; -Dapr logo This article is the AppHost API reference for the [📦 CommunityToolkit.Aspire.Hosting.Dapr](https://www.nuget.org/packages/CommunityToolkit.Aspire.Hosting.Dapr) package. If you're new to the integration, start with [Get started with Dapr and Aspire](../dapr-get-started/). For app-side endpoint variables and SDK examples, see [Connect Aspire apps to Dapr sidecars](../dapr-connect/). diff --git a/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-connect.mdx b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-connect.mdx index fb42ea9da..daa739fa0 100644 --- a/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-connect.mdx +++ b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-connect.mdx @@ -16,6 +16,7 @@ import lavinmqIcon from '@assets/icons/lavinmq-icon.png'; alt="LavinMQ logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-get-started.mdx b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-get-started.mdx index 927d1e5aa..3977cc75c 100644 --- a/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-get-started.mdx +++ b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-get-started.mdx @@ -15,6 +15,7 @@ import lavinmqIcon from '@assets/icons/lavinmq-icon.png'; alt="LavinMQ logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-host.mdx b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-host.mdx index e34c1c60f..a0c39753b 100644 --- a/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-host.mdx +++ b/src/frontend/src/content/docs/integrations/messaging/lavinmq/lavinmq-host.mdx @@ -15,6 +15,7 @@ import lavinmqIcon from '@assets/icons/lavinmq-icon.png'; alt="LavinMQ logo" width={100} height={100} + fit="contain" class:list={'float-inline-left icon'} data-zoom-off /> diff --git a/src/frontend/tests/unit/custom-components.vitest.test.ts b/src/frontend/tests/unit/custom-components.vitest.test.ts index c7c582338..e7f8c1ebc 100644 --- a/src/frontend/tests/unit/custom-components.vitest.test.ts +++ b/src/frontend/tests/unit/custom-components.vitest.test.ts @@ -373,7 +373,7 @@ const basicRenderCases: BasicRenderCase[] = [ alt: 'Themed diagram', zoomable: false, }, - includes: ['theme-image', 'data-light=', 'data-dark=', 'Themed diagram'], + includes: ['theme-image', 'data-light=', 'data-dark=', 'fit=contain', 'Themed diagram'], }, { name: 'ImageShowcase renders image text and CTA', From ff855811c2257fc506a3014284b00c46e91d6afd Mon Sep 17 00:00:00 2001 From: David Pine <7679720+IEvangelist@users.noreply.github.com> Date: Fri, 17 Jul 2026 13:28:44 -0500 Subject: [PATCH 4/5] Add AppHost language parity examples Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 239a58a9-4a99-4706-bd16-dfbe22da34ea --- .../integrations/devtools/dab/dab-connect.mdx | 4 +- .../integrations/devtools/dab/dab-host.mdx | 72 ++++++++++++++-- .../frameworks/dapr/dapr-host.mdx | 84 ++++++++++++++++++- .../messaging/lavinmq/lavinmq-connect.mdx | 43 ++++++++-- .../messaging/lavinmq/lavinmq-host.mdx | 79 ++++++++++++++++- 5 files changed, 259 insertions(+), 23 deletions(-) diff --git a/src/frontend/src/content/docs/integrations/devtools/dab/dab-connect.mdx b/src/frontend/src/content/docs/integrations/devtools/dab/dab-connect.mdx index f56559252..0ca2a2192 100644 --- a/src/frontend/src/content/docs/integrations/devtools/dab/dab-connect.mdx +++ b/src/frontend/src/content/docs/integrations/devtools/dab/dab-connect.mdx @@ -26,14 +26,14 @@ DAB has no dedicated Community Toolkit client package. It exposes standard REST ## Connection values -`DataApiBuilderContainerResource` implements service discovery rather than a connection string. For a DAB resource named `dab`, `.WithReference(dab)` or `.withReference(dab)` injects: +`DataApiBuilderContainerResource` implements service discovery rather than a connection string. Referencing a DAB resource named `dab` injects: | Environment variable | Description | | ------------------------ | ------------------------------------------------------------ | | `services__dab__http__0` | Service-discovery endpoint used by Aspire-aware HTTP clients | | `DAB_HTTP` | Direct URL for the DAB HTTP endpoint | -The AppHost resource also exposes `PrimaryEndpoint`, `Host`, `Port`, and `UriExpression` for building custom AppHost expressions. These are AppHost properties, not additional consuming-app environment variables. +The AppHost resource also exposes endpoint properties for building custom expressions. These are AppHost properties, not additional consuming-app environment variables. See [Use endpoint properties](../dab-host/#use-endpoint-properties) for synchronized C# and TypeScript examples.