diff --git a/extension/loc/xlf/aspire-vscode.xlf b/extension/loc/xlf/aspire-vscode.xlf
index 8855e802d27..2545cfe377c 100644
--- a/extension/loc/xlf/aspire-vscode.xlf
+++ b/extension/loc/xlf/aspire-vscode.xlf
@@ -434,7 +434,7 @@
Welcome to Aspire
- Whether to the Aspire MCP server when a workspace is open.
+ Whether to register the Aspire MCP server when a workspace is open.
Yes
diff --git a/extension/package.json b/extension/package.json
index 773c83e6f66..9c245cea22c 100644
--- a/extension/package.json
+++ b/extension/package.json
@@ -30,6 +30,8 @@
"workspaceContains:**/*.csproj",
"onView:workbench.view.debug",
"workspaceContains:**/apphost.cs",
+ "workspaceContains:**/apphost.ts",
+ "workspaceContains:**/apphost.js",
"onCommand:aspire-vscode.installCliStable",
"onCommand:aspire-vscode.installCliDaily",
"onCommand:aspire-vscode.verifyCliInstalled"
@@ -290,24 +292,24 @@
"explorer/context": [
{
"command": "aspire-vscode.runAppHost",
- "when": "resourceExtname == .cs && resourceFilename =~ /apphost\\.cs$/i",
+ "when": "resourceFilename =~ /apphost\\.(cs|ts|js)$/i",
"group": "aspire_actions@1"
},
{
"command": "aspire-vscode.debugAppHost",
- "when": "resourceExtname == .cs && resourceFilename =~ /apphost\\.cs$/i",
+ "when": "resourceFilename =~ /apphost\\.(cs|ts|js)$/i",
"group": "aspire_actions@2"
}
],
"editor/title/run": [
{
"command": "aspire-vscode.runAppHost",
- "when": "(aspire.fileIsAppHostCs || aspire.workspaceHasAppHost) && aspire.editorSupportsRunDebug",
+ "when": "(aspire.fileIsAppHost || aspire.workspaceHasAppHost) && aspire.editorSupportsRunDebug",
"group": "navigation@-4"
},
{
"command": "aspire-vscode.debugAppHost",
- "when": "(aspire.fileIsAppHostCs || aspire.workspaceHasAppHost) && aspire.editorSupportsRunDebug",
+ "when": "(aspire.fileIsAppHost || aspire.workspaceHasAppHost) && aspire.editorSupportsRunDebug",
"group": "navigation@-3"
}
],
diff --git a/extension/src/capabilities.ts b/extension/src/capabilities.ts
index f1441c1e16a..da4ad8a7955 100644
--- a/extension/src/capabilities.ts
+++ b/extension/src/capabilities.ts
@@ -3,7 +3,7 @@ import { RunSessionInfo } from './dcp/types';
export type Capability =
| 'prompting' // Support using VS Code to capture user input instead of CLI
- | 'baseline.v1'
+ | 'baseline.v1'
| 'secret-prompts.v1'
| 'file-pickers.v1'
| 'build-dotnet-using-cli' // Support building .NET projects using the CLI
@@ -12,7 +12,9 @@ export type Capability =
| 'project' // Support for running C# projects
| 'ms-dotnettools.csharp' // Older AppHost versions used this extension identifier instead of project
| 'python' // Support for running Python projects
- | 'ms-python.python'; // Older AppHost versions used this extension identifier instead of python
+ | 'ms-python.python' // Older AppHost versions used this extension identifier instead of python
+ | 'node' // Support for running Node.js projects
+ | 'browser'; // Support for browser debugging (built-in to VS Code via js-debug)
export type Capabilities = Capability[];
@@ -33,6 +35,11 @@ export function isPythonInstalled() {
return isExtensionInstalled("ms-python.python");
}
+export function isNodeInstalled() {
+ // Node.js debugging uses VS Code's built-in js-debug, no extension needed
+ return true;
+}
+
export function getSupportedCapabilities(): Capabilities {
const capabilities: Capabilities = ['prompting', 'baseline.v1', 'secret-prompts.v1', 'file-pickers.v1', 'build-dotnet-using-cli'];
@@ -51,6 +58,11 @@ export function getSupportedCapabilities(): Capabilities {
capabilities.push("ms-python.python");
}
+ if (isNodeInstalled()) {
+ capabilities.push("node");
+ capabilities.push("browser");
+ }
+
return capabilities;
}
diff --git a/extension/src/dcp/types.ts b/extension/src/dcp/types.ts
index 47c9f804a31..02d98f83eff 100644
--- a/extension/src/dcp/types.ts
+++ b/extension/src/dcp/types.ts
@@ -44,6 +44,28 @@ export function isPythonLaunchConfiguration(obj: any): obj is PythonLaunchConfig
return obj && obj.type === 'python';
}
+export interface NodeLaunchConfiguration extends ExecutableLaunchConfiguration {
+ type: "node"; // Provided by VS Code's built-in js-debug, no extension needed
+ script_path?: string;
+ runtime_executable?: string;
+ working_directory?: string;
+}
+
+export function isNodeLaunchConfiguration(obj: any): obj is NodeLaunchConfiguration {
+ return obj && obj.type === 'node';
+}
+
+export interface BrowserLaunchConfiguration extends ExecutableLaunchConfiguration {
+ type: "browser";
+ url?: string;
+ web_root?: string;
+ browser?: string;
+}
+
+export function isBrowserLaunchConfiguration(obj: any): obj is BrowserLaunchConfiguration {
+ return obj && obj.type === 'browser';
+}
+
export interface EnvVar {
name: string;
value: string;
@@ -121,6 +143,7 @@ export interface AspireResourceExtendedDebugConfiguration extends vscode.DebugCo
runId: string;
debugSessionId: string | null;
projectFile?: string;
+ isApphost?: boolean;
}
export type AspireCommandType = 'run' | 'deploy' | 'publish' | 'do';
diff --git a/extension/src/debugger/AspireDebugSession.ts b/extension/src/debugger/AspireDebugSession.ts
index b38dd770932..adcff239824 100644
--- a/extension/src/debugger/AspireDebugSession.ts
+++ b/extension/src/debugger/AspireDebugSession.ts
@@ -1,13 +1,14 @@
import * as vscode from "vscode";
import { EventEmitter } from "vscode";
import * as fs from "fs";
-import { createDebugAdapterTracker } from "./adapterTracker";
-import { AspireResourceExtendedDebugConfiguration, AspireResourceDebugSession, EnvVar, AspireExtendedDebugConfiguration, ProjectLaunchConfiguration, StartAppHostOptions } from "../dcp/types";
+import { createDebugAdapterTracker, AppHostRestartHandler } from "./adapterTracker";
+import { AspireResourceExtendedDebugConfiguration, AspireResourceDebugSession, EnvVar, AspireExtendedDebugConfiguration, NodeLaunchConfiguration, ProjectLaunchConfiguration, StartAppHostOptions } from "../dcp/types";
import { extensionLogOutputChannel } from "../utils/logging";
import AspireDcpServer, { generateDcpIdPrefix } from "../dcp/AspireDcpServer";
import { spawnCliProcess } from "./languages/cli";
import { disconnectingFromSession, launchingWithAppHost, launchingWithDirectory, processExceptionOccurred, processExitedWithCode, aspireDashboard } from "../loc/strings";
import { projectDebuggerExtension } from "./languages/dotnet";
+import { nodeDebuggerExtension } from "./languages/node";
import AspireRpcServer from "../server/AspireRpcServer";
import { createDebugSessionConfiguration } from "./debuggerExtensions";
import { AspireTerminalProvider } from "../utils/AspireTerminalProvider";
@@ -34,7 +35,6 @@ export class AspireDebugSession implements vscode.DebugAdapter {
private _dashboardDebugSession: vscode.DebugSession | null = null;
private readonly _disposables: vscode.Disposable[] = [];
private _disposed = false;
- private _userInitiatedStop = false;
public readonly onDidSendMessage = this._onDidSendMessage.event;
public readonly debugSessionId: string;
@@ -129,7 +129,6 @@ export class AspireDebugSession implements vscode.DebugAdapter {
}
else if (message.command === 'disconnect' || message.command === 'terminate') {
this.sendMessageWithEmoji("🔌", disconnectingFromSession);
- this._userInitiatedStop = true;
this.dispose();
this.sendEvent({
@@ -215,33 +214,71 @@ export class AspireDebugSession implements vscode.DebugAdapter {
}
}
- createDebugAdapterTrackerCore(debugAdapter: string) {
+ createDebugAdapterTrackerCore(debugAdapter: string, onAppHostRestartRequested?: AppHostRestartHandler) {
if (this._trackedDebugAdapters.includes(debugAdapter)) {
return;
}
this._trackedDebugAdapters.push(debugAdapter);
- this._disposables.push(createDebugAdapterTracker(this._dcpServer, debugAdapter));
+ this._disposables.push(createDebugAdapterTracker(this._dcpServer, debugAdapter, onAppHostRestartRequested));
}
+ private static readonly _nodeAppHostExtensions = ['.js', '.ts', '.mjs', '.mts', '.cjs', '.cts'];
+
+ private _appHostRestartRequested = false;
+
async startAppHost(projectFile: string, args: string[], environment: EnvVar[], debug: boolean, options: StartAppHostOptions): Promise {
try {
- this.createDebugAdapterTrackerCore(projectDebuggerExtension.debugAdapter);
+ const fileExtension = path.extname(projectFile).toLowerCase();
+ const isNodeAppHost = AspireDebugSession._nodeAppHostExtensions.includes(fileExtension);
+
+ const debuggerExtension = isNodeAppHost ? nodeDebuggerExtension : projectDebuggerExtension;
+
+ // Register the adapter tracker with an app host restart handler.
+ // When the user clicks "restart" on the app host child session,
+ // we suppress VS Code's automatic child restart and restart the
+ // entire Aspire debug session instead.
+ this.createDebugAdapterTrackerCore(debuggerExtension.debugAdapter, (debugSessionId) => {
+ if (debugSessionId === this.debugSessionId) {
+ this._appHostRestartRequested = true;
+ return true; // suppress VS Code's child restart
+ }
+ return false;
+ });
- // The CLI sends the full dotnet CLI args (e.g., ["run", "--no-build", "--project", "...", "--", ...appHostArgs]).
- // Since we launch the apphost directly via the debugger (not via dotnet run), extract only the args after "--".
- const separatorIndex = args.indexOf('--');
- const appHostArgs = separatorIndex >= 0 ? args.slice(separatorIndex + 1) : args;
+ let appHostArgs: string[];
+ let launchConfig;
+
+ if (isNodeAppHost) {
+ // The CLI prepends the runtime command (e.g., "npx") as args[0].
+ // Extract it as the runtimeExecutable and use the rest as the actual args.
+ const runtimeExecutable = args.length > 0 ? args[0] : undefined;
+ appHostArgs = args.slice(1);
+ launchConfig = {
+ script_path: projectFile,
+ working_directory: path.dirname(projectFile),
+ type: 'node',
+ ...(runtimeExecutable ? { runtime_executable: runtimeExecutable } : {})
+ } as NodeLaunchConfiguration;
+ }
+ else {
+ // The CLI sends the full dotnet CLI args (e.g., ["run", "--no-build", "--project", "...", "--", ...appHostArgs]).
+ // Since we launch the apphost directly via the debugger (not via dotnet run), extract only the args after "--".
+ const separatorIndex = args.indexOf('--');
+ appHostArgs = separatorIndex >= 0 ? args.slice(separatorIndex + 1) : args;
+ launchConfig = { project_path: projectFile, type: 'project' } as ProjectLaunchConfiguration;
+ }
extensionLogOutputChannel.info(`Starting AppHost for project: ${projectFile} with args: ${appHostArgs.join(' ')}`);
const appHostDebugSessionConfiguration = await createDebugSessionConfiguration(
this.configuration,
- { project_path: projectFile, type: 'project' } as ProjectLaunchConfiguration,
+ launchConfig,
appHostArgs,
environment,
- { debug, forceBuild: options.forceBuild, runId: '', debugSessionId: this.debugSessionId, isApphost: true, debugSession: this },
- projectDebuggerExtension);
+ { debug, forceBuild: isNodeAppHost ? false : options.forceBuild, runId: '', debugSessionId: this.debugSessionId, isApphost: true, debugSession: this },
+ debuggerExtension);
+
const appHostDebugSession = await this.startAndGetDebugSession(appHostDebugSessionConfiguration);
if (!appHostDebugSession) {
@@ -252,15 +289,15 @@ export class AspireDebugSession implements vscode.DebugAdapter {
const disposable = vscode.debug.onDidTerminateDebugSession(async session => {
if (this._appHostDebugSession && session.id === this._appHostDebugSession.id) {
- const command = this.configuration.command ?? 'run';
- // Only restart for 'run' — pipeline commands (do/deploy/publish) exit normally after completing.
- const shouldRestart = !this._userInitiatedStop && command === 'run';
+ // Only restart the Aspire session when the user explicitly clicked
+ // "restart" on the app host debug toolbar (detected via DAP tracker).
+ // All other cases (user stop, process crash/exit) just dispose.
+ const shouldRestart = this._appHostRestartRequested;
const config = this.configuration;
- // Always dispose the current Aspire debug session when the AppHost stops.
this.dispose();
if (shouldRestart) {
- extensionLogOutputChannel.info('AppHost terminated unexpectedly, restarting Aspire debug session');
+ extensionLogOutputChannel.info('AppHost restart requested, restarting Aspire debug session');
await vscode.debug.startDebugging(undefined, config);
}
}
diff --git a/extension/src/debugger/adapterTracker.ts b/extension/src/debugger/adapterTracker.ts
index bfd699a1cf1..d43439c9373 100644
--- a/extension/src/debugger/adapterTracker.ts
+++ b/extension/src/debugger/adapterTracker.ts
@@ -5,10 +5,36 @@ import AspireDcpServer from '../dcp/AspireDcpServer';
import { removeTrailingNewline } from '../utils/strings';
import { dcpServerNotInitialized } from '../loc/strings';
-export function createDebugAdapterTracker(dcpServer: AspireDcpServer, debugAdapter: string): vscode.Disposable {
+/**
+ * Callback invoked when a restart is requested on an app host debug session.
+ * Return `true` to suppress VS Code's automatic child session restart.
+ */
+export type AppHostRestartHandler = (debugSessionId: string) => boolean;
+
+export function createDebugAdapterTracker(dcpServer: AspireDcpServer, debugAdapter: string, onAppHostRestartRequested?: AppHostRestartHandler): vscode.Disposable {
return vscode.debug.registerDebugAdapterTrackerFactory(debugAdapter, {
createDebugAdapterTracker(session: vscode.DebugSession) {
return {
+ onWillReceiveMessage: message => {
+ if (!isDebugConfigurationWithId(session.configuration)) {
+ return;
+ }
+
+ // Detect restart requests on app host debug sessions.
+ // When the user clicks "restart" on the app host child session,
+ // suppress VS Code's automatic child restart so the Aspire debug
+ // session can restart entirely instead.
+ if (session.configuration.isApphost
+ && (message.command === 'disconnect' || message.command === 'terminate')
+ && message.arguments?.restart
+ && onAppHostRestartRequested
+ && session.configuration.debugSessionId) {
+ const shouldSuppress = onAppHostRestartRequested(session.configuration.debugSessionId);
+ if (shouldSuppress) {
+ message.arguments.restart = false;
+ }
+ }
+ },
onDidSendMessage: message => {
if (message.type === 'event' && message.event === 'output') {
if (!isDebugConfigurationWithId(session.configuration) || session.configuration.debugSessionId === null) {
diff --git a/extension/src/debugger/debuggerExtensions.ts b/extension/src/debugger/debuggerExtensions.ts
index c314c44fcb1..2d6c9aaccda 100644
--- a/extension/src/debugger/debuggerExtensions.ts
+++ b/extension/src/debugger/debuggerExtensions.ts
@@ -6,6 +6,8 @@ import { extensionLogOutputChannel } from "../utils/logging";
import { projectDebuggerExtension } from "./languages/dotnet";
import { isCsharpInstalled, isPythonInstalled } from "../capabilities";
import { pythonDebuggerExtension } from "./languages/python";
+import { nodeDebuggerExtension } from "./languages/node";
+import { browserDebuggerExtension } from "./languages/browser";
import { isDirectory } from "../utils/io";
// Represents a resource-specific debugger extension for when the default session configuration is not sufficient to launch the resource.
@@ -39,7 +41,8 @@ export async function createDebugSessionConfiguration(debugSessionConfig: Aspire
noDebug: !launchOptions.debug,
runId: launchOptions.runId,
debugSessionId: launchOptions.debugSessionId,
- console: 'internalConsole'
+ console: 'internalConsole',
+ isApphost: launchOptions.isApphost
};
if (debugSessionConfig.debuggers) {
@@ -72,6 +75,9 @@ export function getResourceDebuggerExtensions(): ResourceDebuggerExtension[] {
extensions.push(pythonDebuggerExtension);
}
+ extensions.push(nodeDebuggerExtension);
+ extensions.push(browserDebuggerExtension);
+
return extensions;
}
diff --git a/extension/src/debugger/languages/browser.ts b/extension/src/debugger/languages/browser.ts
new file mode 100644
index 00000000000..5719a1cd521
--- /dev/null
+++ b/extension/src/debugger/languages/browser.ts
@@ -0,0 +1,41 @@
+import { AspireResourceExtendedDebugConfiguration, ExecutableLaunchConfiguration, isBrowserLaunchConfiguration } from "../../dcp/types";
+import { browserDisplayName, browserLabel, invalidLaunchConfiguration } from "../../loc/strings";
+import { extensionLogOutputChannel } from "../../utils/logging";
+import { ResourceDebuggerExtension } from "../debuggerExtensions";
+
+export const browserDebuggerExtension: ResourceDebuggerExtension = {
+ resourceType: 'browser',
+ debugAdapter: 'pwa-msedge',
+ extensionId: null, // built-in to VS Code via js-debug
+ getDisplayName: (launchConfiguration: ExecutableLaunchConfiguration) => {
+ if (isBrowserLaunchConfiguration(launchConfiguration) && launchConfiguration.url) {
+ return browserDisplayName(launchConfiguration.url);
+ }
+ return browserLabel;
+ },
+ getSupportedFileTypes: () => [],
+ getProjectFile: () => '',
+ createDebugSessionConfigurationCallback: async (launchConfig, _args, _env, _launchOptions, debugConfiguration: AspireResourceExtendedDebugConfiguration): Promise => {
+ if (!isBrowserLaunchConfiguration(launchConfig)) {
+ extensionLogOutputChannel.info(`The resource type was not browser for ${JSON.stringify(launchConfig)}`);
+ throw new Error(invalidLaunchConfiguration(JSON.stringify(launchConfig)));
+ }
+
+ // Map browser name to VS Code js-debug adapter type (pwa- prefix required)
+ const browser = launchConfig.browser || 'msedge';
+ debugConfiguration.type = `pwa-${browser}`;
+ debugConfiguration.request = 'launch';
+ debugConfiguration.url = launchConfig.url;
+ debugConfiguration.webRoot = launchConfig.web_root;
+ debugConfiguration.sourceMaps = true;
+ debugConfiguration.resolveSourceMapLocations = ['**', '!**/node_modules/**'];
+ // Use an auto-managed temp user data directory so multiple browser debuggers
+ // can run concurrently without conflicting
+ debugConfiguration.userDataDir = true;
+
+ // Remove program/args/cwd since browser debugging doesn't use them
+ delete debugConfiguration.program;
+ delete debugConfiguration.args;
+ delete debugConfiguration.cwd;
+ }
+};
diff --git a/extension/src/debugger/languages/node.ts b/extension/src/debugger/languages/node.ts
new file mode 100644
index 00000000000..063ea1f48f7
--- /dev/null
+++ b/extension/src/debugger/languages/node.ts
@@ -0,0 +1,57 @@
+import { AspireResourceExtendedDebugConfiguration, ExecutableLaunchConfiguration, isNodeLaunchConfiguration } from "../../dcp/types";
+import { invalidLaunchConfiguration } from "../../loc/strings";
+import { extensionLogOutputChannel } from "../../utils/logging";
+import { ResourceDebuggerExtension } from "../debuggerExtensions";
+import * as vscode from 'vscode';
+
+function getProjectFile(launchConfig: ExecutableLaunchConfiguration): string {
+ if (isNodeLaunchConfiguration(launchConfig)) {
+ // Use the absolute script path if available, otherwise fall back to working directory.
+ // The working directory ensures cwd is set correctly for package manager mode (npm run dev).
+ return launchConfig.script_path || launchConfig.working_directory || '';
+ }
+
+ throw new Error(invalidLaunchConfiguration(JSON.stringify(launchConfig)));
+}
+
+export const nodeDebuggerExtension: ResourceDebuggerExtension = {
+ resourceType: 'node',
+ debugAdapter: 'node',
+ extensionId: null,
+ getDisplayName: (launchConfiguration: ExecutableLaunchConfiguration) => {
+ if (isNodeLaunchConfiguration(launchConfiguration)) {
+ const displayPath = launchConfiguration.script_path || launchConfiguration.working_directory || '';
+ return `Node.js: ${displayPath ? vscode.workspace.asRelativePath(displayPath) : 'unknown'}`;
+ }
+ return 'Node.js';
+ },
+ getSupportedFileTypes: () => ['.js', '.ts', '.mjs', '.mts', '.cjs', '.cts'],
+ getProjectFile: (launchConfig) => getProjectFile(launchConfig),
+ createDebugSessionConfigurationCallback: async (launchConfig, args, _env, _launchOptions, debugConfiguration: AspireResourceExtendedDebugConfiguration): Promise => {
+ if (!isNodeLaunchConfiguration(launchConfig)) {
+ extensionLogOutputChannel.info(`The resource type was not node for ${JSON.stringify(launchConfig)}`);
+ throw new Error(invalidLaunchConfiguration(JSON.stringify(launchConfig)));
+ }
+
+ debugConfiguration.type = 'node';
+
+ // Use working_directory for cwd if available
+ if (launchConfig.working_directory) {
+ debugConfiguration.cwd = launchConfig.working_directory;
+ }
+
+ if (launchConfig.runtime_executable) {
+ debugConfiguration.runtimeExecutable = launchConfig.runtime_executable;
+ }
+
+ // For package manager script execution (e.g., npm run dev), use args directly as runtimeArgs.
+ // The args from DCP already contain the full command (e.g., ["run", "dev", "--port", "5173"]).
+ if (launchConfig.runtime_executable && launchConfig.runtime_executable !== 'node') {
+ debugConfiguration.runtimeArgs = args ?? [];
+ delete debugConfiguration.args;
+ delete debugConfiguration.program;
+ }
+
+ debugConfiguration.resolveSourceMapLocations = ['**', '!**/node_modules/**'];
+ }
+};
diff --git a/extension/src/editor/AspireEditorCommandProvider.ts b/extension/src/editor/AspireEditorCommandProvider.ts
index 3cf0c5c4d09..3d4989c866c 100644
--- a/extension/src/editor/AspireEditorCommandProvider.ts
+++ b/extension/src/editor/AspireEditorCommandProvider.ts
@@ -59,23 +59,40 @@ export class AspireEditorCommandProvider implements vscode.Disposable {
vscode.commands.executeCommand('setContext', 'aspire.editorSupportsRunDebug', isSupportedFile);
- if (await this.isAppHostCsFile(document.uri.fsPath)) {
- vscode.commands.executeCommand('setContext', 'aspire.fileIsAppHostCs', true);
+ if (await this.isAppHostFile(document.uri.fsPath)) {
+ vscode.commands.executeCommand('setContext', 'aspire.fileIsAppHost', true);
}
else {
- vscode.commands.executeCommand('setContext', 'aspire.fileIsAppHostCs', false);
+ vscode.commands.executeCommand('setContext', 'aspire.fileIsAppHost', false);
}
}
- private async isAppHostCsFile(filePath: string): Promise {
+ private async isAppHostFile(filePath: string): Promise {
const fileText = await vscode.workspace.fs.readFile(vscode.Uri.file(filePath)).then(buffer => buffer.toString());
const lines = fileText.split(/\r?\n/);
+ // C# apphost detection
if (lines.some(line => line.startsWith('#:sdk Aspire.AppHost.Sdk'))) {
return true;
}
- return lines.some(line => line === 'var builder = DistributedApplication.CreateBuilder(args);');
+ if (lines.some(line => line === 'var builder = DistributedApplication.CreateBuilder(args);')) {
+ return true;
+ }
+
+ // TypeScript/JavaScript apphost detection
+ const ext = path.extname(filePath).toLowerCase();
+ if (['.ts', '.js', '.mts', '.mjs'].includes(ext)) {
+ if (lines.some(line => /import\s+.*createBuilder.*from\s+['"].*\.modules\/aspire/.test(line))) {
+ return true;
+ }
+
+ if (lines.some(line => /require\s*\(['"].*\.modules\/aspire/.test(line))) {
+ return true;
+ }
+ }
+
+ return false;
}
private onChangeAppHostPath(newPath: string | null) {
@@ -122,7 +139,7 @@ export class AspireEditorCommandProvider implements vscode.Disposable {
* Returns the resolved AppHost path from the active editor or workspace settings, or null if none is available.
*/
public async getAppHostPath(): Promise {
- if (vscode.window.activeTextEditor && await this.isAppHostCsFile(vscode.window.activeTextEditor.document.uri.fsPath)) {
+ if (vscode.window.activeTextEditor && await this.isAppHostFile(vscode.window.activeTextEditor.document.uri.fsPath)) {
return vscode.window.activeTextEditor.document.uri.fsPath;
}
diff --git a/extension/src/loc/strings.ts b/extension/src/loc/strings.ts
index c0e15ca5e23..87783c4d194 100644
--- a/extension/src/loc/strings.ts
+++ b/extension/src/loc/strings.ts
@@ -65,6 +65,8 @@ export const failedToGetConfigInfo = (exitCode: number) => vscode.l10n.t('Failed
export const failedToParseConfigInfo = (error: any) => vscode.l10n.t('Failed to parse Aspire config info: {0}. Try updating the Aspire CLI with: aspire update', error);
export const errorGettingConfigInfo = (error: any) => vscode.l10n.t('Error getting Aspire config info: {0}. Try updating the Aspire CLI with: aspire update', error);
export const invalidLaunchConfiguration = (projectPath: string) => vscode.l10n.t('Invalid launch configuration for {0}.', projectPath);
+export const browserDisplayName = (url: string) => vscode.l10n.t('Browser: {0}', url);
+export const browserLabel = vscode.l10n.t('Browser');
export const dontShowAgainLabel = vscode.l10n.t("Don't Show Again");
export const doYouWantToSetDefaultApphost = (appHost: string) => vscode.l10n.t('Do you want to set {0} as the default apphost for this workspace?', appHost);
export const doYouWantToSelectDefaultApphost = vscode.l10n.t('Do you want to select the default apphost for this workspace?');
diff --git a/extension/src/server/interactionService.ts b/extension/src/server/interactionService.ts
index 66ff29428a6..a546a1401b6 100644
--- a/extension/src/server/interactionService.ts
+++ b/extension/src/server/interactionService.ts
@@ -522,6 +522,7 @@ function tryExecuteEndpoint(interactionService: IInteractionService, withAuthent
const message = (err && (((err as any).message) ?? String(err))) || 'An unknown error occurred';
extensionLogOutputChannel.error(`Interaction service endpoint '${name}' failed: ${message}`);
vscode.window.showErrorMessage(errorMessage(message));
+
interactionService.showStatus(null);
throw err;
}
diff --git a/playground/AspireWithJavaScript/.vscode/settings.json b/playground/AspireWithJavaScript/.vscode/settings.json
new file mode 100644
index 00000000000..d09fe4abc28
--- /dev/null
+++ b/playground/AspireWithJavaScript/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "aspire.dashboardBrowser": "simpleBrowser"
+}
diff --git a/playground/AspireWithJavaScript/AspireJavaScript.AppHost/AppHost.cs b/playground/AspireWithJavaScript/AspireJavaScript.AppHost/AppHost.cs
index 0fe07a74870..5d7212675df 100644
--- a/playground/AspireWithJavaScript/AspireJavaScript.AppHost/AppHost.cs
+++ b/playground/AspireWithJavaScript/AspireJavaScript.AppHost/AppHost.cs
@@ -10,13 +10,16 @@
.WithExternalHttpEndpoints()
.PublishAsDockerFile();
+#pragma warning disable ASPIREEXTENSION001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
builder.AddJavaScriptApp("react", "../AspireJavaScript.React", runScriptName: "start")
.WithReference(weatherApi)
.WaitFor(weatherApi)
.WithEnvironment("BROWSER", "none") // Disable opening browser on npm start
.WithHttpEndpoint(env: "PORT")
.WithExternalHttpEndpoints()
- .PublishAsDockerFile();
+ .PublishAsDockerFile()
+ .WithBrowserDebugger();
+#pragma warning restore ASPIREEXTENSION001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
builder.AddJavaScriptApp("vue", "../AspireJavaScript.Vue")
.WithRunScript("start")
@@ -27,10 +30,12 @@
.WithExternalHttpEndpoints()
.PublishAsDockerFile();
+#pragma warning disable ASPIREEXTENSION001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
var reactvite = builder.AddViteApp("reactvite", "../AspireJavaScript.Vite")
.WithReference(weatherApi)
.WithEnvironment("BROWSER", "none")
.WithExternalHttpEndpoints();
+#pragma warning restore ASPIREEXTENSION001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
builder.AddNodeApp("node", "../AspireJavaScript.NodeApp", "app.js")
.WithRunScript("dev") // Use 'npm run dev' for development
diff --git a/playground/AspireWithJavaScript/AspireJavaScript.MinimalApi/AppHost.cs b/playground/AspireWithJavaScript/AspireJavaScript.MinimalApi/AppHost.cs
index 784b93baeab..a0f75deaad4 100644
--- a/playground/AspireWithJavaScript/AspireJavaScript.MinimalApi/AppHost.cs
+++ b/playground/AspireWithJavaScript/AspireJavaScript.MinimalApi/AppHost.cs
@@ -5,20 +5,12 @@
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
-builder.Services.AddSwaggerGen();
builder.Services.AddCors();
var app = builder.Build();
app.MapDefaultEndpoints();
-// Configure the HTTP request pipeline.
-if (app.Environment.IsDevelopment())
-{
- app.UseSwagger();
- app.UseSwaggerUI();
-}
-
app.UseHttpsRedirection();
app.UseCors(static builder =>
builder.AllowAnyMethod()
@@ -42,8 +34,7 @@
.ToArray();
return forecast;
})
-.WithName("GetWeatherForecast")
-.WithOpenApi();
+.WithName("GetWeatherForecast");
app.UseFileServer();
diff --git a/playground/AspireWithJavaScript/AspireJavaScript.MinimalApi/Properties/launchSettings.json b/playground/AspireWithJavaScript/AspireJavaScript.MinimalApi/Properties/launchSettings.json
index 4c791b4f6cc..ee034e9ee04 100644
--- a/playground/AspireWithJavaScript/AspireJavaScript.MinimalApi/Properties/launchSettings.json
+++ b/playground/AspireWithJavaScript/AspireJavaScript.MinimalApi/Properties/launchSettings.json
@@ -13,7 +13,6 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
- "launchUrl": "swagger",
"applicationUrl": "http://localhost:5084",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
@@ -23,7 +22,6 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
- "launchUrl": "swagger",
"applicationUrl": "https://localhost:7167;http://localhost:5084",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
diff --git a/playground/AspireWithJavaScript/AspireJavaScript.NodeApp/app.js b/playground/AspireWithJavaScript/AspireJavaScript.NodeApp/app.js
index 9c39903c951..7e0e086f97f 100644
--- a/playground/AspireWithJavaScript/AspireJavaScript.NodeApp/app.js
+++ b/playground/AspireWithJavaScript/AspireJavaScript.NodeApp/app.js
@@ -69,7 +69,7 @@ app.use((err, req, res, next) => {
});
// General 404 handler (for non-API routes)
-app.use('*', (req, res) => {
+app.use((req, res) => {
res.status(404).json({
message: 'Route not found',
path: req.originalUrl
diff --git a/playground/AspireWithJavaScript/AspireJavaScript.React/webpack.config.js b/playground/AspireWithJavaScript/AspireJavaScript.React/webpack.config.js
index 016c52e1674..770f78907a3 100644
--- a/playground/AspireWithJavaScript/AspireJavaScript.React/webpack.config.js
+++ b/playground/AspireWithJavaScript/AspireJavaScript.React/webpack.config.js
@@ -3,6 +3,7 @@ const HTMLWebpackPlugin = require("html-webpack-plugin");
module.exports = (env) => {
return {
entry: "./src/index.js",
+ devtool: "source-map",
devServer: {
port: env.PORT || 4001,
allowedHosts: "all",
diff --git a/playground/TypeScriptAppHost/.gitignore b/playground/TypeScriptAppHost/.gitignore
index 867ed95f2f0..56a45c92c4a 100644
--- a/playground/TypeScriptAppHost/.gitignore
+++ b/playground/TypeScriptAppHost/.gitignore
@@ -1 +1,2 @@
!.aspire/
+.aspire/dcp/
diff --git a/playground/TypeScriptAppHost/.modules/.codegen-hash b/playground/TypeScriptAppHost/.modules/.codegen-hash
index 684c5ac1140..e02d1446575 100644
--- a/playground/TypeScriptAppHost/.modules/.codegen-hash
+++ b/playground/TypeScriptAppHost/.modules/.codegen-hash
@@ -1 +1 @@
-B1EE4C88283B2949DA165E54F052FB8213C98527E5BDA53C3EBB44D5FC8C876B
\ No newline at end of file
+01B89896FB4482B7BC294CB5C1CE4D8763C7096CA487FB9A6430DAA7217C0312
\ No newline at end of file
diff --git a/playground/TypeScriptAppHost/.modules/aspire.ts b/playground/TypeScriptAppHost/.modules/aspire.ts
index 9fb119d55da..8ade3448ce5 100644
--- a/playground/TypeScriptAppHost/.modules/aspire.ts
+++ b/playground/TypeScriptAppHost/.modules/aspire.ts
@@ -26,9 +26,18 @@ import {
// Handle Type Aliases (Internal - not exported to users)
// ============================================================================
+/** Handle to DockerComposeAspireDashboardResource */
+type DockerComposeAspireDashboardResourceHandle = Handle<'Aspire.Hosting.Docker/Aspire.Hosting.Docker.DockerComposeAspireDashboardResource'>;
+
/** Handle to DockerComposeEnvironmentResource */
type DockerComposeEnvironmentResourceHandle = Handle<'Aspire.Hosting.Docker/Aspire.Hosting.Docker.DockerComposeEnvironmentResource'>;
+/** Handle to DockerComposeServiceResource */
+type DockerComposeServiceResourceHandle = Handle<'Aspire.Hosting.Docker/Aspire.Hosting.Docker.DockerComposeServiceResource'>;
+
+/** Handle to Service */
+type ServiceHandle = Handle<'Aspire.Hosting.Docker/Aspire.Hosting.Docker.Resources.ComposeNodes.Service'>;
+
/** Handle to JavaScriptAppResource */
type JavaScriptAppResourceHandle = Handle<'Aspire.Hosting.JavaScript/Aspire.Hosting.JavaScript.JavaScriptAppResource'>;
@@ -65,9 +74,18 @@ type RedisInsightResourceHandle = Handle<'Aspire.Hosting.Redis/Aspire.Hosting.Re
/** Handle to CommandLineArgsCallbackContext */
type CommandLineArgsCallbackContextHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.CommandLineArgsCallbackContext'>;
+/** Handle to ContainerRegistryResource */
+type ContainerRegistryResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ContainerRegistryResource'>;
+
/** Handle to ContainerResource */
type ContainerResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ContainerResource'>;
+/** Handle to CSharpAppResource */
+type CSharpAppResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.CSharpAppResource'>;
+
+/** Handle to DotnetToolResource */
+type DotnetToolResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.DotnetToolResource'>;
+
/** Handle to EndpointReference */
type EndpointReferenceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.EndpointReference'>;
@@ -83,6 +101,12 @@ type ExecutableResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Applicatio
/** Handle to ExecuteCommandContext */
type ExecuteCommandContextHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ExecuteCommandContext'>;
+/** Handle to IComputeResource */
+type IComputeResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.IComputeResource'>;
+
+/** Handle to IContainerFilesDestinationResource */
+type IContainerFilesDestinationResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.IContainerFilesDestinationResource'>;
+
/** Handle to IResource */
type IResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.IResource'>;
@@ -110,6 +134,9 @@ type ProjectResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationMo
/** Handle to ReferenceExpression */
type ReferenceExpressionHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ReferenceExpression'>;
+/** Handle to ReferenceExpressionBuilder */
+type ReferenceExpressionBuilderHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ReferenceExpressionBuilder'>;
+
/** Handle to ResourceLoggerService */
type ResourceLoggerServiceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ResourceLoggerService'>;
@@ -119,6 +146,9 @@ type ResourceNotificationServiceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.A
/** Handle to ResourceUrlsCallbackContext */
type ResourceUrlsCallbackContextHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ApplicationModel.ResourceUrlsCallbackContext'>;
+/** Handle to ConnectionStringResource */
+type ConnectionStringResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ConnectionStringResource'>;
+
/** Handle to DistributedApplication */
type DistributedApplicationHandle = Handle<'Aspire.Hosting/Aspire.Hosting.DistributedApplication'>;
@@ -131,12 +161,30 @@ type DistributedApplicationEventSubscriptionHandle = Handle<'Aspire.Hosting/Aspi
/** Handle to IDistributedApplicationEventing */
type IDistributedApplicationEventingHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Eventing.IDistributedApplicationEventing'>;
+/** Handle to ExternalServiceResource */
+type ExternalServiceResourceHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ExternalServiceResource'>;
+
/** Handle to IDistributedApplicationBuilder */
type IDistributedApplicationBuilderHandle = Handle<'Aspire.Hosting/Aspire.Hosting.IDistributedApplicationBuilder'>;
+/** Handle to IResourceWithContainerFiles */
+type IResourceWithContainerFilesHandle = Handle<'Aspire.Hosting/Aspire.Hosting.IResourceWithContainerFiles'>;
+
/** Handle to IResourceWithServiceDiscovery */
type IResourceWithServiceDiscoveryHandle = Handle<'Aspire.Hosting/Aspire.Hosting.IResourceWithServiceDiscovery'>;
+/** Handle to PipelineConfigurationContext */
+type PipelineConfigurationContextHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineConfigurationContext'>;
+
+/** Handle to PipelineStep */
+type PipelineStepHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStep'>;
+
+/** Handle to PipelineStepContext */
+type PipelineStepContextHandle = Handle<'Aspire.Hosting/Aspire.Hosting.Pipelines.PipelineStepContext'>;
+
+/** Handle to ProjectResourceOptions */
+type ProjectResourceOptionsHandle = Handle<'Aspire.Hosting/Aspire.Hosting.ProjectResourceOptions'>;
+
/** Handle to Dict */
type DictstringanyHandle = Handle<'Aspire.Hosting/Dict'>;
@@ -162,6 +210,14 @@ type IServiceProviderHandle = Handle<'System.ComponentModel/System.IServiceProvi
// Enum Types
// ============================================================================
+/** Enum type for CertificateTrustScope */
+export enum CertificateTrustScope {
+ None = "None",
+ Append = "Append",
+ Override = "Override",
+ System = "System",
+}
+
/** Enum type for ContainerLifetime */
export enum ContainerLifetime {
Session = "Session",
@@ -199,6 +255,20 @@ export enum ImagePullPolicy {
Never = "Never",
}
+/** Enum type for OtlpProtocol */
+export enum OtlpProtocol {
+ Grpc = "Grpc",
+ HttpProtobuf = "HttpProtobuf",
+ HttpJson = "HttpJson",
+}
+
+/** Enum type for ProbeType */
+export enum ProbeType {
+ Startup = "Startup",
+ Readiness = "Readiness",
+ Liveness = "Liveness",
+}
+
/** Enum type for ProtocolType */
export enum ProtocolType {
IP = "IP",
@@ -234,6 +304,12 @@ export enum UrlDisplayLocation {
DetailsOnly = "DetailsOnly",
}
+/** Enum type for WaitBehavior */
+export enum WaitBehavior {
+ WaitOnResourceUnavailable = "WaitOnResourceUnavailable",
+ StopOnResourceUnavailable = "StopOnResourceUnavailable",
+}
+
// ============================================================================
// DTO Interfaces
// ============================================================================
@@ -294,14 +370,27 @@ export interface AddConnectionStringOptions {
environmentVariableName?: string;
}
+export interface AddContainerRegistryOptions {
+ repository?: ParameterResource;
+}
+
export interface AddDatabaseOptions {
databaseName?: string;
}
+export interface AddDockerfileOptions {
+ dockerfilePath?: string;
+ stage?: string;
+}
+
export interface AddJavaScriptAppOptions {
runScriptName?: string;
}
+export interface AddParameterFromConfigurationOptions {
+ secret?: boolean;
+}
+
export interface AddParameterOptions {
secret?: boolean;
}
@@ -325,6 +414,14 @@ export interface AddViteAppOptions {
runScriptName?: string;
}
+export interface AppendFormattedOptions {
+ format?: string;
+}
+
+export interface AppendValueProviderOptions {
+ format?: string;
+}
+
export interface GetValueAsyncOptions {
cancellationToken?: AbortSignal;
}
@@ -341,14 +438,27 @@ export interface WithBindMountOptions {
isReadOnly?: boolean;
}
+export interface WithBrowserDebuggerOptions {
+ browser?: string;
+}
+
export interface WithBuildScriptOptions {
args?: string[];
}
+export interface WithBunOptions {
+ install?: boolean;
+ installArgs?: string[];
+}
+
export interface WithCommandOptions {
commandOptions?: CommandOptions;
}
+export interface WithDashboardOptions {
+ enabled?: boolean;
+}
+
export interface WithDataBindMountOptions {
isReadOnly?: boolean;
}
@@ -362,6 +472,16 @@ export interface WithDescriptionOptions {
enableMarkdown?: boolean;
}
+export interface WithDockerfileBaseImageOptions {
+ buildImage?: string;
+ runtimeImage?: string;
+}
+
+export interface WithDockerfileOptions {
+ dockerfilePath?: string;
+ stage?: string;
+}
+
export interface WithEndpointOptions {
port?: number;
targetPort?: number;
@@ -373,6 +493,15 @@ export interface WithEndpointOptions {
protocol?: ProtocolType;
}
+export interface WithExternalServiceHttpHealthCheckOptions {
+ path?: string;
+ statusCode?: number;
+}
+
+export interface WithForwardedHeadersOptions {
+ enabled?: boolean;
+}
+
export interface WithHostPortOptions {
port?: number;
}
@@ -391,6 +520,20 @@ export interface WithHttpHealthCheckOptions {
endpointName?: string;
}
+export interface WithHttpProbeOptions {
+ path?: string;
+ initialDelaySeconds?: number;
+ periodSeconds?: number;
+ timeoutSeconds?: number;
+ failureThreshold?: number;
+ successThreshold?: number;
+ endpointName?: string;
+}
+
+export interface WithHttpsDeveloperCertificateOptions {
+ password?: ParameterResource;
+}
+
export interface WithHttpsEndpointOptions {
port?: number;
targetPort?: number;
@@ -399,10 +542,19 @@ export interface WithHttpsEndpointOptions {
isProxied?: boolean;
}
+export interface WithIconNameOptions {
+ iconVariant?: IconVariant;
+}
+
export interface WithImageOptions {
tag?: string;
}
+export interface WithMcpServerOptions {
+ path?: string;
+ endpointName?: string;
+}
+
export interface WithNpmOptions {
install?: boolean;
installCommand?: string;
@@ -424,6 +576,18 @@ export interface WithPgWebOptions {
containerName?: string;
}
+export interface WithPipelineStepFactoryOptions {
+ dependsOn?: string[];
+ requiredBy?: string[];
+ tags?: string[];
+ description?: string;
+}
+
+export interface WithPnpmOptions {
+ install?: boolean;
+ installArgs?: string[];
+}
+
export interface WithPostgresMcpOptions {
configureContainer?: (obj: PostgresMcpContainerResource) => Promise;
containerName?: string;
@@ -444,6 +608,10 @@ export interface WithReferenceOptions {
optional?: boolean;
}
+export interface WithRequiredCommandOptions {
+ helpLink?: string;
+}
+
export interface WithRunScriptOptions {
args?: string[];
}
@@ -461,6 +629,11 @@ export interface WithVolumeOptions {
isReadOnly?: boolean;
}
+export interface WithYarnOptions {
+ install?: boolean;
+ installArgs?: string[];
+}
+
// ============================================================================
// CommandLineArgsCallbackContext
// ============================================================================
@@ -930,1057 +1103,15203 @@ export class ExecuteCommandContext {
}
// ============================================================================
-// ResourceUrlsCallbackContext
+// PipelineConfigurationContext
// ============================================================================
/**
- * Type class for ResourceUrlsCallbackContext.
+ * Type class for PipelineConfigurationContext.
*/
-export class ResourceUrlsCallbackContext {
- constructor(private _handle: ResourceUrlsCallbackContextHandle, private _client: AspireClientRpc) {}
+export class PipelineConfigurationContext {
+ constructor(private _handle: PipelineConfigurationContextHandle, private _client: AspireClientRpc) {}
/** Serialize for JSON-RPC transport */
toJSON(): MarshalledHandle { return this._handle.toJSON(); }
- /** Gets the Urls property */
- private _urls?: AspireList;
- get urls(): AspireList {
- if (!this._urls) {
- this._urls = new AspireList(
- this._handle,
- this._client,
- 'Aspire.Hosting.ApplicationModel/ResourceUrlsCallbackContext.urls',
- 'Aspire.Hosting.ApplicationModel/ResourceUrlsCallbackContext.urls'
- );
- }
- return this._urls;
- }
-
- /** Gets the CancellationToken property */
- cancellationToken = {
- get: async (): Promise => {
- return await this._client.invokeCapability(
- 'Aspire.Hosting.ApplicationModel/ResourceUrlsCallbackContext.cancellationToken',
+ /** Gets the Steps property */
+ steps = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Pipelines/PipelineConfigurationContext.steps',
{ context: this._handle }
);
},
- };
-
- /** Gets the ExecutionContext property */
- executionContext = {
- get: async (): Promise => {
- const handle = await this._client.invokeCapability(
- 'Aspire.Hosting.ApplicationModel/ResourceUrlsCallbackContext.executionContext',
- { context: this._handle }
+ set: async (value: PipelineStep[]): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Pipelines/PipelineConfigurationContext.setSteps',
+ { context: this._handle, value }
);
- return new DistributedApplicationExecutionContext(handle, this._client);
- },
+ }
};
+ /** Gets pipeline steps with the specified tag */
+ async getStepsByTag(tag: string): Promise {
+ const rpcArgs: Record = { context: this._handle, tag };
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Pipelines/getStepsByTag',
+ rpcArgs
+ );
+ }
+
+}
+
+/**
+ * Thenable wrapper for PipelineConfigurationContext that enables fluent chaining.
+ */
+export class PipelineConfigurationContextPromise implements PromiseLike {
+ constructor(private _promise: Promise) {}
+
+ then(
+ onfulfilled?: ((value: PipelineConfigurationContext) => TResult1 | PromiseLike) | null,
+ onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null
+ ): PromiseLike {
+ return this._promise.then(onfulfilled, onrejected);
+ }
+
+ /** Gets pipeline steps with the specified tag */
+ getStepsByTag(tag: string): Promise {
+ return this._promise.then(obj => obj.getStepsByTag(tag));
+ }
+
}
// ============================================================================
-// DistributedApplicationBuilder
+// PipelineStep
// ============================================================================
/**
- * Type class for DistributedApplicationBuilder.
+ * Type class for PipelineStep.
*/
-export class DistributedApplicationBuilder {
- constructor(private _handle: IDistributedApplicationBuilderHandle, private _client: AspireClientRpc) {}
+export class PipelineStep {
+ constructor(private _handle: PipelineStepHandle, private _client: AspireClientRpc) {}
/** Serialize for JSON-RPC transport */
toJSON(): MarshalledHandle { return this._handle.toJSON(); }
- /** Gets the AppHostDirectory property */
- appHostDirectory = {
+ /** Gets the Name property */
+ name = {
get: async (): Promise => {
return await this._client.invokeCapability(
- 'Aspire.Hosting/IDistributedApplicationBuilder.appHostDirectory',
+ 'Aspire.Hosting.Pipelines/PipelineStep.name',
{ context: this._handle }
);
},
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Pipelines/PipelineStep.setName',
+ { context: this._handle, value }
+ );
+ }
};
- /** Gets the Eventing property */
- eventing = {
- get: async (): Promise => {
- const handle = await this._client.invokeCapability(
- 'Aspire.Hosting/IDistributedApplicationBuilder.eventing',
+ /** Gets the Description property */
+ description = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Pipelines/PipelineStep.description',
{ context: this._handle }
);
- return new DistributedApplicationEventing(handle, this._client);
},
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Pipelines/PipelineStep.setDescription',
+ { context: this._handle, value }
+ );
+ }
};
- /** Gets the ExecutionContext property */
- executionContext = {
- get: async (): Promise => {
- const handle = await this._client.invokeCapability(
- 'Aspire.Hosting/IDistributedApplicationBuilder.executionContext',
- { context: this._handle }
+ /** Gets the DependsOnSteps property */
+ private _dependsOnSteps?: AspireList;
+ get dependsOnSteps(): AspireList {
+ if (!this._dependsOnSteps) {
+ this._dependsOnSteps = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Pipelines/PipelineStep.dependsOnSteps',
+ 'Aspire.Hosting.Pipelines/PipelineStep.dependsOnSteps'
);
- return new DistributedApplicationExecutionContext(handle, this._client);
- },
- };
+ }
+ return this._dependsOnSteps;
+ }
- /** Builds the distributed application */
- /** @internal */
- async _buildInternal(): Promise {
- const rpcArgs: Record = { context: this._handle };
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting/build',
- rpcArgs
- );
- return new DistributedApplication(result, this._client);
+ /** Gets the RequiredBySteps property */
+ private _requiredBySteps?: AspireList;
+ get requiredBySteps(): AspireList {
+ if (!this._requiredBySteps) {
+ this._requiredBySteps = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Pipelines/PipelineStep.requiredBySteps',
+ 'Aspire.Hosting.Pipelines/PipelineStep.requiredBySteps'
+ );
+ }
+ return this._requiredBySteps;
}
- build(): DistributedApplicationPromise {
- return new DistributedApplicationPromise(this._buildInternal());
+ /** Gets the Tags property */
+ private _tags?: AspireList;
+ get tags(): AspireList {
+ if (!this._tags) {
+ this._tags = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Pipelines/PipelineStep.tags',
+ 'Aspire.Hosting.Pipelines/PipelineStep.tags'
+ );
+ }
+ return this._tags;
}
- /** Adds a container resource */
+ /** Adds a dependency on another step by name */
/** @internal */
- async _addContainerInternal(name: string, image: string): Promise {
- const rpcArgs: Record = { builder: this._handle, name, image };
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting/addContainer',
+ async _dependsOnInternal(stepName: string): Promise {
+ const rpcArgs: Record = { context: this._handle, stepName };
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Pipelines/dependsOn',
rpcArgs
);
- return new ContainerResource(result, this._client);
+ return this;
}
- addContainer(name: string, image: string): ContainerResourcePromise {
- return new ContainerResourcePromise(this._addContainerInternal(name, image));
+ dependsOn(stepName: string): PipelineStepPromise {
+ return new PipelineStepPromise(this._dependsOnInternal(stepName));
}
- /** Adds an executable resource */
+ /** Specifies that another step requires this step by name */
/** @internal */
- async _addExecutableInternal(name: string, command: string, workingDirectory: string, args: string[]): Promise {
- const rpcArgs: Record = { builder: this._handle, name, command, workingDirectory, args };
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting/addExecutable',
+ async _requiredByInternal(stepName: string): Promise {
+ const rpcArgs: Record = { context: this._handle, stepName };
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Pipelines/requiredBy',
rpcArgs
);
- return new ExecutableResource(result, this._client);
+ return this;
}
- addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResourcePromise {
- return new ExecutableResourcePromise(this._addExecutableInternal(name, command, workingDirectory, args));
+ requiredBy(stepName: string): PipelineStepPromise {
+ return new PipelineStepPromise(this._requiredByInternal(stepName));
}
- /** Adds a parameter resource */
- /** @internal */
- async _addParameterInternal(name: string, secret?: boolean): Promise {
- const rpcArgs: Record = { builder: this._handle, name };
- if (secret !== undefined) rpcArgs.secret = secret;
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting/addParameter',
- rpcArgs
- );
- return new ParameterResource(result, this._client);
- }
+}
- addParameter(name: string, options?: AddParameterOptions): ParameterResourcePromise {
- const secret = options?.secret;
- return new ParameterResourcePromise(this._addParameterInternal(name, secret));
- }
+/**
+ * Thenable wrapper for PipelineStep that enables fluent chaining.
+ */
+export class PipelineStepPromise implements PromiseLike {
+ constructor(private _promise: Promise) {}
- /** Adds a connection string resource */
- /** @internal */
- async _addConnectionStringInternal(name: string, environmentVariableName?: string): Promise {
- const rpcArgs: Record = { builder: this._handle, name };
- if (environmentVariableName !== undefined) rpcArgs.environmentVariableName = environmentVariableName;
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting/addConnectionString',
- rpcArgs
- );
- return new ResourceWithConnectionString(result, this._client);
+ then(
+ onfulfilled?: ((value: PipelineStep) => TResult1 | PromiseLike) | null,
+ onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null
+ ): PromiseLike {
+ return this._promise.then(onfulfilled, onrejected);
}
- addConnectionString(name: string, options?: AddConnectionStringOptions): ResourceWithConnectionStringPromise {
- const environmentVariableName = options?.environmentVariableName;
- return new ResourceWithConnectionStringPromise(this._addConnectionStringInternal(name, environmentVariableName));
+ /** Adds a dependency on another step by name */
+ dependsOn(stepName: string): PipelineStepPromise {
+ return new PipelineStepPromise(this._promise.then(obj => obj.dependsOn(stepName)));
}
- /** Adds a .NET project resource */
- /** @internal */
- async _addProjectInternal(name: string, projectPath: string, launchProfileName: string): Promise {
- const rpcArgs: Record = { builder: this._handle, name, projectPath, launchProfileName };
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting/addProject',
- rpcArgs
- );
- return new ProjectResource(result, this._client);
+ /** Specifies that another step requires this step by name */
+ requiredBy(stepName: string): PipelineStepPromise {
+ return new PipelineStepPromise(this._promise.then(obj => obj.requiredBy(stepName)));
}
- addProject(name: string, projectPath: string, launchProfileName: string): ProjectResourcePromise {
- return new ProjectResourcePromise(this._addProjectInternal(name, projectPath, launchProfileName));
- }
+}
- /** Adds a PostgreSQL server resource */
- /** @internal */
- async _addPostgresInternal(name: string, userName?: ParameterResource, password?: ParameterResource, port?: number): Promise {
- const rpcArgs: Record = { builder: this._handle, name };
- if (userName !== undefined) rpcArgs.userName = userName;
- if (password !== undefined) rpcArgs.password = password;
- if (port !== undefined) rpcArgs.port = port;
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting.PostgreSQL/addPostgres',
- rpcArgs
- );
- return new PostgresServerResource(result, this._client);
- }
+// ============================================================================
+// PipelineStepContext
+// ============================================================================
- addPostgres(name: string, options?: AddPostgresOptions): PostgresServerResourcePromise {
- const userName = options?.userName;
- const password = options?.password;
- const port = options?.port;
- return new PostgresServerResourcePromise(this._addPostgresInternal(name, userName, password, port));
- }
+/**
+ * Type class for PipelineStepContext.
+ */
+export class PipelineStepContext {
+ constructor(private _handle: PipelineStepContextHandle, private _client: AspireClientRpc) {}
- /** Adds a Redis container resource with specific port */
- /** @internal */
- async _addRedisWithPortInternal(name: string, port?: number): Promise {
- const rpcArgs: Record = { builder: this._handle, name };
- if (port !== undefined) rpcArgs.port = port;
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting.Redis/addRedisWithPort',
- rpcArgs
- );
- return new RedisResource(result, this._client);
- }
+ /** Serialize for JSON-RPC transport */
+ toJSON(): MarshalledHandle { return this._handle.toJSON(); }
- addRedisWithPort(name: string, options?: AddRedisWithPortOptions): RedisResourcePromise {
- const port = options?.port;
- return new RedisResourcePromise(this._addRedisWithPortInternal(name, port));
- }
+ /** Gets the ExecutionContext property */
+ executionContext = {
+ get: async (): Promise => {
+ const handle = await this._client.invokeCapability(
+ 'Aspire.Hosting.Pipelines/PipelineStepContext.executionContext',
+ { context: this._handle }
+ );
+ return new DistributedApplicationExecutionContext(handle, this._client);
+ },
+ };
- /** Adds a Redis container resource */
- /** @internal */
- async _addRedisInternal(name: string, port?: number, password?: ParameterResource): Promise {
- const rpcArgs: Record = { builder: this._handle, name };
- if (port !== undefined) rpcArgs.port = port;
- if (password !== undefined) rpcArgs.password = password;
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting.Redis/addRedis',
- rpcArgs
- );
- return new RedisResource(result, this._client);
- }
+ /** Gets the CancellationToken property */
+ cancellationToken = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Pipelines/PipelineStepContext.cancellationToken',
+ { context: this._handle }
+ );
+ },
+ };
- addRedis(name: string, options?: AddRedisOptions): RedisResourcePromise {
- const port = options?.port;
- const password = options?.password;
- return new RedisResourcePromise(this._addRedisInternal(name, port, password));
- }
+}
- /** Adds a Node.js application resource */
+// ============================================================================
+// ProjectResourceOptions
+// ============================================================================
+
+/**
+ * Type class for ProjectResourceOptions.
+ */
+export class ProjectResourceOptions {
+ constructor(private _handle: ProjectResourceOptionsHandle, private _client: AspireClientRpc) {}
+
+ /** Serialize for JSON-RPC transport */
+ toJSON(): MarshalledHandle { return this._handle.toJSON(); }
+
+ /** Gets the LaunchProfileName property */
+ launchProfileName = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting/ProjectResourceOptions.launchProfileName',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting/ProjectResourceOptions.setLaunchProfileName',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the ExcludeLaunchProfile property */
+ excludeLaunchProfile = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting/ProjectResourceOptions.excludeLaunchProfile',
+ { context: this._handle }
+ );
+ },
+ set: async (value: boolean): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting/ProjectResourceOptions.setExcludeLaunchProfile',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the ExcludeKestrelEndpoints property */
+ excludeKestrelEndpoints = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting/ProjectResourceOptions.excludeKestrelEndpoints',
+ { context: this._handle }
+ );
+ },
+ set: async (value: boolean): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting/ProjectResourceOptions.setExcludeKestrelEndpoints',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+}
+
+// ============================================================================
+// ReferenceExpressionBuilder
+// ============================================================================
+
+/**
+ * Type class for ReferenceExpressionBuilder.
+ */
+export class ReferenceExpressionBuilder {
+ constructor(private _handle: ReferenceExpressionBuilderHandle, private _client: AspireClientRpc) {}
+
+ /** Serialize for JSON-RPC transport */
+ toJSON(): MarshalledHandle { return this._handle.toJSON(); }
+
+ /** Gets the IsEmpty property */
+ isEmpty = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.ApplicationModel/ReferenceExpressionBuilder.isEmpty',
+ { context: this._handle }
+ );
+ },
+ };
+
+ /** Appends a literal string to the reference expression */
/** @internal */
- async _addNodeAppInternal(name: string, appDirectory: string, scriptPath: string): Promise {
- const rpcArgs: Record = { builder: this._handle, name, appDirectory, scriptPath };
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting.JavaScript/addNodeApp',
+ async _appendLiteralInternal(value: string): Promise {
+ const rpcArgs: Record = { context: this._handle, value };
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.ApplicationModel/appendLiteral',
rpcArgs
);
- return new NodeAppResource(result, this._client);
+ return this;
}
- addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResourcePromise {
- return new NodeAppResourcePromise(this._addNodeAppInternal(name, appDirectory, scriptPath));
+ appendLiteral(value: string): ReferenceExpressionBuilderPromise {
+ return new ReferenceExpressionBuilderPromise(this._appendLiteralInternal(value));
}
- /** Adds a JavaScript application resource */
+ /** Appends a formatted string value to the reference expression */
/** @internal */
- async _addJavaScriptAppInternal(name: string, appDirectory: string, runScriptName?: string): Promise {
- const rpcArgs: Record = { builder: this._handle, name, appDirectory };
- if (runScriptName !== undefined) rpcArgs.runScriptName = runScriptName;
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting.JavaScript/addJavaScriptApp',
+ async _appendFormattedInternal(value: string, format?: string): Promise {
+ const rpcArgs: Record = { context: this._handle, value };
+ if (format !== undefined) rpcArgs.format = format;
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.ApplicationModel/appendFormatted',
rpcArgs
);
- return new JavaScriptAppResource(result, this._client);
+ return this;
}
- addJavaScriptApp(name: string, appDirectory: string, options?: AddJavaScriptAppOptions): JavaScriptAppResourcePromise {
- const runScriptName = options?.runScriptName;
- return new JavaScriptAppResourcePromise(this._addJavaScriptAppInternal(name, appDirectory, runScriptName));
+ appendFormatted(value: string, options?: AppendFormattedOptions): ReferenceExpressionBuilderPromise {
+ const format = options?.format;
+ return new ReferenceExpressionBuilderPromise(this._appendFormattedInternal(value, format));
}
- /** Adds a Vite application resource */
+ /** Appends a value provider to the reference expression */
/** @internal */
- async _addViteAppInternal(name: string, appDirectory: string, runScriptName?: string): Promise {
- const rpcArgs: Record = { builder: this._handle, name, appDirectory };
- if (runScriptName !== undefined) rpcArgs.runScriptName = runScriptName;
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting.JavaScript/addViteApp',
+ async _appendValueProviderInternal(valueProvider: any, format?: string): Promise {
+ const rpcArgs: Record = { context: this._handle, valueProvider };
+ if (format !== undefined) rpcArgs.format = format;
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.ApplicationModel/appendValueProvider',
rpcArgs
);
- return new ViteAppResource(result, this._client);
+ return this;
}
- addViteApp(name: string, appDirectory: string, options?: AddViteAppOptions): ViteAppResourcePromise {
- const runScriptName = options?.runScriptName;
- return new ViteAppResourcePromise(this._addViteAppInternal(name, appDirectory, runScriptName));
+ appendValueProvider(valueProvider: any, options?: AppendValueProviderOptions): ReferenceExpressionBuilderPromise {
+ const format = options?.format;
+ return new ReferenceExpressionBuilderPromise(this._appendValueProviderInternal(valueProvider, format));
}
- /** Adds a Docker Compose publishing environment */
- /** @internal */
- async _addDockerComposeEnvironmentInternal(name: string): Promise {
- const rpcArgs: Record = { builder: this._handle, name };
- const result = await this._client.invokeCapability(
- 'Aspire.Hosting.Docker/addDockerComposeEnvironment',
+ /** Builds the reference expression */
+ async build(): Promise {
+ const rpcArgs: Record = { context: this._handle };
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.ApplicationModel/build',
rpcArgs
);
- return new DockerComposeEnvironmentResource(result, this._client);
- }
-
- addDockerComposeEnvironment(name: string): DockerComposeEnvironmentResourcePromise {
- return new DockerComposeEnvironmentResourcePromise(this._addDockerComposeEnvironmentInternal(name));
}
}
/**
- * Thenable wrapper for DistributedApplicationBuilder that enables fluent chaining.
+ * Thenable wrapper for ReferenceExpressionBuilder that enables fluent chaining.
*/
-export class DistributedApplicationBuilderPromise implements PromiseLike {
- constructor(private _promise: Promise) {}
+export class ReferenceExpressionBuilderPromise implements PromiseLike {
+ constructor(private _promise: Promise) {}
- then(
- onfulfilled?: ((value: DistributedApplicationBuilder) => TResult1 | PromiseLike) | null,
+ then(
+ onfulfilled?: ((value: ReferenceExpressionBuilder) => TResult1 | PromiseLike) | null,
onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null
): PromiseLike {
return this._promise.then(onfulfilled, onrejected);
}
- /** Builds the distributed application */
- build(): DistributedApplicationPromise {
- return new DistributedApplicationPromise(this._promise.then(obj => obj.build()));
- }
-
- /** Adds a container resource */
- addContainer(name: string, image: string): ContainerResourcePromise {
- return new ContainerResourcePromise(this._promise.then(obj => obj.addContainer(name, image)));
- }
-
- /** Adds an executable resource */
- addExecutable(name: string, command: string, workingDirectory: string, args: string[]): ExecutableResourcePromise {
- return new ExecutableResourcePromise(this._promise.then(obj => obj.addExecutable(name, command, workingDirectory, args)));
- }
-
- /** Adds a parameter resource */
- addParameter(name: string, options?: AddParameterOptions): ParameterResourcePromise {
- return new ParameterResourcePromise(this._promise.then(obj => obj.addParameter(name, options)));
- }
-
- /** Adds a connection string resource */
- addConnectionString(name: string, options?: AddConnectionStringOptions): ResourceWithConnectionStringPromise {
- return new ResourceWithConnectionStringPromise(this._promise.then(obj => obj.addConnectionString(name, options)));
- }
-
- /** Adds a .NET project resource */
- addProject(name: string, projectPath: string, launchProfileName: string): ProjectResourcePromise {
- return new ProjectResourcePromise(this._promise.then(obj => obj.addProject(name, projectPath, launchProfileName)));
- }
-
- /** Adds a PostgreSQL server resource */
- addPostgres(name: string, options?: AddPostgresOptions): PostgresServerResourcePromise {
- return new PostgresServerResourcePromise(this._promise.then(obj => obj.addPostgres(name, options)));
- }
-
- /** Adds a Redis container resource with specific port */
- addRedisWithPort(name: string, options?: AddRedisWithPortOptions): RedisResourcePromise {
- return new RedisResourcePromise(this._promise.then(obj => obj.addRedisWithPort(name, options)));
- }
-
- /** Adds a Redis container resource */
- addRedis(name: string, options?: AddRedisOptions): RedisResourcePromise {
- return new RedisResourcePromise(this._promise.then(obj => obj.addRedis(name, options)));
- }
-
- /** Adds a Node.js application resource */
- addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResourcePromise {
- return new NodeAppResourcePromise(this._promise.then(obj => obj.addNodeApp(name, appDirectory, scriptPath)));
+ /** Appends a literal string to the reference expression */
+ appendLiteral(value: string): ReferenceExpressionBuilderPromise {
+ return new ReferenceExpressionBuilderPromise(this._promise.then(obj => obj.appendLiteral(value)));
}
- /** Adds a JavaScript application resource */
- addJavaScriptApp(name: string, appDirectory: string, options?: AddJavaScriptAppOptions): JavaScriptAppResourcePromise {
- return new JavaScriptAppResourcePromise(this._promise.then(obj => obj.addJavaScriptApp(name, appDirectory, options)));
+ /** Appends a formatted string value to the reference expression */
+ appendFormatted(value: string, options?: AppendFormattedOptions): ReferenceExpressionBuilderPromise {
+ return new ReferenceExpressionBuilderPromise(this._promise.then(obj => obj.appendFormatted(value, options)));
}
- /** Adds a Vite application resource */
- addViteApp(name: string, appDirectory: string, options?: AddViteAppOptions): ViteAppResourcePromise {
- return new ViteAppResourcePromise(this._promise.then(obj => obj.addViteApp(name, appDirectory, options)));
+ /** Appends a value provider to the reference expression */
+ appendValueProvider(valueProvider: any, options?: AppendValueProviderOptions): ReferenceExpressionBuilderPromise {
+ return new ReferenceExpressionBuilderPromise(this._promise.then(obj => obj.appendValueProvider(valueProvider, options)));
}
- /** Adds a Docker Compose publishing environment */
- addDockerComposeEnvironment(name: string): DockerComposeEnvironmentResourcePromise {
- return new DockerComposeEnvironmentResourcePromise(this._promise.then(obj => obj.addDockerComposeEnvironment(name)));
+ /** Builds the reference expression */
+ build(): Promise {
+ return this._promise.then(obj => obj.build());
}
}
// ============================================================================
-// DistributedApplicationEventing
+// ResourceUrlsCallbackContext
// ============================================================================
/**
- * Type class for DistributedApplicationEventing.
+ * Type class for ResourceUrlsCallbackContext.
*/
-export class DistributedApplicationEventing {
- constructor(private _handle: IDistributedApplicationEventingHandle, private _client: AspireClientRpc) {}
+export class ResourceUrlsCallbackContext {
+ constructor(private _handle: ResourceUrlsCallbackContextHandle, private _client: AspireClientRpc) {}
/** Serialize for JSON-RPC transport */
toJSON(): MarshalledHandle { return this._handle.toJSON(); }
+ /** Gets the Urls property */
+ private _urls?: AspireList;
+ get urls(): AspireList {
+ if (!this._urls) {
+ this._urls = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.ApplicationModel/ResourceUrlsCallbackContext.urls',
+ 'Aspire.Hosting.ApplicationModel/ResourceUrlsCallbackContext.urls'
+ );
+ }
+ return this._urls;
+ }
+
+ /** Gets the CancellationToken property */
+ cancellationToken = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.ApplicationModel/ResourceUrlsCallbackContext.cancellationToken',
+ { context: this._handle }
+ );
+ },
+ };
+
+ /** Gets the ExecutionContext property */
+ executionContext = {
+ get: async (): Promise => {
+ const handle = await this._client.invokeCapability(
+ 'Aspire.Hosting.ApplicationModel/ResourceUrlsCallbackContext.executionContext',
+ { context: this._handle }
+ );
+ return new DistributedApplicationExecutionContext(handle, this._client);
+ },
+ };
+
+}
+
+// ============================================================================
+// Service
+// ============================================================================
+
+/**
+ * Type class for Service.
+ */
+export class Service {
+ constructor(private _handle: ServiceHandle, private _client: AspireClientRpc) {}
+
+ /** Serialize for JSON-RPC transport */
+ toJSON(): MarshalledHandle { return this._handle.toJSON(); }
+
+ /** Gets the Image property */
+ image = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.image',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setImage',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the PullPolicy property */
+ pullPolicy = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.pullPolicy',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setPullPolicy',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the ContainerName property */
+ containerName = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.containerName',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setContainerName',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the Command property */
+ private _command?: AspireList;
+ get command(): AspireList {
+ if (!this._command) {
+ this._command = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.command',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.command'
+ );
+ }
+ return this._command;
+ }
+
+ /** Gets the Entrypoint property */
+ private _entrypoint?: AspireList;
+ get entrypoint(): AspireList {
+ if (!this._entrypoint) {
+ this._entrypoint = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.entrypoint',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.entrypoint'
+ );
+ }
+ return this._entrypoint;
+ }
+
+ /** Gets the Environment property */
+ private _environment?: AspireDict;
+ get environment(): AspireDict {
+ if (!this._environment) {
+ this._environment = new AspireDict(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.environment',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.environment'
+ );
+ }
+ return this._environment;
+ }
+
+ /** Gets the EnvFile property */
+ private _envFile?: AspireList;
+ get envFile(): AspireList {
+ if (!this._envFile) {
+ this._envFile = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.envFile',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.envFile'
+ );
+ }
+ return this._envFile;
+ }
+
+ /** Gets the WorkingDir property */
+ workingDir = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.workingDir',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setWorkingDir',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the Ports property */
+ private _ports?: AspireList;
+ get ports(): AspireList {
+ if (!this._ports) {
+ this._ports = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.ports',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.ports'
+ );
+ }
+ return this._ports;
+ }
+
+ /** Gets the Expose property */
+ private _expose?: AspireList;
+ get expose(): AspireList {
+ if (!this._expose) {
+ this._expose = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.expose',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.expose'
+ );
+ }
+ return this._expose;
+ }
+
+ /** Gets the User property */
+ user = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.user',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setUser',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the Networks property */
+ private _networks?: AspireList;
+ get networks(): AspireList {
+ if (!this._networks) {
+ this._networks = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.networks',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.networks'
+ );
+ }
+ return this._networks;
+ }
+
+ /** Gets the Restart property */
+ restart = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.restart',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setRestart',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the Labels property */
+ private _labels?: AspireDict;
+ get labels(): AspireDict {
+ if (!this._labels) {
+ this._labels = new AspireDict(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.labels',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.labels'
+ );
+ }
+ return this._labels;
+ }
+
+ /** Gets the DomainName property */
+ domainName = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.domainName',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setDomainName',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the Hostname property */
+ hostname = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.hostname',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setHostname',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the Isolation property */
+ isolation = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.isolation',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setIsolation',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the Ipc property */
+ ipc = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.ipc',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setIpc',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the MacAddress property */
+ macAddress = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.macAddress',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setMacAddress',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the Pid property */
+ pid = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.pid',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setPid',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the CapAdd property */
+ private _capAdd?: AspireList;
+ get capAdd(): AspireList {
+ if (!this._capAdd) {
+ this._capAdd = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.capAdd',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.capAdd'
+ );
+ }
+ return this._capAdd;
+ }
+
+ /** Gets the CapDrop property */
+ private _capDrop?: AspireList;
+ get capDrop(): AspireList {
+ if (!this._capDrop) {
+ this._capDrop = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.capDrop',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.capDrop'
+ );
+ }
+ return this._capDrop;
+ }
+
+ /** Gets the CgroupParent property */
+ cgroupParent = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.cgroupParent',
+ { context: this._handle }
+ );
+ },
+ set: async (value: string): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setCgroupParent',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the Devices property */
+ private _devices?: AspireList;
+ get devices(): AspireList {
+ if (!this._devices) {
+ this._devices = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.devices',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.devices'
+ );
+ }
+ return this._devices;
+ }
+
+ /** Gets the Dns property */
+ private _dns?: AspireList;
+ get dns(): AspireList {
+ if (!this._dns) {
+ this._dns = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.dns',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.dns'
+ );
+ }
+ return this._dns;
+ }
+
+ /** Gets the DnsSearch property */
+ private _dnsSearch?: AspireList;
+ get dnsSearch(): AspireList {
+ if (!this._dnsSearch) {
+ this._dnsSearch = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.dnsSearch',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.dnsSearch'
+ );
+ }
+ return this._dnsSearch;
+ }
+
+ /** Gets the ExtraHosts property */
+ private _extraHosts?: AspireDict;
+ get extraHosts(): AspireDict {
+ if (!this._extraHosts) {
+ this._extraHosts = new AspireDict(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.extraHosts',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.extraHosts'
+ );
+ }
+ return this._extraHosts;
+ }
+
+ /** Gets the GroupAdd property */
+ private _groupAdd?: AspireList;
+ get groupAdd(): AspireList {
+ if (!this._groupAdd) {
+ this._groupAdd = new AspireList(
+ this._handle,
+ this._client,
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.groupAdd',
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.groupAdd'
+ );
+ }
+ return this._groupAdd;
+ }
+
+ /** Gets the Init property */
+ init = {
+ get: async (): Promise => {
+ return await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.init',
+ { context: this._handle }
+ );
+ },
+ set: async (value: boolean): Promise => {
+ await this._client.invokeCapability(
+ 'Aspire.Hosting.Docker.Resources.ComposeNodes/Service.setInit',
+ { context: this._handle, value }
+ );
+ }
+ };
+
+ /** Gets the Links property */
+ private _links?: AspireList;
+ get links(): AspireList {
+ if (!this._links) {
+ this._links = new AspireList