Reorganise Infrastructure/Services into feature namespaces

- Move registration marker interfaces to Registration/Abstractions
- Add feature folders with Abstractions subfolders: EffectiveConfig,
  Dnsmasq/Config, Dnsmasq/Hosts, Dnsmasq/Leases, Dnsmasq/Reload,
  Logs, Updates, UI/Settings, Common/Process
- Place interfaces in each feature's Abstractions namespace; align
  implementation namespaces to folder paths
- Update Program, extensions, controllers, hubs, helpers, components,
  and tests to use new namespaces
- Remove old flat Services/Abstractions and root-level service files
This commit is contained in:
2026-02-28 22:17:20 +10:00
parent f8754d8d6e
commit 2cfbaf000c
67 changed files with 133 additions and 93 deletions
@@ -1,7 +1,7 @@
using DnsmasqWebUI.Models.Config;
using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using DnsmasqWebUI.Infrastructure.Services;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
@@ -3,7 +3,7 @@
@using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig
@using DnsmasqWebUI.Models.Config
@using DnsmasqWebUI.Infrastructure.Helpers.Config
@using DnsmasqWebUI.Infrastructure.Services.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions
@inject IEffectiveConfigRenderFragmentRegistry RenderFragmentRegistry
@* Custom fragment renders only the value; we keep the row shell (label + value slot + badge) here for consistency. Pending value shown until save. *@
@@ -1,7 +1,7 @@
@namespace DnsmasqWebUI.Components.Dnsmasq.EffectiveConfig
@using DnsmasqWebUI.Models.Dnsmasq
@using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig
@using DnsmasqWebUI.Infrastructure.Services.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions
@if (ShowModal)
{
@@ -1,7 +1,7 @@
@namespace DnsmasqWebUI.Components.Dnsmasq.EffectiveConfig
@using DnsmasqWebUI.Models.Dnsmasq
@using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig
@using DnsmasqWebUI.Infrastructure.Services.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions
<div class="modal fade show" style="display: block;" tabindex="-1" role="dialog" aria-labelledby="ec-save-modal-title" aria-modal="true">
<div class="modal-dialog modal-dialog-scrollable" role="document">
@@ -2,7 +2,7 @@
@using DnsmasqWebUI.Models.Dnsmasq
@using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig
@using DnsmasqWebUI.Infrastructure.Helpers.Config
@using DnsmasqWebUI.Infrastructure.Services.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions
@inject IEffectiveConfigEditSession Session
@inject IJSRuntime JSRuntime
@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions;
namespace DnsmasqWebUI.Components.Dnsmasq.EffectiveConfig;
@@ -1,6 +1,6 @@
using DnsmasqWebUI.Extensions;
using DnsmasqWebUI.Models.Client;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.UI.Settings.Abstractions;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.JSInterop;
+9 -1
View File
@@ -10,7 +10,15 @@
@using DnsmasqWebUI.Extensions
@using DnsmasqWebUI.Models.Client
@using DnsmasqWebUI.Models.Client.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.Common.Process.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Hosts.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Leases.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Reload.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.Logs.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.UI.Settings.Abstractions
@using DnsmasqWebUI.Infrastructure.Services.Updates.Abstractions
@using DnsmasqWebUI.Components
@using DnsmasqWebUI.Components.Shared
@using DnsmasqWebUI.Components.Modals
@@ -1,4 +1,5 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Reload.Abstractions;
using DnsmasqWebUI.Models.Config;
using DnsmasqWebUI.Models.Contracts;
using DnsmasqWebUI.Models.Dnsmasq;
@@ -1,4 +1,5 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Reload.Abstractions;
using DnsmasqWebUI.Models.Dhcp;
using DnsmasqWebUI.Models.Dnsmasq;
using Microsoft.AspNetCore.Mvc;
@@ -1,4 +1,5 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Hosts.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Reload.Abstractions;
using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Models.Hosts;
using Microsoft.AspNetCore.Mvc;
@@ -1,4 +1,4 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Leases.Abstractions;
using DnsmasqWebUI.Models.Dhcp;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
@@ -1,4 +1,4 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Reload.Abstractions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
@@ -1,4 +1,5 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Common.Process.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
using DnsmasqWebUI.Models.Config;
using DnsmasqWebUI.Models.Contracts;
using DnsmasqWebUI.Models.Dnsmasq;
@@ -1,7 +1,7 @@
using System.Threading.Channels;
using DnsmasqWebUI.Infrastructure.Logging;
using DnsmasqWebUI.Infrastructure.Services;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Logs;
using DnsmasqWebUI.Infrastructure.Services.Logs.Abstractions;
using DnsmasqWebUI.Models.Config;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@@ -1,7 +1,7 @@
using System.Reflection;
using DnsmasqWebUI.Infrastructure.Client;
using DnsmasqWebUI.Infrastructure.Client.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
+1 -1
View File
@@ -1,4 +1,4 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Logs.Abstractions;
using Microsoft.AspNetCore.SignalR;
namespace DnsmasqWebUI.Hubs;
@@ -1,4 +1,4 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Reload.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Client.Abstractions;
@@ -1,6 +1,6 @@
using DnsmasqWebUI.Infrastructure.Client.Abstractions;
using DnsmasqWebUI.Infrastructure.Helpers.Http;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Reload.Abstractions;
using System.Net.Http.Json;
namespace DnsmasqWebUI.Infrastructure.Client;
@@ -1,5 +1,5 @@
using System.Net;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Client;
@@ -1,6 +1,6 @@
using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Helpers.Config;
@@ -1,6 +1,6 @@
using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Helpers.Config;
@@ -1,6 +1,6 @@
using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Helpers.Config;
@@ -1,5 +1,5 @@
using System.Threading.Channels;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Logs.Abstractions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
@@ -1,6 +1,7 @@
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Contracts;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Common.Process.Abstractions;
/// <summary>Runs a shell command with timeout and cancellation. Used for status, reload, status show, and logs commands.</summary>
public interface IProcessRunner : IApplicationScopedService
@@ -1,10 +1,10 @@
using System.Diagnostics;
using System.Text;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Common.Process.Abstractions;
using DnsmasqWebUI.Models.Contracts;
using Microsoft.Extensions.Logging;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Common.Process;
/// <summary>Runs shell commands via /bin/sh with async output capture and timeout. Used by StatusController and ReloadService.</summary>
public sealed class ProcessRunner : IProcessRunner
@@ -29,9 +29,9 @@ public sealed class ProcessRunner : IProcessRunner
var stdout = new StringBuilder();
var stderr = new StringBuilder();
using var process = new Process
using var process = new System.Diagnostics.Process
{
StartInfo = new ProcessStartInfo
StartInfo = new System.Diagnostics.ProcessStartInfo
{
FileName = "/bin/sh",
Arguments = "-c \"" + command.Replace("\"", "\\\"") + "\"",
@@ -1,6 +1,7 @@
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Contracts;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
/// <summary>
/// Singleton cache for the config set (main + conf-dir + managed file). Invalidates on file watchers, staleness, or manual Invalidate.
@@ -2,9 +2,10 @@ using DnsmasqWebUI.Models.Config;
using DnsmasqWebUI.Models.Contracts;
using DnsmasqWebUI.Models.Dhcp;
using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
/// <summary>Reads and writes the managed dnsmasq config file and DHCP hosts entries (the app-managed config and dhcp-host= lines).</summary>
public interface IDnsmasqConfigService : IApplicationScopedService
@@ -1,7 +1,8 @@
using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
/// <summary>Discovers the dnsmasq config set (main + conf-file/conf-dir) and the managed file path.</summary>
public interface IDnsmasqConfigSetService : IApplicationSingleton
@@ -5,10 +5,10 @@ using DnsmasqWebUI.Models.Dhcp;
using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using DnsmasqWebUI.Infrastructure.Parsers;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
using Microsoft.Extensions.Options;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config;
/// <summary>
/// Singleton cache for the config set (main + conf-dir + managed file). Reads all files once per refresh,
@@ -1,7 +1,7 @@
using System.Text;
using DnsmasqWebUI.Infrastructure.Helpers.Config;
using DnsmasqWebUI.Infrastructure.Parsers;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
using DnsmasqWebUI.Models.Config;
using DnsmasqWebUI.Models.Contracts;
using DnsmasqWebUI.Models.Dhcp;
@@ -9,7 +9,7 @@ using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using Microsoft.Extensions.Logging;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config;
public class DnsmasqConfigService : IDnsmasqConfigService
{
@@ -1,9 +1,9 @@
using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using DnsmasqWebUI.Models.Contracts;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config;
public class DnsmasqConfigSetService : IDnsmasqConfigSetService
{
@@ -1,13 +1,14 @@
using System.Text;
using DnsmasqWebUI.Infrastructure.Helpers.Config;
using DnsmasqWebUI.Infrastructure.Parsers;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Config;
using DnsmasqWebUI.Models.Dnsmasq;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config;
/// <summary>
/// Runs once at startup: ensures the managed file is included only by a conf-file= directive (never conf-dir=),
@@ -1,7 +1,8 @@
using DnsmasqWebUI.Models.Contracts;
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Hosts;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Hosts.Abstractions;
/// <summary>
/// Singleton cache for hosts: managed hosts file + read-only (system + addn-hosts). Invalidates on watchers, staleness, or Invalidate.
@@ -1,6 +1,7 @@
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Hosts;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Hosts.Abstractions;
/// <summary>Reads and writes the app-managed hosts file (the single hosts file the app edits).</summary>
public interface IHostsFileService : IApplicationScopedService
@@ -3,10 +3,11 @@ using DnsmasqWebUI.Models.Config;
using DnsmasqWebUI.Models.Contracts;
using DnsmasqWebUI.Models.Hosts;
using DnsmasqWebUI.Infrastructure.Parsers;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Hosts.Abstractions;
using Microsoft.Extensions.Options;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Hosts;
/// <summary>
/// Singleton cache for hosts: managed hosts file + read-only (system + addn-hosts). Invalidates on watchers (managed + system path), staleness, or Invalidate.
@@ -1,10 +1,11 @@
using DnsmasqWebUI.Infrastructure.Helpers.Config;
using DnsmasqWebUI.Infrastructure.Parsers;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Hosts.Abstractions;
using DnsmasqWebUI.Models.Hosts;
using Microsoft.Extensions.Logging;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Hosts;
public class HostsFileService : IHostsFileService
{
@@ -1,6 +1,7 @@
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Dhcp;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Leases.Abstractions;
/// <summary>
/// Singleton cache for the leases file; invalidates when the file changes (e.g. via file watcher).
@@ -1,6 +1,7 @@
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Dhcp;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Leases.Abstractions;
/// <summary>Reads the dnsmasq DHCP leases file (path from effective config).</summary>
public interface ILeasesFileService : IApplicationScopedService
@@ -1,9 +1,10 @@
using System.Text;
using DnsmasqWebUI.Models.Dhcp;
using DnsmasqWebUI.Infrastructure.Parsers;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Leases.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Leases;
/// <summary>
/// Singleton cache for the leases file with a <see cref="FileSystemWatcher"/> so we re-read only when the file changes.
@@ -1,8 +1,8 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Leases.Abstractions;
using DnsmasqWebUI.Models.Dhcp;
using Microsoft.Extensions.Logging;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Leases;
public class LeasesFileService : ILeasesFileService
{
@@ -1,4 +1,6 @@
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Reload.Abstractions;
/// <summary>Runs the configured dnsmasq reload command (e.g. systemctl reload dnsmasq).</summary>
public interface IReloadService : IApplicationScopedService
@@ -1,9 +1,10 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Common.Process.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Reload.Abstractions;
using DnsmasqWebUI.Models.Config;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Reload;
public class ReloadService : IReloadService
{
@@ -1,6 +1,7 @@
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions;
/// <summary>
/// Scoped orchestrator for effective-config edit lifecycle: edit mode, active field, pending changes, and apply.
@@ -1,9 +1,10 @@
using Microsoft.AspNetCore.Components;
using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions;
/// <summary>
/// Lookup for custom display fragments per effective-config field (section + option).
@@ -1,7 +1,8 @@
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.EffectiveConfig;
public sealed class EffectiveConfigEditSession : IEffectiveConfigEditSession
{
@@ -3,10 +3,10 @@ using DnsmasqWebUI.Infrastructure.Helpers.Config;
using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions;
using DnsmasqWebUI.Components.Dnsmasq.EffectiveConfig.CustomDisplays;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.EffectiveConfig;
/// <summary>
/// Maps (sectionId, optionName) to custom effective-config value display component types and descriptor factories.
@@ -1,4 +1,4 @@
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Logs.Abstractions;
/// <summary>
/// Ring buffer of recent app log lines. Filled by ILoggerProvider, drained for SignalR push.
@@ -1,4 +1,4 @@
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Logs.Abstractions;
/// <summary>
/// Runs LogsCommand, diffs output, chunks by lines, and pushes via SignalR.
@@ -1,7 +1,9 @@
namespace DnsmasqWebUI.Infrastructure.Services;
using DnsmasqWebUI.Infrastructure.Services.Logs.Abstractions;
/// <inheritdoc cref="Abstractions.IAppLogsBuffer" />
public sealed class AppLogsBuffer : Abstractions.IAppLogsBuffer
namespace DnsmasqWebUI.Infrastructure.Services.Logs;
/// <inheritdoc cref="IAppLogsBuffer" />
public sealed class AppLogsBuffer : IAppLogsBuffer
{
private const int MaxLines = 1000;
private readonly List<string> _lines = [];
@@ -1,9 +1,10 @@
using System.Threading.Channels;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Logs.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Logs;
/// <summary>
/// Listens for signals from AppLogsLoggerProvider; drains pending app logs and pushes via LogsService.
@@ -1,12 +1,12 @@
using System.Reflection;
using System.Runtime.InteropServices;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Config;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Logs;
/// <summary>Logs application start and stop with runtime and configuration context.</summary>
public sealed class ApplicationLifecycleLoggingHostedService : IApplicationHostedService
@@ -1,9 +1,11 @@
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Config.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Logs.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Logs;
/// <summary>
/// When LogsPath is set in effective config, watches that file and triggers LogsService push on change.
@@ -1,5 +1,6 @@
using System.Text;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Common.Process.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Logs.Abstractions;
using DnsmasqWebUI.Models.Config;
using DnsmasqWebUI.Models.Logs;
using Microsoft.AspNetCore.SignalR;
@@ -7,7 +8,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Logs;
/// <summary>
/// Runs LogsCommand, diffs against cache, chunks by lines, and pushes via SignalR.
@@ -1,6 +1,6 @@
using Microsoft.Extensions.Hosting;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
/// <summary>
/// Marker interface for application hosted services that are registered via assembly scanning.
@@ -1,4 +1,4 @@
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
/// <summary>
/// Marker for types that are registered as their own concrete type with scoped lifetime.
@@ -1,4 +1,4 @@
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
/// <summary>
/// Marker interface for application services that are registered as scoped.
@@ -1,4 +1,4 @@
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
/// <summary>
/// Marker interface for application services that are registered as singleton.
@@ -1,6 +1,7 @@
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Models.Client;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.UI.Settings.Abstractions;
/// <summary>
/// Loads and saves client-side preferences (e.g. polling intervals) to browser local storage.
@@ -1,6 +1,6 @@
using DnsmasqWebUI.Models.Client;
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.UI.Settings.Abstractions;
/// <summary>
/// Scoped service to open the app-level settings modal from anywhere (e.g. NavMenu, pages).
@@ -1,10 +1,10 @@
using System.Text.Json;
using DnsmasqWebUI.Extensions;
using DnsmasqWebUI.Models.Client;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.UI.Settings.Abstractions;
using Microsoft.JSInterop;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.UI.Settings;
/// <summary>
/// Loads and saves client-side settings to browser local storage via JS interop.
@@ -1,7 +1,7 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.UI.Settings.Abstractions;
using DnsmasqWebUI.Models.Client;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.UI.Settings;
/// <inheritdoc cref="ISettingsModalService" />
public sealed class SettingsModalService : ISettingsModalService
@@ -1,4 +1,4 @@
namespace DnsmasqWebUI.Infrastructure.Services.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Services.Updates.Abstractions;
/// <summary>
/// Service that checks GitHub for a newer release. Runs on a configurable interval (hosted service)
@@ -1,8 +1,9 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Registration.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Updates.Abstractions;
using DnsmasqWebUI.Models.Config;
using Microsoft.Extensions.Options;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Updates;
/// <summary>
/// Runs an update check shortly after startup, then periodically at the configured interval.
@@ -1,11 +1,11 @@
using System.Reflection;
using System.Text.Json;
using DnsmasqWebUI.Extensions;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Updates.Abstractions;
using DnsmasqWebUI.Models.Config;
using Microsoft.Extensions.Options;
namespace DnsmasqWebUI.Infrastructure.Services;
namespace DnsmasqWebUI.Infrastructure.Services.Updates;
public sealed class UpdateCheckService : IUpdateCheckService
{
@@ -1,4 +1,4 @@
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Reload.Abstractions;
namespace DnsmasqWebUI.Models.Dnsmasq;
+4 -2
View File
@@ -3,8 +3,10 @@ using DnsmasqWebUI.Hubs;
using DnsmasqWebUI.Models.Config;
using DnsmasqWebUI.Extensions;
using DnsmasqWebUI.Infrastructure.Helpers.Http;
using DnsmasqWebUI.Infrastructure.Services;
using DnsmasqWebUI.Infrastructure.Services.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.UI.Settings;
using DnsmasqWebUI.Infrastructure.Services.UI.Settings.Abstractions;
using DnsmasqWebUI.Infrastructure.Services.Updates;
using DnsmasqWebUI.Infrastructure.Services.Updates.Abstractions;
using Microsoft.Extensions.Options;
// When not in Development, use the app's directory (not CWD) so static assets work when run via symlink or from any CWD.