| File: Projects\AppHostServerProject.cs | Web Access |
| Project: src\src\Aspire.Cli\Aspire.Cli.csproj (aspire) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Aspire.Cli.Bundles; using Aspire.Cli.DotNet; using Aspire.Cli.Layout; using Aspire.Cli.NuGet; using Aspire.Cli.Packaging; using Aspire.Cli.Utils; using Microsoft.Extensions.Logging; namespace Aspire.Cli.Projects; /// <summary> /// Factory for creating AppHostServerProject instances with required dependencies. /// </summary> internal interface IAppHostServerProjectFactory { Task<IAppHostServerProject> CreateAsync(string appPath, CancellationToken cancellationToken = default); } /// <summary> /// Factory implementation that creates IAppHostServerProject instances. /// Chooses between DotNetBasedAppHostServerProject (dev mode) and PrebuiltAppHostServer (bundle mode). /// </summary> internal sealed class AppHostServerProjectFactory( IDotNetCliRunner dotNetCliRunner, IPackagingService packagingService, IBundleService bundleService, BundleNuGetService bundleNuGetService, IDotNetSdkInstaller sdkInstaller, CliExecutionContext executionContext, IEnvironment environment, IProcessExecutionFactory processExecutionFactory, ILoggerFactory loggerFactory) : IAppHostServerProjectFactory { public async Task<IAppHostServerProject> CreateAsync(string appPath, CancellationToken cancellationToken = default) { var socketPath = CliPathHelper.CreateGuestAppHostSocketPath("apphost.sock"); // Priority 1: Check for dev mode (ASPIRE_REPO_ROOT or running from Aspire source repo) var repoRoot = AspireRepositoryDetector.DetectRepositoryRoot(appPath); if (repoRoot is not null) { return new DotNetBasedAppHostServerProject( appPath, socketPath, repoRoot, dotNetCliRunner, packagingService, processExecutionFactory, environment, loggerFactory.CreateLogger<DotNetBasedAppHostServerProject>(), logFilePath: executionContext.LogFilePath); } // Priority 2: Ensure bundle is extracted and check for layout var layoutLease = await bundleService.EnsureExtractedAndAcquireLayoutAsync("cli", "apphost-server", cancellationToken); var layout = layoutLease?.Layout; // Priority 3: Check if we have a bundle layout with a pre-built AppHost server if (layout is not null && layout.GetManagedPath() is string serverPath && File.Exists(serverPath)) { return CreatePrebuiltAppHostServer(appPath, socketPath, layout, layoutLease); } layoutLease?.Dispose(); throw new InvalidOperationException( "No Aspire AppHost server is available. Ensure the Aspire CLI is installed " + "with a valid bundle layout, or reinstall using 'aspire setup --force'."); } internal PrebuiltAppHostServer CreatePrebuiltAppHostServer( string appPath, string socketPath, LayoutConfiguration layout, BundleLayoutLease? layoutLease) { try { return new PrebuiltAppHostServer( appPath, socketPath, layout, bundleNuGetService, dotNetCliRunner, sdkInstaller, packagingService, executionContext, processExecutionFactory, environment, loggerFactory.CreateLogger<PrebuiltAppHostServer>(), layoutLease); } catch { layoutLease?.Dispose(); throw; } } }