From c937936e5d4dcaf39f32d943f450b83f94022cb3 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Tue, 3 Oct 2023 09:27:02 +0200 Subject: [PATCH 1/9] Fixed Variable Name --- .../Execution/Processing/OperationCompiler.CompilerContext.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/HotChocolate/Core/src/Execution/Processing/OperationCompiler.CompilerContext.cs b/src/HotChocolate/Core/src/Execution/Processing/OperationCompiler.CompilerContext.cs index 66bbfbd898e..6659b83b39b 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/OperationCompiler.CompilerContext.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/OperationCompiler.CompilerContext.cs @@ -8,7 +8,7 @@ namespace HotChocolate.Execution.Processing; public sealed partial class OperationCompiler { - internal sealed class CompilerContext(ISchema schema, DocumentNode document, bool disableNullBubbling) + internal sealed class CompilerContext(ISchema schema, DocumentNode document, bool enableNullBubbling) { public ISchema Schema { get; } = schema; @@ -30,7 +30,7 @@ internal sealed class CompilerContext(ISchema schema, DocumentNode document, boo public IImmutableList Optimizers { get; private set; } = ImmutableList.Empty; - public bool EnableNullBubbling { get; } = disableNullBubbling; + public bool EnableNullBubbling { get; } = enableNullBubbling; public void Initialize( ObjectType type, From ffd03ea9617e78b4e3f7b6c437081c49e531ecb4 Mon Sep 17 00:00:00 2001 From: Tobias Tengler <45513122+tobias-tengler@users.noreply.github.com> Date: Tue, 3 Oct 2023 09:38:29 +0200 Subject: [PATCH 2/9] Print @deprecated in HotChocolate.Skimmed.SchemaFormatter (#6565) --- .../Types/Directives/DeprecatedDirective.cs | 4 +- .../Directives/DeprecatedDirectiveType.cs | 10 +- .../DeprecationMergeTests.cs | 136 ++++++++++++++++++ ..._Output_Field_Argument_Deprecation.graphql | 34 +++++ ...ge_Entity_Output_Field_Deprecation.graphql | 33 +++++ ...Tests.Merge_Enum_Value_Deprecation.graphql | 20 +++ ..._Output_Field_Argument_Deprecation.graphql | 21 +++ ...sts.Merge_Output_Field_Deprecation.graphql | 20 +++ .../Skimmed/Serialization/SchemaFormatter.cs | 62 +++++++- 9 files changed, 323 insertions(+), 17 deletions(-) create mode 100644 src/HotChocolate/Fusion/test/Composition.Tests/DeprecationMergeTests.cs create mode 100644 src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Entity_Output_Field_Argument_Deprecation.graphql create mode 100644 src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Entity_Output_Field_Deprecation.graphql create mode 100644 src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Enum_Value_Deprecation.graphql create mode 100644 src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Output_Field_Argument_Deprecation.graphql create mode 100644 src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Output_Field_Deprecation.graphql diff --git a/src/HotChocolate/Core/src/Types/Types/Directives/DeprecatedDirective.cs b/src/HotChocolate/Core/src/Types/Types/Directives/DeprecatedDirective.cs index a76fd676c9c..c0c60eb4975 100644 --- a/src/HotChocolate/Core/src/Types/Types/Directives/DeprecatedDirective.cs +++ b/src/HotChocolate/Core/src/Types/Types/Directives/DeprecatedDirective.cs @@ -72,11 +72,11 @@ public static DirectiveNode CreateNode(string? reason = null) var arguments = reason is null ? Array.Empty() - : new[] { new ArgumentNode(DeprecatedDirectiveType.Names.Reason, reason) }; + : new[] { new ArgumentNode(WellKnownDirectives.DeprecationReasonArgument, reason) }; return new DirectiveNode( null, - new NameNode(DeprecatedDirectiveType.Names.Deprecated), + new NameNode(WellKnownDirectives.Deprecated), arguments); } } diff --git a/src/HotChocolate/Core/src/Types/Types/Directives/DeprecatedDirectiveType.cs b/src/HotChocolate/Core/src/Types/Types/Directives/DeprecatedDirectiveType.cs index e0770b15ea4..4bf1ea551a5 100644 --- a/src/HotChocolate/Core/src/Types/Types/Directives/DeprecatedDirectiveType.cs +++ b/src/HotChocolate/Core/src/Types/Types/Directives/DeprecatedDirectiveType.cs @@ -16,7 +16,7 @@ protected override void Configure( IDirectiveTypeDescriptor descriptor) { descriptor - .Name(Names.Deprecated) + .Name(WellKnownDirectives.Deprecated) .Description(TypeResources.DeprecatedDirectiveType_TypeDescription) .Location(DirectiveLocation.FieldDefinition) .Location(DirectiveLocation.ArgumentDefinition) @@ -25,15 +25,9 @@ protected override void Configure( descriptor .Argument(t => t.Reason) - .Name(Names.Reason) + .Name(WellKnownDirectives.DeprecationReasonArgument) .Description(TypeResources.DeprecatedDirectiveType_ReasonDescription) .Type() .DefaultValue(WellKnownDirectives.DeprecationDefaultReason); } - - public static class Names - { - public const string Deprecated = "deprecated"; - public const string Reason = "reason"; - } } diff --git a/src/HotChocolate/Fusion/test/Composition.Tests/DeprecationMergeTests.cs b/src/HotChocolate/Fusion/test/Composition.Tests/DeprecationMergeTests.cs new file mode 100644 index 00000000000..ae110337a64 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Composition.Tests/DeprecationMergeTests.cs @@ -0,0 +1,136 @@ +using Xunit.Abstractions; + +namespace HotChocolate.Fusion.Composition; + +public class DeprecationMergeTests(ITestOutputHelper output) : CompositionTestBase(output) +{ + [Fact] + public async Task Merge_Entity_Output_Field_Deprecation() + => await Succeed( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name: String! @deprecated(reason: "Some reason") + } + + interface Node { + id: ID! + } + """, + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + newName: String! + } + + interface Node { + id: ID! + } + """); + + [Fact] + public async Task Merge_Entity_Output_Field_Argument_Deprecation() + => await Succeed( + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name(includeFirstName: Boolean @deprecated(reason: "Some reason")): String! + } + + interface Node { + id: ID! + } + """, + """ + type Query { + brandById(id: ID!): Brand + } + + type Brand implements Node { + id: ID! + name(includeFirstName: Boolean): String! + } + + interface Node { + id: ID! + } + """); + + [Fact] + public async Task Merge_Output_Field_Deprecation() + => await Succeed( + """ + type Query { + brand: Brand + } + + type Brand { + name: String! @deprecated(reason: "Some reason") + } + """, + """ + type Query { + brand: Brand + } + + type Brand { + newName: String! + } + """); + + [Fact] + public async Task Merge_Output_Field_Argument_Deprecation() + => await Succeed( + """ + type Query { + brand: Brand + } + + type Brand { + name(includeFirstName: Boolean @deprecated(reason: "Some reason")): String! + } + """, + """ + type Query { + brand: Brand + } + + type Brand { + name(includeFirstName: Boolean): String! + } + """); + + [Fact] + public async Task Merge_Enum_Value_Deprecation() + => await Succeed( + """ + type Query { + value: OrderStatus + } + + enum OrderStatus { + SENT_OUT @deprecated(reason: "Some reason") + } + """, + """ + type Query { + value: OrderStatus + } + + enum OrderStatus { + SHIPPED + } + """); +} diff --git a/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Entity_Output_Field_Argument_Deprecation.graphql b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Entity_Output_Field_Argument_Deprecation.graphql new file mode 100644 index 00000000000..cd91ddf7af7 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Entity_Output_Field_Argument_Deprecation.graphql @@ -0,0 +1,34 @@ +schema + @fusion(version: 1) + @transport(subgraph: "A", location: "https:\/\/localhost:5001\/graphql", kind: "HTTP") + @transport(subgraph: "B", location: "https:\/\/localhost:5002\/graphql", kind: "HTTP") { + query: Query +} + +type Query { + brandById(id: ID!): Brand + @variable(subgraph: "A", name: "id", argument: "id") + @resolver(subgraph: "A", select: "{ brandById(id: $id) }", arguments: [ { name: "id", type: "ID!" } ]) + @variable(subgraph: "B", name: "id", argument: "id") + @resolver(subgraph: "B", select: "{ brandById(id: $id) }", arguments: [ { name: "id", type: "ID!" } ]) +} + +type Brand implements Node + @variable(subgraph: "A", name: "Brand_id", select: "id") + @variable(subgraph: "B", name: "Brand_id", select: "id") + @resolver(subgraph: "A", select: "{ brandById(id: $Brand_id) }", arguments: [ { name: "Brand_id", type: "ID!" } ]) + @resolver(subgraph: "B", select: "{ brandById(id: $Brand_id) }", arguments: [ { name: "Brand_id", type: "ID!" } ]) { + id: ID! + @source(subgraph: "A") + @source(subgraph: "B") + name(includeFirstName: Boolean + @deprecated(reason: "Some reason")): String! + @source(subgraph: "A") + @variable(subgraph: "A", name: "includeFirstName", argument: "includeFirstName") + @source(subgraph: "B") + @variable(subgraph: "B", name: "includeFirstName", argument: "includeFirstName") +} + +interface Node { + id: ID! +} \ No newline at end of file diff --git a/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Entity_Output_Field_Deprecation.graphql b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Entity_Output_Field_Deprecation.graphql new file mode 100644 index 00000000000..7d21b665113 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Entity_Output_Field_Deprecation.graphql @@ -0,0 +1,33 @@ +schema + @fusion(version: 1) + @transport(subgraph: "A", location: "https:\/\/localhost:5001\/graphql", kind: "HTTP") + @transport(subgraph: "B", location: "https:\/\/localhost:5002\/graphql", kind: "HTTP") { + query: Query +} + +type Query { + brandById(id: ID!): Brand + @variable(subgraph: "A", name: "id", argument: "id") + @resolver(subgraph: "A", select: "{ brandById(id: $id) }", arguments: [ { name: "id", type: "ID!" } ]) + @variable(subgraph: "B", name: "id", argument: "id") + @resolver(subgraph: "B", select: "{ brandById(id: $id) }", arguments: [ { name: "id", type: "ID!" } ]) +} + +type Brand implements Node + @variable(subgraph: "A", name: "Brand_id", select: "id") + @variable(subgraph: "B", name: "Brand_id", select: "id") + @resolver(subgraph: "A", select: "{ brandById(id: $Brand_id) }", arguments: [ { name: "Brand_id", type: "ID!" } ]) + @resolver(subgraph: "B", select: "{ brandById(id: $Brand_id) }", arguments: [ { name: "Brand_id", type: "ID!" } ]) { + id: ID! + @source(subgraph: "A") + @source(subgraph: "B") + name: String! + @source(subgraph: "A") + @deprecated(reason: "Some reason") + newName: String! + @source(subgraph: "B") +} + +interface Node { + id: ID! +} \ No newline at end of file diff --git a/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Enum_Value_Deprecation.graphql b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Enum_Value_Deprecation.graphql new file mode 100644 index 00000000000..2eb1aef33dc --- /dev/null +++ b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Enum_Value_Deprecation.graphql @@ -0,0 +1,20 @@ +schema + @fusion(version: 1) + @transport(subgraph: "A", location: "https:\/\/localhost:5001\/graphql", kind: "HTTP") + @transport(subgraph: "B", location: "https:\/\/localhost:5002\/graphql", kind: "HTTP") { + query: Query +} + +type Query { + value: OrderStatus + @resolver(subgraph: "A", select: "{ value }") + @resolver(subgraph: "B", select: "{ value }") +} + +enum OrderStatus { + SENT_OUT + @source(subgraph: "A") + @deprecated(reason: "Some reason") + SHIPPED + @source(subgraph: "B") +} \ No newline at end of file diff --git a/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Output_Field_Argument_Deprecation.graphql b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Output_Field_Argument_Deprecation.graphql new file mode 100644 index 00000000000..f0f33899875 --- /dev/null +++ b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Output_Field_Argument_Deprecation.graphql @@ -0,0 +1,21 @@ +schema + @fusion(version: 1) + @transport(subgraph: "A", location: "https:\/\/localhost:5001\/graphql", kind: "HTTP") + @transport(subgraph: "B", location: "https:\/\/localhost:5002\/graphql", kind: "HTTP") { + query: Query +} + +type Query { + brand: Brand + @resolver(subgraph: "A", select: "{ brand }") + @resolver(subgraph: "B", select: "{ brand }") +} + +type Brand { + name(includeFirstName: Boolean + @deprecated(reason: "Some reason")): String! + @source(subgraph: "A") + @variable(subgraph: "A", name: "includeFirstName", argument: "includeFirstName") + @source(subgraph: "B") + @variable(subgraph: "B", name: "includeFirstName", argument: "includeFirstName") +} \ No newline at end of file diff --git a/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Output_Field_Deprecation.graphql b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Output_Field_Deprecation.graphql new file mode 100644 index 00000000000..449081c98de --- /dev/null +++ b/src/HotChocolate/Fusion/test/Composition.Tests/__snapshots__/DeprecationMergeTests.Merge_Output_Field_Deprecation.graphql @@ -0,0 +1,20 @@ +schema + @fusion(version: 1) + @transport(subgraph: "A", location: "https:\/\/localhost:5001\/graphql", kind: "HTTP") + @transport(subgraph: "B", location: "https:\/\/localhost:5002\/graphql", kind: "HTTP") { + query: Query +} + +type Query { + brand: Brand + @resolver(subgraph: "A", select: "{ brand }") + @resolver(subgraph: "B", select: "{ brand }") +} + +type Brand { + name: String! + @source(subgraph: "A") + @deprecated(reason: "Some reason") + newName: String! + @source(subgraph: "B") +} \ No newline at end of file diff --git a/src/HotChocolate/Skimmed/src/Skimmed/Serialization/SchemaFormatter.cs b/src/HotChocolate/Skimmed/src/Skimmed/Serialization/SchemaFormatter.cs index 65bbefa2ba7..251a05031c3 100644 --- a/src/HotChocolate/Skimmed/src/Skimmed/Serialization/SchemaFormatter.cs +++ b/src/HotChocolate/Skimmed/src/Skimmed/Serialization/SchemaFormatter.cs @@ -1,5 +1,6 @@ using HotChocolate.Language; using HotChocolate.Language.Utilities; +using HotChocolate.Utilities; namespace HotChocolate.Skimmed.Serialization; @@ -9,10 +10,10 @@ public static class SchemaFormatter private static readonly SyntaxSerializerOptions _options = new() { - Indented = true, + Indented = true, MaxDirectivesPerLine = 0 }; - + public static string FormatAsString(Schema schema, bool indented = true) { var context = new VisitorContext(); @@ -20,9 +21,9 @@ public static string FormatAsString(Schema schema, bool indented = true) if (!indented) { - ((DocumentNode) context.Result!).ToString(false); + ((DocumentNode)context.Result!).ToString(false); } - + return ((DocumentNode)context.Result!).ToString(_options); } @@ -119,7 +120,7 @@ public override void VisitTypes(TypeCollection types, VisitorContext context) foreach (var type in types.OfType().OrderBy(t => t.Name)) { - if(context.Schema?.QueryType == type || + if (context.Schema?.QueryType == type || context.Schema?.MutationType == type || context.Schema?.SubscriptionType == type) { @@ -156,7 +157,7 @@ public override void VisitTypes(TypeCollection types, VisitorContext context) foreach (var type in types.OfType().OrderBy(t => t.Name)) { - if (type is { IsSpecScalar: true } || SpecScalarTypes.IsSpecScalar(type.Name)) + if (type is { IsSpecScalar: true } || SpecScalarTypes.IsSpecScalar(type.Name)) { type.IsSpecScalar = true; continue; @@ -326,6 +327,8 @@ public override void VisitEnumValue(EnumValue value, VisitorContext context) VisitDirectives(value.Directives, context); var directives = (List)context.Result!; + directives = ApplyDeprecatedDirective(value, directives); + context.Result = new EnumValueDefinitionNode( null, new NameNode(value.Name), @@ -399,6 +402,8 @@ public override void VisitOutputField(OutputField field, VisitorContext context) VisitDirectives(field.Directives, context); var directives = (List)context.Result!; + directives = ApplyDeprecatedDirective(field, directives); + context.Result = new FieldDefinitionNode( null, new NameNode(field.Name), @@ -428,6 +433,9 @@ public override void VisitInputFields( public override void VisitInputField(InputField field, VisitorContext context) { VisitDirectives(field.Directives, context); + var directives = (List)context.Result!; + + directives = ApplyDeprecatedDirective(field, directives); context.Result = new InputValueDefinitionNode( null, @@ -437,7 +445,7 @@ field.Description is not null : null, field.Type.ToTypeNode(), field.DefaultValue, - (List)context.Result!); + directives); } public override void VisitDirectives(DirectiveCollection directives, VisitorContext context) @@ -481,6 +489,46 @@ public override void VisitArgument(Argument argument, VisitorContext context) { context.Result = new ArgumentNode(argument.Name, argument.Value); } + + private static List ApplyDeprecatedDirective( + ICanBeDeprecated canBeDeprecated, + List directives) + { + if (canBeDeprecated.IsDeprecated) + { + var deprecateDirective = CreateDeprecatedDirective(canBeDeprecated.DeprecationReason); + + if (directives.Count == 0) + { + directives = new List { deprecateDirective }; + } + else + { + var temp = directives.ToList(); + temp.Add(deprecateDirective); + directives = temp; + } + } + + return directives; + } + + private static DirectiveNode CreateDeprecatedDirective(string? reason = null) + { + if (WellKnownDirectives.DeprecationDefaultReason.EqualsOrdinal(reason)) + { + reason = null; + } + + var arguments = reason is null + ? Array.Empty() + : new[] { new ArgumentNode(WellKnownDirectives.DeprecationReasonArgument, reason) }; + + return new DirectiveNode( + null, + new NameNode(WellKnownDirectives.Deprecated), + arguments); + } } private sealed class VisitorContext From cdfd761727306e9845594bd2b296bfdede816dfe Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Tue, 3 Oct 2023 15:48:18 +0200 Subject: [PATCH 3/9] Fixed tag directive nullability. (#6571) --- src/HotChocolate/Core/src/Types/Types/Directives/Tag.cs | 2 ++ .../TagDirectiveTests.EnsureAllLocationsAreApplied.graphql | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/HotChocolate/Core/src/Types/Types/Directives/Tag.cs b/src/HotChocolate/Core/src/Types/Types/Directives/Tag.cs index 474aa3a5c18..5f30ab8bfa2 100644 --- a/src/HotChocolate/Core/src/Types/Types/Directives/Tag.cs +++ b/src/HotChocolate/Core/src/Types/Types/Directives/Tag.cs @@ -1,3 +1,5 @@ +#nullable enable + using System; using HotChocolate.Properties; using HotChocolate.Utilities; diff --git a/src/HotChocolate/Core/test/Types.Tests/Types/Directives/__snapshots__/TagDirectiveTests.EnsureAllLocationsAreApplied.graphql b/src/HotChocolate/Core/test/Types.Tests/Types/Directives/__snapshots__/TagDirectiveTests.EnsureAllLocationsAreApplied.graphql index da3d3bc79d7..5f2f4ff9cd5 100644 --- a/src/HotChocolate/Core/test/Types.Tests/Types/Directives/__snapshots__/TagDirectiveTests.EnsureAllLocationsAreApplied.graphql +++ b/src/HotChocolate/Core/test/Types.Tests/Types/Directives/__snapshots__/TagDirectiveTests.EnsureAllLocationsAreApplied.graphql @@ -26,4 +26,4 @@ enum FooEnum @tag(name: "OnEnum") { directive @foo(arg: String @tag(name: "OnDirectiveArgument")) on QUERY -directive @tag(name: String) repeatable on SCHEMA | SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION \ No newline at end of file +directive @tag(name: String!) repeatable on SCHEMA | SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION \ No newline at end of file From 5982df13d8fd8165a7590c57419821bf5edf87a2 Mon Sep 17 00:00:00 2001 From: PascalSenn Date: Fri, 6 Oct 2023 14:55:40 +0200 Subject: [PATCH 4/9] Adds `extensions` support for `subgraph-config.json` (#6577) --- .../src/Abstractions/FusionGraphPackage.cs | 9 +- .../src/Abstractions/SubgraphConfigJson.cs | 13 ++- .../src/Abstractions/SubgraphConfiguration.cs | 30 +++++- .../CommandLine/Commands/ComposeCommand.cs | 6 +- .../src/CommandLine/Helpers/PackageHelper.cs | 40 ++++++-- .../Helpers/SubgraphConfigurationDto.cs | 17 +++- .../test/CommandLine.Tests/CommandTestBase.cs | 2 +- ...tChocolate.Fusion.CommandLine.Tests.csproj | 7 ++ .../CommandLine.Tests/PackageHelperTests.cs | 44 ++++++++- ...HelperTests.Create_Extract_Extensions.snap | 94 +++++++++++++++++++ .../Composition.Tests/CompositionTestBase.cs | 15 ++- .../test/Composition.Tests/DataTypesTests.cs | 6 +- .../test/Composition.Tests/ErrorTests.cs | 7 +- .../test/Core.Tests/RequestPlannerTests.cs | 57 ++++++----- .../Fusion/test/Shared/DemoSubgraph.cs | 46 ++++++--- 15 files changed, 311 insertions(+), 82 deletions(-) create mode 100644 src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/PackageHelperTests.Create_Extract_Extensions.snap diff --git a/src/HotChocolate/Fusion/src/Abstractions/FusionGraphPackage.cs b/src/HotChocolate/Fusion/src/Abstractions/FusionGraphPackage.cs index 8f99458fdf7..82ab62c29d1 100644 --- a/src/HotChocolate/Fusion/src/Abstractions/FusionGraphPackage.cs +++ b/src/HotChocolate/Fusion/src/Abstractions/FusionGraphPackage.cs @@ -27,7 +27,7 @@ public sealed class FusionGraphPackage : IDisposable, IAsyncDisposable private static readonly SyntaxSerializerOptions _syntaxSerializerOptions = new() { - Indented = true, + Indented = true, MaxDirectivesPerLine = 0 }; @@ -202,7 +202,7 @@ public Task GetFusionGraphSettingsAsync( return Task.FromResult( JsonDocument.Parse( """ - { + { "fusionTypePrefix" : null, "fusionTypeSelf": false } @@ -523,7 +523,8 @@ private async Task ReadSubgraphConfigurationAsync( config.Name, schema.ToString(true), extensions.Select(t => t.ToString(_syntaxSerializerOptions)).ToArray(), - config.Clients); + config.Clients, + config.Extensions); } private async Task ReadSubgraphConfigurationJsonPartAsync( @@ -646,4 +647,4 @@ public ValueTask DisposeAsync() _package.Close(); return default; } -} \ No newline at end of file +} diff --git a/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJson.cs b/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJson.cs index 63841f645c6..19831ed86c9 100644 --- a/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJson.cs +++ b/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJson.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using HotChocolate.Fusion.Composition; namespace HotChocolate.Fusion; @@ -18,7 +19,8 @@ internal sealed record SubgraphConfigJson /// public SubgraphConfigJson( string name, - IReadOnlyList? clients = null) + IReadOnlyList? clients = null, + JsonDocument? extensions = null) { Name = name; Clients = clients ?? Array.Empty(); @@ -34,6 +36,11 @@ public SubgraphConfigJson( /// public IReadOnlyList Clients { get; init; } + /// + /// Gets the "extensions" property of the subgraph-config.json. + /// + public JsonDocument? Extensions { get; init; } + /// /// Deconstructs the into its components. /// @@ -45,9 +52,11 @@ public SubgraphConfigJson( /// public void Deconstruct( out string name, - out IReadOnlyList clients) + out IReadOnlyList clients, + out JsonDocument? extensions) { name = Name; clients = Clients; + extensions = Extensions; } } diff --git a/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfiguration.cs b/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfiguration.cs index d3a6774a363..524101636b2 100644 --- a/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfiguration.cs +++ b/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfiguration.cs @@ -1,3 +1,5 @@ +using System.Text.Json; + namespace HotChocolate.Fusion.Composition; /// @@ -20,16 +22,21 @@ public sealed class SubgraphConfiguration /// /// The list of clients that can be used to fetch data from this subgraph. /// + /// + /// The "extensions" field of the subgraph-config.json. + /// public SubgraphConfiguration( string name, string schema, IReadOnlyList extensions, - IReadOnlyList clients) + IReadOnlyList clients, + JsonDocument? configurationExtensions) { Name = name; Schema = schema; Extensions = extensions; Clients = clients; + ConfigurationExtensions = configurationExtensions; } /// @@ -47,12 +54,16 @@ public SubgraphConfiguration( /// /// The list of clients that can be used to fetch data from this subgraph. /// + /// + /// The "extensions" field of the subgraph-config.json. + /// public SubgraphConfiguration( string name, string schema, string extensions, - IReadOnlyList clients) - : this(name, schema, new[] { extensions }, clients) { } + IReadOnlyList clients, + JsonDocument? configurationExtensions) + : this(name, schema, new[] { extensions }, clients, configurationExtensions) { } /// /// Initializes a new instance of the class. @@ -69,12 +80,16 @@ public SubgraphConfiguration( /// /// The client that can be used to fetch data from this subgraph. /// + /// + /// The "extensions" field of the subgraph-config.json. + /// public SubgraphConfiguration( string name, string schema, string extensions, - IClientConfiguration client) - : this(name, schema, new[] { extensions }, new[] { client }) { } + IClientConfiguration client, + JsonDocument? configurationExtensions) + : this(name, schema, new[] { extensions }, new[] { client }, configurationExtensions) { } /// /// Gets the name of the subgraph. @@ -95,4 +110,9 @@ public SubgraphConfiguration( /// Gets the list of clients that can be used to fetch data from this subgraph. /// public IReadOnlyList Clients { get; } + + /// + /// Gets the configuration extension. + /// + public JsonDocument? ConfigurationExtensions { get; } } diff --git a/src/HotChocolate/Fusion/src/CommandLine/Commands/ComposeCommand.cs b/src/HotChocolate/Fusion/src/CommandLine/Commands/ComposeCommand.cs index 647da8a0c72..e6a49f98a51 100644 --- a/src/HotChocolate/Fusion/src/CommandLine/Commands/ComposeCommand.cs +++ b/src/HotChocolate/Fusion/src/CommandLine/Commands/ComposeCommand.cs @@ -72,7 +72,7 @@ private static async Task ExecuteAsync( packageFile.Directory.Create(); } - // Append file extension if not exists. + // Append file extension if not exists. if (!packageFile.Extension.EqualsOrdinal(Extensions.FusionPackage) && !packageFile.Extension.EqualsOrdinal(Extensions.ZipPackage)) { @@ -228,7 +228,7 @@ private static async Task ResolveSubgraphPackagesAsync( extensions = new[] { await File.ReadAllTextAsync(extensionFile, cancellationToken) }; } - temp.Add(new SubgraphConfiguration(conf.Name, schema, extensions, conf.Clients)); + temp.Add(new SubgraphConfiguration(conf.Name, schema, extensions, conf.Clients, conf.Extensions)); } } else @@ -363,4 +363,4 @@ public sealed class Transport [JsonPropertyOrder(10)] public string? DefaultClientName { get; set; } = "Fusion"; } -} \ No newline at end of file +} diff --git a/src/HotChocolate/Fusion/src/CommandLine/Helpers/PackageHelper.cs b/src/HotChocolate/Fusion/src/CommandLine/Helpers/PackageHelper.cs index f81f0832787..73f56c8b16f 100644 --- a/src/HotChocolate/Fusion/src/CommandLine/Helpers/PackageHelper.cs +++ b/src/HotChocolate/Fusion/src/CommandLine/Helpers/PackageHelper.cs @@ -19,11 +19,11 @@ internal static class PackageHelper private const string _schemaExtensionKind = "urn:graphql:schema-extensions"; private const string _subgraphConfigKind = "urn:hotchocolate:fusion:subgraph-config"; private const string _subgraphConfigId = "subgraph-config"; - + private static readonly SyntaxSerializerOptions _serializerOptions = new() { - Indented = true, + Indented = true, MaxDirectivesPerLine = 0 }; @@ -51,7 +51,7 @@ public static async Task CreateSubgraphPackageAsync( await AddTransportConfigToPackage(package, transportConfig); await AddSchemaExtensionsToPackage(package, extensions); } - + public static async Task LoadSubgraphConfigFromSubgraphPackageAsync( string packageFile, CancellationToken ct = default) @@ -60,7 +60,7 @@ public static async Task LoadSubgraphConfigFromSubgrap var transportConfig = await ReadSubgraphConfigPartAsync(package, ct); return transportConfig; } - + public static async Task ReplaceSubgraphConfigInSubgraphPackageAsync( string packageFile, SubgraphConfigurationDto config) @@ -108,7 +108,8 @@ public static async Task ReadSubgraphPackageAsync( subgraphConfig.Name, schema.ToString(_serializerOptions), extensions.Select(t => t.ToString(_serializerOptions)).ToArray(), - subgraphConfig.Clients); + subgraphConfig.Clients, + subgraphConfig.Extensions); } public static async Task ExtractSubgraphPackageAsync( @@ -196,6 +197,12 @@ private static WebSocketClientConfiguration ReadWebSocketClientConfiguration( return new WebSocketClientConfiguration(baseAddress, clientName); } + private static JsonDocument ReadExtensions(JsonElement element) + { + var extensionText = element.GetRawText(); + return JsonDocument.Parse(extensionText); + } + private static async Task ParseSubgraphConfigAsync( Stream stream, CancellationToken ct) @@ -203,6 +210,7 @@ private static async Task ParseSubgraphConfigAsync( using var document = await JsonDocument.ParseAsync(stream, cancellationToken: ct); var configs = new List(); var subgraph = default(string?); + var jsonDocument = default(JsonDocument?); foreach (var property in document.RootElement.EnumerateObject()) { @@ -220,6 +228,10 @@ private static async Task ParseSubgraphConfigAsync( configs.Add(ReadWebSocketClientConfiguration(property.Value)); break; + case "extensions": + jsonDocument = ReadExtensions(property.Value); + break; + default: throw new NotSupportedException( $"Configuration property `{property.Value}` is not supported."); @@ -231,7 +243,7 @@ private static async Task ParseSubgraphConfigAsync( throw new InvalidOperationException("No subgraph name was specified."); } - return new SubgraphConfigurationDto(subgraph, configs); + return new SubgraphConfigurationDto(subgraph, configs, jsonDocument); } public static string FormatSubgraphConfig( @@ -255,6 +267,7 @@ public static string FormatSubgraphConfig( { writer.WriteString("clientName", config.ClientName); } + writer.WriteEndObject(); break; @@ -266,6 +279,7 @@ public static string FormatSubgraphConfig( { writer.WriteString("clientName", config.ClientName); } + writer.WriteEndObject(); break; @@ -274,6 +288,12 @@ public static string FormatSubgraphConfig( } } + if (subgraphConfig.Extensions is not null) + { + writer.WritePropertyName("extensions"); + subgraphConfig.Extensions.WriteTo(writer); + } + writer.WriteEndObject(); writer.Flush(); @@ -354,9 +374,13 @@ private static async Task AddTransportConfigToPackage( await using var writer = new StreamWriter(stream, Encoding.UTF8); await writer.WriteAsync(FormatSubgraphConfig(subgraphConfig)); - package.CreateRelationship(part.Uri, TargetMode.Internal, _subgraphConfigKind, _subgraphConfigId); + package.CreateRelationship( + part.Uri, + TargetMode.Internal, + _subgraphConfigKind, + _subgraphConfigId); } - + private static async Task ReplaceTransportConfigInPackageAsync( Package package, SubgraphConfigurationDto subgraphConfig) diff --git a/src/HotChocolate/Fusion/src/CommandLine/Helpers/SubgraphConfigurationDto.cs b/src/HotChocolate/Fusion/src/CommandLine/Helpers/SubgraphConfigurationDto.cs index 2ed18824d10..ced5083daff 100644 --- a/src/HotChocolate/Fusion/src/CommandLine/Helpers/SubgraphConfigurationDto.cs +++ b/src/HotChocolate/Fusion/src/CommandLine/Helpers/SubgraphConfigurationDto.cs @@ -1,24 +1,33 @@ +using System.Text.Json; using HotChocolate.Fusion.Composition; namespace HotChocolate.Fusion.CommandLine.Helpers; internal sealed record SubgraphConfigurationDto { - public SubgraphConfigurationDto(string name, - IReadOnlyList? clients = null) + public SubgraphConfigurationDto( + string name, + IReadOnlyList? clients = null, + JsonDocument? extensions = null) { Name = name; Clients = clients ?? Array.Empty(); + Extensions = extensions; } public string Name { get; init; } public IReadOnlyList Clients { get; init; } - public void Deconstruct(out string name, out IReadOnlyList clients) + public JsonDocument? Extensions { get; init; } + + public void Deconstruct( + out string name, + out IReadOnlyList clients, + out JsonDocument? extensions) { name = Name; clients = Clients; + extensions = Extensions; } } - diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/CommandTestBase.cs b/src/HotChocolate/Fusion/test/CommandLine.Tests/CommandTestBase.cs index 113c04439b7..8e528ccd637 100644 --- a/src/HotChocolate/Fusion/test/CommandLine.Tests/CommandTestBase.cs +++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/CommandTestBase.cs @@ -19,7 +19,7 @@ protected Files CreateFiles(SubgraphConfiguration configuration) { var files = new Files(CreateTempFile(), CreateTempFile(), new[] { CreateTempFile() }); var configJson = PackageHelper.FormatSubgraphConfig( - new(configuration.Name, configuration.Clients)); + new(configuration.Name, configuration.Clients, configuration.ConfigurationExtensions)); File.WriteAllText(files.SchemaFile, configuration.Schema); File.WriteAllText(files.TransportConfigFile, configJson); File.WriteAllText(files.ExtensionFiles[0], configuration.Extensions[0]); diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/HotChocolate.Fusion.CommandLine.Tests.csproj b/src/HotChocolate/Fusion/test/CommandLine.Tests/HotChocolate.Fusion.CommandLine.Tests.csproj index 599b989c16a..daad547f725 100644 --- a/src/HotChocolate/Fusion/test/CommandLine.Tests/HotChocolate.Fusion.CommandLine.Tests.csproj +++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/HotChocolate.Fusion.CommandLine.Tests.csproj @@ -17,6 +17,13 @@ Always + + Always + + + + + diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/PackageHelperTests.cs b/src/HotChocolate/Fusion/test/CommandLine.Tests/PackageHelperTests.cs index 3b5acbdf707..e35eb29271f 100644 --- a/src/HotChocolate/Fusion/test/CommandLine.Tests/PackageHelperTests.cs +++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/PackageHelperTests.cs @@ -1,4 +1,6 @@ using System.Collections.Concurrent; +using System.Text; +using System.Text.Json; using CookieCrumble; using HotChocolate.Fusion.CommandLine.Helpers; using HotChocolate.Fusion.Composition; @@ -30,7 +32,33 @@ await CreateSubgraphPackageAsync( // assert Assert.True(File.Exists(packageFile)); - + + var accountConfigRead = await ReadSubgraphPackageAsync(packageFile); + Match(accountConfig); + Match(accountConfigRead); + } + + [Fact] + public async Task Create_Extract_Extensions() + { + // arrange + using var demoProject = await DemoProject.CreateAsync(); + var extensions = JsonDocument.Parse("{ \"foo\": \"bar\" }"); + var accountConfig = demoProject.Accounts.ToConfiguration(AccountsExtensionSdl, extensions); + var account = CreateFiles(accountConfig); + var packageFile = CreateTempFile(); + + // act + await CreateSubgraphPackageAsync( + packageFile, + new SubgraphFiles( + account.SchemaFile, + account.TransportConfigFile, + account.ExtensionFiles)); + + // assert + Assert.True(File.Exists(packageFile)); + var accountConfigRead = await ReadSubgraphPackageAsync(packageFile); Match(accountConfig); Match(accountConfigRead); @@ -46,12 +74,24 @@ private void Match(SubgraphConfiguration config) { snapshot.Add(extension, nameof(config.Extensions)); } - + foreach (var client in config.Clients) { snapshot.Add(client, nameof(config.Clients)); } + if (config.ConfigurationExtensions is not null) + { + using var stream = new MemoryStream(); + using var writer = + new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true }); + config.ConfigurationExtensions.WriteTo(writer); + writer.Flush(); + + var json = Encoding.UTF8.GetString(stream.ToArray()); + snapshot.Add(json, nameof(config.ConfigurationExtensions)); + } + snapshot.Match(); } } diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/PackageHelperTests.Create_Extract_Extensions.snap b/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/PackageHelperTests.Create_Extract_Extensions.snap new file mode 100644 index 00000000000..a61312e8ece --- /dev/null +++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/PackageHelperTests.Create_Extract_Extensions.snap @@ -0,0 +1,94 @@ +Name +--------------- +Accounts +--------------- + +Schema +--------------- +schema { + query: Query + mutation: Mutation +} + +"The node interface is implemented by entities that have a global unique identifier." +interface Node { + id: ID! +} + +type Query { + "Fetches an object given its ID." + node("ID of the object." id: ID!): Node + "Lookup nodes by a list of IDs." + nodes("The list of node IDs." ids: [ID!]!): [Node]! + users: [User!]! + userById(id: ID!): User + usersById(ids: [ID!]!): [User!]! + viewer: Viewer! +} + +type Mutation { + addUser(input: AddUserInput!): AddUserPayload! +} + +"The `Date` scalar represents an ISO-8601 compliant date type." +scalar Date + +type User implements Node { + id: ID! + name: String! + birthdate: Date! + username: String! +} + +type Viewer { + user: User + data: SomeData! +} + +type SomeData { + accountValue: String! +} + +input AddUserInput { + name: String! + username: String! + birthdate: Date! +} + +type AddUserPayload { + user: User +} +--------------- + +Extensions +--------------- +extend type Query { + userById(id: ID! + @is(field: "id")): User! + usersById(ids: [ID!]! + @is(field: "id")): [User!]! +} +--------------- + +Clients +--------------- +{ + "ClientName": null, + "BaseAddress": "http://localhost:5000/graphql" +} +--------------- + +Clients +--------------- +{ + "ClientName": null, + "BaseAddress": "ws://localhost:5000/graphql" +} +--------------- + +ConfigurationExtensions +--------------- +{ + "foo": "bar" +} +--------------- diff --git a/src/HotChocolate/Fusion/test/Composition.Tests/CompositionTestBase.cs b/src/HotChocolate/Fusion/test/Composition.Tests/CompositionTestBase.cs index 2fd5ee78518..2f378e95494 100644 --- a/src/HotChocolate/Fusion/test/Composition.Tests/CompositionTestBase.cs +++ b/src/HotChocolate/Fusion/test/Composition.Tests/CompositionTestBase.cs @@ -16,7 +16,8 @@ protected async Task Succeed(string schema, string[]? extensions = null) "A", schema, extensions ?? Array.Empty(), - new[] { new HttpClientConfiguration(new Uri("https://localhost:5001/graphql")) }); + new[] { new HttpClientConfiguration(new Uri("https://localhost:5001/graphql")) }, + null); // act var composer = new FusionGraphComposer(logFactory: _logFactory); @@ -34,13 +35,15 @@ protected async Task Succeed(string schema, string schemaB) "A", schema, Array.Empty(), - new[] { new HttpClientConfiguration(new Uri("https://localhost:5001/graphql")) }); + new[] { new HttpClientConfiguration(new Uri("https://localhost:5001/graphql")) }, + null); var configB = new SubgraphConfiguration( "B", schemaB, Array.Empty(), - new[] { new HttpClientConfiguration(new Uri("https://localhost:5002/graphql")) }); + new[] { new HttpClientConfiguration(new Uri("https://localhost:5002/graphql")) }, + null); // act var composer = new FusionGraphComposer(logFactory: _logFactory); @@ -58,13 +61,15 @@ protected async Task Fail(string schemaA, string schemaB) "A", schemaA, Array.Empty(), - new[] { new HttpClientConfiguration(new Uri("https://localhost:5001/graphql")) }); + new[] { new HttpClientConfiguration(new Uri("https://localhost:5001/graphql")) }, + null); var configB = new SubgraphConfiguration( "B", schemaB, Array.Empty(), - new[] { new HttpClientConfiguration(new Uri("https://localhost:5002/graphql")) }); + new[] { new HttpClientConfiguration(new Uri("https://localhost:5002/graphql")) }, + null); // act var log = new ErrorCompositionLog(); diff --git a/src/HotChocolate/Fusion/test/Composition.Tests/DataTypesTests.cs b/src/HotChocolate/Fusion/test/Composition.Tests/DataTypesTests.cs index d8572c2e33c..fc0d60f1de3 100644 --- a/src/HotChocolate/Fusion/test/Composition.Tests/DataTypesTests.cs +++ b/src/HotChocolate/Fusion/test/Composition.Tests/DataTypesTests.cs @@ -34,7 +34,8 @@ type OtherData { } """, Array.Empty(), - new[] { new HttpClientConfiguration(new Uri("https://localhost:5001/graphql")) }); + new[] { new HttpClientConfiguration(new Uri("https://localhost:5001/graphql")) }, + null); var configB = new SubgraphConfiguration( "B", @@ -56,7 +57,8 @@ type OtherData { } """, Array.Empty(), - new[] { new HttpClientConfiguration(new Uri("https://localhost:5002/graphql")) }); + new[] { new HttpClientConfiguration(new Uri("https://localhost:5002/graphql")) }, + null); // act var composer = new FusionGraphComposer(logFactory: _logFactory); diff --git a/src/HotChocolate/Fusion/test/Composition.Tests/ErrorTests.cs b/src/HotChocolate/Fusion/test/Composition.Tests/ErrorTests.cs index a35ec9a6649..97c85f69352 100644 --- a/src/HotChocolate/Fusion/test/Composition.Tests/ErrorTests.cs +++ b/src/HotChocolate/Fusion/test/Composition.Tests/ErrorTests.cs @@ -84,7 +84,8 @@ type Query { new IClientConfiguration[] { new HttpClientConfiguration(new Uri("http://localhost")) - }) + }, + null) }); Assert.Null(fusionConfig); @@ -95,9 +96,9 @@ type Query { { Assert.Equal( "The type `int` is not declared on subgraph Test123. " + - "Check the subgraph schema for consistency.", + "Check the subgraph schema for consistency.", a.Message); Assert.Equal("HF0009", a.Code); }); } -} \ No newline at end of file +} diff --git a/src/HotChocolate/Fusion/test/Core.Tests/RequestPlannerTests.cs b/src/HotChocolate/Fusion/test/Core.Tests/RequestPlannerTests.cs index bcda1fb856b..ec73c10f394 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/RequestPlannerTests.cs +++ b/src/HotChocolate/Fusion/test/Core.Tests/RequestPlannerTests.cs @@ -1097,7 +1097,7 @@ query Query { snapshot.Add(result.QueryPlan, nameof(result.QueryPlan)); await snapshot.MatchAsync(); } - + [Fact] public async Task Query_Plan_28_Simple_Root_Data() { @@ -1107,16 +1107,16 @@ public async Task Query_Plan_28_Simple_Root_Data() type Query { data: Data } - + type Data { a: String } - + schema { query: Query } """; - + var schemaB = """ type Query { @@ -1126,18 +1126,17 @@ type Query { type Data { b: String } - + schema { query: Query } """; - - var fusionGraph = await FusionGraphComposer.ComposeAsync( - new[] - { - new SubgraphConfiguration("A", schemaA, Array.Empty(), CreateClients()), - new SubgraphConfiguration("B", schemaB, Array.Empty(), CreateClients()), - }); + + var fusionGraph = await FusionGraphComposer.ComposeAsync(new[] + { + new SubgraphConfiguration("A", schemaA, Array.Empty(), CreateClients(), null), + new SubgraphConfiguration("B", schemaB, Array.Empty(), CreateClients(), null) + }); // act var result = await CreateQueryPlanAsync( @@ -1156,7 +1155,7 @@ query Query { snapshot.Add(result.QueryPlan, nameof(result.QueryPlan)); await snapshot.MatchAsync(); } - + [Fact] public async Task Query_Plan_29_Simple_Root_List_Data() { @@ -1175,7 +1174,7 @@ type Data { query: Query } """; - + var schemaB = """ type Query { @@ -1190,13 +1189,12 @@ type Data { query: Query } """; - - var fusionGraph = await FusionGraphComposer.ComposeAsync( - new[] - { - new SubgraphConfiguration("A", schemaA, Array.Empty(), CreateClients()), - new SubgraphConfiguration("B", schemaB, Array.Empty(), CreateClients()), - }); + + var fusionGraph = await FusionGraphComposer.ComposeAsync(new[] + { + new SubgraphConfiguration("A", schemaA, Array.Empty(), CreateClients(), null), + new SubgraphConfiguration("B", schemaB, Array.Empty(), CreateClients(), null) + }); // act var result = await CreateQueryPlanAsync( @@ -1215,7 +1213,7 @@ query Query { snapshot.Add(result.QueryPlan, nameof(result.QueryPlan)); await snapshot.MatchAsync(); } - + [Fact] public async Task Query_Plan_30_Entity_Data() { @@ -1235,7 +1233,7 @@ type Entity { query: Query } """; - + var schemaB = """ type Query { @@ -1251,13 +1249,12 @@ type Entity { query: Query } """; - - var fusionGraph = await FusionGraphComposer.ComposeAsync( - new[] - { - new SubgraphConfiguration("A", schemaA, Array.Empty(), CreateClients()), - new SubgraphConfiguration("B", schemaB, Array.Empty(), CreateClients()), - }); + + var fusionGraph = await FusionGraphComposer.ComposeAsync(new[] + { + new SubgraphConfiguration("A", schemaA, Array.Empty(), CreateClients(), null), + new SubgraphConfiguration("B", schemaB, Array.Empty(), CreateClients(), null) + }); // act var result = await CreateQueryPlanAsync( diff --git a/src/HotChocolate/Fusion/test/Shared/DemoSubgraph.cs b/src/HotChocolate/Fusion/test/Shared/DemoSubgraph.cs index 386fe7c1cf0..e6656d118f9 100644 --- a/src/HotChocolate/Fusion/test/Shared/DemoSubgraph.cs +++ b/src/HotChocolate/Fusion/test/Shared/DemoSubgraph.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using HotChocolate.Fusion.Composition; using HotChocolate.Language; using HotChocolate.Language.Utilities; @@ -13,7 +14,7 @@ public sealed class DemoSubgraph Indented = true, MaxDirectivesPerLine = 0 }; - + public DemoSubgraph( string name, Uri httpEndpointUri, @@ -39,17 +40,37 @@ public DemoSubgraph( public TestServer Server { get; } public SubgraphConfiguration ToConfiguration( - string extensions, + string extensions, bool onlyHttp = false) => onlyHttp ? new SubgraphConfiguration( + Name, + Schema.ToString(_serializerOptions), + Utf8GraphQLParser.Parse(extensions).ToString(_serializerOptions), + new IClientConfiguration[] { new HttpClientConfiguration(HttpEndpointUri) }, + null) + : new SubgraphConfiguration( Name, Schema.ToString(_serializerOptions), Utf8GraphQLParser.Parse(extensions).ToString(_serializerOptions), new IClientConfiguration[] { - new HttpClientConfiguration(HttpEndpointUri) - }) + new HttpClientConfiguration(HttpEndpointUri), + new WebSocketClientConfiguration(WebSocketEndpointUri) + }, + null); + + public SubgraphConfiguration ToConfiguration( + string extensions, + JsonDocument configurationExtensions, + bool onlyHttp = false) + => onlyHttp + ? new SubgraphConfiguration( + Name, + Schema.ToString(_serializerOptions), + Utf8GraphQLParser.Parse(extensions).ToString(_serializerOptions), + new IClientConfiguration[] { new HttpClientConfiguration(HttpEndpointUri) }, + configurationExtensions) : new SubgraphConfiguration( Name, Schema.ToString(_serializerOptions), @@ -58,19 +79,17 @@ public SubgraphConfiguration ToConfiguration( { new HttpClientConfiguration(HttpEndpointUri), new WebSocketClientConfiguration(WebSocketEndpointUri) - }); + }, + configurationExtensions); - public SubgraphConfiguration ToConfiguration( - bool onlyHttp = false) - => onlyHttp + public SubgraphConfiguration ToConfiguration(bool onlyHttp = false) + => onlyHttp ? new SubgraphConfiguration( Name, Schema.ToString(_serializerOptions), Array.Empty(), - new IClientConfiguration[] - { - new HttpClientConfiguration(HttpEndpointUri) - }) + new IClientConfiguration[] { new HttpClientConfiguration(HttpEndpointUri) }, + null) : new SubgraphConfiguration( Name, Schema.ToString(_serializerOptions), @@ -79,5 +98,6 @@ public SubgraphConfiguration ToConfiguration( { new HttpClientConfiguration(HttpEndpointUri), new WebSocketClientConfiguration(WebSocketEndpointUri) - }); + }, + null); } From 892bbf8c565499d14fb3f3081c6f68362073ccf6 Mon Sep 17 00:00:00 2001 From: Marco Hamann Date: Mon, 9 Oct 2023 00:17:08 +0200 Subject: [PATCH 5/9] Added automatic GraphQL wrapper for open api specification. (#6398) --- .build/Build.Tests.2.cs | 4 + .build/Helpers.cs | 1 + .../Processing/ValueCompletion.List.cs | 25 + .../src/Types.Json/FromJsonSchemaDirective.cs | 5 +- .../Types.Json/JsonObjectTypeExtensions.cs | 13 +- ...poseCommandTests.Compose_Fusion_Graph.snap | 3 +- ....Compose_Fusion_Graph_Append_Subgraph.snap | 6 +- ...andTests.Compose_Loose_Subgraph_Files.snap | 3 +- .../OpenApi/Directory.Build.props | 10 + .../OpenApi/HotChocolate.OpenApi.sln | 36 + .../OpenApi/src/Directory.Build.props | 4 + .../Helpers/ObjectTypeFactory.cs | 80 + .../Helpers/OpenApiNamingHelper.cs | 114 + .../Helpers/OperationResolverHelper.cs | 162 + .../Helpers/Utf8JsonWriterHelper.cs | 63 + .../HotChocolate.OpenApi.csproj | 47 + .../IOpenApiWrapperMiddleware.cs | 10 + .../OpenApiFieldNameNullException.cs | 6 + .../HotChocolate.OpenApi/OpenApiWrapper.cs | 23 + .../OpenApiWrapperContext.cs | 28 + .../OpenApiWrapperContextExtensions.cs | 18 + .../OpenApiWrapperPipelineBuilder.cs | 31 + .../src/HotChocolate.OpenApi/Operation.cs | 61 + .../Pipeline/CreateInputTypesMiddleware.cs | 141 + .../Pipeline/CreateMutationTypeMiddleware.cs | 52 + .../Pipeline/CreatePayloadTypesMiddleware.cs | 48 + .../Pipeline/CreateQueryTypeMiddleware.cs | 79 + .../Pipeline/DiscoverOperationsMiddleware.cs | 54 + .../Properties/OpenApiResources.Designer.cs | 102 + .../Properties/OpenApiResources.resx | 48 + .../RequestExecutorBuilderExtension.cs | 130 + .../HotChocolate.OpenApi/SchemaTypeInfo.cs | 96 + .../HotChocolate.OpenApi/packages.lock.json | 746 ++++ .../OpenApi/tests/Directory.Build.props | 45 + .../Controller/PetStoreController.cs | 55 + .../Controller/UberController.cs | 71 + .../HotChocolate.OpenApi.Tests.csproj | 33 + .../IntegrationTests.cs | 105 + .../SchemaGenerationTests.cs | 71 + .../__resources__/PetStore.yaml | 158 + .../__resources__/Uber.json | 370 ++ ...ests.QueryPets_Returns_Results_addPet.json | 7 + ...s.QueryPets_Returns_Results_deletePet.json | 7 + ...QueryPets_Returns_Results_findAnyPets.json | 12 + ...eryPets_Returns_Results_findSinglePet.json | 7 + ...QueryUber_Returns_Results_getProducts.json | 14 + ...ionTests.QueryUber_Returns_Results_me.json | 11 + ...tStore_V3_Generates_Correct_Schema.graphql | 42 + ...V3_Generates_Correct_SkimmedSchema.graphql | 39 + ...er_Generates_Correct_SkimmedSchema.graphql | 69 + .../packages.lock.json | 3442 +++++++++++++++++ .../Utilities/HotChocolate.Utilities.csproj | 1 + 52 files changed, 6801 insertions(+), 7 deletions(-) create mode 100644 src/HotChocolate/OpenApi/Directory.Build.props create mode 100644 src/HotChocolate/OpenApi/HotChocolate.OpenApi.sln create mode 100644 src/HotChocolate/OpenApi/src/Directory.Build.props create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/ObjectTypeFactory.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/OpenApiNamingHelper.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/OperationResolverHelper.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/Utf8JsonWriterHelper.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/HotChocolate.OpenApi.csproj create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/IOpenApiWrapperMiddleware.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiFieldNameNullException.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapper.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapperContext.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapperContextExtensions.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapperPipelineBuilder.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Operation.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreateInputTypesMiddleware.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreateMutationTypeMiddleware.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreatePayloadTypesMiddleware.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreateQueryTypeMiddleware.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/DiscoverOperationsMiddleware.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Properties/OpenApiResources.Designer.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Properties/OpenApiResources.resx create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/RequestExecutorBuilderExtension.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/SchemaTypeInfo.cs create mode 100644 src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/packages.lock.json create mode 100644 src/HotChocolate/OpenApi/tests/Directory.Build.props create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/Controller/PetStoreController.cs create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/Controller/UberController.cs create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/HotChocolate.OpenApi.Tests.csproj create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/IntegrationTests.cs create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/SchemaGenerationTests.cs create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__resources__/PetStore.yaml create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__resources__/Uber.json create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_addPet.json create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_deletePet.json create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_findAnyPets.json create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_findSinglePet.json create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryUber_Returns_Results_getProducts.json create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryUber_Returns_Results_me.json create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/SchemaGenerationTests.Simple_PetStore_V3_Generates_Correct_Schema.graphql create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/SchemaGenerationTests.Simple_PetStore_V3_Generates_Correct_SkimmedSchema.graphql create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/SchemaGenerationTests.Uber_Generates_Correct_SkimmedSchema.graphql create mode 100644 src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/packages.lock.json diff --git a/.build/Build.Tests.2.cs b/.build/Build.Tests.2.cs index 77e8d817b5d..f243121e07f 100644 --- a/.build/Build.Tests.2.cs +++ b/.build/Build.Tests.2.cs @@ -81,6 +81,10 @@ partial class Build .Produces(TestResultDirectory / "*.trx") .Executes(() => RunTests(SourceDirectory / "HotChocolate" / "Neo4J" / "HotChocolate.Neo4J.sln")); + Target TestHotChocolateOpenApi => _ => _ + .Produces(TestResultDirectory / "*.trx") + .Executes(() => RunTests(SourceDirectory / "HotChocolate" / "OpenApi" / "HotChocolate.OpenApi.sln")); + Target TestHotChocolatePersistedQueries => _ => _ .Produces(TestResultDirectory / "*.trx") .Executes(() => RunTests(SourceDirectory / "HotChocolate" / "PersistedQueries" / "HotChocolate.PersistedQueries.sln")); diff --git a/.build/Helpers.cs b/.build/Helpers.cs index 2e6f8aee585..baed1f82742 100644 --- a/.build/Helpers.cs +++ b/.build/Helpers.cs @@ -28,6 +28,7 @@ static class Helpers Path.Combine("HotChocolate", "Marten"), Path.Combine("HotChocolate", "MongoDb"), Path.Combine("HotChocolate", "Neo4J"), + Path.Combine("HotChocolate", "OpenApi"), Path.Combine("HotChocolate", "Raven"), Path.Combine("HotChocolate", "Skimmed"), Path.Combine("HotChocolate", "Stitching"), diff --git a/src/HotChocolate/Core/src/Execution/Processing/ValueCompletion.List.cs b/src/HotChocolate/Core/src/Execution/Processing/ValueCompletion.List.cs index 6dd3913c018..2f3592de7bf 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/ValueCompletion.List.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/ValueCompletion.List.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Text.Json; using HotChocolate.Types; using static HotChocolate.Execution.ErrorHelper; using static HotChocolate.Execution.Processing.PathHelper; @@ -89,6 +90,30 @@ internal static partial class ValueCompletion return resultList; } + if (result is JsonElement { ValueKind: JsonValueKind.Array } node) + { + var resultList = operationContext.Result.RentList(4); + resultList.IsNullable = elementType.Kind is not TypeKind.NonNull; + resultList.SetParent(parent, index); + + var i = 0; + foreach (var element in node.EnumerateArray()) + { + if (resultList.Count == resultList.Capacity) + { + resultList.Grow(); + } + + if (!TryCompleteElement(context, selection, elementType, isLeafType, resultList, i++, element)) + { + operationContext.Result.AddRemovedResult(resultList); + return null; + } + } + + return resultList; + } + var errorPath = CreatePathFromContext(selection, parent, index); var error = ListValueIsNotSupported(result.GetType(), selection.SyntaxNode, errorPath); operationContext.ReportError(error, resolverContext, selection); diff --git a/src/HotChocolate/Core/src/Types.Json/FromJsonSchemaDirective.cs b/src/HotChocolate/Core/src/Types.Json/FromJsonSchemaDirective.cs index 7a30661e2fd..481d3700da4 100644 --- a/src/HotChocolate/Core/src/Types.Json/FromJsonSchemaDirective.cs +++ b/src/HotChocolate/Core/src/Types.Json/FromJsonSchemaDirective.cs @@ -29,7 +29,8 @@ public void ApplyConfiguration( if (type.IsListType()) { - throw ThrowHelper.CannotInferTypeFromJsonObj(ctx.Type.Name); + JsonObjectTypeExtensions.InferListResolver(def); + return; } if (namedType is ScalarType scalarType) @@ -46,7 +47,7 @@ public void ApplyConfiguration( } } - private string? GetPropertyName(DirectiveNode directive) + private static string? GetPropertyName(DirectiveNode directive) { if (directive.Arguments.Count == 0) { diff --git a/src/HotChocolate/Core/src/Types.Json/JsonObjectTypeExtensions.cs b/src/HotChocolate/Core/src/Types.Json/JsonObjectTypeExtensions.cs index e33e0a6fac9..afd3410a36f 100644 --- a/src/HotChocolate/Core/src/Types.Json/JsonObjectTypeExtensions.cs +++ b/src/HotChocolate/Core/src/Types.Json/JsonObjectTypeExtensions.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.Text.Json; +using System.Threading.Tasks; using HotChocolate.Resolvers; using HotChocolate.Types.Descriptors.Definitions; @@ -44,7 +46,8 @@ public static IObjectFieldDescriptor FromJson( if (type.IsListType()) { - throw ThrowHelper.CannotInferTypeFromJsonObj(ctx.Type.Name); + InferListResolver(def); + return; } if (namedType is ScalarType scalarType) @@ -98,6 +101,11 @@ public static IObjectFieldDescriptor FromJson( return descriptor; } + internal static void InferListResolver(ObjectFieldDefinition def) + { + def.PureResolver = ctx => new ValueTask(ctx.ToEnumerable()); + } + internal static void InferResolver( ITypeSystemObject type, ObjectFieldDefinition def, @@ -257,6 +265,9 @@ internal static void InferResolver( } } + private static IEnumerable ToEnumerable(this IPureResolverContext context) + => context.Parent().EnumerateArray(); + private static JsonElement? GetProperty(this IPureResolverContext context, string propertyName) => context.Parent().TryGetProperty(propertyName, out var element) ? element diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Fusion_Graph.snap b/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Fusion_Graph.snap index 64e07ec552e..5ae2aa95ee3 100644 --- a/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Fusion_Graph.snap +++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Fusion_Graph.snap @@ -121,6 +121,7 @@ Accounts Subgraph Configuration "ClientName": null, "BaseAddress": "ws://localhost:5000/graphql" } - ] + ], + "ConfigurationExtensions": null } --------------- diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Fusion_Graph_Append_Subgraph.snap b/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Fusion_Graph_Append_Subgraph.snap index d7b1f3156e7..5364c0a322e 100644 --- a/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Fusion_Graph_Append_Subgraph.snap +++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Fusion_Graph_Append_Subgraph.snap @@ -197,7 +197,8 @@ Accounts Subgraph Configuration "ClientName": null, "BaseAddress": "ws://localhost:5000/graphql" } - ] + ], + "ConfigurationExtensions": null } --------------- @@ -218,6 +219,7 @@ Reviews2 Subgraph Configuration "ClientName": null, "BaseAddress": "ws://localhost:5000/graphql" } - ] + ], + "ConfigurationExtensions": null } --------------- diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Loose_Subgraph_Files.snap b/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Loose_Subgraph_Files.snap index fbae6ca4343..3d73680ba61 100644 --- a/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Loose_Subgraph_Files.snap +++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Loose_Subgraph_Files.snap @@ -97,6 +97,7 @@ accounts Subgraph Configuration "ClientName": null, "BaseAddress": "https://localhost:3000/graphql" } - ] + ], + "ConfigurationExtensions": null } --------------- diff --git a/src/HotChocolate/OpenApi/Directory.Build.props b/src/HotChocolate/OpenApi/Directory.Build.props new file mode 100644 index 00000000000..70f4818b593 --- /dev/null +++ b/src/HotChocolate/OpenApi/Directory.Build.props @@ -0,0 +1,10 @@ + + + + + $(Library3TargetFrameworks) + enable + enable + + + diff --git a/src/HotChocolate/OpenApi/HotChocolate.OpenApi.sln b/src/HotChocolate/OpenApi/HotChocolate.OpenApi.sln new file mode 100644 index 00000000000..36f1f332309 --- /dev/null +++ b/src/HotChocolate/OpenApi/HotChocolate.OpenApi.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F2C06745-5F7C-4672-A905-17C8319CE67A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{2D2DC25A-E937-418B-945F-F8C07246D6B9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.OpenApi", "src\HotChocolate.OpenApi\HotChocolate.OpenApi.csproj", "{235A80D3-0696-403B-BB06-94E839C2F174}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HotChocolate.OpenApi.Tests", "tests\HotChocolate.OpenApi.Tests\HotChocolate.OpenApi.Tests.csproj", "{D525025A-E91A-43F8-9322-EA0B6C835208}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {235A80D3-0696-403B-BB06-94E839C2F174} = {F2C06745-5F7C-4672-A905-17C8319CE67A} + {D525025A-E91A-43F8-9322-EA0B6C835208} = {2D2DC25A-E937-418B-945F-F8C07246D6B9} + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {235A80D3-0696-403B-BB06-94E839C2F174}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {235A80D3-0696-403B-BB06-94E839C2F174}.Debug|Any CPU.Build.0 = Debug|Any CPU + {235A80D3-0696-403B-BB06-94E839C2F174}.Release|Any CPU.ActiveCfg = Release|Any CPU + {235A80D3-0696-403B-BB06-94E839C2F174}.Release|Any CPU.Build.0 = Release|Any CPU + {D525025A-E91A-43F8-9322-EA0B6C835208}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D525025A-E91A-43F8-9322-EA0B6C835208}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D525025A-E91A-43F8-9322-EA0B6C835208}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D525025A-E91A-43F8-9322-EA0B6C835208}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/src/HotChocolate/OpenApi/src/Directory.Build.props b/src/HotChocolate/OpenApi/src/Directory.Build.props new file mode 100644 index 00000000000..6b1707b5ed2 --- /dev/null +++ b/src/HotChocolate/OpenApi/src/Directory.Build.props @@ -0,0 +1,4 @@ + + + + diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/ObjectTypeFactory.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/ObjectTypeFactory.cs new file mode 100644 index 00000000000..54d2943ecc4 --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/ObjectTypeFactory.cs @@ -0,0 +1,80 @@ +using HotChocolate.OpenApi.Properties; +using HotChocolate.Skimmed; +using HotChocolate.Types; +using Microsoft.OpenApi.Models; +using INamedType = HotChocolate.Skimmed.INamedType; +using ObjectType = HotChocolate.Skimmed.ObjectType; + +namespace HotChocolate.OpenApi.Helpers; + +internal static class ObjectTypeFactory +{ + /// + /// Parses the and it fields and adds new object types + /// to context if necessary + /// + /// + /// + /// + /// + public static INamedType ParseType(OpenApiWrapperContext context, string typeName, OpenApiSchema schema) + { + if (context.MutableSchema.Types.ContainsName(typeName)) + { + return context.MutableSchema.Types[typeName]; + } + + if (Scalars.IsBuiltIn(typeName)) + { + return new ObjectType(typeName); + } + + var type = new ObjectType(typeName) + { + Description = schema.Description + }; + + var typeInfo = context.GetSchemaTypeInfo(schema); + + foreach (var property in schema.Properties) + { + var field = CreateField(context, typeInfo.RootSchema, property); + type.Fields.Add(field); + } + + foreach (var allOf in schema.AllOf) + { + foreach (var allOfProperty in allOf.Properties) + { + var field = CreateField(context, typeInfo.RootSchema, allOfProperty); + type.Fields.Add(field); + } + } + + if (!context.MutableSchema.Types.ContainsName(typeName)) + { + context.MutableSchema.Types.Add(type); + } + + return type; + } + + private static OutputField CreateField(OpenApiWrapperContext context, OpenApiSchema schema, KeyValuePair property) + { + var typeInfo = context.GetSchemaTypeInfo(property.Value); + var isRequired = schema.Required.Contains(property.Key); + var fieldType = typeInfo.GetGraphQLTypeNode(isRequired); + var field = new OutputField(OpenApiNamingHelper.GetFieldName(property.Key)) + { + Type = fieldType, + Description = property.Value.Description, + ContextData = + { + [OpenApiResources.OpenApiPropertyName] = property.Key + } + }; + + ParseType(context, fieldType.NamedType().Name, typeInfo.RootSchema); + return field; + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/OpenApiNamingHelper.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/OpenApiNamingHelper.cs new file mode 100644 index 00000000000..7ed6c02563d --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/OpenApiNamingHelper.cs @@ -0,0 +1,114 @@ +using System.Text; +using HotChocolate.Utilities; + +namespace HotChocolate.OpenApi.Helpers; + +internal static class OpenApiNamingHelper +{ + public static string GetFieldName(string value) + { + var sb = new StringBuilder(value.Length); + var toUpper = false; + var alreadyCamelCase = true; + + foreach (var c in value.AsSpan()) + { + if (char.IsLetterOrDigit(c)) + { + if (toUpper) + { + sb.Append(char.ToUpperInvariant(c)); + toUpper = false; + } + else + { + sb.Append(c); + } + + } + else if (c is '_' or '-' or ' ') + { + toUpper = true; + alreadyCamelCase = false; + } + } + + if (sb.Length > 0 && char.IsUpper(sb[0])) + { + sb[0] = char.ToLowerInvariant(sb[0]); + alreadyCamelCase = false; + } + + return alreadyCamelCase ? value : sb.ToString(); + } + + public static string GetInputTypeName(string value) + => $"{GetTypeName(value)}Input"; + + public static string GetPayloadTypeName(string value) + => $"{GetTypeName(value)}Payload"; + + public static string GetTypeName(string value) + => value.RemoveCharacterAndEnsureName(' ').EnsureStartWithUpperChar() ?? + throw new OpenApiFieldNameNullException(); + + public static string GetPathAsName(string path) + => path.RemoveCharacterAndEnsureName('/').EnsureStartWithUpperChar(); + + private static string EnsureStartWithLowerChar(this string text) + { + if (string.IsNullOrEmpty(text)) + { + return text; + } + + return char.ToLowerInvariant(text[0]) + text[1..]; + } + + private static string EnsureStartWithUpperChar(this string text) + { + if (string.IsNullOrEmpty(text)) + { + return text; + } + + return char.ToUpperInvariant(text[0]) + text[1..]; + } + + private static string RemoveCharacterAndEnsureName(this string input, char c) + { + if (string.IsNullOrEmpty(input)) + { + return string.Empty; + } + + var sb = new StringBuilder(); + var capitalizeNext = false; + + // Go through all the characters + foreach (var currentChar in input.AsSpan()) + { + // Only process alphabetic characters and spaces + if (!char.IsLetter(currentChar) && currentChar != c) + { + continue; + } + + if (currentChar == c) + { + capitalizeNext = true; // We want to capitalize the next character + } + else if (capitalizeNext) + { + sb.Append(char.ToUpper(currentChar)); + capitalizeNext = false; // Reset flag after capitalizing + } + else + { + sb.Append(currentChar); + } + } + + return NameUtils.MakeValidGraphQLName(sb.ToString()) ?? throw new OpenApiFieldNameNullException(); + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/OperationResolverHelper.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/OperationResolverHelper.cs new file mode 100644 index 00000000000..c9966edf54d --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/OperationResolverHelper.cs @@ -0,0 +1,162 @@ +using System.Net.Http.Headers; +using System.Runtime.CompilerServices; +using System.Text; +using System.Text.Json; +using HotChocolate.Language; +using HotChocolate.Resolvers; +using HotChocolate.Utilities; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.ObjectPool; +using Microsoft.OpenApi.Models; +using static HotChocolate.OpenApi.Properties.OpenApiResources; + +namespace HotChocolate.OpenApi.Helpers; + +internal static class OperationResolverHelper +{ + private static readonly JsonDocument _successResult = JsonDocument.Parse(BoolSuccessResult); + + public static Func> CreateResolverFunc(string clientName, Operation operation) + => context => ResolveAsync(context, clientName, operation); + + private static async Task ResolveAsync( + IResolverContext resolverContext, + string clientName, + Operation operation) + { + var services = resolverContext.Services; + var stringBuilderPool = services.GetRequiredService>(); + var httpClient = services.GetRequiredService().CreateClient(clientName); + + using var arrayWriter = new ArrayWriter(); + var sb = stringBuilderPool.Get(); + sb.Clear(); + + var request = CreateRequest(resolverContext, operation, arrayWriter, sb); + stringBuilderPool.Return(sb); + + var response = await httpClient.SendAsync(request); + + if (!response.IsSuccessStatusCode) + { + throw new InvalidOperationException(await response.Content.ReadAsStringAsync()); + } + + var responseBuffer = await response.Content.ReadAsByteArrayAsync(); + return ParseResponse(operation, responseBuffer); + } + + private static JsonElement ParseResponse(Operation operation, ReadOnlySpan response) + { + if (response.Length == 0 && operation.Response?.Reference is null) + { + return _successResult.RootElement; + } + + var reader = new Utf8JsonReader(response, true, default); + return JsonElement.ParseValue(ref reader); + } + + private static HttpRequestMessage CreateRequest( + IResolverContext resolverContext, + Operation operation, + ArrayWriter arrayWriter, + StringBuilder sb) + { + HttpContent? content = null; + + BuildPath(resolverContext, operation, sb); + BuildQueryString(resolverContext, operation, sb); + + if (operation.RequestBody is not null) + { + var valueNode = resolverContext.ArgumentLiteral(InputField); + + using var writer = new Utf8JsonWriter(arrayWriter); + Utf8JsonWriterHelper.WriteValueNode(writer, valueNode); + writer.Flush(); + + content = new ByteArrayContent(arrayWriter.GetInternalBuffer(), 0, arrayWriter.Length); + content.Headers.ContentType = new MediaTypeHeaderValue(JsonMediaType); + } + + var request = new HttpRequestMessage(operation.Method, sb.ToString()); + + if (content is not null) + { + request.Content = content; + } + + return request; + } + + private static void BuildPath(IResolverContext resolverContext, Operation operation, StringBuilder sb) + { + sb.Append(operation.Path); + + ref var parameter = ref operation.GetParameterRef(); + ref var end = ref Unsafe.Add(ref parameter, operation.Parameters.Count); + + while (Unsafe.IsAddressLessThan(ref parameter, ref end)) + { + var pathValue = operation.Method == HttpMethod.Get + ? resolverContext.ArgumentValue(parameter.Name) + : GetValueOfValueNode( + resolverContext.ArgumentLiteral(InputField), + parameter.Name); + sb.Replace($"{{{parameter.Name}}}", pathValue); + parameter = ref Unsafe.Add(ref parameter, 1); + } + } + + private static void BuildQueryString(IResolverContext resolverContext, Operation operation, StringBuilder sb) + { + ref var parameter = ref operation.GetParameterRef(); + ref var end = ref Unsafe.Add(ref parameter, operation.Parameters.Count); + var next = false; + + while (Unsafe.IsAddressLessThan(ref parameter, ref end)) + { + if (parameter.In == ParameterLocation.Query) + { + var pathValue = operation.Method == HttpMethod.Get + ? resolverContext.ArgumentValue(parameter.Name) + : GetValueOfValueNode( + resolverContext.ArgumentLiteral(InputField), + parameter.Name); + + if (next) + { + sb.Append('&'); + } + else + { + sb.Append('?'); + next = true; + } + + sb.Append(parameter.Name); + sb.Append('='); + sb.Append(pathValue); + } + + parameter = ref Unsafe.Add(ref parameter, 1); + } + } + + private static string GetJsonValueOfInputNode(IValueNode valueNode) + { + using var arrayWriter = new ArrayWriter(); + using var writer = new Utf8JsonWriter(arrayWriter); + Utf8JsonWriterHelper.WriteValueNode(writer, valueNode); + writer.Flush(); + return Encoding.UTF8.GetString(arrayWriter.GetInternalBuffer(), 0, arrayWriter.Length); + } + + private static string GetValueOfValueNode(IValueNode input, string fieldName) + { + var json = GetJsonValueOfInputNode(input); + using var document = JsonDocument.Parse(json); + return document.RootElement.GetProperty(fieldName).GetRawText(); + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/Utf8JsonWriterHelper.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/Utf8JsonWriterHelper.cs new file mode 100644 index 00000000000..f69a33ec69a --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Helpers/Utf8JsonWriterHelper.cs @@ -0,0 +1,63 @@ +using System.Text.Json; +using HotChocolate.Language; + +namespace HotChocolate.OpenApi.Helpers; + +internal static class Utf8JsonWriterHelper +{ + public static void WriteValueNode( + Utf8JsonWriter writer, + IValueNode value) + { + switch (value) + { + case ObjectValueNode objectValue: + writer.WriteStartObject(); + + for (var i = 0; i < objectValue.Fields.Count; i++) + { + var field = objectValue.Fields[i]; + writer.WritePropertyName(field.Name.Value); + WriteValueNode(writer, field.Value); + } + + writer.WriteEndObject(); + break; + + case ListValueNode listValue: + writer.WriteStartArray(); + + for (var i = 0; i < listValue.Items.Count; i++) + { + var item = listValue.Items[i]; + WriteValueNode(writer, item); + } + + writer.WriteEndArray(); + break; + + case StringValueNode stringValue: + writer.WriteStringValue(stringValue.Value); + break; + + case IntValueNode intValue: + writer.WriteRawValue(intValue.Value); + break; + + case FloatValueNode floatValue: + writer.WriteRawValue(floatValue.Value); + break; + + case BooleanValueNode booleanValue: + writer.WriteBooleanValue(booleanValue.Value); + break; + + case EnumValueNode enumValue: + writer.WriteStringValue(enumValue.Value); + break; + + default: + throw new NotSupportedException(); + } + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/HotChocolate.OpenApi.csproj b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/HotChocolate.OpenApi.csproj new file mode 100644 index 00000000000..f0da8c7ed5c --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/HotChocolate.OpenApi.csproj @@ -0,0 +1,47 @@ + + + + HotChocolate.OpenApi + HotChocolate.OpenApi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ResXFileCodeGenerator + OpenApi.Designer.cs + + + + + + True + True + OpenApiResources.resx + + + + diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/IOpenApiWrapperMiddleware.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/IOpenApiWrapperMiddleware.cs new file mode 100644 index 00000000000..ca39d7aabb1 --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/IOpenApiWrapperMiddleware.cs @@ -0,0 +1,10 @@ +namespace HotChocolate.OpenApi; + +internal interface IOpenApiWrapperMiddleware +{ + void Invoke(OpenApiWrapperContext context, OpenApiWrapperDelegate next); +} + +internal delegate OpenApiWrapperDelegate OpenApiWrapperMiddleware(OpenApiWrapperDelegate next); + +internal delegate void OpenApiWrapperDelegate(OpenApiWrapperContext context); diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiFieldNameNullException.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiFieldNameNullException.cs new file mode 100644 index 00000000000..28f672a0409 --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiFieldNameNullException.cs @@ -0,0 +1,6 @@ +using static HotChocolate.OpenApi.Properties.OpenApiResources; + +namespace HotChocolate.OpenApi; + +public sealed class OpenApiFieldNameNullException() + : Exception(OpenApiFieldNameNullException_DefaultMessage); diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapper.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapper.cs new file mode 100644 index 00000000000..1bf46b1123e --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapper.cs @@ -0,0 +1,23 @@ +using HotChocolate.OpenApi.Pipeline; +using Microsoft.OpenApi.Models; + +namespace HotChocolate.OpenApi; + +internal class OpenApiWrapper +{ + private readonly OpenApiWrapperDelegate _pipeline = + OpenApiWrapperPipelineBuilder.New() + .Use() + .Use() + .Use() + .Use() + .Use() + .Build(); + + public Skimmed.Schema Wrap(string clientName, OpenApiDocument openApi) + { + var context = new OpenApiWrapperContext(clientName, openApi); + _pipeline.Invoke(context); + return context.MutableSchema; + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapperContext.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapperContext.cs new file mode 100644 index 00000000000..d8656574f3b --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapperContext.cs @@ -0,0 +1,28 @@ +using HotChocolate.Skimmed; +using Microsoft.OpenApi.Models; + +namespace HotChocolate.OpenApi; + +internal sealed class OpenApiWrapperContext( string clientName, OpenApiDocument openApiDocument) +{ + private readonly Dictionary _schemaTypeInfos = new(); + + public OpenApiDocument OpenApiDocument { get; } = openApiDocument; + public string ClientName { get; } = clientName; + public Dictionary Operations { get; } = new(); + public Dictionary OperationInputTypeLookup { get; } = new(); + public Dictionary OperationPayloadTypeLookup { get; } = new(); + public Skimmed.Schema MutableSchema { get; } = new(); + + public SchemaTypeInfo GetSchemaTypeInfo(OpenApiSchema schema) + { + if (_schemaTypeInfos.TryGetValue(schema, out var typeInfo)) + { + return typeInfo; + } + + var newTypeInfo = new SchemaTypeInfo(schema); + _schemaTypeInfos.Add(schema, newTypeInfo); + return newTypeInfo; + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapperContextExtensions.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapperContextExtensions.cs new file mode 100644 index 00000000000..897e2fcae5f --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapperContextExtensions.cs @@ -0,0 +1,18 @@ +using Microsoft.OpenApi.Models; + +namespace HotChocolate.OpenApi; + +internal static class OpenApiWrapperContextExtensions +{ + public static OpenApiSchema? GetSchema(this OpenApiWrapperContext ctx, string? name) + { + ctx.OpenApiDocument.Components.Schemas.TryGetValue(name ?? string.Empty, out var schema); + return schema; + } + + public static List> GetQueryOperations(this OpenApiWrapperContext ctx) + => ctx.Operations.Where(o => o.Value.Method == HttpMethod.Get).ToList(); + + public static List> GetMutationOperations(this OpenApiWrapperContext ctx) + => ctx.Operations.Where(o => o.Value.Method != HttpMethod.Get).ToList(); +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapperPipelineBuilder.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapperPipelineBuilder.cs new file mode 100644 index 00000000000..59a8e10773b --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/OpenApiWrapperPipelineBuilder.cs @@ -0,0 +1,31 @@ +namespace HotChocolate.OpenApi; + +internal sealed class OpenApiWrapperPipelineBuilder +{ + private readonly List _pipeline = new(); + + private OpenApiWrapperPipelineBuilder() + { + } + + public OpenApiWrapperDelegate Build() + { + OpenApiWrapperDelegate next = _ => { }; + for (var i = _pipeline.Count - 1; i >= 0; i--) next = _pipeline[i].Invoke(next); + return next; + } + + public static OpenApiWrapperPipelineBuilder New() => new(); + + public OpenApiWrapperPipelineBuilder Use() + where TMiddleware : IOpenApiWrapperMiddleware, new() + { + _pipeline.Add(next => + { + var middleware = new TMiddleware(); + return context => middleware.Invoke(context, next); + }); + + return this; + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Operation.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Operation.cs new file mode 100644 index 00000000000..7d2e83506b4 --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Operation.cs @@ -0,0 +1,61 @@ +using System.Runtime.InteropServices; +using Microsoft.OpenApi.Models; + +namespace HotChocolate.OpenApi; +/// +/// Container class which represents all necessary data +/// of a rest operation +/// +internal sealed class Operation(string operationId, string path, HttpMethod method, OpenApiOperation openApiOperation) +{ + private readonly List _parameters = new(); + + /// + /// Id of the operation + /// + public string OperationId { get; set; } = operationId; + + /// + /// An optional description of the operation + /// + public string? Description { get; set; } + + /// + /// Relative url path e.g. /pets + /// + public string Path { get; set; } = path; + + /// + /// Http method e.g. POST + /// + public HttpMethod Method { get; set; } = method; + + /// + /// Direct reference to the deserialized + /// + public OpenApiOperation OpenApiOperation { get; set; } = openApiOperation; + + /// + /// A list of all parameter which can be part of url query, header, cookie + /// + public IReadOnlyList Parameters => _parameters; + + /// + /// Optional request body e.g some json for post operations + /// + public OpenApiRequestBody? RequestBody { get; set; } + + /// + /// Direct reference to the deserialized + /// + public OpenApiResponse? Response { get; set; } + + /// + /// Adds a parameter to the parameter list + /// + /// + public void AddParameter(OpenApiParameter parameter) => _parameters.Add(parameter); + + internal ref OpenApiParameter GetParameterRef() + => ref MemoryMarshal.GetReference(CollectionsMarshal.AsSpan(_parameters)); +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreateInputTypesMiddleware.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreateInputTypesMiddleware.cs new file mode 100644 index 00000000000..11d1ae71d95 --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreateInputTypesMiddleware.cs @@ -0,0 +1,141 @@ +using HotChocolate.OpenApi.Helpers; +using HotChocolate.Skimmed; +using Microsoft.OpenApi.Models; +using InputField = HotChocolate.Skimmed.InputField; +using InputObjectType = HotChocolate.Skimmed.InputObjectType; +using IType = HotChocolate.Skimmed.IType; +using ScalarType = HotChocolate.Skimmed.ScalarType; + +namespace HotChocolate.OpenApi.Pipeline; + + +/// +/// Parses all operations and creates input type where it's necessary +/// +internal sealed class CreateInputTypesMiddleware : IOpenApiWrapperMiddleware +{ + /// + public void Invoke(OpenApiWrapperContext context, OpenApiWrapperDelegate next) + { + CreateQueryInputTypes(context); + CreateMutationInputTypes(context); + + next.Invoke(context); + } + + private static void CreateQueryInputTypes(OpenApiWrapperContext context) + { + foreach (var operation in context.GetQueryOperations()) + { + foreach (var parameter in operation.Value.Parameters) + { + CreateInputTypeForNonScalar(context, parameter.Schema); + } + + if (operation.Value.RequestBody is { } requestBody && + requestBody.Content.FirstOrDefault().Value.Schema is {} schema) + { + CreateInputTypeForNonScalar(context, schema); + } + } + } + + private static void CreateInputTypeForNonScalar(OpenApiWrapperContext context, OpenApiSchema schema) + { + var typeInfo = context.GetSchemaTypeInfo(schema); + + if (!typeInfo.IsScalar) + { + CreateInputType(context, schema); + } + } + + private static void CreateMutationInputTypes(OpenApiWrapperContext context) + { + foreach (var operation in context.GetMutationOperations()) + { + AddInputType(context, operation.Value); + } + } + + private static void AddInputType(OpenApiWrapperContext context, Operation operation) + { + var inputType = new InputObjectType(OpenApiNamingHelper.GetInputTypeName(operation.OperationId)); + + foreach (var parameter in operation.Parameters) + { + AddInputField(parameter.Name, parameter.Required, context, parameter.Schema, inputType); + } + + if (operation.RequestBody is { } requestBody && + requestBody.Content.FirstOrDefault().Value.Schema is {} schema) + { + AddFieldsToInputType(context, schema, inputType); + } + + AddIfNecessary(context, inputType); + context.OperationInputTypeLookup[operation.OperationId] = inputType; + } + + private static void AddIfNecessary(OpenApiWrapperContext context, InputObjectType inputObjectType) + { + if (context.MutableSchema.Types.ContainsName(inputObjectType.Name)) return; + context.MutableSchema.Types.Add(inputObjectType); + } + + private static void AddInputField( + string fieldName, + bool required, + OpenApiWrapperContext context, + OpenApiSchema schema, + InputObjectType inputType) + { + var graphQLName = OpenApiNamingHelper.GetFieldName(fieldName); + var typeInfo = context.GetSchemaTypeInfo(schema); + + IType type = typeInfo.IsScalar + ? new ScalarType(typeInfo.GraphQLTypeName) + : CreateInputType(context, schema); + type = required ? new NonNullType(type) : type; + + inputType.Fields.Add(new InputField(graphQLName, type)); + } + + private static InputObjectType CreateInputType(OpenApiWrapperContext context, OpenApiSchema schema) + { + var inputType = new InputObjectType(OpenApiNamingHelper.GetInputTypeName(schema.Reference.Id)); + AddFieldsToInputType(context, schema, inputType); + + AddIfNecessary(context, inputType); + return inputType; + } + + private static void AddFieldsToInputType( + OpenApiWrapperContext context, + OpenApiSchema schema, + InputObjectType inputType) + { + foreach (var schemaProperty in schema.Properties) + { + AddInputField( + schemaProperty.Key, + schema.Required.Contains(schemaProperty.Key), + context, + schemaProperty.Value, + inputType); + } + + foreach (var allOf in schema.AllOf) + { + foreach (var allOfProperty in allOf.Properties) + { + AddInputField( + allOfProperty.Key, + allOf.Required.Contains(allOfProperty.Key), + context, + allOfProperty.Value, + inputType); + } + } + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreateMutationTypeMiddleware.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreateMutationTypeMiddleware.cs new file mode 100644 index 00000000000..9bac554ab20 --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreateMutationTypeMiddleware.cs @@ -0,0 +1,52 @@ +using System.Text.Json; +using HotChocolate.OpenApi.Helpers; +using HotChocolate.OpenApi.Properties; +using HotChocolate.Resolvers; +using HotChocolate.Skimmed; +using static HotChocolate.OpenApi.Helpers.OpenApiNamingHelper; + +namespace HotChocolate.OpenApi.Pipeline; + +/// +/// Creates the mutation type based on all operations +/// +internal sealed class CreateMutationTypeMiddleware : IOpenApiWrapperMiddleware +{ + /// + public void Invoke(OpenApiWrapperContext context, OpenApiWrapperDelegate next) + { + CreateMutationType(context); + next.Invoke(context); + } + + private static void CreateMutationType(OpenApiWrapperContext context) + { + var operations = context.GetMutationOperations(); + + if (operations.Count == 0) return; + + var mutationType = new ObjectType(OpenApiResources.RootTypeMutation); + + foreach (var operation in operations) + { + var outputField = new OutputField(GetFieldName(operation.Value.OperationId)) + { + Type = context.OperationPayloadTypeLookup[operation.Value.OperationId] + }; + + if (operation.Value.Parameters.Count > 0 || operation.Value.RequestBody is not null) + { + var inputField = new InputField( + OpenApiResources.InputField, + context.OperationInputTypeLookup[operation.Value.OperationId]); + outputField.Arguments.Add(inputField); + } + mutationType.Fields.Add(outputField); + + outputField.ContextData[OpenApiResources.ContextResolverParameter] = + OperationResolverHelper.CreateResolverFunc(context.ClientName, operation.Value); + } + + context.MutableSchema.MutationType = mutationType; + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreatePayloadTypesMiddleware.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreatePayloadTypesMiddleware.cs new file mode 100644 index 00000000000..02b2dc346d6 --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreatePayloadTypesMiddleware.cs @@ -0,0 +1,48 @@ +using HotChocolate.OpenApi.Helpers; +using HotChocolate.OpenApi.Properties; +using HotChocolate.Skimmed; +using ObjectType = HotChocolate.Skimmed.ObjectType; + +namespace HotChocolate.OpenApi.Pipeline; + +/// +/// Creates payload types for all mutation operations +/// +internal sealed class CreatePayloadTypesMiddleware : IOpenApiWrapperMiddleware +{ + /// + public void Invoke(OpenApiWrapperContext context, OpenApiWrapperDelegate next) + { + var operations = context.GetMutationOperations(); + + foreach (var operation in operations) + { + CreatePayloadType(context, operation.Value); + } + + next.Invoke(context); + } + + private static void CreatePayloadType(OpenApiWrapperContext context, Operation operation) + { + var typeName = OpenApiNamingHelper.GetPayloadTypeName(operation.OperationId); + + var schema = operation.Response?.Content.FirstOrDefault().Value?.Schema; + if (schema is null) + { + var payloadType = new ObjectType(typeName); + var field = new OutputField(OpenApiResources.PayloadSuccessField) + { + Type = new ObjectType(nameof(Boolean)) + }; + payloadType.Fields.Add(field); + context.MutableSchema.Types.Add(payloadType); + context.OperationPayloadTypeLookup[operation.OperationId] = payloadType; + } + else + { + var payloadType = ObjectTypeFactory.ParseType(context, typeName, schema); + context.OperationPayloadTypeLookup[operation.OperationId] = payloadType; + } + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreateQueryTypeMiddleware.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreateQueryTypeMiddleware.cs new file mode 100644 index 00000000000..1842bb7a230 --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/CreateQueryTypeMiddleware.cs @@ -0,0 +1,79 @@ +using System.Text.Json; +using HotChocolate.OpenApi.Helpers; +using HotChocolate.OpenApi.Properties; +using HotChocolate.Resolvers; +using HotChocolate.Skimmed; +using InputField = HotChocolate.Skimmed.InputField; +using ObjectType = HotChocolate.Skimmed.ObjectType; + +namespace HotChocolate.OpenApi.Pipeline; + +/// +/// Creates a query type based on all operations +/// +internal sealed class CreateQueryTypeMiddleware : IOpenApiWrapperMiddleware +{ + /// + public void Invoke(OpenApiWrapperContext context, OpenApiWrapperDelegate next) + { + CreateQueryType(context); + next.Invoke(context); + } + + private static void CreateQueryType(OpenApiWrapperContext context) + { + var queryType = new ObjectType(OpenApiResources.RootTypeQuery); + + var queryOperations = context.GetQueryOperations(); + + foreach (var operation in queryOperations) + { + var schema = operation.Value.Response?.Content.First().Value.Schema; + + if (schema is null) + { + continue; + } + + var typeInfo = context.GetSchemaTypeInfo(schema); + var type = typeInfo.GetGraphQLTypeNode(false); + + var outputField = new OutputField(OpenApiNamingHelper.GetFieldName(operation.Value.OperationId)) + { + Type = type + }; + + ObjectTypeFactory.ParseType(context, type.NamedType().Name, typeInfo.RootSchema); + + queryType.Fields.Add(outputField); + + AddArguments(context, operation, outputField); + + outputField.ContextData[OpenApiResources.ContextResolverParameter] = + OperationResolverHelper.CreateResolverFunc(context.ClientName, operation.Value); + } + + context.MutableSchema.QueryType = queryType; + } + + + + private static void AddArguments( + OpenApiWrapperContext context, + KeyValuePair operation, + OutputField outputField) + { + foreach (var parameter in operation.Value.Parameters) + { + var typeInfo = context.GetSchemaTypeInfo(parameter.Schema); + outputField.Arguments.Add(new InputField(parameter.Name, typeInfo.GetGraphQLTypeNode(false))); + } + + if (operation.Value.RequestBody is { } requestBody && + requestBody.Content.FirstOrDefault().Value.Schema is {} schema) + { + var typeInfo = context.GetSchemaTypeInfo(schema); + outputField.Arguments.Add(new InputField("value", typeInfo.GetGraphQLTypeNode(false))); + } + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/DiscoverOperationsMiddleware.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/DiscoverOperationsMiddleware.cs new file mode 100644 index 00000000000..49eb04cad2d --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Pipeline/DiscoverOperationsMiddleware.cs @@ -0,0 +1,54 @@ +using System.Text.RegularExpressions; +using HotChocolate.OpenApi.Helpers; +using Microsoft.OpenApi.Models; + +namespace HotChocolate.OpenApi.Pipeline; + +/// +/// Discovers all operations of an open api document +/// +internal partial class DiscoverOperationsMiddleware : IOpenApiWrapperMiddleware +{ + private readonly Regex _successfulStatusCode = SuccessfulRegex(); + + /// + public void Invoke(OpenApiWrapperContext context, OpenApiWrapperDelegate next) + { + foreach (var openApiPath in context.OpenApiDocument.Paths) + { + var path = openApiPath.Value; + foreach (var operationKeyValue in path.Operations) + { + var response = operationKeyValue.Value.Responses + .FirstOrDefault(r => _successfulStatusCode.IsMatch(r.Key)); + + var resultOperation = new Operation( + operationKeyValue.Value.OperationId ?? + OpenApiNamingHelper.GetPathAsName(openApiPath.Key), + openApiPath.Key, + new HttpMethod(operationKeyValue.Key.ToString()), + operationKeyValue.Value) + { + Description = string.IsNullOrEmpty(operationKeyValue.Value.Description) + ? operationKeyValue.Value.Summary + : operationKeyValue.Value.Description, + Response = response.Value, + RequestBody = operationKeyValue.Value.RequestBody + }; + + foreach (var openApiParameter in operationKeyValue.Value.Parameters) + { + resultOperation.AddParameter(openApiParameter); + } + + if (context.Operations.ContainsKey(resultOperation.OperationId)) continue; + context.Operations.Add(resultOperation.OperationId, resultOperation); + } + } + + next.Invoke(context); + } + + [GeneratedRegex("2[0-9]{2}|2XX", RegexOptions.Compiled)] + private static partial Regex SuccessfulRegex(); +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Properties/OpenApiResources.Designer.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Properties/OpenApiResources.Designer.cs new file mode 100644 index 00000000000..3fb16ec8b3e --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Properties/OpenApiResources.Designer.cs @@ -0,0 +1,102 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace HotChocolate.OpenApi.Properties { + using System; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class OpenApiResources { + + private static System.Resources.ResourceManager resourceMan; + + private static System.Globalization.CultureInfo resourceCulture; + + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal OpenApiResources() { + } + + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + internal static System.Resources.ResourceManager ResourceManager { + get { + if (object.Equals(null, resourceMan)) { + System.Resources.ResourceManager temp = new System.Resources.ResourceManager("HotChocolate.OpenApi.Properties.OpenApiResources", typeof(OpenApiResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + internal static System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + internal static string RootTypeQuery { + get { + return ResourceManager.GetString("RootTypeQuery", resourceCulture); + } + } + + internal static string RootTypeMutation { + get { + return ResourceManager.GetString("RootTypeMutation", resourceCulture); + } + } + + internal static string ContextResolverParameter { + get { + return ResourceManager.GetString("ContextResolverParameter", resourceCulture); + } + } + + internal static string PayloadSuccessField { + get { + return ResourceManager.GetString("PayloadSuccessField", resourceCulture); + } + } + + internal static string InputField { + get { + return ResourceManager.GetString("InputField", resourceCulture); + } + } + + internal static string JsonMediaType { + get { + return ResourceManager.GetString("JsonMediaType", resourceCulture); + } + } + + internal static string BoolSuccessResult { + get { + return ResourceManager.GetString("BoolSuccessResult", resourceCulture); + } + } + + internal static string OpenApiPropertyName { + get { + return ResourceManager.GetString("OpenApiPropertyName", resourceCulture); + } + } + + internal static string OpenApiFieldNameNullException_DefaultMessage { + get { + return ResourceManager.GetString("OpenApiFieldNameNullException_DefaultMessage", resourceCulture); + } + } + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Properties/OpenApiResources.resx b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Properties/OpenApiResources.resx new file mode 100644 index 00000000000..51dc0182b10 --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/Properties/OpenApiResources.resx @@ -0,0 +1,48 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Query + + + Mutation + + + resolver + + + success + + + input + + + application/json + + + { "success": true } + + + OpenApiPropertyName + + + Field name cannot be null + + diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/RequestExecutorBuilderExtension.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/RequestExecutorBuilderExtension.cs new file mode 100644 index 00000000000..11fe8baa5a0 --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/RequestExecutorBuilderExtension.cs @@ -0,0 +1,130 @@ +using System.Text.Json; +using HotChocolate.Execution.Configuration; +using HotChocolate.Language; +using HotChocolate.Resolvers; +using HotChocolate.Skimmed; +using HotChocolate.Types; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Readers; +using static HotChocolate.OpenApi.Properties.OpenApiResources; +using IField = HotChocolate.Skimmed.IField; +using InputObjectType = HotChocolate.Skimmed.InputObjectType; +using ObjectType = HotChocolate.Skimmed.ObjectType; +using TypeKind = HotChocolate.Skimmed.TypeKind; + +namespace HotChocolate.OpenApi; + +public static class RequestExecutorBuilderExtension +{ + public static IRequestExecutorBuilder AddOpenApi( + this IRequestExecutorBuilder builder, + string clientName, + string openApi) + { + ArgumentNullException.ThrowIfNull(builder); + ArgumentException.ThrowIfNullOrEmpty(clientName); + ArgumentException.ThrowIfNullOrEmpty(openApi); + + var documentReader = new OpenApiStringReader(); + var wrapper = new OpenApiWrapper(); + + var document = documentReader.Read(openApi, out _); + var schema = wrapper.Wrap(clientName, document); + + builder.AddJsonSupport(); + builder.InitializeSchema(schema); + + return builder; + } + + private static void InitializeSchema( + this IRequestExecutorBuilder requestExecutorBuilder, + Skimmed.Schema schema) + { + if (schema.QueryType is { } queryType) + { + requestExecutorBuilder.AddQueryType(SetupType(queryType)); + } + + if (schema.MutationType is { } mutationType) + { + requestExecutorBuilder.AddMutationType(SetupType(mutationType)); + } + + foreach (var type in schema.Types.OfType()) + { + requestExecutorBuilder.AddObjectType(SetupType(type)); + } + + foreach (var type in schema.Types.OfType()) + { + requestExecutorBuilder.AddInputObjectType(SetupInputType(type)); + } + } + + private static Action SetupType(ComplexType skimmedType) => + desc => + { + desc.Name(skimmedType.Name) + .Description(skimmedType.Description); + + foreach (var field in skimmedType.Fields) + { + var fieldDescriptor = CreateFieldDescriptor(field, desc); + + foreach (var fieldArgument in field.Arguments) + { + fieldDescriptor.Argument( + fieldArgument.Name, + descriptor => descriptor.Type(new NamedTypeNode(fieldArgument.Type.NamedType().Name))); + } + + if (field.ContextData.TryGetValue(ContextResolverParameter, out var res) && + res is Func> resolver) + { + fieldDescriptor.Resolve(ctx => resolver.Invoke(ctx)); + } + else + { + var propertyName = field.ContextData.TryGetValue(OpenApiPropertyName, out var name) + ? name?.ToString() + : null; + fieldDescriptor.FromJson(propertyName); + } + } + }; + + private static IObjectFieldDescriptor CreateFieldDescriptor(IField field, IObjectTypeDescriptor desc) + { + ITypeNode baseType = field.Type.Kind == TypeKind.NonNull + ? new NonNullTypeNode(new NamedTypeNode(field.Type.NamedType().Name)) + : new NamedTypeNode(field.Type.NamedType().Name); + + var fieldDescriptor = desc.Field(field.Name) + .Description(field.Description) + .Type(field.Type.Kind == TypeKind.List ? new ListTypeNode(baseType) : baseType); + + return fieldDescriptor; + } + + private static Action SetupInputType(InputObjectType skimmedType) => + desc => + { + desc.Name(skimmedType.Name) + .Description(skimmedType.Description); + + foreach (var field in skimmedType.Fields) + { + ITypeNode baseType = field.Type.Kind == TypeKind.NonNull + ? new NonNullTypeNode(new NamedTypeNode(field.Type.NamedType().Name)) + : new NamedTypeNode(field.Type.NamedType().Name); + + desc.Field(field.Name) + .Description(field.Description) + .Type(field.Type.Kind == TypeKind.List + ? new ListTypeNode(baseType) + : baseType); + } + }; +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/SchemaTypeInfo.cs b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/SchemaTypeInfo.cs new file mode 100644 index 00000000000..e4d5b90363e --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/SchemaTypeInfo.cs @@ -0,0 +1,96 @@ +using HotChocolate.OpenApi.Helpers; +using HotChocolate.Types; +using Microsoft.OpenApi.Models; +using IType = HotChocolate.Skimmed.IType; +using ListType = HotChocolate.Skimmed.ListType; +using NonNullType = HotChocolate.Skimmed.NonNullType; +using ObjectType = HotChocolate.Skimmed.ObjectType; + +namespace HotChocolate.OpenApi; + +/// +/// Container class which exposes metadata and GraphQL related data +/// read of an +/// +public class SchemaTypeInfo +{ + public SchemaTypeInfo(OpenApiSchema schema) + { + Schema = schema; + + IsListType = schema.Items is not null; + + TypeName = IsListType ? schema.Items!.Type : schema.Type; + TypeName ??= IsListType ? schema.Items!.Reference.Id : schema.Reference.Id; + + Format = IsListType ? schema.Items!.Format : schema.Format; + GraphQLTypeName = GetGraphQLTypeName(TypeName, Format); + IsScalar = Scalars.IsBuiltIn(GraphQLTypeName); + } + + /// + /// The schema the information is based on + /// + public OpenApiSchema Schema { get; } + + /// + /// Is the base schema e.g. if the schema is an array it is the item schema + /// + public OpenApiSchema RootSchema => IsListType ? Schema.Items : Schema; + + /// + /// Is the schema a list type + /// + public bool IsListType { get; } + + /// + /// Is the schema scalar type + /// + public bool IsScalar { get; } + + /// + /// A graphql name for the schema + /// + public string GraphQLTypeName { get; } + + /// + /// Type name from open api + /// + public string TypeName { get; } + + /// + /// More detailed information about the type e.g + /// int64 + /// + public string? Format { get; } + + /// + /// Creates a type node of this schema + /// + /// + /// + public IType GetGraphQLTypeNode(bool required) + { + var unwrappedType = new ObjectType(GraphQLTypeName); + IType baseType = required + ? new NonNullType(unwrappedType) + : unwrappedType; + + return IsListType + ? new ListType(baseType) + : baseType; + } + + private static string GetGraphQLTypeName(string openApiSchemaTypeName, string? format) + { + var typename = openApiSchemaTypeName switch + { + "string" => ScalarNames.String, + "number" => ScalarNames.Float, + "integer" => format == "int64" ? ScalarNames.Long : ScalarNames.Int, + "boolean" => ScalarNames.Boolean, + _ => OpenApiNamingHelper.GetTypeName(openApiSchemaTypeName) + }; + return typename ?? throw new InvalidOperationException(); + } +} diff --git a/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/packages.lock.json b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/packages.lock.json new file mode 100644 index 00000000000..b0c453dcabb --- /dev/null +++ b/src/HotChocolate/OpenApi/src/HotChocolate.OpenApi/packages.lock.json @@ -0,0 +1,746 @@ +{ + "version": 1, + "dependencies": { + "net7.0": { + "Microsoft.Extensions.Http": { + "type": "Direct", + "requested": "[7.0.0, )", + "resolved": "7.0.0", + "contentHash": "9Pq9f/CvOSz0t9yQa6g1uWpxa2sm13daLFm8EZwy9MaQUjKXWdNUXQwIxwhmba5N83UIqURiPHSNqGK1vfWF2w==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0", + "Microsoft.Extensions.Logging": "7.0.0", + "Microsoft.Extensions.Logging.Abstractions": "7.0.0", + "Microsoft.Extensions.Options": "7.0.0" + } + }, + "Microsoft.OpenApi": { + "type": "Direct", + "requested": "[1.6.6, )", + "resolved": "1.6.6", + "contentHash": "7SE3RTGpdXUN+PkVN4xRrtsATgBI7BpsBvbjg6SykurEinA69vIl4S8DWPeGLaBykaCDq87/Ebf2Ashoh7Ky/g==" + }, + "Microsoft.OpenApi.Readers": { + "type": "Direct", + "requested": "[1.6.6, )", + "resolved": "1.6.6", + "contentHash": "yWNvjxTS1lN9Ix91b0+zoOCSTHr2haZSm5qokko7qRKBiVQo+EDqlY+d93pxtCLcIj6LdHe+8AdfPGi7eAwtGA==", + "dependencies": { + "Microsoft.OpenApi": "1.6.6", + "SharpYaml": "2.1.0" + } + }, + "Microsoft.SourceLink.GitHub": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "DD/LF81k5ODHCfPnBCds97N6KKSS1X1NiDcJYUUpiTu5mmuPktZplhYFrAPQPktMBKvNMdwFrwJ7Fqa3tyTIuA==", + "dependencies": { + "Microsoft.Build.Tasks.Git": "1.1.0", + "Microsoft.SourceLink.Common": "1.1.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg==" + }, + "Microsoft.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "DD84CsvKf+hfDBbYXIvBXeY7JGfbtoIMMjlPGVaKIp6aWoIdL5EJbWvk+skGkM7/Weezj3q1a89nTPAcGlGcpw==" + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "elNeOmkeX3eDVG6pYVeV82p29hr+UKDaBhrZyWvWLw/EVZSYEkZlQdkp0V39k/Xehs2Qa0mvoCvkVj3eQxNQ1Q==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "h3j/QfmFN4S0w4C2A6X7arXij/M/OVw3uQHSOFxnND4DyAzO1F9eMX7Eti7lU/OkSthEE0WzRsfT/Dmx86jzCw==" + }, + "Microsoft.Extensions.DiagnosticAdapter": { + "type": "Transitive", + "resolved": "3.1.4", + "contentHash": "JiYsxaO6FnH477kGwQLZoj1+XFgwA1ZOjnmypgGhxeLdsmL4o29dP1vfOwmwsU9+nJ5ugtqq4Xs4DcVAGSLt3w==", + "dependencies": { + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "Nw2muoNrOG5U5qa2ZekXwudUn2BJcD41e65zwmDHb1fQegTX66UokLWZkJRpqSSHXDOWZ5V0iqhbxOEky91atA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "7.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0", + "Microsoft.Extensions.Logging.Abstractions": "7.0.0", + "Microsoft.Extensions.Options": "7.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "kmn78+LPVMOWeITUjIlfxUPDsI0R6G0RkeAMBmQxAJ7vBJn4q2dTva7pWi65ceN5vPGjJ9q/Uae2WKgvfktJAw==" + }, + "Microsoft.Extensions.ObjectPool": { + "type": "Transitive", + "resolved": "3.1.4", + "contentHash": "ZmgpBTnKA2OSJjtL5A1tNSWAQn8I0ELJMW+oKMZVmVHhjG8IyqlhqkfXT9jxgPp8ddCt4t4oXsKn1HAz+sJO1A==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "lP1yBnTTU42cKpMozuafbvNtQ7QcBjr/CcK3bYOGEMH55Fjt+iecXjT6chR7vbgCMqy3PG3aNQSZgo/EuY/9qQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0", + "Microsoft.Extensions.Primitives": "7.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "um1KU5kxcRp3CNuI8o/GrZtD4AIOXDk+RLsytjZ9QPok3ttLUelLKpilVPuaFT3TFjOhSibUAso0odbOaCDj3Q==" + }, + "Microsoft.SourceLink.Common": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "TyGnSaCanfxunClp2af9jpXY127q7g5tiOv0XN/JGcalyKwYusYp06BUGSmCopg/GhmJJSiR/9PS0suXHCGxtw==" + }, + "SharpYaml": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2jBenJ6QN0mj8G3ohrNO/uNhA92OJYsQFuI5dJ4zM/HauVoC/oJzK1sCVlUaVUpuXpHUa/k1waXVkkBR2luP/w==" + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "1.7.0", + "contentHash": "RVSM6wZUo6L2y6P3vN6gjUtyJ2IF2RVtrepF3J7nrDKfFQd5u/SnSUFclchYQis8/k5scHy9E+fVeKVQLnnkzw==" + }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "0YFqjhp/mYkDGpU0Ye1GjE53HMp9UVfGN7seGpAMttAC0C40v5gw598jCgpbBLMmCo0E5YRLBv5Z2doypO49ZQ==" + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "4.7.1", + "contentHash": "j81Lovt90PDAq8kLpaJfJKV/rWdWuEk6jfV+MBkee33vzYLEUsy4gXK8laa9V2nZlLM9VM9yA/OOQxxPEJKAMw==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.7", + "contentHash": "/Tf/9XjprpHolbcDOrxsKVYy/mUG/FS7aGd9YUgBVEiHeQH4kAE0T1sMbde7q6B5xcrNUsJ5iW7D1RvHudQNqA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "gdOOXBhtt2UpTxYJm1DRmoqNfYg5ypvhzhVt0vxKhzxXFjS81r8yIOSFsJYLRa1Jc14GBAqCnjxJstO3zBN7gg==" + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "greendonut": { + "type": "Project", + "dependencies": { + "Microsoft.Extensions.ObjectPool": "[3.1.4, )", + "System.Diagnostics.DiagnosticSource": "[4.7.0, )", + "System.Threading.Tasks.Extensions": "[4.5.0, )" + } + }, + "HotChocolate": { + "type": "Project", + "dependencies": { + "HotChocolate.Authorization": "[0.0.0, )", + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Fetching": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )", + "HotChocolate.Types.CursorPagination": "[0.0.0, )", + "HotChocolate.Types.Mutations": "[0.0.0, )", + "HotChocolate.Types.OffsetPagination": "[0.0.0, )", + "HotChocolate.Validation": "[0.0.0, )" + } + }, + "hotchocolate.abstractions": { + "type": "Project", + "dependencies": { + "HotChocolate.Language": "[0.0.0, )", + "Microsoft.Bcl.AsyncInterfaces": "[1.1.0, )", + "System.Collections.Immutable": "[1.7.0, )" + } + }, + "hotchocolate.authorization": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )" + } + }, + "hotchocolate.execution": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Execution.Abstractions": "[0.0.0, )", + "HotChocolate.Fetching": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )", + "HotChocolate.Validation": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection": "[3.1.4, )", + "Microsoft.Extensions.DiagnosticAdapter": "[3.1.4, )", + "System.Threading.Channels": "[4.7.0, )" + } + }, + "hotchocolate.execution.abstractions": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )" + } + }, + "hotchocolate.fetching": { + "type": "Project", + "dependencies": { + "GreenDonut": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.language": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )", + "HotChocolate.Language.Utf8": "[0.0.0, )", + "HotChocolate.Language.Visitors": "[0.0.0, )", + "HotChocolate.Language.Web": "[0.0.0, )" + } + }, + "hotchocolate.language.syntaxtree": { + "type": "Project", + "dependencies": { + "Microsoft.Extensions.ObjectPool": "[3.1.4, )" + } + }, + "hotchocolate.language.utf8": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )" + } + }, + "hotchocolate.language.visitors": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )" + } + }, + "hotchocolate.language.web": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.Utf8": "[0.0.0, )" + } + }, + "HotChocolate.Skimmed": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Language": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )" + } + }, + "hotchocolate.types": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )", + "HotChocolate.Utilities.Introspection": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )", + "Microsoft.Extensions.ObjectPool": "[3.1.4, )", + "System.ComponentModel.Annotations": "[4.7.0, )", + "System.Text.Json": "[6.0.7, )" + } + }, + "hotchocolate.types.cursorpagination": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.json": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.mutations": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.offsetpagination": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.scalars": { + "type": "Project", + "dependencies": { + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.utilities": { + "type": "Project", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "[1.1.0, )", + "System.Memory": "[4.5.4, )", + "System.Threading.Tasks.Extensions": "[4.5.4, )" + } + }, + "hotchocolate.utilities.introspection": { + "type": "Project", + "dependencies": { + "HotChocolate.Language": "[0.0.0, )", + "System.Text.Json": "[6.0.7, )" + } + }, + "hotchocolate.validation": { + "type": "Project", + "dependencies": { + "HotChocolate.Types": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )", + "Microsoft.Extensions.Options": "[3.1.4, )" + } + } + }, + "net8.0": { + "Microsoft.Extensions.Http": { + "type": "Direct", + "requested": "[8.0.0-rc.1.23419.4, )", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "uUCk1A8XUVUEGoTATMxih15uZoF8QzBB+MZwUfB3Lj4QAQZFxWG/VbUMrUyCKpvvvncOyXgT1xq0SAyLmzUPIw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Diagnostics": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Logging": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Options": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.OpenApi": { + "type": "Direct", + "requested": "[1.6.6, )", + "resolved": "1.6.6", + "contentHash": "7SE3RTGpdXUN+PkVN4xRrtsATgBI7BpsBvbjg6SykurEinA69vIl4S8DWPeGLaBykaCDq87/Ebf2Ashoh7Ky/g==" + }, + "Microsoft.OpenApi.Readers": { + "type": "Direct", + "requested": "[1.6.6, )", + "resolved": "1.6.6", + "contentHash": "yWNvjxTS1lN9Ix91b0+zoOCSTHr2haZSm5qokko7qRKBiVQo+EDqlY+d93pxtCLcIj6LdHe+8AdfPGi7eAwtGA==", + "dependencies": { + "Microsoft.OpenApi": "1.6.6", + "SharpYaml": "2.1.0" + } + }, + "Microsoft.SourceLink.GitHub": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "DD/LF81k5ODHCfPnBCds97N6KKSS1X1NiDcJYUUpiTu5mmuPktZplhYFrAPQPktMBKvNMdwFrwJ7Fqa3tyTIuA==", + "dependencies": { + "Microsoft.Build.Tasks.Git": "1.1.0", + "Microsoft.SourceLink.Common": "1.1.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg==" + }, + "Microsoft.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "DD84CsvKf+hfDBbYXIvBXeY7JGfbtoIMMjlPGVaKIp6aWoIdL5EJbWvk+skGkM7/Weezj3q1a89nTPAcGlGcpw==" + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "NoIBM0qnZrl5o3em/5Qx4T3HcDruKdDVvm4PsG/wiuWawtwHRqaqkFjPS66lPnu1Kgzv+D1JJd+r4C5wPxXErw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Primitives": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "tY5wKwXNZ6cBeyHxvxyLy57TxUaA6H82/vW8vTTmikG9bkfRzfyS0EEDloiPzL4ln8P+3aZxeAestjPC6942Kg==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "npSDU7QSVdMjIFasVVBygHTaSd3H6rJD9zBXb6tcmAO8D7chkCJ2MarAYVKDICT5I9Hfawxv7FitJFAgNVIn3w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "q1M8U8Qhf0siOpZ0PRB7jZR8Um+Pnm4HgCL81hYDtIunWJmlqEGKjGWg/gl140K9imZUqLkePSVVQGlP7/Xo+A==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "SAv6AcbXKzvBq4kQAU5S9sW3ZOV7j4qLjqT+Iw6CLgqsSCgoJhmVvadtr8PUWaRfj4uVT9CX5V3zIojehtMq8w==" + }, + "Microsoft.Extensions.DiagnosticAdapter": { + "type": "Transitive", + "resolved": "3.1.4", + "contentHash": "JiYsxaO6FnH477kGwQLZoj1+XFgwA1ZOjnmypgGhxeLdsmL4o29dP1vfOwmwsU9+nJ5ugtqq4Xs4DcVAGSLt3w==", + "dependencies": { + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "Microsoft.Extensions.Diagnostics": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "RqerNpeQoixriNPi2RPxJWu9V6ljz3u/M9lCzwLsYtNqLKUzO3K838C8NU2uDFg0SviJyuMV1JG0RG+c9Hdglw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Diagnostics.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "ukvKfK+sgwReTEsbP3hCuXUWOCaqH7HCXGTXfqAyl6IvSJVZHWpTZAFHELcNbSz4hdAzG/8QY/4JxU5xNQOzlA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Options": "8.0.0-rc.1.23419.4", + "System.Diagnostics.DiagnosticSource": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "n39LJSx0Mpl89hhT0DWTyPyGv/z60/Ygp0b4ZE1zNy9R8O42PrsK+XFdiaKtCnpOPezX2Jq07dFyZzpCqmIvzw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Options": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "jphvzZmIDCEwl5PkxegeiO0y+zeMRg92QtY0weVFy8tH9ySgb2EwX85B78H0FYTFixFApRlmsh/pEdEs+VKbZA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.ObjectPool": { + "type": "Transitive", + "resolved": "3.1.4", + "contentHash": "ZmgpBTnKA2OSJjtL5A1tNSWAQn8I0ELJMW+oKMZVmVHhjG8IyqlhqkfXT9jxgPp8ddCt4t4oXsKn1HAz+sJO1A==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "fsKycFyh/aX7Vs9o/gOH+XBWRh5VB4iwV6xHZdvN9kDvJfBhCm2IQ/E+xaWa5KtX7tXOx0hclZ8ihK97ab3mPQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Primitives": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "7y1Ob1fZniZnTGeuurHjGAXmW0+reI4MUOZxR3Dyvu9htNSkGsrsICY2f0bIev1D+pQrFwNg/+yUOpvc46/jkg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Configuration.Binder": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Options": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Primitives": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "zyoB4zblhvpylS9VOmKyBuGH+RjKDsfi0cTB2KRPPDD6tFinpP+vGr3dictaNYLhGUg6jaBmq+2H/WZMCnvGDQ==" + }, + "Microsoft.SourceLink.Common": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "TyGnSaCanfxunClp2af9jpXY127q7g5tiOv0XN/JGcalyKwYusYp06BUGSmCopg/GhmJJSiR/9PS0suXHCGxtw==" + }, + "SharpYaml": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2jBenJ6QN0mj8G3ohrNO/uNhA92OJYsQFuI5dJ4zM/HauVoC/oJzK1sCVlUaVUpuXpHUa/k1waXVkkBR2luP/w==" + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "1.7.0", + "contentHash": "RVSM6wZUo6L2y6P3vN6gjUtyJ2IF2RVtrepF3J7nrDKfFQd5u/SnSUFclchYQis8/k5scHy9E+fVeKVQLnnkzw==" + }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "0YFqjhp/mYkDGpU0Ye1GjE53HMp9UVfGN7seGpAMttAC0C40v5gw598jCgpbBLMmCo0E5YRLBv5Z2doypO49ZQ==" + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "hdyhGAFW9nXz+UfN8XxW4iTzyef03BsIXc6AqLNbDcqw63343di6XFGFSYJ8Rh+yHlZazrGTt6keQ2GDh9avmg==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.7", + "contentHash": "/Tf/9XjprpHolbcDOrxsKVYy/mUG/FS7aGd9YUgBVEiHeQH4kAE0T1sMbde7q6B5xcrNUsJ5iW7D1RvHudQNqA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "gdOOXBhtt2UpTxYJm1DRmoqNfYg5ypvhzhVt0vxKhzxXFjS81r8yIOSFsJYLRa1Jc14GBAqCnjxJstO3zBN7gg==" + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "greendonut": { + "type": "Project", + "dependencies": { + "Microsoft.Extensions.ObjectPool": "[3.1.4, )", + "System.Diagnostics.DiagnosticSource": "[4.7.0, )", + "System.Threading.Tasks.Extensions": "[4.5.0, )" + } + }, + "HotChocolate": { + "type": "Project", + "dependencies": { + "HotChocolate.Authorization": "[0.0.0, )", + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Fetching": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )", + "HotChocolate.Types.CursorPagination": "[0.0.0, )", + "HotChocolate.Types.Mutations": "[0.0.0, )", + "HotChocolate.Types.OffsetPagination": "[0.0.0, )", + "HotChocolate.Validation": "[0.0.0, )" + } + }, + "hotchocolate.abstractions": { + "type": "Project", + "dependencies": { + "HotChocolate.Language": "[0.0.0, )", + "Microsoft.Bcl.AsyncInterfaces": "[1.1.0, )", + "System.Collections.Immutable": "[1.7.0, )" + } + }, + "hotchocolate.authorization": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )" + } + }, + "hotchocolate.execution": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Execution.Abstractions": "[0.0.0, )", + "HotChocolate.Fetching": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )", + "HotChocolate.Validation": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection": "[3.1.4, )", + "Microsoft.Extensions.DiagnosticAdapter": "[3.1.4, )", + "System.Threading.Channels": "[4.7.0, )" + } + }, + "hotchocolate.execution.abstractions": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )" + } + }, + "hotchocolate.fetching": { + "type": "Project", + "dependencies": { + "GreenDonut": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.language": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )", + "HotChocolate.Language.Utf8": "[0.0.0, )", + "HotChocolate.Language.Visitors": "[0.0.0, )", + "HotChocolate.Language.Web": "[0.0.0, )" + } + }, + "hotchocolate.language.syntaxtree": { + "type": "Project", + "dependencies": { + "Microsoft.Extensions.ObjectPool": "[3.1.4, )" + } + }, + "hotchocolate.language.utf8": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )" + } + }, + "hotchocolate.language.visitors": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )" + } + }, + "hotchocolate.language.web": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.Utf8": "[0.0.0, )" + } + }, + "HotChocolate.Skimmed": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Language": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )" + } + }, + "hotchocolate.types": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )", + "HotChocolate.Utilities.Introspection": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )", + "Microsoft.Extensions.ObjectPool": "[3.1.4, )", + "System.ComponentModel.Annotations": "[4.7.0, )", + "System.Text.Json": "[6.0.7, )" + } + }, + "hotchocolate.types.cursorpagination": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.json": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.mutations": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.offsetpagination": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.scalars": { + "type": "Project", + "dependencies": { + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.utilities": { + "type": "Project", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "[1.1.0, )", + "System.Memory": "[4.5.4, )", + "System.Threading.Tasks.Extensions": "[4.5.4, )" + } + }, + "hotchocolate.utilities.introspection": { + "type": "Project", + "dependencies": { + "HotChocolate.Language": "[0.0.0, )", + "System.Text.Json": "[6.0.7, )" + } + }, + "hotchocolate.validation": { + "type": "Project", + "dependencies": { + "HotChocolate.Types": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )", + "Microsoft.Extensions.Options": "[3.1.4, )" + } + } + } + } +} \ No newline at end of file diff --git a/src/HotChocolate/OpenApi/tests/Directory.Build.props b/src/HotChocolate/OpenApi/tests/Directory.Build.props new file mode 100644 index 00000000000..71aa355289f --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/Directory.Build.props @@ -0,0 +1,45 @@ + + + + + false + 0 + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/Controller/PetStoreController.cs b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/Controller/PetStoreController.cs new file mode 100644 index 00000000000..1a1e8f94fdc --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/Controller/PetStoreController.cs @@ -0,0 +1,55 @@ +using System.ComponentModel.DataAnnotations; +using Microsoft.AspNetCore.Mvc; +using Swashbuckle.AspNetCore.Annotations; + +namespace HotChocolate.OpenApi.Tests.Controller; + +public record NewPet([Required]string Name, string? Tag); + +public record Pet([Required]string Name, [Required] long Id, string? Tag) : NewPet(Name, Tag); + +[ApiController] +public class PetStoreController : ControllerBase +{ + private static readonly List _pets = new() + { + new Pet("Chopper", 1, null), + new Pet("Rex", 2, null), + }; + + [HttpPost] + [Route("/pets")] + public IActionResult AddPet([FromBody] NewPet body) + { + var newPet = new Pet(body.Name, _pets.Max(p => p.Id) + 1, body.Tag); + + _pets.Add(newPet); + return new ObjectResult(newPet); + } + + [HttpDelete] + [Route("/pets/{id}")] + public IActionResult DeletePet([FromRoute] [Required] long? id) + { + var toDelete = _pets.FirstOrDefault(p => p.Id == id); + + if (toDelete is null) return BadRequest("Pet not found"); + _pets.Remove(toDelete); + return Ok(); + + } + + [HttpGet] + [Route("/pets/{id}")] + public IActionResult FindPetById([FromRoute] [Required] long? id) + { + return new ObjectResult(_pets.FirstOrDefault(p => p.Id == id)); + } + + [HttpGet] + [Route("/pets")] + public IActionResult FindPets([FromQuery] List tags, [FromQuery] int? limit) + { + return new ObjectResult(_pets); + } +} diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/Controller/UberController.cs b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/Controller/UberController.cs new file mode 100644 index 00000000000..e3f67946fad --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/Controller/UberController.cs @@ -0,0 +1,71 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Mvc; + +namespace HotChocolate.OpenApi.Tests.Controller; + +public record Activities(int Offset, int Limit, int Count, Activity[] History); + +public record Activity(string Uuid); + +public record Profile( + [property: JsonPropertyName("first_name")] + string FirstName, + [property: JsonPropertyName("last_name")] + string LastName, + string Email, + string Picture, + [property: JsonPropertyName("promo_code")] + string PromoCode +); + +public record PriceEstimate( + [property: JsonPropertyName("product_id")] + string ProductId, + [property: JsonPropertyName("currency_code")] + string CurrencyCode, + [property: JsonPropertyName("display_name")] + string DisplayName, + string Estimate, + [property: JsonPropertyName("low_estimate")] + float LowEstimate, + [property: JsonPropertyName("high_estimate")] + float HighEstimate, + [property: JsonPropertyName("surge_multiplier")] + float SurgeMultiplier +); + +public record Product( + [property: JsonPropertyName("product_id")] + string ProductId, + string Description, + [property: JsonPropertyName("display_name")] + string DisplayName, + string Capacity, + string Image +); + +[ApiController] +public class UberController +{ + private static readonly List _products = new() + { + new Product("ProductA", "Desc", "Product A", "Cap", "http://img.png"), + new Product("ProductB", "Desc", "Product B", "Cap", "http://img.png") + }; + + [HttpGet] + [Route("/products")] + public IActionResult GetProducts([Required] double longitude, [Required] double latitude) => + new ObjectResult(_products); + + [HttpGet] + [Route("/me")] + public IActionResult GetMe() => new ObjectResult(new Profile( + "Max", + "Mustermann", + "max.mustermann@email.abc", + "http://img.png", + "1234" + )); +} diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/HotChocolate.OpenApi.Tests.csproj b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/HotChocolate.OpenApi.Tests.csproj new file mode 100644 index 00000000000..1c5f811aeb5 --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/HotChocolate.OpenApi.Tests.csproj @@ -0,0 +1,33 @@ + + + + false + true + + + + + + + + + + + + Always + + + + Always + + + + + + + + + + + + diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/IntegrationTests.cs b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/IntegrationTests.cs new file mode 100644 index 00000000000..e847a400080 --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/IntegrationTests.cs @@ -0,0 +1,105 @@ +using System.Text.Json; +using CookieCrumble; +using HotChocolate.Execution; +using HotChocolate.Execution.Processing; +using Microsoft.AspNetCore.TestHost; +using Moq; +using Xunit; +using static System.IO.Path; + +[assembly: CollectionBehavior(DisableTestParallelization = true)] + +namespace HotChocolate.OpenApi.Tests; + +[Collection("Open api integration tests")] +public class IntegrationTests +{ + [Theory] + [InlineData("findAnyPets", "query { findPets { name } }")] + [InlineData("findSinglePet", "query { findPetById(id: 1) { name } }")] + [InlineData("addPet", """mutation { addPet(input: {name: "Goofy" tag: "Cartoon" }) { name } }""")] + [InlineData("deletePet", """mutation { deletePet(input: { id: 1}) { success } }""")] + public async Task QueryPets_Returns_Results(string caseName, string query) + { + // Arrange + var httpClientFactoryMock = new Mock(); + var builder = new WebHostBuilder(); + builder.ConfigureServices(services => + { + services.AddRouting(); + services.AddControllers(); + }); + builder.Configure(app => + { + app.UseRouting(); + app.UseEndpoints(e => e.MapControllers()); + }); + var openApiServer = new TestServer(builder); + + httpClientFactoryMock + .Setup(f => f.CreateClient(It.IsAny())) + .Returns(() => + { + var client = openApiServer.CreateClient(); + client.BaseAddress = new Uri("http://localhost:5000"); + return client; + }); + + await openApiServer.Host.StartAsync(); + var apiDocument = await File.ReadAllTextAsync(Combine("__resources__", "PetStore.yaml")); + + var schema = await new ServiceCollection() + .AddSingleton(httpClientFactoryMock.Object) + .AddGraphQL() + .AddOpenApi("PetStore", apiDocument) + .BuildRequestExecutorAsync(); + + // Act + var result = await schema.ExecuteAsync(QueryRequestBuilder.Create(query)); + + // Assert + Assert.NotNull(result); + Snapshot.Match(result, postFix: caseName, extension: ".json"); + } + + + [Theory] + [InlineData("me", "query { me { firstName lastName email picture promoCode } }")] + [InlineData("getProducts", "query { products(longitude: 1, latitude: 1) { productId displayName } }")] + public async Task QueryUber_Returns_Results(string caseName, string query) + { + // Arrange + var httpClientFactoryMock = new Mock(); + var builder = new WebHostBuilder(); + builder.ConfigureServices(services => + { + services.AddRouting(); + services.AddControllers(); + }); + builder.Configure(app => + { + app.UseRouting(); + app.UseEndpoints(e => e.MapControllers()); + }); + var openApiServer = new TestServer(builder); + + httpClientFactoryMock.Setup(f => f.CreateClient(It.IsAny())) + .Returns(() => openApiServer.CreateClient()); + + await openApiServer.Host.StartAsync(); + var apiDocument = await File.ReadAllTextAsync(Combine("__resources__", "Uber.json")); + + var schema = await new ServiceCollection() + .AddSingleton(httpClientFactoryMock.Object) + .AddGraphQL() + .AddOpenApi("Uber", apiDocument) + .BuildRequestExecutorAsync(); + + // Act + var result = await schema.ExecuteAsync(QueryRequestBuilder.Create(query)); + + // Assert + Assert.NotNull(result); + Snapshot.Match(result, postFix: caseName, extension: ".json"); + } +} diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/SchemaGenerationTests.cs b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/SchemaGenerationTests.cs new file mode 100644 index 00000000000..24db0b3a559 --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/SchemaGenerationTests.cs @@ -0,0 +1,71 @@ +using CookieCrumble; +using HotChocolate.Execution; +using HotChocolate.Skimmed.Serialization; +using Microsoft.OpenApi.Readers; +using Xunit; +using Xunit.Abstractions; +using static System.IO.Path; + +namespace HotChocolate.OpenApi.Tests; + +public class SchemaGenerationTests +{ + private readonly ITestOutputHelper _testOutputHelper; + + public SchemaGenerationTests(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } + + [Fact] + public async Task Simple_PetStore_V3_Generates_Correct_SkimmedSchema() + { + // Arrange + await using var stream = File.Open(Combine("__resources__", "PetStore.yaml"), FileMode.Open); + var wrapper = new OpenApiWrapper(); + var document = new OpenApiStreamReader().Read(stream, out var diag); + + // Act + var schema = wrapper.Wrap("PetStore", document); + + // Assert + var sdl = SchemaFormatter.FormatAsString(schema); + _testOutputHelper.WriteLine(sdl); + Snapshot.Match(sdl, extension: ".graphql"); + } + + [Fact] + public async Task Simple_PetStore_V3_Generates_Correct_Schema() + { + // Arrange + var apiDocument = await File.ReadAllTextAsync(Combine("__resources__", "PetStore.yaml")); + + // Act + var schema = await new ServiceCollection() + .AddGraphQL() + .AddOpenApi("PetStore", apiDocument) + .BuildSchemaAsync(); + + // Assert + _testOutputHelper.WriteLine(schema.ToString()); + schema.MatchSnapshot(); + } + + [Fact] + public async Task Uber_Generates_Correct_SkimmedSchema() + { + // Arrange + await using var stream = File.Open(Combine("__resources__", "Uber.json"), FileMode.Open); + var wrapper = new OpenApiWrapper(); + var document = new OpenApiStreamReader().Read(stream, out var diag); + + // Act + var schema = wrapper.Wrap("PetStore", document); + + // Assert + var sdl = SchemaFormatter.FormatAsString(schema); + _testOutputHelper.WriteLine(sdl); + Assert.NotNull(sdl); + Snapshot.Match(sdl, extension: ".graphql"); + } +} diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__resources__/PetStore.yaml b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__resources__/PetStore.yaml new file mode 100644 index 00000000000..10e9dcc7cc7 --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__resources__/PetStore.yaml @@ -0,0 +1,158 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore + description: A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification + termsOfService: http://swagger.io/terms/ + contact: + name: Swagger API Team + email: apiteam@swagger.io + url: http://swagger.io + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: https://petstore.swagger.io/v2 +paths: + /pets: + get: + description: | + Returns all pets from the system that the user has access to + Nam sed condimentum est. Maecenas tempor sagittis sapien, nec rhoncus sem sagittis sit amet. Aenean at gravida augue, ac iaculis sem. Curabitur odio lorem, ornare eget elementum nec, cursus id lectus. Duis mi turpis, pulvinar ac eros ac, tincidunt varius justo. In hac habitasse platea dictumst. Integer at adipiscing ante, a sagittis ligula. Aenean pharetra tempor ante molestie imperdiet. Vivamus id aliquam diam. Cras quis velit non tortor eleifend sagittis. Praesent at enim pharetra urna volutpat venenatis eget eget mauris. In eleifend fermentum facilisis. Praesent enim enim, gravida ac sodales sed, placerat id erat. Suspendisse lacus dolor, consectetur non augue vel, vehicula interdum libero. Morbi euismod sagittis libero sed lacinia. + + Sed tempus felis lobortis leo pulvinar rutrum. Nam mattis velit nisl, eu condimentum ligula luctus nec. Phasellus semper velit eget aliquet faucibus. In a mattis elit. Phasellus vel urna viverra, condimentum lorem id, rhoncus nibh. Ut pellentesque posuere elementum. Sed a varius odio. Morbi rhoncus ligula libero, vel eleifend nunc tristique vitae. Fusce et sem dui. Aenean nec scelerisque tortor. Fusce malesuada accumsan magna vel tempus. Quisque mollis felis eu dolor tristique, sit amet auctor felis gravida. Sed libero lorem, molestie sed nisl in, accumsan tempor nisi. Fusce sollicitudin massa ut lacinia mattis. Sed vel eleifend lorem. Pellentesque vitae felis pretium, pulvinar elit eu, euismod sapien. + operationId: findPets + parameters: + - name: tags + in: query + description: tags to filter by + required: false + style: form + schema: + type: array + items: + type: string + - name: limit + in: query + description: maximum number of results to return + required: false + schema: + type: integer + format: int32 + responses: + '200': + description: pet response + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + post: + description: Creates a new pet in the store. Duplicates are allowed + operationId: addPet + requestBody: + description: Pet to add to the store + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NewPet' + responses: + '200': + description: pet response + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /pets/{id}: + get: + description: Returns a user based on a single ID, if the user does not have access to the pet + operationId: find pet by id + parameters: + - name: id + in: path + description: ID of pet to fetch + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: pet response + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + description: deletes a single pet based on the ID supplied + operationId: deletePet + parameters: + - name: id + in: path + description: ID of pet to delete + required: true + schema: + type: integer + format: int64 + responses: + '204': + description: pet deleted + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' +components: + schemas: + Pet: + allOf: + - $ref: '#/components/schemas/NewPet' + - type: object + required: + - id + properties: + id: + type: integer + format: int64 + + NewPet: + type: object + required: + - name + properties: + name: + type: string + tag: + type: string + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__resources__/Uber.json b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__resources__/Uber.json new file mode 100644 index 00000000000..819019c1a47 --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__resources__/Uber.json @@ -0,0 +1,370 @@ +{ + "swagger": "2.0", + "info": { + "title": "Uber API", + "description": "Move your app forward with the Uber API", + "version": "1.0.0" + }, + "host": "api.uber.com", + "schemes": [ + "https" + ], + "basePath": "/v1", + "produces": [ + "application/json" + ], + "paths": { + "/products": { + "get": { + "summary": "Product Types", + "description": "The Products endpoint returns information about the Uber products offered at a given location. The response includes the display name and other details about each product, and lists the products in the proper display order.", + "parameters": [ + { + "name": "latitude", + "in": "query", + "description": "Latitude component of location.", + "required": true, + "type": "number", + "format": "double" + }, + { + "name": "longitude", + "in": "query", + "description": "Longitude component of location.", + "required": true, + "type": "number", + "format": "double" + } + ], + "tags": [ + "Products" + ], + "responses": { + "200": { + "description": "An array of products", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Product" + } + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/estimates/price": { + "get": { + "summary": "Price Estimates", + "description": "The Price Estimates endpoint returns an estimated price range for each product offered at a given location. The price estimate is provided as a formatted string with the full price range and the localized currency symbol.

The response also includes low and high estimates, and the [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code for situations requiring currency conversion. When surge is active for a particular product, its surge_multiplier will be greater than 1, but the price estimate already factors in this multiplier.", + "parameters": [ + { + "name": "start_latitude", + "in": "query", + "description": "Latitude component of start location.", + "required": true, + "type": "number", + "format": "double" + }, + { + "name": "start_longitude", + "in": "query", + "description": "Longitude component of start location.", + "required": true, + "type": "number", + "format": "double" + }, + { + "name": "end_latitude", + "in": "query", + "description": "Latitude component of end location.", + "required": true, + "type": "number", + "format": "double" + }, + { + "name": "end_longitude", + "in": "query", + "description": "Longitude component of end location.", + "required": true, + "type": "number", + "format": "double" + } + ], + "tags": [ + "Estimates" + ], + "responses": { + "200": { + "description": "An array of price estimates by product", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/PriceEstimate" + } + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/estimates/time": { + "get": { + "summary": "Time Estimates", + "description": "The Time Estimates endpoint returns ETAs for all products offered at a given location, with the responses expressed as integers in seconds. We recommend that this endpoint be called every minute to provide the most accurate, up-to-date ETAs.", + "parameters": [ + { + "name": "start_latitude", + "in": "query", + "description": "Latitude component of start location.", + "required": true, + "type": "number", + "format": "double" + }, + { + "name": "start_longitude", + "in": "query", + "description": "Longitude component of start location.", + "required": true, + "type": "number", + "format": "double" + }, + { + "name": "customer_uuid", + "in": "query", + "type": "string", + "format": "uuid", + "description": "Unique customer identifier to be used for experience customization." + }, + { + "name": "product_id", + "in": "query", + "type": "string", + "description": "Unique identifier representing a specific product for a given latitude & longitude." + } + ], + "tags": [ + "Estimates" + ], + "responses": { + "200": { + "description": "An array of products", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Product" + } + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/me": { + "get": { + "summary": "User Profile", + "description": "The User Profile endpoint returns information about the Uber user that has authorized with the application.", + "tags": [ + "User" + ], + "responses": { + "200": { + "description": "Profile information for a user", + "schema": { + "$ref": "#/definitions/Profile" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/history": { + "get": { + "summary": "User Activity", + "description": "The User Activity endpoint returns data about a user's lifetime activity with Uber. The response will include pickup locations and times, dropoff locations and times, the distance of past requests, and information about which products were requested.

The history array in the response will have a maximum length based on the limit parameter. The response value count may exceed limit, therefore subsequent API requests may be necessary.", + "parameters": [ + { + "name": "offset", + "in": "query", + "type": "integer", + "format": "int32", + "description": "Offset the list of returned results by this amount. Default is zero." + }, + { + "name": "limit", + "in": "query", + "type": "integer", + "format": "int32", + "description": "Number of items to retrieve. Default is 5, maximum is 100." + } + ], + "tags": [ + "User" + ], + "responses": { + "200": { + "description": "History information for the given user", + "schema": { + "$ref": "#/definitions/Activities" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } + }, + "definitions": { + "Product": { + "properties": { + "product_id": { + "type": "string", + "description": "Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles." + }, + "description": { + "type": "string", + "description": "Description of product." + }, + "display_name": { + "type": "string", + "description": "Display name of product." + }, + "capacity": { + "type": "string", + "description": "Capacity of product. For example, 4 people." + }, + "image": { + "type": "string", + "description": "Image URL representing the product." + } + } + }, + "PriceEstimate": { + "properties": { + "product_id": { + "type": "string", + "description": "Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles" + }, + "currency_code": { + "type": "string", + "description": "[ISO 4217](http://en.wikipedia.org/wiki/ISO_4217) currency code." + }, + "display_name": { + "type": "string", + "description": "Display name of product." + }, + "estimate": { + "type": "string", + "description": "Formatted string of estimate in local currency of the start location. Estimate could be a range, a single number (flat rate) or \"Metered\" for TAXI." + }, + "low_estimate": { + "type": "number", + "description": "Lower bound of the estimated price." + }, + "high_estimate": { + "type": "number", + "description": "Upper bound of the estimated price." + }, + "surge_multiplier": { + "type": "number", + "description": "Expected surge multiplier. Surge is active if surge_multiplier is greater than 1. Price estimate already factors in the surge multiplier." + } + } + }, + "Profile": { + "properties": { + "first_name": { + "type": "string", + "description": "First name of the Uber user." + }, + "last_name": { + "type": "string", + "description": "Last name of the Uber user." + }, + "email": { + "type": "string", + "description": "Email address of the Uber user" + }, + "picture": { + "type": "string", + "description": "Image URL of the Uber user." + }, + "promo_code": { + "type": "string", + "description": "Promo code of the Uber user." + } + } + }, + "Activity": { + "properties": { + "uuid": { + "type": "string", + "description": "Unique identifier for the activity" + } + } + }, + "Activities": { + "properties": { + "offset": { + "type": "integer", + "format": "int32", + "description": "Position in pagination." + }, + "limit": { + "type": "integer", + "format": "int32", + "description": "Number of items to retrieve (100 max)." + }, + "count": { + "type": "integer", + "format": "int32", + "description": "Total number of items available." + }, + "history": { + "type": "array", + "items": { + "$ref": "#/definitions/Activity" + } + } + } + }, + "Error": { + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "fields": { + "type": "string" + } + } + } + } +} diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_addPet.json b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_addPet.json new file mode 100644 index 00000000000..ff1d41d8a8d --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_addPet.json @@ -0,0 +1,7 @@ +{ + "data": { + "addPet": { + "name": "Goofy" + } + } +} \ No newline at end of file diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_deletePet.json b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_deletePet.json new file mode 100644 index 00000000000..d01b8312e53 --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_deletePet.json @@ -0,0 +1,7 @@ +{ + "data": { + "deletePet": { + "success": true + } + } +} \ No newline at end of file diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_findAnyPets.json b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_findAnyPets.json new file mode 100644 index 00000000000..625b1ace6f0 --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_findAnyPets.json @@ -0,0 +1,12 @@ +{ + "data": { + "findPets": [ + { + "name": "Rex" + }, + { + "name": "Goofy" + } + ] + } +} \ No newline at end of file diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_findSinglePet.json b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_findSinglePet.json new file mode 100644 index 00000000000..9010d6156ce --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryPets_Returns_Results_findSinglePet.json @@ -0,0 +1,7 @@ +{ + "data": { + "findPetById": { + "name": "Chopper" + } + } +} \ No newline at end of file diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryUber_Returns_Results_getProducts.json b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryUber_Returns_Results_getProducts.json new file mode 100644 index 00000000000..0350331c7e3 --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryUber_Returns_Results_getProducts.json @@ -0,0 +1,14 @@ +{ + "data": { + "products": [ + { + "productId": "ProductA", + "displayName": "Product A" + }, + { + "productId": "ProductB", + "displayName": "Product B" + } + ] + } +} \ No newline at end of file diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryUber_Returns_Results_me.json b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryUber_Returns_Results_me.json new file mode 100644 index 00000000000..9b12d8c3a0c --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/IntegrationTests.QueryUber_Returns_Results_me.json @@ -0,0 +1,11 @@ +{ + "data": { + "me": { + "firstName": "Max", + "lastName": "Mustermann", + "email": "max.mustermann@email.abc", + "picture": "http://img.png", + "promoCode": "1234" + } + } +} \ No newline at end of file diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/SchemaGenerationTests.Simple_PetStore_V3_Generates_Correct_Schema.graphql b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/SchemaGenerationTests.Simple_PetStore_V3_Generates_Correct_Schema.graphql new file mode 100644 index 00000000000..a13d57c97b7 --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/SchemaGenerationTests.Simple_PetStore_V3_Generates_Correct_Schema.graphql @@ -0,0 +1,42 @@ +schema { + query: Query + mutation: Mutation +} + +type AddPetPayload { + id: Long + name: String + tag: String +} + +type DeletePetPayload { + success: Boolean +} + +type Mutation { + addPet(input: AddPetInput): AddPetPayload + deletePet(input: DeletePetInput): DeletePetPayload +} + +type Pet { + id: Long + name: String + tag: String +} + +type Query { + findPetById(id: Long): Pet + findPets(limit: Int tags: String): [Pet] +} + +input AddPetInput { + name: String! + tag: String +} + +input DeletePetInput { + id: Long! +} + +"The `Long` scalar type represents non-fractional signed whole 64-bit numeric values. Long can represent values between -(2^63) and 2^63 - 1." +scalar Long \ No newline at end of file diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/SchemaGenerationTests.Simple_PetStore_V3_Generates_Correct_SkimmedSchema.graphql b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/SchemaGenerationTests.Simple_PetStore_V3_Generates_Correct_SkimmedSchema.graphql new file mode 100644 index 00000000000..f855502645e --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/SchemaGenerationTests.Simple_PetStore_V3_Generates_Correct_SkimmedSchema.graphql @@ -0,0 +1,39 @@ +schema { + query: Query + mutation: Mutation +} + +type Query { + findPetById(id: Long): Pet + findPets(limit: Int tags: [String]): [Pet] +} + +type Mutation { + addPet(input: AddPetInput): AddPetPayload + deletePet(input: DeletePetInput): DeletePetPayload +} + +type AddPetPayload { + id: Long + name: String + tag: String +} + +type DeletePetPayload { + success: Boolean +} + +type Pet { + id: Long + name: String + tag: String +} + +input AddPetInput { + name: String! + tag: String +} + +input DeletePetInput { + id: Long! +} \ No newline at end of file diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/SchemaGenerationTests.Uber_Generates_Correct_SkimmedSchema.graphql b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/SchemaGenerationTests.Uber_Generates_Correct_SkimmedSchema.graphql new file mode 100644 index 00000000000..70f583f36ef --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/__snapshots__/SchemaGenerationTests.Uber_Generates_Correct_SkimmedSchema.graphql @@ -0,0 +1,69 @@ +schema { + query: Query +} + +type Query { + estimatesPrice(end_latitude: Float end_longitude: Float start_latitude: Float start_longitude: Float): [PriceEstimate] + estimatesTime(customer_uuid: String product_id: String start_latitude: Float start_longitude: Float): [Product] + history(limit: Int offset: Int): Activities + me: Profile + products(latitude: Float longitude: Float): [Product] +} + +type Activities { + "Total number of items available." + count: Int + history: [Activity] + "Number of items to retrieve (100 max)." + limit: Int + "Position in pagination." + offset: Int +} + +type Activity { + "Unique identifier for the activity" + uuid: String +} + +type PriceEstimate { + "[ISO 4217](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) currency code." + currencyCode: String + "Display name of product." + displayName: String + "Formatted string of estimate in local currency of the start location. Estimate could be a range, a single number (flat rate) or \"Metered\" for TAXI." + estimate: String + "Upper bound of the estimated price." + highEstimate: Float + "Lower bound of the estimated price." + lowEstimate: Float + "Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles" + productId: String + "Expected surge multiplier. Surge is active if surge_multiplier is greater than 1. Price estimate already factors in the surge multiplier." + surgeMultiplier: Float +} + +type Product { + "Capacity of product. For example, 4 people." + capacity: String + "Description of product." + description: String + "Display name of product." + displayName: String + "Image URL representing the product." + image: String + "Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles." + productId: String +} + +type Profile { + "Email address of the Uber user" + email: String + "First name of the Uber user." + firstName: String + "Last name of the Uber user." + lastName: String + "Image URL of the Uber user." + picture: String + "Promo code of the Uber user." + promoCode: String +} \ No newline at end of file diff --git a/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/packages.lock.json b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/packages.lock.json new file mode 100644 index 00000000000..0074c63fb2f --- /dev/null +++ b/src/HotChocolate/OpenApi/tests/HotChocolate.OpenApi.Tests/packages.lock.json @@ -0,0 +1,3442 @@ +{ + "version": 1, + "dependencies": { + "net7.0": { + "ChilliCream.Testing.Utilities": { + "type": "Direct", + "requested": "[0.2.0, )", + "resolved": "0.2.0", + "contentHash": "gqRu5DNIt6FphQX4EZYlkOI3QmyzatQhuqf3zNXYBmmvmVQ0KaJStDvrANosxlrlVtVX+L5q/s4z9gZMCeuwkA==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "xunit": "2.3.1" + } + }, + "coverlet.msbuild": { + "type": "Direct", + "requested": "[3.1.2, )", + "resolved": "3.1.2", + "contentHash": "QhM0fnDtmIMImY7oxyQ/kh1VYtRxPyRVeLwRUGuUvI6Xp83pSYG9gerK8WgJj4TzUl7ISziADUGtIWKhtlbkbQ==" + }, + "Microsoft.AspNetCore.TestHost": { + "type": "Direct", + "requested": "[7.0.1, )", + "resolved": "7.0.1", + "contentHash": "I58R30e092fSlTfvqe/fWibMtgsOiY/+jeLJAWtNerSXq2iVRuc0fSpt0TR1C6uSx3KSkdWPEZe1ScdfC/SGrg==", + "dependencies": { + "System.IO.Pipelines": "7.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Direct", + "requested": "[7.0.0, )", + "resolved": "7.0.0", + "contentHash": "elNeOmkeX3eDVG6pYVeV82p29hr+UKDaBhrZyWvWLw/EVZSYEkZlQdkp0V39k/Xehs2Qa0mvoCvkVj3eQxNQ1Q==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0" + } + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.1.0, )", + "resolved": "17.1.0", + "contentHash": "MVKvOsHIfrZrvg+8aqOF5dknO/qWrR1sWZjMPQ1N42MKMlL/zQL30FQFZxPeWfmVKWUWAOmAHYsqB5OerTKziw==", + "dependencies": { + "Microsoft.CodeCoverage": "17.1.0", + "Microsoft.TestPlatform.TestHost": "17.1.0" + } + }, + "Microsoft.SourceLink.GitHub": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "DD/LF81k5ODHCfPnBCds97N6KKSS1X1NiDcJYUUpiTu5mmuPktZplhYFrAPQPktMBKvNMdwFrwJ7Fqa3tyTIuA==", + "dependencies": { + "Microsoft.Build.Tasks.Git": "1.1.0", + "Microsoft.SourceLink.Common": "1.1.0" + } + }, + "Moq": { + "type": "Direct", + "requested": "[4.18.1, )", + "resolved": "4.18.1", + "contentHash": "MmZIKNyvn8VrivSaqA8tqy5DmwUievC9zsuNTrcb00oY4IeGq6fXT5BQK329lZ05/tyi5vp30AWe9fl0d2PZQg==", + "dependencies": { + "Castle.Core": "5.0.0", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Snapshooter.Xunit": { + "type": "Direct", + "requested": "[0.5.4, )", + "resolved": "0.5.4", + "contentHash": "gE9VlseOySUSwwAKCXastwxJ7qYpVHwIEi+QbzRVmdOvV6Ry/vE1WqyuolRHwhjx2QZY8+YuO4L/cKJGrt2H6w==", + "dependencies": { + "Snapshooter": "0.5.4", + "xunit.assert": "2.4.1", + "xunit.core": "2.4.1" + } + }, + "Swashbuckle.AspNetCore": { + "type": "Direct", + "requested": "[5.5.1, )", + "resolved": "5.5.1", + "contentHash": "M1CdrptwDw/9Es/W1twwM6w2W0I019uhMDA5q3LUQo4TYZblDipu/oO5gtUpe0tEh1UOdrxlZeQBhmJSTtAtnA==", + "dependencies": { + "Microsoft.Extensions.ApiDescription.Server": "3.0.0", + "Swashbuckle.AspNetCore.Swagger": "5.5.1", + "Swashbuckle.AspNetCore.SwaggerGen": "5.5.1", + "Swashbuckle.AspNetCore.SwaggerUI": "5.5.1" + } + }, + "Swashbuckle.AspNetCore.Annotations": { + "type": "Direct", + "requested": "[5.5.1, )", + "resolved": "5.5.1", + "contentHash": "WK3ni//iAfdt6dcSYA/ZEY2q3eW9HpGNoHYd2b2vVr74H1pI36C3cliJiAzzMXopcieeFgBBzGCfHuAiUUQEhA==", + "dependencies": { + "Swashbuckle.AspNetCore.SwaggerGen": "5.5.1" + } + }, + "Swashbuckle.AspNetCore.Newtonsoft": { + "type": "Direct", + "requested": "[5.5.1, )", + "resolved": "5.5.1", + "contentHash": "7nMO1nVeB1lI7RbAtRlHokP+tejxNJNKB4fSXhQqa6YJtXLeB2mZWD6IXwbV/y3XzKvp4RDX4mTVhkg02pdpqg==", + "dependencies": { + "Microsoft.AspNetCore.Mvc.NewtonsoftJson": "3.0.0", + "Swashbuckle.AspNetCore.SwaggerGen": "5.5.1" + } + }, + "Swashbuckle.AspNetCore.SwaggerGen": { + "type": "Direct", + "requested": "[5.5.1, )", + "resolved": "5.5.1", + "contentHash": "SftLofzIA063y73rn17YCf4dSXrgZdxLBig9E/HT4IIZ9mlsm12KmsNKUXf4U+X09KO8sVq1D29XfjVtC69eAg==", + "dependencies": { + "Swashbuckle.AspNetCore.Swagger": "5.5.1" + } + }, + "Swashbuckle.AspNetCore.SwaggerUI": { + "type": "Direct", + "requested": "[5.5.1, )", + "resolved": "5.5.1", + "contentHash": "a2Ym9DYrvTZ/Yt8GVfn6M1ZP++Ra3KAfCNe4pTtkNiHpBgWhsYWUT3T07REtFImduBh93GAHuItZpltSOZV13A==" + }, + "xunit": { + "type": "Direct", + "requested": "[2.4.1, )", + "resolved": "2.4.1", + "contentHash": "XNR3Yz9QTtec16O0aKcO6+baVNpXmOnPUxDkCY97J+8krUYxPvXT1szYYEUdKk4sB8GOI2YbAjRIOm8ZnXRfzQ==", + "dependencies": { + "xunit.analyzers": "0.10.0", + "xunit.assert": "[2.4.1]", + "xunit.core": "[2.4.1]" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[2.4.3, )", + "resolved": "2.4.3", + "contentHash": "kZZSmOmKA8OBlAJaquPXnJJLM9RwQ27H7BMVqfMLUcTi9xHinWGJiWksa3D4NEtz0wZ/nxd2mogObvBgJKCRhQ==" + }, + "BananaCakePop.Middleware": { + "type": "Transitive", + "resolved": "7.0.4", + "contentHash": "MjXgiZ2WTmijyojmuiDMoqa2rokg0yNROwpe6yQibFre6D3CPdmCiIt48YE9+8ZBwgss5BK49iluktHFuf0XfQ==", + "dependencies": { + "Yarp.ReverseProxy": "2.0.1" + } + }, + "Castle.Core": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "edc8jjyXqzzy8jFdhs36FZdwmlDDTgqPb2Zy1Q5F/f2uAc88bu/VS/0Tpvgupmpl9zJOvOo5ZizVANb0ltN1NQ==", + "dependencies": { + "System.Diagnostics.EventLog": "6.0.0" + } + }, + "DiffPlex": { + "type": "Transitive", + "resolved": "1.7.1", + "contentHash": "a0fSO2p8ykrcfzgG0sjpZAMZPthXXz4l6UIVuM9uyIYIh5yga4sq3aydSGt6n+MkdSBKvMurjjaKnxIqZtfG1g==" + }, + "Microsoft.AspNetCore.JsonPatch": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "LQVXEPxV4jIUiVHHUgBzZxOePSdD7wxV1ndtjg1a76JMqoK3siFka2pVfJXwRq0G4hxbYVWxvamqO733wUhQiA==", + "dependencies": { + "Microsoft.CSharp": "4.6.0", + "Newtonsoft.Json": "12.0.2" + } + }, + "Microsoft.AspNetCore.Mvc.NewtonsoftJson": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "euuKDPev8bb87dzyyDd252jxafKkCNCU0Yh1ujLq7DT7g4sUwUsq1bVnow9isaYFFx+DBWSywUcL8ngSra0QHg==", + "dependencies": { + "Microsoft.AspNetCore.JsonPatch": "3.0.0", + "Newtonsoft.Json": "12.0.2", + "Newtonsoft.Json.Bson": "1.0.2" + } + }, + "Microsoft.AspNetCore.WebUtilities": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "9ErxAAKaDzxXASB/b5uLEkLgUWv1QbeVxyJYEHQwMaxXOeFFVkQxiq8RyfVcifLU7NR0QY0p3acqx4ZpYfhHDg==", + "dependencies": { + "Microsoft.Net.Http.Headers": "2.2.0", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg==" + }, + "Microsoft.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "DD84CsvKf+hfDBbYXIvBXeY7JGfbtoIMMjlPGVaKIp6aWoIdL5EJbWvk+skGkM7/Weezj3q1a89nTPAcGlGcpw==" + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "0N/ZJ71ncCxQWhgtkEYKOgu2oMHa8h1tsOUbhmIKXF8UwtSUCe4vHAsJ3DVcNWRwNfQzSTy263ZE+QF6MdIhhQ==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.6.0", + "contentHash": "kxn3M2rnAGy5N5DgcIwcE8QTePWU/XiYcQVzn9HqTls2NKluVzVSmVWRjK7OUPWbljCXuZxHyhEz9kPRIQeXow==" + }, + "Microsoft.Extensions.ApiDescription.Server": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "LH4OE/76F6sOCslif7+Xh3fS/wUUrE5ryeXAMcoCnuwOQGT5Smw0p57IgDh/pHgHaGz/e+AmEQb7pRgb++wt0w==" + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "h3j/QfmFN4S0w4C2A6X7arXij/M/OVw3uQHSOFxnND4DyAzO1F9eMX7Eti7lU/OkSthEE0WzRsfT/Dmx86jzCw==" + }, + "Microsoft.Extensions.DiagnosticAdapter": { + "type": "Transitive", + "resolved": "3.1.4", + "contentHash": "JiYsxaO6FnH477kGwQLZoj1+XFgwA1ZOjnmypgGhxeLdsmL4o29dP1vfOwmwsU9+nJ5ugtqq4Xs4DcVAGSLt3w==", + "dependencies": { + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "9Pq9f/CvOSz0t9yQa6g1uWpxa2sm13daLFm8EZwy9MaQUjKXWdNUXQwIxwhmba5N83UIqURiPHSNqGK1vfWF2w==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0", + "Microsoft.Extensions.Logging": "7.0.0", + "Microsoft.Extensions.Logging.Abstractions": "7.0.0", + "Microsoft.Extensions.Options": "7.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "Nw2muoNrOG5U5qa2ZekXwudUn2BJcD41e65zwmDHb1fQegTX66UokLWZkJRpqSSHXDOWZ5V0iqhbxOEky91atA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "7.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0", + "Microsoft.Extensions.Logging.Abstractions": "7.0.0", + "Microsoft.Extensions.Options": "7.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "kmn78+LPVMOWeITUjIlfxUPDsI0R6G0RkeAMBmQxAJ7vBJn4q2dTva7pWi65ceN5vPGjJ9q/Uae2WKgvfktJAw==" + }, + "Microsoft.Extensions.ObjectPool": { + "type": "Transitive", + "resolved": "3.1.4", + "contentHash": "ZmgpBTnKA2OSJjtL5A1tNSWAQn8I0ELJMW+oKMZVmVHhjG8IyqlhqkfXT9jxgPp8ddCt4t4oXsKn1HAz+sJO1A==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "lP1yBnTTU42cKpMozuafbvNtQ7QcBjr/CcK3bYOGEMH55Fjt+iecXjT6chR7vbgCMqy3PG3aNQSZgo/EuY/9qQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0", + "Microsoft.Extensions.Primitives": "7.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "um1KU5kxcRp3CNuI8o/GrZtD4AIOXDk+RLsytjZ9QPok3ttLUelLKpilVPuaFT3TFjOhSibUAso0odbOaCDj3Q==" + }, + "Microsoft.Net.Http.Headers": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "iZNkjYqlo8sIOI0bQfpsSoMTmB/kyvmV2h225ihyZT33aTp48ZpF6qYnXxzSXmHt8DpBAwBTX+1s1UFLbYfZKg==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.2.0", + "System.Buffers": "4.5.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.OpenApi": { + "type": "Transitive", + "resolved": "1.6.6", + "contentHash": "7SE3RTGpdXUN+PkVN4xRrtsATgBI7BpsBvbjg6SykurEinA69vIl4S8DWPeGLaBykaCDq87/Ebf2Ashoh7Ky/g==" + }, + "Microsoft.OpenApi.Readers": { + "type": "Transitive", + "resolved": "1.6.6", + "contentHash": "yWNvjxTS1lN9Ix91b0+zoOCSTHr2haZSm5qokko7qRKBiVQo+EDqlY+d93pxtCLcIj6LdHe+8AdfPGi7eAwtGA==", + "dependencies": { + "Microsoft.OpenApi": "1.6.6", + "SharpYaml": "2.1.0" + } + }, + "Microsoft.SourceLink.Common": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "TyGnSaCanfxunClp2af9jpXY127q7g5tiOv0XN/JGcalyKwYusYp06BUGSmCopg/GhmJJSiR/9PS0suXHCGxtw==" + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "OMo/FYnKGy3lZEK0gfitskRM3ga/YBt6MyCyFPq0xNLeybGOQ6HnYNAAvzyePo5WPuMiw3LX+HiuRWNjnas1fA==", + "dependencies": { + "NuGet.Frameworks": "5.11.0", + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "JS0JDLniDhIzkSPLHz7N/x1CG8ywJOtwInFDYA3KQvbz+ojGoT5MT2YDVReL1b86zmNRV8339vsTSm/zh0RcMg==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.1.0", + "Newtonsoft.Json": "9.0.1" + } + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.2", + "contentHash": "R2pZ3B0UjeyHShm9vG+Tu0EBb2lC8b0dFzV9gVn50ofHXh9Smjk6kTn7A/FdAsC8B5cKib1OnGYOXxRBz5XQDg==" + }, + "Newtonsoft.Json.Bson": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "QYFyxhaABwmq3p/21VrZNYvCg3DaEoN/wUuw5nmfAf0X3HLjgupwhkEWdgfb9nvGAUIv3osmZoD3kKl4jxEmYQ==", + "dependencies": { + "Newtonsoft.Json": "12.0.1" + } + }, + "NuGet.Frameworks": { + "type": "Transitive", + "resolved": "5.11.0", + "contentHash": "eaiXkUjC4NPcquGWzAGMXjuxvLwc6XGKMptSyOGQeT0X70BUZObuybJFZLA0OfTdueLd3US23NBPTBb6iF3V1Q==" + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" + }, + "SharpYaml": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2jBenJ6QN0mj8G3ohrNO/uNhA92OJYsQFuI5dJ4zM/HauVoC/oJzK1sCVlUaVUpuXpHUa/k1waXVkkBR2luP/w==" + }, + "Snapshooter": { + "type": "Transitive", + "resolved": "0.5.4", + "contentHash": "znayjnxtFjFcRFdS4W8KyeODS/FOVkIzlAD8hRfrrf3fd3hJ9k+XMNRYCARtzrN3ueIpF4USQbAhWrO73Z9z6w==", + "dependencies": { + "Newtonsoft.Json": "12.0.1" + } + }, + "Swashbuckle.AspNetCore.Swagger": { + "type": "Transitive", + "resolved": "5.5.1", + "contentHash": "YlrnRiIFQdjh+MfBtiUzPPsRwk5745dv1DeWwgNBehN3PwZjIs+gczVaS0h5KKP9ON+e8GM3ieajV6BVZtc/dQ==", + "dependencies": { + "Microsoft.OpenApi": "1.1.4" + } + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "pL2ChpaRRWI/p4LXyy4RgeWlYF2sgfj/pnVMvBqwNFr5cXg7CXNnWZWxrOONLg8VGdFB8oB+EG2Qw4MLgTOe+A==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "1.7.0", + "contentHash": "RVSM6wZUo6L2y6P3vN6gjUtyJ2IF2RVtrepF3J7nrDKfFQd5u/SnSUFclchYQis8/k5scHy9E+fVeKVQLnnkzw==" + }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "0YFqjhp/mYkDGpU0Ye1GjE53HMp9UVfGN7seGpAMttAC0C40v5gw598jCgpbBLMmCo0E5YRLBv5Z2doypO49ZQ==" + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "4.7.1", + "contentHash": "j81Lovt90PDAq8kLpaJfJKV/rWdWuEk6jfV+MBkee33vzYLEUsy4gXK8laa9V2nZlLM9VM9yA/OOQxxPEJKAMw==" + }, + "System.Diagnostics.EventLog": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw==" + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "sDnWM0N3AMCa86LrKTWeF3BZLD2sgWyYUc7HL6z4+xyDZNQRwzmxbo4qP2rX2MqC+Sy1/gOSRDah5ltxY5jPxw==" + }, + "System.IO.Packaging": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "+j5ezLP7785/pd4taKQhXAWsymsIW2nTnE/U3/jpGZzcJx5lip6qkj6UrxSE7ZYZfL0GaLuymwGLqwJV/c7O7Q==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "jRn6JYnNPW6xgQazROBLSfpdoczRw694vO5kKvMcNnpXuolEixUyw6IBuBs2Y2mlSX/LdLvyyWmfXhaI3ND1Yg==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Reactive": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==" + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.7", + "contentHash": "/Tf/9XjprpHolbcDOrxsKVYy/mUG/FS7aGd9YUgBVEiHeQH4kAE0T1sMbde7q6B5xcrNUsJ5iW7D1RvHudQNqA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "gdOOXBhtt2UpTxYJm1DRmoqNfYg5ypvhzhVt0vxKhzxXFjS81r8yIOSFsJYLRa1Jc14GBAqCnjxJstO3zBN7gg==" + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "xunit.abstractions": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" + }, + "xunit.analyzers": { + "type": "Transitive", + "resolved": "0.10.0", + "contentHash": "4/IDFCJfIeg6bix9apmUtIMwvOsiwqdEexeO/R2D4GReIGPLIRODTpId/l4LRSrAJk9lEO3Zx1H0Zx6uohJDNg==" + }, + "xunit.assert": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "O/Oe0BS5RmSsM+LQOb041TzuPo5MdH2Rov+qXGS37X+KFG1Hxz7kopYklM5+1Y+tRGeXrOx5+Xne1RuqLFQoyQ==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "xunit.core": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "Zsj5OMU6JasNGERXZy8s72+pcheG6Q15atS5XpZXqAtULuyQiQ6XNnUsp1gyfC6WgqScqMvySiEHmHcOG6Eg0Q==", + "dependencies": { + "xunit.extensibility.core": "[2.4.1]", + "xunit.extensibility.execution": "[2.4.1]" + } + }, + "xunit.extensibility.core": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "yKZKm/8QNZnBnGZFD9SewkllHBiK0DThybQD/G4PiAmQjKtEZyHi6ET70QPU9KtSMJGRYS6Syk7EyR2EVDU4Kg==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.abstractions": "2.0.3" + } + }, + "xunit.extensibility.execution": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "7e/1jqBpcb7frLkB6XDrHCGXAbKN4Rtdb88epYxCSRQuZDRW8UtTfdTEVpdTl8s4T56e07hOBVd4G0OdCxIY2A==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.extensibility.core": "[2.4.1]" + } + }, + "Yarp.ReverseProxy": { + "type": "Transitive", + "resolved": "2.0.1", + "contentHash": "op7vBwONPFeR1PYxeLw+RLqSodODDX8RWd0OinLGMVIq6yi1q9mv1j56ImuyZgiAToksiC0Dc7jbRUZ9I+jvFA==", + "dependencies": { + "System.IO.Hashing": "7.0.0" + } + }, + "cookiecrumble": { + "type": "Project", + "dependencies": { + "DiffPlex": "[1.7.1, )", + "HotChocolate": "[0.0.0, )", + "HotChocolate.AspNetCore": "[0.0.0, )", + "HotChocolate.Fusion": "[0.0.0, )", + "HotChocolate.Transport.Abstractions": "[0.0.0, )", + "Microsoft.AspNetCore.WebUtilities": "[2.2.0, )", + "Newtonsoft.Json": "[13.0.2, )", + "Xunit": "[2.4.1, )" + } + }, + "greendonut": { + "type": "Project", + "dependencies": { + "Microsoft.Extensions.ObjectPool": "[3.1.4, )", + "System.Diagnostics.DiagnosticSource": "[4.7.0, )", + "System.Threading.Tasks.Extensions": "[4.5.0, )" + } + }, + "HotChocolate": { + "type": "Project", + "dependencies": { + "HotChocolate.Authorization": "[0.0.0, )", + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Fetching": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )", + "HotChocolate.Types.CursorPagination": "[0.0.0, )", + "HotChocolate.Types.Mutations": "[0.0.0, )", + "HotChocolate.Types.OffsetPagination": "[0.0.0, )", + "HotChocolate.Validation": "[0.0.0, )" + } + }, + "hotchocolate.abstractions": { + "type": "Project", + "dependencies": { + "HotChocolate.Language": "[0.0.0, )", + "Microsoft.Bcl.AsyncInterfaces": "[1.1.0, )", + "System.Collections.Immutable": "[1.7.0, )" + } + }, + "hotchocolate.aspnetcore": { + "type": "Project", + "dependencies": { + "BananaCakePop.Middleware": "[7.0.4, )", + "HotChocolate": "[0.0.0, )", + "HotChocolate.Subscriptions.InMemory": "[0.0.0, )", + "HotChocolate.Transport.Sockets": "[0.0.0, )", + "HotChocolate.Types.Scalars.Upload": "[0.0.0, )" + } + }, + "hotchocolate.aspnetcore.tests.utilities": { + "type": "Project", + "dependencies": { + "CookieCrumble": "[0.0.0, )", + "HotChocolate.AspNetCore": "[0.0.0, )", + "HotChocolate.StarWars": "[0.0.0, )", + "HotChocolate.Subscriptions.InMemory": "[0.0.0, )", + "HotChocolate.Tests.Utilities": "[0.0.0, )", + "HotChocolate.Transport.Sockets.Client": "[0.0.0, )", + "HotChocolate.Types.Scalars.Upload": "[0.0.0, )", + "Microsoft.AspNetCore.TestHost": "[7.0.0, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "Moq": "[4.18.1, )", + "xunit": "[2.4.1, )" + } + }, + "hotchocolate.authorization": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )" + } + }, + "hotchocolate.execution": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Execution.Abstractions": "[0.0.0, )", + "HotChocolate.Fetching": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )", + "HotChocolate.Validation": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection": "[3.1.4, )", + "Microsoft.Extensions.DiagnosticAdapter": "[3.1.4, )", + "System.Threading.Channels": "[4.7.0, )" + } + }, + "hotchocolate.execution.abstractions": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )" + } + }, + "hotchocolate.fetching": { + "type": "Project", + "dependencies": { + "GreenDonut": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.fusion": { + "type": "Project", + "dependencies": { + "HotChocolate": "[0.0.0, )", + "HotChocolate.AspNetCore": "[0.0.0, )", + "HotChocolate.Fusion.Abstractions": "[0.0.0, )", + "HotChocolate.Transport.Http": "[0.0.0, )", + "HotChocolate.Transport.Sockets.Client": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[7.0.0, )", + "Microsoft.Extensions.Http": "[7.0.0, )", + "System.Reactive": "[5.0.0, )" + } + }, + "hotchocolate.fusion.abstractions": { + "type": "Project", + "dependencies": { + "HotChocolate.Language": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )", + "System.IO.Packaging": "[7.0.0, )" + } + }, + "hotchocolate.language": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )", + "HotChocolate.Language.Utf8": "[0.0.0, )", + "HotChocolate.Language.Visitors": "[0.0.0, )", + "HotChocolate.Language.Web": "[0.0.0, )" + } + }, + "hotchocolate.language.syntaxtree": { + "type": "Project", + "dependencies": { + "Microsoft.Extensions.ObjectPool": "[3.1.4, )" + } + }, + "hotchocolate.language.utf8": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )" + } + }, + "hotchocolate.language.visitors": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )" + } + }, + "hotchocolate.language.web": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.Utf8": "[0.0.0, )" + } + }, + "hotchocolate.openapi": { + "type": "Project", + "dependencies": { + "HotChocolate": "[0.0.0, )", + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Skimmed": "[0.0.0, )", + "HotChocolate.Types.Json": "[0.0.0, )", + "HotChocolate.Types.Scalars": "[0.0.0, )", + "Microsoft.Extensions.Http": "[7.0.0, )", + "Microsoft.OpenApi": "[1.6.6, )", + "Microsoft.OpenApi.Readers": "[1.6.6, )" + } + }, + "HotChocolate.Skimmed": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Language": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )" + } + }, + "HotChocolate.StarWars": { + "type": "Project", + "dependencies": { + "ChilliCream.Testing.Utilities": "[0.2.0, )", + "CookieCrumble": "[0.0.0, )", + "DiffPlex": "[1.7.1, )", + "HotChocolate": "[0.0.0, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "Moq": "[4.18.1, )", + "Snapshooter.Xunit": "[0.5.4, )", + "xunit": "[2.4.1, )" + } + }, + "hotchocolate.subscriptions": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Execution.Abstractions": "[0.0.0, )" + } + }, + "hotchocolate.subscriptions.inmemory": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution.Abstractions": "[0.0.0, )", + "HotChocolate.Subscriptions": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )" + } + }, + "hotchocolate.tests.utilities": { + "type": "Project", + "dependencies": { + "ChilliCream.Testing.Utilities": "[0.2.0, )", + "CookieCrumble": "[0.0.0, )", + "DiffPlex": "[1.7.1, )", + "HotChocolate.StarWars": "[0.0.0, )", + "HotChocolate.Subscriptions.InMemory": "[0.0.0, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "Moq": "[4.18.1, )", + "Snapshooter.Xunit": "[0.5.4, )", + "xunit": "[2.4.1, )" + } + }, + "hotchocolate.transport.abstractions": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )", + "System.Collections.Immutable": "[1.7.0, )", + "System.Text.Json": "[6.0.7, )" + } + }, + "hotchocolate.transport.http": { + "type": "Project", + "dependencies": { + "HotChocolate.Transport.Abstractions": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )", + "System.IO.Pipelines": "[6.0.0, )" + } + }, + "hotchocolate.transport.sockets": { + "type": "Project", + "dependencies": { + "System.IO.Pipelines": "[4.7.0, )" + } + }, + "hotchocolate.transport.sockets.client": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )", + "HotChocolate.Transport.Abstractions": "[0.0.0, )", + "HotChocolate.Transport.Sockets": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )", + "System.Collections.Immutable": "[1.7.0, )", + "System.Text.Json": "[6.0.7, )" + } + }, + "hotchocolate.types": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )", + "HotChocolate.Utilities.Introspection": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )", + "Microsoft.Extensions.ObjectPool": "[3.1.4, )", + "System.ComponentModel.Annotations": "[4.7.0, )", + "System.Text.Json": "[6.0.7, )" + } + }, + "hotchocolate.types.cursorpagination": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.json": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.mutations": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.offsetpagination": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.scalars": { + "type": "Project", + "dependencies": { + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.scalars.upload": { + "type": "Project", + "dependencies": { + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.utilities": { + "type": "Project", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "[1.1.0, )", + "System.Memory": "[4.5.4, )", + "System.Threading.Tasks.Extensions": "[4.5.4, )" + } + }, + "hotchocolate.utilities.introspection": { + "type": "Project", + "dependencies": { + "HotChocolate.Language": "[0.0.0, )", + "System.Text.Json": "[6.0.7, )" + } + }, + "hotchocolate.validation": { + "type": "Project", + "dependencies": { + "HotChocolate.Types": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )", + "Microsoft.Extensions.Options": "[3.1.4, )" + } + } + }, + "net8.0": { + "ChilliCream.Testing.Utilities": { + "type": "Direct", + "requested": "[0.2.0, )", + "resolved": "0.2.0", + "contentHash": "gqRu5DNIt6FphQX4EZYlkOI3QmyzatQhuqf3zNXYBmmvmVQ0KaJStDvrANosxlrlVtVX+L5q/s4z9gZMCeuwkA==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "xunit": "2.3.1" + } + }, + "coverlet.msbuild": { + "type": "Direct", + "requested": "[3.1.2, )", + "resolved": "3.1.2", + "contentHash": "QhM0fnDtmIMImY7oxyQ/kh1VYtRxPyRVeLwRUGuUvI6Xp83pSYG9gerK8WgJj4TzUl7ISziADUGtIWKhtlbkbQ==" + }, + "Microsoft.AspNetCore.TestHost": { + "type": "Direct", + "requested": "[8.0.0-rc.1.23421.29, )", + "resolved": "8.0.0-rc.1.23421.29", + "contentHash": "Hkxba+PTz03OdtBgXoHVC93PAHNG9QPVOJwzNs7P2DNKKIx0d+YrcvMVlbI7JNi3mXSpgkho3ioTM9SnN0m1vA==", + "dependencies": { + "System.IO.Pipelines": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Direct", + "requested": "[8.0.0-rc.1.23419.4, )", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "q1M8U8Qhf0siOpZ0PRB7jZR8Um+Pnm4HgCL81hYDtIunWJmlqEGKjGWg/gl140K9imZUqLkePSVVQGlP7/Xo+A==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.1.0, )", + "resolved": "17.1.0", + "contentHash": "MVKvOsHIfrZrvg+8aqOF5dknO/qWrR1sWZjMPQ1N42MKMlL/zQL30FQFZxPeWfmVKWUWAOmAHYsqB5OerTKziw==", + "dependencies": { + "Microsoft.CodeCoverage": "17.1.0", + "Microsoft.TestPlatform.TestHost": "17.1.0" + } + }, + "Microsoft.SourceLink.GitHub": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "DD/LF81k5ODHCfPnBCds97N6KKSS1X1NiDcJYUUpiTu5mmuPktZplhYFrAPQPktMBKvNMdwFrwJ7Fqa3tyTIuA==", + "dependencies": { + "Microsoft.Build.Tasks.Git": "1.1.0", + "Microsoft.SourceLink.Common": "1.1.0" + } + }, + "Moq": { + "type": "Direct", + "requested": "[4.18.1, )", + "resolved": "4.18.1", + "contentHash": "MmZIKNyvn8VrivSaqA8tqy5DmwUievC9zsuNTrcb00oY4IeGq6fXT5BQK329lZ05/tyi5vp30AWe9fl0d2PZQg==", + "dependencies": { + "Castle.Core": "5.0.0", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Snapshooter.Xunit": { + "type": "Direct", + "requested": "[0.5.4, )", + "resolved": "0.5.4", + "contentHash": "gE9VlseOySUSwwAKCXastwxJ7qYpVHwIEi+QbzRVmdOvV6Ry/vE1WqyuolRHwhjx2QZY8+YuO4L/cKJGrt2H6w==", + "dependencies": { + "Snapshooter": "0.5.4", + "xunit.assert": "2.4.1", + "xunit.core": "2.4.1" + } + }, + "Swashbuckle.AspNetCore": { + "type": "Direct", + "requested": "[5.5.1, )", + "resolved": "5.5.1", + "contentHash": "M1CdrptwDw/9Es/W1twwM6w2W0I019uhMDA5q3LUQo4TYZblDipu/oO5gtUpe0tEh1UOdrxlZeQBhmJSTtAtnA==", + "dependencies": { + "Microsoft.Extensions.ApiDescription.Server": "3.0.0", + "Swashbuckle.AspNetCore.Swagger": "5.5.1", + "Swashbuckle.AspNetCore.SwaggerGen": "5.5.1", + "Swashbuckle.AspNetCore.SwaggerUI": "5.5.1" + } + }, + "Swashbuckle.AspNetCore.Annotations": { + "type": "Direct", + "requested": "[5.5.1, )", + "resolved": "5.5.1", + "contentHash": "WK3ni//iAfdt6dcSYA/ZEY2q3eW9HpGNoHYd2b2vVr74H1pI36C3cliJiAzzMXopcieeFgBBzGCfHuAiUUQEhA==", + "dependencies": { + "Swashbuckle.AspNetCore.SwaggerGen": "5.5.1" + } + }, + "Swashbuckle.AspNetCore.Newtonsoft": { + "type": "Direct", + "requested": "[5.5.1, )", + "resolved": "5.5.1", + "contentHash": "7nMO1nVeB1lI7RbAtRlHokP+tejxNJNKB4fSXhQqa6YJtXLeB2mZWD6IXwbV/y3XzKvp4RDX4mTVhkg02pdpqg==", + "dependencies": { + "Microsoft.AspNetCore.Mvc.NewtonsoftJson": "3.0.0", + "Swashbuckle.AspNetCore.SwaggerGen": "5.5.1" + } + }, + "Swashbuckle.AspNetCore.SwaggerGen": { + "type": "Direct", + "requested": "[5.5.1, )", + "resolved": "5.5.1", + "contentHash": "SftLofzIA063y73rn17YCf4dSXrgZdxLBig9E/HT4IIZ9mlsm12KmsNKUXf4U+X09KO8sVq1D29XfjVtC69eAg==", + "dependencies": { + "Swashbuckle.AspNetCore.Swagger": "5.5.1" + } + }, + "Swashbuckle.AspNetCore.SwaggerUI": { + "type": "Direct", + "requested": "[5.5.1, )", + "resolved": "5.5.1", + "contentHash": "a2Ym9DYrvTZ/Yt8GVfn6M1ZP++Ra3KAfCNe4pTtkNiHpBgWhsYWUT3T07REtFImduBh93GAHuItZpltSOZV13A==" + }, + "xunit": { + "type": "Direct", + "requested": "[2.4.1, )", + "resolved": "2.4.1", + "contentHash": "XNR3Yz9QTtec16O0aKcO6+baVNpXmOnPUxDkCY97J+8krUYxPvXT1szYYEUdKk4sB8GOI2YbAjRIOm8ZnXRfzQ==", + "dependencies": { + "xunit.analyzers": "0.10.0", + "xunit.assert": "[2.4.1]", + "xunit.core": "[2.4.1]" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[2.4.3, )", + "resolved": "2.4.3", + "contentHash": "kZZSmOmKA8OBlAJaquPXnJJLM9RwQ27H7BMVqfMLUcTi9xHinWGJiWksa3D4NEtz0wZ/nxd2mogObvBgJKCRhQ==" + }, + "BananaCakePop.Middleware": { + "type": "Transitive", + "resolved": "7.0.4", + "contentHash": "MjXgiZ2WTmijyojmuiDMoqa2rokg0yNROwpe6yQibFre6D3CPdmCiIt48YE9+8ZBwgss5BK49iluktHFuf0XfQ==", + "dependencies": { + "Yarp.ReverseProxy": "2.0.1" + } + }, + "Castle.Core": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "edc8jjyXqzzy8jFdhs36FZdwmlDDTgqPb2Zy1Q5F/f2uAc88bu/VS/0Tpvgupmpl9zJOvOo5ZizVANb0ltN1NQ==", + "dependencies": { + "System.Diagnostics.EventLog": "6.0.0" + } + }, + "DiffPlex": { + "type": "Transitive", + "resolved": "1.7.1", + "contentHash": "a0fSO2p8ykrcfzgG0sjpZAMZPthXXz4l6UIVuM9uyIYIh5yga4sq3aydSGt6n+MkdSBKvMurjjaKnxIqZtfG1g==" + }, + "Microsoft.AspNetCore.JsonPatch": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "LQVXEPxV4jIUiVHHUgBzZxOePSdD7wxV1ndtjg1a76JMqoK3siFka2pVfJXwRq0G4hxbYVWxvamqO733wUhQiA==", + "dependencies": { + "Microsoft.CSharp": "4.6.0", + "Newtonsoft.Json": "12.0.2" + } + }, + "Microsoft.AspNetCore.Mvc.NewtonsoftJson": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "euuKDPev8bb87dzyyDd252jxafKkCNCU0Yh1ujLq7DT7g4sUwUsq1bVnow9isaYFFx+DBWSywUcL8ngSra0QHg==", + "dependencies": { + "Microsoft.AspNetCore.JsonPatch": "3.0.0", + "Newtonsoft.Json": "12.0.2", + "Newtonsoft.Json.Bson": "1.0.2" + } + }, + "Microsoft.AspNetCore.WebUtilities": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "9ErxAAKaDzxXASB/b5uLEkLgUWv1QbeVxyJYEHQwMaxXOeFFVkQxiq8RyfVcifLU7NR0QY0p3acqx4ZpYfhHDg==", + "dependencies": { + "Microsoft.Net.Http.Headers": "2.2.0", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "1Am6l4Vpn3/K32daEqZI+FFr96OlZkgwK2LcT3pZ2zWubR5zTPW3/FkO1Rat9kb7oQOa4rxgl9LJHc5tspCWfg==" + }, + "Microsoft.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "DD84CsvKf+hfDBbYXIvBXeY7JGfbtoIMMjlPGVaKIp6aWoIdL5EJbWvk+skGkM7/Weezj3q1a89nTPAcGlGcpw==" + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "0N/ZJ71ncCxQWhgtkEYKOgu2oMHa8h1tsOUbhmIKXF8UwtSUCe4vHAsJ3DVcNWRwNfQzSTy263ZE+QF6MdIhhQ==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.6.0", + "contentHash": "kxn3M2rnAGy5N5DgcIwcE8QTePWU/XiYcQVzn9HqTls2NKluVzVSmVWRjK7OUPWbljCXuZxHyhEz9kPRIQeXow==" + }, + "Microsoft.Extensions.ApiDescription.Server": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "LH4OE/76F6sOCslif7+Xh3fS/wUUrE5ryeXAMcoCnuwOQGT5Smw0p57IgDh/pHgHaGz/e+AmEQb7pRgb++wt0w==" + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "NoIBM0qnZrl5o3em/5Qx4T3HcDruKdDVvm4PsG/wiuWawtwHRqaqkFjPS66lPnu1Kgzv+D1JJd+r4C5wPxXErw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Primitives": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "tY5wKwXNZ6cBeyHxvxyLy57TxUaA6H82/vW8vTTmikG9bkfRzfyS0EEDloiPzL4ln8P+3aZxeAestjPC6942Kg==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "npSDU7QSVdMjIFasVVBygHTaSd3H6rJD9zBXb6tcmAO8D7chkCJ2MarAYVKDICT5I9Hfawxv7FitJFAgNVIn3w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "SAv6AcbXKzvBq4kQAU5S9sW3ZOV7j4qLjqT+Iw6CLgqsSCgoJhmVvadtr8PUWaRfj4uVT9CX5V3zIojehtMq8w==" + }, + "Microsoft.Extensions.DiagnosticAdapter": { + "type": "Transitive", + "resolved": "3.1.4", + "contentHash": "JiYsxaO6FnH477kGwQLZoj1+XFgwA1ZOjnmypgGhxeLdsmL4o29dP1vfOwmwsU9+nJ5ugtqq4Xs4DcVAGSLt3w==", + "dependencies": { + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "Microsoft.Extensions.Diagnostics": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "RqerNpeQoixriNPi2RPxJWu9V6ljz3u/M9lCzwLsYtNqLKUzO3K838C8NU2uDFg0SviJyuMV1JG0RG+c9Hdglw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Diagnostics.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "ukvKfK+sgwReTEsbP3hCuXUWOCaqH7HCXGTXfqAyl6IvSJVZHWpTZAFHELcNbSz4hdAzG/8QY/4JxU5xNQOzlA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Options": "8.0.0-rc.1.23419.4", + "System.Diagnostics.DiagnosticSource": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "uUCk1A8XUVUEGoTATMxih15uZoF8QzBB+MZwUfB3Lj4QAQZFxWG/VbUMrUyCKpvvvncOyXgT1xq0SAyLmzUPIw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Diagnostics": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Logging": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Options": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "n39LJSx0Mpl89hhT0DWTyPyGv/z60/Ygp0b4ZE1zNy9R8O42PrsK+XFdiaKtCnpOPezX2Jq07dFyZzpCqmIvzw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Options": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "jphvzZmIDCEwl5PkxegeiO0y+zeMRg92QtY0weVFy8tH9ySgb2EwX85B78H0FYTFixFApRlmsh/pEdEs+VKbZA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.ObjectPool": { + "type": "Transitive", + "resolved": "3.1.4", + "contentHash": "ZmgpBTnKA2OSJjtL5A1tNSWAQn8I0ELJMW+oKMZVmVHhjG8IyqlhqkfXT9jxgPp8ddCt4t4oXsKn1HAz+sJO1A==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "fsKycFyh/aX7Vs9o/gOH+XBWRh5VB4iwV6xHZdvN9kDvJfBhCm2IQ/E+xaWa5KtX7tXOx0hclZ8ihK97ab3mPQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Primitives": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "7y1Ob1fZniZnTGeuurHjGAXmW0+reI4MUOZxR3Dyvu9htNSkGsrsICY2f0bIev1D+pQrFwNg/+yUOpvc46/jkg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Configuration.Binder": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Options": "8.0.0-rc.1.23419.4", + "Microsoft.Extensions.Primitives": "8.0.0-rc.1.23419.4" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "zyoB4zblhvpylS9VOmKyBuGH+RjKDsfi0cTB2KRPPDD6tFinpP+vGr3dictaNYLhGUg6jaBmq+2H/WZMCnvGDQ==" + }, + "Microsoft.Net.Http.Headers": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "iZNkjYqlo8sIOI0bQfpsSoMTmB/kyvmV2h225ihyZT33aTp48ZpF6qYnXxzSXmHt8DpBAwBTX+1s1UFLbYfZKg==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.2.0", + "System.Buffers": "4.5.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.OpenApi": { + "type": "Transitive", + "resolved": "1.6.6", + "contentHash": "7SE3RTGpdXUN+PkVN4xRrtsATgBI7BpsBvbjg6SykurEinA69vIl4S8DWPeGLaBykaCDq87/Ebf2Ashoh7Ky/g==" + }, + "Microsoft.OpenApi.Readers": { + "type": "Transitive", + "resolved": "1.6.6", + "contentHash": "yWNvjxTS1lN9Ix91b0+zoOCSTHr2haZSm5qokko7qRKBiVQo+EDqlY+d93pxtCLcIj6LdHe+8AdfPGi7eAwtGA==", + "dependencies": { + "Microsoft.OpenApi": "1.6.6", + "SharpYaml": "2.1.0" + } + }, + "Microsoft.SourceLink.Common": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "TyGnSaCanfxunClp2af9jpXY127q7g5tiOv0XN/JGcalyKwYusYp06BUGSmCopg/GhmJJSiR/9PS0suXHCGxtw==" + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "OMo/FYnKGy3lZEK0gfitskRM3ga/YBt6MyCyFPq0xNLeybGOQ6HnYNAAvzyePo5WPuMiw3LX+HiuRWNjnas1fA==", + "dependencies": { + "NuGet.Frameworks": "5.11.0", + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "JS0JDLniDhIzkSPLHz7N/x1CG8ywJOtwInFDYA3KQvbz+ojGoT5MT2YDVReL1b86zmNRV8339vsTSm/zh0RcMg==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.1.0", + "Newtonsoft.Json": "9.0.1" + } + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.2", + "contentHash": "R2pZ3B0UjeyHShm9vG+Tu0EBb2lC8b0dFzV9gVn50ofHXh9Smjk6kTn7A/FdAsC8B5cKib1OnGYOXxRBz5XQDg==" + }, + "Newtonsoft.Json.Bson": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "QYFyxhaABwmq3p/21VrZNYvCg3DaEoN/wUuw5nmfAf0X3HLjgupwhkEWdgfb9nvGAUIv3osmZoD3kKl4jxEmYQ==", + "dependencies": { + "Newtonsoft.Json": "12.0.1" + } + }, + "NuGet.Frameworks": { + "type": "Transitive", + "resolved": "5.11.0", + "contentHash": "eaiXkUjC4NPcquGWzAGMXjuxvLwc6XGKMptSyOGQeT0X70BUZObuybJFZLA0OfTdueLd3US23NBPTBb6iF3V1Q==" + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" + }, + "SharpYaml": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2jBenJ6QN0mj8G3ohrNO/uNhA92OJYsQFuI5dJ4zM/HauVoC/oJzK1sCVlUaVUpuXpHUa/k1waXVkkBR2luP/w==" + }, + "Snapshooter": { + "type": "Transitive", + "resolved": "0.5.4", + "contentHash": "znayjnxtFjFcRFdS4W8KyeODS/FOVkIzlAD8hRfrrf3fd3hJ9k+XMNRYCARtzrN3ueIpF4USQbAhWrO73Z9z6w==", + "dependencies": { + "Newtonsoft.Json": "12.0.1" + } + }, + "Swashbuckle.AspNetCore.Swagger": { + "type": "Transitive", + "resolved": "5.5.1", + "contentHash": "YlrnRiIFQdjh+MfBtiUzPPsRwk5745dv1DeWwgNBehN3PwZjIs+gczVaS0h5KKP9ON+e8GM3ieajV6BVZtc/dQ==", + "dependencies": { + "Microsoft.OpenApi": "1.1.4" + } + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "pL2ChpaRRWI/p4LXyy4RgeWlYF2sgfj/pnVMvBqwNFr5cXg7CXNnWZWxrOONLg8VGdFB8oB+EG2Qw4MLgTOe+A==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "1.7.0", + "contentHash": "RVSM6wZUo6L2y6P3vN6gjUtyJ2IF2RVtrepF3J7nrDKfFQd5u/SnSUFclchYQis8/k5scHy9E+fVeKVQLnnkzw==" + }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "0YFqjhp/mYkDGpU0Ye1GjE53HMp9UVfGN7seGpAMttAC0C40v5gw598jCgpbBLMmCo0E5YRLBv5Z2doypO49ZQ==" + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "hdyhGAFW9nXz+UfN8XxW4iTzyef03BsIXc6AqLNbDcqw63343di6XFGFSYJ8Rh+yHlZazrGTt6keQ2GDh9avmg==" + }, + "System.Diagnostics.EventLog": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw==" + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "sDnWM0N3AMCa86LrKTWeF3BZLD2sgWyYUc7HL6z4+xyDZNQRwzmxbo4qP2rX2MqC+Sy1/gOSRDah5ltxY5jPxw==" + }, + "System.IO.Packaging": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "JK7ZXouNniiURdatp/Y1q/G1SyCsFNTelRGKRioe8A46hYyqO71WuAnXCOu1PEz6WKNJDz9O5MkrSwZYu7kQ2g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "8.0.0-rc.1.23419.4", + "contentHash": "Xha7Ev45lonwHcDCBUM52ps6dqI8p83mn/OjpBEiqW8dcmdw3lIqPLPj1pdDJOoBnznoEzXagA5nEw9WiEvEkg==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Reactive": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "erBZjkQHWL9jpasCE/0qKAryzVBJFxGHVBAvgRN1bzM0q2s1S4oYREEEL0Vb+1kA/6BKb5FjUZMp5VXmy+gzkQ==" + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.7", + "contentHash": "/Tf/9XjprpHolbcDOrxsKVYy/mUG/FS7aGd9YUgBVEiHeQH4kAE0T1sMbde7q6B5xcrNUsJ5iW7D1RvHudQNqA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "gdOOXBhtt2UpTxYJm1DRmoqNfYg5ypvhzhVt0vxKhzxXFjS81r8yIOSFsJYLRa1Jc14GBAqCnjxJstO3zBN7gg==" + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "xunit.abstractions": { + "type": "Transitive", + "resolved": "2.0.3", + "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" + }, + "xunit.analyzers": { + "type": "Transitive", + "resolved": "0.10.0", + "contentHash": "4/IDFCJfIeg6bix9apmUtIMwvOsiwqdEexeO/R2D4GReIGPLIRODTpId/l4LRSrAJk9lEO3Zx1H0Zx6uohJDNg==" + }, + "xunit.assert": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "O/Oe0BS5RmSsM+LQOb041TzuPo5MdH2Rov+qXGS37X+KFG1Hxz7kopYklM5+1Y+tRGeXrOx5+Xne1RuqLFQoyQ==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "xunit.core": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "Zsj5OMU6JasNGERXZy8s72+pcheG6Q15atS5XpZXqAtULuyQiQ6XNnUsp1gyfC6WgqScqMvySiEHmHcOG6Eg0Q==", + "dependencies": { + "xunit.extensibility.core": "[2.4.1]", + "xunit.extensibility.execution": "[2.4.1]" + } + }, + "xunit.extensibility.core": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "yKZKm/8QNZnBnGZFD9SewkllHBiK0DThybQD/G4PiAmQjKtEZyHi6ET70QPU9KtSMJGRYS6Syk7EyR2EVDU4Kg==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.abstractions": "2.0.3" + } + }, + "xunit.extensibility.execution": { + "type": "Transitive", + "resolved": "2.4.1", + "contentHash": "7e/1jqBpcb7frLkB6XDrHCGXAbKN4Rtdb88epYxCSRQuZDRW8UtTfdTEVpdTl8s4T56e07hOBVd4G0OdCxIY2A==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.extensibility.core": "[2.4.1]" + } + }, + "Yarp.ReverseProxy": { + "type": "Transitive", + "resolved": "2.0.1", + "contentHash": "op7vBwONPFeR1PYxeLw+RLqSodODDX8RWd0OinLGMVIq6yi1q9mv1j56ImuyZgiAToksiC0Dc7jbRUZ9I+jvFA==", + "dependencies": { + "System.IO.Hashing": "7.0.0" + } + }, + "cookiecrumble": { + "type": "Project", + "dependencies": { + "DiffPlex": "[1.7.1, )", + "HotChocolate": "[0.0.0, )", + "HotChocolate.AspNetCore": "[0.0.0, )", + "HotChocolate.Fusion": "[0.0.0, )", + "HotChocolate.Transport.Abstractions": "[0.0.0, )", + "Microsoft.AspNetCore.WebUtilities": "[2.2.0, )", + "Newtonsoft.Json": "[13.0.2, )", + "Xunit": "[2.4.1, )" + } + }, + "greendonut": { + "type": "Project", + "dependencies": { + "Microsoft.Extensions.ObjectPool": "[3.1.4, )", + "System.Diagnostics.DiagnosticSource": "[4.7.0, )", + "System.Threading.Tasks.Extensions": "[4.5.0, )" + } + }, + "HotChocolate": { + "type": "Project", + "dependencies": { + "HotChocolate.Authorization": "[0.0.0, )", + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Fetching": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )", + "HotChocolate.Types.CursorPagination": "[0.0.0, )", + "HotChocolate.Types.Mutations": "[0.0.0, )", + "HotChocolate.Types.OffsetPagination": "[0.0.0, )", + "HotChocolate.Validation": "[0.0.0, )" + } + }, + "hotchocolate.abstractions": { + "type": "Project", + "dependencies": { + "HotChocolate.Language": "[0.0.0, )", + "Microsoft.Bcl.AsyncInterfaces": "[1.1.0, )", + "System.Collections.Immutable": "[1.7.0, )" + } + }, + "hotchocolate.aspnetcore": { + "type": "Project", + "dependencies": { + "BananaCakePop.Middleware": "[7.0.4, )", + "HotChocolate": "[0.0.0, )", + "HotChocolate.Subscriptions.InMemory": "[0.0.0, )", + "HotChocolate.Transport.Sockets": "[0.0.0, )", + "HotChocolate.Types.Scalars.Upload": "[0.0.0, )" + } + }, + "hotchocolate.aspnetcore.tests.utilities": { + "type": "Project", + "dependencies": { + "CookieCrumble": "[0.0.0, )", + "HotChocolate.AspNetCore": "[0.0.0, )", + "HotChocolate.StarWars": "[0.0.0, )", + "HotChocolate.Subscriptions.InMemory": "[0.0.0, )", + "HotChocolate.Tests.Utilities": "[0.0.0, )", + "HotChocolate.Transport.Sockets.Client": "[0.0.0, )", + "HotChocolate.Types.Scalars.Upload": "[0.0.0, )", + "Microsoft.AspNetCore.TestHost": "[8.0.0-rc.1.23421.29, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "Moq": "[4.18.1, )", + "xunit": "[2.4.1, )" + } + }, + "hotchocolate.authorization": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )" + } + }, + "hotchocolate.execution": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Execution.Abstractions": "[0.0.0, )", + "HotChocolate.Fetching": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )", + "HotChocolate.Validation": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection": "[3.1.4, )", + "Microsoft.Extensions.DiagnosticAdapter": "[3.1.4, )", + "System.Threading.Channels": "[4.7.0, )" + } + }, + "hotchocolate.execution.abstractions": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )" + } + }, + "hotchocolate.fetching": { + "type": "Project", + "dependencies": { + "GreenDonut": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.fusion": { + "type": "Project", + "dependencies": { + "HotChocolate": "[0.0.0, )", + "HotChocolate.AspNetCore": "[0.0.0, )", + "HotChocolate.Fusion.Abstractions": "[0.0.0, )", + "HotChocolate.Transport.Http": "[0.0.0, )", + "HotChocolate.Transport.Sockets.Client": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection": "[8.0.0-rc.1.23419.4, )", + "Microsoft.Extensions.Http": "[8.0.0-rc.1.23419.4, )", + "System.Reactive": "[5.0.0, )" + } + }, + "hotchocolate.fusion.abstractions": { + "type": "Project", + "dependencies": { + "HotChocolate.Language": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )", + "System.IO.Packaging": "[8.0.0-rc.1.23419.4, )" + } + }, + "hotchocolate.language": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )", + "HotChocolate.Language.Utf8": "[0.0.0, )", + "HotChocolate.Language.Visitors": "[0.0.0, )", + "HotChocolate.Language.Web": "[0.0.0, )" + } + }, + "hotchocolate.language.syntaxtree": { + "type": "Project", + "dependencies": { + "Microsoft.Extensions.ObjectPool": "[3.1.4, )" + } + }, + "hotchocolate.language.utf8": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )" + } + }, + "hotchocolate.language.visitors": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )" + } + }, + "hotchocolate.language.web": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.Utf8": "[0.0.0, )" + } + }, + "hotchocolate.openapi": { + "type": "Project", + "dependencies": { + "HotChocolate": "[0.0.0, )", + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Skimmed": "[0.0.0, )", + "HotChocolate.Types.Json": "[0.0.0, )", + "HotChocolate.Types.Scalars": "[0.0.0, )", + "Microsoft.Extensions.Http": "[8.0.0-rc.1.23419.4, )", + "Microsoft.OpenApi": "[1.6.6, )", + "Microsoft.OpenApi.Readers": "[1.6.6, )" + } + }, + "HotChocolate.Skimmed": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Language": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )" + } + }, + "HotChocolate.StarWars": { + "type": "Project", + "dependencies": { + "ChilliCream.Testing.Utilities": "[0.2.0, )", + "CookieCrumble": "[0.0.0, )", + "DiffPlex": "[1.7.1, )", + "HotChocolate": "[0.0.0, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "Moq": "[4.18.1, )", + "Snapshooter.Xunit": "[0.5.4, )", + "xunit": "[2.4.1, )" + } + }, + "hotchocolate.subscriptions": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Execution.Abstractions": "[0.0.0, )" + } + }, + "hotchocolate.subscriptions.inmemory": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution.Abstractions": "[0.0.0, )", + "HotChocolate.Subscriptions": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )" + } + }, + "hotchocolate.tests.utilities": { + "type": "Project", + "dependencies": { + "ChilliCream.Testing.Utilities": "[0.2.0, )", + "CookieCrumble": "[0.0.0, )", + "DiffPlex": "[1.7.1, )", + "HotChocolate.StarWars": "[0.0.0, )", + "HotChocolate.Subscriptions.InMemory": "[0.0.0, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "Moq": "[4.18.1, )", + "Snapshooter.Xunit": "[0.5.4, )", + "xunit": "[2.4.1, )" + } + }, + "hotchocolate.transport.abstractions": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )", + "System.Collections.Immutable": "[1.7.0, )", + "System.Text.Json": "[6.0.7, )" + } + }, + "hotchocolate.transport.http": { + "type": "Project", + "dependencies": { + "HotChocolate.Transport.Abstractions": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )", + "System.IO.Pipelines": "[6.0.0, )" + } + }, + "hotchocolate.transport.sockets": { + "type": "Project", + "dependencies": { + "System.IO.Pipelines": "[4.7.0, )" + } + }, + "hotchocolate.transport.sockets.client": { + "type": "Project", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "[0.0.0, )", + "HotChocolate.Transport.Abstractions": "[0.0.0, )", + "HotChocolate.Transport.Sockets": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )", + "System.Collections.Immutable": "[1.7.0, )", + "System.Text.Json": "[6.0.7, )" + } + }, + "hotchocolate.types": { + "type": "Project", + "dependencies": { + "HotChocolate.Abstractions": "[0.0.0, )", + "HotChocolate.Utilities": "[0.0.0, )", + "HotChocolate.Utilities.Introspection": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )", + "Microsoft.Extensions.ObjectPool": "[3.1.4, )", + "System.ComponentModel.Annotations": "[4.7.0, )", + "System.Text.Json": "[6.0.7, )" + } + }, + "hotchocolate.types.cursorpagination": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.json": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.mutations": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.offsetpagination": { + "type": "Project", + "dependencies": { + "HotChocolate.Execution": "[0.0.0, )", + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.scalars": { + "type": "Project", + "dependencies": { + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.types.scalars.upload": { + "type": "Project", + "dependencies": { + "HotChocolate.Types": "[0.0.0, )" + } + }, + "hotchocolate.utilities": { + "type": "Project", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "[1.1.0, )", + "System.Memory": "[4.5.4, )", + "System.Threading.Tasks.Extensions": "[4.5.4, )" + } + }, + "hotchocolate.utilities.introspection": { + "type": "Project", + "dependencies": { + "HotChocolate.Language": "[0.0.0, )", + "System.Text.Json": "[6.0.7, )" + } + }, + "hotchocolate.validation": { + "type": "Project", + "dependencies": { + "HotChocolate.Types": "[0.0.0, )", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[3.1.4, )", + "Microsoft.Extensions.Options": "[3.1.4, )" + } + } + } + } +} \ No newline at end of file diff --git a/src/HotChocolate/Utilities/src/Utilities/HotChocolate.Utilities.csproj b/src/HotChocolate/Utilities/src/Utilities/HotChocolate.Utilities.csproj index 4a4f68d62a3..6c270ca8a55 100644 --- a/src/HotChocolate/Utilities/src/Utilities/HotChocolate.Utilities.csproj +++ b/src/HotChocolate/Utilities/src/Utilities/HotChocolate.Utilities.csproj @@ -16,6 +16,7 @@ + From 59b0e804d74d083525c983942771dd250f733b5e Mon Sep 17 00:00:00 2001 From: Vatsalya Goel Date: Mon, 9 Oct 2023 11:24:15 +0400 Subject: [PATCH 6/9] [Strawberry Shake] Use scheme provided by arguments (#6582) --- .../dotnet-graphql/OAuth/AuthArgumentsBase.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/AuthArgumentsBase.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/AuthArgumentsBase.cs index 16ede3f693c..fe1bd979490 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/AuthArgumentsBase.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/AuthArgumentsBase.cs @@ -41,15 +41,15 @@ public AuthArguments( IConsoleOutput output, CancellationToken cancellationToken) { - if (Token.HasValue()) - { - string? scheme = null; + string? scheme = null; - if (!NoScheme.HasValue()) - { - scheme = Scheme.HasValue() ? Scheme.Value()!.Trim() : _defaultScheme; - } + if (!NoScheme.HasValue()) + { + scheme = Scheme.HasValue() ? Scheme.Value()!.Trim() : _defaultScheme; + } + if (Token.HasValue()) + { return new AccessToken( Token.Value()!.Trim(), scheme); @@ -69,7 +69,7 @@ public AuthArguments( scopes, cancellationToken) .ConfigureAwait(false); - return new AccessToken(token, _defaultScheme); + return new AccessToken(token, scheme); } return null; @@ -104,4 +104,4 @@ private void ValidateOAuthArguments(IActivity activity) .Build()); } } -} \ No newline at end of file +} From 23e4e1e25442081a58143365fa6c404e7005c109 Mon Sep 17 00:00:00 2001 From: PascalSenn Date: Mon, 9 Oct 2023 11:16:05 +0200 Subject: [PATCH 7/9] Move to JsonElement in ConfigurationExtensions (#6580) --- .../src/Abstractions/FusionGraphPackage.cs | 3 ++- .../HotChocolate.Fusion.Abstractions.csproj | 1 + .../src/Abstractions/JsonElementExtensions.cs | 18 ++++++++++++++++++ .../src/Abstractions/SubgraphConfigJson.cs | 13 ++++++++++--- .../SubgraphConfigJsonSerializer.cs | 13 ++++++++++++- .../src/Abstractions/SubgraphConfiguration.cs | 8 ++++---- .../src/CommandLine/Helpers/PackageHelper.cs | 14 ++++---------- .../Helpers/SubgraphConfigurationDto.cs | 6 +++--- .../CommandLine.Tests/PackageHelperTests.cs | 4 ++-- .../Fusion/test/Shared/DemoSubgraph.cs | 2 +- .../Utilities/HotChocolate.Utilities.csproj | 1 + 11 files changed, 58 insertions(+), 25 deletions(-) create mode 100644 src/HotChocolate/Fusion/src/Abstractions/JsonElementExtensions.cs diff --git a/src/HotChocolate/Fusion/src/Abstractions/FusionGraphPackage.cs b/src/HotChocolate/Fusion/src/Abstractions/FusionGraphPackage.cs index 82ab62c29d1..661185f7313 100644 --- a/src/HotChocolate/Fusion/src/Abstractions/FusionGraphPackage.cs +++ b/src/HotChocolate/Fusion/src/Abstractions/FusionGraphPackage.cs @@ -579,7 +579,8 @@ private async Task WriteSubgraphConfigurationJsonPartAsync( { var config = new SubgraphConfigJson( configuration.Name, - configuration.Clients); + configuration.Clients, + configuration.ConfigurationExtensions); var path = $"{configuration.Name}/{SubgraphConfigFileName}"; var uri = PackUriHelper.CreatePartUri(new Uri(path, UriKind.Relative)); diff --git a/src/HotChocolate/Fusion/src/Abstractions/HotChocolate.Fusion.Abstractions.csproj b/src/HotChocolate/Fusion/src/Abstractions/HotChocolate.Fusion.Abstractions.csproj index f82d8d37732..053fd648a20 100644 --- a/src/HotChocolate/Fusion/src/Abstractions/HotChocolate.Fusion.Abstractions.csproj +++ b/src/HotChocolate/Fusion/src/Abstractions/HotChocolate.Fusion.Abstractions.csproj @@ -14,6 +14,7 @@ + diff --git a/src/HotChocolate/Fusion/src/Abstractions/JsonElementExtensions.cs b/src/HotChocolate/Fusion/src/Abstractions/JsonElementExtensions.cs new file mode 100644 index 00000000000..d5254096ca7 --- /dev/null +++ b/src/HotChocolate/Fusion/src/Abstractions/JsonElementExtensions.cs @@ -0,0 +1,18 @@ +using System.Text.Json; +using HotChocolate.Utilities; + +namespace HotChocolate.Fusion; + +internal static class JsonElementExtensions +{ + public static JsonElement SafeClone(this JsonElement element) + { + var writer = new ArrayWriter(); + using var jsonWriter = new Utf8JsonWriter(writer); + + element.WriteTo(jsonWriter); + var reader = new Utf8JsonReader(writer.GetSpan(), true, default); + + return JsonElement.ParseValue(ref reader); + } +} diff --git a/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJson.cs b/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJson.cs index 19831ed86c9..a3eee77f479 100644 --- a/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJson.cs +++ b/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJson.cs @@ -17,13 +17,17 @@ internal sealed record SubgraphConfigJson /// /// The list of clients that can be used to fetch data from this subgraph. /// + /// + /// The "extensions" property of the subgraph-config.json. + /// public SubgraphConfigJson( string name, IReadOnlyList? clients = null, - JsonDocument? extensions = null) + JsonElement? extensions = null) { Name = name; Clients = clients ?? Array.Empty(); + Extensions = extensions; } /// @@ -39,7 +43,7 @@ public SubgraphConfigJson( /// /// Gets the "extensions" property of the subgraph-config.json. /// - public JsonDocument? Extensions { get; init; } + public JsonElement? Extensions { get; init; } /// /// Deconstructs the into its components. @@ -50,10 +54,13 @@ public SubgraphConfigJson( /// /// The list of clients that can be used to fetch data from this subgraph. /// + /// + /// The "extensions" property of the subgraph-config.json. + /// public void Deconstruct( out string name, out IReadOnlyList clients, - out JsonDocument? extensions) + out JsonElement? extensions) { name = Name; clients = Clients; diff --git a/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJsonSerializer.cs b/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJsonSerializer.cs index 6556c6593f3..6937fe33213 100644 --- a/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJsonSerializer.cs +++ b/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJsonSerializer.cs @@ -146,6 +146,12 @@ public static async ValueTask FormatAsync( } } + if (config.Extensions is not null) + { + writer.WritePropertyName("extensions"); + config.Extensions.Value.WriteTo(writer); + } + writer.WriteEndObject(); await writer.FlushAsync(cancellationToken); } @@ -176,6 +182,7 @@ public static async Task ParseAsync( stream, cancellationToken: cancellationToken); var configs = new List(); var subgraph = default(string?); + var extensions = default(JsonElement?); foreach (var property in document.RootElement.EnumerateObject()) { @@ -193,6 +200,10 @@ public static async Task ParseAsync( configs.Add(ReadWebSocketClientConfiguration(property.Value)); break; + case "extensions": + extensions = property.Value.SafeClone(); + break; + default: throw new NotSupportedException( $"Configuration property `{property.Value}` is not supported."); @@ -204,7 +215,7 @@ public static async Task ParseAsync( throw new InvalidOperationException("No subgraph name was specified."); } - return new SubgraphConfigJson(subgraph, configs); + return new SubgraphConfigJson(subgraph, configs, extensions); } private static HttpClientConfiguration ReadHttpClientConfiguration( diff --git a/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfiguration.cs b/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfiguration.cs index 524101636b2..6fe5f8486d8 100644 --- a/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfiguration.cs +++ b/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfiguration.cs @@ -30,7 +30,7 @@ public SubgraphConfiguration( string schema, IReadOnlyList extensions, IReadOnlyList clients, - JsonDocument? configurationExtensions) + JsonElement? configurationExtensions) { Name = name; Schema = schema; @@ -62,7 +62,7 @@ public SubgraphConfiguration( string schema, string extensions, IReadOnlyList clients, - JsonDocument? configurationExtensions) + JsonElement? configurationExtensions) : this(name, schema, new[] { extensions }, clients, configurationExtensions) { } /// @@ -88,7 +88,7 @@ public SubgraphConfiguration( string schema, string extensions, IClientConfiguration client, - JsonDocument? configurationExtensions) + JsonElement? configurationExtensions) : this(name, schema, new[] { extensions }, new[] { client }, configurationExtensions) { } /// @@ -114,5 +114,5 @@ public SubgraphConfiguration( /// /// Gets the configuration extension. /// - public JsonDocument? ConfigurationExtensions { get; } + public JsonElement? ConfigurationExtensions { get; } } diff --git a/src/HotChocolate/Fusion/src/CommandLine/Helpers/PackageHelper.cs b/src/HotChocolate/Fusion/src/CommandLine/Helpers/PackageHelper.cs index 73f56c8b16f..3386bffc3eb 100644 --- a/src/HotChocolate/Fusion/src/CommandLine/Helpers/PackageHelper.cs +++ b/src/HotChocolate/Fusion/src/CommandLine/Helpers/PackageHelper.cs @@ -197,12 +197,6 @@ private static WebSocketClientConfiguration ReadWebSocketClientConfiguration( return new WebSocketClientConfiguration(baseAddress, clientName); } - private static JsonDocument ReadExtensions(JsonElement element) - { - var extensionText = element.GetRawText(); - return JsonDocument.Parse(extensionText); - } - private static async Task ParseSubgraphConfigAsync( Stream stream, CancellationToken ct) @@ -210,7 +204,7 @@ private static async Task ParseSubgraphConfigAsync( using var document = await JsonDocument.ParseAsync(stream, cancellationToken: ct); var configs = new List(); var subgraph = default(string?); - var jsonDocument = default(JsonDocument?); + var extensions = default(JsonElement?); foreach (var property in document.RootElement.EnumerateObject()) { @@ -229,7 +223,7 @@ private static async Task ParseSubgraphConfigAsync( break; case "extensions": - jsonDocument = ReadExtensions(property.Value); + extensions = property.Value.SafeClone(); break; default: @@ -243,7 +237,7 @@ private static async Task ParseSubgraphConfigAsync( throw new InvalidOperationException("No subgraph name was specified."); } - return new SubgraphConfigurationDto(subgraph, configs, jsonDocument); + return new SubgraphConfigurationDto(subgraph, configs, extensions); } public static string FormatSubgraphConfig( @@ -291,7 +285,7 @@ public static string FormatSubgraphConfig( if (subgraphConfig.Extensions is not null) { writer.WritePropertyName("extensions"); - subgraphConfig.Extensions.WriteTo(writer); + subgraphConfig.Extensions.Value.WriteTo(writer); } writer.WriteEndObject(); diff --git a/src/HotChocolate/Fusion/src/CommandLine/Helpers/SubgraphConfigurationDto.cs b/src/HotChocolate/Fusion/src/CommandLine/Helpers/SubgraphConfigurationDto.cs index ced5083daff..8011b8c1fd6 100644 --- a/src/HotChocolate/Fusion/src/CommandLine/Helpers/SubgraphConfigurationDto.cs +++ b/src/HotChocolate/Fusion/src/CommandLine/Helpers/SubgraphConfigurationDto.cs @@ -8,7 +8,7 @@ internal sealed record SubgraphConfigurationDto public SubgraphConfigurationDto( string name, IReadOnlyList? clients = null, - JsonDocument? extensions = null) + JsonElement? extensions = null) { Name = name; Clients = clients ?? Array.Empty(); @@ -19,12 +19,12 @@ public SubgraphConfigurationDto( public IReadOnlyList Clients { get; init; } - public JsonDocument? Extensions { get; init; } + public JsonElement? Extensions { get; init; } public void Deconstruct( out string name, out IReadOnlyList clients, - out JsonDocument? extensions) + out JsonElement? extensions) { name = Name; clients = Clients; diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/PackageHelperTests.cs b/src/HotChocolate/Fusion/test/CommandLine.Tests/PackageHelperTests.cs index e35eb29271f..d611e0d0ec2 100644 --- a/src/HotChocolate/Fusion/test/CommandLine.Tests/PackageHelperTests.cs +++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/PackageHelperTests.cs @@ -43,7 +43,7 @@ public async Task Create_Extract_Extensions() { // arrange using var demoProject = await DemoProject.CreateAsync(); - var extensions = JsonDocument.Parse("{ \"foo\": \"bar\" }"); + var extensions = JsonDocument.Parse("{ \"foo\": \"bar\" }").RootElement; var accountConfig = demoProject.Accounts.ToConfiguration(AccountsExtensionSdl, extensions); var account = CreateFiles(accountConfig); var packageFile = CreateTempFile(); @@ -85,7 +85,7 @@ private void Match(SubgraphConfiguration config) using var stream = new MemoryStream(); using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true }); - config.ConfigurationExtensions.WriteTo(writer); + config.ConfigurationExtensions.Value.WriteTo(writer); writer.Flush(); var json = Encoding.UTF8.GetString(stream.ToArray()); diff --git a/src/HotChocolate/Fusion/test/Shared/DemoSubgraph.cs b/src/HotChocolate/Fusion/test/Shared/DemoSubgraph.cs index e6656d118f9..251476ede77 100644 --- a/src/HotChocolate/Fusion/test/Shared/DemoSubgraph.cs +++ b/src/HotChocolate/Fusion/test/Shared/DemoSubgraph.cs @@ -62,7 +62,7 @@ public SubgraphConfiguration ToConfiguration( public SubgraphConfiguration ToConfiguration( string extensions, - JsonDocument configurationExtensions, + JsonElement configurationExtensions, bool onlyHttp = false) => onlyHttp ? new SubgraphConfiguration( diff --git a/src/HotChocolate/Utilities/src/Utilities/HotChocolate.Utilities.csproj b/src/HotChocolate/Utilities/src/Utilities/HotChocolate.Utilities.csproj index 6c270ca8a55..3aef4956611 100644 --- a/src/HotChocolate/Utilities/src/Utilities/HotChocolate.Utilities.csproj +++ b/src/HotChocolate/Utilities/src/Utilities/HotChocolate.Utilities.csproj @@ -16,6 +16,7 @@ + From b7bb6ccf50c2549e9e1184e9bdad56b800dcab09 Mon Sep 17 00:00:00 2001 From: PascalSenn Date: Mon, 9 Oct 2023 13:17:27 +0200 Subject: [PATCH 8/9] Adds remove subgraph to Fusion Tooling (#6584) --- .../src/Abstractions/FusionGraphPackage.cs | 49 ++++++- .../SubgraphConfigJsonSerializer.cs | 2 +- .../CommandLine/Commands/ComposeCommand.cs | 21 ++- .../CommandLine.Tests/ComposeCommandTests.cs | 63 +++++++++ ....Compose_Fusion_Graph_Remove_Subgraph.snap | 127 ++++++++++++++++++ 5 files changed, 255 insertions(+), 7 deletions(-) create mode 100644 src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Fusion_Graph_Remove_Subgraph.snap diff --git a/src/HotChocolate/Fusion/src/Abstractions/FusionGraphPackage.cs b/src/HotChocolate/Fusion/src/Abstractions/FusionGraphPackage.cs index 661185f7313..7f4207a70b4 100644 --- a/src/HotChocolate/Fusion/src/Abstractions/FusionGraphPackage.cs +++ b/src/HotChocolate/Fusion/src/Abstractions/FusionGraphPackage.cs @@ -416,7 +416,7 @@ public async Task> GetSubgraphConfiguration /// /// The Fusion graph package must be opened in read/write mode to update contents. /// - public Task SetSubgraphConfigurationAsync( + public async Task SetSubgraphConfigurationAsync( SubgraphConfiguration configuration, CancellationToken cancellationToken = default) { @@ -430,9 +430,46 @@ public Task SetSubgraphConfigurationAsync( throw new FusionGraphPackageException(FusionGraphPackage_CannotWrite); } - if (_package.RelationshipExists(configuration.Name)) + await RemoveSubgraphConfigurationAsync(configuration.Name, cancellationToken); + + await WriteSubgraphConfigurationAsync(configuration, cancellationToken); + } + + /// + /// Removes a subgraph configuration from the package. + /// + /// + /// The name of the subgraph configuration to remove. + /// + /// + /// The cancellation token. + /// + /// + /// A representing the asynchronous operation. + /// + /// + /// is null. + /// + /// + /// The Fusion graph package must be opened in read/write mode to update contents. + /// + public Task RemoveSubgraphConfigurationAsync( + string subgraphName, + CancellationToken cancellationToken = default) + { + if (subgraphName is null) { - var rootRel = _package.GetRelationship(configuration.Name); + throw new ArgumentNullException(nameof(subgraphName)); + } + + if (_package.FileOpenAccess != FileAccess.ReadWrite) + { + throw new FusionGraphPackageException(FusionGraphPackage_CannotWrite); + } + + if (_package.RelationshipExists(subgraphName)) + { + var rootRel = _package.GetRelationship(subgraphName); var rootPart = _package.GetPart(rootRel.TargetUri); foreach (var relationship in rootPart.GetRelationships()) @@ -440,11 +477,13 @@ public Task SetSubgraphConfigurationAsync( _package.DeletePart(relationship.TargetUri); } - _package.DeleteRelationship(configuration.Name); + _package.DeleteRelationship(subgraphName); _package.DeletePart(rootPart.Uri); } - return WriteSubgraphConfigurationAsync(configuration, cancellationToken); + _package.Flush(); + + return Task.CompletedTask; } private static async Task ReadSchemaPartAsync( diff --git a/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJsonSerializer.cs b/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJsonSerializer.cs index 6937fe33213..c500e868009 100644 --- a/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJsonSerializer.cs +++ b/src/HotChocolate/Fusion/src/Abstractions/SubgraphConfigJsonSerializer.cs @@ -203,7 +203,7 @@ public static async Task ParseAsync( case "extensions": extensions = property.Value.SafeClone(); break; - + default: throw new NotSupportedException( $"Configuration property `{property.Value}` is not supported."); diff --git a/src/HotChocolate/Fusion/src/CommandLine/Commands/ComposeCommand.cs b/src/HotChocolate/Fusion/src/CommandLine/Commands/ComposeCommand.cs index e6a49f98a51..08711f5547f 100644 --- a/src/HotChocolate/Fusion/src/CommandLine/Commands/ComposeCommand.cs +++ b/src/HotChocolate/Fusion/src/CommandLine/Commands/ComposeCommand.cs @@ -34,6 +34,9 @@ public ComposeCommand() : base("compose") fusionPackageSettingsFile.AddAlias("--package-settings"); fusionPackageSettingsFile.AddAlias("--settings"); + var removeSubgraphs = new Option?>("--remove"); + removeSubgraphs.AddAlias("-r"); + var workingDirectory = new WorkingDirectoryOption(); var enableNodes = new Option("--enable-nodes"); @@ -43,12 +46,14 @@ public ComposeCommand() : base("compose") AddOption(subgraphPackageFile); AddOption(workingDirectory); AddOption(enableNodes); + AddOption(removeSubgraphs); this.SetHandler( ExecuteAsync, Bind.FromServiceProvider(), fusionPackageFile, subgraphPackageFile, + removeSubgraphs, fusionPackageSettingsFile, workingDirectory, enableNodes, @@ -61,6 +66,7 @@ private static async Task ExecuteAsync( IConsole console, FileInfo packageFile, List? subgraphPackageFiles, + List? removeSubgraphs, FileInfo? settingsFile, DirectoryInfo workingDirectory, bool? enableNodes, @@ -94,8 +100,21 @@ private static async Task ExecuteAsync( await using var package = FusionGraphPackage.Open(packageFile.FullName); + if(removeSubgraphs is not null) + { + foreach (var subgraph in removeSubgraphs) + { + await package.RemoveSubgraphConfigurationAsync(subgraph, cancellationToken); + } + } + var configs = (await package.GetSubgraphConfigurationsAsync(cancellationToken)).ToDictionary(t => t.Name); - await ResolveSubgraphPackagesAsync(workingDirectory, subgraphPackageFiles, configs, cancellationToken); + + // resolve subraph packages will scan the directory for fsp's. In case of remove we don't want to do that. + if (removeSubgraphs is not { Count: > 0 } || subgraphPackageFiles is { Count: > 0 }) + { + await ResolveSubgraphPackagesAsync(workingDirectory, subgraphPackageFiles, configs, cancellationToken); + } using var settingsJson = settingsFile.Exists ? JsonDocument.Parse(await File.ReadAllTextAsync(settingsFile.FullName, cancellationToken)) diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/ComposeCommandTests.cs b/src/HotChocolate/Fusion/test/CommandLine.Tests/ComposeCommandTests.cs index 9fdc6a1c41e..613901c50d0 100644 --- a/src/HotChocolate/Fusion/test/CommandLine.Tests/ComposeCommandTests.cs +++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/ComposeCommandTests.cs @@ -265,4 +265,67 @@ public async Task Compose_Loose_Subgraph_Files() snapshot.MatchSnapshot(); } + + [Fact] + public async Task Compose_Fusion_Graph_Remove_Subgraph() + { + // arrange + using var demoProject = await DemoProject.CreateAsync(); + var accountConfig = demoProject.Accounts.ToConfiguration(AccountsExtensionSdl); + var account = CreateFiles(accountConfig); + var accountSubgraphPackageFile = CreateTempFile(); + + await PackageHelper.CreateSubgraphPackageAsync( + accountSubgraphPackageFile, + new SubgraphFiles( + account.SchemaFile, + account.TransportConfigFile, + account.ExtensionFiles)); + + var reviewConfig = demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl); + var review = CreateFiles(reviewConfig); + var reviewSubgraphPackageFile = CreateTempFile(); + + await PackageHelper.CreateSubgraphPackageAsync( + reviewSubgraphPackageFile, + new SubgraphFiles( + review.SchemaFile, + review.TransportConfigFile, + review.ExtensionFiles)); + + var packageFile = CreateTempFile(Extensions.FusionPackage); + + var app = App.CreateBuilder().Build(); + await app.InvokeAsync(new[] { "compose", "-p", packageFile, "-s", accountSubgraphPackageFile }); + + app = App.CreateBuilder().Build(); + await app.InvokeAsync( + new[] { "compose", "-p", packageFile, "-s", reviewSubgraphPackageFile }); + + // act + app = App.CreateBuilder().Build(); + await app.InvokeAsync( + new[] { "compose", "-p", packageFile, "-r", "Reviews2" }); + + // assert + Assert.True(File.Exists(packageFile)); + + await using var package = FusionGraphPackage.Open(packageFile, FileAccess.Read); + + var fusionGraph = await package.GetFusionGraphAsync(); + var schema = await package.GetSchemaAsync(); + var subgraphs = await package.GetSubgraphConfigurationsAsync(); + + var snapshot = new Snapshot(); + + snapshot.Add(schema, "Schema Document"); + snapshot.Add(fusionGraph, "Fusion Graph Document"); + + foreach (var subgraph in subgraphs) + { + snapshot.Add(subgraph, $"{subgraph.Name} Subgraph Configuration"); + } + + snapshot.MatchSnapshot(); + } } diff --git a/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Fusion_Graph_Remove_Subgraph.snap b/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Fusion_Graph_Remove_Subgraph.snap new file mode 100644 index 00000000000..5ae2aa95ee3 --- /dev/null +++ b/src/HotChocolate/Fusion/test/CommandLine.Tests/__snapshots__/ComposeCommandTests.Compose_Fusion_Graph_Remove_Subgraph.snap @@ -0,0 +1,127 @@ +Schema Document +--------------- +schema { + query: Query + mutation: Mutation +} + +type Query { + userById(id: ID!): User + users: [User!]! + usersById(ids: [ID!]!): [User!]! + viewer: Viewer! +} + +type Mutation { + addUser(input: AddUserInput!): AddUserPayload! +} + +type AddUserPayload { + user: User +} + +type SomeData { + accountValue: String! +} + +type User implements Node { + birthdate: Date! + id: ID! + name: String! + username: String! +} + +type Viewer { + data: SomeData! + user: User +} + +"The node interface is implemented by entities that have a global unique identifier." +interface Node { + id: ID! +} + +input AddUserInput { + birthdate: Date! + name: String! + username: String! +} + +"The `Date` scalar represents an ISO-8601 compliant date type." +scalar Date +--------------- + +Fusion Graph Document +--------------- +schema @fusion(version: 1) @transport(subgraph: "Accounts", group: "Fusion", location: "http:\/\/localhost:5000\/graphql", kind: "HTTP") @transport(subgraph: "Accounts", group: "Fusion", location: "ws:\/\/localhost:5000\/graphql", kind: "WebSocket") { + query: Query + mutation: Mutation +} + +type Query { + userById(id: ID!): User @variable(subgraph: "Accounts", name: "id", argument: "id") @resolver(subgraph: "Accounts", select: "{ userById(id: $id) }", arguments: [ { name: "id", type: "ID!" } ]) + users: [User!]! @resolver(subgraph: "Accounts", select: "{ users }") + usersById(ids: [ID!]!): [User!]! @variable(subgraph: "Accounts", name: "ids", argument: "ids") @resolver(subgraph: "Accounts", select: "{ usersById(ids: $ids) }", arguments: [ { name: "ids", type: "[ID!]!" } ]) + viewer: Viewer! @resolver(subgraph: "Accounts", select: "{ viewer }") +} + +type Mutation { + addUser(input: AddUserInput!): AddUserPayload! @variable(subgraph: "Accounts", name: "input", argument: "input") @resolver(subgraph: "Accounts", select: "{ addUser(input: $input) }", arguments: [ { name: "input", type: "AddUserInput!" } ]) +} + +type AddUserPayload { + user: User @source(subgraph: "Accounts") +} + +type SomeData { + accountValue: String! @source(subgraph: "Accounts") +} + +type User implements Node @variable(subgraph: "Accounts", name: "User_id", select: "id") @resolver(subgraph: "Accounts", select: "{ userById(id: $User_id) }", arguments: [ { name: "User_id", type: "ID!" } ]) @resolver(subgraph: "Accounts", select: "{ usersById(ids: $User_id) }", arguments: [ { name: "User_id", type: "[ID!]!" } ], kind: "BATCH") { + birthdate: Date! @source(subgraph: "Accounts") + id: ID! @source(subgraph: "Accounts") + name: String! @source(subgraph: "Accounts") + username: String! @source(subgraph: "Accounts") +} + +type Viewer { + data: SomeData! @source(subgraph: "Accounts") + user: User @source(subgraph: "Accounts") +} + +"The node interface is implemented by entities that have a global unique identifier." +interface Node { + id: ID! +} + +input AddUserInput { + birthdate: Date! + name: String! + username: String! +} + +"The `Date` scalar represents an ISO-8601 compliant date type." +scalar Date +--------------- + +Accounts Subgraph Configuration +--------------- +{ + "Name": "Accounts", + "Schema": "schema {\n query: Query\n mutation: Mutation\n}\n\n\"The node interface is implemented by entities that have a global unique identifier.\"\ninterface Node {\n id: ID!\n}\n\ntype Query {\n \"Fetches an object given its ID.\"\n node(\"ID of the object.\" id: ID!): Node\n \"Lookup nodes by a list of IDs.\"\n nodes(\"The list of node IDs.\" ids: [ID!]!): [Node]!\n users: [User!]!\n userById(id: ID!): User\n usersById(ids: [ID!]!): [User!]!\n viewer: Viewer!\n}\n\ntype Mutation {\n addUser(input: AddUserInput!): AddUserPayload!\n}\n\n\"The `Date` scalar represents an ISO-8601 compliant date type.\"\nscalar Date\n\ntype User implements Node {\n id: ID!\n name: String!\n birthdate: Date!\n username: String!\n}\n\ntype Viewer {\n user: User\n data: SomeData!\n}\n\ntype SomeData {\n accountValue: String!\n}\n\ninput AddUserInput {\n name: String!\n username: String!\n birthdate: Date!\n}\n\ntype AddUserPayload {\n user: User\n}", + "Extensions": [ + "extend type Query {\n userById(id: ID!\n @is(field: \"id\")): User!\n usersById(ids: [ID!]!\n @is(field: \"id\")): [User!]!\n}" + ], + "Clients": [ + { + "ClientName": null, + "BaseAddress": "http://localhost:5000/graphql" + }, + { + "ClientName": null, + "BaseAddress": "ws://localhost:5000/graphql" + } + ], + "ConfigurationExtensions": null +} +--------------- From b741f5f0750c9c9211345f0b05896eb2cda0ac3b Mon Sep 17 00:00:00 2001 From: Daniel Wust Date: Mon, 9 Oct 2023 19:12:16 +0200 Subject: [PATCH 9/9] Make CustomOptionsFlags on Selections public (#6587) --- .../Core/src/Execution/Processing/Selection.cs | 10 ++++++---- .../Core/src/Types/Execution/Processing/ISelection.cs | 1 - 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/HotChocolate/Core/src/Execution/Processing/Selection.cs b/src/HotChocolate/Core/src/Execution/Processing/Selection.cs index 60a5296db52..774895a6d63 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/Selection.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/Selection.cs @@ -88,7 +88,7 @@ protected Selection(Selection selection) /// public int Id { get; } - internal CustomOptionsFlags CustomOptions { get; private set; } + public CustomOptionsFlags CustomOptions { get; private set; } /// public SelectionExecutionStrategy Strategy { get; private set; } @@ -320,7 +320,7 @@ internal void MarkAsStream(long ifCondition) _flags |= Flags.Stream; } - internal void SetOption(CustomOptionsFlags customOptions) + public void SetOption(CustomOptionsFlags customOptions) { if ((_flags & Flags.Sealed) == Flags.Sealed) { @@ -390,14 +390,16 @@ private enum Flags } [Flags] - internal enum CustomOptionsFlags : byte + public enum CustomOptionsFlags : byte { None = 0, Option1 = 1, Option2 = 2, Option3 = 4, Option4 = 8, - Option5 = 16 + Option5 = 16, + Option6 = 32, + Option7 = 64 } internal sealed class Sealed : Selection diff --git a/src/HotChocolate/Core/src/Types/Execution/Processing/ISelection.cs b/src/HotChocolate/Core/src/Types/Execution/Processing/ISelection.cs index ad6ebafc658..d1ff0aabfd7 100644 --- a/src/HotChocolate/Core/src/Types/Execution/Processing/ISelection.cs +++ b/src/HotChocolate/Core/src/Types/Execution/Processing/ISelection.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using HotChocolate.Language; using HotChocolate.Resolvers;