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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 44 additions & 25 deletions eng/scripts/pack-cli-npm-package.pointer.README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,52 +13,61 @@ 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();
```

`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.
Expand All @@ -83,6 +92,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
Expand Down
8 changes: 8 additions & 0 deletions tests/Infrastructure.Tests/Pipelines/NpmCliPackageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Loading