-
-
Notifications
You must be signed in to change notification settings - Fork 181
/
interface.ex
136 lines (121 loc) · 3.8 KB
/
interface.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
defmodule Ash.Resource.Interface do
@moduledoc """
Represents a function in a resource's code interface
"""
defstruct [:name, :action, :args, :get?, :get_by, :get_by_identity]
@type t :: %__MODULE__{}
defmacro __using__(_) do
quote bind_quoted: [], generated: true do
if Ash.Resource.Info.define_interface_in_resource?(__MODULE__) do
require Ash.CodeInterface
Ash.CodeInterface.define_interface(
Ash.Resource.Info.define_interface_for(__MODULE__),
__MODULE__
)
end
end
end
def transform(definition) do
if definition.get_by || definition.get_by_identity do
{:ok, %{definition | get?: true}}
else
{:ok, definition}
end
end
def interface_options(action_type) do
[
tenant: [
type: :any,
doc: "set the tenant of the query/changeset"
],
context: [
type: :any,
doc: "set context on the query/changeset"
],
actor: [
type: :any,
doc: "set the actor for authorization"
],
authorize?: [
type: :boolean,
doc: """
whether or not to perform authorization.
If an actor option is provided (even if it is `nil`), defaults to `true`. If not, defaults to `false`.
"""
],
verbose?: [
type: :boolean,
doc: "a flag to toggle verbose output from the internal Ash engine (for debugging)"
],
timeout: [
type: :timeout,
doc: "A timeout to apply to the operation. See the timeouts guide for more."
]
] ++ action_type_opts(action_type)
end
defp action_type_opts(:create) do
[
changeset: [
type: :any,
doc: "A changeset to seed the action with."
]
]
end
defp action_type_opts(:read) do
[
query: [
type: :any,
doc: "A query to seed the action with."
],
load: [
type: :any,
doc: "Adds a load statement to the query before passing it to the action."
]
]
end
defp action_type_opts(_), do: []
@schema [
name: [
type: :atom,
doc: "The name of the function that will be defined",
required: true
],
action: [
type: :atom,
doc:
"The name of the action that will be called. Defaults to the same name as the function."
],
args: [
type: {:list, {:or, [:atom, {:tagged_tuple, :optional, :atom}]}},
doc: """
Map specific arguments to named inputs. Can provide any argument/attributes that the action allows.
"""
],
get?: [
type: :boolean,
doc: """
Only relevant for read actions. Expects to only receive a single result from a read action.
The action should return a single result based on any arguments provided. To make it so that the function
takes a specific field, and filters on that field, use `get_by` instead.
Useful for creating functions like `get_user_by_email` that map to an action that has an `:email` argument.
"""
],
get_by: [
type: {:list, :atom},
doc: """
Only relevant for read actions. Takes a list of fields and adds those fields as arguments, which will then be used to filter.
Automatically sets `get?` to `true`.
The action should return a single result based on any arguments provided. To make it so that the function
takes a specific field, and filters on that field, use `get_by` instead. When combined, `get_by` takes precedence.
Useful for creating functions like `get_user_by_id` that map to a basic read action.
"""
],
get_by_identity: [
type: :atom,
doc: """
Only relevant for read actions. Takes an identity, and gets its field list, performing the same logic as `get_by` once it has the list of fields.
"""
]
]
def schema, do: @schema
end