diff --git a/src/frontend/src/content/docs/architecture/resource-api-patterns.mdx b/src/frontend/src/content/docs/architecture/resource-api-patterns.mdx index 7366782f8..f1cb1745d 100644 --- a/src/frontend/src/content/docs/architecture/resource-api-patterns.mdx +++ b/src/frontend/src/content/docs/architecture/resource-api-patterns.mdx @@ -156,9 +156,11 @@ Custom value objects defer evaluation and allow the framework to discover depend |--|--|--|--| | `IValueProvider` | `ValueTask GetValueAsync(CancellationToken)` | Run | Resolve live values at runtime | | `IManifestExpressionProvider` | `string ValueExpression { get; }` | Publish | Emit structured expressions in manifests | +| `IExpressionValue` | Inherits `IValueProvider` and `IManifestExpressionProvider` | Run and publish | Mark a value object as usable wherever an expression-backed value is accepted | | `IValueWithReferences` _(opt.)_ | `IEnumerable References { get; }` | Both (if needed) | Declare dependencies on other resources | - **Implement** `IValueProvider` and `IManifestExpressionProvider` on all structured value types. +- **Implement** `IExpressionValue` when a structured value type should be accepted by APIs such as `WithEnvironment(...)`. - **Implement** `IValueWithReferences` only when your type holds resource references. ### Attaching to resources @@ -198,5 +200,6 @@ public static IResourceBuilder WithEnvironment( |--|--|--| | `IValueProvider` | `GetValueAsync(...)` | Deferred runtime resolution | | `IManifestExpressionProvider` | `ValueExpression` | Structured publish-time expression | +| `IExpressionValue` | `IValueProvider` + `IManifestExpressionProvider` | Reusable expression-backed value | | `IValueWithReferences` _(opt.)_ | `References` | Declare resource dependencies | -| `WithEnvironment(...)` | `new("NAME", valueProvider)` | Attach structured values unflattened | \ No newline at end of file +| `WithEnvironment(...)` | `new("NAME", valueProvider)` | Attach structured values unflattened | diff --git a/src/frontend/src/content/docs/extensibility/multi-language-integration-authoring.mdx b/src/frontend/src/content/docs/extensibility/multi-language-integration-authoring.mdx index ef0a36529..f86be32fc 100644 --- a/src/frontend/src/content/docs/extensibility/multi-language-integration-authoring.mdx +++ b/src/frontend/src/content/docs/extensibility/multi-language-integration-authoring.mdx @@ -479,7 +479,13 @@ When a parameter accepts multiple types, use `[AspireUnion]` to declare the vali public static IResourceBuilder WithEnvironment( this IResourceBuilder builder, string name, - [AspireUnion(typeof(string), typeof(ReferenceExpression), typeof(EndpointReference))] + [AspireUnion( + typeof(string), + typeof(ReferenceExpression), + typeof(EndpointReference), + typeof(IResourceBuilder), + typeof(IResourceBuilder), + typeof(IExpressionValue))] object value) where T : IResourceWithEnvironment { @@ -596,7 +602,7 @@ The following types are ATS-compatible and can be used in exported method signat | **Collections** | `List`, `Dictionary`, arrays — where `T` is ATS-compatible | | **Delegates** | `Action`, `Func`, and other delegate types (use `RunSyncOnBackgroundThread = true` for synchronous delegates invoked inline) | | **Services** | `ILogger`, `IServiceProvider`, `IConfiguration` (already exported by the core framework) | -| **Special** | `ParameterResource`, `ReferenceExpression`, `EndpointReference`, `CancellationToken` | +| **Special** | `ParameterResource`, `ReferenceExpression`, `EndpointReference`, `IExpressionValue`, `CancellationToken` | | **Nullable** | Any of the above as nullable (`T?`) | Types that are **not** ATS-compatible include: interpolated string handlers and custom complex types without `[AspireExport]` or `[AspireDto]`. diff --git a/src/frontend/src/content/docs/whats-new/aspire-13-3.mdx b/src/frontend/src/content/docs/whats-new/aspire-13-3.mdx index 65785496f..4091d39c3 100644 --- a/src/frontend/src/content/docs/whats-new/aspire-13-3.mdx +++ b/src/frontend/src/content/docs/whats-new/aspire-13-3.mdx @@ -137,6 +137,36 @@ You can also disable it in `launchSettings.json`: For more details on container networking, see [Inner-loop networking overview](/fundamentals/networking-overview/). +## 🔀 Unified withEnvironment API for multi-language AppHosts + +Aspire 13.3 introduces a unified `withEnvironment(name, value)` API for polyglot AppHosts (TypeScript, Java, Python, Go, Rust). Previously, environment variable injection required separate methods for each value kind (`withEnvironmentEndpoint`, `withEnvironmentParameter`, `withEnvironmentConnectionString`, and so on). Now, a single call handles all value types: + +```typescript title="TypeScript — apphost.ts" +const api = await builder.addApi("api") + .withEnvironment("SERVICE_URL", cache.primaryEndpoint) + .withEnvironment("API_KEY", apiKeyParam) + .withEnvironment("DB", database); +``` + +The `value` argument accepts any of: a plain `string`, a `ReferenceExpression`, an `EndpointReference`, a parameter builder, a connection string resource builder, or an `IExpressionValue` — a new public interface that any type implementing both `IValueProvider` and `IManifestExpressionProvider` can implement to plug into this unified path. + +### Deprecation of old withEnvironment* aliases + +The previous per-kind aliases are still generated for backward compatibility but are marked `@deprecated` in the SDK. Migrate to `withEnvironment(name, value)` at your convenience: + +| Deprecated | Replacement | +|---|---| +| `withEnvironmentExpression` | `withEnvironment` | +| `withEnvironmentEndpoint` | `withEnvironment` | +| `withEnvironmentParameter` | `withEnvironment` | +| `withEnvironmentConnectionString` | `withEnvironment` | +| `withEnvironmentFromOutput` | `withEnvironment` | +| `withEnvironmentFromKeyVaultSecret` | `withEnvironment` | + + + For integration authors, see [Multi-language integrations](/extensibility/multi-language-integration-authoring/#union-types) for union-type parameter annotations. + + ## 🐍 Python starter template migrated to TypeScript AppHost The `aspire-py-starter` template (Starter App with FastAPI and React) has moved from the `dotnet new` template system to the Aspire CLI template system and now uses a **TypeScript AppHost** instead of a C# AppHost. This aligns it with the same pattern as the `aspire-ts-starter` template.