improvement: support 3.0

This commit is contained in:
Zach Daniel 2024-05-25 07:07:39 -04:00
parent 19e6de356e
commit c7bce0db6f
10 changed files with 59 additions and 46 deletions

View file

@ -1,10 +1,9 @@
--- ---
name: Proposal name: Proposal
about: Suggest an idea for this project about: Suggest an idea for this project
title: '' title: ""
labels: enhancement, needs review labels: enhancement, needs review
assignees: '' assignees: ""
--- ---
**Is your feature request related to a problem? Please describe.** **Is your feature request related to a problem? Please describe.**
@ -29,7 +28,7 @@ For example
Or Or
```elixir ```elixir
Api.read(:resource, bar: 10) # <- Adding `bar` here would cause <x> Ash.read(..., bar: 10) # <- Adding `bar` here would cause <x>
``` ```
**Additional context** **Additional context**

View file

@ -1,2 +0,0 @@
erlang 26.0.2
elixir 1.15.4-otp-26

View file

@ -133,7 +133,7 @@ defmodule AshJsonApiWrapper.DataLayer do
defmodule Query do defmodule Query do
@moduledoc false @moduledoc false
defstruct [ defstruct [
:api, :domain,
:context, :context,
:headers, :headers,
:action, :action,
@ -206,8 +206,8 @@ defmodule AshJsonApiWrapper.DataLayer do
def can?(_, _), do: false def can?(_, _), do: false
@impl true @impl true
def resource_to_query(resource, api \\ nil) do def resource_to_query(resource, domain \\ nil) do
%Query{path: AshJsonApiWrapper.DataLayer.Info.endpoint_base(resource), api: api} %Query{path: AshJsonApiWrapper.DataLayer.Info.endpoint_base(resource), domain: domain}
end end
@impl true @impl true
@ -341,7 +341,7 @@ defmodule AshJsonApiWrapper.DataLayer do
query query
| query_params: params, | query_params: params,
headers: headers, headers: headers,
api: query.api, domain: query.domain,
action: action, action: action,
endpoint: AshJsonApiWrapper.DataLayer.Info.endpoint(resource, action.name), endpoint: AshJsonApiWrapper.DataLayer.Info.endpoint(resource, action.name),
context: context context: context
@ -667,7 +667,7 @@ defmodule AshJsonApiWrapper.DataLayer do
if is_nil(query.runtime_filter) do if is_nil(query.runtime_filter) do
{:ok, results} {:ok, results}
else else
Ash.Filter.Runtime.filter_matches(query.api, results, query.runtime_filter) Ash.Filter.Runtime.filter_matches(query.domain, results, query.runtime_filter)
end end
end end

View file

@ -1,19 +1,12 @@
defmodule AshJsonApiWrapper.Errors.InvalidData do defmodule AshJsonApiWrapper.Errors.InvalidData do
@moduledoc "Used when an invalid value is present in the response for a given attribute" @moduledoc "Used when an invalid value is present in the response for a given attribute"
use Ash.Error.Exception
def_ash_error([:field, :value], class: :invalid) use Splode.Error, fields: [:field, :value], class: :invalid
defimpl Ash.ErrorKind do def message(error) do
def id(_), do: Ash.UUID.generate() "Invalid value provided#{for_field(error)}: #{inspect(error.value)}"
def code(_), do: "invalid_data"
def message(error) do
"Invalid value provided#{for_field(error)}: #{inspect(error.value)}"
end
defp for_field(%{field: field}) when not is_nil(field), do: " for #{field}"
defp for_field(_), do: ""
end end
defp for_field(%{field: field}) when not is_nil(field), do: " for #{field}"
defp for_field(_), do: ""
end end

View file

@ -2,7 +2,7 @@ defmodule AshJsonApiWrapper.OpenApi.ResourceGenerator do
@moduledoc "Generates resources from an open api specification" @moduledoc "Generates resources from an open api specification"
# sobelow_skip ["DOS.StringToAtom"] # sobelow_skip ["DOS.StringToAtom"]
def generate(json, main_config) do def generate(json, domain, main_config) do
main_config[:resources] main_config[:resources]
|> Enum.map(fn {resource, config} -> |> Enum.map(fn {resource, config} ->
endpoints = endpoints =
@ -158,7 +158,7 @@ defmodule AshJsonApiWrapper.OpenApi.ResourceGenerator do
code = code =
""" """
defmodule #{resource} do defmodule #{resource} do
use Ash.Resource, data_layer: AshJsonApiWrapper.DataLayer use Ash.Resource, domain: #{inspect(domain)}, data_layer: AshJsonApiWrapper.DataLayer
json_api_wrapper do json_api_wrapper do
#{tesla} #{tesla}

View file

@ -72,8 +72,9 @@ defmodule AshJsonApiWrapper.CustomPagination.Test do
defmodule Users do defmodule Users do
use Ash.Resource, use Ash.Resource,
domain: AshJsonApiWrapper.CustomPagination.Test.Domain,
data_layer: AshJsonApiWrapper.DataLayer, data_layer: AshJsonApiWrapper.DataLayer,
validate_api_inclusion?: false validate_domain_inclusion?: false
json_api_wrapper do json_api_wrapper do
tesla(TestingTesla) tesla(TestingTesla)
@ -112,8 +113,8 @@ defmodule AshJsonApiWrapper.CustomPagination.Test do
end end
end end
defmodule Api do defmodule Domain do
use Ash.Api, validate_config_inclusion?: false use Ash.Domain, validate_config_inclusion?: false
resources do resources do
allow_unregistered?(true) allow_unregistered?(true)
@ -160,12 +161,12 @@ defmodule AshJsonApiWrapper.CustomPagination.Test do
Users Users
|> Ash.Query.for_read(:list_users) |> Ash.Query.for_read(:list_users)
# |> Ash.Query.limit(2) # |> Ash.Query.limit(2)
|> Api.read!(page: [limit: 2, offset: 0]) |> Ash.read!(page: [limit: 2, offset: 0])
users2 = users2 =
Users Users
|> Ash.Query.for_read(:list_users) |> Ash.Query.for_read(:list_users)
|> Api.read!(page: [limit: 2, offset: 1]) |> Ash.read!(page: [limit: 2, offset: 1])
users_count = users.results |> Enum.count() users_count = users.results |> Enum.count()
users2_count = users2.results |> Enum.count() users2_count = users2.results |> Enum.count()

View file

@ -6,8 +6,9 @@ defmodule AshJsonApiWrapper.Hackernews.Test do
defmodule TopStory do defmodule TopStory do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshJsonApiWrapper.Hackernews.Test.Domain,
data_layer: AshJsonApiWrapper.DataLayer, data_layer: AshJsonApiWrapper.DataLayer,
validate_api_inclusion?: false validate_domain_inclusion?: false
json_api_wrapper do json_api_wrapper do
endpoints do endpoints do
@ -44,7 +45,7 @@ defmodule AshJsonApiWrapper.Hackernews.Test do
defmodule ShortUrl do defmodule ShortUrl do
@moduledoc false @moduledoc false
use Ash.Calculation use Ash.Resource.Calculation
def calculate(records, _, _) do def calculate(records, _, _) do
Enum.map(records, fn record -> Enum.map(records, fn record ->
@ -60,8 +61,9 @@ defmodule AshJsonApiWrapper.Hackernews.Test do
defmodule Story do defmodule Story do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshJsonApiWrapper.Hackernews.Test.Domain,
data_layer: AshJsonApiWrapper.DataLayer, data_layer: AshJsonApiWrapper.DataLayer,
validate_api_inclusion?: false validate_domain_inclusion?: false
calculations do calculations do
calculate(:short_url, :string, ShortUrl) calculate(:short_url, :string, ShortUrl)
@ -112,8 +114,9 @@ defmodule AshJsonApiWrapper.Hackernews.Test do
defmodule User do defmodule User do
@moduledoc false @moduledoc false
use Ash.Resource, use Ash.Resource,
domain: AshJsonApiWrapper.Hackernews.Test.Domain,
data_layer: AshJsonApiWrapper.DataLayer, data_layer: AshJsonApiWrapper.DataLayer,
validate_api_inclusion?: false validate_domain_inclusion?: false
attributes do attributes do
attribute :id, :string do attribute :id, :string do
@ -143,9 +146,9 @@ defmodule AshJsonApiWrapper.Hackernews.Test do
end end
end end
defmodule Api do defmodule Domain do
@moduledoc false @moduledoc false
use Ash.Api, validate_config_inclusion?: false use Ash.Domain, validate_config_inclusion?: false
resources do resources do
allow_unregistered?(true) allow_unregistered?(true)
@ -157,7 +160,7 @@ defmodule AshJsonApiWrapper.Hackernews.Test do
TopStory TopStory
|> Ash.Query.limit(1) |> Ash.Query.limit(1)
|> Ash.Query.load(story: :user) |> Ash.Query.load(story: :user)
|> Api.read!() |> Domain.read!()
|> Enum.map(& &1.story) |> Enum.map(& &1.story)
assert is_binary(top_story.url) assert is_binary(top_story.url)

View file

@ -38,9 +38,18 @@ defmodule AshJsonApiWrapper.OpenApi.CybridTest do
] ]
] ]
defmodule Domain do
use Ash.Domain,
validate_config_inclusion?: false
resources do
allow_unregistered? true
end
end
test "it does stuff" do test "it does stuff" do
@json @json
|> AshJsonApiWrapper.OpenApi.ResourceGenerator.generate(@config) |> AshJsonApiWrapper.OpenApi.ResourceGenerator.generate(Domain, @config)
|> Enum.map(fn {resource, code} -> |> Enum.map(fn {resource, code} ->
Code.eval_string(code) Code.eval_string(code)
resource resource

View file

@ -31,9 +31,18 @@ defmodule AshJsonApiWrapper.OpenApi.PetstoreTest do
] ]
] ]
defmodule Domain do
use Ash.Domain,
validate_config_inclusion?: false
resources do
allow_unregistered? true
end
end
test "it does stuff" do test "it does stuff" do
@json @json
|> AshJsonApiWrapper.OpenApi.ResourceGenerator.generate(@config) |> AshJsonApiWrapper.OpenApi.ResourceGenerator.generate(Domain, @config)
|> Enum.map(fn {resource, code} -> |> Enum.map(fn {resource, code} ->
Code.eval_string(code) Code.eval_string(code)
resource resource

View file

@ -11,7 +11,8 @@ defmodule AshJsonApiWrapper.Petstore.Test do
defmodule Petstore do defmodule Petstore do
use Ash.Resource, use Ash.Resource,
data_layer: AshJsonApiWrapper.DataLayer, data_layer: AshJsonApiWrapper.DataLayer,
validate_api_inclusion?: false domain: AshJsonApiWrapper.Petstore.Test.Domain,
validate_domain_inclusion?: false
json_api_wrapper do json_api_wrapper do
tesla(TestingTesla) tesla(TestingTesla)
@ -68,8 +69,8 @@ defmodule AshJsonApiWrapper.Petstore.Test do
end end
end end
defmodule Api do defmodule Domain do
use Ash.Api, validate_config_inclusion?: false use Ash.Domain, validate_config_inclusion?: false
resources do resources do
allow_unregistered?(true) allow_unregistered?(true)
@ -80,16 +81,16 @@ defmodule AshJsonApiWrapper.Petstore.Test do
Petstore Petstore
|> Ash.Query.for_read(:find_pets_by_status) |> Ash.Query.for_read(:find_pets_by_status)
|> Ash.Query.filter(status == "pending") |> Ash.Query.filter(status == "pending")
|> Api.read!() |> Ash.read!()
Petstore Petstore
|> Ash.Query.for_read(:by_status) |> Ash.Query.for_read(:by_status)
|> Ash.Query.filter(status == "available") |> Ash.Query.filter(status == "available")
|> Api.read!() |> Ash.read!()
Petstore Petstore
|> Ash.Query.for_read(:pet) |> Ash.Query.for_read(:pet)
|> Ash.Query.filter(id == 10) |> Ash.Query.filter(id == 10)
|> Api.read!() |> Ash.read!()
end end
end end