using Apollinare.API.Hubs; using Apollinare.API.Services; using Apollinare.API.Services.Reports; using Apollinare.API.Modules.Warehouse.Services; using Apollinare.Infrastructure.Data; using Microsoft.EntityFrameworkCore; using System.Text.Json.Serialization; var builder = WebApplication.CreateBuilder(args); // Database var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? "Data Source=apollinare.db"; builder.Services.AddDbContext(options => options.UseSqlite(connectionString)); // Services builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddSingleton(); // Warehouse Module Services builder.Services.AddScoped(); // Memory cache for module state builder.Services.AddMemoryCache(); // SignalR - with increased message size for template sync (default is 32KB) builder.Services.AddSignalR(options => { options.MaximumReceiveMessageSize = 1024 * 1024; // 1MB max message size }) .AddJsonProtocol(options => { options.PayloadSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; options.PayloadSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; }); // CORS - Allow credentials for SignalR (accepts any origin for external access) builder.Services.AddCors(options => { options.AddPolicy("AllowFrontend", policy => { policy.SetIsOriginAllowed(_ => true) // Permette qualsiasi origine .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); // Controllers with JSON options builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; }); builder.Services.AddOpenApi(); var app = builder.Build(); // Apply pending migrations automatically on startup using (var scope = app.Services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); var logger = scope.ServiceProvider.GetRequiredService>(); try { var pendingMigrations = await db.Database.GetPendingMigrationsAsync(); if (pendingMigrations.Any()) { logger.LogInformation("Applying {Count} pending migrations: {Migrations}", pendingMigrations.Count(), string.Join(", ", pendingMigrations)); await db.Database.MigrateAsync(); logger.LogInformation("Migrations applied successfully"); } else { logger.LogInformation("Database is up to date, no migrations to apply"); } } catch (Exception ex) { logger.LogError(ex, "Error applying migrations"); throw; } // Seed data (only in development or if database is empty) DbSeeder.Seed(db); // Seed default modules var moduleService = scope.ServiceProvider.GetRequiredService(); await moduleService.SeedDefaultModulesAsync(); // Seed warehouse default data var warehouseService = scope.ServiceProvider.GetRequiredService(); await warehouseService.SeedDefaultDataAsync(); // Seed AutoCode configurations var autoCodeService = scope.ServiceProvider.GetRequiredService(); await autoCodeService.SeedDefaultConfigurationsAsync(); } if (app.Environment.IsDevelopment()) { app.MapOpenApi(); } app.UseCors("AllowFrontend"); app.UseWebSockets(); app.UseAuthorization(); app.MapControllers(); app.MapHub("/hubs/data"); app.MapHub("/hubs/collaboration"); app.Run();