ApplicationBuilderHelpers 4.0.25
dotnet add package ApplicationBuilderHelpers --version 4.0.25
NuGet\Install-Package ApplicationBuilderHelpers -Version 4.0.25
<PackageReference Include="ApplicationBuilderHelpers" Version="4.0.25" />
<PackageVersion Include="ApplicationBuilderHelpers" Version="4.0.25" />
<PackageReference Include="ApplicationBuilderHelpers" />
paket add ApplicationBuilderHelpers --version 4.0.25
#r "nuget: ApplicationBuilderHelpers, 4.0.25"
#:package ApplicationBuilderHelpers@4.0.25
#addin nuget:?package=ApplicationBuilderHelpers&version=4.0.25
#tool nuget:?package=ApplicationBuilderHelpers&version=4.0.25
ApplicationBuilderHelpers
A powerful .NET library for building command-line applications with a fluent API, dependency injection, and modular architecture. ApplicationBuilderHelpers simplifies the creation of CLI tools by providing a structured approach to command handling, configuration management, and application composition.
Features
- 🎯 Command-based Architecture - Build CLI applications using command patterns with automatic argument parsing
- 🔧 Fluent Builder API - Intuitive application setup using method chaining
- 💉 Dependency Injection - Full support for Microsoft.Extensions.DependencyInjection
- 🏗️ Modular Application Structure - Compose applications from reusable components
- ⚙️ Configuration Management - Seamless integration with .NET configuration system
- 🎨 Attribute-based Command Options - Define command-line arguments using attributes
- 🔄 Middleware Pipeline - Support for application middleware and lifecycle hooks
- 📦 Multiple Application Contexts - Support for WebApplication, ConsoleApp, and custom host builders
Installation
dotnet add package ApplicationBuilderHelpers
Quick Start
1. Create Your Main Program
using ApplicationBuilderHelpers;
using YourApp.Commands;
using YourApp.Applications;
return await ApplicationBuilder.Create()
.AddApplication<CoreApplication>()
.AddApplication<InfrastructureApplication>()
.AddCommand<MainCommand>()
.AddCommand<ProcessCommand>()
.AddCommand<MigrateCommand>()
.RunAsync(args);
2. Define a Command
using ApplicationBuilderHelpers.Attributes;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace YourApp.Commands;
[Command(description: "Main command for your application")]
public class MainCommand : Command
{
[CommandOption('v', "verbose", Description = "Enable verbose output")]
public bool Verbose { get; set; }
[CommandOption('c', "config", Description = "Configuration file path", EnvironmentVariable = "APP_CONFIG")]
public string? ConfigPath { get; set; }
[CommandOption("timeout", Description = "Timeout in seconds")]
public int Timeout { get; set; } = 30;
protected override async ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cancellationTokenSource)
{
// Access services from DI container
var logger = applicationHost.Services.GetRequiredService<ILogger<MainCommand>>();
var myService = applicationHost.Services.GetRequiredService<IMyService>();
logger.LogInformation("Running main command with verbose={Verbose}, config={Config}, timeout={Timeout}",
Verbose, ConfigPath, Timeout);
// Your command logic here
await myService.DoWorkAsync();
cancellationTokenSource.Cancel(); // Stop the application when done
}
}
3. Create an Application Module
using ApplicationBuilderHelpers;
using ApplicationBuilderHelpers.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace YourApp.Applications;
public class CoreApplication : ApplicationDependency
{
public override void CommandPreparation(ApplicationBuilder applicationBuilder)
{
// Add custom type parsers for command arguments
applicationBuilder.AddCommandTypeParser<CustomTypeParser>();
}
public override void BuilderPreparation(ApplicationHostBuilder applicationBuilder)
{
// Prepare the host builder before configuration
}
public override void AddConfigurations(ApplicationHostBuilder applicationBuilder, IConfiguration configuration)
{
// Add custom configuration providers or bind configuration sections
applicationBuilder.Services.Configure<AppSettings>(configuration.GetSection("AppSettings"));
}
public override void AddServices(ApplicationHostBuilder applicationBuilder, IServiceCollection services)
{
// Register your services
services.AddSingleton<IMyService, MyService>();
services.AddHttpClient();
// Add other services
services.AddLogging();
}
public override void AddMiddlewares(ApplicationHost applicationHost, IHost host)
{
// Add middleware to the application pipeline
}
public override void RunPreparation(ApplicationHost applicationHost)
{
// Perform any final setup before the application runs
}
}
Core Components
ApplicationBuilder
The entry point for building your application. Provides a fluent API for composing applications and commands.
Key Methods:
Create()
- Creates a new ApplicationBuilder instanceAddApplication<T>()
- Adds an application moduleAddCommand<T>()
- Registers a commandRunAsync(args)
- Builds and runs the application
Command
Base class for all CLI commands. Override the Run
method to implement command logic. Commands can also configure services and application behavior just like ApplicationDependency.
Command Attributes:
[Command]
- Defines command metadata (name, description, aliases)[CommandOption]
- Defines command-line options[CommandArgument]
- Defines positional arguments
Command Lifecycle Methods:
Commands inherit the same lifecycle methods as ApplicationDependency:
[Command("process", description: "Process data with custom services")]
public class ProcessCommand : Command
{
[CommandOption('f', "file", Description = "Input file path")]
public string? FilePath { get; set; }
// Configure command-specific services
public override void AddServices(ApplicationHostBuilder applicationBuilder, IServiceCollection services)
{
services.AddScoped<IDataProcessor, DataProcessor>();
services.AddScoped<IFileValidator, FileValidator>();
services.AddLogging(logging => logging.AddConsole());
}
// Configure command-specific settings
public override void AddConfigurations(ApplicationHostBuilder applicationBuilder, IConfiguration configuration)
{
applicationBuilder.Services.Configure<ProcessingOptions>(
configuration.GetSection("Processing"));
}
// Add command-specific middleware
public override void AddMiddlewares(ApplicationHost applicationHost, IHost host)
{
// Add performance monitoring middleware for this command
var logger = host.Services.GetRequiredService<ILogger<ProcessCommand>>();
logger.LogInformation("Process command middleware initialized");
}
protected override async ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cancellationTokenSource)
{
var processor = applicationHost.Services.GetRequiredService<IDataProcessor>();
var validator = applicationHost.Services.GetRequiredService<IFileValidator>();
var logger = applicationHost.Services.GetRequiredService<ILogger<ProcessCommand>>();
if (await validator.ValidateAsync(FilePath))
{
await processor.ProcessFileAsync(FilePath);
logger.LogInformation("Processing completed");
}
cancellationTokenSource.Cancel();
}
}
Accessing Services in Commands:
- Service Locator Pattern (through ApplicationHost):
protected override async ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cancellationTokenSource)
{
var logger = applicationHost.Services.GetRequiredService<ILogger<MyCommand>>();
var dbContext = applicationHost.Services.GetRequiredService<AppDbContext>();
logger.LogInformation("Command started");
// Use services...
}
- Constructor Injection (if supported by the command resolver):
public class ImportCommand : Command
{
private readonly IDataImporter _importer;
private readonly ILogger<ImportCommand> _logger;
public ImportCommand(IDataImporter importer, ILogger<ImportCommand> logger)
{
_importer = importer;
_logger = logger;
}
protected override async ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cancellationTokenSource)
{
_logger.LogInformation("Importing data...");
await _importer.ImportAsync();
cancellationTokenSource.Cancel();
}
}
ApplicationDependency
Base class for application modules that configure services, middleware, and application behavior.
Lifecycle Methods (shared with Command):
CommandPreparation
- Configure command parsingBuilderPreparation
- Prepare the host builderAddConfigurations
- Add configuration providersAddServices
- Register services with DI containerAddMiddlewares
- Configure middleware pipelineRunPreparation
- Final setup before run
Advanced Features
Custom Type Parsers
Implement custom parsing for command arguments by implementing the ICommandTypeParser
interface:
using ApplicationBuilderHelpers.Interfaces;
using System.Diagnostics.CodeAnalysis;
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public class DateTimeTypeParser : ICommandTypeParser
{
public Type Type => typeof(DateTime);
public object? Parse(string? value, out string? validateError)
{
validateError = null;
if (string.IsNullOrEmpty(value))
{
validateError = "Date value cannot be empty";
return null;
}
if (DateTime.TryParse(value, out var result))
{
return result;
}
validateError = $"'{value}' is not a valid date format";
return null;
}
public string? GetString(object? value)
{
if (value is DateTime dateTime)
{
return dateTime.ToString("yyyy-MM-dd HH:mm:ss");
}
return value?.ToString();
}
}
// Register in your application
public class CoreApplication : ApplicationDependency
{
public override void CommandPreparation(ApplicationBuilder applicationBuilder)
{
applicationBuilder.AddCommandTypeParser<DateTimeTypeParser>();
}
}
More complex type parser example:
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public class LogLevelTypeParser : ICommandTypeParser
{
public Type Type => typeof(LogLevel);
public object? Parse(string? value, out string? validateError)
{
validateError = null;
if (string.IsNullOrWhiteSpace(value))
{
validateError = "Log level cannot be empty";
return null;
}
if (Enum.TryParse<LogLevel>(value, true, out var logLevel))
{
return logLevel;
}
var validValues = string.Join(", ", Enum.GetNames(typeof(LogLevel)));
validateError = $"'{value}' is not a valid log level. Valid values are: {validValues}";
return null;
}
public string? GetString(object? value)
{
return value?.ToString()?.ToLower();
}
}
// Usage in a command
[Command(description: "Configure logging")]
public class LogCommand : Command
{
[CommandOption('l', "level", Description = "Set the logging level")]
public LogLevel Level { get; set; } = LogLevel.Information;
protected override ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cts)
{
var logger = applicationHost.Services.GetRequiredService<ILogger<LogCommand>>();
logger.LogInformation("Logging level set to: {Level}", Level);
cts.Cancel();
return ValueTask.CompletedTask;
}
}
Self-Contained Commands
Commands can be completely self-contained with their own service configuration:
[Command("backup", description: "Backup database")]
public class BackupCommand : Command
{
[CommandOption('o', "output", Description = "Output file path")]
public string OutputPath { get; set; } = $"backup_{DateTime.Now:yyyyMMdd_HHmmss}.bak";
// Register services specific to backup operations
public override void AddServices(ApplicationHostBuilder applicationBuilder, IServiceCollection services)
{
services.AddSingleton<IBackupService, BackupService>();
services.AddSingleton<ICompressionService, CompressionService>();
services.AddSingleton<ICloudStorageService, AzureStorageService>();
// Add Azure Storage client
services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(applicationBuilder.Configuration["Azure:StorageConnection"]);
});
}
public override void AddConfigurations(ApplicationHostBuilder applicationBuilder, IConfiguration configuration)
{
// Bind backup-specific configuration
applicationBuilder.Services.Configure<BackupOptions>(
configuration.GetSection("Backup"));
}
protected override async ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cancellationTokenSource)
{
var backupService = applicationHost.Services.GetRequiredService<IBackupService>();
var cloudStorage = applicationHost.Services.GetRequiredService<ICloudStorageService>();
var logger = applicationHost.Services.GetRequiredService<ILogger<BackupCommand>>();
logger.LogInformation("Creating backup to {OutputPath}", OutputPath);
var backupFile = await backupService.CreateBackupAsync(OutputPath);
logger.LogInformation("Uploading backup to cloud storage");
await cloudStorage.UploadAsync(backupFile);
logger.LogInformation("Backup completed successfully");
cancellationTokenSource.Cancel();
}
}
Sub-Commands
Create hierarchical command structures using space-separated command names:
// Main deploy command
[Command("deploy", description: "Deployment commands")]
public class DeployCommand : Command
{
protected override ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cts)
{
Console.WriteLine("Please specify a deployment target. Use --help for available options.");
cts.Cancel();
return ValueTask.CompletedTask;
}
}
// Sub-command: deploy prod
[Command("deploy prod", description: "Deploy to production environment")]
public class DeployProductionCommand : Command
{
[CommandOption("skip-tests", Description = "Skip running tests before deployment")]
public bool SkipTests { get; set; }
// Add production-specific services
public override void AddServices(ApplicationHostBuilder applicationBuilder, IServiceCollection services)
{
services.AddSingleton<IDeploymentService, ProductionDeploymentService>();
services.AddSingleton<IHealthCheckService, HealthCheckService>();
services.AddSingleton<IRollbackService, RollbackService>();
}
protected override async ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cts)
{
var deployService = applicationHost.Services.GetRequiredService<IDeploymentService>();
var healthCheck = applicationHost.Services.GetRequiredService<IHealthCheckService>();
var logger = applicationHost.Services.GetRequiredService<ILogger<DeployProductionCommand>>();
logger.LogInformation("Deploying to production environment...");
if (!SkipTests)
{
logger.LogInformation("Running pre-deployment tests...");
// Run tests
}
await deployService.DeployAsync();
await healthCheck.VerifyDeploymentAsync();
cts.Cancel();
}
}
// Sub-command: deploy staging
[Command("deploy staging", description: "Deploy to staging environment")]
public class DeployStagingCommand : Command
{
// Add staging-specific services
public override void AddServices(ApplicationHostBuilder applicationBuilder, IServiceCollection services)
{
services.AddSingleton<IDeploymentService, StagingDeploymentService>();
}
protected override async ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cts)
{
var deployService = applicationHost.Services.GetRequiredService<IDeploymentService>();
var logger = applicationHost.Services.GetRequiredService<ILogger<DeployStagingCommand>>();
logger.LogInformation("Deploying to staging environment...");
await deployService.DeployAsync();
cts.Cancel();
}
}
// Deeper nesting: deploy prod rollback
[Command("deploy prod rollback", description: "Rollback production deployment")]
public class DeployProductionRollbackCommand : Command
{
[CommandOption("version", Description = "Specific version to rollback to")]
public string? Version { get; set; }
protected override async ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cts)
{
var deployService = applicationHost.Services.GetRequiredService<IDeploymentService>();
var logger = applicationHost.Services.GetRequiredService<ILogger<DeployProductionRollbackCommand>>();
logger.LogInformation("Rolling back production to version {Version}...", Version ?? "previous");
await deployService.RollbackProductionAsync(Version);
cts.Cancel();
}
}
Usage examples:
# Main deploy command
myapp deploy
# Deploy to production
myapp deploy prod
# Deploy to staging
myapp deploy staging
# Rollback production
myapp deploy prod rollback --version 1.2.3
Multiple Host Types
ApplicationBuilderHelpers supports different host types:
HostApplicationBuilder
- For console applicationsWebApplicationBuilder
- For web applications- Custom builders implementing
IHostApplicationBuilder
Environment-Specific Configuration
public override void AddConfigurations(ApplicationHostBuilder applicationBuilder, IConfiguration configuration)
{
var environment = applicationBuilder.Environment;
if (environment.IsDevelopment())
{
// Development-specific configuration
}
else if (environment.IsProduction())
{
// Production-specific configuration
}
}
Architecture
ApplicationBuilderHelpers follows a modular architecture pattern:
┌─────────────────────┐
│ ApplicationBuilder │ ← Entry Point
└──────────┬──────────┘
│
┌──────▼──────┐
│ Commands │ ← Command Registration (can also configure services)
└──────┬──────┘
│
┌──────▼──────────┐
│ Applications │ ← Application Modules
└──────┬──────────┘
│
┌──────▼───────────┐
│ Host Builder │ ← Host Configuration
└──────┬───────────┘
│
┌──────▼──────┐
│ Services │ ← Dependency Injection (from both Commands and Applications)
└──────┬──────┘
│
┌──────▼──────────┐
│ Middleware │ ← Request Pipeline
└──────┬──────────┘
│
┌──────▼──────┐
│ Execution │ ← Command Execution
└─────────────┘
Best Practices
- Separation of Concerns - Keep commands focused on coordination, move business logic to services
- Use Application Modules - Group related configurations and services in ApplicationDependency classes
- Command-Specific Services - Register services in commands when they're only needed for that specific command
- Leverage DI - Use dependency injection for better testability and maintainability
- Configuration Over Code - Use configuration files for environment-specific settings
- Async All The Way - Use async/await patterns for I/O operations
- Prefer Service Locator in Commands - When constructor injection isn't available, use
applicationHost.Services
to access dependencies - Logical Command Hierarchy - Use space-separated command names for intuitive sub-command structures
- Validate in Type Parsers - Return meaningful error messages from custom type parsers to help users
Examples
Simple Console Application
// Program.cs
return await ApplicationBuilder.Create()
.AddCommand<GreetCommand>()
.RunAsync(args);
// GreetCommand.cs
[Command(description: "Greet someone")]
public class GreetCommand : Command
{
[CommandArgument(0, Description = "Name to greet")]
public string Name { get; set; } = "World";
protected override ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cts)
{
Console.WriteLine($"Hello, {Name}!");
cts.Cancel();
return ValueTask.CompletedTask;
}
}
Command with Its Own Services
// Program.cs
return await ApplicationBuilder.Create()
.AddCommand<ReportCommand>()
.RunAsync(args);
// ReportCommand.cs
[Command("report", description: "Generate reports")]
public class ReportCommand : Command
{
[CommandOption('f', "format", Description = "Report format (pdf, excel, html)")]
public string Format { get; set; } = "pdf";
[CommandOption('o', "output", Description = "Output directory")]
public string OutputDir { get; set; } = "./reports";
// Register report-specific services
public override void AddServices(ApplicationHostBuilder applicationBuilder, IServiceCollection services)
{
services.AddScoped<IReportGenerator, ReportGenerator>();
services.AddScoped<IPdfRenderer, PdfRenderer>();
services.AddScoped<IExcelRenderer, ExcelRenderer>();
services.AddScoped<IHtmlRenderer, HtmlRenderer>();
services.AddScoped<IDataRepository, DataRepository>();
// Add logging specifically for report generation
services.AddLogging(logging =>
{
logging.AddConsole();
logging.AddFile("logs/reports-{Date}.txt");
});
}
public override void AddConfigurations(ApplicationHostBuilder applicationBuilder, IConfiguration configuration)
{
// Bind report configuration
applicationBuilder.Services.Configure<ReportOptions>(
configuration.GetSection("Reporting"));
}
protected override async ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cts)
{
var generator = applicationHost.Services.GetRequiredService<IReportGenerator>();
var logger = applicationHost.Services.GetRequiredService<ILogger<ReportCommand>>();
logger.LogInformation("Generating {Format} report to {OutputDir}", Format, OutputDir);
var report = await generator.GenerateAsync(Format);
await report.SaveToAsync(OutputDir);
logger.LogInformation("Report generated successfully");
cts.Cancel();
}
}
Complex Application with Command Hierarchy
// Program.cs
return await ApplicationBuilder.Create()
.AddApplication<CoreApplication>()
.AddApplication<InfrastructureApplication>()
.AddCommand<MainCommand>()
.AddCommand<DbCommand>()
.AddCommand<DbMigrateCommand>()
.AddCommand<DbSeedCommand>()
.AddCommand<DbBackupCommand>()
.RunAsync(args);
// Database commands hierarchy
[Command("db", description: "Database management commands")]
public class DbCommand : Command
{
protected override ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cts)
{
Console.WriteLine("Database management commands. Use --help for available sub-commands.");
cts.Cancel();
return ValueTask.CompletedTask;
}
}
[Command("db migrate", description: "Run database migrations")]
public class DbMigrateCommand : Command
{
[CommandOption("connection-string", Description = "Database connection string", EnvironmentVariable = "DB_CONNECTION")]
public string? ConnectionString { get; set; }
[CommandOption("dry-run", Description = "Preview migrations without applying")]
public bool DryRun { get; set; }
// Add migration-specific services
public override void AddServices(ApplicationHostBuilder applicationBuilder, IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options =>
{
var connectionString = ConnectionString ?? applicationBuilder.Configuration.GetConnectionString("DefaultConnection");
options.UseSqlServer(connectionString);
});
services.AddScoped<IDatabaseMigrator, EfCoreMigrator>();
}
protected override async ValueTask Run(ApplicationHost<HostApplicationBuilder> applicationHost, CancellationTokenSource cancellationTokenSource)
{
var logger = applicationHost.Services.GetRequiredService<ILogger<DbMigrateCommand>>();
var migrator = applicationHost.Services.GetRequiredService<IDatabaseMigrator>();
logger.LogInformation("Starting database migration. Dry run: {DryRun}", DryRun);
if (DryRun)
{
var pending = await migrator.GetPendingMigrationsAsync();
logger.LogInformation("Pending migrations: {Migrations}", string.Join(", ", pending));
}
else
{
await migrator.MigrateAsync();
logger.LogInformation("Database migration completed successfully");
}
cancellationTokenSource.Cancel();
}
}
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
For issues, questions, or suggestions, please create an issue on the GitHub repository.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net6.0
- AbsolutePathHelpers (>= 0.3.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.7)
- Microsoft.Extensions.Hosting (>= 9.0.7)
-
net7.0
- AbsolutePathHelpers (>= 0.3.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.7)
- Microsoft.Extensions.Hosting (>= 9.0.7)
-
net8.0
- AbsolutePathHelpers (>= 0.3.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.7)
- Microsoft.Extensions.Hosting (>= 9.0.7)
-
net9.0
- AbsolutePathHelpers (>= 0.3.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.7)
- Microsoft.Extensions.Hosting (>= 9.0.7)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
4.0.25 | 0 | 8/22/2025 |
4.0.24 | 0 | 8/21/2025 |
4.0.23 | 7 | 8/20/2025 |
4.0.22 | 6 | 8/20/2025 |
4.0.21 | 7 | 8/18/2025 |
4.0.20 | 8 | 8/16/2025 |
4.0.19 | 7 | 8/15/2025 |
4.0.18 | 14 | 8/12/2025 |
4.0.17 | 8 | 8/11/2025 |
4.0.16 | 11 | 8/9/2025 |
4.0.15 | 9 | 8/8/2025 |
4.0.14 | 9 | 8/8/2025 |
4.0.13 | 25 | 8/7/2025 |
4.0.12 | 17 | 8/7/2025 |
4.0.11 | 17 | 8/7/2025 |
4.0.10 | 17 | 8/7/2025 |
4.0.9 | 21 | 8/7/2025 |
4.0.8 | 22 | 8/7/2025 |
4.0.7 | 23 | 8/7/2025 |
4.0.6 | 23 | 8/7/2025 |
4.0.5 | 24 | 8/7/2025 |
4.0.2 | 32 | 8/6/2025 |
4.0.1 | 26 | 8/6/2025 |
4.0.0 | 24 | 8/6/2025 |
3.1.4 | 12 | 7/30/2025 |
3.1.3 | 78 | 7/29/2025 |
3.1.2 | 8 | 7/29/2025 |
3.1.1 | 8 | 7/28/2025 |
3.1.0 | 10 | 7/28/2025 |
3.0.0 | 152 | 7/15/2025 |
2.1.6 | 273 | 7/4/2025 |
2.1.5 | 31 | 7/4/2025 |
2.1.3 | 123 | 6/29/2025 |
2.1.2 | 404 | 6/5/2025 |
2.1.1 | 49 | 6/5/2025 |
2.1.0 | 33 | 6/4/2025 |
2.0.22 | 38 | 6/4/2025 |
2.0.21 | 38 | 6/4/2025 |
2.0.20 | 38 | 6/4/2025 |
2.0.19 | 42 | 6/4/2025 |
2.0.18 | 56 | 5/27/2025 |
2.0.17 | 914 | 5/23/2025 |
2.0.16 | 740 | 5/5/2025 |
2.0.15 | 301 | 4/29/2025 |
2.0.14 | 84 | 4/28/2025 |
2.0.13 | 285 | 4/24/2025 |
2.0.12 | 347 | 4/16/2025 |
2.0.11 | 132 | 4/15/2025 |
2.0.10 | 128 | 4/11/2025 |
2.0.9 | 175 | 4/4/2025 |
2.0.8 | 172 | 3/28/2025 |
2.0.7 | 167 | 3/28/2025 |
2.0.6 | 237 | 3/24/2025 |
2.0.5 | 204 | 3/24/2025 |
2.0.4 | 204 | 3/19/2025 |
2.0.3 | 256 | 3/8/2025 |
2.0.2 | 314 | 3/7/2025 |
2.0.1 | 314 | 3/7/2025 |
2.0.0 | 362 | 3/5/2025 |
1.0.62 | 384 | 2/13/2025 |
1.0.61 | 727 | 2/12/2025 |
1.0.60 | 864 | 1/16/2025 |
1.0.59 | 115 | 1/15/2025 |
1.0.58 | 90 | 1/14/2025 |
1.0.57 | 102 | 1/10/2025 |
1.0.56 | 144 | 1/1/2025 |
1.0.55 | 109 | 12/27/2024 |
1.0.54 | 129 | 12/26/2024 |
1.0.53 | 130 | 12/18/2024 |
1.0.52 | 252 | 12/6/2024 |
1.0.51 | 110 | 12/5/2024 |
1.0.50 | 105 | 12/5/2024 |
1.0.49 | 115 | 12/4/2024 |
1.0.48 | 118 | 12/3/2024 |
1.0.47 | 835 | 12/3/2024 |
1.0.46 | 182 | 11/26/2024 |
1.0.45 | 91 | 11/25/2024 |
1.0.44 | 98 | 11/22/2024 |
1.0.43 | 94 | 11/22/2024 |
1.0.42 | 99 | 11/22/2024 |
1.0.41 | 96 | 11/21/2024 |
1.0.40 | 97 | 11/20/2024 |
1.0.39 | 172 | 11/14/2024 |
1.0.38 | 385 | 11/13/2024 |
1.0.37 | 1,276 | 11/8/2024 |
1.0.36 | 102 | 11/7/2024 |
1.0.35 | 147 | 11/6/2024 |
1.0.34 | 181 | 11/5/2024 |
1.0.33 | 477 | 10/30/2024 |
1.0.32 | 94 | 10/30/2024 |
1.0.31 | 213 | 10/29/2024 |
1.0.30 | 254 | 10/28/2024 |
1.0.29 | 158 | 10/25/2024 |
1.0.28 | 327 | 10/23/2024 |
1.0.27 | 204 | 10/22/2024 |
1.0.26 | 306 | 10/17/2024 |
1.0.25 | 210 | 10/15/2024 |
1.0.24 | 304 | 10/14/2024 |
1.0.23 | 101 | 10/14/2024 |
1.0.22 | 266 | 10/10/2024 |
1.0.21 | 165 | 10/9/2024 |
1.0.20 | 220 | 10/8/2024 |
1.0.19 | 238 | 10/7/2024 |
1.0.18 | 100 | 10/7/2024 |
1.0.17 | 296 | 10/3/2024 |
1.0.16 | 258 | 9/30/2024 |
1.0.15 | 161 | 9/27/2024 |
1.0.14 | 262 | 9/25/2024 |
1.0.13 | 178 | 9/25/2024 |
1.0.12 | 229 | 9/24/2024 |
1.0.11 | 287 | 9/20/2024 |
1.0.10 | 130 | 9/20/2024 |
1.0.9 | 241 | 9/18/2024 |
1.0.8 | 128 | 9/17/2024 |
1.0.7 | 327 | 9/11/2024 |
1.0.6 | 203 | 9/10/2024 |
1.0.5 | 275 | 9/6/2024 |
1.0.4 | 241 | 9/3/2024 |
1.0.3 | 159 | 9/2/2024 |
1.0.2 | 115 | 9/2/2024 |
1.0.1 | 105 | 9/2/2024 |
1.0.0 | 98 | 9/2/2024 |
0.2.19 | 188 | 8/29/2024 |
0.2.18 | 143 | 8/28/2024 |
0.2.17 | 210 | 8/26/2024 |
0.2.16 | 235 | 8/23/2024 |
0.2.15 | 239 | 8/21/2024 |
0.2.14 | 167 | 8/20/2024 |
0.2.13 | 209 | 8/15/2024 |
0.2.12 | 209 | 8/14/2024 |
0.2.11 | 196 | 8/13/2024 |
0.2.10 | 261 | 8/1/2024 |
0.2.9 | 143 | 7/31/2024 |
0.2.8 | 196 | 7/26/2024 |
0.2.7 | 412 | 7/16/2024 |
0.2.6 | 105 | 7/15/2024 |
0.2.5 | 112 | 7/13/2024 |
0.2.4 | 102 | 7/12/2024 |
0.2.3 | 124 | 7/10/2024 |
0.2.2 | 111 | 7/8/2024 |
0.2.1 | 166 | 7/7/2024 |
0.2.0 | 115 | 7/6/2024 |
0.1.7 | 101 | 7/2/2024 |
0.1.6 | 142 | 7/1/2024 |
0.1.5 | 116 | 6/30/2024 |
0.1.4 | 113 | 6/27/2024 |
0.1.3 | 149 | 5/14/2024 |
0.1.2 | 107 | 5/14/2024 |
0.1.1 | 110 | 5/14/2024 |
0.1.0 | 583 | 3/31/2024 |
## New Version
* Bump `application_builder_helpers` from `4.0.24` to `4.0.25`. See [changelog](https://github.com/Kiryuumaru/ApplicationBuilderHelpers/compare/application_builder_helpers/4.0.24...application_builder_helpers/4.0.25)
## What's Changed
* Add support for C# required keyword in CLI handling by @Kiryuumaru in https://github.com/Kiryuumaru/ApplicationBuilderHelpers/pull/166
**Full Changelog**: https://github.com/Kiryuumaru/ApplicationBuilderHelpers/compare/build.20250821110327.1c69638...build.20250822100205.d45837e