Skip to content

Commit

Permalink
improvement: make pagination more explicitly configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
zachdaniel committed Mar 13, 2024
1 parent f895d29 commit ae94fcd
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 17 deletions.
8 changes: 8 additions & 0 deletions lib/resource/query.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ defmodule AshGraphql.Resource.Query do
hide_inputs: [],
metadata_names: [],
metadata_types: [],
paginate_with: :keyset,
show_metadata: nil,
type_name: nil,
relay?: false
Expand Down Expand Up @@ -106,6 +107,13 @@ defmodule AshGraphql.Resource.Query do
doc: """
If true, the graphql queries/resolvers for this resource will be built to honor the relay specification. See [the relay guide](/documentation/topics/relay.html) for more.
"""
],
paginate_with: [
type: {:one_of, [:keyset, :offset, nil]},
default: :keyset,
doc: """
Determine the pagination strategy to use, if multiple are available. If `nil`, no pagination is applied, otherwise the given strategy is used.
"""
]
]
|> Spark.OptionsHelpers.merge_schemas(@query_schema, "Shared Query Options")
Expand Down
88 changes: 71 additions & 17 deletions lib/resource/resource.ex
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,15 @@ defmodule AshGraphql.Resource do

%Absinthe.Blueprint.Schema.FieldDefinition{
arguments:
args(query.type, resource, query_action, schema, query.identity, query.hide_inputs),
args(
query.type,
resource,
query_action,
schema,
query.identity,
query.hide_inputs,
query
),
identifier: query.name,
middleware:
action_middleware ++
Expand Down Expand Up @@ -1237,7 +1245,7 @@ defmodule AshGraphql.Resource do
defp query_type(%{type: :list, relay?: relay?} = query, _resource, action, type) do
type = query.type_name || type

if action.pagination do
if pagination_strategy(query, action) do
cond do
relay? ->
String.to_atom("#{type}_connection")
Expand Down Expand Up @@ -1265,6 +1273,43 @@ defmodule AshGraphql.Resource do
maybe_wrap_non_null(type, not query.allow_nil?)
end

defp pagination_strategy(nil, _) do
nil
end

defp pagination_strategy(%{paginate_with: strategy}, action) do
if !action.pagination do
nil
else
strategies =
if !action.pagination.required? do
[nil]
else
[]
end

strategies =
if action.pagination.keyset? do
[:keyset | strategies]
else
strategies
end

strategies =
if action.pagination.offset? do
[:offset | strategies]
else
strategies
end

if strategy in strategies do
strategy
else
Enum.at(strategies, 0)
end
end
end

defp maybe_wrap_non_null({:non_null, type}, true) do
%Absinthe.Blueprint.TypeReference.NonNull{
of_type: type
Expand Down Expand Up @@ -1342,14 +1387,22 @@ defmodule AshGraphql.Resource do
end)
end

defp args(action_type, resource, action, schema, identity \\ nil, hide_inputs \\ [])
defp args(
action_type,
resource,
action,
schema,
identity \\ nil,
hide_inputs \\ [],
query \\ nil
)

defp args(:get, resource, action, schema, nil, hide_inputs) do
defp args(:get, resource, action, schema, nil, hide_inputs, _query) do
get_fields(resource) ++
read_args(resource, action, schema, hide_inputs)
end

defp args(:get, resource, action, schema, identity, hide_inputs) do
defp args(:get, resource, action, schema, identity, hide_inputs, _query) do
if identity do
resource
|> Ash.Resource.Info.identities()
Expand All @@ -1374,7 +1427,7 @@ defmodule AshGraphql.Resource do
|> Enum.concat(read_args(resource, action, schema, hide_inputs))
end

defp args(:read_one, resource, action, schema, _, hide_inputs) do
defp args(:read_one, resource, action, schema, _, hide_inputs, _query) do
args =
if AshGraphql.Resource.Info.derive_filter?(resource) do
case resource_filter_fields(resource, schema) do
Expand All @@ -1399,7 +1452,7 @@ defmodule AshGraphql.Resource do
args ++ read_args(resource, action, schema, hide_inputs)
end

defp args(:list, resource, action, schema, _, hide_inputs) do
defp args(:list, resource, action, schema, _, hide_inputs, query) do
args =
if AshGraphql.Resource.Info.derive_filter?(resource) do
case resource_filter_fields(resource, schema) do
Expand Down Expand Up @@ -1445,10 +1498,10 @@ defmodule AshGraphql.Resource do
args
end

args ++ pagination_args(action) ++ read_args(resource, action, schema, hide_inputs)
args ++ pagination_args(query, action) ++ read_args(resource, action, schema, hide_inputs)
end

defp args(:list_related, resource, action, schema, identity, hide_inputs) do
defp args(:list_related, resource, action, schema, identity, hide_inputs, _) do
args(:list, resource, action, schema, identity, hide_inputs) ++
[
%Absinthe.Blueprint.Schema.InputValueDefinition{
Expand All @@ -1468,7 +1521,7 @@ defmodule AshGraphql.Resource do
]
end

defp args(:one_related, resource, action, schema, _identity, hide_inputs) do
defp args(:one_related, resource, action, schema, _identity, hide_inputs, _) do
read_args(resource, action, schema, hide_inputs)
end

Expand All @@ -1492,15 +1545,16 @@ defmodule AshGraphql.Resource do
end)
end

defp pagination_args(action) do
if action.pagination do
if action.pagination.keyset? do
defp pagination_args(query, action) do
case pagination_strategy(query, action) do
nil ->
[]

:keyset ->
keyset_pagination_args(action)
else

:offset ->
offset_pagination_args(action)
end
else
[]
end
end

Expand Down

0 comments on commit ae94fcd

Please sign in to comment.