diff --git a/DevProxy.Plugins/Mocking/CrudApiPlugin.cs b/DevProxy.Plugins/Mocking/CrudApiPlugin.cs index 3ce73610..6b711061 100644 --- a/DevProxy.Plugins/Mocking/CrudApiPlugin.cs +++ b/DevProxy.Plugins/Mocking/CrudApiPlugin.cs @@ -19,6 +19,7 @@ using System.Security.Claims; using System.Text.Json.Serialization; using System.Text.RegularExpressions; +using System.Web; using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Models; @@ -246,6 +247,7 @@ private async Task SetupOpenIdConnectConfigurationAsync() }); var requestUrlWithoutQuery = request.RequestUri.GetLeftPart(UriPartial.Path); + var requestQuery = request.RequestUri.Query; var parameters = new Dictionary(); var action = Configuration.Actions.FirstOrDefault(action => { @@ -256,33 +258,85 @@ private async Task SetupOpenIdConnectConfigurationAsync() var absoluteActionUrl = (Configuration.BaseUrl + action.Url).Replace("//", "/", 8); - if (absoluteActionUrl == requestUrlWithoutQuery) + // split action URL into path and query parts + string actionPath; + string? actionQuery = null; + var queryIndex = absoluteActionUrl.IndexOf('?', StringComparison.OrdinalIgnoreCase); + if (queryIndex >= 0) { - return true; + actionPath = absoluteActionUrl[..queryIndex]; + actionQuery = absoluteActionUrl[queryIndex..]; + } + else + { + actionPath = absoluteActionUrl; } - // check if the action contains parameters - // if it doesn't, it's not a match for the current request for sure - if (!absoluteActionUrl.Contains('{', StringComparison.OrdinalIgnoreCase)) + // match the path part + var pathMatched = false; + if (actionPath == requestUrlWithoutQuery) { - return false; + pathMatched = true; + } + else if (actionPath.Contains('{', StringComparison.OrdinalIgnoreCase)) + { + var pathRegex = Regex.Replace(Regex.Escape(actionPath).Replace("\\{", "{", StringComparison.OrdinalIgnoreCase), "({[^}]+})", parameterMatchEvaluator); + var pathMatch = Regex.Match(requestUrlWithoutQuery, pathRegex); + if (pathMatch.Success) + { + pathMatched = true; + foreach (var groupName in pathMatch.Groups.Keys) + { + if (groupName == "0") + { + continue; + } + parameters[groupName] = Uri.UnescapeDataString(pathMatch.Groups[groupName].Value); + } + } } - // convert parameters into named regex groups - var urlRegex = Regex.Replace(Regex.Escape(absoluteActionUrl).Replace("\\{", "{", StringComparison.OrdinalIgnoreCase), "({[^}]+})", parameterMatchEvaluator); - var match = Regex.Match(requestUrlWithoutQuery, urlRegex); - if (!match.Success) + if (!pathMatched) { return false; } - foreach (var groupName in match.Groups.Keys) + // if the action has no query string definition, it's a match + if (string.IsNullOrEmpty(actionQuery)) + { + return true; + } + + // match query string parameters individually (order-independent) + var actionQueryParams = HttpUtility.ParseQueryString(actionQuery.TrimStart('?')); + var requestQueryParams = HttpUtility.ParseQueryString(requestQuery.TrimStart('?')); + + foreach (string? key in actionQueryParams.AllKeys) { - if (groupName == "0") + if (key is null) { continue; } - parameters.Add(groupName, Uri.UnescapeDataString(match.Groups[groupName].Value)); + + var actionValue = actionQueryParams[key] ?? string.Empty; + var requestValue = requestQueryParams[key]; + + if (requestValue is null) + { + return false; + } + + // check if the action value is a parameter pattern like {param} + var paramMatch = Regex.Match(actionValue, "^{([^}]+)}$"); + if (paramMatch.Success) + { + var paramName = paramMatch.Groups[1].Value.Replace('-', '_'); + parameters[paramName] = Uri.UnescapeDataString(requestValue); + } + else if (!string.Equals(actionValue, requestValue, StringComparison.OrdinalIgnoreCase)) + { + return false; + } } return true; }); diff --git a/DevProxy/packages.lock.json b/DevProxy/packages.lock.json index 441046d2..288d91d3 100644 --- a/DevProxy/packages.lock.json +++ b/DevProxy/packages.lock.json @@ -18,7 +18,10 @@ "contentHash": "HH9/nnRF/YmRrc3hUlgXjMBYKH5kFmd5UWC81l9U0ySQhwHTcgvDPSewB8DyQHzFJzNGgG7VFK6ynC6+XQz9WA==", "dependencies": { "Microsoft.EntityFrameworkCore.Sqlite.Core": "10.0.9", + "Microsoft.Extensions.Caching.Memory": "10.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.9", "Microsoft.Extensions.DependencyModel": "10.0.9", + "Microsoft.Extensions.Logging": "10.0.9", "SQLitePCLRaw.bundle_e_sqlite3": "2.1.11", "SQLitePCLRaw.core": "2.1.11" } @@ -56,6 +59,8 @@ "resolved": "1.16.0", "contentHash": "nE/Px3MUvQC8c0UG0DOP5OJE7vMtiMaPYi/6TkSS/o/O0s/oPq+8WaPYTVEPzb7lwu/QyLgknc+sFm2FjPXe2A==", "dependencies": { + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0", + "Microsoft.Extensions.Logging.Configuration": "10.0.0", "OpenTelemetry.Api.ProviderBuilderExtensions": "1.16.0" } }, @@ -90,7 +95,9 @@ "resolved": "0.1.5", "contentHash": "HiICGm0e44+i4aVHpLn+aphmSC2eQnDvlTttw1rE0hntOZKoLGRy37sydqqbRP1ZokMf3Mt0GEgSWxDwnucKGg==", "dependencies": { - "BouncyCastle.Cryptography": "2.4.0" + "BouncyCastle.Cryptography": "2.4.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.1", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "Azure.Core": { @@ -99,6 +106,8 @@ "contentHash": "x9c/toFMOtRrlTdFuE7rlGCVAduQzWVfKmLz5juj41zJAXEhYD5hluiUyyAEzJ6OxpBnKtiaBztzwpZITAVjtg==", "dependencies": { "Microsoft.Bcl.AsyncInterfaces": "10.0.3", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.3", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.3", "Microsoft.Identity.Client": "4.83.1", "Microsoft.Identity.Client.Extensions.Msal": "4.83.1", "System.ClientModel": "1.10.0", @@ -139,7 +148,9 @@ "contentHash": "tu85SRzOT021V7EQlViCiAE7TqldVn469Y6lt5TEn/+XC4/MeNCHgMRSxqYuWqvF4zAQZUhCmtNEZuM3ss4LeA==", "dependencies": { "Microsoft.EntityFrameworkCore.Abstractions": "10.0.9", - "Microsoft.EntityFrameworkCore.Analyzers": "10.0.9" + "Microsoft.EntityFrameworkCore.Analyzers": "10.0.9", + "Microsoft.Extensions.Caching.Memory": "10.0.9", + "Microsoft.Extensions.Logging": "10.0.9" } }, "Microsoft.EntityFrameworkCore.Abstractions": { @@ -157,7 +168,10 @@ "resolved": "10.0.9", "contentHash": "dEoyYKgiaZHHgOFm1WMWm1sFEsEuhPWufX4L9PekKtqd/RaIcPjkCjvbrVvJtApErb5wPSJhYvnTlxhH+p9h2g==", "dependencies": { - "Microsoft.EntityFrameworkCore": "10.0.9" + "Microsoft.EntityFrameworkCore": "10.0.9", + "Microsoft.Extensions.Caching.Memory": "10.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.9", + "Microsoft.Extensions.Logging": "10.0.9" } }, "Microsoft.EntityFrameworkCore.Sqlite.Core": { @@ -167,21 +181,211 @@ "dependencies": { "Microsoft.Data.Sqlite.Core": "10.0.9", "Microsoft.EntityFrameworkCore.Relational": "10.0.9", + "Microsoft.Extensions.Caching.Memory": "10.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.9", "Microsoft.Extensions.DependencyModel": "10.0.9", + "Microsoft.Extensions.Logging": "10.0.9", "SQLitePCLRaw.core": "2.1.11" } }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "5fGxcw2vuYp8s0wio9H1ECiuk4iKSdTIlNuigdLIrkhg+5XAwgFVDB/5Ots3pfN/QhABLYXutA79JFtnUKDSHA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.9" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "G9mregdatGWMCQWeCw012LDeJVP7G/XIxH8Ddbjc8bD1//dA+8VVQdcRE9jI1moyoJxSSZhHITUnNQ8FUDl5+Q==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "10.0.9", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.9", + "Microsoft.Extensions.Logging.Abstractions": "10.0.9", + "Microsoft.Extensions.Options": "10.0.9", + "Microsoft.Extensions.Primitives": "10.0.9" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "woZsWLhOQsASuxbmgiZJqiGUBNo3IjRdXC92xt8rRokza+P6/nIsnzq7sm9Or6ZYcRl2kL1ufj8HVzp1QlPTXw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.9", + "Microsoft.Extensions.Primitives": "10.0.9" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "qGhRPd3VxfLV9UqatVOiD9mAeUbj2KiMwGFYC5uXlzExiZQoe4X/hdmzGIU7BQjNLTqCnnbTHVyBglG3668/HA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.9" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "Tp/+LPb70RyjjtLg9m5C959eP4KrUpJHThZfAegZVpsfmGvzfuNkuYbI/ft+LvXhMSyUcAeOPaN6rzTccwnZAg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.9" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "NgLB9cYnIb0/djSDcnqo4GIGGWooxGmr/gCUe3/CRXcKqLizOFui8MyW4EVkTB/KNJL+oXdMXnD6ZRm3Y+qkrQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.9", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.9", + "Microsoft.Extensions.FileProviders.Physical": "10.0.9", + "Microsoft.Extensions.Primitives": "10.0.9" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "LiFKJgc9jZEW+7RhcSfsvCwoikt1lDdOqOn+whZC5zVHyg/gExftHl2QPtmfiHsEdDNg+Y+BDr6835tOfj8Y7A==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.9", + "Microsoft.Extensions.Configuration.FileExtensions": "10.0.9", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.9" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "NijozhERJDIaJ4k5TSMy1jOi0cSC2HfkvRD/Sl+kGSSKgVbFnF4GxgtMN/MrzHB8D1JxIrD4xSer9Blh9v3axQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.9" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "g41l/30G3K4B/d/L8kjux0+30e27c8D0FVQ/PFCpbekgfDpj9mnDhieP67EqXWvl1EWNeZh2rpR4F5B/jcDOHA==" + }, "Microsoft.Extensions.DependencyModel": { "type": "Transitive", "resolved": "10.0.9", "contentHash": "SCDTQ6HubnRvTUjR7dgMKHZvNoCb03t44ttHL8trlFTGgfDteWn/0nRdOxDhcI+lTWhKgd/flCVJEtAOPhSLNg==" }, + "Microsoft.Extensions.Diagnostics.Abstractions": { + "type": "Transitive", + "resolved": "10.0.3", + "contentHash": "mQiTzAj7PIJ2A9YXR5QhgulS1fTWhmQc3ckd1Mrf3hKW07d03fBDqx8vVaFw+cRTebDOeB6pNqdWdnRxsi1hBA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.3", + "Microsoft.Extensions.Options": "10.0.3" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "Oxn4vqDk+EwceTMpZxVm7L/UZEAM1qIQlNP1+7tBZckD+P4SKrm/5X4gMTPCTdpnau/xY8Sb4/0d6onomSg4ZA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "10.0.9" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "zm8WVod4swgprGrkxkuSILlbXqdDRqF+3y6U0I7jlmj4PMyKN6d8pzXZHUn5lr/gZVULzk/+FeTYlTupt6akpg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.9", + "Microsoft.Extensions.FileSystemGlobbing": "10.0.9", + "Microsoft.Extensions.Primitives": "10.0.9" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "mvRf9qOH/LslWIee/h+lsElnoUyKotEwoPL31soqScmO/eoxObaTCLCdx2DdqPdRi9LnB+7qKZ49jfyrLZuc+w==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "10.0.3", + "contentHash": "GdMpC10Jf6poxSvUJ4lgYpJ5F/kJeaAoJmrPufjBoPYyCTKKY5Dyl0rZA+LBNvFqTq1cZa/lhlptlUhNvU6xrg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.3", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.3", + "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.3", + "Microsoft.Extensions.FileProviders.Abstractions": "10.0.3", + "Microsoft.Extensions.Logging.Abstractions": "10.0.3" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "N7Gm9SjugYjmmnhwbBKC9DFqGqjfJvh6YfOJgtwh0AW0Xpok3dIVors1ik050XmUxKAgAc7nNngDIJyFb06K2g==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "10.0.9", + "Microsoft.Extensions.Logging.Abstractions": "10.0.9", + "Microsoft.Extensions.Options": "10.0.9" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "9S/DFt4cohlMPpzIxjG6kk0L8MuN2vDm9pbMCulxtJzzk82oJHVLBd8vuQxaPskaYQwKqmFmbannf5eoChgjYg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.9" + } + }, + "Microsoft.Extensions.Logging.Configuration": { + "type": "Transitive", + "resolved": "10.0.0", + "contentHash": "j8zcwhS6bYB6FEfaY3nYSgHdpiL2T+/V3xjpHtslVAegyI1JUbB9yAt/BFdvZdsNbY0Udm4xFtvfT/hUwcOOOg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "10.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0", + "Microsoft.Extensions.Configuration.Binder": "10.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0", + "Microsoft.Extensions.Logging": "10.0.0", + "Microsoft.Extensions.Logging.Abstractions": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.0" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "hyNdX4c2UwkRkzb9byw0H2DQkRzwBM3mzY2sCM9egwzTyg8dvQJmp5noQHGEaaCORQrNK3DD2gREBsc2DlXS4A==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.9", + "Microsoft.Extensions.Primitives": "10.0.9" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "10.0.0", + "contentHash": "tL9cSl3maS5FPzp/3MtlZI21ExWhni0nnUCF8HY4npTsINw45n9SNDbkKXBMtFyUFGSsQep25fHIDN4f/Vp3AQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.0", + "Microsoft.Extensions.Configuration.Binder": "10.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0", + "Microsoft.Extensions.Options": "10.0.0", + "Microsoft.Extensions.Primitives": "10.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "10.0.9", + "contentHash": "fmEbAUFsaIKirgLt/lYhuFRBwhcSJN31jjHgCdbQxJiWOum6EdLjkbgGuukSP9z/a+9LibaxII/kF+GwOXgC4g==" + }, "Microsoft.Identity.Client": { "type": "Transitive", "resolved": "4.83.1", "contentHash": "jOLIrZ3cynoqHLLO1cXplFFabrhrMEYs/EuKHvmCyrOm1axqiVFT6nCSnHxk7w5+d2BeQfCdM12Yf/0X7OeS1g==", "dependencies": { - "Microsoft.IdentityModel.Abstractions": "8.14.0" + "Microsoft.IdentityModel.Abstractions": "8.14.0", + "System.Diagnostics.DiagnosticSource": "6.0.1", + "System.ValueTuple": "4.5.0" } }, "Microsoft.Identity.Client.Extensions.Msal": { @@ -228,13 +432,17 @@ "contentHash": "KDiuSLXud2AFVNAOottd8ztVysfPeHyr4r8gofU3/VKUXlI7oytzGTnPsNJ/B3nui17rgz8wAdWNJOtzPjkUxw==", "dependencies": { "Microsoft.Bcl.Cryptography": "10.0.2", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", "Microsoft.IdentityModel.Logging": "8.19.1" } }, "Microsoft.OpenApi": { "type": "Transitive", "resolved": "3.7.0", - "contentHash": "7Ld/wUsxSEKBjAk8nPZ13qkju5kNoh20gf0JHPeHrK41tMZRpIq9amXFAOHncicjg0U5M035I+6/z3cBsYBHfg==" + "contentHash": "7Ld/wUsxSEKBjAk8nPZ13qkju5kNoh20gf0JHPeHrK41tMZRpIq9amXFAOHncicjg0U5M035I+6/z3cBsYBHfg==", + "dependencies": { + "System.Text.Json": "8.0.5" + } }, "Microsoft.OpenApi.YamlReader": { "type": "Transitive", @@ -242,7 +450,8 @@ "contentHash": "+KSHfoEiXDFmCeIG6T5xAuYNFulwfxxBh4AJOY6dvGrDeFVV4eL4/xP/RNEaFYvcSZpLkj3ZoQ8Vn3vtUViu5g==", "dependencies": { "Microsoft.OpenApi": "3.7.0", - "SharpYaml": "2.1.4" + "SharpYaml": "2.1.4", + "System.Text.Json": "8.0.5" } }, "Microsoft.VisualStudio.Threading.Analyzers": { @@ -281,6 +490,7 @@ "resolved": "1.16.0", "contentHash": "hZwaHAkXvUNn9+cS+vEvYBgIrIQOQRz2cIRUODZ5gxHsDsLeNCueLgZFkybopjE0jUhLut6lm5eL3LTqbW0hMg==", "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0", "OpenTelemetry.Api": "1.16.0" } }, @@ -306,7 +516,10 @@ "SQLitePCLRaw.core": { "type": "Transitive", "resolved": "2.1.11", - "contentHash": "PK0GLFkfhZzLQeR3PJf71FmhtHox+U3vcY6ZtswoMjrefkB9k6ErNJEnwXqc5KgXDSjige2XXrezqS39gkpQKA==" + "contentHash": "PK0GLFkfhZzLQeR3PJf71FmhtHox+U3vcY6ZtswoMjrefkB9k6ErNJEnwXqc5KgXDSjige2XXrezqS39gkpQKA==", + "dependencies": { + "System.Memory": "4.5.3" + } }, "SQLitePCLRaw.lib.e_sqlite3": { "type": "Transitive", @@ -326,19 +539,50 @@ "resolved": "1.10.0", "contentHash": "lBEWs54F5Y5pZ9hC+8z4S/X76957ex+DPk7WecRHlbIHtrPfbRMMlOgI3iDn4Jpb3bSxvBnKaaHoD59auFjlBA==", "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "10.0.3", + "Microsoft.Extensions.Hosting.Abstractions": "10.0.3", + "Microsoft.Extensions.Logging.Abstractions": "10.0.3", "System.Memory.Data": "10.0.3" } }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.3", + "contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA==" + }, "System.Memory.Data": { "type": "Transitive", "resolved": "10.0.3", "contentHash": "MaGhRfGunmrj/nHjtsi9XkhlYJ/ERGWrbA+BiSKNtGnAjc9XlG5EhAvak6VRcX5LYzPF6pBO8nJ613dTgzabig==" }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, "System.Security.Cryptography.ProtectedData": { "type": "Transitive", "resolved": "4.5.0", "contentHash": "wLBKzFnDCxP12VL9ANydSYhk59fC4cvOr9ypYQLPnAj48NQIhqnjdD2yhP8yEKyBJEjERWS9DisKL7rX5eU25Q==" }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "8.0.5", + "contentHash": "0f1B50Ss7rqxXiaBJyzUu9bWFOO2/zSlifZ/UNMdiIpDYe4cY4LQQicP4nirK1OS31I43rn062UIJ1Q9bpmHpg==" + }, + "System.ValueTuple": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" + }, "YamlDotNet": { "type": "Transitive", "resolved": "18.1.0", @@ -349,6 +593,11 @@ "dependencies": { "Markdig": "[1.3.2, )", "Microsoft.EntityFrameworkCore.Sqlite": "[10.0.9, )", + "Microsoft.Extensions.Configuration": "[10.0.9, )", + "Microsoft.Extensions.Configuration.Binder": "[10.0.9, )", + "Microsoft.Extensions.Configuration.Json": "[10.0.9, )", + "Microsoft.Extensions.FileSystemGlobbing": "[10.0.9, )", + "Microsoft.Extensions.Logging.Abstractions": "[10.0.9, )", "Microsoft.OpenApi": "[3.7.0, )", "Microsoft.OpenApi.YamlReader": "[3.7.0, )", "Newtonsoft.Json.Schema": "[4.0.1, )",