mirror of
https://github.com/ash-project/ash_json_api_wrapper.git
synced 2024-09-21 05:43:16 +12:00
fix: restore support for custom paginators (#6)
This commit is contained in:
parent
2c8fe82ff1
commit
4ecdcea91e
6 changed files with 139 additions and 40 deletions
|
@ -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
|
||||
|
|
111
test/custom_pagination_test.exs
Normal file
111
test/custom_pagination_test.exs
Normal 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
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue