Skip to content

Commit

Permalink
Merge pull request #25 from appany/0.1.12
Browse files Browse the repository at this point in the history
Move attemptedValues to extended details
  • Loading branch information
sergeyshaykhullin authored Feb 12, 2021
2 parents d9415d4 + a01045b commit a893ab5
Show file tree
Hide file tree
Showing 41 changed files with 1,548 additions and 340 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This library is a rework of internal package inside @appany
- Most of extensibility points is just a composable delegates
- Fine-tuning of validation for each field: conditional validation skipping, multiple validators or error mappers per input
- Strongly typed `ValidationStrategy<T>` support
- Basic attribute-based support
- First-class attribute-based approach support

## Docs

Expand All @@ -27,6 +27,7 @@ This library is a rework of internal package inside @appany
- [Input validators](docs/examples/input-validators.md)
- [Root validator segregation](docs/examples/root-validator-segregation.md)
- [Argument level overrides](docs/examples/argument-level-overrides.md)
- [Attribute-based approach](docs/examples/attribute-based-approach.md)

## Usage

Expand All @@ -36,7 +37,8 @@ services.AddGraphQLServer()
.AddFluentValidation();

descriptor.Field(x => x.Example(default!))
// Explicit over implicit preferred, you have to add .UseFluentValidation() to all arguments requiring validation
// Explicit over implicit preferred
// You have to add .UseFluentValidation() to all arguments requiring validation
.Argument("input", argument => argument.UseFluentValidation());

... Example([UseFluentValidation] ExampleInput input) { ... }
Expand Down Expand Up @@ -65,7 +67,7 @@ descriptor.Field(x => x.Example(default!))
});
}));

... Example([UseFluentValidation(typeof(ExampleInputValidator))] ExampleInput input) { ... }
... Example([UseFluentValidation, UseValidator((typeof(ExampleInputValidator))] ExampleInput input) { ... }
```

## Benchmarks
Expand Down
73 changes: 73 additions & 0 deletions docs/examples/attribute-based-approach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Attribute-based approach

Use default input validator

```cs
... Example([UseFluentValidation] ExampleInput input) { ... }
```

Use single validator type for single validator

```cs
... Example([UseFluentValidation, UseValidator(typeof(ExampleInputValidator))] ExampleInput input) { ... }
```

Use single validator type for multiple validators

```cs
... Example([UseFluentValidation, UseValidators(typeof(IValidator<ExampleInput>))] ExampleInput input) { ... }
```

Use validator with custom [validation strategy](validation-strategies.md)

```cs
... Example([
UseFluentValidation,
UseValidator(
typeof(ExampleInputValidator),
IncludeProperties=new[]{"ExampleProperty"},
IncludeRuleSets=new[]{"FastValidation"})
] ExampleInput input) { ... }
```

Use validators with custom [validation strategy](validation-strategies.md)

```cs
... Example([
UseFluentValidation,
UseValidators(
typeof(ExampleInputValidator),
IncludeAllRuleSets=true,
IncludeRulesNotInRuleSet=true)
] ExampleInput input) { ... }
```

Use default [input validator](input-validators.md)

```cs
... Example([UseFluentValidation, UseDefaultInputValidator)] ExampleInput input) { ... }
```

Use default [error mapper](error-mappers.md)

```cs
... Example([UseFluentValidation, UseDefaultErrorMapper)] ExampleInput input) { ... }
```

Use default [error mapper](error-mappers.md) with details

```cs
... Example([UseFluentValidation, UseDefaultErrorMapperWithDetails)] ExampleInput input) { ... }
```

Use default [error mapper](error-mappers.md) with extended details

```cs
... Example([UseFluentValidation, UseDefaultErrorMapperWithExtendedDetails)] ExampleInput input) { ... }
```

Skip validation

```cs
... Example([UseFluentValidation, SkipValidation)] ExampleInput input) { ... }
```
5 changes: 3 additions & 2 deletions docs/examples/error-mappers.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@
"extensions": {
"code": "ValidationFailed",
"validator": "NotEmptyValidator",
"field": "createUser",
"argument": "input",
"property": "Name",
"severity": "Error",
"attemptedValue": ""
"severity": "Error"
}
}
],
Expand All @@ -65,6 +65,7 @@
"extensions": {
"code": "ValidationFailed",
"validator": "NotEmptyValidator",
"field": "createUser",
"argument": "input",
"property": "Name",
"severity": "Error",
Expand Down
4 changes: 2 additions & 2 deletions src/AppAny.HotChocolate.FluentValidation.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable>
<Version>0.1.11</Version>
<Version>0.1.12</Version>
<LangVersion>9</LangVersion>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
Expand All @@ -24,7 +24,7 @@
</PropertyGroup>

<ItemGroup Label="Packages">
<PackageReference Include="FluentValidation" Version="9.5.0" />
<PackageReference Include="FluentValidation" Version="9.5.1" />
<PackageReference Include="HotChocolate.Execution" Version="11.0.9" />
</ItemGroup>

Expand Down
56 changes: 56 additions & 0 deletions src/Attributes/BaseUseValidatorAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using FluentValidation.Internal;

namespace AppAny.HotChocolate.FluentValidation
{
public abstract class BaseUseValidatorAttribute : FluentValidationAttribute
{
protected BaseUseValidatorAttribute(Type validatorType)
{
ValidatorType = validatorType;
}

public Type ValidatorType { get; }

public string[]? IncludeProperties { get; set; }
public string[]? IncludeRuleSets { get; set; }
public bool IncludeAllRuleSets { get; set; }
public bool IncludeRulesNotInRuleSet { get; set; }

protected Action<ValidationStrategy<object>>? TryGetValidationStrategy()
{
var shouldUseValidationStrategy = IncludeProperties is not null
|| IncludeRuleSets is not null
|| IncludeAllRuleSets
|| IncludeRulesNotInRuleSet;

if (shouldUseValidationStrategy)
{
return strategy =>
{
if (IncludeProperties is not null)
{
strategy.IncludeProperties(IncludeProperties);
}

if (IncludeRuleSets is not null)
{
strategy.IncludeRuleSets(IncludeRuleSets);
}

if (IncludeAllRuleSets)
{
strategy.IncludeAllRuleSets();
}

if (IncludeRulesNotInRuleSet)
{
strategy.IncludeRulesNotInRuleSet();
}
};
}

return null;
}
}
}
9 changes: 9 additions & 0 deletions src/Attributes/FluentValidationAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace AppAny.HotChocolate.FluentValidation
{
public abstract class FluentValidationAttribute : Attribute
{
public abstract void Configure(ArgumentValidationBuilder builder);
}
}
10 changes: 10 additions & 0 deletions src/Attributes/SkipValidationAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace AppAny.HotChocolate.FluentValidation
{
public sealed class SkipValidationAttribute : FluentValidationAttribute
{
public override void Configure(ArgumentValidationBuilder builder)
{
builder.SkipValidation();
}
}
}
10 changes: 10 additions & 0 deletions src/Attributes/UseDefaultErrorMapperAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace AppAny.HotChocolate.FluentValidation
{
public sealed class UseDefaultErrorMapperAttribute : FluentValidationAttribute
{
public override void Configure(ArgumentValidationBuilder builder)
{
builder.UseDefaultErrorMapper();
}
}
}
10 changes: 10 additions & 0 deletions src/Attributes/UseDefaultErrorMapperWithDetailsAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace AppAny.HotChocolate.FluentValidation
{
public sealed class UseDefaultErrorMapperWithDetailsAttribute : FluentValidationAttribute
{
public override void Configure(ArgumentValidationBuilder builder)
{
builder.UseDefaultErrorMapperWithDetails();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace AppAny.HotChocolate.FluentValidation
{
public sealed class UseDefaultErrorMapperWithExtendedDetailsAttribute : FluentValidationAttribute
{
public override void Configure(ArgumentValidationBuilder builder)
{
builder.UseDefaultErrorMapperWithExtendedDetails();
}
}
}
10 changes: 10 additions & 0 deletions src/Attributes/UseDefaultInputValidatorAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace AppAny.HotChocolate.FluentValidation
{
public sealed class UseDefaultInputValidatorAttribute : FluentValidationAttribute
{
public override void Configure(ArgumentValidationBuilder builder)
{
builder.UseDefaultInputValidator();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,18 @@ namespace AppAny.HotChocolate.FluentValidation
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class UseFluentValidationAttribute : ArgumentDescriptorAttribute
{
private readonly Type[] validators;

public UseFluentValidationAttribute(params Type[] validators)
{
this.validators = validators;
}

public override void OnConfigure(
IDescriptorContext context,
IArgumentDescriptor descriptor,
ParameterInfo parameter)
{
var fluentValidationAttributes = parameter.GetCustomAttributes<FluentValidationAttribute>();

descriptor.UseFluentValidation(options =>
{
foreach (var validator in validators)
foreach (var fluentValidationAttribute in fluentValidationAttributes)
{
options.UseValidator(validator);
fluentValidationAttribute.Configure(options);
}
});
}
Expand Down
26 changes: 26 additions & 0 deletions src/Attributes/UseValidatorAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;

namespace AppAny.HotChocolate.FluentValidation
{
public sealed class UseValidatorAttribute : BaseUseValidatorAttribute
{
public UseValidatorAttribute(Type validatorType)
: base(validatorType)
{
}

public override void Configure(ArgumentValidationBuilder builder)
{
var validationStrategy = TryGetValidationStrategy();

if (validationStrategy is null)
{
builder.UseValidator(ValidatorType);
}
else
{
builder.UseValidator(ValidatorType, validationStrategy);
}
}
}
}
26 changes: 26 additions & 0 deletions src/Attributes/UseValidatorsAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;

namespace AppAny.HotChocolate.FluentValidation
{
public sealed class UseValidatorsAttribute : BaseUseValidatorAttribute
{
public UseValidatorsAttribute(Type validatorType)
: base(validatorType)
{
}

public override void Configure(ArgumentValidationBuilder builder)
{
var validationStrategy = TryGetValidationStrategy();

if (validationStrategy is null)
{
builder.UseValidators(ValidatorType);
}
else
{
builder.UseValidators(ValidatorType, validationStrategy);
}
}
}
}
Loading

0 comments on commit a893ab5

Please sign in to comment.