ash/lib/ash.ex

147 lines
4 KiB
Elixir
Raw Normal View History

2019-10-03 16:08:36 +13:00
defmodule Ash do
2019-12-05 20:18:13 +13:00
@moduledoc """
2019-12-06 07:45:02 +13:00
The primary interface for interrogating apis and resources.
2019-12-05 20:18:13 +13:00
This is not the code level interface for a resource. Instead, call functions
2019-12-23 17:28:40 +13:00
on an `Api` module that contains those resources. This is for retrieving
resource/api configurations.
2019-12-05 20:18:13 +13:00
"""
2019-10-07 09:36:06 +13:00
alias Ash.Resource.Relationships.{BelongsTo, HasOne, HasMany, ManyToMany}
2019-12-05 20:18:13 +13:00
alias Ash.Resource.Actions.{Create, Read, Update, Destroy}
2020-01-14 07:16:24 +13:00
2019-12-24 20:53:56 +13:00
@type authorization :: Keyword.t()
2019-10-07 09:36:06 +13:00
@type record :: struct
@type cardinality_one_relationship() :: HasOne.t() | BelongsTo.t()
@type cardinality_many_relationship() :: HasMany.t() | ManyToMany.t()
@type relationship :: cardinality_one_relationship() | cardinality_many_relationship()
@type resource :: module
2019-12-05 20:18:13 +13:00
@type data_layer :: module
@type data_layer_query :: struct
2019-12-03 05:25:00 +13:00
@type api :: module
2019-10-07 09:36:06 +13:00
@type error :: struct
2019-11-29 19:54:11 +13:00
@type filter :: map()
2019-12-23 17:28:40 +13:00
@type params :: Keyword.t()
@type create_params :: Keyword.t()
@type update_params :: Keyword.t()
@type delete_params :: Keyword.t()
2019-11-30 05:36:01 +13:00
@type sort :: Keyword.t()
2019-11-28 10:36:25 +13:00
@type side_loads :: Keyword.t()
2019-12-05 20:18:13 +13:00
@type attribute :: Ash.Attributes.Attribute.t()
@type action :: Create.t() | Read.t() | Update.t() | Destroy.t()
@type query :: Ash.Query.t()
2019-10-07 09:36:06 +13:00
def ash_error?(value) do
!!Ash.Error.impl_for(value)
end
def to_ash_error(values) when is_list(values) do
values =
Enum.map(values, fn value ->
if ash_error?(value) do
value
else
Ash.Error.Unknown.exception(error: values)
end
end)
Ash.Error.choose_error(values)
end
def to_ash_error(value) do
to_ash_error([value])
end
2020-05-02 21:01:57 +12:00
def describe(resource) do
resource.describe()
end
2020-01-14 07:16:24 +13:00
@spec resource_module?(module) :: boolean
def resource_module?(module) do
:attributes
|> module.module_info()
|> Keyword.get(:behaviour, [])
|> Enum.any?(&(&1 == Ash.Resource))
end
2019-12-09 19:44:07 +13:00
@spec data_layer_can?(resource(), Ash.DataLayer.feature()) :: boolean
def data_layer_can?(resource, feature) do
data_layer = data_layer(resource)
data_layer && data_layer.can?(feature)
end
2019-12-05 20:18:13 +13:00
@spec resources(api) :: list(resource())
2019-12-02 10:58:29 +13:00
def resources(api) do
api.resources()
end
2019-12-07 20:42:14 +13:00
@spec primary_key(resource()) :: list(attribute)
2019-11-03 09:36:46 +13:00
def primary_key(resource) do
resource.primary_key()
end
2019-12-05 20:18:13 +13:00
@spec relationship(resource(), atom() | String.t()) :: relationship() | nil
2019-11-30 05:36:01 +13:00
def relationship(resource, relationship_name) when is_bitstring(relationship_name) do
Enum.find(resource.relationships(), &(to_string(&1.name) == relationship_name))
end
def relationship(resource, relationship_name) do
2019-11-28 10:36:25 +13:00
Enum.find(resource.relationships(), &(&1.name == relationship_name))
end
2019-12-05 20:18:13 +13:00
@spec relationships(resource()) :: list(relationship())
2019-10-04 15:33:55 +13:00
def relationships(resource) do
resource.relationships()
end
2019-12-05 20:18:13 +13:00
@spec primary_action(resource(), atom()) :: action() | nil
2019-11-25 13:01:21 +13:00
def primary_action(resource, type) do
resource
|> actions()
2019-11-28 10:36:25 +13:00
|> Enum.filter(&(&1.type == type))
|> case do
[action] -> action
actions -> Enum.find(actions, & &1.primary?)
end
2019-11-25 13:01:21 +13:00
end
2019-12-05 20:18:13 +13:00
@spec action(resource(), atom(), atom()) :: action() | nil
2019-11-28 10:36:25 +13:00
def action(resource, name, type) do
Enum.find(resource.actions(), &(&1.name == name && &1.type == type))
end
2019-12-05 20:18:13 +13:00
@spec actions(resource()) :: list(action())
def actions(resource) do
resource.actions()
end
2019-12-05 20:18:13 +13:00
@spec attribute(resource(), String.t() | atom) :: attribute() | nil
2019-11-30 05:36:01 +13:00
def attribute(resource, name) when is_bitstring(name) do
Enum.find(resource.attributes, &(to_string(&1.name) == name))
end
2019-11-28 10:36:25 +13:00
def attribute(resource, name) do
Enum.find(resource.attributes, &(&1.name == name))
end
2019-12-05 20:18:13 +13:00
@spec attributes(resource()) :: list(attribute())
def attributes(resource) do
resource.attributes()
end
2019-12-05 20:18:13 +13:00
@spec name(resource()) :: String.t()
def name(resource) do
resource.name()
end
2019-10-03 20:40:37 +13:00
2019-12-05 20:18:13 +13:00
@spec type(resource()) :: String.t()
2019-10-03 20:40:37 +13:00
def type(resource) do
resource.type()
end
2019-10-07 09:36:06 +13:00
2019-12-05 20:18:13 +13:00
@spec data_layer(resource()) :: data_layer()
2019-10-07 09:36:06 +13:00
def data_layer(resource) do
resource.data_layer()
end
2019-10-03 16:08:36 +13:00
end