From 527e1ae475a81a91e403c9d1064d66b3c67a72a1 Mon Sep 17 00:00:00 2001 From: Colin Ledbetter Date: Sun, 24 May 2026 21:30:16 -0400 Subject: [PATCH 1/4] More changes to infrastructure --- .gitignore | 2 +- LowPressureZone.sln | 32 +------- package.json | 2 +- .../appsettings-template.Development.json | 16 ---- .../appsettings.json | 16 ---- src/server/LowPressureZone.Aspire/AppHost.cs | 10 +-- .../ConfigurationSectionExtensions.cs | 30 +++++++ .../Extensions/ResourceBuilderExtensions.cs | 18 +++++ .../LowPressureZone.Aspire.csproj | 9 ++- .../appsettings-template.Development.json | 79 +++++++++++++++++++ .../LowPressureZone.Aspire/appsettings.json | 3 +- .../DesignTimeDataContextFactory.cs | 15 ++++ .../DesignTimeIdentityContextFactory.cs | 14 ++++ tools/deploy-client.sh | 6 -- tools/deployment-setup.sh | 5 -- tools/initialize-development.linux.sh | 10 +-- 16 files changed, 177 insertions(+), 90 deletions(-) delete mode 100644 src/server/LowPressureZone.Aspire.Migrations/appsettings-template.Development.json delete mode 100644 src/server/LowPressureZone.Aspire.Migrations/appsettings.json create mode 100644 src/server/LowPressureZone.Aspire/Extensions/ConfigurationSectionExtensions.cs create mode 100644 src/server/LowPressureZone.Aspire/Extensions/ResourceBuilderExtensions.cs create mode 100644 src/server/LowPressureZone.Aspire/appsettings-template.Development.json create mode 100644 src/server/LowPressureZone.Domain/DesignTimeDataContextFactory.cs create mode 100644 src/server/LowPressureZone.Identity/DesignTimeIdentityContextFactory.cs delete mode 100644 tools/deployment-setup.sh diff --git a/.gitignore b/.gitignore index 468ede58..794025ea 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,7 @@ coverage *.local .yarn/* .yarn -**/wwwroot/client-build +wwwroot/** /cypress/videos/ /cypress/screenshots/ diff --git a/LowPressureZone.sln b/LowPressureZone.sln index 5571b7f2..81befbe5 100644 --- a/LowPressureZone.sln +++ b/LowPressureZone.sln @@ -40,7 +40,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1. Main Application", "1. M EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2. Auxiliary", "2. Auxiliary", "{21C27C36-5628-47D2-A6B4-21A4748CEE6A}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3. Core", "3. Core", "{C8CE0E2B-370A-43AB-888A-65BF960BA18B}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3. Infrastructure", "3. Infrastructure", "{C8CE0E2B-370A-43AB-888A-65BF960BA18B}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LowPressureZone.Core", "src\server\LowPressureZone.Core\LowPressureZone.Core.csproj", "{6F15A668-3BE3-469D-9983-87CD9936BF61}" EndProject @@ -52,10 +52,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LowPressureZone.Aspire", "s EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0. Development Runtime", "0. Development Runtime", "{BD16DBED-7A26-43B3-A844-1ADF1321285C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LowPressureZone.Aspire.Migrations", "src\server\LowPressureZone.Aspire.Migrations\LowPressureZone.Aspire.Migrations.csproj", "{559DF07D-BE6D-4C9B-9C90-1C81146C40F7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LowPressureZone.Aspire.ServiceDefaults", "src\server\LowPressureZone.Aspire.ServiceDefaults\LowPressureZone.Aspire.ServiceDefaults.csproj", "{41881D9F-8A28-427D-84B2-48FDA7630CD1}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -150,30 +146,6 @@ Global {66F83131-6ACD-4067-BDE4-8B788DBFDCED}.Release|x64.Build.0 = Release|Any CPU {66F83131-6ACD-4067-BDE4-8B788DBFDCED}.Release|x86.ActiveCfg = Release|Any CPU {66F83131-6ACD-4067-BDE4-8B788DBFDCED}.Release|x86.Build.0 = Release|Any CPU - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7}.Debug|x64.ActiveCfg = Debug|Any CPU - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7}.Debug|x64.Build.0 = Debug|Any CPU - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7}.Debug|x86.ActiveCfg = Debug|Any CPU - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7}.Debug|x86.Build.0 = Debug|Any CPU - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7}.Release|Any CPU.Build.0 = Release|Any CPU - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7}.Release|x64.ActiveCfg = Release|Any CPU - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7}.Release|x64.Build.0 = Release|Any CPU - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7}.Release|x86.ActiveCfg = Release|Any CPU - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7}.Release|x86.Build.0 = Release|Any CPU - {41881D9F-8A28-427D-84B2-48FDA7630CD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {41881D9F-8A28-427D-84B2-48FDA7630CD1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {41881D9F-8A28-427D-84B2-48FDA7630CD1}.Debug|x64.ActiveCfg = Debug|Any CPU - {41881D9F-8A28-427D-84B2-48FDA7630CD1}.Debug|x64.Build.0 = Debug|Any CPU - {41881D9F-8A28-427D-84B2-48FDA7630CD1}.Debug|x86.ActiveCfg = Debug|Any CPU - {41881D9F-8A28-427D-84B2-48FDA7630CD1}.Debug|x86.Build.0 = Debug|Any CPU - {41881D9F-8A28-427D-84B2-48FDA7630CD1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {41881D9F-8A28-427D-84B2-48FDA7630CD1}.Release|Any CPU.Build.0 = Release|Any CPU - {41881D9F-8A28-427D-84B2-48FDA7630CD1}.Release|x64.ActiveCfg = Release|Any CPU - {41881D9F-8A28-427D-84B2-48FDA7630CD1}.Release|x64.Build.0 = Release|Any CPU - {41881D9F-8A28-427D-84B2-48FDA7630CD1}.Release|x86.ActiveCfg = Release|Any CPU - {41881D9F-8A28-427D-84B2-48FDA7630CD1}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -186,8 +158,6 @@ Global {6F15A668-3BE3-469D-9983-87CD9936BF61} = {C8CE0E2B-370A-43AB-888A-65BF960BA18B} {5DEF3DA9-DCB9-4C29-921B-52AEA5F9D053} = {2E2C54E2-972F-4583-BB87-A5B5606D397D} {66F83131-6ACD-4067-BDE4-8B788DBFDCED} = {BD16DBED-7A26-43B3-A844-1ADF1321285C} - {559DF07D-BE6D-4C9B-9C90-1C81146C40F7} = {BD16DBED-7A26-43B3-A844-1ADF1321285C} - {41881D9F-8A28-427D-84B2-48FDA7630CD1} = {BD16DBED-7A26-43B3-A844-1ADF1321285C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E01F24AA-56EC-4C41-A7A6-82A3D36C4C70} diff --git a/package.json b/package.json index 7e4211a1..b2d86618 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "description": "Handles development dependencies and deployment.", "scripts": { - "deploy-prod": "./tools/deploy-client.sh && ./tools/deploy-server.sh", + "deploy-prod": "git reset --hard && chmod +x ./tools/deploy-client.sh && chmod +x ./tools/deploy-server.sh && ./tools/deploy-client.sh && ./tools/deploy-server.sh", "initialize-development": "node -e \"const p=process.platform; const cmd=p==='win32'?'npm run initialize-development:windows':(p==='darwin'?'npm run initialize-development:macos':'npm run initialize-development:linux'); require('child_process').execSync(cmd,{stdio:'inherit'})\"", "initialize-development:windows": "powershell -File .\\tools\\initialize-development.windows.ps1", "initialize-development:linux": "bash ./tools/initialize-development.linux.sh", diff --git a/src/server/LowPressureZone.Aspire.Migrations/appsettings-template.Development.json b/src/server/LowPressureZone.Aspire.Migrations/appsettings-template.Development.json deleted file mode 100644 index 585e4de9..00000000 --- a/src/server/LowPressureZone.Aspire.Migrations/appsettings-template.Development.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "SeedData": { - "Identity": { - "AdminUsername": "{AdminUsername}", - "AdminDisplayName": "{AdminDisplayName}", - "AdminEmail": "{AdminEmail}", - "AdminPassword": "{AdminPassword}" - } - } -} diff --git a/src/server/LowPressureZone.Aspire.Migrations/appsettings.json b/src/server/LowPressureZone.Aspire.Migrations/appsettings.json deleted file mode 100644 index 49187fab..00000000 --- a/src/server/LowPressureZone.Aspire.Migrations/appsettings.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "SeedData": { - "Identity": { - "AdminUsername": "", - "AdminDisplayName": "", - "AdminEmail": "", - "AdminPassword": "" - } - } -} diff --git a/src/server/LowPressureZone.Aspire/AppHost.cs b/src/server/LowPressureZone.Aspire/AppHost.cs index f626fbd2..1587f6ef 100644 --- a/src/server/LowPressureZone.Aspire/AppHost.cs +++ b/src/server/LowPressureZone.Aspire/AppHost.cs @@ -1,3 +1,5 @@ +using LowPressureZone.Aspire.Extensions; +using Microsoft.Extensions.Configuration; using Projects; // ReSharper disable UnusedVariable @@ -12,12 +14,6 @@ var identityDatabase = postgres.AddDatabase("lpz-identity"); var pgAdmin = postgres.WithPgAdmin(containerName: "lpz-pgAdmin"); -var migrations = builder.AddProject("migrations") - .WaitFor(domainDatabase) - .WaitFor(identityDatabase) - .WithReference(domainDatabase, "Data") - .WithReference(identityDatabase, "Identity"); - var azuracast = builder.AddContainer("azuracast", "ghcr.io/azuracast/azuracast", "0.23.3") .WithBindMount($"{bindMountDir}/azuracast/stations", "/var/azuracast/stations") @@ -49,9 +45,9 @@ var mailpit = builder.AddMailPit("mailpit", 9280, 9281); var api = builder.AddProject("lpz-api") + .AddConfigurationToEnvironment(builder.Configuration.GetSection("LowPressureZone")) .WaitFor(azuracast) .WaitFor(mailpit) - .WaitForCompletion(migrations) .WaitFor(domainDatabase) .WaitFor(identityDatabase) .WithReference(mailpit) diff --git a/src/server/LowPressureZone.Aspire/Extensions/ConfigurationSectionExtensions.cs b/src/server/LowPressureZone.Aspire/Extensions/ConfigurationSectionExtensions.cs new file mode 100644 index 00000000..d7cd34de --- /dev/null +++ b/src/server/LowPressureZone.Aspire/Extensions/ConfigurationSectionExtensions.cs @@ -0,0 +1,30 @@ +using Microsoft.Extensions.Configuration; + +namespace LowPressureZone.Aspire.Extensions; + +public static class ConfigurationSectionExtensions +{ + public static IEnumerable> Flatten(this IConfigurationSection section, string? variablePrefix = null) + { + variablePrefix ??= ""; + var children = section.GetChildren().ToList(); + + if (children.Count == 0) + { + yield return new KeyValuePair(variablePrefix, section.Value ?? string.Empty); + yield break; + } + + foreach (var child in children) + { + var childPath = !string.IsNullOrWhiteSpace(variablePrefix) + ? string.Concat(variablePrefix, "__", child.Key) + : child.Key; + + foreach (var entry in child.Flatten(childPath)) + { + yield return entry; + } + } + } +} \ No newline at end of file diff --git a/src/server/LowPressureZone.Aspire/Extensions/ResourceBuilderExtensions.cs b/src/server/LowPressureZone.Aspire/Extensions/ResourceBuilderExtensions.cs new file mode 100644 index 00000000..277f9887 --- /dev/null +++ b/src/server/LowPressureZone.Aspire/Extensions/ResourceBuilderExtensions.cs @@ -0,0 +1,18 @@ +using Microsoft.Extensions.Configuration; + +namespace LowPressureZone.Aspire.Extensions; + +public static class ResourceBuilderExtensions +{ + public static IResourceBuilder AddConfigurationToEnvironment(this IResourceBuilder builder, IConfigurationSection section) + where TResource : IResourceWithEnvironment + { + var environmentVariables = section.Flatten(); + foreach (var environmentVariable in environmentVariables) + { + builder.WithEnvironment(environmentVariable.Key, environmentVariable.Value); + } + + return builder; + } +} \ No newline at end of file diff --git a/src/server/LowPressureZone.Aspire/LowPressureZone.Aspire.csproj b/src/server/LowPressureZone.Aspire/LowPressureZone.Aspire.csproj index b21a46ae..e1b94e34 100644 --- a/src/server/LowPressureZone.Aspire/LowPressureZone.Aspire.csproj +++ b/src/server/LowPressureZone.Aspire/LowPressureZone.Aspire.csproj @@ -19,7 +19,14 @@ - + + + + + true + PreserveNewest + PreserveNewest + diff --git a/src/server/LowPressureZone.Aspire/appsettings-template.Development.json b/src/server/LowPressureZone.Aspire/appsettings-template.Development.json new file mode 100644 index 00000000..a9c22257 --- /dev/null +++ b/src/server/LowPressureZone.Aspire/appsettings-template.Development.json @@ -0,0 +1,79 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Aspire.Hosting.Dcp": "Warning" + } + }, + "LowPressureZone": { + "AllowedHosts": "*", + "AzuraCastClient": { + "ApiUrl": "http://localhost:8147", + "ApiKey": "8184be3e33bbee61:f9e06d6ad66020b1de29ce12c3e5eb40", + "StationId": "1", + "SftpHost": "localhost", + "SftpPort": "8149", + "SftpUser": "dev", + "SftpPassword": "password" + }, + "AzuraCastInstallation": { + "PrerecordedSetLocation": "Prerecords", + "ArchiveSetLocation": "Archive", + "ArchivePlaylistName": "Rotation" + }, + "ConnectionStrings": { + "Data": "", + "Identity": "" + }, + "Email": { + "MailgunApiKey": "", + "MailgunDomain": "", + "SmtpHost": "localhost", + "SmtpPort": "9281", + "AdminEmail": "{AdminEmail}", + "FromAddress": "noreply@lowpressurezone.com" + }, + "Files": { + "AzuraCastArchiveSetLocation": "Archives", + "AzuraCastPrerecordedSetLocation": "Prerecords" + }, + "Icecast": { + "StreamingUrl": "https://lowpressurezone.com:8443" + }, + "Logging": { + "LogLevel": { + "Default": "Warning", + "Microsoft.AspNetCore": "Debug", + "LowPressureZone": "Information" + } + }, + "SeedData": { + "Identity": { + "AdminUsername": "", + "AdminDisplayName": "", + "AdminEmail": "", + "AdminPassword": "" + } + }, + "Streaming": { + "Live": { + "Host": "http://localhost", + "Port": "8030", + "Mount": "live" + }, + "Test": { + "Host": "http://localhost", + "Port": "8000", + "Mount": "test", + "Username": "source", + "Password": "hackme" + } + }, + "Url": { + "SiteUrl": "http://localhost:4001", + "RegisterUrl": "http://localhost:4001/user/register", + "ResetPasswordUrl": "http://localhost:4001/user/resetpassword" + } + } +} \ No newline at end of file diff --git a/src/server/LowPressureZone.Aspire/appsettings.json b/src/server/LowPressureZone.Aspire/appsettings.json index 31c092aa..17b9e014 100644 --- a/src/server/LowPressureZone.Aspire/appsettings.json +++ b/src/server/LowPressureZone.Aspire/appsettings.json @@ -5,5 +5,6 @@ "Microsoft.AspNetCore": "Warning", "Aspire.Hosting.Dcp": "Warning" } - } + }, + "LowPressureZone": {} } diff --git a/src/server/LowPressureZone.Domain/DesignTimeDataContextFactory.cs b/src/server/LowPressureZone.Domain/DesignTimeDataContextFactory.cs new file mode 100644 index 00000000..87fed031 --- /dev/null +++ b/src/server/LowPressureZone.Domain/DesignTimeDataContextFactory.cs @@ -0,0 +1,15 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Options; + +namespace LowPressureZone.Domain; + +public class DesignTimeDataContextFactory : IDesignTimeDbContextFactory +{ + public DataContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseNpgsql(); + return new DataContext(optionsBuilder.Options); + } +} \ No newline at end of file diff --git a/src/server/LowPressureZone.Identity/DesignTimeIdentityContextFactory.cs b/src/server/LowPressureZone.Identity/DesignTimeIdentityContextFactory.cs new file mode 100644 index 00000000..e005ea56 --- /dev/null +++ b/src/server/LowPressureZone.Identity/DesignTimeIdentityContextFactory.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; + +namespace LowPressureZone.Identity; + +public class DesignTimeIdentityContextFactory : IDesignTimeDbContextFactory +{ + public IdentityContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseNpgsql(); + return new IdentityContext(optionsBuilder.Options); + } +} \ No newline at end of file diff --git a/tools/deploy-client.sh b/tools/deploy-client.sh index a0a924de..0048655e 100644 --- a/tools/deploy-client.sh +++ b/tools/deploy-client.sh @@ -5,10 +5,4 @@ yarn install --immutable sed -i 's/development/production/g' vite.config.ts yarn build sed -i 's/production/development/g' vite.config.ts -sudo rm -r /var/www/html/low-pressure-zone/* -sudo cp -r dist/* /var/www/html/low-pressure-zone -sudo chown -R root:www-data /var/www/html/low-pressure-zone -sudo chmod -R 770 /var/www/html/low-pressure-zone -sudo chmod 640 /var/www/html/low-pressure-zone/index.html -sudo chmod 640 /var/www/html/low-pressure-zone/assets/* cd ../.. diff --git a/tools/deployment-setup.sh b/tools/deployment-setup.sh deleted file mode 100644 index ef8cde11..00000000 --- a/tools/deployment-setup.sh +++ /dev/null @@ -1,5 +0,0 @@ -sudo cp tools/service.template /etc/systemd/system/lpzapi.service -sudo mkdir /var/www/html/low-pressure-zone -sudo chown -R root:www-data /var/www/html/low-pressure-zone -sudo mkdir /var/www/html/low-pressure-zone-api -sudo chown -R root:www-data /var/www/html/low-pressure-zone-api \ No newline at end of file diff --git a/tools/initialize-development.linux.sh b/tools/initialize-development.linux.sh index 6e03280a..92ff4ef2 100644 --- a/tools/initialize-development.linux.sh +++ b/tools/initialize-development.linux.sh @@ -12,11 +12,11 @@ read admin_password rm src/server/LowPressureZone.Aspire.Migrations/appsettings.Development.json rm src/server/LowPressureZone.Api/appsettings.Development.json -cp src/server/LowPressureZone.Aspire.Migrations/appsettings-template.Development.json src/server/LowPressureZone.Aspire.Migrations/appsettings.Development.json -sed -i "s/{AdminUsername}/$admin_username/g" src/server/LowPressureZone.Aspire.Migrations/appsettings.Development.json -sed -i "s/{AdminDisplayName}/$admin_displayname/g" src/server/LowPressureZone.Aspire.Migrations/appsettings.Development.json -sed -i "s/{AdminEmail}/$admin_email/g" src/server/LowPressureZone.Aspire.Migrations/appsettings.Development.json -sed -i "s/{AdminPassword}/$admin_password/g" src/server/LowPressureZone.Aspire.Migrations/appsettings.Development.json +cp src/server/LowPressureZone.Aspire/appsettings-template.Development.json src/server/LowPressureZone.Aspire/appsettings.Development.json +sed -i "s/{AdminUsername}/$admin_username/g" src/server/LowPressureZone.Aspire/appsettings.Development.json +sed -i "s/{AdminDisplayName}/$admin_displayname/g" src/server/LowPressureZone.Aspire/appsettings.Development.json +sed -i "s/{AdminEmail}/$admin_email/g" src/server/LowPressureZone.Aspire/appsettings.Development.json +sed -i "s/{AdminPassword}/$admin_password/g" src/server/LowPressureZone.Aspire/appsettings.Development.json cp src/server/LowPressureZone.Api/appsettings-template.Development.json src/server/LowPressureZone.Api/appsettings.Development.json sed -i "s/{AdminEmail}/$admin_email/g" src/server/LowPressureZone.Api/appsettings.Development.json From 352d4874ff6f9051adffdfcb5e4dce8578900448 Mon Sep 17 00:00:00 2001 From: Colin Ledbetter Date: Sun, 24 May 2026 21:30:37 -0400 Subject: [PATCH 2/4] Remove files --- .../LowPressureZone.Aspire.Migrations.csproj | 21 --- .../Program.cs | 22 --- .../Properties/launchSettings.json | 12 -- .../Worker.cs | 28 ---- .../Extensions.cs | 132 ------------------ ...PressureZone.Aspire.ServiceDefaults.csproj | 25 ---- 6 files changed, 240 deletions(-) delete mode 100644 src/server/LowPressureZone.Aspire.Migrations/LowPressureZone.Aspire.Migrations.csproj delete mode 100644 src/server/LowPressureZone.Aspire.Migrations/Program.cs delete mode 100644 src/server/LowPressureZone.Aspire.Migrations/Properties/launchSettings.json delete mode 100644 src/server/LowPressureZone.Aspire.Migrations/Worker.cs delete mode 100644 src/server/LowPressureZone.Aspire.ServiceDefaults/Extensions.cs delete mode 100644 src/server/LowPressureZone.Aspire.ServiceDefaults/LowPressureZone.Aspire.ServiceDefaults.csproj diff --git a/src/server/LowPressureZone.Aspire.Migrations/LowPressureZone.Aspire.Migrations.csproj b/src/server/LowPressureZone.Aspire.Migrations/LowPressureZone.Aspire.Migrations.csproj deleted file mode 100644 index e4942acc..00000000 --- a/src/server/LowPressureZone.Aspire.Migrations/LowPressureZone.Aspire.Migrations.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - net10.0 - enable - enable - dotnet-LowPressureZone.Aspire.Migrations-a468d0c2-64c4-4125-83da-933d9a53687d - - - - - - - - - - - - - - diff --git a/src/server/LowPressureZone.Aspire.Migrations/Program.cs b/src/server/LowPressureZone.Aspire.Migrations/Program.cs deleted file mode 100644 index 3c183974..00000000 --- a/src/server/LowPressureZone.Aspire.Migrations/Program.cs +++ /dev/null @@ -1,22 +0,0 @@ -using LowPressureZone.Aspire.Migrations; -using LowPressureZone.Aspire.ServiceDefaults; -using LowPressureZone.Domain; -using LowPressureZone.Domain.Extensions; -using LowPressureZone.Identity; -using LowPressureZone.Identity.Extensions; - -var builder = Host.CreateApplicationBuilder(args); - -builder.AddServiceDefaults(); -builder.Services.AddHostedService(); - -builder.Services - .AddOpenTelemetry() - .WithTracing(tracing => tracing.AddSource(Worker.ActivitySourceName)); - -builder.AddNpgsqlDbContext("Data", configureDbContextOptions: config => config.ConfigureDomainSeeding()); -builder.AddNpgsqlDbContext("Identity", - configureDbContextOptions: config => config.ConfigureIdentitySeeding()); - -var host = builder.Build(); -host.Run(); \ No newline at end of file diff --git a/src/server/LowPressureZone.Aspire.Migrations/Properties/launchSettings.json b/src/server/LowPressureZone.Aspire.Migrations/Properties/launchSettings.json deleted file mode 100644 index 70c5eb37..00000000 --- a/src/server/LowPressureZone.Aspire.Migrations/Properties/launchSettings.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "profiles": { - "LowPressureZone.Aspire.Migrations": { - "commandName": "Project", - "dotnetRunMessages": true, - "environmentVariables": { - "DOTNET_ENVIRONMENT": "Development" - } - } - } -} diff --git a/src/server/LowPressureZone.Aspire.Migrations/Worker.cs b/src/server/LowPressureZone.Aspire.Migrations/Worker.cs deleted file mode 100644 index 28e444e2..00000000 --- a/src/server/LowPressureZone.Aspire.Migrations/Worker.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Diagnostics; -using LowPressureZone.Domain; -using LowPressureZone.Identity; -using Microsoft.EntityFrameworkCore; - -namespace LowPressureZone.Aspire.Migrations; - -public sealed class Worker( - IServiceProvider serviceProvider, - IHostApplicationLifetime hostApplicationLifetime) : BackgroundService -{ - public const string ActivitySourceName = "Migrations"; - private static readonly ActivitySource ActivitySource = new(ActivitySourceName); - - protected override async Task ExecuteAsync(CancellationToken cancellationToken) - { - using var activity = ActivitySource.StartActivity(nameof(Migrations), ActivityKind.Client); - using var scope = serviceProvider.CreateScope(); - - var dataContext = scope.ServiceProvider.GetRequiredService(); - var identityContext = scope.ServiceProvider.GetRequiredService(); - - await dataContext.Database.MigrateAsync(cancellationToken); - await identityContext.Database.MigrateAsync(cancellationToken); - - hostApplicationLifetime.StopApplication(); - } -} \ No newline at end of file diff --git a/src/server/LowPressureZone.Aspire.ServiceDefaults/Extensions.cs b/src/server/LowPressureZone.Aspire.ServiceDefaults/Extensions.cs deleted file mode 100644 index 0ef9897e..00000000 --- a/src/server/LowPressureZone.Aspire.ServiceDefaults/Extensions.cs +++ /dev/null @@ -1,132 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using OpenTelemetry; -using OpenTelemetry.Metrics; -using OpenTelemetry.Trace; - -namespace LowPressureZone.Aspire.ServiceDefaults; - -// Adds common Aspire services: service discovery, resilience, health checks, and OpenTelemetry. -// This project should be referenced by each service project in your solution. -// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults -public static class Extensions -{ - private const string HealthEndpointPath = "/health"; - private const string AlivenessEndpointPath = "/alive"; - - public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder - { - builder.ConfigureOpenTelemetry(); - - builder.AddDefaultHealthChecks(); - - builder.Services.AddServiceDiscovery(); - - builder.Services.ConfigureHttpClientDefaults(http => - { - // Turn on resilience by default - http.AddStandardResilienceHandler(); - - // Turn on service discovery by default - http.AddServiceDiscovery(); - }); - - // Uncomment the following to restrict the allowed schemes for service discovery. - // builder.Services.Configure(options => - // { - // options.AllowedSchemes = ["https"]; - // }); - - return builder; - } - - public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) - where TBuilder : IHostApplicationBuilder - { - builder.Logging.AddOpenTelemetry(logging => - { - logging.IncludeFormattedMessage = true; - logging.IncludeScopes = true; - }); - - builder.Services.AddOpenTelemetry() - .WithMetrics(metrics => - { - metrics.AddAspNetCoreInstrumentation() - .AddHttpClientInstrumentation() - .AddRuntimeInstrumentation(); - }) - .WithTracing(tracing => - { - tracing.AddSource(builder.Environment.ApplicationName) - .AddAspNetCoreInstrumentation(tracing => - // Exclude health check requests from tracing - tracing.Filter = context => - !context.Request.Path - .StartsWithSegments(HealthEndpointPath) - && !context.Request.Path - .StartsWithSegments(AlivenessEndpointPath) - ) - // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package) - //.AddGrpcClientInstrumentation() - .AddHttpClientInstrumentation(); - }); - - builder.AddOpenTelemetryExporters(); - - return builder; - } - - private static TBuilder AddOpenTelemetryExporters(this TBuilder builder) - where TBuilder : IHostApplicationBuilder - { - var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); - - if (useOtlpExporter) - { - builder.Services.AddOpenTelemetry().UseOtlpExporter(); - } - - // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package) - //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"])) - //{ - // builder.Services.AddOpenTelemetry() - // .UseAzureMonitor(); - //} - - return builder; - } - - public static TBuilder AddDefaultHealthChecks(this TBuilder builder) - where TBuilder : IHostApplicationBuilder - { - builder.Services.AddHealthChecks() - // Add a default liveness check to ensure app is responsive - .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); - - return builder; - } - - public static WebApplication MapDefaultEndpoints(this WebApplication app) - { - // Adding health checks endpoints to applications in non-development environments has security implications. - // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments. - if (app.Environment.IsDevelopment()) - { - // All health checks must pass for app to be considered ready to accept traffic after starting - app.MapHealthChecks(HealthEndpointPath); - - // Only health checks tagged with the "live" tag must pass for app to be considered alive - app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions - { - Predicate = r => r.Tags.Contains("live") - }); - } - - return app; - } -} \ No newline at end of file diff --git a/src/server/LowPressureZone.Aspire.ServiceDefaults/LowPressureZone.Aspire.ServiceDefaults.csproj b/src/server/LowPressureZone.Aspire.ServiceDefaults/LowPressureZone.Aspire.ServiceDefaults.csproj deleted file mode 100644 index 86d436a2..00000000 --- a/src/server/LowPressureZone.Aspire.ServiceDefaults/LowPressureZone.Aspire.ServiceDefaults.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - net10.0 - enable - enable - true - - - - - - - - - - - - - - - - - - From d4e869a9cb0ef7d3cc769fd5535e2602c43ab3c2 Mon Sep 17 00:00:00 2001 From: Colin Ledbetter Date: Wed, 10 Jun 2026 00:43:28 -0400 Subject: [PATCH 3/4] Add bitrate selectors --- .../.idea/dataSources.xml | 10 ++ .../.idea/db-forest-config.xml | 1 + src/client/src/api/resources/streamApi.ts | 11 +- .../src/components/controls/PlayButton.vue | 103 ++++++++++++++++-- src/client/src/stores/streamStore.ts | 20 +++- .../Stream/Status/StreamStatusMapper.cs | 4 +- .../Stream/Status/StreamStatusResponse.cs | 6 +- .../Models/Stream/Mount.cs | 3 + .../Models/Stream/StreamStatus.cs | 2 +- .../StreamStatus/AzuraCastStatusService.cs | 10 +- src/server/LowPressureZone.Aspire/AppHost.cs | 4 +- .../LowPressureZone.Aspire.csproj | 12 +- 12 files changed, 159 insertions(+), 27 deletions(-) create mode 100644 src/server/LowPressureZone.Api/Models/Stream/Mount.cs diff --git a/.idea/.idea.LowPressureZone/.idea/dataSources.xml b/.idea/.idea.LowPressureZone/.idea/dataSources.xml index 4037f86c..a035fdce 100644 --- a/.idea/.idea.LowPressureZone/.idea/dataSources.xml +++ b/.idea/.idea.LowPressureZone/.idea/dataSources.xml @@ -27,5 +27,15 @@ $ProjectFileDir$ + + postgresql + true + org.postgresql.Driver + jdbc:postgresql://localhost:42197/?password=h%213y%7D%21.SMK_f*f3P%7D%28A4pA&user=postgres + + + + $ProjectFileDir$ + \ No newline at end of file diff --git a/.idea/.idea.LowPressureZone/.idea/db-forest-config.xml b/.idea/.idea.LowPressureZone/.idea/db-forest-config.xml index 65b52708..e25b69ec 100644 --- a/.idea/.idea.LowPressureZone/.idea/db-forest-config.xml +++ b/.idea/.idea.LowPressureZone/.idea/db-forest-config.xml @@ -5,6 +5,7 @@ ---------------------------------------- 1:0:c2cbbeb1-54aa-4fdd-a3ef-620a35907436 2:0:cad2bb4e-3522-4abd-ac20-00177c1bbf8d + 3:0:082253da-dbdc-4d4f-b400-170624546f51 . diff --git a/src/client/src/api/resources/streamApi.ts b/src/client/src/api/resources/streamApi.ts index 33dfeec8..9232995b 100644 --- a/src/client/src/api/resources/streamApi.ts +++ b/src/client/src/api/resources/streamApi.ts @@ -14,10 +14,15 @@ export interface StreamStatusResponse { isStatusStale: boolean name: string | null type: string | null - listenUrl: string | null listenerCount: number startedAt: string | null durationSeconds: number | null + mounts: Mount[] +} + +export interface Mount { + name: string + url: string } export const defaultStreamStatus: StreamStatusResponse = { @@ -26,10 +31,10 @@ export const defaultStreamStatus: StreamStatusResponse = { isStatusStale: false, name: null, type: null, - listenUrl: null, listenerCount: 0, startedAt: null, - durationSeconds: null + durationSeconds: null, + mounts: [], } export interface ConnectionInformationResponse { diff --git a/src/client/src/components/controls/PlayButton.vue b/src/client/src/components/controls/PlayButton.vue index 834409ed..329266b1 100644 --- a/src/client/src/components/controls/PlayButton.vue +++ b/src/client/src/components/controls/PlayButton.vue @@ -31,9 +31,15 @@ rounded size="large" @click="toggleVolumeSlider"> - - - + + +
@@ -41,11 +47,17 @@ v-model.number="volumeSliderAmount" class="play-button__volume__slider" />
+
+ +