mirror of
https://github.com/ash-project/ash_blog.git
synced 2024-09-19 04:43:23 +12:00
WIP
This commit is contained in:
parent
31e246d305
commit
fdf9b75c51
7 changed files with 204 additions and 33 deletions
190
.credo.exs
Normal file
190
.credo.exs
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
# This file contains the configuration for Credo and you are probably reading
|
||||||
|
# this after creating it with `mix credo.gen.config`.
|
||||||
|
#
|
||||||
|
# If you find anything wrong or unclear in this file, please report an
|
||||||
|
# issue on GitHub: https://github.com/rrrene/credo/issues
|
||||||
|
#
|
||||||
|
%{
|
||||||
|
#
|
||||||
|
# You can have as many configs as you like in the `configs:` field.
|
||||||
|
configs: [
|
||||||
|
%{
|
||||||
|
#
|
||||||
|
# Run any config using `mix credo -C <name>`. If no config name is given
|
||||||
|
# "default" is used.
|
||||||
|
#
|
||||||
|
name: "default",
|
||||||
|
#
|
||||||
|
# These are the files included in the analysis:
|
||||||
|
files: %{
|
||||||
|
#
|
||||||
|
# You can give explicit globs or simply directories.
|
||||||
|
# In the latter case `**/*.{ex,exs}` will be used.
|
||||||
|
#
|
||||||
|
included: [
|
||||||
|
"lib/",
|
||||||
|
"src/",
|
||||||
|
"test/",
|
||||||
|
"web/",
|
||||||
|
"apps/*/lib/",
|
||||||
|
"apps/*/src/",
|
||||||
|
"apps/*/test/",
|
||||||
|
"apps/*/web/"
|
||||||
|
],
|
||||||
|
excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"]
|
||||||
|
},
|
||||||
|
#
|
||||||
|
# Load and configure plugins here:
|
||||||
|
#
|
||||||
|
plugins: [],
|
||||||
|
#
|
||||||
|
# If you create your own checks, you must specify the source files for
|
||||||
|
# them here, so they can be loaded by Credo before running the analysis.
|
||||||
|
#
|
||||||
|
requires: [],
|
||||||
|
#
|
||||||
|
# If you want to enforce a style guide and need a more traditional linting
|
||||||
|
# experience, you can change `strict` to `true` below:
|
||||||
|
#
|
||||||
|
strict: false,
|
||||||
|
#
|
||||||
|
# To modify the timeout for parsing files, change this value:
|
||||||
|
#
|
||||||
|
parse_timeout: 5000,
|
||||||
|
#
|
||||||
|
# If you want to use uncolored output by default, you can change `color`
|
||||||
|
# to `false` below:
|
||||||
|
#
|
||||||
|
color: true,
|
||||||
|
#
|
||||||
|
# You can customize the parameters of any check by adding a second element
|
||||||
|
# to the tuple.
|
||||||
|
#
|
||||||
|
# To disable a check put `false` as second element:
|
||||||
|
#
|
||||||
|
# {Credo.Check.Design.DuplicatedCode, false}
|
||||||
|
#
|
||||||
|
checks: [
|
||||||
|
#
|
||||||
|
## Consistency Checks
|
||||||
|
#
|
||||||
|
{Credo.Check.Consistency.ExceptionNames, []},
|
||||||
|
{Credo.Check.Consistency.LineEndings, []},
|
||||||
|
{Credo.Check.Consistency.ParameterPatternMatching, []},
|
||||||
|
# This check was erroring on sigils so I had to disable it
|
||||||
|
{Credo.Check.Consistency.SpaceAroundOperators, false},
|
||||||
|
{Credo.Check.Consistency.SpaceInParentheses, []},
|
||||||
|
{Credo.Check.Consistency.TabsOrSpaces, []},
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
## Design Checks
|
||||||
|
#
|
||||||
|
# You can customize the priority of any check
|
||||||
|
# Priority values are: `low, normal, high, higher`
|
||||||
|
#
|
||||||
|
{Credo.Check.Design.AliasUsage, false},
|
||||||
|
# You can also customize the exit_status of each check.
|
||||||
|
# If you don't want TODO comments to cause `mix credo` to fail, just
|
||||||
|
# set this value to 0 (zero).
|
||||||
|
#
|
||||||
|
{Credo.Check.Design.TagTODO, false},
|
||||||
|
{Credo.Check.Design.TagFIXME, []},
|
||||||
|
|
||||||
|
#
|
||||||
|
## Readability Checks
|
||||||
|
#
|
||||||
|
{Credo.Check.Readability.AliasOrder, []},
|
||||||
|
{Credo.Check.Readability.FunctionNames, []},
|
||||||
|
{Credo.Check.Readability.LargeNumbers, []},
|
||||||
|
{Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]},
|
||||||
|
{Credo.Check.Readability.ModuleAttributeNames, []},
|
||||||
|
{Credo.Check.Readability.ModuleDoc, []},
|
||||||
|
{Credo.Check.Readability.ModuleNames, []},
|
||||||
|
{Credo.Check.Readability.ParenthesesInCondition, false},
|
||||||
|
{Credo.Check.Readability.ParenthesesOnZeroArityDefs, []},
|
||||||
|
{Credo.Check.Readability.PredicateFunctionNames, []},
|
||||||
|
{Credo.Check.Readability.PreferImplicitTry, []},
|
||||||
|
{Credo.Check.Readability.RedundantBlankLines, []},
|
||||||
|
{Credo.Check.Readability.Semicolons, []},
|
||||||
|
{Credo.Check.Readability.SpaceAfterCommas, []},
|
||||||
|
{Credo.Check.Readability.StringSigils, []},
|
||||||
|
{Credo.Check.Readability.TrailingBlankLine, []},
|
||||||
|
{Credo.Check.Readability.TrailingWhiteSpace, []},
|
||||||
|
{Credo.Check.Readability.UnnecessaryAliasExpansion, []},
|
||||||
|
{Credo.Check.Readability.VariableNames, []},
|
||||||
|
|
||||||
|
#
|
||||||
|
## Refactoring Opportunities
|
||||||
|
#
|
||||||
|
{Credo.Check.Refactor.CondStatements, []},
|
||||||
|
{Credo.Check.Refactor.CyclomaticComplexity, false},
|
||||||
|
{Credo.Check.Refactor.FunctionArity, false},
|
||||||
|
{Credo.Check.Refactor.LongQuoteBlocks, false},
|
||||||
|
{Credo.Check.Refactor.MapInto, false},
|
||||||
|
{Credo.Check.Refactor.MatchInCondition, []},
|
||||||
|
{Credo.Check.Refactor.NegatedConditionsInUnless, []},
|
||||||
|
{Credo.Check.Refactor.NegatedConditionsWithElse, []},
|
||||||
|
{Credo.Check.Refactor.Nesting, [max_nesting: 5]},
|
||||||
|
{Credo.Check.Refactor.UnlessWithElse, []},
|
||||||
|
{Credo.Check.Refactor.WithClauses, []},
|
||||||
|
|
||||||
|
#
|
||||||
|
## Warnings
|
||||||
|
#
|
||||||
|
{Credo.Check.Warning.BoolOperationOnSameValues, []},
|
||||||
|
{Credo.Check.Warning.ExpensiveEmptyEnumCheck, []},
|
||||||
|
{Credo.Check.Warning.IExPry, []},
|
||||||
|
{Credo.Check.Warning.IoInspect, []},
|
||||||
|
{Credo.Check.Warning.LazyLogging, false},
|
||||||
|
{Credo.Check.Warning.MixEnv, false},
|
||||||
|
{Credo.Check.Warning.OperationOnSameValues, []},
|
||||||
|
{Credo.Check.Warning.OperationWithConstantResult, []},
|
||||||
|
{Credo.Check.Warning.RaiseInsideRescue, []},
|
||||||
|
{Credo.Check.Warning.UnusedEnumOperation, []},
|
||||||
|
{Credo.Check.Warning.UnusedFileOperation, []},
|
||||||
|
{Credo.Check.Warning.UnusedKeywordOperation, []},
|
||||||
|
{Credo.Check.Warning.UnusedListOperation, []},
|
||||||
|
{Credo.Check.Warning.UnusedPathOperation, []},
|
||||||
|
{Credo.Check.Warning.UnusedRegexOperation, []},
|
||||||
|
{Credo.Check.Warning.UnusedStringOperation, []},
|
||||||
|
{Credo.Check.Warning.UnusedTupleOperation, []},
|
||||||
|
{Credo.Check.Warning.UnsafeExec, []},
|
||||||
|
|
||||||
|
#
|
||||||
|
# Checks scheduled for next check update (opt-in for now, just replace `false` with `[]`)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Controversial and experimental checks (opt-in, just replace `false` with `[]`)
|
||||||
|
#
|
||||||
|
# {Credo.Check.Readability.StrictModuleLayout,
|
||||||
|
# order: [:shortdoc, :moduledoc, :behaviour, :use, :defstruct, :type, :import, :alias, :require],
|
||||||
|
# ignore: [:module_attribute, :type]},
|
||||||
|
{Credo.Check.Readability.StrictModuleLayout, false},
|
||||||
|
{Credo.Check.Consistency.MultiAliasImportRequireUse, false},
|
||||||
|
{Credo.Check.Consistency.UnusedVariableNames, false},
|
||||||
|
{Credo.Check.Design.DuplicatedCode, false},
|
||||||
|
{Credo.Check.Readability.AliasAs, false},
|
||||||
|
{Credo.Check.Readability.MultiAlias, false},
|
||||||
|
{Credo.Check.Readability.Specs, false},
|
||||||
|
{Credo.Check.Readability.SinglePipe, false},
|
||||||
|
{Credo.Check.Readability.WithCustomTaggedTuple, false},
|
||||||
|
{Credo.Check.Refactor.ABCSize, false},
|
||||||
|
{Credo.Check.Refactor.Apply, false},
|
||||||
|
{Credo.Check.Refactor.AppendSingleItem, false},
|
||||||
|
{Credo.Check.Refactor.DoubleBooleanNegation, false},
|
||||||
|
{Credo.Check.Refactor.ModuleDependencies, false},
|
||||||
|
{Credo.Check.Refactor.NegatedIsNil, false},
|
||||||
|
{Credo.Check.Refactor.PipeChainStart, false},
|
||||||
|
{Credo.Check.Refactor.VariableRebinding, false},
|
||||||
|
{Credo.Check.Warning.LeakyEnvironment, false},
|
||||||
|
{Credo.Check.Warning.MapGetUnsafePass, false},
|
||||||
|
{Credo.Check.Warning.UnsafeToAtom, false}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Custom checks can be created using `mix credo.gen.check`.
|
||||||
|
#
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -535,25 +535,6 @@ defmodule AshBlog.DataLayer do
|
||||||
apply(m, f, [changeset | a])
|
apply(m, f, [changeset | a])
|
||||||
end
|
end
|
||||||
|
|
||||||
defp put_or_insert_new(table, {pkey, record}, resource) do
|
|
||||||
attributes = resource |> Ash.Resource.Info.attributes()
|
|
||||||
|
|
||||||
case dump_to_native(record, attributes) do
|
|
||||||
{:ok, casted} ->
|
|
||||||
case ETS.Set.put(table, {pkey, casted}) do
|
|
||||||
{:ok, set} ->
|
|
||||||
{_key, record} = ETS.Set.get!(set, pkey)
|
|
||||||
cast_record(record, resource)
|
|
||||||
|
|
||||||
other ->
|
|
||||||
other
|
|
||||||
end
|
|
||||||
|
|
||||||
other ->
|
|
||||||
other
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
def dump_to_native(record, attributes) do
|
def dump_to_native(record, attributes) do
|
||||||
Enum.reduce_while(attributes, {:ok, %{}}, fn attribute, {:ok, attrs} ->
|
Enum.reduce_while(attributes, {:ok, %{}}, fn attribute, {:ok, attrs} ->
|
||||||
|
@ -585,8 +566,7 @@ defmodule AshBlog.DataLayer do
|
||||||
@doc false
|
@doc false
|
||||||
@impl true
|
@impl true
|
||||||
def update(resource, changeset) do
|
def update(resource, changeset) do
|
||||||
with {:ok, record} <- Ash.Changeset.apply_attributes(changeset),
|
with {:ok, record} <-
|
||||||
{:ok, record} <-
|
|
||||||
do_update(changeset, resource),
|
do_update(changeset, resource),
|
||||||
{:ok, record} <- cast_record(record, resource) do
|
{:ok, record} <- cast_record(record, resource) do
|
||||||
file_path =
|
file_path =
|
||||||
|
@ -612,7 +592,7 @@ defmodule AshBlog.DataLayer do
|
||||||
|
|
||||||
{:ok,
|
{:ok,
|
||||||
record
|
record
|
||||||
|> Ash.Resource.put_metadata(:ash_blog_file, changeset.data.__metadata__[:ash_blog_file])
|
|> Ash.Resource.put_metadata(:ash_blog_file, file_path)
|
||||||
|> Ash.Resource.set_meta(%Ecto.Schema.Metadata{state: :loaded, schema: resource})}
|
|> Ash.Resource.set_meta(%Ecto.Schema.Metadata{state: :loaded, schema: resource})}
|
||||||
else
|
else
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
|
@ -630,14 +610,12 @@ defmodule AshBlog.DataLayer do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_update(changeset, resource) do
|
defp do_update(changeset, resource) do
|
||||||
attributes = resource |> Ash.Resource.Info.attributes()
|
|
||||||
|
|
||||||
file_path =
|
file_path =
|
||||||
changeset.data.__metadata__[:ash_blog_file] ||
|
changeset.data.__metadata__[:ash_blog_file] ||
|
||||||
raise "Missing `ash_blog_file` metadata for record, cannot update!"
|
raise "Missing `ash_blog_file` metadata for record, cannot update!"
|
||||||
|
|
||||||
with {:ok, record} <- Ash.Changeset.apply_attributes(changeset),
|
with {:ok, record} <- Ash.Changeset.apply_attributes(changeset),
|
||||||
recore <-
|
record <-
|
||||||
Ash.Resource.set_meta(record, %Ecto.Schema.Metadata{state: :loaded, schema: resource}),
|
Ash.Resource.set_meta(record, %Ecto.Schema.Metadata{state: :loaded, schema: resource}),
|
||||||
{:ok, yaml} <- yaml_frontmatter(record) do
|
{:ok, yaml} <- yaml_frontmatter(record) do
|
||||||
File.mkdir_p!(Path.dirname(file_path))
|
File.mkdir_p!(Path.dirname(file_path))
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
defmodule AshBlog.FileNamer do
|
defmodule AshBlog.FileNamer do
|
||||||
|
@moduledoc """
|
||||||
|
The default file namer, uses the current timestamp and the title attribute of the post in the form `YYYY/YYYY-MM-DD-name.md`
|
||||||
|
"""
|
||||||
def name_file(changeset) do
|
def name_file(changeset) do
|
||||||
name =
|
name =
|
||||||
case Ash.Changeset.get_attribute(changeset, :title) ||
|
case Ash.Changeset.get_attribute(
|
||||||
Ash.Changeset.get_attribute(changeset, :name) do
|
changeset,
|
||||||
|
AshBlog.DataLayer.Info.title_attribute(changeset.resource)
|
||||||
|
) do
|
||||||
nil ->
|
nil ->
|
||||||
nil
|
nil
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,4 @@ defmodule AshBlog.DataLayer.Info do
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def full_file_name(resource) do
|
|
||||||
Path.join([folder(resource), file_name(resource)])
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
4
mix.lock
4
mix.lock
|
@ -1,5 +1,5 @@
|
||||||
%{
|
%{
|
||||||
"ash": {:git, "https://github.com/ash-project/ash.git", "e52d7187d889d3ec3403e7d8bb411f12bed3b103", []},
|
"ash": {:git, "https://github.com/ash-project/ash.git", "1718314f40dd9ebad0e169b5c98d9894f45a7f27", []},
|
||||||
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
|
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
|
||||||
"certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"},
|
"certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"},
|
||||||
"comparable": {:hex, :comparable, "1.0.0", "bb669e91cedd14ae9937053e5bcbc3c52bb2f22422611f43b6e38367d94a495f", [:mix], [{:typable, "~> 0.1", [hex: :typable, repo: "hexpm", optional: false]}], "hexpm", "277c11eeb1cd726e7cd41c6c199e7e52fa16ee6830b45ad4cdc62e51f62eb60c"},
|
"comparable": {:hex, :comparable, "1.0.0", "bb669e91cedd14ae9937053e5bcbc3c52bb2f22422611f43b6e38367d94a495f", [:mix], [{:typable, "~> 0.1", [hex: :typable, repo: "hexpm", optional: false]}], "hexpm", "277c11eeb1cd726e7cd41c6c199e7e52fa16ee6830b45ad4cdc62e51f62eb60c"},
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
"providers": {:hex, :providers, "1.8.1", "70b4197869514344a8a60e2b2a4ef41ca03def43cfb1712ecf076a0f3c62f083", [:rebar3], [{:getopt, "1.0.1", [hex: :getopt, repo: "hexpm", optional: false]}], "hexpm", "e45745ade9c476a9a469ea0840e418ab19360dc44f01a233304e118a44486ba0"},
|
"providers": {:hex, :providers, "1.8.1", "70b4197869514344a8a60e2b2a4ef41ca03def43cfb1712ecf076a0f3c62f083", [:rebar3], [{:getopt, "1.0.1", [hex: :getopt, repo: "hexpm", optional: false]}], "hexpm", "e45745ade9c476a9a469ea0840e418ab19360dc44f01a233304e118a44486ba0"},
|
||||||
"sobelow": {:hex, :sobelow, "0.11.1", "23438964486f8112b41e743bbfd402da3e5b296fdc9eacab29914b79c48916dd", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9897363a7eff96f4809304a90aad819e2ad5e5d24db547af502885146746a53c"},
|
"sobelow": {:hex, :sobelow, "0.11.1", "23438964486f8112b41e743bbfd402da3e5b296fdc9eacab29914b79c48916dd", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9897363a7eff96f4809304a90aad819e2ad5e5d24db547af502885146746a53c"},
|
||||||
"sourceror": {:hex, :sourceror, "0.11.2", "549ce48be666421ac60cfb7f59c8752e0d393baa0b14d06271d3f6a8c1b027ab", [:mix], [], "hexpm", "9ab659118896a36be6eec68ff7b0674cba372fc8e210b1e9dc8cf2b55bb70dfb"},
|
"sourceror": {:hex, :sourceror, "0.11.2", "549ce48be666421ac60cfb7f59c8752e0d393baa0b14d06271d3f6a8c1b027ab", [:mix], [], "hexpm", "9ab659118896a36be6eec68ff7b0674cba372fc8e210b1e9dc8cf2b55bb70dfb"},
|
||||||
"spark": {:hex, :spark, "0.2.2", "782989111ef63c76ab02779c1f996f0139b644a688a9f08445a33623f4737ff1", [:mix], [{:nimble_options, "~> 0.4.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 0.1", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "998684022e932b18c1512d2d1ac34938eb719df617e982281a50e4a4ea3fdf93"},
|
"spark": {:hex, :spark, "0.2.3", "3678177ca1f1f4c7919da90b49f5e378c39e1bdf2f59ad8909c0c3591fe8dbb6", [:mix], [{:nimble_options, "~> 0.4.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 0.1", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "933dadc7fcce93198104e7d88243772bbde9e54b001929a4c04bc733812e8e3b"},
|
||||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
|
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
|
||||||
"stream_data": {:hex, :stream_data, "0.5.0", "b27641e58941685c75b353577dc602c9d2c12292dd84babf506c2033cd97893e", [:mix], [], "hexpm", "012bd2eec069ada4db3411f9115ccafa38540a3c78c4c0349f151fc761b9e271"},
|
"stream_data": {:hex, :stream_data, "0.5.0", "b27641e58941685c75b353577dc602c9d2c12292dd84babf506c2033cd97893e", [:mix], [], "hexpm", "012bd2eec069ada4db3411f9115ccafa38540a3c78c4c0349f151fc761b9e271"},
|
||||||
"telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"},
|
"telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"},
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
defmodule AshBlog.Test.Api do
|
defmodule AshBlog.Test.Api do
|
||||||
|
@moduledoc false
|
||||||
use Ash.Api
|
use Ash.Api
|
||||||
|
|
||||||
resources do
|
resources do
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
defmodule AshBlog.Test.Post do
|
defmodule AshBlog.Test.Post do
|
||||||
|
@moduledoc false
|
||||||
use Ash.Resource,
|
use Ash.Resource,
|
||||||
otp_app: :ash_blog,
|
otp_app: :ash_blog,
|
||||||
data_layer: AshBlog.DataLayer
|
data_layer: AshBlog.DataLayer
|
||||||
|
|
Loading…
Reference in a new issue