diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a0313a9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,225 @@ +root = true + +[*.js] +indent_style = space +indent_size = 4 +insert_final_newline = true + +[*.json] +indent_style = space +indent_size = 2 +insert_final_newline = true + +[*.yaml] +indent_style = space +indent_size = 2 +insert_final_newline = true + +# C# files +[*.cs] +insert_final_newline = true + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 + +# New line preferences +end_of_line = lf + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = false +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false:silent +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_property = false:silent + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent + +# Expression-level preferences +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_object_initializer = true:suggestion +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion + +# Field preferences +dotnet_style_readonly_field = true:suggestion + +# Parameter preferences +dotnet_code_quality_unused_parameters = all:suggestion + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = false:silent +csharp_style_var_for_built_in_types = false:silent +csharp_style_var_when_type_is_apparent = false:silent + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_prefer_switch_expression = true:suggestion + +# Null-checking preferences +csharp_style_conditional_delegate_call = true:suggestion + +# Modifier preferences +csharp_prefer_static_local_function = true:suggestion +csharp_preferred_modifier_order = public, private, protected, internal, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, volatile, async:silent + +# Code-block preferences +csharp_prefer_braces = true:silent +csharp_prefer_simple_using_statement = true:suggestion + +# Expression-level preferences +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent + +# 'using' directive preferences +csharp_using_directive_placement = inside_namespace:silent + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +# C# files +[*.csproj] +insert_final_newline = true + diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 659168f..4da61d5 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -1,4 +1,4 @@ -name: .NET +name: CI on: push: @@ -12,14 +12,12 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Setup .NET - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.x - - name: Restore dependencies - run: dotnet restore - - name: Build - run: dotnet build --no-restore - - name: Test - run: dotnet test --no-build --verbosity normal + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test --no-restore --no-build --verbosity normal diff --git a/EnvironmentFile.sln b/EnvironmentFile.sln index 5ba2de6..7ab2835 100644 --- a/EnvironmentFile.sln +++ b/EnvironmentFile.sln @@ -7,6 +7,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnvironmentFile.UnitTests", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnvironmentFile", "src\EnvironmentFile\EnvironmentFile.csproj", "{170471BC-C280-4389-BA2A-C4A09343CA82}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "solution-folder", "solution-folder", "{1BC9669D-331F-4C0F-90BA-E7AC64E6699A}" + ProjectSection(SolutionItems) = preProject + .github\workflows\dotnet.yml = .github\workflows\dotnet.yml + README.md = README.md + LICENSE = LICENSE + RELEASE_NOTES.md = RELEASE_NOTES.md + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/LICENSE b/LICENSE index 81c7dee..3be88af 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ The MIT License -Copyright (c) 2018 griffo.io +Copyright (c) 2018 https://github.com/dariogriffo Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 93d62c8..612a6e1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -[![NuGet](https://img.shields.io/nuget/v/Configuration.Extensions.EnvironmentFile.svg?style=flat)](https://www.nuget.org/packages/Configuration.Extensions.EnvironmentFile/) -[![GitHub license](https://img.shields.io/github/license/griffo-io/Configuration.Extensions.EnvironmentFile.svg)](https://raw.githubusercontent.com/griffo-io/Configuration.Extensions.EnvironmentFile/master/LICENSE) -[![N|Solid](https://avatars2.githubusercontent.com/u/39886363?s=200&v=4)](https://github.com/griffo-io/Configuration.Extensions.EnvironmentFile) +[![NuGet Info](https://img.shields.io/nuget/dt/Configuration.Extensions.EnvironmentFile)](https://www.nuget.org/packages/Configuration.Extensions.EnvironmentFile/) +![GitHub License](https://img.shields.io/github/license/dariogriffo/Configuration.Extensions.EnvironmentFile) +![CI](https://github.com/dariogriffo/Configuration.Extensions.EnvironmentFile/workflows/CI/badge.svg) # Configuration.Extensions.EnvironmentFile diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md new file mode 100644 index 0000000..d583be4 --- /dev/null +++ b/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +Release Notes += + +## [2.0.0](https://github.com/dariogriffo/registrator-net/2.0.0) + +Dropped support for Microsoft.Extensions.Configuration < 3.0.0 diff --git a/src/EnvironmentFile/EnvironmentFile.csproj b/src/EnvironmentFile/EnvironmentFile.csproj index ff16b89..93b4b7d 100644 --- a/src/EnvironmentFile/EnvironmentFile.csproj +++ b/src/EnvironmentFile/EnvironmentFile.csproj @@ -4,39 +4,51 @@ Configuration.Extensions.EnvironmentFile Configuration.Extensions.EnvironmentFile netstandard2.0 - 1.3.0 + 2.0.0 https://github.com/dariogriffo https://github.com/dariogriffo Configuration.Extensions.EnvironmentFile https://github.com/dariogriffo Unix style EnvironmentFile to configure applications - https://raw.githubusercontent.com/dariogriffo/Configuration.Extensions.EnvironmentFile/master/LICENSE + https://raw.githubusercontent.com/dariogriffo/Configuration.Extensions.EnvironmentFile/main/LICENSE https://github.com/dariogriffo/Configuration.Extensions.EnvironmentFile https://github.com/dariogriffo/Configuration.Extensions.EnvironmentFile Configuration.Extensions.EnvironmentFile snupkg - - - + latest + enable images\icon.png Configuration Environment .env - Automatic reload on file change. + Dropped support for Microsoft.Extensions.Configuration < 3.0.0 - license\license.txt + MIT + images\icon.png + README.md + git + true - - - - + + Always + + + Always + + Always - - + + + + + <_Parameter1>$(AssemblyName).UnitTests + + + diff --git a/src/EnvironmentFile/EnvironmentFileConfigurationExtensions.cs b/src/EnvironmentFile/EnvironmentFileConfigurationExtensions.cs index 5a626e5..f14e5d0 100644 --- a/src/EnvironmentFile/EnvironmentFileConfigurationExtensions.cs +++ b/src/EnvironmentFile/EnvironmentFileConfigurationExtensions.cs @@ -1,40 +1,63 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Microsoft.Extensions.Configuration; - -namespace Configuration.Extensions.EnvironmentFile -{ - public static class EnvironmentFileConfigurationExtensions - { - public static IConfigurationBuilder AddEnvironmentFile( - this IConfigurationBuilder builder, - string fileName = ".env", - bool trim = true, - bool removeWrappingQuotes = true, - string prefix = null, - bool reloadOnChange = false) - { - - var filePath = fileName; - if (!Path.IsPathRooted(fileName)) - { - var directory = builder.Properties.TryGetValue("FileProvider", out var p) && p is FileConfigurationProvider configurationProvider - ? Path.GetDirectoryName(configurationProvider.Source.Path) - : Directory.GetCurrentDirectory(); - - filePath = Path.Combine(directory, fileName); - } - - if (!File.Exists(filePath)) - { - return builder; - } - var provider = - new EnvironmentFileConfigurationProvider(filePath, trim, removeWrappingQuotes, prefix, reloadOnChange); - - return builder.Add(new EnvironmentFileConfigurationSource(provider)); - - } - } -} +using System; +using System.IO; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.FileProviders.Physical; + +namespace Configuration.Extensions.EnvironmentFile; + +public static class EnvironmentFileConfigurationExtensions +{ + /// + /// Adds Unix style Environment files to IConfigurationBuilder for .NET applications + /// + /// the + /// The name of the file, defaults to .env + /// If true the spaces are trimmed to left and right of values. Defaults to true + /// If true remove wrapping quotes from values. Defaults to true + /// If specified, the prefix is removed from the key name when loaded into the configuration + /// If true, the file is watched for changes to reload the configuration. Defaults to false + /// + public static IConfigurationBuilder AddEnvironmentFile( + this IConfigurationBuilder builder, + string fileName = ".env", + bool trim = true, + bool removeWrappingQuotes = true, + string? prefix = null, + bool reloadOnChange = false + ) + { + string? directory; + if (!Path.IsPathRooted(fileName)) + { + directory = + builder.Properties.TryGetValue("FileProvider", out object? p) + && p is FileConfigurationProvider configurationProvider + ? Path.GetDirectoryName(configurationProvider.Source.Path) + : Directory.GetCurrentDirectory(); + } + else + { + directory = EnsureTrailingSlash(Path.GetFullPath(fileName)); + } + + Action configureSource = s => + { + s.Prefix = prefix; + s.RemoveWrappingQuotes = removeWrappingQuotes; + s.Trim = trim; + s.Path = fileName; + s.Optional = true; + s.ReloadOnChange = reloadOnChange; + s.FileProvider = new PhysicalFileProvider(directory!, ExclusionFilters.None); + }; + return builder.Add(configureSource); + } + + private static string EnsureTrailingSlash(string path) + { + return !string.IsNullOrEmpty(path) && path[path.Length - 1] != Path.DirectorySeparatorChar + ? path + Path.DirectorySeparatorChar + : path; + } +} diff --git a/src/EnvironmentFile/EnvironmentFileConfigurationParser.cs b/src/EnvironmentFile/EnvironmentFileConfigurationParser.cs new file mode 100644 index 0000000..f3e352f --- /dev/null +++ b/src/EnvironmentFile/EnvironmentFileConfigurationParser.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Configuration.Extensions.EnvironmentFile; + +internal static class EnvironmentFileConfigurationParser +{ + public static Dictionary Parse( + Stream stream, + bool trim, + bool removeWrappingQuotes, + string? prefix + ) + { + StreamReader reader = new(stream); + + IEnumerable nonCommentLinesWithPropertyValues = reader + .ReadToEnd() + .Split(["\r\n", "\r", "\n"], StringSplitOptions.None) + .Select(x => x.TrimStart()) + .Select(x => string.IsNullOrWhiteSpace(prefix) ? x : x.Replace(prefix, string.Empty)) + .Where(x => !x.StartsWith("#") && x.Contains("=")); + + IEnumerable>? configuration = nonCommentLinesWithPropertyValues + .Select(ParseQuotes) + .Select(x => RemoveCommentsAtTheEndAndTrimIfNecessary(x, trim)) + .Select(x => x.Split('=')) + .Select(x => new KeyValuePair( + x[0].Replace("__", ":"), + string.Join("=", x.Skip(1)) + )); + + return configuration.ToDictionary(x => x.Key, x => x.Value); + + string ParseQuotes(string line) + { + if (!removeWrappingQuotes) + { + return line; + } + + string[] parts = line.Split('='); + line = string.Join("=", parts.Skip(1)); + return $"{parts[0]}={line.Trim('"')}"; + } + + static string RemoveCommentsAtTheEndAndTrimIfNecessary(string line, bool t) + { + return t ? line.Trim() : line; + } + } +} diff --git a/src/EnvironmentFile/EnvironmentFileConfigurationProvider.cs b/src/EnvironmentFile/EnvironmentFileConfigurationProvider.cs index ec574a3..648ad8c 100644 --- a/src/EnvironmentFile/EnvironmentFileConfigurationProvider.cs +++ b/src/EnvironmentFile/EnvironmentFileConfigurationProvider.cs @@ -1,92 +1,34 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Primitives; - -namespace Configuration.Extensions.EnvironmentFile -{ - internal class EnvironmentFileConfigurationProvider : ConfigurationProvider, IDisposable - { - private readonly string _fileName; - private readonly bool _trim; - private readonly bool _removeWrappingQuotes; - private readonly string _prefix; - private readonly FileSystemWatcher _watcher; - - internal EnvironmentFileConfigurationProvider( - string fileName, - bool trim, - bool removeWrappingQuotes, - string prefix, - bool reloadOnChange - ) - { - _fileName = fileName; - _trim = trim; - _removeWrappingQuotes = removeWrappingQuotes; - _prefix = prefix; - if (!reloadOnChange) - { - return; - } - - _watcher = new FileSystemWatcher(Path.GetDirectoryName(_fileName)); - _watcher.Changed += new FileSystemEventHandler(OnChanged); - _watcher.EnableRaisingEvents = true; - } - - private void OnChanged(object sender, FileSystemEventArgs e) - { - Load(); - OnReload(); - } - - public override void Load() - { - LoadData(); - } - - private void LoadData() - { - var nonCommentLinesWithPropertyValues = - File - .ReadAllLines(_fileName) - .Select(x => x.TrimStart()) - .Select(x => string.IsNullOrWhiteSpace(_prefix) ? x : x.Replace(_prefix, string.Empty)) - .Where(x => !x.StartsWith("#") && x.Contains("=")); - - string ParseQuotes(string line) - { - if (!_removeWrappingQuotes) - { - return line; - } - - var parts = line.Split('='); - line = string.Join("=", parts.Skip(1)); - return $"{parts[0]}={line.Trim('"')}"; - } - - string RemoveCommentsAtTheEndAndTrimIfNecessary(string line) - { - return _trim ? line.Trim() : line; - } - - var configuration = - nonCommentLinesWithPropertyValues - .Select(ParseQuotes) - .Select(RemoveCommentsAtTheEndAndTrimIfNecessary) - .Select(x => x.Split('=')) - .Select(x => - new KeyValuePair(x[0].Replace("__", ":"), string.Join("=", x.Skip(1)))); - Data = configuration.ToDictionary(x => x.Key, x => x.Value); - } - - public void Dispose() - { - _watcher?.Dispose(); - } - } -} +using System.IO; +using Microsoft.Extensions.Configuration; + +namespace Configuration.Extensions.EnvironmentFile; + +internal class EnvironmentFileConfigurationProvider : FileConfigurationProvider +{ + private readonly bool _trim; + private readonly bool _removeWrappingQuotes; + private readonly string? _prefix; + + public override void Load(Stream stream) + { + Data = EnvironmentFileConfigurationParser.Parse( + stream, + _trim, + _removeWrappingQuotes, + _prefix + ); + } + + internal EnvironmentFileConfigurationProvider( + FileConfigurationSource source, + bool trim, + bool removeWrappingQuotes, + string? prefix + ) + : base(source) + { + _trim = trim; + _removeWrappingQuotes = removeWrappingQuotes; + _prefix = prefix; + } +} diff --git a/src/EnvironmentFile/EnvironmentFileConfigurationSource.cs b/src/EnvironmentFile/EnvironmentFileConfigurationSource.cs index f6805cd..4d41ede 100644 --- a/src/EnvironmentFile/EnvironmentFileConfigurationSource.cs +++ b/src/EnvironmentFile/EnvironmentFileConfigurationSource.cs @@ -1,23 +1,22 @@ -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using Microsoft.Extensions.Configuration; - -[assembly: InternalsVisibleTo("Configuration.Extensions.EnvironmentFile.UnitTests")] - -namespace Configuration.Extensions.EnvironmentFile -{ - internal class EnvironmentFileConfigurationSource : IConfigurationSource - { - private readonly EnvironmentFileConfigurationProvider _provider; - - internal EnvironmentFileConfigurationSource(EnvironmentFileConfigurationProvider provider) - { - _provider = provider; - } - - public IConfigurationProvider Build(IConfigurationBuilder builder) - { - return _provider; - } - } -} +using System.Runtime.CompilerServices; +using Microsoft.Extensions.Configuration; + +namespace Configuration.Extensions.EnvironmentFile; + +public class EnvironmentFileConfigurationSource : FileConfigurationSource +{ + public EnvironmentFileConfigurationSource() + { + Path = ".env"; + } + + internal string? Prefix { get; set; } + internal bool RemoveWrappingQuotes { get; set; } = true; + internal bool Trim { get; set; } = true; + + public override IConfigurationProvider Build(IConfigurationBuilder builder) + { + EnsureDefaults(builder); + return new EnvironmentFileConfigurationProvider(this, Trim, RemoveWrappingQuotes, Prefix); + } +} diff --git a/src/EnvironmentFile/licenses/license.txt b/src/EnvironmentFile/licenses/license.txt deleted file mode 100644 index 81c7dee..0000000 --- a/src/EnvironmentFile/licenses/license.txt +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License -Copyright (c) 2018 griffo.io - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/tests/EnvironmentFile.UnitTests/EnvironmentFile.UnitTests.csproj b/tests/EnvironmentFile.UnitTests/EnvironmentFile.UnitTests.csproj index e5179fb..fd717b4 100644 --- a/tests/EnvironmentFile.UnitTests/EnvironmentFile.UnitTests.csproj +++ b/tests/EnvironmentFile.UnitTests/EnvironmentFile.UnitTests.csproj @@ -3,21 +3,21 @@ Configuration.Extensions.EnvironmentFile.UnitTests Configuration.Extensions.EnvironmentFile.UnitTests - net5.0 + net8.0 false - - - - - - + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + @@ -26,31 +26,31 @@ - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always Always diff --git a/tests/EnvironmentFile.UnitTests/EnvironmentFileConfigurationExtensionsTests.cs b/tests/EnvironmentFile.UnitTests/EnvironmentFileConfigurationExtensionsTests.cs index b89b757..faba6cb 100644 --- a/tests/EnvironmentFile.UnitTests/EnvironmentFileConfigurationExtensionsTests.cs +++ b/tests/EnvironmentFile.UnitTests/EnvironmentFileConfigurationExtensionsTests.cs @@ -1,117 +1,139 @@ -using System.IO; -using System.Threading; -using FluentAssertions; -using Microsoft.Extensions.Configuration; -using Xunit; - -namespace Configuration.Extensions.EnvironmentFile.UnitTests -{ - public class EnvironmentFileConfigurationExtensionsTests - { - [Fact] - public void AddEnvironmentFile_With_No_Parameters_Loads_Default_File() - { - var configuration = new ConfigurationBuilder().AddEnvironmentFile().Build(); - configuration.GetConnectionString("Test").Should().Be("Value"); - } - - [Fact] - public void AddEnvironmentFile_When_File_Does_Not_Exist_Nothing_IsLoaded() - { - var configuration = new ConfigurationBuilder().AddEnvironmentFile("missing-file").Build(); - configuration.GetConnectionString("Test").Should().BeNullOrEmpty(); - } - - [Fact] - public void AddEnvironmentFile_Only_Works_On_Dev() - { - var configuration = new ConfigurationBuilder().AddEnvironmentFile().Build(); - configuration.GetConnectionString("Test").Should().Be("Value"); - } - - [Fact] - public void AddEnvironmentFile_With_Sections_They_Are_Loaded_Correctly() - { - var configuration = new ConfigurationBuilder().AddEnvironmentFile(".env-with-sections").Build(); - configuration.GetSection("Section1").Get().Should().NotBeNull(); - } - - [Fact] - public void AddEnvironmentFile_With_Prefix_Values_Are_Loaded_Correctly() - { - var configuration = new ConfigurationBuilder().AddEnvironmentFile(".env-with-prefix", prefix: "MyPrefix_") - .Build(); - configuration.GetSection("Section1").Get().Should().NotBeNull(); - } - - [Fact] - public void AddEnvironmentFile_When_File_Has_Comments_They_Are_Skipped() - { - var configuration = new ConfigurationBuilder().AddEnvironmentFile(".env-with-comments").Build(); - configuration.GetConnectionString("Commented").Should().BeNullOrEmpty(); - } - - [Fact] - public void AddEnvironmentFile_When_File_Has_Invalid_Lines_They_Are_Skipped() - { - var configuration = new ConfigurationBuilder().AddEnvironmentFile(".env-with-invalid-lines").Build(); - configuration.GetConnectionString("Test").Should().Be("Value"); - } - - [Fact] - public void AddEnvironmentFile_When_Configuration_Values_Have_An_Equals_Sign_Value_Is_Correctly_Parsed() - { - var configuration = new ConfigurationBuilder().AddEnvironmentFile(".env-with-equals-in-value").Build(); - configuration.GetConnectionString("Test").Should().Be("Value=1"); - } - - [Fact] - public void AddEnvironmentFile_When_Configuration_Has_Comments_After_Variable_Value_File_Is_Correctly_Parsed() - { - var configuration = new ConfigurationBuilder().AddEnvironmentFile(".env-with-comments-at-end-of-line") - .Build(); - configuration.GetConnectionString("WithComment").Should().Be("http://google.com#comment"); - } - - [Fact] - public void AddEnvironmentFile_When_Trim_Is_False_Is_Correctly_Parsed() - { - var configuration = new ConfigurationBuilder().AddEnvironmentFile(".env-no-trim", trim: false).Build(); - configuration.GetConnectionString("Property").Should().Be("1 "); - } - - [Fact] - public void AddEnvironmentFile_When_Trim_Is_True_Is_Correctly_Parsed() - { - var configuration = new ConfigurationBuilder().AddEnvironmentFile(".env-no-trim", trim: true).Build(); - configuration.GetConnectionString("Property").Should().Be("1"); - } - - [Fact] - public void AddEnvironmentFile_RemoveWrappingQuotes_Is_False_Is_Correctly_Parsed() - { - var configuration = new ConfigurationBuilder() - .AddEnvironmentFile(".env-wrapping-quotes", removeWrappingQuotes: false).Build(); - configuration.GetConnectionString("Property").Should().Be("\"1 \""); - } - - [Fact] - public void AddEnvironmentFile_RemoveWrappingQuotes_Is_True_Is_Correctly_Parsed() - { - var configuration = new ConfigurationBuilder() - .AddEnvironmentFile(".env-wrapping-quotes", trim: false, removeWrappingQuotes: true).Build(); - configuration.GetConnectionString("Property").Should().Be("1 "); - } - - [Fact] - public void AddEnvironmentFile_OnFileChange_ReloadsData() - { - var configuration = new ConfigurationBuilder().AddEnvironmentFile(".env-reload", reloadOnChange: true) - .Build(); - configuration.GetConnectionString("Test").Should().Be("Value"); - File.AppendAllText(Path.Combine(Directory.GetCurrentDirectory(), ".env-reload"), "ConnectionStrings__Another=Another"); - Thread.Sleep(1000); - configuration.GetConnectionString("Another").Should().Be("Another"); - } - } -} \ No newline at end of file +using System.IO; +using System.Threading; +using FluentAssertions; +using Microsoft.Extensions.Configuration; +using Xunit; + +namespace Configuration.Extensions.EnvironmentFile.UnitTests; + +public class EnvironmentFileConfigurationExtensionsTests +{ + [Fact] + public void AddEnvironmentFile_With_No_Parameters_Loads_Default_File() + { + IConfigurationRoot configuration = new ConfigurationBuilder().AddEnvironmentFile().Build(); + configuration.GetConnectionString("Test").Should().Be("Value"); + } + + [Fact] + public void AddEnvironmentFile_When_File_Does_Not_Exist_Nothing_IsLoaded() + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddEnvironmentFile("missing-file") + .Build(); + configuration.GetConnectionString("Test").Should().BeNullOrEmpty(); + } + + [Fact] + public void AddEnvironmentFile_Only_Works_On_Dev() + { + IConfigurationRoot configuration = new ConfigurationBuilder().AddEnvironmentFile().Build(); + configuration.GetConnectionString("Test").Should().Be("Value"); + } + + [Fact] + public void AddEnvironmentFile_With_Sections_They_Are_Loaded_Correctly() + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddEnvironmentFile(".env-with-sections") + .Build(); + configuration.GetSection("Section1").Get().Should().NotBeNull(); + } + + [Fact] + public void AddEnvironmentFile_With_Prefix_Values_Are_Loaded_Correctly() + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddEnvironmentFile(".env-with-prefix", prefix: "MyPrefix_") + .Build(); + configuration.GetSection("Section1").Get().Should().NotBeNull(); + } + + [Fact] + public void AddEnvironmentFile_When_File_Has_Comments_They_Are_Skipped() + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddEnvironmentFile(".env-with-comments") + .Build(); + configuration.GetConnectionString("Commented").Should().BeNullOrEmpty(); + } + + [Fact] + public void AddEnvironmentFile_When_File_Has_Invalid_Lines_They_Are_Skipped() + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddEnvironmentFile(".env-with-invalid-lines") + .Build(); + configuration.GetConnectionString("Test").Should().Be("Value"); + } + + [Fact] + public void AddEnvironmentFile_When_Configuration_Values_Have_An_Equals_Sign_Value_Is_Correctly_Parsed() + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddEnvironmentFile(".env-with-equals-in-value") + .Build(); + configuration.GetConnectionString("Test").Should().Be("Value=1"); + } + + [Fact] + public void AddEnvironmentFile_When_Configuration_Has_Comments_After_Variable_Value_File_Is_Correctly_Parsed() + { + var addEnvironmentFile = new ConfigurationBuilder().AddEnvironmentFile( + ".env-with-comments-at-end-of-line" + ); + IConfiguration configuration = addEnvironmentFile.Build(); + configuration.GetConnectionString("WithComment").Should().Be("http://google.com#comment"); + } + + [Fact] + public void AddEnvironmentFile_When_Trim_Is_False_Is_Correctly_Parsed() + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddEnvironmentFile(".env-no-trim", trim: false) + .Build(); + configuration.GetConnectionString("Property").Should().Be("1 "); + } + + [Fact] + public void AddEnvironmentFile_When_Trim_Is_True_Is_Correctly_Parsed() + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddEnvironmentFile(".env-no-trim", trim: true) + .Build(); + configuration.GetConnectionString("Property").Should().Be("1"); + } + + [Fact] + public void AddEnvironmentFile_RemoveWrappingQuotes_Is_False_Is_Correctly_Parsed() + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddEnvironmentFile(".env-wrapping-quotes", removeWrappingQuotes: false) + .Build(); + configuration.GetConnectionString("Property").Should().Be("\"1 \""); + } + + [Fact] + public void AddEnvironmentFile_RemoveWrappingQuotes_Is_True_Is_Correctly_Parsed() + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddEnvironmentFile(".env-wrapping-quotes", trim: false, removeWrappingQuotes: true) + .Build(); + configuration.GetConnectionString("Property").Should().Be("1 "); + } + + [Fact] + public void AddEnvironmentFile_OnFileChange_ReloadsData() + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddEnvironmentFile(".env-reload", reloadOnChange: true) + .Build(); + configuration.GetConnectionString("Test").Should().Be("Value"); + File.AppendAllText( + Path.Combine(Directory.GetCurrentDirectory(), ".env-reload"), + "ConnectionStrings__Another=Another" + ); + Thread.Sleep(1000); + configuration.GetConnectionString("Another").Should().Be("Another"); + } +} diff --git a/tests/EnvironmentFile.UnitTests/Section1.cs b/tests/EnvironmentFile.UnitTests/Section1.cs index b74ec33..6b8df67 100644 --- a/tests/EnvironmentFile.UnitTests/Section1.cs +++ b/tests/EnvironmentFile.UnitTests/Section1.cs @@ -1,10 +1,8 @@ -namespace Configuration.Extensions.EnvironmentFile.UnitTests -{ - public class Section1 - { - - public int Property1 { get; set; } - - public string Property2 { get; set; } - } -} \ No newline at end of file +namespace Configuration.Extensions.EnvironmentFile.UnitTests; + +public class Section1 +{ + public int Property1 { get; set; } + + public string Property2 { get; set; } +}