Packages

ash

3.27.0
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 info manifest json_serializer.ex
Raw

lib/ash/info/manifest/json_serializer.ex

# SPDX-FileCopyrightText: 2025 ash contributors <https://github.com/ash-project/ash/graphs/contributors>
#
# SPDX-License-Identifier: MIT
defmodule Ash.Info.Manifest.JsonSerializer do
@moduledoc """
Serializes `%Ash.Info.Manifest{}` structs to JSON.
Recursively converts structs to maps, converting module atoms to strings
and omitting nil fields.
"""
@doc """
Serialize an `%Ash.Info.Manifest{}` to a JSON string.
"""
@spec to_json(Ash.Info.Manifest.t(), keyword()) :: {:ok, String.t()} | {:error, term()}
def to_json(%Ash.Info.Manifest{} = spec, opts \\ []) do
pretty? = Keyword.get(opts, :pretty, false)
map = to_map(spec)
json_opts = if pretty?, do: [pretty: true], else: []
{:ok, Jason.encode!(map, json_opts)}
rescue
e -> {:error, Exception.message(e)}
end
@doc """
Convert an `%Ash.Info.Manifest{}` to a plain map (suitable for JSON encoding).
"""
@spec to_map(Ash.Info.Manifest.t()) :: map()
def to_map(%Ash.Info.Manifest{} = spec) do
%{
"schema_version" => Ash.Info.Manifest.schema_version(),
"resources" => Enum.map(spec.resources, &serialize_resource/1),
"types" => Enum.map(spec.types, &serialize_type/1),
"entrypoints" => Enum.map(spec.entrypoints, &serialize_entrypoint/1)
}
|> put_if_present(
"filter_capabilities",
serialize_filter_capabilities(spec.filter_capabilities)
)
|> put_if_present(
"sort_capabilities",
serialize_sort_capabilities(spec.sort_capabilities)
)
end
defp serialize_filter_capabilities(nil), do: nil
defp serialize_filter_capabilities(%Ash.Info.Manifest.FilterCapabilities{} = caps) do
%{
"operators" => Enum.map(caps.operators, &serialize_operator/1),
"functions" => Enum.map(caps.functions, &serialize_function/1),
"custom_expressions" => Enum.map(caps.custom_expressions, &serialize_custom_expression/1),
"boolean_connectives" => Enum.map(caps.boolean_connectives, &to_string/1),
"predicate_operators" => Enum.map(caps.predicate_operators, &to_string/1),
"predicate_functions" => Enum.map(caps.predicate_functions, &to_string/1),
"predicate_custom_expressions" => Enum.map(caps.predicate_custom_expressions, &to_string/1)
}
end
defp serialize_sort_capabilities(nil), do: nil
defp serialize_sort_capabilities(%Ash.Info.Manifest.SortCapabilities{} = caps) do
%{"directions" => Enum.map(caps.directions, &to_string/1)}
end
defp serialize_operator(%Ash.Info.Manifest.Operator{} = op) do
%{
"name" => to_string(op.name),
"module" => module_to_string(op.module),
"aliases" => Enum.map(op.aliases || [], &to_string/1),
"predicate" => op.predicate?,
"signatures" => Enum.map(op.signatures || [], &serialize_signature/1),
"returns" => serialize_returns(op.returns)
}
|> put_if_present("description", op.description)
end
defp serialize_function(%Ash.Info.Manifest.Function{} = fun) do
%{
"name" => to_string(fun.name),
"module" => module_to_string(fun.module),
"predicate" => fun.predicate?,
"signatures" => serialize_function_signatures(fun.signatures),
"returns" => serialize_returns(fun.returns)
}
|> put_if_present("description", fun.description)
|> put_if_present("data_layer_module", module_to_string(fun.data_layer_module))
end
defp serialize_custom_expression(%Ash.Info.Manifest.CustomExpression{} = ce) do
%{
"name" => to_string(ce.name),
"module" => module_to_string(ce.module),
"predicate" => ce.predicate?,
"signatures" => Enum.map(ce.signatures || [], &serialize_signature/1)
}
|> put_if_present("description", ce.description)
end
defp serialize_function_signatures(:var_args), do: "var_args"
defp serialize_function_signatures(sigs) when is_list(sigs),
do: Enum.map(sigs, &serialize_signature/1)
defp serialize_signature(%Ash.Info.Manifest.ArgumentSignature{args: args}) do
%{"args" => Enum.map(args, &serialize_arg_spec/1)}
end
defp serialize_arg_spec(%{kind: kind} = arg) do
%{"kind" => to_string(kind)}
|> put_if_present("type_ref", module_to_string(arg[:type_ref]))
|> put_if_present("of", serialize_arg_of(arg[:of]))
|> put_if_present(
"constraints",
if(arg[:constraints] in [nil, []], do: nil, else: inspect(arg[:constraints]))
)
end
defp serialize_arg_of(nil), do: nil
defp serialize_arg_of(%{kind: _} = inner), do: serialize_arg_spec(inner)
defp serialize_returns(:unknown), do: "unknown"
defp serialize_returns(nil), do: nil
defp serialize_returns(%{kind: _} = arg), do: serialize_arg_spec(arg)
defp serialize_resource(%Ash.Info.Manifest.Resource{} = resource) do
%{
"name" => resource.name,
"module" => module_to_string(resource.module),
"embedded" => resource.embedded?,
"primary_key" => Enum.map(resource.primary_key || [], &to_string/1),
"fields" => serialize_named_map(resource.fields, &serialize_field/1),
"relationships" => serialize_named_map(resource.relationships, &serialize_relationship/1)
}
|> put_if_present("description", resource.description)
|> put_if_present("multitenancy", serialize_multitenancy(resource.multitenancy))
end
defp serialize_entrypoint(%Ash.Info.Manifest.Entrypoint{} = entrypoint) do
# config is omitted from JSON — it carries internal extension-specific structs
%{
"resource" => module_to_string(entrypoint.resource),
"action" => serialize_action(entrypoint.action)
}
end
defp serialize_field(%Ash.Info.Manifest.Field{} = field) do
base = %{
"kind" => to_string(field.kind),
"type" => serialize_type(field.type),
"allow_nil" => field.allow_nil?,
"writable" => field.writable?,
"has_default" => field.has_default?,
"filterable" => field.filterable?,
"sortable" => field.sortable?,
"primary_key" => field.primary_key?,
"sensitive" => field.sensitive?,
"select_by_default" => field.select_by_default?
}
base
|> put_if_present("description", field.description)
|> put_if_present("arguments", serialize_arguments_list(field.arguments))
|> put_if_present("aggregate_kind", serialize_atom(field.aggregate_kind))
|> put_if_present("filter_operators", serialize_applicable_list(field.filter_operators))
|> put_if_present("filter_functions", serialize_applicable_list(field.filter_functions))
|> put_if_present(
"filter_custom_expressions",
serialize_applicable_list(field.filter_custom_expressions)
)
end
defp serialize_applicable_list(nil), do: nil
defp serialize_applicable_list(list) when is_list(list) do
Enum.map(list, &serialize_applicable/1)
end
defp serialize_applicable(%Ash.Info.Manifest.ApplicableOperator{name: name, rhs: rhs}) do
%{"name" => to_string(name), "rhs" => serialize_rhs(rhs)}
end
defp serialize_applicable(%Ash.Info.Manifest.ApplicableFunction{name: name, rhs: rhs}) do
%{"name" => to_string(name), "rhs" => serialize_rhs(rhs)}
end
defp serialize_applicable(%Ash.Info.Manifest.ApplicableCustomExpression{
name: name,
rhs: rhs
}) do
%{"name" => to_string(name), "rhs" => serialize_rhs(rhs)}
end
defp serialize_rhs(:same), do: "same"
defp serialize_rhs(:any), do: "any"
defp serialize_rhs({:concrete, ref}) when is_atom(ref),
do: %{"concrete" => module_to_string(ref)}
defp serialize_rhs({:array, inner}), do: %{"array" => serialize_rhs(inner)}
defp serialize_rhs(_), do: "any"
defp serialize_relationship(%Ash.Info.Manifest.Relationship{} = rel) do
%{
"type" => to_string(rel.type),
"cardinality" => to_string(rel.cardinality),
"destination" => module_to_string(rel.destination),
"allow_nil" => rel.allow_nil?,
"filterable" => rel.filterable?,
"sortable" => rel.sortable?
}
|> put_if_present("description", rel.description)
end
defp serialize_action(%Ash.Info.Manifest.Action{} = action) do
%{
"type" => to_string(action.type),
"primary" => action.primary?,
"get" => action.get?,
"inputs" => Enum.map(action.inputs || [], &serialize_argument/1),
"metadata" => Enum.map(action.metadata || [], &serialize_metadata/1)
}
|> put_if_present("description", action.description)
|> put_if_present("returns", serialize_type(action.returns))
|> put_if_present("pagination", serialize_pagination(action.pagination))
end
defp serialize_type(nil), do: nil
defp serialize_type(%Ash.Info.Manifest.Type{} = type) do
base = %{
"kind" => to_string(type.kind),
"name" => type.name,
"allow_nil" => type.allow_nil?
}
base
|> put_if_present("module", module_to_string(type.module))
|> put_if_present("values", serialize_atom_list(type.values))
|> put_if_present("members", serialize_members(type.members))
|> put_if_present("resource_module", module_to_string(type.resource_module))
|> put_if_present("fields", serialize_type_fields(type.fields))
|> put_if_present("instance_of", module_to_string(type.instance_of))
|> put_if_present("item_type", serialize_type(type.item_type))
|> put_if_present("element_types", serialize_type_fields(type.element_types))
|> put_if_present("resource", serialize_nested_resource(type.resource))
end
defp serialize_nested_resource(nil), do: nil
defp serialize_nested_resource(%Ash.Info.Manifest.Resource{} = resource),
do: serialize_resource(resource)
defp serialize_argument(%Ash.Info.Manifest.Argument{} = arg) do
%{
"name" => to_string(arg.name),
"type" => serialize_type(arg.type),
"allow_nil" => arg.allow_nil?,
"has_default" => arg.has_default?,
"required" => arg.required?,
"sensitive" => arg.sensitive?
}
|> put_if_present("description", arg.description)
end
defp serialize_metadata(%Ash.Info.Manifest.Metadata{} = meta) do
%{
"name" => to_string(meta.name),
"type" => serialize_type(meta.type),
"allow_nil" => meta.allow_nil?
}
|> put_if_present("description", meta.description)
end
defp serialize_pagination(nil), do: nil
defp serialize_pagination(%Ash.Info.Manifest.Pagination{} = page) do
%{
"offset" => page.offset?,
"keyset" => page.keyset?,
"required" => page.required?,
"countable" => page.countable?,
"default_limit" => page.default_limit,
"max_page_size" => page.max_page_size
}
end
defp serialize_multitenancy(nil), do: nil
defp serialize_multitenancy(%{} = mt) do
%{
"strategy" => to_string(mt.strategy),
"global" => mt.global?,
"attribute" => serialize_atom(mt.attribute)
}
end
defp serialize_named_map(map, serialize_fn) when is_map(map) do
Map.new(map, fn {name, value} ->
{to_string(name), serialize_fn.(value)}
end)
end
defp serialize_arguments_list(nil), do: nil
defp serialize_arguments_list([]), do: nil
defp serialize_arguments_list(args), do: Enum.map(args, &serialize_argument/1)
defp serialize_members(nil), do: nil
defp serialize_members(members) do
Enum.map(members, fn member ->
%{
"name" => to_string(member.name),
"type" => serialize_type(member.type)
}
|> put_if_present("description", Map.get(member, :description))
end)
end
defp serialize_type_fields(nil), do: nil
defp serialize_type_fields(fields) do
Enum.map(fields, fn field ->
%{
"name" => to_string(field.name),
"type" => serialize_type(field.type),
"allow_nil" => field.allow_nil?
}
|> put_if_present("description", Map.get(field, :description))
end)
end
defp serialize_atom_list(nil), do: nil
defp serialize_atom_list(list), do: Enum.map(list, &to_string/1)
defp serialize_atom(nil), do: nil
defp serialize_atom(atom) when is_atom(atom), do: to_string(atom)
defp module_to_string(nil), do: nil
defp module_to_string(module) when is_atom(module) do
case Atom.to_string(module) do
"Elixir." <> _ -> module |> Module.split() |> Enum.join(".")
other -> other
end
end
defp module_to_string(other), do: inspect(other)
defp put_if_present(map, _key, nil), do: map
defp put_if_present(map, key, value), do: Map.put(map, key, value)
end