Packages

ash

1.43.1
3.29.3 3.29.2 3.29.1 3.29.0 3.28.0 3.27.8 3.27.7 3.27.6 3.27.5 3.27.4 3.27.3 3.27.2 3.27.1 3.27.0 3.26.0 3.25.2 3.25.1 3.25.0 retired 3.24.7 3.24.6 3.24.5 3.24.4 3.24.3 3.24.2 3.24.1 3.24.0 3.23.1 3.23.0 3.22.2 3.22.1 3.22.0 3.21.3 3.21.2 3.21.1 3.21.0 3.20.0 3.19.3 3.19.2 3.19.1 3.19.0 3.18.0 3.17.1 3.17.0 3.16.0 3.15.0 3.14.1 3.14.0 retired 3.13.2 3.13.1 3.13.0 3.12.0 3.11.3 3.11.2 3.11.1 3.11.0 3.10.1 3.10.0 3.9.0 3.8.0 3.7.6 3.7.5 3.7.4 3.7.3 3.7.2 3.7.1 3.7.0 retired 3.6.3 retired 3.6.2 3.6.1 3.6.0 3.5.43 3.5.42 3.5.41 3.5.40 3.5.39 3.5.38 3.5.37 3.5.36 3.5.35 3.5.34 3.5.33 3.5.32 3.5.31 3.5.30 3.5.29 3.5.28 3.5.27 3.5.26 3.5.25 3.5.24 3.5.23 3.5.22 3.5.21 3.5.20 3.5.19 3.5.18 3.5.17 3.5.16 3.5.15 3.5.14 3.5.13 3.5.12 3.5.11 3.5.10 3.5.9 3.5.8 3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.74 retired 3.4.73 3.4.72 3.4.71 3.4.70 3.4.69 3.4.68 3.4.67 3.4.66 3.4.65 3.4.64 3.4.63 3.4.62 3.4.61 3.4.60 3.4.59 3.4.58 3.4.57 3.4.56 3.4.55 3.4.54 3.4.53 3.4.52 3.4.51 3.4.50 3.4.49 3.4.48 3.4.47 3.4.46 3.4.45 3.4.44 3.4.43 3.4.42 3.4.41 3.4.40 3.4.39 3.4.38 3.4.37 3.4.36 3.4.35 3.4.34 3.4.33 3.4.32 3.4.31 3.4.30 3.4.29 3.4.28 3.4.27 3.4.26 3.4.25 3.4.24 3.4.23 3.4.22 3.4.21 3.4.20 3.4.19 3.4.18 3.4.17 3.4.16 3.4.15 3.4.14 3.4.13 3.4.12 3.4.11 3.4.10 3.4.9 3.4.8 3.4.7 3.4.6 3.4.5 3.4.4 3.4.3 3.4.2 3.4.1 3.4.0 3.3.3 3.3.2 3.3.1 3.3.0 3.2.6 3.2.5 3.2.4 3.2.3 3.2.2 3.2.1 3.2.0 3.1.8 3.1.7 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.16 3.0.15 3.0.14 3.0.13 3.0.12 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.4 3.0.3 3.0.2 3.0.1 3.0.0 3.0.0-rc.46 3.0.0-rc.45 3.0.0-rc.44 3.0.0-rc.43 3.0.0-rc.42 3.0.0-rc.41 3.0.0-rc.40 3.0.0-rc.39 3.0.0-rc.38 3.0.0-rc.37 3.0.0-rc.36 3.0.0-rc.35 3.0.0-rc.34 3.0.0-rc.33 3.0.0-rc.32 3.0.0-rc.31 3.0.0-rc.29 3.0.0-rc.28 3.0.0-rc.27 3.0.0-rc.26 3.0.0-rc.25 3.0.0-rc.24 3.0.0-rc.23 3.0.0-rc.22 3.0.0-rc.21 3.0.0-rc.20 3.0.0-rc.19 3.0.0-rc.18 3.0.0-rc.17 3.0.0-rc.16 3.0.0-rc.15 3.0.0-rc.14 3.0.0-rc.13 3.0.0-rc.12 3.0.0-rc.11 3.0.0-rc.10 3.0.0-rc.9 3.0.0-rc.8 3.0.0-rc.7 3.0.0-rc.6 3.0.0-rc.5 3.0.0-rc.4 3.0.0-rc.3 3.0.0-rc.1 3.0.0-rc.0 2.21.15 2.21.14 2.21.13 2.21.12 2.21.11 2.21.10 2.21.9 2.21.8 2.21.7 2.21.6 2.21.5 2.21.4 2.21.3 2.21.2 2.21.1 2.21.0 2.20.3 2.20.2 2.20.1 2.20.0 2.19.14 2.19.13 2.19.12 2.19.11 2.19.10 2.19.9 2.19.8 2.19.7 2.19.6 2.19.5 2.19.4 2.19.3 retired 2.19.2 retired 2.19.1 retired 2.19.0 retired 2.18.2 2.18.1 2.18.0 2.17.24 2.17.23 2.17.22 2.17.21 2.17.20 2.17.19 2.17.18 2.17.17 2.17.16 2.17.15 2.17.14 2.17.13 2.17.12 2.17.11 2.17.10 2.17.9 2.17.8 2.17.7 2.17.6 2.17.5 2.17.4 2.17.3 2.17.2 2.17.1 2.17.0 2.16.1 2.16.0 2.15.20 2.15.19 2.15.18 2.15.17 2.15.16 2.15.15 2.15.14 2.15.13 2.15.12 2.15.11 2.15.10 2.15.9 2.15.8 2.15.7 2.15.6 2.15.5 2.15.4 2.15.2 2.15.1 2.15.0 2.14.21 2.14.20 2.14.19 2.14.18 2.14.17 2.14.16 2.14.15 2.14.14 2.14.13 2.14.12 2.14.11 2.14.10 2.14.9 2.14.8 2.14.7 2.14.6 2.14.5 2.14.4 2.14.3 2.14.2 2.14.1 2.14.0 2.13.4 retired 2.13.3 2.13.2 2.13.1 2.13.0 2.12.1 2.12.0 2.11.11 2.11.10 2.11.9 2.11.8 2.11.7 2.11.6 2.11.5 2.11.4 2.11.3 2.11.2 2.11.1 2.11.0 2.11.0-rc.3 2.11.0-rc.2 2.11.0-rc.1 2.11.0-rc.0 2.10.2 2.10.1 2.10.0 2.9.29 2.9.28 2.9.27 2.9.26 2.9.25 2.9.24 2.9.23 2.9.22 2.9.21 2.9.20 2.9.19 2.9.18 2.9.17 2.9.16 2.9.15 2.9.14 2.9.13 2.9.12 2.9.11 2.9.10 2.9.9 2.9.8 2.9.7 2.9.6 2.9.5 2.9.4 2.9.3 2.9.2 2.9.1 2.9.0 2.8.1 2.8.0 2.7.1 2.7.0 2.6.31 2.6.30 2.6.29 2.6.28 2.6.27 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 2.6.4 2.6.3 2.6.2 2.6.1 2.6.0 2.5.16 2.5.15 2.5.14 2.5.13 2.5.12 2.5.11 2.5.10 2.5.9 2.5.8 2.5.7 2.5.6 2.5.5 2.5.4 2.5.3 2.5.2 2.5.1 2.5.0 2.5.0-rc.6 2.5.0-rc.5 2.5.0-rc.4 2.5.0-rc.3 2.5.0-rc.2 2.5.0-rc.1 2.5.0-rc.0 2.4.30 2.4.29 2.4.28 2.4.27 2.4.26 2.4.25 2.4.24 2.4.23 2.4.22 2.4.21 2.4.20 2.4.19 2.4.18 2.4.17 2.4.16 2.4.15 2.4.14 2.4.13 2.4.12 2.4.11 2.4.10 2.4.9 2.4.8 2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4.0 2.3.0 2.2.0 2.1.0 2.0.0 2.0.0-rc.15 2.0.0-rc.14 2.0.0-rc.13 2.0.0-rc.12 2.0.0-rc.11 2.0.0-rc.10 2.0.0-rc.9 2.0.0-rc.8 2.0.0-rc.7 2.0.0-rc.6 2.0.0-rc.5 2.0.0-rc.4 2.0.0-rc.3 2.0.0-rc.2 2.0.0-rc.1 2.0.0-rc.0 2.0.0-pre.8 2.0.0-pre.7 2.0.0-pre.6 2.0.0-pre.5 2.0.0-pre.4 2.0.0-pre.3 2.0.0-pre.2 2.0.0-pre.1 2.0.0-pre.0 1.53.3 1.53.2 1.53.0 1.52.0-rc.22 1.52.0-rc.21 1.52.0-rc.20 1.52.0-rc.19 1.52.0-rc.18 1.52.0-rc.17 1.52.0-rc.16 1.52.0-rc.15 1.52.0-rc.14 1.52.0-rc.13 1.52.0-rc.12 1.52.0-rc.11 1.52.0-rc.10 1.52.0-rc.9 1.52.0-rc.8 1.52.0-rc.7 1.52.0-rc.6 1.52.0-rc.5 1.52.0-rc.4 1.52.0-rc.3 1.52.0-rc.2 1.52.0-rc.1 1.52.0-rc.0 1.51.2 1.51.1 retired 1.51.0 1.50.21 1.50.20 1.50.19 1.50.18 1.50.17 1.50.16 1.50.15 1.50.14 1.50.13 1.50.12 1.50.11 1.50.10 1.50.9 1.50.8 1.50.7 1.50.6 1.50.5 1.50.4 1.50.3 1.50.2 1.50.1 1.50.0 1.49.0 1.48.0-rc.30 1.48.0-rc.29 1.48.0-rc.28 1.48.0-rc.27 1.48.0-rc.26 1.48.0-rc.25 1.48.0-rc.24 1.48.0-rc.23 1.48.0-rc.22 1.48.0-rc.21 1.48.0-rc.20 1.48.0-rc.19 1.48.0-rc.18 1.48.0-rc.17 1.48.0-rc.16 1.48.0-rc.15 1.48.0-rc.14 1.48.0-rc.13 1.48.0-rc.12 1.48.0-rc.11 1.48.0-rc.10 1.48.0-rc.9 1.48.0-rc.8 1.48.0-rc.7 1.48.0-rc.6 1.48.0-rc.5 1.48.0-rc.4 1.48.0-rc.3 1.48.0-rc.2 1.48.0-rc.1 1.48.0-rc.0 1.47.12 1.47.11 1.47.10 1.47.9 1.47.8 1.47.7 1.47.6 1.47.5 1.47.4 1.47.3 1.47.2 1.47.1 1.47.0 1.46.13 1.46.12 1.46.11 1.46.10 1.46.9 1.46.8 1.46.7 1.46.6 1.46.5 1.46.4 1.46.3 1.46.2 1.46.1 1.46.0 1.45.0-rc9 1.45.0-rc8 1.45.0-rc7 1.45.0-rc6 1.45.0-rc5 1.45.0-rc4 1.45.0-rc3 1.45.0-rc20 1.45.0-rc2 1.45.0-rc19 1.45.0-rc18 1.45.0-rc17 1.45.0-rc16 1.45.0-rc15 1.45.0-rc14 1.45.0-rc13 1.45.0-rc12 1.45.0-rc11 1.45.0-rc10 1.45.0-rc1 1.45.0-rc0 1.44.13 1.44.12 1.44.11 1.44.10 1.44.9 1.44.8 1.44.7 1.44.6 1.44.5 1.44.4 1.44.3 1.44.2 1.44.1 1.44.0 1.43.12 1.43.11 1.43.10 1.43.9 1.43.8 1.43.7 1.43.6 1.43.5 1.43.4 1.43.3 1.43.2 1.43.1 1.43.0 1.42.0 1.41.12 1.41.11 1.41.10 1.41.9 1.41.8 1.41.7 1.41.6 1.41.5 1.41.4 1.41.3 1.41.2 1.41.1 1.41.0 1.40.0 1.39.7 1.39.6 1.39.5 1.39.4 1.39.3 1.39.2 1.39.1 1.39.0 1.38.0 1.37.2 1.37.1 1.37.0 1.36.22 1.36.21 1.36.19 1.36.18 1.36.17 1.36.16 1.36.15 1.36.14 1.36.13 1.36.12 1.36.11 1.36.10 1.36.9 1.36.8 1.36.7 1.36.6 1.36.5 1.36.4 1.36.3 1.36.2 1.36.0 1.35.1 1.35.0 1.34.9 1.34.8 1.34.7 1.34.6 1.34.5 1.34.4 1.34.3 1.34.2 1.34.1 1.34.0 1.33.0 1.32.2 1.32.1 1.32.0 1.31.1 1.31.0 1.30.2 1.30.1 1.29.0-rc1 1.29.0-rc0 1.28.1 1.28.0 1.27.1 1.27.0 1.26.13 1.26.12 1.26.11 1.26.10 1.26.9 1.26.8 1.26.7 1.26.6 1.26.5 1.26.4 1.26.2 1.26.1 1.26.0 1.25.8 1.25.7 1.25.6 1.25.5 1.25.4 1.25.3 1.25.2 1.25.1 1.25.0 1.24.2 1.24.1 1.24.0 1.23.3 1.23.2 1.23.1 1.23.0 1.22.1 1.22.0 1.20.1 1.20.0 1.19.1 1.19.0 1.18.1 1.18.0 1.17.1 1.17.0 1.16.2 1.15.1 1.15.0 1.14.0 1.13.4 1.13.3 1.13.2 1.13.1 1.13.0 1.12.0 1.11.1 1.11.0 1.10.0 1.9.0 1.8.0 1.7.0 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.1 1.5.0 1.4.1 1.4.0 1.3.1 1.3.0 1.2.1 1.2.0 1.1.3 1.1.2 1.1.0 1.0.3 1.0.2 1.0.1 1.0.0 0.13.1 0.13.0 0.12.0 0.10.0 0.9.1 0.9.0 0.8.0 0.7.0 0.6.5 0.6.4 0.6.3 0.6.2 0.6.1 0.6.0 0.5.2 0.5.1 0.5.0 0.4.0 0.3.0 0.2.0 0.1.9 0.1.8 0.1.3 0.1.1 0.1.0

A declarative, extensible framework for building Elixir applications.

Security advisory: This version has known vulnerabilities. View advisories

Current section

Files

Jump to
ash lib ash api interface.ex
Raw

lib/ash/api/interface.ex

defmodule Ash.Api.Interface do
@moduledoc false
defmacro define_interface(api, resource) do
quote bind_quoted: [api: api, resource: resource], generated: true do
for interface <- Ash.Resource.Info.interfaces(resource) do
action = Ash.Resource.Info.action(resource, interface.action || interface.name)
unless action do
raise Ash.Error.Dsl.DslError,
module: resource,
message:
"The interface of #{inspect(resource)} refers to a non-existent action #{
interface.action || interface.name
}",
path: [:interfaces, :interface, interface.name]
end
args = interface.args || []
arg_vars = Enum.map(args, &{&1, [], Elixir})
doc = """
#{
action.description ||
"Calls the #{action.name} action on the #{inspect(resource)} resource."
}
## Options
#{Ash.OptionsHelpers.docs(Ash.Resource.Interface.interface_options())}
"""
case action.type do
:read ->
@doc doc
def unquote(interface.name)(
unquote_splicing(arg_vars),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [%{}, params_or_opts])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
query =
opts[:query]
|> Kernel.||(unquote(resource))
|> Ash.Query.for_read(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant])
)
if unquote(interface.get?) do
query
|> unquote(api).read_one(Keyword.drop(opts, [:query, :tenant]))
|> case do
{:ok, nil} ->
{:error, Ash.Error.Query.NotFound.exception(resource: query.resource)}
{:ok, result} ->
{:ok, result}
end
else
unquote(api).read(query, Keyword.drop(opts, [:query, :tenant]))
end
end
end
@doc doc
# sobelow_skip ["DOS.BinToAtom"]
def unquote(:"#{interface.name}!")(
unquote_splicing(arg_vars),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [%{}, params_or_opts])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
query =
opts[:query]
|> Kernel.||(unquote(resource))
|> Ash.Query.for_read(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant])
)
if unquote(interface.get?) do
query
|> unquote(api).read_one!(Keyword.drop(opts, [:query, :tenant]))
|> case do
nil ->
raise Ash.Error.Query.NotFound, resource: query.resource
result ->
result
end
else
unquote(api).read!(query, Keyword.drop(opts, [:query, :tenant]))
end
end
end
:create ->
@doc doc
def unquote(interface.name)(
unquote_splicing(arg_vars),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [%{}, params_or_opts])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
changeset =
unquote(resource)
|> Ash.Changeset.for_create(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant])
)
unquote(api).create(changeset, opts)
end
end
@doc doc
# sobelow_skip ["DOS.BinToAtom"]
def unquote(:"#{interface.name}!")(
unquote_splicing(arg_vars),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [%{}, params_or_opts])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
changeset =
unquote(resource)
|> Ash.Changeset.for_create(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant])
)
unquote(api).create!(changeset, Keyword.drop(opts, [:actor, :tenant]))
end
end
:update ->
@doc doc
def unquote(interface.name)(
record,
unquote_splicing(arg_vars),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [%{}, params_or_opts])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
changeset =
record
|> Ash.Changeset.for_update(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant])
)
unquote(api).update(changeset, Keyword.drop(opts, [:actor, :tenant]))
end
end
@doc doc
# sobelow_skip ["DOS.BinToAtom"]
def unquote(:"#{interface.name}!")(
record,
unquote_splicing(arg_vars),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [%{}, params_or_opts])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
changeset =
record
|> Ash.Changeset.for_update(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant])
)
unquote(api).update!(changeset, Keyword.drop(opts, [:actor, :tenant]))
end
end
:destroy ->
@doc doc
def unquote(interface.name)(
record,
unquote_splicing(arg_vars),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [%{}, params_or_opts])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
changeset =
record
|> Ash.Changeset.for_destroy(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant])
)
unquote(api).destroy(changeset, Keyword.drop(opts, [:actor, :tenant]))
end
end
@doc doc
# sobelow_skip ["DOS.BinToAtom"]
def unquote(:"#{interface.name}!")(
record,
unquote_splicing(arg_vars),
params_or_opts \\ %{},
opts \\ []
) do
if opts == [] && Keyword.keyword?(params_or_opts) do
apply(__MODULE__, elem(__ENV__.function, 0), [%{}, params_or_opts])
else
input =
unquote(args)
|> Enum.zip([unquote_splicing(arg_vars)])
|> Enum.reduce(params_or_opts, fn {key, value}, params_or_opts ->
Map.put(params_or_opts, key, value)
end)
changeset =
record
|> Ash.Changeset.for_destroy(
unquote(action.name),
input,
Keyword.take(opts, [:actor, :tenant])
)
unquote(api).destroy!(changeset, Keyword.drop(opts, [:actor, :tenant]))
end
end
end
end
end
end
defmacro __using__(_) do
quote bind_quoted: [], generated: true do
alias Ash.Api
for resource <- Ash.Api.resources(__MODULE__) do
Ash.Api.Interface.define_interface(__MODULE__, resource)
end
# @spec get!(Ash.Resource.t(), term, Keyword.t()) :: Ash.Resource.record() | no_return
def get!(resource, id_or_filter, params \\ []) do
Ash.Api.Interface.enforce_resource!(resource)
Api.get!(__MODULE__, resource, id_or_filter, params)
end
# @spec get(Ash.Resource.t(), term, Keyword.t()) ::
# {:ok, Ash.Resource.record() | nil} | {:error, Ash.Error.t()}
def get(resource, id_or_filter, params \\ []) do
Ash.Api.Interface.enforce_resource!(resource)
Ash.Api.Interface.enforce_keyword_list!(params)
case Api.get(__MODULE__, resource, id_or_filter, params) do
{:ok, instance} -> {:ok, instance}
{:error, error} -> {:error, Ash.Error.to_ash_error(error)}
end
end
# @spec read!(Ash.Query.t() | Ash.Resource.t(), Keyword.t()) ::
def read!(query, opts \\ [])
def read!(query, opts) do
Ash.Api.Interface.enforce_query_or_resource!(query)
Ash.Api.Interface.enforce_keyword_list!(opts)
Api.read!(__MODULE__, query, opts)
end
def read(query, opts \\ [])
def read(query, opts) do
Ash.Api.Interface.enforce_query_or_resource!(query)
Ash.Api.Interface.enforce_keyword_list!(opts)
case Api.read(__MODULE__, query, opts) do
{:ok, results, query} -> {:ok, results, query}
{:ok, results} -> {:ok, results}
{:error, error} -> {:error, Ash.Error.to_ash_error(error)}
end
end
# @spec read_one!(Ash.Query.t() | Ash.Resource.t(), Keyword.t()) ::
# {:ok, Ash.Resource.record() | nil} | {:error, Ash.Error.t()} | no_return
def read_one!(query, opts \\ [])
def read_one!(query, opts) do
Ash.Api.Interface.enforce_query_or_resource!(query)
Ash.Api.Interface.enforce_keyword_list!(opts)
Api.read_one!(__MODULE__, query, opts)
end
def read_one(query, opts \\ [])
def read_one(query, opts) do
Ash.Api.Interface.enforce_query_or_resource!(query)
Ash.Api.Interface.enforce_keyword_list!(opts)
case Api.read_one(__MODULE__, query, opts) do
{:ok, result} -> {:ok, result}
{:ok, result, query} -> {:ok, result, query}
{:error, error} -> {:error, Ash.Error.to_ash_error(error)}
end
end
def page!(page, request) do
Api.page!(__MODULE__, page, request)
end
def page(page, request) do
case Api.page(__MODULE__, page, request) do
{:ok, page} -> {:ok, page}
{:error, error} -> {:error, Ash.Error.to_ash_error(error)}
end
end
def load!(data, query, opts \\ []) do
Api.load!(__MODULE__, data, query, opts)
end
def load(data, query, opts \\ []) do
case Api.load(__MODULE__, data, query, opts) do
{:ok, results} -> {:ok, results}
{:error, error} -> {:error, Ash.Error.to_ash_error(error)}
end
end
def create!(changeset, params \\ []) do
Api.create!(__MODULE__, changeset, params)
end
def create(changeset, params \\ []) do
case Api.create(__MODULE__, changeset, params) do
{:ok, instance} -> {:ok, instance}
{:ok, instance, notifications} -> {:ok, instance, notifications}
{:error, error} -> {:error, Ash.Error.to_ash_error(error)}
end
end
def update!(changeset, params \\ []) do
Api.update!(__MODULE__, changeset, params)
end
def update(changeset, params \\ []) do
case Api.update(__MODULE__, changeset, params) do
{:ok, instance} -> {:ok, instance}
{:ok, instance, notifications} -> {:ok, instance, notifications}
{:error, error} -> {:error, Ash.Error.to_ash_error(error)}
end
end
def destroy!(record, params \\ []) do
Api.destroy!(__MODULE__, record, params)
end
def destroy(record, params \\ []) do
case Api.destroy(__MODULE__, record, params) do
:ok -> :ok
{:ok, notifications} -> {:ok, notifications}
{:error, error} -> {:error, Ash.Error.to_ash_error(error)}
end
end
def reload!(%resource{} = record, params \\ []) do
id = record |> Map.take(Ash.Resource.Info.primary_key(resource)) |> Enum.to_list()
params = Keyword.put_new(params, :tenant, Map.get(record.__metadata__, :tenant))
get!(resource, id, params)
end
def reload(%resource{} = record, params \\ []) do
id = record |> Map.take(Ash.Resource.Info.primary_key(resource)) |> Enum.to_list()
params = Keyword.put_new(params, :tenant, Map.get(record.__metadata__, :tenant))
get(resource, id, params)
end
end
end
@doc false
def set_tenant(query_or_changeset, opts) do
case Keyword.fetch(opts, :tenant) do
{:ok, tenant} ->
case query_or_changeset do
%Ash.Query{} = query ->
Ash.Query.set_tenant(query, tenant)
%Ash.Changeset{} = changeset ->
Ash.Changeset.set_tenant(changeset, tenant)
other ->
other
end
:error ->
query_or_changeset
end
end
@doc false
def action_interface(api) do
api
|> Ash.Api.resource_references()
|> Enum.flat_map(fn %{resource: resource} = reference ->
resource_name = name(reference)
resource
|> Ash.Resource.Info.actions()
|> Enum.map(fn action ->
{resource, resource_name, action}
end)
end)
end
@doc false
def getters(api) do
api
|> Ash.Api.resource_references()
|> Enum.flat_map(fn %{resource: resource} = reference ->
if Ash.Resource.Info.primary_action(resource, :read) do
resource_name = name(reference)
resource
|> Ash.Resource.Info.identities()
|> Enum.map(fn identity ->
{resource, resource_name, identity}
end)
else
[]
end
end)
end
@doc false
def resources_with_names(api) do
api
|> Ash.Api.resource_references()
|> Enum.map(fn ref ->
{ref.resource, name(ref)}
end)
end
@doc false
def name(reference) do
reference
|> Map.get(:as)
|> Kernel.||(
reference.resource
|> Module.split()
|> List.last()
|> to_string()
|> Macro.underscore()
)
|> to_string()
end
defmacro enforce_query_or_resource!(query_or_resource) do
quote do
case Ash.Api.Interface.do_enforce_query_or_resource!(unquote(query_or_resource)) do
:ok ->
:ok
_ ->
{fun, arity} = __ENV__.function
mfa = "#{inspect(__ENV__.module)}.#{fun}/#{arity}"
raise "#{mfa} expected an %Ash.Query{} or an Ash Resource but instead got #{
inspect(unquote(query_or_resource))
}"
end
end
end
def do_enforce_query_or_resource!(query_or_resource)
def do_enforce_query_or_resource!(%Ash.Query{}), do: :ok
def do_enforce_query_or_resource!(resource) when is_atom(resource) do
if Ash.Resource.Info.resource?(resource), do: :ok, else: :error
end
def do_enforce_query_or_resource!(_something), do: :error
defmacro enforce_resource!(resource) do
quote do
if Ash.Resource.Info.resource?(unquote(resource)) do
:ok
else
{fun, arity} = __ENV__.function
mfa = "#{inspect(__ENV__.module)}.#{fun}/#{arity}"
raise Ash.Error.Invalid.NoSuchResource,
message: "#{mfa} expected an Ash Resource but instead got #{inspect(unquote(resource))}"
end
end
end
defmacro enforce_keyword_list!(list) do
quote do
if Keyword.keyword?(unquote(list)) do
:ok
else
{fun, arity} = __ENV__.function
mfa = "#{inspect(__ENV__.module)}.#{fun}/#{arity}"
raise "#{mfa} expected a keyword list, but instead got #{inspect(unquote(list))}"
end
end
end
end