Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed and issue where the connection type was registered twice. #842

Merged
merged 6 commits into from
Jun 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Subscription now uses pipeline API to abstract sockets. [#807](https://github.com/ChilliCream/hotchocolate/pull/807)
- Improved parser performance. [#806](https://github.com/ChilliCream/hotchocolate/pull/806)

## [9.0.4] - 2019-06-16

### Fixed

- Fixed paging flaws that in some cases lead to the connection type being registered twice. [#842](https://github.com/ChilliCream/hotchocolate/pull/842)

## [9.0.3] - 2019-06-13

### Fixed

- Fixed issues where the type initializer would swallow schema errors.

## [9.0.2] - 2019-06-12

### Fixed
Expand Down
34 changes: 34 additions & 0 deletions examples/AspNetCore.StarWars/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/netcoreapp2.1/AspNetCore.StarWars.dll",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"serverReadyAction": {
"action": "openExternally",
"pattern": "^\\s*Now listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}
17 changes: 17 additions & 0 deletions examples/AspNetCore.StarWars/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet build",
"type": "shell",
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
}
]
}
3 changes: 2 additions & 1 deletion examples/AspNetCore.StarWars/Types/CharacterType.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using HotChocolate.Types;
using HotChocolate.Types.Relay;
using StarWars.Models;

namespace StarWars.Types
Expand All @@ -17,7 +18,7 @@ protected override void Configure(IInterfaceTypeDescriptor<ICharacter> descripto
.Type<StringType>();

descriptor.Field(f => f.Friends)
.Type<ListType<CharacterType>>();
.UsePaging<CharacterType>();

descriptor.Field(f => f.AppearsIn)
.Type<ListType<EpisodeType>>();
Expand Down
3 changes: 2 additions & 1 deletion examples/AspNetCore.StarWars/Types/DroidType.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using HotChocolate.Types;
using HotChocolate.Types.Relay;
using StarWars.Models;
using StarWars.Resolvers;

Expand All @@ -18,7 +19,7 @@ protected override void Configure(IObjectTypeDescriptor<Droid> descriptor)
.Type<ListType<EpisodeType>>();

descriptor.Field<SharedResolvers>(r => r.GetCharacter(default, default))
.Type<ListType<CharacterType>>()
.UsePaging<CharacterType>()
.Name("friends");

descriptor.Field<SharedResolvers>(t => t.GetHeight(default, default))
Expand Down
3 changes: 2 additions & 1 deletion examples/AspNetCore.StarWars/Types/HumanType.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using HotChocolate.Types;
using HotChocolate.Types.Relay;
using StarWars.Models;
using StarWars.Resolvers;

Expand All @@ -18,7 +19,7 @@ protected override void Configure(IObjectTypeDescriptor<Human> descriptor)
.Type<ListType<EpisodeType>>();

descriptor.Field<SharedResolvers>(r => r.GetCharacter(default, default))
.Type<ListType<CharacterType>>()
.UsePaging<CharacterType>()
.Name("friends");

descriptor.Field<SharedResolvers>(t => t.GetHeight(default, default))
Expand Down
81 changes: 79 additions & 2 deletions src/Core/Types.Tests/Types/Relay/ConnectionTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void CheckFieldsAreCorrect()
},
t =>
{
Assert.Equal("items", t.Name);
Assert.Equal("nodes", t.Name);
Assert.IsType<StringType>(
Assert.IsType<ListType>(t.Type).ElementType);
},
Expand Down Expand Up @@ -104,7 +104,7 @@ public async Task UsePaging_WithNonNull_ElementType()
cursor
node
}
items
nodes
pageInfo
{
hasNextPage
Expand All @@ -122,6 +122,43 @@ public async Task UsePaging_WithNonNull_ElementType()
result.MatchSnapshot();
}

[Fact]
public async Task UsePaging_WithComplexType()
{
// arrange
ISchema schema = SchemaBuilder.New()
.AddType<FooType>()
.AddQueryType<QueryType3>()
.Create();

IQueryExecutor executor = schema.MakeExecutable();

string query = @"
{
s
{
bar {
edges {
cursor
node
}
pageInfo
{
hasNextPage
}
totalCount
}
}
}
";

// act
IExecutionResult result = await executor.ExecuteAsync(query);

// assert
result.MatchSnapshot();
}

public class QueryType
: ObjectType
{
Expand Down Expand Up @@ -152,10 +189,50 @@ protected override void Configure(IObjectTypeDescriptor descriptor)
}
}

public class QueryType3
: ObjectType
{
protected override void Configure(IObjectTypeDescriptor descriptor)
{
descriptor.Name("Query");
descriptor.Field("s")
.Resolver(ctx => new Foo());
}
}

public class Query
{
public ICollection<string> Strings { get; } =
new List<string> { "a", "b", "c", "d", "e", "f", "g" };
}

public class FooType
: ObjectType<Foo>
{
protected override void Configure(
IObjectTypeDescriptor<Foo> descriptor)
{
descriptor.Interface<FooInterfaceType>();
descriptor.Field(t => t.Bar).UsePaging<StringType>();
}
}

public class FooInterfaceType
: InterfaceType
{
protected override void Configure(
IInterfaceTypeDescriptor descriptor)
{
descriptor.Name("IFoo");
descriptor.Field("bar")
.UsePaging<StringType>();
}
}

public class Foo
{
public ICollection<string> Bar { get; } =
new List<string> { "a", "b", "c", "d", "e", "f", "g" };
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"Data": {
"s": {
"bar": {
"edges": [
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjB9",
"node": "a"
},
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjF9",
"node": "b"
},
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjJ9",
"node": "c"
},
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjN9",
"node": "d"
},
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjR9",
"node": "e"
},
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjV9",
"node": "f"
},
{
"cursor": "eyJfX3RvdGFsQ291bnQiOjcsIl9fcG9zaXRpb24iOjZ9",
"node": "g"
}
],
"pageInfo": {
"hasNextPage": false
},
"totalCount": 7
}
}
},
"Extensions": {},
"Errors": [],
"ContextData": {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"node": "g"
}
],
"items": [
"nodes": [
"f",
"g"
],
Expand Down
27 changes: 1 addition & 26 deletions src/Core/Types/Types/Relay/ConnectionType.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Linq;
using HotChocolate.Configuration;
using HotChocolate.Resolvers;
using HotChocolate.Types.Descriptors;
using HotChocolate.Types.Descriptors.Definitions;

Expand Down Expand Up @@ -29,7 +28,6 @@ public ConnectionType(

public IEdgeType EdgeType { get; private set; }


protected new static void Configure(
IObjectTypeDescriptor<IConnection> descriptor)
{
Expand All @@ -50,7 +48,7 @@ public ConnectionType(
.Description("A list of edges.")
.Type<ListType<NonNullType<EdgeType<T>>>>();

descriptor.Field("items")
descriptor.Field("nodes")
.Description("A flattened list of the nodes.")
.Type<ListType<T>>()
.Resolver(ctx =>
Expand All @@ -77,28 +75,5 @@ protected override void OnCompleteType(
EdgeType = context.GetType<EdgeType<T>>(
ClrTypeReference.FromSchemaType<EdgeType<T>>());
}

public static ConnectionType<T> CreateWithTotalCount()
{
return new ConnectionType<T>(c =>
{
c.Field("totalCount")
.Type<NonNullType<IntType>>()
.Resolver(ctx => GetTotalCount(ctx));
});
}

private static IResolverResult<long> GetTotalCount(
IResolverContext context)
{
IConnection connection = context.Parent<IConnection>();
if (connection.PageInfo.TotalCount.HasValue)
{
return ResolverResult.CreateValue(
connection.PageInfo.TotalCount.Value);
}
return ResolverResult.CreateError<long>(
"The total count was not provided by the connection.");
}
}
}
46 changes: 46 additions & 0 deletions src/Core/Types/Types/Relay/ConnectionWithCountType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using HotChocolate.Resolvers;

namespace HotChocolate.Types.Relay
{
public class ConnectionWithCountType<T>
: ConnectionType<T>
where T : IOutputType
{
public ConnectionWithCountType()
: base(descriptor => Configure(descriptor))
{
}

public ConnectionWithCountType(
Action<IObjectTypeDescriptor<IConnection>> configure)
: base(descriptor =>
{
Configure(descriptor);
configure?.Invoke(descriptor);
})
{
}

protected new static void Configure(
IObjectTypeDescriptor<IConnection> descriptor)
{
descriptor.Field("totalCount")
.Type<NonNullType<IntType>>()
.Resolver(ctx => GetTotalCount(ctx));
}

private static IResolverResult<long> GetTotalCount(
IResolverContext context)
{
IConnection connection = context.Parent<IConnection>();
if (connection.PageInfo.TotalCount.HasValue)
{
return ResolverResult.CreateValue(
connection.PageInfo.TotalCount.Value);
}
return ResolverResult.CreateError<long>(
"The total count was not provided by the connection.");
}
}
}
Loading