diff --git a/Dapper.GraphQL.Test/Dapper.GraphQL.Test.csproj b/Dapper.GraphQL.Test/Dapper.GraphQL.Test.csproj
index f4efc07..1fb9dde 100644
--- a/Dapper.GraphQL.Test/Dapper.GraphQL.Test.csproj
+++ b/Dapper.GraphQL.Test/Dapper.GraphQL.Test.csproj
@@ -10,6 +10,8 @@
0.4.2.0
0.4.2-beta
+
+ latest
diff --git a/Dapper.GraphQL.Test/GraphQL/Cursor.cs b/Dapper.GraphQL.Test/GraphQL/Cursor.cs
new file mode 100644
index 0000000..50f7d81
--- /dev/null
+++ b/Dapper.GraphQL.Test/GraphQL/Cursor.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+
+namespace Dapper.GraphQL.Test.GraphQL
+{
+ public static class Cursor
+ {
+ public static T FromCursor(string cursor)
+ {
+ if (string.IsNullOrEmpty(cursor))
+ {
+ return default;
+ }
+
+ string decodedValue;
+ try
+ {
+ decodedValue = Base64Decode(cursor);
+ }
+ catch (FormatException)
+ {
+ return default;
+ }
+
+ return (T)Convert.ChangeType(decodedValue, Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T), CultureInfo.InvariantCulture);
+ }
+
+ public static (string firstCursor, string lastCursor) GetFirstAndLastCursor(
+ IEnumerable enumerable,
+ Func getCursorProperty)
+ {
+ if (getCursorProperty == null)
+ {
+ throw new ArgumentNullException(nameof(getCursorProperty));
+ }
+
+ if (enumerable == null || enumerable.Count() == 0)
+ {
+ return (null, null);
+ }
+
+ var firstCursor = ToCursor(getCursorProperty(enumerable.First()));
+ var lastCursor = ToCursor(getCursorProperty(enumerable.Last()));
+
+ return (firstCursor, lastCursor);
+ }
+
+ public static string ToCursor(T value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+
+ return Base64Encode(value.ToString());
+ }
+
+ private static string Base64Decode(string value) => Encoding.UTF8.GetString(Convert.FromBase64String(value));
+
+ private static string Base64Encode(string value) => Convert.ToBase64String(Encoding.UTF8.GetBytes(value));
+ }
+}
diff --git a/Dapper.GraphQL.Test/GraphQL/PersonQuery.cs b/Dapper.GraphQL.Test/GraphQL/PersonQuery.cs
index e311738..b036632 100644
--- a/Dapper.GraphQL.Test/GraphQL/PersonQuery.cs
+++ b/Dapper.GraphQL.Test/GraphQL/PersonQuery.cs
@@ -1,21 +1,33 @@
-using Dapper.GraphQL.Test.EntityMappers;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Dapper.GraphQL.Test.EntityMappers;
using Dapper.GraphQL.Test.Models;
+using GraphQL.Builders;
using GraphQL.Types;
+using GraphQL.Types.Relay.DataObjects;
using Microsoft.Extensions.DependencyInjection;
-using System;
-using System.Data;
-using System.Data.Common;
-using System.Linq;
+using Dapper.GraphQL.Test.Repositories;
+
namespace Dapper.GraphQL.Test.GraphQL
{
public class PersonQuery :
ObjectGraphType
{
+ private const int MaxPageSize = 10;
+ private readonly IPersonRepository _personRepository;
+
public PersonQuery(
IQueryBuilder personQueryBuilder,
- IServiceProvider serviceProvider)
+ IServiceProvider serviceProvider,
+ IPersonRepository personRepository)
{
+ _personRepository = personRepository;
+
Field>(
"people",
description: "A list of people.",
@@ -99,6 +111,85 @@ public PersonQuery(
}
}
);
+
+ Connection()
+ .Name("personConnection")
+ .Description("Gets pages of Person objects.")
+ // Enable the last and before arguments to do paging in reverse.
+ .Bidirectional()
+ // Set the maximum size of a page, use .ReturnAll() to set no maximum size.
+ .PageSize(MaxPageSize)
+ .ResolveAsync(context => ResolveConnection(context, personQueryBuilder));
+ }
+
+ private async Task