mirror of
https://github.com/ash-project/ash_hq.git
synced 2024-09-19 21:03:30 +12:00
improvement: change all kinds of things, build docs statically
This commit is contained in:
parent
9ac964694f
commit
48d999e125
29 changed files with 1527 additions and 448 deletions
|
@ -29,8 +29,8 @@ COPY ./mix.lock .
|
|||
COPY ./config/config.exs config/config.exs
|
||||
COPY ./config/prod.exs config/prod.exs
|
||||
COPY ./assets/tailwind.colors.json ./assets/tailwind.colors.json
|
||||
RUN mix deps.get && \
|
||||
mix deps.compile
|
||||
RUN mix deps.get
|
||||
RUN mix deps.compile
|
||||
COPY ./lib ./lib
|
||||
COPY ./priv ./priv
|
||||
COPY ./assets ./assets
|
||||
|
|
|
@ -7,6 +7,20 @@
|
|||
# General application configuration
|
||||
import Config
|
||||
|
||||
config :ash_hq, AshHq.Docs.Cache,
|
||||
# When using :shards as backend
|
||||
# backend: :shards,
|
||||
# GC interval for pushing new generation: 12 hrs
|
||||
gc_interval: :timer.hours(12),
|
||||
# Max 1 million entries in cache
|
||||
max_size: 1_000_000,
|
||||
# Max 2 GB of memory
|
||||
allocated_memory: 1_000_000_000,
|
||||
# GC min timeout: 10 sec
|
||||
gc_cleanup_min_timeout: :timer.seconds(10),
|
||||
# GC max timeout: 10 min
|
||||
gc_cleanup_max_timeout: :timer.minutes(10)
|
||||
|
||||
config :ash_hq,
|
||||
ecto_repos: [AshHq.Repo]
|
||||
|
||||
|
|
|
@ -22,6 +22,10 @@ port = String.to_integer(System.get_env("PORT") || "4000")
|
|||
|
||||
config :ash_hq, url: System.get_env("ASH_HQ_URL") || "http://localhost:4000"
|
||||
|
||||
if config_env() != :dev do
|
||||
config :logger, level: String.to_existing_atom(System.get_env("LOG_LEVEL") || "info")
|
||||
end
|
||||
|
||||
if config_env() == :prod do
|
||||
database_url =
|
||||
System.get_env("DATABASE_URL") ||
|
||||
|
|
|
@ -166,10 +166,9 @@ defmodule AshHq.Accounts.User do
|
|||
|
||||
validate(confirm(:password, :password_confirmation))
|
||||
|
||||
validate {AshHq.Accounts.User.Validations.ValidateCurrentPassword,
|
||||
argument: :current_password} do
|
||||
only_when_valid?(true)
|
||||
before_action?(true)
|
||||
validate {AshAuthentication.Strategy.Password.PasswordValidation, password_argument: :current_password} do
|
||||
only_when_valid? true
|
||||
before_action? true
|
||||
end
|
||||
|
||||
change(set_context(%{strategy_name: :password}))
|
||||
|
@ -184,10 +183,9 @@ defmodule AshHq.Accounts.User do
|
|||
allow_nil?(false)
|
||||
end
|
||||
|
||||
validate {AshHq.Accounts.User.Validations.ValidateCurrentPassword,
|
||||
argument: :current_password} do
|
||||
only_when_valid?(true)
|
||||
before_action?(true)
|
||||
validate {AshAuthentication.Strategy.Password.PasswordValidation, password_argument: :current_password} do
|
||||
only_when_valid? true
|
||||
before_action? true
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
defmodule AshHq.Accounts.User.Validations.ValidateCurrentPassword do
|
||||
@moduledoc """
|
||||
Confirms that the provided password is valid.
|
||||
|
||||
This is useful for actions that should only be able to be taken on a given user if you know
|
||||
their password (like changing the email, for example).
|
||||
"""
|
||||
use Ash.Resource.Validation
|
||||
|
||||
@impl true
|
||||
def validate(changeset, opts) do
|
||||
strategy = AshAuthentication.Info.strategy!(changeset.resource, :password)
|
||||
plaintext_password = Ash.Changeset.get_argument(changeset, opts[:argument])
|
||||
|
||||
hashed_password = Map.get(changeset.data, strategy.hashed_password_field)
|
||||
|
||||
if hashed_password do
|
||||
if strategy.hash_provider.valid?(plaintext_password, hashed_password) do
|
||||
:ok
|
||||
else
|
||||
{:error, [field: opts[:argument], message: "is incorrect"]}
|
||||
end
|
||||
else
|
||||
{:error,
|
||||
[
|
||||
field: opts[:argument],
|
||||
message:
|
||||
"has not been set. If you logged in with github and would like to set a password, please log out and use the forgot password flow."
|
||||
]}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -32,6 +32,7 @@ defmodule AshHq.Application do
|
|||
AshHqWeb.Telemetry,
|
||||
# Start the PubSub system
|
||||
{Phoenix.PubSub, name: AshHq.PubSub},
|
||||
{AshHq.Docs.Cache, []},
|
||||
# Start the Endpoint (http/https)
|
||||
AshHqWeb.Endpoint
|
||||
# Start a worker by calling: AshHq.Worker.start_link(arg)
|
||||
|
|
5
lib/ash_hq/docs/cache.ex
Normal file
5
lib/ash_hq/docs/cache.ex
Normal file
|
@ -0,0 +1,5 @@
|
|||
defmodule AshHq.Docs.Cache do
|
||||
use Nebulex.Cache,
|
||||
otp_app: :ash_hq,
|
||||
adapter: Nebulex.Adapters.Local
|
||||
end
|
|
@ -4,13 +4,16 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Changes.RenderMarkdown do
|
|||
"""
|
||||
|
||||
require Logger
|
||||
require Ash.Query
|
||||
use Ash.Resource.Change
|
||||
use AshHqWeb, :verified_routes
|
||||
|
||||
def change(changeset, opts, _) do
|
||||
Ash.Changeset.before_action(changeset, fn changeset ->
|
||||
if Ash.Changeset.changing_attribute?(changeset, opts[:source]) do
|
||||
source = Ash.Changeset.get_attribute(changeset, opts[:source])
|
||||
text = remove_ash_hq_hidden_content(source)
|
||||
libraries = AshHq.Docs.Library.read!()
|
||||
text = process_text(source)
|
||||
|
||||
attribute = Ash.Resource.Info.attribute(changeset.resource, opts[:destination])
|
||||
|
||||
|
@ -21,8 +24,39 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Changes.RenderMarkdown do
|
|||
changeset
|
||||
end
|
||||
|
||||
current_module =
|
||||
cond do
|
||||
changeset.resource == AshHq.Docs.Module ->
|
||||
Ash.Changeset.get_attribute(changeset, :name)
|
||||
|
||||
changeset.resource == AshHq.Docs.Function ->
|
||||
AshHq.Docs.get!(
|
||||
AshHq.Docs.Module,
|
||||
Ash.Changeset.get_attribute(changeset, :module_id)
|
||||
).name
|
||||
|
||||
true ->
|
||||
nil
|
||||
end
|
||||
|
||||
current_library =
|
||||
case Ash.Changeset.get_attribute(changeset, :library_version_id) do
|
||||
nil ->
|
||||
nil
|
||||
|
||||
library_version_id ->
|
||||
AshHq.Docs.Library
|
||||
|> Ash.Query.select(:name)
|
||||
|> Ash.Query.filter(versions.id == ^library_version_id)
|
||||
|> AshHq.Docs.read_one!()
|
||||
|> Map.get(:name)
|
||||
end
|
||||
|
||||
case AshHq.Docs.Extensions.RenderMarkdown.as_html(
|
||||
text,
|
||||
libraries,
|
||||
current_library,
|
||||
current_module,
|
||||
AshHq.Docs.Extensions.RenderMarkdown.header_ids?(changeset.resource)
|
||||
) do
|
||||
{:error, html_doc, error_messages} ->
|
||||
|
@ -67,12 +101,18 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Changes.RenderMarkdown do
|
|||
end)
|
||||
end
|
||||
|
||||
defp remove_ash_hq_hidden_content(nil), do: nil
|
||||
|
||||
defp remove_ash_hq_hidden_content(strings) when is_list(strings) do
|
||||
Enum.map(strings, &remove_ash_hq_hidden_content/1)
|
||||
@doc false
|
||||
def process_text(text) when is_list(text) do
|
||||
Enum.map(text, &process_text(&1))
|
||||
end
|
||||
|
||||
def process_text(text) do
|
||||
text
|
||||
|> remove_ash_hq_hidden_content()
|
||||
end
|
||||
|
||||
defp remove_ash_hq_hidden_content(nil), do: nil
|
||||
|
||||
defp remove_ash_hq_hidden_content(string) do
|
||||
string
|
||||
|> String.split(~r/\<\!---.*ash-hq-hide-start.*--\>/)
|
||||
|
|
|
@ -3,18 +3,23 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Highlighter do
|
|||
# Copied *directly* from nimble_publisher
|
||||
# https://github.com/dashbitco/nimble_publisher/blob/v0.1.2/lib/nimble_publisher/highlighter.ex
|
||||
|
||||
use AshHqWeb, :verified_routes
|
||||
|
||||
@doc """
|
||||
Highlights all code block in an already generated HTML document.
|
||||
"""
|
||||
def highlight(html) when is_list(html) do
|
||||
Enum.map(html, &highlight/1)
|
||||
def highlight(html, libraries, current_library, current_module) when is_list(html) do
|
||||
Enum.map(html, &highlight(&1, libraries, current_library, current_module))
|
||||
end
|
||||
|
||||
def highlight(html) do
|
||||
def highlight(html, libraries, current_library, current_module) do
|
||||
html
|
||||
|> Floki.parse_document!()
|
||||
|> Floki.traverse_and_update(fn
|
||||
{"pre", _, [{"code", attrs, [body]}]} when is_binary(body) ->
|
||||
{"a", attrs, contents} ->
|
||||
{"a", rewrite_href_attr(attrs, current_library, libraries), contents}
|
||||
|
||||
{"code", attrs, [body]} when is_binary(body) ->
|
||||
lexer =
|
||||
find_value_class(attrs, fn class ->
|
||||
case Makeup.Registry.fetch_lexer_by_name(class) do
|
||||
|
@ -29,10 +34,9 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Highlighter do
|
|||
|
||||
nil ->
|
||||
if find_value_class(attrs, &(&1 == "inline")) do
|
||||
{:keep, maybe_highlight_module(body)}
|
||||
{:keep, maybe_highlight_module(body, libraries, current_module)}
|
||||
else
|
||||
{:keep,
|
||||
~s(<pre class="code-pre"><code class="text-black dark:text-white">#{body}</code></pre>)}
|
||||
{:keep, ~s(<code class="text-black dark:text-white">#{body}</code>)}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -42,6 +46,95 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Highlighter do
|
|||
|> AshHq.Docs.Extensions.RenderMarkdown.RawHTML.raw_html(pretty: true)
|
||||
end
|
||||
|
||||
defp rewrite_href_attr(attrs, current_library, libraries) do
|
||||
Enum.map(attrs, fn
|
||||
{"href", value} ->
|
||||
{"href", rewrite_href(value, current_library, libraries)}
|
||||
|
||||
other ->
|
||||
other
|
||||
end)
|
||||
end
|
||||
|
||||
@doc false
|
||||
def rewrite_href(value, current_library, libraries) do
|
||||
uri = URI.parse(value)
|
||||
|
||||
case {uri, Path.split(String.trim_leading(uri.path || "", "/"))} |> IO.inspect() do
|
||||
{%{host: "hexdocs.pm"}, [library, guide]} ->
|
||||
if Enum.any?(libraries, &(&1.name == library)) do
|
||||
if String.ends_with?(guide, ".html") do
|
||||
name =
|
||||
guide
|
||||
|> String.trim_trailing(".html")
|
||||
|> AshHqWeb.DocRoutes.sanitize_name()
|
||||
|
||||
url(~p"/docs/guides/#{library}/latest/#{name}")
|
||||
end
|
||||
else
|
||||
value
|
||||
end
|
||||
|
||||
{%{host: "hexdocs.pm"}, [library]} ->
|
||||
if Enum.any?(libraries, &(&1.name == library)) do
|
||||
url(~p"/docs/#{library}/latest")
|
||||
else
|
||||
value
|
||||
end
|
||||
|
||||
{%{host: "hex.pm"}, ["packages", library]} ->
|
||||
if Enum.any?(libraries, &(&1.name == library)) do
|
||||
url(~p"/docs/#{library}/latest")
|
||||
else
|
||||
value
|
||||
end
|
||||
|
||||
{%{host: "github.com"}, [owner, library]} ->
|
||||
if Enum.any?(libraries, &(&1.name == library && &1.repo_org == owner)) do
|
||||
url(~p"/docs/#{library}/latest")
|
||||
else
|
||||
value
|
||||
end
|
||||
|
||||
{%{host: "github.com"}, [owner, library, "blob", _, "documentation", guide]} ->
|
||||
github_guide_link(value, libraries, owner, library, guide)
|
||||
|
||||
{%{host: "github.com"}, [owner, library, "tree", _, "documentation", guide]} ->
|
||||
github_guide_link(value, libraries, owner, library, guide)
|
||||
|
||||
{%{host: nil}, ["documentation", _type, guide]} ->
|
||||
github_guide_link(value, libraries, nil, current_library, guide)
|
||||
|
||||
{%{host: nil}, [guide]} ->
|
||||
github_guide_link(value, libraries, nil, current_library, guide)
|
||||
|
||||
_ ->
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
defp github_guide_link(value, _libraries, _owner, nil, _guide) do
|
||||
value
|
||||
end
|
||||
|
||||
defp github_guide_link(value, libraries, owner, library, guide) do
|
||||
guide = String.trim_trailing(guide, ".md")
|
||||
|
||||
if owner do
|
||||
if Enum.any?(libraries, &(&1.name == library && &1.repo_org == owner)) do
|
||||
url(~p"/docs/guides/#{library}/latest/#{guide}")
|
||||
else
|
||||
value
|
||||
end
|
||||
else
|
||||
if Enum.any?(libraries, &(&1.name == library)) do
|
||||
url(~p"/docs/guides/#{library}/latest/#{guide}")
|
||||
else
|
||||
value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp find_value_class(attrs, func) do
|
||||
Enum.find_value(attrs, fn
|
||||
{"class", classes} ->
|
||||
|
@ -54,7 +147,7 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Highlighter do
|
|||
end)
|
||||
end
|
||||
|
||||
defp maybe_highlight_module(code) do
|
||||
def maybe_highlight_module(code, libraries, current_module) do
|
||||
code_without_c =
|
||||
case code do
|
||||
"c:" <> rest ->
|
||||
|
@ -73,19 +166,101 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Highlighter do
|
|||
nil
|
||||
end
|
||||
|
||||
try_parse_multi([
|
||||
{~s(data-fun-type="callback"), code_without_c},
|
||||
{~s(data-fun-type="type"), code_without_type},
|
||||
{nil, code}
|
||||
])
|
||||
code_without_dsl =
|
||||
case code do
|
||||
"d:" <> rest ->
|
||||
rest
|
||||
|
||||
_ ->
|
||||
nil
|
||||
end
|
||||
|
||||
defp try_parse_multi([{_, nil} | rest]), do: try_parse_multi(rest)
|
||||
try_parse_multi(
|
||||
[
|
||||
{"callback", code_without_c},
|
||||
{"type", code_without_type},
|
||||
{"dsl", code_without_dsl},
|
||||
{nil, code}
|
||||
],
|
||||
libraries,
|
||||
current_module
|
||||
)
|
||||
end
|
||||
|
||||
defp try_parse_multi([{text, code} | rest]) do
|
||||
defp try_parse_multi([{_, nil} | rest], libraries, current_module),
|
||||
do: try_parse_multi(rest, libraries, current_module)
|
||||
|
||||
defp try_parse_multi([{"dsl", code} | rest], libraries, current_module) do
|
||||
code = String.trim(code)
|
||||
|
||||
with [code | maybe_anchor] when length(rest) in [0, 1] <- String.split(code, "|", trim: true),
|
||||
{module, dsl_path} <-
|
||||
code
|
||||
|> String.split(".")
|
||||
|> Enum.split_while(&capitalized?/1) do
|
||||
if module == [] and !current_module do
|
||||
~s[<code class="inline">#{code}</code>]
|
||||
else
|
||||
anchor =
|
||||
case maybe_anchor do
|
||||
[] ->
|
||||
""
|
||||
|
||||
option ->
|
||||
"##{option}"
|
||||
end
|
||||
|
||||
module =
|
||||
case module do
|
||||
[] ->
|
||||
current_module
|
||||
|
||||
module ->
|
||||
Enum.join(module, ".")
|
||||
end
|
||||
|
||||
dsl_dots = Enum.join(dsl_path, ".")
|
||||
dsl_path = Enum.join(dsl_path, "/")
|
||||
|
||||
code =
|
||||
~s[<code class="inline maybe-dsl text-black dark:text-white" data-module="#{module}" data-dsl="#{dsl_dots}">#{code}</code>]
|
||||
|
||||
case library_for(module, libraries) do
|
||||
nil ->
|
||||
code
|
||||
|
||||
library ->
|
||||
link =
|
||||
url(
|
||||
~p'/docs/dsl/#{library.name}/latest/#{AshHqWeb.DocRoutes.sanitize_name(module)}'
|
||||
) <> "/" <> dsl_path <> anchor
|
||||
|
||||
~s[<a href="#{link}">#{code}</a>]
|
||||
end
|
||||
end
|
||||
else
|
||||
_ ->
|
||||
~s[<code class="inline">#{code}</code>]
|
||||
end
|
||||
end
|
||||
|
||||
defp try_parse_multi([{type, code} | rest], libraries, current_module) do
|
||||
case Code.string_to_quoted(code) do
|
||||
{:ok, {fun, _, []}} when is_atom(fun) ->
|
||||
~s[<code #{text} class="inline maybe-local-call text-black dark:text-white" data-fun="#{fun}">#{code}</code>]
|
||||
arity = 0
|
||||
|
||||
if current_module do
|
||||
function_href(
|
||||
~s[<code #{function_type(type)} class="inline maybe-call text-black dark:text-white" data-module="#{current_module}" data-fun="#{fun}" data-arity="#{arity}">#{code}</code>],
|
||||
libraries,
|
||||
type,
|
||||
current_module,
|
||||
fun,
|
||||
arity
|
||||
)
|
||||
else
|
||||
~s[<code #{function_type(type)} class="inline maybe-local-call text-black dark:text-white" data-fun="#{fun}" data-arity="#{arity}">#{code}</code>]
|
||||
end
|
||||
|
||||
{:ok,
|
||||
{:/, _,
|
||||
|
@ -94,19 +269,44 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Highlighter do
|
|||
arity
|
||||
]}}
|
||||
when is_atom(fun) and is_integer(arity) ->
|
||||
~s[<code #{text} class="inline maybe-call text-black dark:text-white" data-module="#{Enum.join(parts, ".")}" data-fun="#{fun}" data-arity="#{arity}">#{code}</code>]
|
||||
function_href(
|
||||
~s[<code #{function_type(type)} class="inline maybe-call text-black dark:text-white" data-module="#{Enum.join(parts, ".")}" data-fun="#{fun}" data-arity="#{arity}">#{code}</code>],
|
||||
libraries,
|
||||
type,
|
||||
Enum.join(parts, "."),
|
||||
fun,
|
||||
arity
|
||||
)
|
||||
|
||||
{:ok, {:/, _, [{fun, _, nil}, arity]}} when is_atom(fun) and is_integer(arity) ->
|
||||
~s[<code #{text} class="inline maybe-local-call text-black dark:text-white" data-fun="#{fun}" data-arity="#{arity}">#{code}</code>]
|
||||
function_href(
|
||||
if current_module do
|
||||
~s[<code #{function_type(type)} class="inline maybe-call text-black dark:text-white" data-module="#{current_module}" data-fun="#{fun}" data-arity="#{arity}">#{code}</code>]
|
||||
else
|
||||
~s[<code #{function_type(type)} class="inline maybe-local-call text-black dark:text-white" data-fun="#{fun}" data-arity="#{arity}">#{code}</code>]
|
||||
end,
|
||||
libraries,
|
||||
type,
|
||||
current_module,
|
||||
fun,
|
||||
arity
|
||||
)
|
||||
|
||||
{:ok, {:__aliases__, _, parts}} ->
|
||||
~s[<code #{text} class="inline maybe-module text-black dark:text-white" data-module="#{Enum.join(parts, ".")}">#{code}</code>]
|
||||
module_name = Enum.join(parts, ".")
|
||||
|
||||
module_href(
|
||||
~s[<code class="inline maybe-module text-black dark:text-white" data-module="#{module_name}">#{code}</code>],
|
||||
libraries,
|
||||
type,
|
||||
module_name
|
||||
)
|
||||
|
||||
_ ->
|
||||
if rest == [] do
|
||||
~s[<code class="inline text-black dark:text-white">#{code}</code>]
|
||||
else
|
||||
try_parse_multi(rest)
|
||||
try_parse_multi(rest, libraries, current_module)
|
||||
end
|
||||
end
|
||||
rescue
|
||||
|
@ -114,6 +314,63 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Highlighter do
|
|||
~s[<code class="inline">#{code}</code>]
|
||||
end
|
||||
|
||||
defp capitalized?(string) do
|
||||
str =
|
||||
string
|
||||
|> String.graphemes()
|
||||
|> Enum.at(0)
|
||||
|> Kernel.||("")
|
||||
|
||||
String.downcase(str) != str
|
||||
end
|
||||
|
||||
defp function_type(nil), do: nil
|
||||
|
||||
defp function_type(type) do
|
||||
"data-fun-type=\"#{type}\""
|
||||
end
|
||||
|
||||
defp function_href(contents, _libraries, nil, _, _, _), do: contents
|
||||
|
||||
defp function_href(contents, _libraries, _, nil, _, _), do: contents
|
||||
|
||||
defp function_href(contents, libraries, type, module_name, fun, arity) do
|
||||
case library_for(module_name, libraries) do
|
||||
nil ->
|
||||
contents
|
||||
|
||||
library ->
|
||||
link =
|
||||
url(
|
||||
~p'/docs/module/#{library.name}/latest/#{AshHqWeb.DocRoutes.sanitize_name(module_name)}'
|
||||
) <>
|
||||
"##{type}-#{AshHqWeb.DocRoutes.sanitize_name(fun)}-#{arity}"
|
||||
|
||||
~s[<a href="#{link}">#{contents}</a>]
|
||||
end
|
||||
end
|
||||
|
||||
defp module_href(contents, libraries, _type, module_name) do
|
||||
case library_for(module_name, libraries) do
|
||||
nil ->
|
||||
contents
|
||||
|
||||
library ->
|
||||
link =
|
||||
url(
|
||||
~p'/docs/module/#{library.name}/latest/#{AshHqWeb.DocRoutes.sanitize_name(module_name)}'
|
||||
)
|
||||
|
||||
~s[<a href="#{link}">#{contents}</a>]
|
||||
end
|
||||
end
|
||||
|
||||
defp library_for(module, libraries) do
|
||||
Enum.find(libraries, fn library ->
|
||||
Enum.any?(library.module_prefixes, &String.starts_with?(module, &1 <> "."))
|
||||
end)
|
||||
end
|
||||
|
||||
defp render_code(lang, lexer, lexer_opts, code) do
|
||||
highlighted =
|
||||
code
|
||||
|
@ -142,7 +399,7 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.Highlighter do
|
|||
"{{mix_dep:#{value}}}"
|
||||
end)
|
||||
|
||||
~s(<pre class="code-pre"><code class="makeup #{lang} highlight">#{highlighted}</code></pre>)
|
||||
~s(<code class="makeup #{lang} highlight">#{highlighted}</code>)
|
||||
end
|
||||
|
||||
entities = [{"&", ?&}, {"<", ?<}, {">", ?>}, {""", ?"}, {"'", ?'}]
|
||||
|
|
|
@ -32,50 +32,33 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown do
|
|||
Spark.Dsl.Extension.get_opt(resource, [:render_markdown], :header_ids?, [])
|
||||
end
|
||||
|
||||
def render!(%resource{} = record, key, on_demand? \\ false) do
|
||||
cond do
|
||||
render_attributes(resource)[key] ->
|
||||
Map.get(record, render_attributes(resource)[key])
|
||||
def as_html!(text, libraries, current_module, add_ids? \\ true)
|
||||
|
||||
on_demand? ->
|
||||
case Map.get(record, key) do
|
||||
value when is_list(value) ->
|
||||
Enum.map(value, fn value ->
|
||||
as_html!(value || "", header_ids?(resource))
|
||||
end)
|
||||
|
||||
value ->
|
||||
as_html!(value || "", header_ids?(resource))
|
||||
end
|
||||
|
||||
true ->
|
||||
raise "#{resource} dos not render #{key} as markdown. Pass the `on_demand?` argument as `true` to render it dynamically."
|
||||
end
|
||||
end
|
||||
|
||||
def as_html!(text, add_ids? \\ true)
|
||||
|
||||
def as_html!(nil, _) do
|
||||
def as_html!(nil, _, _, _) do
|
||||
""
|
||||
end
|
||||
|
||||
def as_html!(%Ash.NotLoaded{}, _) do
|
||||
def as_html!(%Ash.NotLoaded{}, _libraries, _, _) do
|
||||
""
|
||||
end
|
||||
|
||||
def as_html!(text, add_ids?) when is_list(text) do
|
||||
Enum.map(text, &as_html!(&1, add_ids?))
|
||||
def as_html!(text, libraries, current_module, add_ids?) when is_list(text) do
|
||||
Enum.map(text, &as_html!(&1, libraries, current_module, add_ids?))
|
||||
end
|
||||
|
||||
def as_html!(text, add_ids?) do
|
||||
def as_html!(text, libraries, current_library, current_module, add_ids?) do
|
||||
text
|
||||
|> Earmark.as_html!(opts(add_ids?))
|
||||
|> AshHq.Docs.Extensions.RenderMarkdown.Highlighter.highlight()
|
||||
|> AshHq.Docs.Extensions.RenderMarkdown.Highlighter.highlight(
|
||||
libraries,
|
||||
current_library,
|
||||
current_module
|
||||
)
|
||||
end
|
||||
|
||||
def as_html(text, add_ids?) when is_list(text) do
|
||||
def as_html(text, libraries, current_module, add_ids?) when is_list(text) do
|
||||
Enum.reduce_while(text, {:ok, [], []}, fn text, {:ok, list, errors} ->
|
||||
case as_html(text, add_ids?) do
|
||||
case as_html(text, libraries, current_module, add_ids?) do
|
||||
{:ok, text, new_errors} ->
|
||||
{:cont, {:ok, [text | list], errors ++ new_errors}}
|
||||
|
||||
|
@ -92,12 +75,18 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown do
|
|||
end
|
||||
end
|
||||
|
||||
def as_html(text, add_ids?) do
|
||||
def as_html(text, libraries, current_library, current_module, add_ids?) do
|
||||
text
|
||||
|> Earmark.as_html(opts(add_ids?))
|
||||
|> case do
|
||||
{:ok, html_doc, errors} ->
|
||||
{:ok, AshHq.Docs.Extensions.RenderMarkdown.Highlighter.highlight(html_doc), errors}
|
||||
{:ok,
|
||||
AshHq.Docs.Extensions.RenderMarkdown.Highlighter.highlight(
|
||||
html_doc,
|
||||
libraries,
|
||||
current_library,
|
||||
current_module
|
||||
), errors}
|
||||
|
||||
{:error, html_doc, errors} ->
|
||||
{:error, html_doc, errors}
|
||||
|
@ -105,7 +94,7 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown do
|
|||
end
|
||||
|
||||
defp opts(true) do
|
||||
[postprocessor: &add_ids/1]
|
||||
[postprocessor: &add_ids/1, escape: false]
|
||||
end
|
||||
|
||||
defp opts(_) do
|
||||
|
|
|
@ -46,7 +46,7 @@ defmodule AshHq.Docs.Importer do
|
|||
|> Enum.reject(&String.starts_with?(&1, "/_build"))
|
||||
|> Enum.join(":")
|
||||
|
||||
for %{name: name, latest_version: latest_version} = library <-
|
||||
for %{name: name, latest_version: latest_version, mix_project: mix_project} = library <-
|
||||
AshHq.Docs.Library.read!(load: :latest_version, query: query) do
|
||||
latest_version =
|
||||
if latest_version do
|
||||
|
@ -83,7 +83,6 @@ defmodule AshHq.Docs.Importer do
|
|||
|
||||
result =
|
||||
try do
|
||||
with_retry("#{name}: #{version}", fn ->
|
||||
{_, 0} =
|
||||
System.cmd(
|
||||
"elixir",
|
||||
|
@ -91,14 +90,14 @@ defmodule AshHq.Docs.Importer do
|
|||
Path.join([:code.priv_dir(:ash_hq), "scripts", "build_dsl_docs.exs"]),
|
||||
name,
|
||||
version,
|
||||
file
|
||||
file,
|
||||
mix_project || Macro.camelize(name) <> ".MixProject"
|
||||
],
|
||||
env: %{"PATH" => path_var}
|
||||
)
|
||||
|
||||
output = File.read!(file)
|
||||
:erlang.binary_to_term(Base.decode64!(String.trim(output)))
|
||||
end)
|
||||
after
|
||||
File.rm_rf!(file)
|
||||
end
|
||||
|
@ -125,7 +124,7 @@ defmodule AshHq.Docs.Importer do
|
|||
id: id,
|
||||
extensions: result[:extensions],
|
||||
doc: result[:doc],
|
||||
guides: add_text(result[:guides], library.name, version),
|
||||
guides: result[:guides],
|
||||
modules: result[:modules],
|
||||
mix_tasks: result[:mix_tasks]
|
||||
}
|
||||
|
@ -136,83 +135,6 @@ defmodule AshHq.Docs.Importer do
|
|||
end
|
||||
end
|
||||
|
||||
# sobelow_skip ["Misc.BinToTerm", "Traversal.FileModule"]
|
||||
defp add_text([], _, _), do: []
|
||||
|
||||
# sobelow_skip ["Misc.BinToTerm", "Traversal.FileModule"]
|
||||
defp add_text(guides, name, version) do
|
||||
path = Path.expand("tmp")
|
||||
tarball_path = Path.expand(Path.join(["tmp", "tarballs"]))
|
||||
tar_path = Path.join(tarball_path, "#{name}-#{version}.tar")
|
||||
untar_path = Path.join(path, "#{name}-#{version}")
|
||||
contents_untar_path = Path.join(path, "#{name}-#{version}/contents")
|
||||
contents_tar_path = Path.join([path, "#{name}-#{version}", "contents.tar.gz"])
|
||||
|
||||
try do
|
||||
File.rm_rf!(tar_path)
|
||||
File.rm_rf!(contents_untar_path)
|
||||
File.mkdir_p!(untar_path)
|
||||
File.mkdir_p!(contents_untar_path)
|
||||
|
||||
{_, 0} =
|
||||
System.cmd(
|
||||
"curl",
|
||||
[
|
||||
"-L",
|
||||
"--create-dirs",
|
||||
"-o",
|
||||
"#{tar_path}",
|
||||
"https://repo.hex.pm/tarballs/#{name}-#{version}.tar"
|
||||
]
|
||||
)
|
||||
|
||||
{_, 0} =
|
||||
System.cmd(
|
||||
"tar",
|
||||
[
|
||||
"-xf",
|
||||
tar_path,
|
||||
"-C",
|
||||
untar_path
|
||||
],
|
||||
cd: "tmp"
|
||||
)
|
||||
|
||||
{_, 0} =
|
||||
System.cmd(
|
||||
"tar",
|
||||
[
|
||||
"-xzf",
|
||||
contents_tar_path
|
||||
],
|
||||
cd: contents_untar_path
|
||||
)
|
||||
|
||||
Enum.map(guides, fn %{path: path} = guide ->
|
||||
contents =
|
||||
contents_untar_path
|
||||
|> Path.join(path)
|
||||
|> File.read!()
|
||||
|
||||
Map.put(guide, :text, contents)
|
||||
end)
|
||||
after
|
||||
File.rm_rf!(tar_path)
|
||||
File.rm_rf!(untar_path)
|
||||
end
|
||||
end
|
||||
|
||||
defp with_retry(context, func, retries \\ 3) do
|
||||
func.()
|
||||
rescue
|
||||
_e ->
|
||||
if retries == 1 do
|
||||
Logger.error("Failed to import: #{context}")
|
||||
else
|
||||
with_retry(context, func, retries - 1)
|
||||
end
|
||||
end
|
||||
|
||||
defp filter_by_version(versions, latest_version) do
|
||||
if latest_version do
|
||||
Enum.take_while(versions, fn version ->
|
||||
|
|
|
@ -27,10 +27,6 @@ defmodule AshHq.Docs.Dsl do
|
|||
default []
|
||||
end
|
||||
|
||||
attribute :links, :map do
|
||||
default %{}
|
||||
end
|
||||
|
||||
attribute :examples, {:array, :string}
|
||||
attribute :args, {:array, :string}
|
||||
attribute :optional_args, {:array, :string} do
|
||||
|
|
|
@ -25,6 +25,13 @@ defmodule AshHq.Docs.Library do
|
|||
default "ash-project"
|
||||
end
|
||||
|
||||
attribute :module_prefixes, {:array, :string} do
|
||||
allow_nil? false
|
||||
default []
|
||||
end
|
||||
|
||||
attribute :mix_project, :string
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
|
@ -35,6 +42,8 @@ defmodule AshHq.Docs.Library do
|
|||
postgres do
|
||||
table "libraries"
|
||||
repo AshHq.Repo
|
||||
|
||||
migration_defaults module_prefixes: "[]"
|
||||
end
|
||||
|
||||
actions do
|
||||
|
|
|
@ -12,6 +12,11 @@ defmodule AshHq.Docs.LibraryVersion do
|
|||
allow_nil? false
|
||||
end
|
||||
|
||||
attribute :hydrated, :boolean do
|
||||
default false
|
||||
allow_nil? false
|
||||
end
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
|
|
34
lib/ash_hq/simple_postgres_cache.ex
Normal file
34
lib/ash_hq/simple_postgres_cache.ex
Normal file
|
@ -0,0 +1,34 @@
|
|||
# defmodule AshHq.Docs.SimplePostgresCache do
|
||||
# @moduledoc """
|
||||
# Simple experimental key/value based cache on top of the postgres data layer.
|
||||
|
||||
# Will be problematic if used with queries that reference things like
|
||||
# the current time.
|
||||
# """
|
||||
# @behaviour Ash.DataLayer
|
||||
|
||||
# Code.ensure_compiled!(AshPostgres.DataLayer)
|
||||
|
||||
# for {function, arity} <- Ash.DataLayer.behaviour_info(:callbacks) do
|
||||
# arguments = Macro.generate_unique_arguments(arity, __MODULE__)
|
||||
|
||||
# case {function, arity} do
|
||||
# {:run_query, 2} ->
|
||||
# def run_query(query, _resource) do
|
||||
# if query.__ash_bindings__.context[:data_layer][:cache?] do
|
||||
# case AshHq.Docs.Cache.get(query) do
|
||||
# nil ->
|
||||
|
||||
# end
|
||||
# else
|
||||
|
||||
# end
|
||||
# end
|
||||
|
||||
# _ ->
|
||||
# if function_exported?(AshPostgres.DataLayer, function, arity) do
|
||||
# defdelegate unquote(function)(unquote_splicing(arguments)), to: AshPostgres.DataLayer
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
# end
|
|
@ -32,7 +32,7 @@ defmodule AshHqWeb.Components.Docs.Functions do
|
|||
</div>
|
||||
</div>
|
||||
<div class="p-4">
|
||||
{raw(rendered(@libraries, @selected_versions, function.html_for))}
|
||||
{raw(rendered(function.html_for))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -41,9 +41,8 @@ defmodule AshHqWeb.Components.Docs.Functions do
|
|||
"""
|
||||
end
|
||||
|
||||
defp rendered(libraries, selected_versions, html_for) do
|
||||
libraries
|
||||
|> render_replacements(selected_versions, html_for)
|
||||
defp rendered(html_for) do
|
||||
html_for
|
||||
|> String.split("<!--- heads-end -->")
|
||||
|> case do
|
||||
[] ->
|
||||
|
|
|
@ -11,29 +11,29 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
alias Surface.Components.LivePatch
|
||||
require Logger
|
||||
|
||||
prop change_versions, :event, required: true
|
||||
prop selected_versions, :map, required: true
|
||||
prop libraries, :list, default: []
|
||||
prop uri, :string
|
||||
prop remove_version, :event
|
||||
prop add_version, :event
|
||||
prop change_version, :event
|
||||
prop params, :map, required: true
|
||||
prop(change_versions, :event, required: true)
|
||||
prop(selected_versions, :map, required: true)
|
||||
prop(libraries, :list, default: [])
|
||||
prop(uri, :string)
|
||||
prop(remove_version, :event)
|
||||
prop(add_version, :event)
|
||||
prop(change_version, :event)
|
||||
prop(params, :map, required: true)
|
||||
|
||||
data library, :any
|
||||
data extension, :any
|
||||
data docs, :any
|
||||
data library_version, :any
|
||||
data guide, :any
|
||||
data doc_path, :list, default: []
|
||||
data dsls, :list, default: []
|
||||
data dsl, :any
|
||||
data options, :list, default: []
|
||||
data module, :any
|
||||
data mix_task, :any
|
||||
data positional_options, :list
|
||||
data description, :string
|
||||
data title, :string
|
||||
data(library, :any)
|
||||
data(extension, :any)
|
||||
data(docs, :any)
|
||||
data(library_version, :any)
|
||||
data(guide, :any)
|
||||
data(doc_path, :list, default: [])
|
||||
data(dsls, :list, default: [])
|
||||
data(dsl, :any)
|
||||
data(options, :list, default: [])
|
||||
data(module, :any)
|
||||
data(mix_task, :any)
|
||||
data(positional_options, :list)
|
||||
data(description, :string)
|
||||
data(title, :string)
|
||||
|
||||
@spec render(any) :: Phoenix.LiveView.Rendered.t()
|
||||
def render(assigns) do
|
||||
|
@ -133,18 +133,6 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
{/for}
|
||||
</ul>
|
||||
{/if}
|
||||
{#if @dsl}
|
||||
{#for {category, links} <- @dsl.links || %{}}
|
||||
<h3>{String.capitalize(category)}</h3>
|
||||
<ul>
|
||||
{#for link <- links}
|
||||
<li>
|
||||
{raw(render_replacements(@libraries, @selected_versions, "{{link:#{link}}}"))}
|
||||
</li>
|
||||
{/for}
|
||||
</ul>
|
||||
{/for}
|
||||
{/if}
|
||||
</div>
|
||||
{#if @module}
|
||||
<Functions
|
||||
|
@ -226,7 +214,6 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
<th>Default</th>
|
||||
{/if}
|
||||
<th>Doc</th>
|
||||
<th>Links</th>
|
||||
</tr>
|
||||
{#for option <- positional_options(@options)}
|
||||
<tr id={"#{option.sanitized_path}/#{option.name}"}>
|
||||
|
@ -237,7 +224,10 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
</LivePatch>
|
||||
<div class="flex flex-row space-x-2">
|
||||
<CalloutText text={option.name} />
|
||||
{render_tags(assigns, %{option | required: option.required && !Map.has_key?(@dsl.arg_defaults, option.name)})}
|
||||
{render_tags(assigns, %{
|
||||
option
|
||||
| required: option.required && !Map.has_key?(@dsl.arg_defaults || %{}, option.name)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
@ -245,20 +235,11 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
{option.type}
|
||||
</td>
|
||||
{#if @dsl.arg_defaults not in [%{}, nil]}
|
||||
<th>{Map.get(@dsl.arg_defaults, option.name)}</th>
|
||||
<th>{Map.get(@dsl.arg_defaults || %{}, option.name)}</th>
|
||||
{/if}
|
||||
<td>
|
||||
{raw(render_replacements(@libraries, @selected_versions, option.html_for))}
|
||||
</td>
|
||||
<td>
|
||||
{raw(
|
||||
Enum.map_join(
|
||||
List.flatten(Map.values(option.links || %{})),
|
||||
", ",
|
||||
&render_replacements(@libraries, @selected_versions, "{{link:#{&1}}}")
|
||||
)
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
{/for}
|
||||
{/if}
|
||||
|
@ -274,7 +255,6 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
<th>Type</th>
|
||||
<th>Default</th>
|
||||
<th>Doc</th>
|
||||
<th>Links</th>
|
||||
</tr>
|
||||
{#for %{argument_index: nil} = option <- @options}
|
||||
<tr id={"#{option.sanitized_path}/#{option.name}"}>
|
||||
|
@ -296,15 +276,6 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
<td>
|
||||
{raw(render_replacements(@libraries, @selected_versions, option.html_for))}
|
||||
</td>
|
||||
<td>
|
||||
{raw(
|
||||
Enum.map_join(
|
||||
List.flatten(Map.values(option.links || %{})),
|
||||
", ",
|
||||
&render_replacements(@libraries, @selected_versions, "{{link:#{&1}}}")
|
||||
)
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
{/for}
|
||||
{/if}
|
||||
|
@ -490,7 +461,9 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
AshHq.Docs.Extension
|
||||
|> Ash.Query.sort(order: :asc)
|
||||
|> Ash.Query.load(options: options_query, dsls: dsls_query)
|
||||
|> load_for_search(socket.assigns[:params]["extension"])
|
||||
|> load_for_search(
|
||||
socket.assigns[:params]["extension"] || socket.assigns[:params]["module"]
|
||||
)
|
||||
|
||||
new_libraries =
|
||||
socket.assigns.libraries
|
||||
|
@ -682,10 +655,23 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
socket.assigns[:params]["extension"]
|
||||
end)
|
||||
)
|
||||
else
|
||||
if socket.assigns.library_version && socket.assigns[:params]["module"] do
|
||||
extensions = socket.assigns.library_version.extensions
|
||||
|
||||
assign(socket,
|
||||
extension:
|
||||
Enum.find(extensions, fn extension ->
|
||||
extension.sanitized_name == socket.assigns[:params]["module"] ||
|
||||
AshHqWeb.DocRoutes.sanitize_name(extension.target) ==
|
||||
socket.assigns[:params]["module"]
|
||||
end)
|
||||
)
|
||||
else
|
||||
assign(socket, :extension, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp assign_guide(socket) do
|
||||
guide_route = socket.assigns[:params]["guide"]
|
||||
|
@ -734,7 +720,7 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
end
|
||||
|
||||
defp assign_module(socket) do
|
||||
if socket.assigns.library && socket.assigns.library_version &&
|
||||
if !socket.assigns.extension && socket.assigns.library && socket.assigns.library_version &&
|
||||
socket.assigns[:params]["module"] do
|
||||
module =
|
||||
Enum.find(
|
||||
|
@ -775,6 +761,8 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
defp assign_docs(socket) do
|
||||
cond do
|
||||
socket.assigns.module ->
|
||||
send(self(), {:page_title, socket.assigns.module.name})
|
||||
|
||||
assign(socket,
|
||||
docs: socket.assigns.module.html_for,
|
||||
title: "Module: #{socket.assigns.module.name}",
|
||||
|
@ -784,6 +772,8 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
)
|
||||
|
||||
socket.assigns.mix_task ->
|
||||
send(self(), {:page_title, socket.assigns.module.name})
|
||||
|
||||
assign(socket,
|
||||
docs: socket.assigns.mix_task.html_for,
|
||||
title: "Mix Task: #{socket.assigns.mix_task.name}",
|
||||
|
@ -793,6 +783,8 @@ defmodule AshHqWeb.Pages.Docs do
|
|||
)
|
||||
|
||||
socket.assigns.dsl ->
|
||||
send(self(), {:page_title, socket.assigns.module.name})
|
||||
|
||||
meta_name =
|
||||
Enum.join(
|
||||
[
|
||||
|
|
|
@ -5,37 +5,39 @@ defmodule AshHqWeb.Router do
|
|||
import AshAdmin.Router
|
||||
|
||||
pipeline :browser do
|
||||
plug :accepts, ["html"]
|
||||
plug :fetch_session
|
||||
plug :fetch_live_flash
|
||||
plug :put_root_layout, {AshHqWeb.LayoutView, :root}
|
||||
plug :protect_from_forgery
|
||||
plug AshHqWeb.SessionPlug
|
||||
plug :assign_user_agent
|
||||
plug :load_from_session
|
||||
plug(:accepts, ["html"])
|
||||
plug(:fetch_session)
|
||||
plug(:fetch_live_flash)
|
||||
plug(:put_root_layout, {AshHqWeb.LayoutView, :root})
|
||||
plug(:protect_from_forgery)
|
||||
plug(AshHqWeb.SessionPlug)
|
||||
plug(:assign_user_agent)
|
||||
plug(:load_from_session)
|
||||
end
|
||||
|
||||
pipeline :api do
|
||||
plug :accepts, ["json"]
|
||||
plug :load_from_bearer
|
||||
plug(:accepts, ["json"])
|
||||
plug(:load_from_bearer)
|
||||
end
|
||||
|
||||
pipeline :admin_basic_auth do
|
||||
plug :basic_auth
|
||||
plug(:basic_auth)
|
||||
end
|
||||
|
||||
scope "/", AshHqWeb do
|
||||
pipe_through :browser
|
||||
reset_route []
|
||||
pipe_through(:browser)
|
||||
reset_route([])
|
||||
|
||||
sign_in_route overrides: [AshHqWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default]
|
||||
sign_in_route(
|
||||
overrides: [AshHqWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default]
|
||||
)
|
||||
|
||||
sign_out_route AuthController
|
||||
sign_out_route(AuthController)
|
||||
auth_routes_for(AshHq.Accounts.User, to: AuthController)
|
||||
end
|
||||
|
||||
scope "/", AshHqWeb do
|
||||
pipe_through :browser
|
||||
pipe_through(:browser)
|
||||
|
||||
live_session :main,
|
||||
on_mount: [
|
||||
|
@ -45,21 +47,21 @@ defmodule AshHqWeb.Router do
|
|||
],
|
||||
session: {AshAuthentication.Phoenix.LiveSession, :generate_session, []},
|
||||
root_layout: {AshHqWeb.LayoutView, :root} do
|
||||
live "/", AppViewLive, :home
|
||||
live "/media", AppViewLive, :media
|
||||
live "/blog", AppViewLive, :blog
|
||||
live "/blog/:slug", AppViewLive, :blog
|
||||
live "/docs/", AppViewLive, :docs_dsl
|
||||
live "/docs/guides/:library/:version/*guide", AppViewLive, :docs_dsl
|
||||
live "/docs/dsl/:library", AppViewLive, :docs_dsl
|
||||
live "/docs/dsl/:library/:version", AppViewLive, :docs_dsl
|
||||
live "/docs/dsl/:library/:version/:extension", AppViewLive, :docs_dsl
|
||||
live "/docs/dsl/:library/:version/:extension/*dsl_path", AppViewLive, :docs_dsl
|
||||
live "/docs/module/:library/:version/:module", AppViewLive, :docs_dsl
|
||||
live "/docs/mix_task/:library/:version/:mix_task", AppViewLive, :docs_dsl
|
||||
live "/docs/:library/:version", AppViewLive, :docs_dsl
|
||||
live("/", AppViewLive, :home)
|
||||
live("/media", AppViewLive, :media)
|
||||
live("/blog", AppViewLive, :blog)
|
||||
live("/blog/:slug", AppViewLive, :blog)
|
||||
live("/docs/", AppViewLive, :docs_dsl)
|
||||
live("/docs/guides/:library/:version/*guide", AppViewLive, :docs_dsl)
|
||||
live("/docs/dsl/:library", AppViewLive, :docs_dsl)
|
||||
live("/docs/dsl/:library/:version", AppViewLive, :docs_dsl)
|
||||
live("/docs/dsl/:library/:version/:extension", AppViewLive, :docs_dsl)
|
||||
live("/docs/dsl/:library/:version/:extension/*dsl_path", AppViewLive, :docs_dsl)
|
||||
live("/docs/module/:library/:version/:module", AppViewLive, :docs_dsl)
|
||||
live("/docs/mix_task/:library/:version/:mix_task", AppViewLive, :docs_dsl)
|
||||
live("/docs/:library/:version", AppViewLive, :docs_dsl)
|
||||
|
||||
get "/unsubscribe", MailingListController, :unsubscribe
|
||||
get("/unsubscribe", MailingListController, :unsubscribe)
|
||||
end
|
||||
|
||||
live_session :authenticated_only,
|
||||
|
@ -70,20 +72,22 @@ defmodule AshHqWeb.Router do
|
|||
],
|
||||
session: {AshAuthentication.Phoenix.LiveSession, :generate_session, []},
|
||||
root_layout: {AshHqWeb.LayoutView, :root} do
|
||||
live "/users/settings", AppViewLive, :user_settings
|
||||
live("/users/settings", AppViewLive, :user_settings)
|
||||
end
|
||||
end
|
||||
|
||||
get "/rss", AshHqWeb.RssController, :rss
|
||||
get("/rss", AshHqWeb.RssController, :rss)
|
||||
|
||||
## Api routes
|
||||
scope "/" do
|
||||
forward "/gql", Absinthe.Plug, schema: AshHqWeb.Schema
|
||||
forward("/gql", Absinthe.Plug, schema: AshHqWeb.Schema)
|
||||
|
||||
forward "/playground",
|
||||
forward(
|
||||
"/playground",
|
||||
Absinthe.Plug.GraphiQL,
|
||||
schema: AshHqWeb.Schema,
|
||||
interface: :playground
|
||||
)
|
||||
end
|
||||
|
||||
# Enables LiveDashboard only for development
|
||||
|
@ -97,17 +101,18 @@ defmodule AshHqWeb.Router do
|
|||
|
||||
scope "/" do
|
||||
if Mix.env() in [:dev, :test] do
|
||||
pipe_through [:browser]
|
||||
pipe_through([:browser])
|
||||
else
|
||||
pipe_through [:browser, :admin_basic_auth]
|
||||
pipe_through([:browser, :admin_basic_auth])
|
||||
end
|
||||
|
||||
ash_admin("/admin")
|
||||
|
||||
live_dashboard "/dashboard",
|
||||
live_dashboard("/dashboard",
|
||||
metrics: AshHqWeb.Telemetry,
|
||||
ecto_repos: [AshHq.Repo],
|
||||
ecto_psql_extras_options: [long_running_queries: [threshold: "200 milliseconds"]]
|
||||
)
|
||||
end
|
||||
|
||||
# Enables the Swoosh mailbox preview in development.
|
||||
|
@ -116,9 +121,9 @@ defmodule AshHqWeb.Router do
|
|||
# node running the Phoenix server.
|
||||
if Mix.env() == :dev do
|
||||
scope "/dev" do
|
||||
pipe_through [:browser]
|
||||
pipe_through([:browser])
|
||||
|
||||
forward "/mailbox", Plug.Swoosh.MailboxPreview
|
||||
forward("/mailbox", Plug.Swoosh.MailboxPreview)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -12,22 +12,22 @@ defmodule AshHqWeb.AppViewLive do
|
|||
|
||||
import AshHqWeb.Tails
|
||||
|
||||
data configured_theme, :string, default: :system
|
||||
data selected_versions, :map, default: %{}
|
||||
data libraries, :list, default: []
|
||||
data selected_types, :map, default: %{}
|
||||
data current_user, :map
|
||||
data(configured_theme, :string, default: :system)
|
||||
data(selected_versions, :map, default: %{})
|
||||
data(libraries, :list, default: [])
|
||||
data(selected_types, :map, default: %{})
|
||||
data(current_user, :map)
|
||||
|
||||
data library, :any, default: nil
|
||||
data extension, :any, default: nil
|
||||
data docs, :any, default: nil
|
||||
data library_version, :any, default: nil
|
||||
data guide, :any, default: nil
|
||||
data doc_path, :list, default: []
|
||||
data dsls, :list, default: []
|
||||
data dsl, :any, default: nil
|
||||
data options, :list, default: []
|
||||
data module, :any, default: nil
|
||||
data(library, :any, default: nil)
|
||||
data(extension, :any, default: nil)
|
||||
data(docs, :any, default: nil)
|
||||
data(library_version, :any, default: nil)
|
||||
data(guide, :any, default: nil)
|
||||
data(doc_path, :list, default: [])
|
||||
data(dsls, :list, default: [])
|
||||
data(dsl, :any, default: nil)
|
||||
data(options, :list, default: [])
|
||||
data(module, :any, default: nil)
|
||||
|
||||
def render(%{platform: :ios} = assigns) do
|
||||
~F"""
|
||||
|
@ -85,7 +85,7 @@ defmodule AshHqWeb.AppViewLive do
|
|||
<div
|
||||
id="main-container"
|
||||
class={
|
||||
"w-full min-g-screen bg-white dark:bg-base-dark-850 dark:text-white flex flex-col items-stretch",
|
||||
"w-full min-h-screen bg-white dark:bg-base-dark-850 dark:text-white flex flex-col items-stretch",
|
||||
"h-screen overflow-y-auto": @live_action != :docs_dsl
|
||||
}
|
||||
>
|
||||
|
@ -186,6 +186,10 @@ defmodule AshHqWeb.AppViewLive do
|
|||
|> assign(params: params, uri: uri)}
|
||||
end
|
||||
|
||||
def handle_info({:page_title, title}, socket) do
|
||||
assign(socket, :page_title, "Ash Framework - #{title}")
|
||||
end
|
||||
|
||||
def handle_event("remove_version", %{"library" => library}, socket) do
|
||||
new_selected_versions = Map.put(socket.assigns.selected_versions, library, "")
|
||||
|
||||
|
@ -248,6 +252,8 @@ defmodule AshHqWeb.AppViewLive do
|
|||
end
|
||||
|
||||
def mount(_params, session, socket) do
|
||||
socket = assign(socket, :page_title, "Ash Framework")
|
||||
|
||||
socket =
|
||||
assign_new(socket, :user_agent, fn _assigns ->
|
||||
get_connect_params(socket)["user_agent"]
|
||||
|
|
8
mix.exs
8
mix.exs
|
@ -40,15 +40,12 @@ defmodule AshHq.MixProject do
|
|||
defp deps do
|
||||
[
|
||||
{:ash, github: "ash-project/ash", override: true},
|
||||
{:ash_postgres, "~> 1.1"},
|
||||
{:ash_postgres, github: "ash-project/ash_postgres"},
|
||||
{:ash_admin, github: "ash-project/ash_admin"},
|
||||
{:ash_phoenix, github: "ash-project/ash_phoenix", override: true},
|
||||
{:ash_graphql, github: "ash-project/ash_graphql"},
|
||||
{:ash_json_api, github: "ash-project/ash_json_api"},
|
||||
{:ash_authentication,
|
||||
branch: "set-confirmed-field-to-nil",
|
||||
github: "team-alembic/ash_authentication",
|
||||
override: true},
|
||||
{:ash_authentication, github: "team-alembic/ash_authentication", override: true},
|
||||
{:ash_authentication_phoenix, github: "team-alembic/ash_authentication_phoenix"},
|
||||
{:absinthe_plug, "~> 1.5"},
|
||||
{:ash_blog, github: "ash-project/ash_blog"},
|
||||
|
@ -61,6 +58,7 @@ defmodule AshHq.MixProject do
|
|||
{:surface, "~> 0.9.1"},
|
||||
{:surface_heroicons, "~> 0.6.0"},
|
||||
{:ua_inspector, "~> 3.0"},
|
||||
{:nebulex, "~> 2.4"},
|
||||
# Syntax Highlighting
|
||||
{:elixir_sense, github: "elixir-lsp/elixir_sense", only: [:dev, :test]},
|
||||
{:makeup, "~> 1.1"},
|
||||
|
|
26
mix.lock
26
mix.lock
|
@ -1,16 +1,16 @@
|
|||
%{
|
||||
"absinthe": {:hex, :absinthe, "1.7.0", "36819e7b1fd5046c9c734f27fe7e564aed3bda59f0354c37cd2df88fd32dd014", [:mix], [{:dataloader, "~> 1.0.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0 or ~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "566a5b5519afc9b29c4d367f0c6768162de3ec03e9bf9916f9dc2bcbe7c09643"},
|
||||
"absinthe_plug": {:hex, :absinthe_plug, "1.5.8", "38d230641ba9dca8f72f1fed2dfc8abd53b3907d1996363da32434ab6ee5d6ab", [:mix], [{:absinthe, "~> 1.5", [hex: :absinthe, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bbb04176647b735828861e7b2705465e53e2cf54ccf5a73ddd1ebd855f996e5a"},
|
||||
"ash": {:git, "https://github.com/ash-project/ash.git", "1eaeacc7486e50d70138baaf65133cef5e8b5869", []},
|
||||
"ash": {:git, "https://github.com/ash-project/ash.git", "22e07c06b5e0da531e7e6f632009290031429875", []},
|
||||
"ash_admin": {:git, "https://github.com/ash-project/ash_admin.git", "cdb3b469abeeadddda884e7cfcf67c6fea10f9ef", []},
|
||||
"ash_authentication": {:git, "https://github.com/team-alembic/ash_authentication.git", "5acbaeeb9c53f9953f5018dd59aff8176561460f", [branch: "set-confirmed-field-to-nil"]},
|
||||
"ash_authentication_phoenix": {:git, "https://github.com/team-alembic/ash_authentication_phoenix.git", "fbe5272f874532b3119033ddb1dfb49d71f7b571", []},
|
||||
"ash_authentication": {:git, "https://github.com/team-alembic/ash_authentication.git", "d4f3bec947b3cef160fa8e6768396884a3ee6149", []},
|
||||
"ash_authentication_phoenix": {:git, "https://github.com/team-alembic/ash_authentication_phoenix.git", "14c38739cf56c4821797963b9ee261597a261b00", []},
|
||||
"ash_blog": {:git, "https://github.com/ash-project/ash_blog.git", "9254773dfedabfc7987af6326a62885c24c3655b", []},
|
||||
"ash_csv": {:git, "https://github.com/ash-project/ash_csv.git", "77187f6e4505ed4d88598bf87e56983a6a74a456", []},
|
||||
"ash_graphql": {:git, "https://github.com/ash-project/ash_graphql.git", "09fe8ce9bbbdf03d12b17e5037235a7752326e59", []},
|
||||
"ash_json_api": {:git, "https://github.com/ash-project/ash_json_api.git", "5594f18d07d0771b4bc8b3d3db99cc8c08958a66", []},
|
||||
"ash_csv": {:git, "https://github.com/ash-project/ash_csv.git", "2a068cea47d13065f23a3686f4c28bf875353ffd", []},
|
||||
"ash_graphql": {:git, "https://github.com/ash-project/ash_graphql.git", "c0f5f596cb0dad47f0e83e2be2411210a2d97112", []},
|
||||
"ash_json_api": {:git, "https://github.com/ash-project/ash_json_api.git", "bfd80c2083a5ce0f61fa128e011ddf9a6e41bc14", []},
|
||||
"ash_phoenix": {:git, "https://github.com/ash-project/ash_phoenix.git", "b205c9bb4f153f855420f11d766cfe515930631e", []},
|
||||
"ash_postgres": {:hex, :ash_postgres, "1.2.2", "0da0d9e1878f8b24829a8971e497e7bafe5596aced3604ba39d96e70174a8b11", [:mix], [{:ash, ">= 2.4.0", [hex: :ash, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.9", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.5", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "8796f1de22863451a445f33a0874904145efeecfff75175f6c1ce62754c8df4e"},
|
||||
"ash_postgres": {:git, "https://github.com/ash-project/ash_postgres.git", "7bf4cf80b17e04378fa85773435a5ac559e56c54", []},
|
||||
"assent": {:hex, :assent, "0.2.1", "46ad0ed92b72330f38c60bc03c528e8408475dc386f48d4ecd18833cfa581b9f", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, ">= 0.0.0", [hex: :certifi, repo: "hexpm", optional: true]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: true]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:ssl_verify_fun, ">= 0.0.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: true]}], "hexpm", "58c558b6029ffa287e15b38c8e07cd99f0b24e4846c52abad0c0a6225c4873bc"},
|
||||
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.0.1", "9be815469e6bfefec40fa74658ecbbe6897acfb57614df1416eeccd4903f602c", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "486bb95efb645d1efc6794c1ddd776a186a9a713abf06f45708a6ce324fb96cf"},
|
||||
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
|
||||
|
@ -30,13 +30,14 @@
|
|||
"db_connection": {:hex, :db_connection, "2.4.3", "3b9aac9f27347ec65b271847e6baeb4443d8474289bd18c1d6f4de655b70c94d", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c127c15b0fa6cfb32eed07465e05da6c815b032508d4ed7c116122871df73c12"},
|
||||
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
|
||||
"dialyxir": {:hex, :dialyxir, "1.2.0", "58344b3e87c2e7095304c81a9ae65cb68b613e28340690dfe1a5597fd08dec37", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "61072136427a851674cab81762be4dbeae7679f85b1272b6d25c3a839aff8463"},
|
||||
"doctor": {:hex, :doctor, "0.21.0", "20ef89355c67778e206225fe74913e96141c4d001cb04efdeba1a2a9704f1ab5", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "a227831daa79784eb24cdeedfa403c46a4cb7d0eab0e31232ec654314447e4e0"},
|
||||
"earmark": {:hex, :earmark, "1.5.0-pre1", "e04aca73692bc3cda3429d6df99c8dae2bf76411e5e76d006a4bc04ac81ef1c1", [:mix], [{:earmark_parser, "~> 1.4.21", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "26ec0473ad2ef995b9672f89309a7a4952887f69b78cfc7af14e320bc6546bfa"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"},
|
||||
"ecto": {:hex, :ecto, "3.9.4", "3ee68e25dbe0c36f980f1ba5dd41ee0d3eb0873bccae8aeaf1a2647242bffa35", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "de5f988c142a3aa4ec18b85a4ec34a2390b65b24f02385c1144252ff6ff8ee75"},
|
||||
"ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.10", "e14d400930f401ca9f541b3349212634e44027d7f919bbb71224d7ac0d0e8acd", [:mix], [{:ecto_sql, "~> 3.4", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.15.7 or ~> 0.16.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "505e8cd81e4f17c090be0f99e92b1b3f0fd915f98e76965130b8ccfb891e7088"},
|
||||
"ecto_sql": {:hex, :ecto_sql, "3.9.2", "34227501abe92dba10d9c3495ab6770e75e79b836d114c41108a4bf2ce200ad5", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1eb5eeb4358fdbcd42eac11c1fbd87e3affd7904e639d77903c1358b2abd3f70"},
|
||||
"eflame": {:hex, :eflame, "1.0.1", "0664d287e39eef3c413749254b3af5f4f8b00be71c1af67d325331c4890be0fc", [:mix], [], "hexpm", "e0b08854a66f9013129de0b008488f3411ae9b69b902187837f994d7a99cf04e"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.7.3", "c37fdae1b52d2cc51069713a58c2314877c1ad40800a57efb213f77b078a460d", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "24ada3e3996adbed1fa024ca14995ef2ba3d0d17b678b0f3f2b1f66e6ce2b274"},
|
||||
"elixir_sense": {:git, "https://github.com/elixir-lsp/elixir_sense.git", "ed875265f54994911774ac05c3a1b9adb65b80e7", []},
|
||||
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
|
||||
"esbuild": {:hex, :esbuild, "0.5.0", "d5bb08ff049d7880ee3609ed5c4b864bd2f46445ea40b16b4acead724fb4c4a3", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "f183a0b332d963c4cfaf585477695ea59eef9a6f2204fdd0efa00e099694ffe5"},
|
||||
|
@ -44,6 +45,7 @@
|
|||
"ex_check": {:hex, :ex_check, "0.14.0", "d6fbe0bcc51cf38fea276f5bc2af0c9ae0a2bb059f602f8de88709421dae4f0e", [:mix], [], "hexpm", "8a602e98c66e6a4be3a639321f1f545292042f290f91fa942a285888c6868af0"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.28.5", "3e52a6d2130ce74d096859e477b97080c156d0926701c13870a4e1f752363279", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d2c4b07133113e9aa3e9ba27efb9088ba900e9e51caa383919676afdf09ab181"},
|
||||
"excoveralls": {:hex, :excoveralls, "0.14.6", "610e921e25b180a8538229ef547957f7e04bd3d3e9a55c7c5b7d24354abbba70", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "0eceddaa9785cfcefbf3cd37812705f9d8ad34a758e513bb975b081dce4eb11e"},
|
||||
"faker": {:hex, :faker, "0.17.0", "671019d0652f63aefd8723b72167ecdb284baf7d47ad3a82a15e9b8a6df5d1fa", [:mix], [], "hexpm", "a7d4ad84a93fd25c5f5303510753789fc2433ff241bf3b4144d3f6f291658a6a"},
|
||||
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||
"finch": {:hex, :finch, "0.10.2", "9ad27d68270d879f73f26604bb2e573d40f29bf0e907064a9a337f90a16a0312", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dd8b11b282072cec2ef30852283949c248bd5d2820c88d8acc89402b81db7550"},
|
||||
"floki": {:hex, :floki, "0.33.1", "f20f1eb471e726342b45ccb68edb9486729e7df94da403936ea94a794f072781", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "461035fd125f13fdf30f243c85a0b1e50afbec876cbf1ceefe6fddd2e6d712c6"},
|
||||
|
@ -69,7 +71,9 @@
|
|||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||
"mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"},
|
||||
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
|
||||
"mimic": {:hex, :mimic, "1.7.4", "cd2772ffbc9edefe964bc668bfd4059487fa639a5b7f1cbdf4fd22946505aa4f", [:mix], [], "hexpm", "437c61041ecf8a7fae35763ce89859e4973bb0666e6ce76d75efc789204447c3"},
|
||||
"mint": {:hex, :mint, "1.4.2", "50330223429a6e1260b2ca5415f69b0ab086141bc76dc2fbf34d7c389a6675b2", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "ce75a5bbcc59b4d7d8d70f8b2fc284b1751ffb35c7b6a6302b5192f8ab4ddd80"},
|
||||
"nebulex": {:hex, :nebulex, "2.4.2", "b3d2d86d57b15896fb8e6d6dd49b4a9dee2eedd6eddfb3b69bfdb616a09c2817", [:mix], [{:decorator, "~> 1.4", [hex: :decorator, repo: "hexpm", optional: true]}, {:shards, "~> 1.0", [hex: :shards, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "c9f888e5770fd47614c95990d0a02c3515216d51dc72e3c830eaf28f5649ba52"},
|
||||
"nimble_options": {:hex, :nimble_options, "0.5.2", "42703307b924880f8c08d97719da7472673391905f528259915782bb346e0a1b", [:mix], [], "hexpm", "4da7f904b915fd71db549bcdc25f8d56f378ef7ae07dc1d372cbe72ba950dce0"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"},
|
||||
"nimble_pool": {:hex, :nimble_pool, "0.2.6", "91f2f4c357da4c4a0a548286c84a3a28004f68f05609b4534526871a22053cde", [:mix], [], "hexpm", "1c715055095d3f2705c4e236c18b618420a35490da94149ff8b580a2144f653f"},
|
||||
|
@ -84,7 +88,7 @@
|
|||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"},
|
||||
"phoenix_template": {:hex, :phoenix_template, "1.0.0", "c57bc5044f25f007dc86ab21895688c098a9f846a8dda6bc40e2d0ddc146e38f", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "1b066f99a26fd22064c12b2600a9a6e56700f591bf7b20b418054ea38b4d4357"},
|
||||
"phoenix_view": {:hex, :phoenix_view, "2.0.2", "6bd4d2fd595ef80d33b439ede6a19326b78f0f1d8d62b9a318e3d9c1af351098", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "a929e7230ea5c7ee0e149ffcf44ce7cf7f4b6d2bfe1752dd7c084cdff152d36f"},
|
||||
"picosat_elixir": {:hex, :picosat_elixir, "0.2.2", "1cacfdb4fb0c3ead5e5e9b1e98ac822a777f07eab35e29c3f8fc7086de2bfb36", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "9d0cc569552cca417abea8270a54b71153a63be4b951ff249e94642f1c0f35d1"},
|
||||
"picosat_elixir": {:hex, :picosat_elixir, "0.2.3", "bf326d0f179fbb3b706bb2c15fbc367dacfa2517157d090fdfc32edae004c597", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f76c9db2dec9d2561ffaa9be35f65403d53e984e8cd99c832383b7ab78c16c66"},
|
||||
"plug": {:hex, :plug, "1.14.0", "ba4f558468f69cbd9f6b356d25443d0b796fbdc887e03fa89001384a9cac638f", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bf020432c7d4feb7b3af16a0c2701455cbbbb95e5b6866132cb09eb0c29adc14"},
|
||||
"plug_content_security_policy": {:hex, :plug_content_security_policy, "0.2.1", "0a19c76307ad000b3757739c14b34b83ecccf7d0a3472e64e14797a20b62939b", [:mix], [{:plug, "~> 1.3", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ceea10050671c0387c64526e2cb337ee08e12705c737eaed80439266df5b2e29"},
|
||||
"plug_cowboy": {:hex, :plug_cowboy, "2.6.0", "d1cf12ff96a1ca4f52207c5271a6c351a4733f413803488d75b70ccf44aebec2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "073cf20b753ce6682ed72905cd62a2d4bd9bad1bf9f7feb02a1b8e525bd94fa6"},
|
||||
|
@ -95,7 +99,7 @@
|
|||
"slugify": {:hex, :slugify, "1.3.1", "0d3b8b7e5c1eeaa960e44dce94382bee34a39b3ea239293e457a9c5b47cc6fd3", [:mix], [], "hexpm", "cb090bbeb056b312da3125e681d98933a360a70d327820e4b7f91645c4d8be76"},
|
||||
"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"},
|
||||
"spark": {:hex, :spark, "0.3.4", "0084ce931c0e444194d5198b6f872c74c85607b6e5672436056e9f5b6fa41139", [:mix], [{:nimble_options, "~> 0.5", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 0.1", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "7816d3a43916c5fac2bb2308f9a3442644950e5e269014e4cdc5b2cab0bab5e0"},
|
||||
"spark": {:hex, :spark, "0.3.5", "99905e681156050a713218e2b57956870b88b660dff57e7ee061b0245fc5dd50", [:mix], [{:nimble_options, "~> 0.5", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 0.1", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "f272fe581f37123bf90568974937dbc18ce575fc43580a5a658965b35b993520"},
|
||||
"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"},
|
||||
"sunflower_ui": {:git, "https://github.com/zachdaniel/sunflower_ui.git", "3ec87f33e003693e6db2329f9d6d8ac59983cf17", []},
|
||||
|
@ -104,7 +108,7 @@
|
|||
"swoosh": {:hex, :swoosh, "1.8.1", "b1694d57c01852f50f7d4e6a74f5d119b2d8722d6a82f7288703c3e448ddbbf8", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e64a93d71d1e1e32db681cf7870697495c9cb2df4a5484f4d91ded326ccd3cbb"},
|
||||
"table_rex": {:hex, :table_rex, "3.1.1", "0c67164d1714b5e806d5067c1e96ff098ba7ae79413cc075973e17c38a587caa", [:mix], [], "hexpm", "678a23aba4d670419c23c17790f9dcd635a4a89022040df7d5d772cb21012490"},
|
||||
"tails": {:hex, :tails, "0.1.1", "4d912b8c4e5bf244f2e899fee76b2d2fb99d2c4740defaa00ed5570266ee87f4", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "4d273173487f32db0040d901a312a6bf347ba5159b6c2fdf080830649839569c"},
|
||||
"telemetry": {:hex, :telemetry, "1.2.0", "a8ce551485a9a3dac8d523542de130eafd12e40bbf76cf0ecd2528f24e812a44", [:rebar3], [], "hexpm", "1427e73667b9a2002cf1f26694c422d5c905df889023903c4518921d53e3e883"},
|
||||
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
|
||||
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
|
||||
"telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"},
|
||||
"typable": {:hex, :typable, "0.3.0", "0431e121d124cd26f312123e313d2689b9a5322b15add65d424c07779eaa3ca1", [:mix], [], "hexpm", "880a0797752da1a4c508ac48f94711e04c86156f498065a83d160eef945858f8"},
|
||||
|
|
29
priv/repo/migrations/20230117145347_migrate_resources41.exs
Normal file
29
priv/repo/migrations/20230117145347_migrate_resources41.exs
Normal file
|
@ -0,0 +1,29 @@
|
|||
defmodule AshHq.Repo.Migrations.MigrateResources41 do
|
||||
@moduledoc """
|
||||
Updates resources based on their most recent snapshots.
|
||||
|
||||
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||
"""
|
||||
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
alter table(:library_versions) do
|
||||
add :hydrated, :boolean, null: false, default: false
|
||||
end
|
||||
|
||||
alter table(:libraries) do
|
||||
add :module_prefixes, {:array, :text}, null: false, default: []
|
||||
end
|
||||
end
|
||||
|
||||
def down do
|
||||
alter table(:libraries) do
|
||||
remove :module_prefixes
|
||||
end
|
||||
|
||||
alter table(:library_versions) do
|
||||
remove :hydrated
|
||||
end
|
||||
end
|
||||
end
|
38
priv/repo/migrations/20230117205917_migrate_resources42.exs
Normal file
38
priv/repo/migrations/20230117205917_migrate_resources42.exs
Normal file
|
@ -0,0 +1,38 @@
|
|||
defmodule AshHq.Repo.Migrations.MigrateResources42 do
|
||||
@moduledoc """
|
||||
Updates resources based on their most recent snapshots.
|
||||
|
||||
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||
"""
|
||||
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
alter table(:libraries) do
|
||||
add :mix_project, :text
|
||||
end
|
||||
|
||||
# alter table(:dsls) do
|
||||
# Attribute removal has been commented out to avoid data loss. See the migration generator documentation for more
|
||||
# If you uncomment this, be sure to also uncomment the corresponding attribute *addition* in the `down` migration
|
||||
# remove :links
|
||||
#
|
||||
# end
|
||||
#
|
||||
end
|
||||
|
||||
def down do
|
||||
# alter table(:dsls) do
|
||||
# This is the `down` migration of the statement:
|
||||
#
|
||||
# remove :links
|
||||
#
|
||||
#
|
||||
# add :links, :map
|
||||
# end
|
||||
#
|
||||
alter table(:libraries) do
|
||||
remove :mix_project
|
||||
end
|
||||
end
|
||||
end
|
|
@ -3,6 +3,7 @@ AshHq.Docs.Library.create!(
|
|||
name: "ash",
|
||||
display_name: "Ash",
|
||||
order: 0,
|
||||
module_prefixes: ["Ash"],
|
||||
description: """
|
||||
The core framework, providing all the features and goodies that power and enable the rest of the ecosystem.
|
||||
"""
|
||||
|
@ -16,6 +17,7 @@ AshHq.Docs.Library.create!(
|
|||
name: "ash_postgres",
|
||||
display_name: "AshPostgres",
|
||||
order: 10,
|
||||
module_prefixes: ["AshPostgres"],
|
||||
description: """
|
||||
A PostgreSQL data layer for Ash resources, allowing for rich query capabilities and seamless persistence.
|
||||
"""
|
||||
|
@ -28,6 +30,7 @@ AshHq.Docs.Library.create!(
|
|||
%{
|
||||
name: "ash_phoenix",
|
||||
display_name: "AshPhoenix",
|
||||
module_prefixes: ["AshPhoenix"],
|
||||
order: 20,
|
||||
description: """
|
||||
Utilities for using Ash resources with Phoenix Framework, from building forms to running queries in sockets & LiveViews.
|
||||
|
@ -41,6 +44,7 @@ AshHq.Docs.Library.create!(
|
|||
%{
|
||||
name: "ash_graphql",
|
||||
display_name: "AshGraphql",
|
||||
module_prefixes: ["AshGraphql"],
|
||||
order: 40,
|
||||
description: """
|
||||
A GraphQL extension that allows you to build a rich and customizable GraphQL API with minimal configuration required.
|
||||
|
@ -54,6 +58,7 @@ AshHq.Docs.Library.create!(
|
|||
%{
|
||||
name: "ash_json_api",
|
||||
display_name: "AshJsonApi",
|
||||
module_prefixes: ["AshJsonApi"],
|
||||
order: 50,
|
||||
description: """
|
||||
A JSON:API extension that allows you to effortlessly create a JSON:API spec compliant API.
|
||||
|
@ -67,6 +72,7 @@ AshHq.Docs.Library.create!(
|
|||
%{
|
||||
name: "ash_authentication",
|
||||
display_name: "AshAuthentication",
|
||||
module_prefixes: ["AshAuthentication"],
|
||||
order: 55,
|
||||
repo_org: "team-alembic",
|
||||
description: """
|
||||
|
@ -81,6 +87,7 @@ AshHq.Docs.Library.create!(
|
|||
%{
|
||||
name: "ash_authentication_phoenix",
|
||||
display_name: "AshAuthenticationPhoenix",
|
||||
module_prefixes: ["AshAuthenticationPhoenix"],
|
||||
order: 56,
|
||||
repo_org: "team-alembic",
|
||||
description: """
|
||||
|
@ -95,6 +102,7 @@ AshHq.Docs.Library.create!(
|
|||
%{
|
||||
name: "ash_csv",
|
||||
display_name: "AshCSV",
|
||||
module_prefixes: ["AshCsv"],
|
||||
order: 70,
|
||||
description: """
|
||||
A CSV data layer allowing resources to be queried from and persisted in a CSV file.
|
||||
|
@ -108,6 +116,7 @@ AshHq.Docs.Library.create!(
|
|||
%{
|
||||
name: "ash_archival",
|
||||
display_name: "AshArchival",
|
||||
module_prefixes: ["AshArchival"],
|
||||
order: 85,
|
||||
description: """
|
||||
A light-weight resource extension that modifies resources to simulate deletion by setting an `archived_at` attribute.
|
||||
|
@ -122,6 +131,7 @@ AshHq.Docs.Library.create!(
|
|||
%{
|
||||
name: "spark",
|
||||
display_name: "Spark",
|
||||
module_prefixes: ["Spark"],
|
||||
order: 100,
|
||||
description: """
|
||||
The core DSL and extension tooling, allowing for powerful, extensible DSLs with minimal effort.
|
||||
|
|
285
priv/resource_snapshots/repo/dsls/20230117205917.json
Normal file
285
priv/resource_snapshots/repo/dsls/20230117205917.json
Normal file
|
@ -0,0 +1,285 @@
|
|||
{
|
||||
"attributes": [
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "sanitized_path",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"uuid_generate_v4()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": true,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "id",
|
||||
"type": "uuid"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "name",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "\"\"",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "doc",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "doc_html",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "imports",
|
||||
"type": [
|
||||
"array",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "examples",
|
||||
"type": [
|
||||
"array",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "args",
|
||||
"type": [
|
||||
"array",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "[]",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "optional_args",
|
||||
"type": [
|
||||
"array",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "arg_defaults",
|
||||
"type": "map"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "path",
|
||||
"type": [
|
||||
"array",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "recursive_as",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "order",
|
||||
"type": "bigint"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "type",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"now()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "inserted_at",
|
||||
"type": "utc_datetime_usec"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"now()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "updated_at",
|
||||
"type": "utc_datetime_usec"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": {
|
||||
"destination_attribute": "id",
|
||||
"destination_attribute_default": null,
|
||||
"destination_attribute_generated": null,
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"name": "dsls_library_version_id_fkey",
|
||||
"on_delete": "delete",
|
||||
"on_update": null,
|
||||
"schema": "public",
|
||||
"table": "library_versions"
|
||||
},
|
||||
"size": null,
|
||||
"source": "library_version_id",
|
||||
"type": "uuid"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": {
|
||||
"destination_attribute": "id",
|
||||
"destination_attribute_default": null,
|
||||
"destination_attribute_generated": null,
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"name": "dsls_extension_id_fkey",
|
||||
"on_delete": null,
|
||||
"on_update": null,
|
||||
"schema": "public",
|
||||
"table": "extensions"
|
||||
},
|
||||
"size": null,
|
||||
"source": "extension_id",
|
||||
"type": "uuid"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": {
|
||||
"destination_attribute": "id",
|
||||
"destination_attribute_default": null,
|
||||
"destination_attribute_generated": null,
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"name": "dsls_dsl_id_fkey",
|
||||
"on_delete": null,
|
||||
"on_update": null,
|
||||
"schema": "public",
|
||||
"table": "dsls"
|
||||
},
|
||||
"size": null,
|
||||
"source": "dsl_id",
|
||||
"type": "uuid"
|
||||
}
|
||||
],
|
||||
"base_filter": null,
|
||||
"check_constraints": [],
|
||||
"custom_indexes": [],
|
||||
"custom_statements": [
|
||||
{
|
||||
"code?": false,
|
||||
"down": "DROP INDEX dsls_name_lower_index;",
|
||||
"name": "name_index",
|
||||
"up": "CREATE INDEX dsls_name_lower_index ON dsls(lower(name));\n"
|
||||
},
|
||||
{
|
||||
"code?": false,
|
||||
"down": "DROP INDEX dsls_name_trigram_index;",
|
||||
"name": "trigram_index",
|
||||
"up": "CREATE INDEX dsls_name_trigram_index ON dsls USING GIST (name gist_trgm_ops);\n"
|
||||
},
|
||||
{
|
||||
"code?": false,
|
||||
"down": "DROP INDEX dsls_search_index;",
|
||||
"name": "search_index",
|
||||
"up": "CREATE INDEX dsls_search_index ON dsls USING GIN((\n setweight(to_tsvector('english', name), 'A') ||\n setweight(to_tsvector('english', doc), 'D')\n));\n"
|
||||
}
|
||||
],
|
||||
"has_create_action": true,
|
||||
"hash": "0B14F4C3EB4751D846DCFCD660770D2476F8A22F30636C18D0A545A6C158ED0D",
|
||||
"identities": [],
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"repo": "Elixir.AshHq.Repo",
|
||||
"schema": null,
|
||||
"table": "dsls"
|
||||
}
|
129
priv/resource_snapshots/repo/libraries/20230117145347.json
Normal file
129
priv/resource_snapshots/repo/libraries/20230117145347.json
Normal file
|
@ -0,0 +1,129 @@
|
|||
{
|
||||
"attributes": [
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"uuid_generate_v4()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": true,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "id",
|
||||
"type": "uuid"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "name",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "display_name",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "order",
|
||||
"type": "bigint"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "description",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "\"ash-project\"",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "repo_org",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "[]",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "module_prefixes",
|
||||
"type": [
|
||||
"array",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"now()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "inserted_at",
|
||||
"type": "utc_datetime_usec"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"now()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "updated_at",
|
||||
"type": "utc_datetime_usec"
|
||||
}
|
||||
],
|
||||
"base_filter": null,
|
||||
"check_constraints": [],
|
||||
"custom_indexes": [],
|
||||
"custom_statements": [],
|
||||
"has_create_action": true,
|
||||
"hash": "FC92198B6E8B374CDFE92AC7D002E41DF2BF91397AD1F59C92A1069EB30381B7",
|
||||
"identities": [
|
||||
{
|
||||
"base_filter": null,
|
||||
"index_name": "libraries_unique_name_index",
|
||||
"keys": [
|
||||
"name"
|
||||
],
|
||||
"name": "unique_name"
|
||||
},
|
||||
{
|
||||
"base_filter": null,
|
||||
"index_name": "libraries_unique_order_index",
|
||||
"keys": [
|
||||
"order"
|
||||
],
|
||||
"name": "unique_order"
|
||||
}
|
||||
],
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"repo": "Elixir.AshHq.Repo",
|
||||
"schema": null,
|
||||
"table": "libraries"
|
||||
}
|
139
priv/resource_snapshots/repo/libraries/20230117205917.json
Normal file
139
priv/resource_snapshots/repo/libraries/20230117205917.json
Normal file
|
@ -0,0 +1,139 @@
|
|||
{
|
||||
"attributes": [
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"uuid_generate_v4()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": true,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "id",
|
||||
"type": "uuid"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "name",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "display_name",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "order",
|
||||
"type": "bigint"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "description",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "\"ash-project\"",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "repo_org",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "[]",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "module_prefixes",
|
||||
"type": [
|
||||
"array",
|
||||
"text"
|
||||
]
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "mix_project",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"now()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "inserted_at",
|
||||
"type": "utc_datetime_usec"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"now()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "updated_at",
|
||||
"type": "utc_datetime_usec"
|
||||
}
|
||||
],
|
||||
"base_filter": null,
|
||||
"check_constraints": [],
|
||||
"custom_indexes": [],
|
||||
"custom_statements": [],
|
||||
"has_create_action": true,
|
||||
"hash": "4074AA4197B032BDA64341BB2FEC32ADDED587E8021DF8A2370106B151907023",
|
||||
"identities": [
|
||||
{
|
||||
"base_filter": null,
|
||||
"index_name": "libraries_unique_name_index",
|
||||
"keys": [
|
||||
"name"
|
||||
],
|
||||
"name": "unique_name"
|
||||
},
|
||||
{
|
||||
"base_filter": null,
|
||||
"index_name": "libraries_unique_order_index",
|
||||
"keys": [
|
||||
"order"
|
||||
],
|
||||
"name": "unique_order"
|
||||
}
|
||||
],
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"repo": "Elixir.AshHq.Repo",
|
||||
"schema": null,
|
||||
"table": "libraries"
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
{
|
||||
"attributes": [
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "sanitized_version",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"uuid_generate_v4()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": true,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "id",
|
||||
"type": "uuid"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "version",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "false",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "hydrated",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"now()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "inserted_at",
|
||||
"type": "utc_datetime_usec"
|
||||
},
|
||||
{
|
||||
"allow_nil?": false,
|
||||
"default": "fragment(\"now()\")",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": null,
|
||||
"size": null,
|
||||
"source": "updated_at",
|
||||
"type": "utc_datetime_usec"
|
||||
},
|
||||
{
|
||||
"allow_nil?": true,
|
||||
"default": "nil",
|
||||
"generated?": false,
|
||||
"primary_key?": false,
|
||||
"references": {
|
||||
"destination_attribute": "id",
|
||||
"destination_attribute_default": null,
|
||||
"destination_attribute_generated": null,
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"name": "library_versions_library_id_fkey",
|
||||
"on_delete": null,
|
||||
"on_update": null,
|
||||
"schema": "public",
|
||||
"table": "libraries"
|
||||
},
|
||||
"size": null,
|
||||
"source": "library_id",
|
||||
"type": "uuid"
|
||||
}
|
||||
],
|
||||
"base_filter": null,
|
||||
"check_constraints": [],
|
||||
"custom_indexes": [],
|
||||
"custom_statements": [
|
||||
{
|
||||
"code?": false,
|
||||
"down": "DROP INDEX library_versions_name_lower_index;",
|
||||
"name": "name_index",
|
||||
"up": "CREATE INDEX library_versions_name_lower_index ON library_versions(lower(version));\n"
|
||||
},
|
||||
{
|
||||
"code?": false,
|
||||
"down": "DROP INDEX library_versions_name_trigram_index;",
|
||||
"name": "trigram_index",
|
||||
"up": "CREATE INDEX library_versions_name_trigram_index ON library_versions USING GIST (version gist_trgm_ops);\n"
|
||||
},
|
||||
{
|
||||
"code?": false,
|
||||
"down": "DROP INDEX library_versions_search_index;",
|
||||
"name": "search_index",
|
||||
"up": "CREATE INDEX library_versions_search_index ON library_versions USING GIN((\n to_tsvector('english', version)\n));\n"
|
||||
}
|
||||
],
|
||||
"has_create_action": true,
|
||||
"hash": "FEEDF65ECA522C910B790387521C468262CE0A0307C2ECE57CFEEFF2C201BF38",
|
||||
"identities": [
|
||||
{
|
||||
"base_filter": null,
|
||||
"index_name": "library_versions_unique_version_for_library_index",
|
||||
"keys": [
|
||||
"version",
|
||||
"library_id"
|
||||
],
|
||||
"name": "unique_version_for_library"
|
||||
}
|
||||
],
|
||||
"multitenancy": {
|
||||
"attribute": null,
|
||||
"global": null,
|
||||
"strategy": null
|
||||
},
|
||||
"repo": "Elixir.AshHq.Repo",
|
||||
"schema": null,
|
||||
"table": "library_versions"
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
require Logger
|
||||
[name, version, file] = System.argv()
|
||||
[name, version, file, mix_project] = System.argv()
|
||||
mix_project = Module.concat([mix_project])
|
||||
|
||||
Application.put_env(:dsl, :name, name)
|
||||
Application.put_env(:ash, :use_all_identities_in_manage_relationship?, true)
|
||||
|
||||
Mix.install(
|
||||
[
|
||||
|
@ -177,8 +179,8 @@ defmodule Utils do
|
|||
[]
|
||||
end),
|
||||
arg_defaults:
|
||||
Enum.reduce(entity.args, %{},
|
||||
fn {:optional, name, default}, acc ->
|
||||
Enum.reduce(entity.args, %{}, fn
|
||||
{:optional, name, default}, acc ->
|
||||
Map.put(acc, name, inspect(default))
|
||||
|
||||
_, acc ->
|
||||
|
@ -198,7 +200,8 @@ defmodule Utils do
|
|||
|
||||
defp add_argument_indices(values, arguments) do
|
||||
Enum.map(values, fn value ->
|
||||
case Enum.find_index(arguments, fn {:optional, name, _} ->
|
||||
case Enum.find_index(arguments, fn
|
||||
{:optional, name, _} ->
|
||||
name == value.name
|
||||
|
||||
{:optional, name} ->
|
||||
|
@ -475,61 +478,136 @@ defmodule Utils do
|
|||
defp type({:spark_type, type, _}), do: inspect(type)
|
||||
defp type({:spark_type, type, _, _}), do: inspect(type)
|
||||
|
||||
def doc_index?(module) do
|
||||
Spark.implements_behaviour?(module, Spark.DocIndex) &&
|
||||
module.for_library() == Application.get_env(:dsl, :name)
|
||||
def modules_for(all_modules, modules) do
|
||||
case modules do
|
||||
%Regex{} = regex ->
|
||||
Enum.filter(all_modules, fn module ->
|
||||
Regex.match?(regex, inspect(module)) || Regex.match?(regex, to_string(module))
|
||||
end)
|
||||
|
||||
other ->
|
||||
if is_list(modules) do
|
||||
Enum.flat_map(modules, &modules_for(all_modules, &1))
|
||||
else
|
||||
List.wrap(other)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
dsls =
|
||||
for [app] <- :ets.match(:ac_tab, {{:loaded, :"$1"}, :_}),
|
||||
{:ok, modules} = :application.get_key(app, :modules),
|
||||
module <- Enum.filter(modules, &Utils.doc_index?/1) do
|
||||
module
|
||||
def guides(mix_project, name) do
|
||||
root_dir = File.cwd!()
|
||||
app_dir =
|
||||
name
|
||||
|> Application.app_dir()
|
||||
|> Path.join("../../../../deps/#{name}")
|
||||
|> Path.expand()
|
||||
|
||||
try do
|
||||
File.cd!(app_dir)
|
||||
|
||||
extras =
|
||||
Enum.map(mix_project.project[:docs][:extras], fn {file, config} ->
|
||||
config =
|
||||
if config[:title] do
|
||||
Keyword.put(config, :name, config[:title])
|
||||
else
|
||||
config
|
||||
end
|
||||
|
||||
case Enum.at(dsls, 0) do
|
||||
nil ->
|
||||
File.write!(file, Base.encode64(:erlang.term_to_binary(nil)))
|
||||
{to_string(file), config}
|
||||
|
||||
dsl ->
|
||||
extensions = dsl.extensions()
|
||||
file ->
|
||||
title =
|
||||
file
|
||||
|> Path.basename(".md")
|
||||
|> String.split(~r/[-_]/)
|
||||
|> Enum.map(&String.capitalize/1)
|
||||
|> Enum.join(" ")
|
||||
|> case do
|
||||
"F A Q" ->
|
||||
"FAQ"
|
||||
|
||||
other ->
|
||||
other
|
||||
end
|
||||
|
||||
{to_string(file), name: title}
|
||||
end)
|
||||
|
||||
groups_for_extras =
|
||||
mix_project.project[:docs][:groups_for_extras]
|
||||
|> List.wrap()
|
||||
|> Kernel.++([{"Miscellaneous", ~r/.*/}])
|
||||
|
||||
groups_for_extras
|
||||
|> Enum.reduce({extras, []}, fn {group, matcher}, {remaining_extras, acc} ->
|
||||
matches_for_group =
|
||||
matcher
|
||||
|> List.wrap()
|
||||
|> Enum.flat_map(&take_matching(remaining_extras, &1))
|
||||
|
||||
{remaining_extras -- matches_for_group, [{group, matches_for_group} | acc]}
|
||||
end)
|
||||
|> elem(1)
|
||||
|> Enum.reverse()
|
||||
|> Enum.flat_map(fn {category, matches} ->
|
||||
matches
|
||||
|> Enum.with_index()
|
||||
|> Enum.map(fn {{path, config}, index} ->
|
||||
route =
|
||||
path
|
||||
|> Path.absname()
|
||||
|> String.trim_leading(app_dir)
|
||||
|> String.trim_leading("/documentation/")
|
||||
|> String.trim_trailing(".md")
|
||||
|
||||
config
|
||||
|> Map.new()
|
||||
|> Map.put(:order, index)
|
||||
|> Map.put(:route, route)
|
||||
|> Map.put(:category, category)
|
||||
|> Map.put(:text, File.read!(path))
|
||||
end)
|
||||
end)
|
||||
after
|
||||
File.cd!(root_dir)
|
||||
end
|
||||
end
|
||||
|
||||
defp take_matching(extras, matcher) when is_binary(matcher) do
|
||||
extras
|
||||
|> Enum.filter(fn {name, _} ->
|
||||
name == matcher
|
||||
end)
|
||||
end
|
||||
|
||||
defp take_matching(extras, %Regex{} = matcher) do
|
||||
Enum.filter(extras, fn {name, _} -> Regex.match?(matcher, name) end)
|
||||
end
|
||||
end
|
||||
|
||||
acc = %{
|
||||
doc: Utils.module_docs(dsl),
|
||||
guides: [],
|
||||
extensions: [],
|
||||
guides: Utils.guides(mix_project, String.to_atom(name)),
|
||||
modules: [],
|
||||
mix_tasks: []
|
||||
mix_tasks: [],
|
||||
default_guide: mix_project.project[:docs][:spark][:default_guide]
|
||||
}
|
||||
|
||||
default_guide = Utils.try_apply(fn -> dsl.default_guide() end)
|
||||
|
||||
acc =
|
||||
Utils.try_apply(fn -> dsl.guides() end, [])
|
||||
|> Enum.with_index()
|
||||
|> Enum.reduce(acc, fn {guide, order}, acc ->
|
||||
Map.update!(acc, :guides, fn guides ->
|
||||
guide =
|
||||
guide
|
||||
|> Map.put(:order, order)
|
||||
|> Map.update!(:route, &String.trim_trailing(&1, ".md"))
|
||||
|
||||
guide =
|
||||
if guide.route == default_guide.route do
|
||||
Map.put(guide, :default, true)
|
||||
else
|
||||
guide
|
||||
end
|
||||
|
||||
[guide | guides]
|
||||
end)
|
||||
end)
|
||||
extensions = mix_project.project[:docs][:spark][:extensions] || mix_project.project[:docs][:spark_extensions]
|
||||
|
||||
{:ok, all_modules} =
|
||||
name
|
||||
|> String.to_atom()
|
||||
|> :application.get_key(:modules)
|
||||
|
||||
all_modules =
|
||||
all_modules
|
||||
|> Kernel.||([])
|
||||
|> Enum.reject(fn module ->
|
||||
Enum.find(extensions || [], &(&1.target == inspect(module)))
|
||||
end)
|
||||
|
||||
all_modules =
|
||||
Enum.filter(all_modules, fn module ->
|
||||
case Code.fetch_docs(module) do
|
||||
|
@ -542,18 +620,11 @@ case Enum.at(dsls, 0) do
|
|||
end)
|
||||
|
||||
acc =
|
||||
Utils.try_apply(fn -> dsl.code_modules() end, [])
|
||||
mix_project.project[:docs][:groups_for_modules]
|
||||
|> Kernel.||([{"Miscellaneous", ~r/.*/}])
|
||||
|> Enum.reduce(acc, fn {category, modules}, acc ->
|
||||
modules =
|
||||
case modules do
|
||||
%Regex{} = regex ->
|
||||
Enum.filter(all_modules, fn module ->
|
||||
Regex.match?(regex, inspect(module)) || Regex.match?(regex, to_string(module))
|
||||
end)
|
||||
|
||||
other ->
|
||||
List.wrap(other)
|
||||
end
|
||||
Utils.modules_for(all_modules, modules)
|
||||
|
||||
modules
|
||||
|> Enum.with_index()
|
||||
|
@ -565,7 +636,7 @@ case Enum.at(dsls, 0) do
|
|||
end)
|
||||
|
||||
acc =
|
||||
Utils.try_apply(fn -> dsl.mix_tasks() end, [])
|
||||
mix_project.project[:docs][:spark][:mix_tasks]
|
||||
|> List.wrap()
|
||||
|> Enum.reduce(acc, fn {category, mix_tasks}, acc ->
|
||||
mix_tasks
|
||||
|
@ -579,6 +650,7 @@ case Enum.at(dsls, 0) do
|
|||
|
||||
data =
|
||||
extensions
|
||||
|> Kernel.||([])
|
||||
|> Enum.with_index()
|
||||
|> Enum.reduce(acc, fn {extension, i}, acc ->
|
||||
acc
|
||||
|
@ -589,4 +661,3 @@ case Enum.at(dsls, 0) do
|
|||
end)
|
||||
|
||||
File.write!(file, Base.encode64(:erlang.term_to_binary(data)))
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue