fix: restore support for custom paginators (#6)

This commit is contained in:
Peter Hartman 2023-10-26 03:08:42 +01:00 committed by GitHub
parent 2c8fe82ff1
commit 4ecdcea91e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 139 additions and 40 deletions

View file

@ -330,7 +330,7 @@ defmodule AshJsonApiWrapper.DataLayer do
end
@impl true
def set_context(_resource, query, context) do
def set_context(resource, query, context) do
params = context[:data_layer][:query_params] || %{}
headers = Map.to_list(context[:data_layer][:headers] || %{})
@ -343,6 +343,7 @@ defmodule AshJsonApiWrapper.DataLayer do
headers: headers,
api: query.api,
action: action,
endpoint: AshJsonApiWrapper.DataLayer.Info.endpoint(resource, action.name),
context: context
}}
end
@ -668,7 +669,7 @@ defmodule AshJsonApiWrapper.DataLayer do
end
defp do_sort({:ok, results}, %{sort: sort}) when sort not in [nil, []] do
Ash.Sort.runtime_sort(results, sort)
Ash.Sort.runtime_sort(results, sort, [])
end
defp do_sort(other, _), do: other

View file

@ -0,0 +1,111 @@
defmodule AshJsonApiWrapper.CustomPagination.Test do
use ExUnit.Case
require Ash.Query
@moduletag :custom_pagination
# ── Custom paginator ──
defmodule CustomPaginator do
use AshJsonApiWrapper.Paginator
def cursor do
case :ets.whereis(:cursor) do
:undefined ->
:ets.new(:cursor, [:set, :protected, :named_table])
|> :ets.insert({self(), 1})
1
_ ->
[{_, value} | _rest] = :ets.lookup(:cursor, self())
value
end
end
def increment_cursor do
:ets.insert(:cursor, {self(), cursor() + 1})
end
def reset_cursor do
:ets.insert(:cursor, {self(), 1})
end
def continue(_response, [], _) do
reset_cursor()
:halt
end
def continue(_response, _entities, _opts) do
increment_cursor()
{:ok, %{params: %{:p => cursor()}}}
end
end
# ── Resource ──
defmodule Users do
use Ash.Resource,
data_layer: AshJsonApiWrapper.DataLayer,
validate_api_inclusion?: false
json_api_wrapper do
tesla(Tesla)
endpoints do
base("https://65383945a543859d1bb1528e.mockapi.io/api/v1")
endpoint :list_users do
path("/users")
limit_with {:param, "l"}
runtime_sort? true
paginator CustomPaginator
end
end
end
actions do
read(:list_users) do
primary?(true)
pagination do
offset?(true)
required?(true)
default_limit(50)
end
end
end
attributes do
attribute :id, :integer do
primary_key?(true)
allow_nil?(false)
end
attribute(:name, :string)
end
end
defmodule Api do
use Ash.Api, validate_config_inclusion?: false
resources do
allow_unregistered?(true)
end
end
# ── Test it! ──
test "it works" do
Application.put_env(:ash, :validate_api_resource_inclusion?, false)
Application.put_env(:ash, :validate_api_config_inclusion?, false)
users =
Users
|> Ash.Query.for_read(:list_users)
|> Api.read!(page: [limit: 99])
user_count = users.results |> Enum.count()
assert(user_count == 99)
end
end

View file

@ -6,14 +6,15 @@ defmodule AshJsonApiWrapper.Hackernews.Test do
defmodule TopStory do
@moduledoc false
use Ash.Resource,
data_layer: AshJsonApiWrapper.DataLayer
data_layer: AshJsonApiWrapper.DataLayer,
validate_api_inclusion?: false
json_api_wrapper do
endpoints do
base "https://hacker-news.firebaseio.com/v0/"
endpoint :read do
limit_with "limitToFirst"
limit_with {:param, "limitToFirst"}
path "topstories.json"
end
end
@ -59,7 +60,8 @@ defmodule AshJsonApiWrapper.Hackernews.Test do
defmodule Story do
@moduledoc false
use Ash.Resource,
data_layer: AshJsonApiWrapper.DataLayer
data_layer: AshJsonApiWrapper.DataLayer,
validate_api_inclusion?: false
calculations do
calculate(:short_url, :string, ShortUrl)
@ -110,7 +112,8 @@ defmodule AshJsonApiWrapper.Hackernews.Test do
defmodule User do
@moduledoc false
use Ash.Resource,
data_layer: AshJsonApiWrapper.DataLayer
data_layer: AshJsonApiWrapper.DataLayer,
validate_api_inclusion?: false
attributes do
attribute :id, :string do
@ -142,7 +145,7 @@ defmodule AshJsonApiWrapper.Hackernews.Test do
defmodule Api do
@moduledoc false
use Ash.Api
use Ash.Api, validate_config_inclusion?: false
resources do
allow_unregistered?(true)

View file

@ -1,7 +1,7 @@
defmodule AshJsonApiWrapper.OpenApi.CybridTest do
use ExUnit.Case
require Ash.Query
@moduletag :oapi_cybrid
@json "test/support/cybrid.json" |> File.read!() |> Jason.decode!()
@ -38,14 +38,6 @@ defmodule AshJsonApiWrapper.OpenApi.CybridTest do
]
]
defmodule Api do
use Ash.Api
resources do
allow_unregistered? true
end
end
test "it does stuff" do
@json
|> AshJsonApiWrapper.OpenApi.ResourceGenerator.generate(@config)

View file

@ -1,7 +1,7 @@
defmodule AshJsonApiWrapper.OpenApi.PetstoreTest do
use ExUnit.Case
require Ash.Query
@moduletag :oapi_petstore
@json "test/support/pet_store.json" |> File.read!() |> Jason.decode!()
@ -17,7 +17,7 @@ defmodule AshJsonApiWrapper.OpenApi.PetstoreTest do
tesla: TestingTesla,
endpoint: "https://petstore3.swagger.io/api/v3",
resources: [
"Petstore.Order": [
Petstore: [
path: "/store/order/{orderId}",
object_type: "components.schemas.Order",
primary_key: "id",
@ -31,14 +31,6 @@ defmodule AshJsonApiWrapper.OpenApi.PetstoreTest do
]
]
defmodule Api do
use Ash.Api
resources do
allow_unregistered? true
end
end
test "it does stuff" do
@json
|> AshJsonApiWrapper.OpenApi.ResourceGenerator.generate(@config)

View file

@ -1,7 +1,6 @@
defmodule AshJsonApiWrapper.Petstore.Test do
use ExUnit.Case
require Ash.Query
@moduletag :petstore
defmodule TestingTesla do
@ -9,8 +8,10 @@ defmodule AshJsonApiWrapper.Petstore.Test do
# plug Tesla.Middleware.Logger
end
defmodule Petstore.Order do
use Ash.Resource, data_layer: AshJsonApiWrapper.DataLayer
defmodule Petstore do
use Ash.Resource,
data_layer: AshJsonApiWrapper.DataLayer,
validate_api_inclusion?: false
json_api_wrapper do
tesla(TestingTesla)
@ -18,7 +19,7 @@ defmodule AshJsonApiWrapper.Petstore.Test do
endpoints do
base("https://petstore3.swagger.io/api/v3")
endpoint [:find_pets_by_status, :fpbs] do
endpoint [:find_pets_by_status, :by_status] do
path("/pet/findByStatus")
field :status do
@ -37,11 +38,11 @@ defmodule AshJsonApiWrapper.Petstore.Test do
actions do
read(:find_pets_by_status) do
primary? true
primary? false
end
read(:fpbs) do
primary? false
read(:by_status) do
primary? true
end
read(:pet) do
@ -68,8 +69,7 @@ defmodule AshJsonApiWrapper.Petstore.Test do
end
defmodule Api do
@moduledoc false
use Ash.Api
use Ash.Api, validate_config_inclusion?: false
resources do
allow_unregistered?(true)
@ -77,19 +77,19 @@ defmodule AshJsonApiWrapper.Petstore.Test do
end
test "it works" do
Petstore.Order
Petstore
|> Ash.Query.for_read(:find_pets_by_status)
|> Ash.Query.filter(status == "pending")
|> Api.read!()
Petstore.Order
|> Ash.Query.for_read(:fpbs)
Petstore
|> Ash.Query.for_read(:by_status)
|> Ash.Query.filter(status == "available")
|> Api.read!()
Petstore.Order
Petstore
|> Ash.Query.for_read(:pet)
|> Ash.Query.filter(id == 1)
|> Ash.Query.filter(id == 10)
|> Api.read!()
end
end