From 49ce29b8779261d0b42fad6e92145db45d974ff6 Mon Sep 17 00:00:00 2001 From: Adam Ratzman Date: Mon, 15 Jun 2026 17:38:23 -0400 Subject: [PATCH 1/2] Make npm package README TypeScript-only and document standalone dashboard Port of microsoft/aspire#18220 to release/13.4. - Remove the C# AppHost example so the npm README is TypeScript-only. - Refresh the TypeScript example to the current ts-starter template (apphost.mts importing ./.aspire/modules/aspire.mjs), fixing the stale apphost.ts / aspire.js references that no longer match the template. - Add a Postgres + Redis backing-services example with an `aspire add` note for the postgresql and redis integrations. - Add a Standalone dashboard section documenting `aspire dashboard run`. - Update NpmCliPackageTests to assert the TypeScript-only README content. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../pack-cli-npm-package.pointer.README.md | 69 ++++++++++++------- .../Pipelines/NpmCliPackageTests.cs | 8 +++ 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/eng/scripts/pack-cli-npm-package.pointer.README.md b/eng/scripts/pack-cli-npm-package.pointer.README.md index 340befe48d4..69aa0af780f 100644 --- a/eng/scripts/pack-cli-npm-package.pointer.README.md +++ b/eng/scripts/pack-cli-npm-package.pointer.README.md @@ -13,53 +13,60 @@ Use an AppHost to describe how services, frontends, containers, databases, cache ## A simple app definition -The same application definition can be written in different languages. +You describe your app in a TypeScript AppHost (`apphost.mts`). The example below runs an Express API and a Vite frontend, exposes the API over HTTP, and wires the frontend to it: -__C#__ (`apphost.cs`) +```typescript +import { createBuilder } from './.aspire/modules/aspire.mjs'; -```csharp -var builder = DistributedApplication.CreateBuilder(args); +const builder = await createBuilder(); -var cache = builder.AddRedis("cache"); +// Run the Express API and expose its HTTP endpoint externally. +const app = await builder + .addNodeApp("app", "./api", "src/index.ts") + .withHttpEndpoint({ env: "PORT" }) + .withExternalHttpEndpoints(); -var api = builder.AddNodeApp("api", "./api", "src/index.ts") - .WithReference(cache) - .WaitFor(cache) - .WithHttpEndpoint(env: "PORT") - .WithExternalHttpEndpoints(); +// Run the Vite frontend after the API and inject the API URL for local proxying. +const frontend = await builder + .addViteApp("frontend", "./frontend") + .withReference(app) + .waitFor(app); -builder.AddViteApp("frontend", "./frontend") - .WithReference(api) - .WaitFor(api); +// Bundle the frontend build output into the API container for publish/deploy. +await app.publishWithContainerFiles(frontend, "./static"); -builder.Build().Run(); +await builder.build().run(); ``` -__TypeScript__ (`apphost.ts`) +Each builder call returns a promise, so `await` is used to get the resource before referencing it from another resource. `aspire run` builds and launches everything, then opens the dashboard. + +### Add backing services + +Resources like databases and caches are added the same way and connected with `withReference`. `waitFor` holds dependents until the resource is ready: ```typescript -import { createBuilder } from './.aspire/modules/aspire.js'; +import { createBuilder } from './.aspire/modules/aspire.mjs'; const builder = await createBuilder(); +const postgres = await builder.addPostgres("postgres"); +const db = await postgres.addDatabase("db"); + const cache = await builder.addRedis("cache"); -const api = await builder +await builder .addNodeApp("api", "./api", "src/index.ts") - .withReference(cache) - .waitFor(cache) .withHttpEndpoint({ env: "PORT" }) - .withExternalHttpEndpoints(); - -await builder - .addViteApp("frontend", "./frontend") - .withReference(api) - .waitFor(api); + .withExternalHttpEndpoints() + .withReference(db) + .withReference(cache) + .waitFor(db) + .waitFor(cache); await builder.build().run(); ``` -## Install +`addPostgres` and `addRedis` become available once the matching integrations are installed with `aspire add postgresql` and `aspire add redis`. This package requires Node.js 20 or later. @@ -83,6 +90,16 @@ aspire run The native platform packages are installed through npm optional dependencies. Do not install this package with optional dependencies disabled, or the `aspire` launcher will not be able to find the native CLI binary. +## Standalone dashboard + +The Aspire dashboard shows logs, traces, and metrics for any app that exports OpenTelemetry, even without an AppHost. Start one in a single command: + +```bash +aspire dashboard run +``` + +This launches the dashboard with an OTLP endpoint your apps can point at via `OTEL_EXPORTER_OTLP_ENDPOINT`. Use `aspire dashboard run --help` to see options such as `--frontend-url`, `--otlp-grpc-url`, and `--allow-anonymous`. + ## Update ```bash diff --git a/tests/Infrastructure.Tests/Pipelines/NpmCliPackageTests.cs b/tests/Infrastructure.Tests/Pipelines/NpmCliPackageTests.cs index 3d4adcd3dc3..68643b3d032 100644 --- a/tests/Infrastructure.Tests/Pipelines/NpmCliPackageTests.cs +++ b/tests/Infrastructure.Tests/Pipelines/NpmCliPackageTests.cs @@ -186,7 +186,15 @@ public async Task PackScriptGeneratesPointerPackageMetadataMapAndReadme() Assert.Contains($"npm install -g {PackageName}", readme); Assert.Contains("The native platform packages are installed through npm optional dependencies.", readme); Assert.Contains("If you run `aspire update --self` from an npm install, the CLI points you back to this npm update command.", readme); + Assert.Contains("TypeScript AppHost (`apphost.mts`)", readme); + Assert.Contains("import { createBuilder } from './.aspire/modules/aspire.mjs';", readme); + Assert.Contains("aspire dashboard run", readme); + Assert.DoesNotContain("apphost.ts", readme); + Assert.DoesNotContain("./.aspire/modules/aspire.js", readme); Assert.DoesNotContain("__PACKAGE_NAME__", readme); + // The C# AppHost example was intentionally removed; the npm README is TypeScript-only. + Assert.DoesNotContain("apphost.cs", readme); + Assert.DoesNotContain("```csharp", readme); } [Theory] From d576db102e038cbeb1ee6bc54909640160d98c47 Mon Sep 17 00:00:00 2001 From: Adam Ratzman Date: Mon, 15 Jun 2026 17:44:58 -0400 Subject: [PATCH 2/2] Restore Install heading dropped from npm README Code review found the install instructions were orphaned under the 'Add backing services' subsection after the C# example removal. Restore the '## Install' heading so install steps render as their own section. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- eng/scripts/pack-cli-npm-package.pointer.README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eng/scripts/pack-cli-npm-package.pointer.README.md b/eng/scripts/pack-cli-npm-package.pointer.README.md index 69aa0af780f..b0ab6d2d05f 100644 --- a/eng/scripts/pack-cli-npm-package.pointer.README.md +++ b/eng/scripts/pack-cli-npm-package.pointer.README.md @@ -68,6 +68,8 @@ await builder.build().run(); `addPostgres` and `addRedis` become available once the matching integrations are installed with `aspire add postgresql` and `aspire add redis`. +## Install + This package requires Node.js 20 or later. ```bash