mirror of
https://github.com/ash-project/ash_graphql.git
synced 2024-09-20 05:13:33 +12:00
fix: non relay keyset pagination was broken when relay was introduced
This commit is contained in:
parent
9a3136fd5d
commit
8d79fd7d2a
4 changed files with 109 additions and 24 deletions
|
@ -144,7 +144,7 @@ defmodule AshGraphql.Graphql.Resolver do
|
||||||
|
|
||||||
def resolve(
|
def resolve(
|
||||||
%{arguments: args, context: context} = resolution,
|
%{arguments: args, context: context} = resolution,
|
||||||
{api, resource, %{type: :list, action: action, modify_resolution: modify}}
|
{api, resource, %{type: :list, relay?: relay?, action: action, modify_resolution: modify}}
|
||||||
) do
|
) do
|
||||||
opts = [
|
opts = [
|
||||||
actor: Map.get(context, :actor),
|
actor: Map.get(context, :actor),
|
||||||
|
@ -157,7 +157,7 @@ defmodule AshGraphql.Graphql.Resolver do
|
||||||
|
|
||||||
{result, modify_args} =
|
{result, modify_args} =
|
||||||
with {:ok, opts} <- validate_resolve_opts(resolution, pagination, opts, args),
|
with {:ok, opts} <- validate_resolve_opts(resolution, pagination, opts, args),
|
||||||
result_fields <- get_result_fields(pagination),
|
result_fields <- get_result_fields(pagination, relay?),
|
||||||
initial_query <-
|
initial_query <-
|
||||||
query
|
query
|
||||||
|> Ash.Query.set_tenant(Map.get(context, :tenant))
|
|> Ash.Query.set_tenant(Map.get(context, :tenant))
|
||||||
|
@ -172,7 +172,7 @@ defmodule AshGraphql.Graphql.Resolver do
|
||||||
authorize?: AshGraphql.Api.Info.authorize?(api)
|
authorize?: AshGraphql.Api.Info.authorize?(api)
|
||||||
)
|
)
|
||||||
|> api.read(opts) do
|
|> api.read(opts) do
|
||||||
result = paginate(resource, action, page)
|
result = paginate(resource, action, page, relay?)
|
||||||
{result, [query, result]}
|
{result, [query, result]}
|
||||||
else
|
else
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
|
@ -279,15 +279,19 @@ defmodule AshGraphql.Graphql.Resolver do
|
||||||
{:ok, opts}
|
{:ok, opts}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_result_fields(%{keyset?: true}) do
|
defp get_result_fields(%{keyset?: true}, true) do
|
||||||
["edges", "node"]
|
["edges", "node"]
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_result_fields(%{offset?: true}) do
|
defp get_result_fields(%{keyset?: true}, false) do
|
||||||
["results"]
|
["results"]
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_result_fields(_pagination) do
|
defp get_result_fields(%{offset?: true}, _) do
|
||||||
|
["results"]
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_result_fields(_pagination, _) do
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -299,12 +303,17 @@ defmodule AshGraphql.Graphql.Resolver do
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
|
||||||
defp paginate(_resource, _action, %Ash.Page.Keyset{
|
defp paginate(
|
||||||
results: results,
|
_resource,
|
||||||
more?: more,
|
_action,
|
||||||
after: after_cursor,
|
%Ash.Page.Keyset{
|
||||||
before: before_cursor
|
results: results,
|
||||||
}) do
|
more?: more,
|
||||||
|
after: after_cursor,
|
||||||
|
before: before_cursor
|
||||||
|
},
|
||||||
|
true
|
||||||
|
) do
|
||||||
{start_cursor, end_cursor} =
|
{start_cursor, end_cursor} =
|
||||||
case results do
|
case results do
|
||||||
[] ->
|
[] ->
|
||||||
|
@ -351,22 +360,44 @@ defmodule AshGraphql.Graphql.Resolver do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp paginate(_resource, _action, %Ash.Page.Offset{results: results, count: count}) do
|
defp paginate(
|
||||||
|
_resource,
|
||||||
|
_action,
|
||||||
|
%Ash.Page.Keyset{
|
||||||
|
results: results,
|
||||||
|
count: count
|
||||||
|
},
|
||||||
|
false
|
||||||
|
) do
|
||||||
{:ok, %{results: results, count: count}}
|
{:ok, %{results: results, count: count}}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp paginate(resource, action, page) do
|
defp paginate(_resource, _action, %Ash.Page.Offset{results: results, count: count}, _) do
|
||||||
|
{:ok, %{results: results, count: count}}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp paginate(resource, action, page, relay?) do
|
||||||
case Ash.Resource.Info.action(resource, action).pagination do
|
case Ash.Resource.Info.action(resource, action).pagination do
|
||||||
%{offset?: true} ->
|
%{offset?: true} ->
|
||||||
paginate(resource, action, %Ash.Page.Offset{results: page, count: Enum.count(page)})
|
paginate(
|
||||||
|
resource,
|
||||||
|
action,
|
||||||
|
%Ash.Page.Offset{results: page, count: Enum.count(page)},
|
||||||
|
relay?
|
||||||
|
)
|
||||||
|
|
||||||
%{keyset?: true} ->
|
%{keyset?: true} ->
|
||||||
paginate(resource, action, %Ash.Page.Keyset{
|
paginate(
|
||||||
results: page,
|
resource,
|
||||||
more?: false,
|
action,
|
||||||
after: nil,
|
%Ash.Page.Keyset{
|
||||||
before: nil
|
results: page,
|
||||||
})
|
more?: false,
|
||||||
|
after: nil,
|
||||||
|
before: nil
|
||||||
|
},
|
||||||
|
relay?
|
||||||
|
)
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
{:ok, page}
|
{:ok, page}
|
||||||
|
|
|
@ -1078,7 +1078,6 @@ defmodule AshGraphql.Resource do
|
||||||
name: "first",
|
name: "first",
|
||||||
identifier: :first,
|
identifier: :first,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
default_value: action.pagination.default_limit,
|
|
||||||
description: "The number of records to return from the beginning." <> max_message,
|
description: "The number of records to return from the beginning." <> max_message,
|
||||||
__reference__: ref(__ENV__)
|
__reference__: ref(__ENV__)
|
||||||
},
|
},
|
||||||
|
@ -1100,7 +1099,6 @@ defmodule AshGraphql.Resource do
|
||||||
name: "last",
|
name: "last",
|
||||||
identifier: :last,
|
identifier: :last,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
default_value: action.pagination.default_limit,
|
|
||||||
description: "The number of records to return to the end." <> max_message,
|
description: "The number of records to return to the end." <> max_message,
|
||||||
__reference__: ref(__ENV__)
|
__reference__: ref(__ENV__)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,58 @@ defmodule AshGraphql.PaginateTest do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "pagination" do
|
describe "keyset pagination" do
|
||||||
|
setup do
|
||||||
|
letters = ["a", "b", "c", "d", "e"]
|
||||||
|
|
||||||
|
for text <- letters do
|
||||||
|
post =
|
||||||
|
AshGraphql.Test.Post
|
||||||
|
|> Ash.Changeset.for_create(:create, text: text, published: true)
|
||||||
|
|> AshGraphql.Test.Api.create!()
|
||||||
|
|
||||||
|
for text <- letters do
|
||||||
|
AshGraphql.Test.Comment
|
||||||
|
|> Ash.Changeset.for_create(:create, text: text)
|
||||||
|
|> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove)
|
||||||
|
|> AshGraphql.Test.Api.create!()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
test "default_limit records are fetched" do
|
||||||
|
doc = """
|
||||||
|
query KeysetPaginatedPosts {
|
||||||
|
keysetPaginatedPosts(sort: [{field: TEXT}]) {
|
||||||
|
count
|
||||||
|
results{
|
||||||
|
text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
assert {:ok,
|
||||||
|
%{
|
||||||
|
data: %{
|
||||||
|
"keysetPaginatedPosts" => %{
|
||||||
|
"count" => 5,
|
||||||
|
"results" => [
|
||||||
|
%{"text" => "a"},
|
||||||
|
%{"text" => "b"},
|
||||||
|
%{"text" => "c"},
|
||||||
|
%{"text" => "d"},
|
||||||
|
%{"text" => "e"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}} = Absinthe.run(doc, AshGraphql.Test.Schema)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "offset pagination" do
|
||||||
setup do
|
setup do
|
||||||
letters = ["a", "b", "c", "d", "e"]
|
letters = ["a", "b", "c", "d", "e"]
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,7 @@ defmodule AshGraphql.Test.Post do
|
||||||
list :post_library, :library
|
list :post_library, :library
|
||||||
list :post_score, :score
|
list :post_score, :score
|
||||||
list :paginated_posts, :paginated
|
list :paginated_posts, :paginated
|
||||||
|
list :keyset_paginated_posts, :keyset_paginated
|
||||||
list :paginated_posts_without_limit, :paginated_without_limit
|
list :paginated_posts_without_limit, :paginated_without_limit
|
||||||
list :paginated_posts_limit_not_required, :paginated_limit_not_required
|
list :paginated_posts_limit_not_required, :paginated_limit_not_required
|
||||||
end
|
end
|
||||||
|
@ -160,6 +161,10 @@ defmodule AshGraphql.Test.Post do
|
||||||
pagination(required?: true, offset?: true, countable: true, default_limit: 20)
|
pagination(required?: true, offset?: true, countable: true, default_limit: 20)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
read :keyset_paginated do
|
||||||
|
pagination(required?: true, keyset?: true, countable: true, default_limit: 20)
|
||||||
|
end
|
||||||
|
|
||||||
read :paginated_without_limit do
|
read :paginated_without_limit do
|
||||||
pagination(required?: true, offset?: true, countable: true)
|
pagination(required?: true, offset?: true, countable: true)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue