mirror of
https://github.com/ash-project/ash.git
synced 2024-09-19 13:03:02 +12:00
feat: extension section module imports, generated .formatter.exs (#71)
This commit is contained in:
parent
c776da9237
commit
b6101a4dff
13 changed files with 290 additions and 77 deletions
|
@ -17,7 +17,8 @@
|
|||
"mix coveralls.github"
|
||||
else
|
||||
"mix test"
|
||||
end}
|
||||
end},
|
||||
{:check_formatter, command: "mix ash.formatter --check"}
|
||||
|
||||
## custom new tools may be added (mix tasks or arbitrary commands)
|
||||
# {:my_mix_task, command: "mix release", env: %{"MIX_ENV" => "prod"}},
|
||||
|
|
|
@ -1,27 +1,47 @@
|
|||
# Used by "mix format"
|
||||
# THIS FILE IS AUTOGENERATED USING `mix ash.formatter`
|
||||
# DONT MODIFY IT BY HAND
|
||||
locals_without_parens = [
|
||||
read: 1,
|
||||
read: 2,
|
||||
create: 1,
|
||||
create: 2,
|
||||
update: 1,
|
||||
update: 2,
|
||||
destroy: 1,
|
||||
destroy: 2,
|
||||
actions: 1,
|
||||
allow_nil?: 1,
|
||||
attribute: 2,
|
||||
attribute: 3,
|
||||
belongs_to: 2,
|
||||
belongs_to: 3,
|
||||
has_one: 2,
|
||||
has_one: 3,
|
||||
create: 1,
|
||||
create: 2,
|
||||
create_timestamp: 1,
|
||||
create_timestamp: 2,
|
||||
default: 1,
|
||||
define_field?: 1,
|
||||
description: 1,
|
||||
destination_field: 1,
|
||||
destination_field_on_join_table: 1,
|
||||
destroy: 1,
|
||||
destroy: 2,
|
||||
field_type: 1,
|
||||
generated?: 1,
|
||||
has_many: 2,
|
||||
has_many: 3,
|
||||
has_one: 2,
|
||||
has_one: 3,
|
||||
many_to_many: 2,
|
||||
many_to_many: 3,
|
||||
resources: 1,
|
||||
destination_field: 1,
|
||||
allow_nil?: 1
|
||||
primary?: 1,
|
||||
primary_key?: 1,
|
||||
read: 1,
|
||||
read: 2,
|
||||
resource: 1,
|
||||
resource: 2,
|
||||
reverse_relationship: 1,
|
||||
source_field: 1,
|
||||
source_field_on_join_table: 1,
|
||||
through: 1,
|
||||
type: 1,
|
||||
update: 1,
|
||||
update: 2,
|
||||
update_default: 1,
|
||||
update_timestamp: 1,
|
||||
update_timestamp: 2,
|
||||
writable?: 1
|
||||
]
|
||||
|
||||
[
|
||||
|
|
2
.github/workflows/elixir.yml
vendored
2
.github/workflows/elixir.yml
vendored
|
@ -1,4 +1,4 @@
|
|||
name: Elixir CI
|
||||
name: Ash CI
|
||||
|
||||
on:
|
||||
push:
|
||||
|
|
15
lib/ash.ex
15
lib/ash.ex
|
@ -106,12 +106,19 @@ defmodule Ash do
|
|||
|> Enum.find(&(&1.name == relationship_name))
|
||||
end
|
||||
|
||||
@spec resource_module?(module) :: boolean
|
||||
def resource_module?(module) do
|
||||
def implements_behaviour?(module, behaviour) do
|
||||
:attributes
|
||||
|> module.module_info()
|
||||
|> Keyword.get(:behaviour, [])
|
||||
|> Enum.any?(&(&1 == Ash.Resource))
|
||||
|> Enum.flat_map(fn
|
||||
{:behaviour, value} -> List.wrap(value)
|
||||
_ -> []
|
||||
end)
|
||||
|> Enum.any?(&(&1 == behaviour))
|
||||
end
|
||||
|
||||
@spec resource_module?(module) :: boolean
|
||||
def resource_module?(module) do
|
||||
implements_behaviour?(module, Ash.Resource)
|
||||
end
|
||||
|
||||
@doc false
|
||||
|
|
|
@ -27,13 +27,17 @@ defmodule Ash.Dsl.Entity do
|
|||
other values in that struct. If you need things that aren't contained in that struct, use an
|
||||
`Ash.Dsl.Transformer`.
|
||||
|
||||
`entities` allows you to specify a keyword list of nested entities. Nested entities are stored
|
||||
on the struct in the corresponding key, and are used in the same way entities are otherwise.
|
||||
|
||||
For a full example, see `Ash.Dsl.Extension`.
|
||||
"""
|
||||
defstruct [
|
||||
:name,
|
||||
:examples,
|
||||
:target,
|
||||
:transform,
|
||||
examples: [],
|
||||
entities: [],
|
||||
describe: "",
|
||||
args: [],
|
||||
schema: [],
|
||||
|
@ -47,17 +51,20 @@ defmodule Ash.Dsl.Entity do
|
|||
examples: [String.t()],
|
||||
transform: mfa | nil,
|
||||
args: [atom],
|
||||
entities: Keyword.t(),
|
||||
auto_set_fields: Keyword.t(),
|
||||
schema: NimbleOptions.schema()
|
||||
}
|
||||
|
||||
def build(
|
||||
%{target: target, schema: schema, auto_set_fields: auto_set_fields, transform: transform},
|
||||
opts
|
||||
opts,
|
||||
nested_entities
|
||||
) do
|
||||
with {:ok, opts} <- NimbleOptions.validate(opts, schema),
|
||||
opts <- Keyword.merge(opts, auto_set_fields || []),
|
||||
built <- struct(target, opts),
|
||||
built <- struct(built, nested_entities),
|
||||
{:ok, built} <-
|
||||
transform(transform, built) do
|
||||
{:ok, built}
|
||||
|
|
|
@ -149,7 +149,7 @@ defmodule Ash.Dsl.Extension do
|
|||
|> Enum.filter(fn key ->
|
||||
is_tuple(key) and elem(key, 0) == __MODULE__
|
||||
end)
|
||||
|> Enum.each(&Process.delete/1)
|
||||
|> Enum.each(&:persistent_term.delete/1)
|
||||
end
|
||||
|
||||
imports =
|
||||
|
@ -351,6 +351,13 @@ defmodule Ash.Dsl.Extension do
|
|||
section_path = unquote(path ++ [section.name])
|
||||
section = unquote(Macro.escape(section))
|
||||
|
||||
configured_imports =
|
||||
for module <- unquote(section.imports) do
|
||||
quote do
|
||||
import unquote(module)
|
||||
end
|
||||
end
|
||||
|
||||
entity_imports =
|
||||
for module <- unquote(entity_modules) do
|
||||
quote do
|
||||
|
@ -376,6 +383,13 @@ defmodule Ash.Dsl.Extension do
|
|||
]
|
||||
end
|
||||
|
||||
configured_unimports =
|
||||
for module <- unquote(section.imports) do
|
||||
quote do
|
||||
import unquote(module), only: []
|
||||
end
|
||||
end
|
||||
|
||||
entity_unimports =
|
||||
for module <- unquote(entity_modules) do
|
||||
quote do
|
||||
|
@ -404,6 +418,7 @@ defmodule Ash.Dsl.Extension do
|
|||
entity_imports ++
|
||||
section_imports ++
|
||||
opts_import ++
|
||||
configured_imports ++
|
||||
[
|
||||
quote do
|
||||
unquote(body[:do])
|
||||
|
@ -428,12 +443,15 @@ defmodule Ash.Dsl.Extension do
|
|||
path: unquote(section_path)
|
||||
end
|
||||
|
||||
Process.put({__MODULE__, :ash, unquote(section_path)}, %{
|
||||
entities: current_config.entities,
|
||||
opts: opts
|
||||
})
|
||||
Process.put(
|
||||
{__MODULE__, :ash, unquote(section_path)},
|
||||
%{
|
||||
entities: current_config.entities,
|
||||
opts: opts
|
||||
}
|
||||
)
|
||||
end
|
||||
] ++ opts_unimport ++ entity_unimports ++ section_unimports
|
||||
] ++ configured_unimports ++ opts_unimport ++ entity_unimports ++ section_unimports
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -496,6 +514,7 @@ defmodule Ash.Dsl.Extension do
|
|||
section_path = unquote(Macro.escape(section_path))
|
||||
field = unquote(Macro.escape(field))
|
||||
extension = unquote(extension)
|
||||
section = unquote(Macro.escape(section))
|
||||
|
||||
quote do
|
||||
current_sections = Process.get({__MODULE__, :ash_sections}, [])
|
||||
|
@ -515,8 +534,8 @@ defmodule Ash.Dsl.Extension do
|
|||
Process.put(
|
||||
{__MODULE__, :ash, unquote(section_path)},
|
||||
%{
|
||||
entities: current_config.entities,
|
||||
opts: Keyword.put(current_config.opts, unquote(field), unquote(value))
|
||||
current_config
|
||||
| opts: Keyword.put(current_config.opts, unquote(field), unquote(value))
|
||||
}
|
||||
)
|
||||
end
|
||||
|
@ -533,12 +552,32 @@ defmodule Ash.Dsl.Extension do
|
|||
end
|
||||
|
||||
@doc false
|
||||
def build_entity(mod, extension, section_path, entity) do
|
||||
mod_name = Module.concat(mod, Macro.camelize(to_string(entity.name)))
|
||||
def build_entity(mod, extension, section_path, entity, nested_entity_path \\ []) do
|
||||
nested_entity_parts = Enum.map(nested_entity_path, &Macro.camelize(to_string(&1)))
|
||||
|
||||
options_mod_name = Module.concat([mod, Macro.camelize(to_string(entity.name)), "Options"])
|
||||
mod_parts =
|
||||
Enum.concat([[mod], nested_entity_parts, [Macro.camelize(to_string(entity.name))]])
|
||||
|
||||
Ash.Dsl.Extension.build_entity_options(options_mod_name, entity.schema)
|
||||
mod_name = Module.concat(mod_parts)
|
||||
|
||||
options_mod_name = Module.concat(mod_name, "Options")
|
||||
|
||||
nested_entity_mods =
|
||||
Enum.flat_map(entity.entities, fn {key, entities} ->
|
||||
entities
|
||||
|> List.wrap()
|
||||
|> Enum.map(fn entity ->
|
||||
build_entity(
|
||||
mod_name,
|
||||
extension,
|
||||
section_path,
|
||||
entity,
|
||||
nested_entity_path ++ [key]
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
||||
Ash.Dsl.Extension.build_entity_options(options_mod_name, entity.schema, nested_entity_path)
|
||||
|
||||
args = Enum.map(entity.args, &Macro.var(&1, mod_name))
|
||||
|
||||
|
@ -549,65 +588,87 @@ defmodule Ash.Dsl.Extension do
|
|||
entity: Macro.escape(entity),
|
||||
args: Macro.escape(args),
|
||||
section_path: Macro.escape(section_path),
|
||||
options_mod_name: Macro.escape(options_mod_name)
|
||||
options_mod_name: Macro.escape(options_mod_name),
|
||||
nested_entity_mods: Macro.escape(nested_entity_mods),
|
||||
nested_entity_path: Macro.escape(nested_entity_path)
|
||||
] do
|
||||
@doc Ash.Dsl.Entity.describe(entity)
|
||||
defmacro unquote(entity.name)(unquote_splicing(args), opts \\ []) do
|
||||
section_path = unquote(section_path)
|
||||
section_path = unquote(Macro.escape(section_path))
|
||||
entity_schema = unquote(Macro.escape(entity.schema))
|
||||
entity = unquote(Macro.escape(entity))
|
||||
entity_name = unquote(entity.name)
|
||||
entity_args = unquote(entity.args)
|
||||
options_mod_name = unquote(options_mod_name)
|
||||
entity_name = unquote(Macro.escape(entity.name))
|
||||
entity_args = unquote(Macro.escape(entity.args))
|
||||
options_mod_name = unquote(Macro.escape(options_mod_name))
|
||||
source = unquote(__MODULE__)
|
||||
extension = unquote(extension)
|
||||
extension = unquote(Macro.escape(extension))
|
||||
nested_entity_mods = unquote(Macro.escape(nested_entity_mods))
|
||||
nested_entity_path = unquote(Macro.escape(nested_entity_path))
|
||||
|
||||
arg_values = unquote(args)
|
||||
|
||||
quote do
|
||||
alias Ash.Dsl.Entity
|
||||
section_path = unquote(section_path)
|
||||
entity_name = unquote(entity_name)
|
||||
extension = unquote(extension)
|
||||
|
||||
current_config =
|
||||
Process.get(
|
||||
{__MODULE__, :ash, section_path},
|
||||
%{entities: [], opts: []}
|
||||
)
|
||||
|
||||
current_sections = Process.get({__MODULE__, :ash_sections}, [])
|
||||
|
||||
opts_without_do =
|
||||
Process.put(
|
||||
{:builder_opts, unquote(nested_entity_path)},
|
||||
Keyword.merge(
|
||||
unquote(Keyword.delete(opts, :do)),
|
||||
Enum.zip(unquote(entity_args), unquote(arg_values))
|
||||
)
|
||||
)
|
||||
|
||||
import unquote(options_mod_name)
|
||||
|
||||
Ash.Dsl.Extension.import_mods(unquote(nested_entity_mods))
|
||||
|
||||
unquote(opts[:do])
|
||||
|
||||
current_config =
|
||||
Process.get(
|
||||
{__MODULE__, :ash, section_path ++ unquote(nested_entity_path)},
|
||||
%{entities: [], opts: []}
|
||||
)
|
||||
|
||||
import unquote(options_mod_name), only: []
|
||||
|
||||
all_opts =
|
||||
case Process.delete(:builder_opts) do
|
||||
nil ->
|
||||
opts_without_do
|
||||
Ash.Dsl.Extension.unimport_mods(unquote(nested_entity_mods))
|
||||
|
||||
opts ->
|
||||
Keyword.merge(opts, opts_without_do)
|
||||
end
|
||||
opts = Process.delete({:builder_opts, unquote(nested_entity_path)})
|
||||
|
||||
alias Ash.Dsl.Entity
|
||||
|
||||
nested_entities =
|
||||
unquote(Macro.escape(entity.entities))
|
||||
|> Enum.map(&elem(&1, 0))
|
||||
|> Enum.uniq()
|
||||
|> Enum.reduce(%{}, fn key, acc ->
|
||||
nested_path = section_path ++ unquote(nested_entity_path) ++ [key]
|
||||
|
||||
entities =
|
||||
{__MODULE__, :ash, nested_path}
|
||||
|> Process.get(%{entities: []})
|
||||
|> Map.get(:entities, [])
|
||||
|> Enum.reverse()
|
||||
|
||||
Map.update(acc, key, entities, fn current_nested_entities ->
|
||||
(current_nested_entities || []) ++ entities
|
||||
end)
|
||||
end)
|
||||
|
||||
built =
|
||||
case Entity.build(unquote(Macro.escape(entity)), all_opts) do
|
||||
case Entity.build(unquote(Macro.escape(entity)), opts, nested_entities) do
|
||||
{:ok, built} ->
|
||||
Map.put(built, :__entity_name__, unquote(entity_name))
|
||||
built
|
||||
|
||||
{:error, error} ->
|
||||
additional_path =
|
||||
if all_opts[:name] do
|
||||
[unquote(entity.name), all_opts[:name]]
|
||||
if opts[:name] do
|
||||
[unquote(entity.name), opts[:name]]
|
||||
else
|
||||
[unquote(entity.name)]
|
||||
end
|
||||
|
@ -629,7 +690,7 @@ defmodule Ash.Dsl.Extension do
|
|||
path: section_path ++ additional_path
|
||||
end
|
||||
|
||||
new_config = %{opts: current_config.opts, entities: [built | current_config.entities]}
|
||||
new_config = %{current_config | entities: current_config.entities ++ [built]}
|
||||
|
||||
unless {extension, section_path} in current_sections do
|
||||
Process.put({__MODULE__, :ash_sections}, [
|
||||
|
@ -638,7 +699,7 @@ defmodule Ash.Dsl.Extension do
|
|||
end
|
||||
|
||||
Process.put(
|
||||
{__MODULE__, :ash, section_path},
|
||||
{__MODULE__, :ash, section_path ++ unquote(nested_entity_path)},
|
||||
new_config
|
||||
)
|
||||
end
|
||||
|
@ -650,20 +711,41 @@ defmodule Ash.Dsl.Extension do
|
|||
mod_name
|
||||
end
|
||||
|
||||
defmacro import_mods(mods) do
|
||||
for mod <- mods do
|
||||
quote do
|
||||
import unquote(mod)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defmacro unimport_mods(mods) do
|
||||
for mod <- mods do
|
||||
quote do
|
||||
import unquote(mod), only: []
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@doc false
|
||||
def build_entity_options(module_name, schema) do
|
||||
def build_entity_options(module_name, schema, nested_entity_path) do
|
||||
Module.create(
|
||||
module_name,
|
||||
quote bind_quoted: [schema: Macro.escape(schema)] do
|
||||
quote bind_quoted: [schema: Macro.escape(schema), nested_entity_path: nested_entity_path] do
|
||||
@moduledoc false
|
||||
for {key, value} <- schema do
|
||||
|
||||
for {key, _value} <- schema do
|
||||
defmacro unquote(key)(value) do
|
||||
key = unquote(key)
|
||||
nested_entity_path = unquote(nested_entity_path)
|
||||
|
||||
quote do
|
||||
current_opts = Process.get(:builder_opts, [])
|
||||
current_opts = Process.get({:builder_opts, unquote(nested_entity_path)}, [])
|
||||
|
||||
Process.put(:builder_opts, Keyword.put(current_opts, unquote(key), unquote(value)))
|
||||
Process.put(
|
||||
{:builder_opts, unquote(nested_entity_path)},
|
||||
Keyword.put(current_opts, unquote(key), unquote(value))
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,7 +20,7 @@ defmodule Ash.Dsl.Section do
|
|||
|
||||
For a full example, see `Ash.Dsl.Extension`.
|
||||
"""
|
||||
defstruct [:name, schema: [], describe: "", entities: [], sections: []]
|
||||
defstruct [:name, imports: [], schema: [], describe: "", entities: [], sections: []]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
name: atom,
|
||||
|
|
|
@ -40,7 +40,7 @@ defmodule Ash.Resource do
|
|||
alias Ash.Dsl.Extension
|
||||
|
||||
:persistent_term.put({__MODULE__, :data_layer}, @data_layer)
|
||||
:persistent_term.put({__MODULE__, :ash, :authorizers}, @authorizers)
|
||||
:persistent_term.put({__MODULE__, :authorizers}, @authorizers)
|
||||
|
||||
Extension.set_state(false)
|
||||
|
||||
|
@ -51,7 +51,7 @@ defmodule Ash.Resource do
|
|||
@doc false
|
||||
def build_dsl do
|
||||
:persistent_term.put({__MODULE__, :data_layer}, @data_layer)
|
||||
:persistent_term.put({__MODULE__, :ash, :authorizers}, @authorizers)
|
||||
:persistent_term.put({__MODULE__, :authorizers}, @authorizers)
|
||||
Extension.set_state(true)
|
||||
|
||||
:ok
|
||||
|
|
|
@ -41,7 +41,7 @@ defmodule Ash.Resource.Relationships.ManyToMany do
|
|||
type: :atom,
|
||||
required: true,
|
||||
doc:
|
||||
"The field on the join table that should line up with `source_field` on this resource. Default: [resource_name]_id"
|
||||
"The field on the join table that should line up with `source_field` on this resource."
|
||||
],
|
||||
destination_field_on_join_table: [
|
||||
type: :atom,
|
||||
|
|
|
@ -13,7 +13,7 @@ defmodule Ash.Resource.Relationships.SharedOptions do
|
|||
destination_field: [
|
||||
type: :atom,
|
||||
doc:
|
||||
"The field on the related resource that should match the `source_field` on this resource. Default: [resource.name]_id"
|
||||
"The field on the related resource that should match the `source_field` on this resource."
|
||||
],
|
||||
source_field: [
|
||||
type: :atom,
|
||||
|
|
|
@ -233,9 +233,6 @@ defmodule Ash.Type do
|
|||
end
|
||||
|
||||
defp ash_type_module?(module) do
|
||||
:attributes
|
||||
|> module.module_info()
|
||||
|> Keyword.get(:behaviour, [])
|
||||
|> Enum.any?(&(&1 == __MODULE__))
|
||||
Ash.implements_behaviour?(module, __MODULE__)
|
||||
end
|
||||
end
|
||||
|
|
97
lib/mix/tasks/ash.formatter.ex
Normal file
97
lib/mix/tasks/ash.formatter.ex
Normal file
|
@ -0,0 +1,97 @@
|
|||
defmodule Mix.Tasks.Ash.Formatter do
|
||||
@moduledoc "Generates a .formatter.exs from a list of extensions, and writes it."
|
||||
use Mix.Task
|
||||
|
||||
@formatter_exs_template """
|
||||
# THIS FILE IS AUTOGENERATED USING `mix ash.formatter`
|
||||
# DONT MODIFY IT BY HAND
|
||||
locals_without_parens = __replace_me__
|
||||
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"],
|
||||
locals_without_parens: locals_without_parens,
|
||||
export: [
|
||||
locals_without_parens: locals_without_parens
|
||||
]
|
||||
]
|
||||
|
||||
"""
|
||||
|
||||
@shortdoc @moduledoc
|
||||
def run(opts) do
|
||||
{opts, []} = OptionParser.parse!(opts, strict: [check: :boolean, extensions: :string])
|
||||
|
||||
unless opts[:extensions] do
|
||||
raise "Must supply a comma separated list of extensions to generate a .formatter.exs for"
|
||||
end
|
||||
|
||||
locals_without_parens =
|
||||
opts[:extensions]
|
||||
|> String.split(",")
|
||||
|> Enum.flat_map(fn extension ->
|
||||
extension_mod = Module.concat([extension])
|
||||
|
||||
all_entity_builders(extension_mod.sections())
|
||||
end)
|
||||
|> Enum.uniq()
|
||||
|> Enum.sort()
|
||||
|
||||
contents =
|
||||
@formatter_exs_template
|
||||
|> String.replace("__replace_me__", inspect(locals_without_parens))
|
||||
|> Code.format_string!()
|
||||
|
||||
# |> IO.puts()
|
||||
|
||||
contents_with_newline = [contents, "\n"]
|
||||
|
||||
if opts[:check] do
|
||||
if File.read!(".formatter.exs") != IO.iodata_to_binary(contents_with_newline) do
|
||||
raise """
|
||||
.formatter.exs is not up to date!
|
||||
|
||||
Run the following command and commit the result:
|
||||
|
||||
mix ash.formatter --extensions #{opts[:extensions]}
|
||||
"""
|
||||
else
|
||||
IO.puts("The current .formatter.exs is correct")
|
||||
end
|
||||
else
|
||||
File.write!(".formatter.exs", contents_with_newline)
|
||||
end
|
||||
end
|
||||
|
||||
defp all_entity_builders(sections) do
|
||||
Enum.flat_map(sections, fn section ->
|
||||
Enum.concat([
|
||||
entity_option_builders(section),
|
||||
section_option_builders(section),
|
||||
entity_builders(section)
|
||||
])
|
||||
end)
|
||||
end
|
||||
|
||||
defp entity_builders(section) do
|
||||
Enum.flat_map(section.entities, fn entity ->
|
||||
arg_count = Enum.count(entity.args)
|
||||
[{entity.name, arg_count}, {entity.name, arg_count + 1}]
|
||||
end) ++ all_entity_builders(section.sections())
|
||||
end
|
||||
|
||||
defp entity_option_builders(section) do
|
||||
Enum.flat_map(section.entities, fn entity ->
|
||||
entity.schema
|
||||
|> Keyword.drop(entity.args)
|
||||
|> Enum.map(fn {key, _schema} ->
|
||||
{key, 1}
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
defp section_option_builders(section) do
|
||||
Enum.map(section.schema, fn {key, _} ->
|
||||
{key, 1}
|
||||
end)
|
||||
end
|
||||
end
|
4
mix.exs
4
mix.exs
|
@ -18,6 +18,7 @@ defmodule Ash.MixProject do
|
|||
elixirc_paths: elixirc_paths(Mix.env()),
|
||||
package: package(),
|
||||
deps: deps(),
|
||||
dialyzer: [plt_add_apps: [:mix]],
|
||||
test_coverage: [tool: ExCoveralls],
|
||||
preferred_cli_env: [
|
||||
coveralls: :test,
|
||||
|
@ -97,7 +98,8 @@ defmodule Ash.MixProject do
|
|||
defp aliases do
|
||||
[
|
||||
sobelow: "sobelow --skip",
|
||||
credo: "credo --strict"
|
||||
credo: "credo --strict",
|
||||
"ash.formatter": "ash.formatter --extensions Ash.Dsl,Ash.Api.Dsl"
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue