improvement: handle dsl patches in docs (sort of)

improvement: write article about macros
This commit is contained in:
Zach Daniel 2023-05-11 16:00:36 -04:00
parent e2c039f861
commit b76841a214
11 changed files with 630 additions and 106 deletions

View file

@ -77,7 +77,7 @@ defmodule AshHq.Blog.Post do
relationships do relationships do
has_many :tags, AshHq.Blog.Tag do has_many :tags, AshHq.Blog.Tag do
manual fn posts, %{query: query} -> manual fn posts, %{query: query} ->
all_tags = Enum.flat_map(posts, & &1.tag_names) all_tags = Enum.flat_map(posts, &(&1.tag_names || []))
tags = tags =
query query
@ -104,11 +104,12 @@ defmodule AshHq.Blog.Post do
Ash.Changeset.after_action(changeset, fn _, %{tag_names: tag_names} = record -> Ash.Changeset.after_action(changeset, fn _, %{tag_names: tag_names} = record ->
all_post_tags = all_post_tags =
__MODULE__.published!() __MODULE__.published!()
|> Enum.flat_map(& &1.tag_names) |> Enum.flat_map(&(&1.tag_names || []))
|> IO.inspect()
notifications = notifications =
Enum.flat_map( Enum.flat_map(
tag_names, tag_names || [],
&elem(AshHq.Blog.Tag.upsert!(&1, return_notifications?: true), 1) &elem(AshHq.Blog.Tag.upsert!(&1, return_notifications?: true), 1)
) )

View file

@ -47,17 +47,20 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.PostProcessors.Highlighter do
end end
end) end)
case lexer do code =
{lang, lexer, opts} -> case lexer do
{:keep, render_code(lang, lexer, opts, body)} {lang, lexer, opts} ->
render_code(lang, lexer, opts, body)
nil -> nil ->
if find_value_class(attrs, &(&1 == "inline")) do if find_value_class(attrs, &(&1 == "inline")) do
{:keep, maybe_highlight_module(body, libraries, current_module)} maybe_highlight_module(body, libraries, current_module)
else else
{:keep, ~s(<code class="text-black dark:text-white">#{body}</code>)} ~s(<code class="text-black dark:text-white">#{body}</code>)
end end
end end
{:keep, code}
other -> other ->
other other
@ -423,7 +426,7 @@ defmodule AshHq.Docs.Extensions.RenderMarkdown.PostProcessors.Highlighter do
formatter_options: [highlight_tag: "span"] formatter_options: [highlight_tag: "span"]
) )
~s(<code class="makeup #{lang} highlight">#{highlighted}</code>) ~s(<code class="not-prose makeup #{lang} highlight">#{highlighted}</code>)
end end
entities = [{"&amp;", ?&}, {"&lt;", ?<}, {"&gt;", ?>}, {"&quot;", ?"}, {"&#39;", ?'}] entities = [{"&amp;", ?&}, {"&lt;", ?<}, {"&gt;", ?>}, {"&quot;", ?"}, {"&#39;", ?'}]

View file

@ -60,6 +60,8 @@ defmodule AshHq.Docs.Dsl do
attribute :name, :string do attribute :name, :string do
allow_nil? false allow_nil? false
end end
attribute :requires_extension, :string
attribute :doc, :string do attribute :doc, :string do
allow_nil? false allow_nil? false

View file

@ -6,13 +6,13 @@ defmodule AshHqWeb.Pages.Blog do
alias AshHqWeb.Components.Blog.Tag alias AshHqWeb.Components.Blog.Tag
prop params, :map, default: %{} prop(params, :map, default: %{})
data post, :any, default: nil data(post, :any, default: nil)
data posts, :any, default: [] data(posts, :any, default: [])
data tag, :string data(tag, :string)
data tags, :any, default: [] data(tags, :any, default: [])
data slug, :string data(slug, :string)
def render(assigns) do def render(assigns) do
~F""" ~F"""
@ -28,7 +28,7 @@ defmodule AshHqWeb.Pages.Blog do
<div class="border-b"> <div class="border-b">
<h1 class="mt-6 text-3xl font-semibold mb-4">{@post.title}</h1> <h1 class="mt-6 text-3xl font-semibold mb-4">{@post.title}</h1>
<div class="flex flex-row space-x-2 mb-4"> <div class="flex flex-row space-x-2 mb-4">
{#for tag <- @post.tag_names} {#for tag <- @post.tag_names || []}
<Tag prefix="/blog" tag={tag} /> <Tag prefix="/blog" tag={tag} />
{/for} {/for}
</div> </div>
@ -69,7 +69,7 @@ defmodule AshHqWeb.Pages.Blog do
{post.published_at |> DateTime.to_date()} {post.published_at |> DateTime.to_date()}
</div> </div>
<div class="flex space-x-2"> <div class="flex space-x-2">
{#for tag <- post.tag_names} {#for tag <- post.tag_names || []}
<Tag prefix="/blog" tag={tag} /> <Tag prefix="/blog" tag={tag} />
{/for} {/for}
</div> </div>

View file

@ -13,32 +13,32 @@ defmodule AshHqWeb.Pages.Docs do
require Logger require Logger
require Ash.Query require Ash.Query
prop change_versions, :event, required: true prop(change_versions, :event, required: true)
prop selected_versions, :map, required: true prop(selected_versions, :map, required: true)
prop libraries, :list, default: [] prop(libraries, :list, default: [])
prop uri, :string prop(uri, :string)
prop remove_version, :event prop(remove_version, :event)
prop add_version, :event prop(add_version, :event)
prop change_version, :event prop(change_version, :event)
prop params, :map, required: true prop(params, :map, required: true)
prop show_catalogue_call_to_action, :boolean prop(show_catalogue_call_to_action, :boolean)
data library, :any data(library, :any)
data docs, :any data(docs, :any)
data library_version, :any data(library_version, :any)
data guide, :any data(guide, :any)
data doc_path, :list, default: [] data(doc_path, :list, default: [])
data dsls, :list, default: [] data(dsls, :list, default: [])
data dsl, :any data(dsl, :any)
data module, :any data(module, :any)
data mix_task, :any data(mix_task, :any)
data positional_options, :list data(positional_options, :list)
data description, :string data(description, :string)
data title, :string data(title, :string)
data sidebar_data, :any data(sidebar_data, :any)
data not_found, :boolean, default: false data(not_found, :boolean, default: false)
data dsl_target_extensions, :list data(dsl_target_extensions, :list)
data dsl_target, :string data(dsl_target, :string)
@spec render(any) :: Phoenix.LiveView.Rendered.t() @spec render(any) :: Phoenix.LiveView.Rendered.t()
def render(assigns) do def render(assigns) do
@ -256,6 +256,11 @@ defmodule AshHqWeb.Pages.Docs do
</div> </div>
</div> </div>
</div> </div>
{#if dsl.requires_extension}
<div class="w-full pt-4">
Requires Extension: <span class="text-primary-light-600">{dsl.requires_extension}</span>
</div>
{/if}
<div class="prose dark:prose-invert my-4"> <div class="prose dark:prose-invert my-4">
{raw(dsl.doc_html)} {raw(dsl.doc_html)}

View file

@ -1,11 +1,11 @@
%{ %{
"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": {: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"}, "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", "3d8f988e130a65dddbb4cbb397cc4750cc3502a0", []}, "ash": {:git, "https://github.com/ash-project/ash.git", "ccacfd78fcc51523603b2799d864931f916f28b4", []},
"ash_admin": {:git, "https://github.com/ash-project/ash_admin.git", "3002af9ec69dc475582ef5f445064e4594bf45ac", []}, "ash_admin": {:git, "https://github.com/ash-project/ash_admin.git", "3002af9ec69dc475582ef5f445064e4594bf45ac", []},
"ash_authentication": {:hex, :ash_authentication, "3.10.5", "8a5e9b4b6887c8f6ddd44763dd1ce11fd6db1376e11cfa90dbbc24a72ee2ab2b", [:mix], [{:ash, ">= 2.5.11 and < 3.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:assent, "~> 0.2", [hex: :assent, repo: "hexpm", optional: false]}, {:bcrypt_elixir, "~> 3.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: false]}, {:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:joken, "~> 2.5", [hex: :joken, repo: "hexpm", optional: false]}, {:mint, "~> 1.4", [hex: :mint, repo: "hexpm", optional: false]}, {:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: false]}, {:spark, ">= 0.4.1 and < 1.0.0-0 or ~> 1.0", [hex: :spark, repo: "hexpm", optional: false]}], "hexpm", "6a7d5a64ce8afed4d13231b3964e79870c3de5d1d33b7311eb5173d9a64ceef0"}, "ash_authentication": {:hex, :ash_authentication, "3.10.5", "8a5e9b4b6887c8f6ddd44763dd1ce11fd6db1376e11cfa90dbbc24a72ee2ab2b", [:mix], [{:ash, ">= 2.5.11 and < 3.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:assent, "~> 0.2", [hex: :assent, repo: "hexpm", optional: false]}, {:bcrypt_elixir, "~> 3.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: false]}, {:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:joken, "~> 2.5", [hex: :joken, repo: "hexpm", optional: false]}, {:mint, "~> 1.4", [hex: :mint, repo: "hexpm", optional: false]}, {:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: false]}, {:spark, ">= 0.4.1 and < 1.0.0-0 or ~> 1.0", [hex: :spark, repo: "hexpm", optional: false]}], "hexpm", "6a7d5a64ce8afed4d13231b3964e79870c3de5d1d33b7311eb5173d9a64ceef0"},
"ash_authentication_phoenix": {:hex, :ash_authentication_phoenix, "1.7.0", "2dad9b819ea91893297417762be7cf61204520caaa8597fdfe49e5002070c76c", [:mix], [{:ash, "~> 2.2", [hex: :ash, repo: "hexpm", optional: false]}, {:ash_authentication, "~> 3.10", [hex: :ash_authentication, repo: "hexpm", optional: false]}, {:ash_phoenix, "~> 1.1", [hex: :ash_phoenix, repo: "hexpm", optional: false]}, {:bcrypt_elixir, "~> 3.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:slugify, "~> 1.3", [hex: :slugify, repo: "hexpm", optional: false]}], "hexpm", "bcb30999d214e12aeaceb31fe71bda0d12ec398c6195ccdd85589d11829bacca"}, "ash_authentication_phoenix": {:hex, :ash_authentication_phoenix, "1.7.0", "2dad9b819ea91893297417762be7cf61204520caaa8597fdfe49e5002070c76c", [:mix], [{:ash, "~> 2.2", [hex: :ash, repo: "hexpm", optional: false]}, {:ash_authentication, "~> 3.10", [hex: :ash_authentication, repo: "hexpm", optional: false]}, {:ash_phoenix, "~> 1.1", [hex: :ash_phoenix, repo: "hexpm", optional: false]}, {:bcrypt_elixir, "~> 3.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:slugify, "~> 1.3", [hex: :slugify, repo: "hexpm", optional: false]}], "hexpm", "bcb30999d214e12aeaceb31fe71bda0d12ec398c6195ccdd85589d11829bacca"},
"ash_blog": {:git, "https://github.com/ash-project/ash_blog.git", "9254773dfedabfc7987af6326a62885c24c3655b", []}, "ash_blog": {:git, "https://github.com/ash-project/ash_blog.git", "5d185eccd1ffad084642aa80c25af3d895a70be9", []},
"ash_csv": {:git, "https://github.com/ash-project/ash_csv.git", "7f47b820077619ccb7340fbede0c4fd1b5313a17", []}, "ash_csv": {:git, "https://github.com/ash-project/ash_csv.git", "7f47b820077619ccb7340fbede0c4fd1b5313a17", []},
"ash_graphql": {:git, "https://github.com/ash-project/ash_graphql.git", "2a9baf81646f242c1c17f2d28a381e4e02bea21e", []}, "ash_graphql": {:git, "https://github.com/ash-project/ash_graphql.git", "2a9baf81646f242c1c17f2d28a381e4e02bea21e", []},
"ash_json_api": {:git, "https://github.com/ash-project/ash_json_api.git", "9663ddc68ec2384cc3412a997eacdb6e3f4c29d8", []}, "ash_json_api": {:git, "https://github.com/ash-project/ash_json_api.git", "9663ddc68ec2384cc3412a997eacdb6e3f4c29d8", []},

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1 @@
name name
ash
release
elixir
community

1 name
ash
release
elixir
community

View file

@ -0,0 +1,21 @@
defmodule AshHq.Repo.Migrations.MigrateResources52 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(:dsls) do
add :requires_extension, :text
end
end
def down do
alter table(:dsls) do
remove :requires_extension
end
end
end

View file

@ -0,0 +1,301 @@
{
"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?": true,
"default": "nil",
"generated?": false,
"primary_key?": false,
"references": null,
"size": null,
"source": "requires_extension",
"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,
"primary_key?": true,
"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,
"primary_key?": true,
"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,
"primary_key?": true,
"schema": "public",
"table": "dsls"
},
"size": null,
"source": "dsl_id",
"type": "uuid"
}
],
"base_filter": null,
"check_constraints": [],
"custom_indexes": [
{
"concurrently": false,
"fields": [
"searchable"
],
"include": null,
"message": null,
"name": null,
"prefix": null,
"table": null,
"unique": false,
"using": "GIN",
"where": null
}
],
"custom_statements": [
{
"code?": false,
"down": "ALTER TABLE dsls\n DROP COLUMN searchable\n",
"name": "search_column",
"up": "ALTER TABLE dsls\n ADD COLUMN searchable tsvector\n GENERATED ALWAYS AS (\n setweight(to_tsvector('english', name), 'A') ||\n setweight(to_tsvector('english', doc), 'D')\n ) STORED;\n"
}
],
"has_create_action": true,
"hash": "7518001C6D3973E39FF61BD6EB92201BE1EE57714307E7CDB31593535C82382E",
"identities": [],
"multitenancy": {
"attribute": null,
"global": null,
"strategy": null
},
"repo": "Elixir.AshHq.Repo",
"schema": null,
"table": "dsls"
}

View file

@ -105,7 +105,7 @@ defmodule Utils do
default default
end end
def build(extension, order) do def build(extension, all_extensions, order) do
%{ %{
name: extension.name, name: extension.name,
target: extension[:target], target: extension[:target],
@ -114,18 +114,37 @@ defmodule Utils do
type: extension[:type], type: extension[:type],
order: order, order: order,
doc: module_docs(extension.module) || "No documentation", doc: module_docs(extension.module) || "No documentation",
dsls: build_sections(extension.module.sections()) dsls: build_sections(extension.module.sections(), extension.module, all_extensions)
} }
end end
defp build_sections(sections, path \\ []) do defp build_sections(sections, this_extension_module, all_extensions, path \\ []) do
sections sections
|> Enum.with_index() |> Enum.with_index()
|> Enum.flat_map(fn {section, index} -> |> Enum.flat_map(fn {section, index} ->
section_path = path ++ [section.name]
entities =
all_extensions
|> Enum.flat_map(fn extension ->
extension.module.dsl_patches()
|> Enum.filter(&match?(%Spark.Dsl.Patch.AddEntity{section_path: ^section_path}, &1))
|> Enum.map(fn %{entity: entity} ->
if extension.module == this_extension_module do
entity
else
Map.put(entity, :__requires_extension__, inspect(extension.module))
end
end)
end)
|> then(fn entities ->
Enum.concat(section.entities, entities)
end)
[ [
%{ %{
name: section.name, name: section.name,
options: schema(section.schema, path ++ [section.name]), options: schema(section.schema, section_path),
links: Map.new(section.links || []), links: Map.new(section.links || []),
imports: Enum.map(section.imports, &inspect/1), imports: Enum.map(section.imports, &inspect/1),
type: :section, type: :section,
@ -134,8 +153,8 @@ defmodule Utils do
path: path path: path
} }
] ++ ] ++
build_entities(section.entities, path ++ [section.name]) ++ build_entities(entities, section_path) ++
build_sections(section.sections, path ++ [section.name]) build_sections(section.sections, this_extension_module, all_extensions, section_path)
end) end)
end end
@ -171,56 +190,67 @@ defmodule Utils do
entities entities
|> Enum.with_index() |> Enum.with_index()
|> Enum.flat_map(fn {entity, index} -> |> Enum.flat_map(fn {entity, index} ->
keys_to_remove = Enum.map(entity.auto_set_fields || [], &elem(&1, 0)) [build_entity(entity, path, index)] ++
build_entities(List.flatten(Keyword.values(entity.entities)), path ++ [entity.name])
end)
end
option_schema = Keyword.drop(entity.schema || [], keys_to_remove) defp build_entity(entity, path, index) do
keys_to_remove = Enum.map(entity.auto_set_fields || [], &elem(&1, 0))
option_schema = Keyword.drop(entity.schema || [], keys_to_remove)
[ %{
%{ name: entity.name,
name: entity.name, recursive_as: Map.get(entity, :recursive_as),
recursive_as: Map.get(entity, :recursive_as), doc: docs_with_examples(entity.describe || "", examples(entity.examples)),
order: index, order: index,
doc: docs_with_examples(entity.describe || "", examples(entity.examples)), imports: [],
imports: [], links: Map.new(entity.links || []),
links: Map.new(entity.links || []), args:
args: Enum.map(entity.args, fn
Enum.map(entity.args, fn {:optional, name, _} ->
{:optional, name, _} -> name
name
{:optional, name} -> {:optional, name} ->
name name
name -> name ->
name name
end), end),
optional_args: optional_args:
Enum.flat_map(entity.args, fn Enum.flat_map(entity.args, fn
{:optional, name, _} -> {:optional, name, _} ->
[name] [name]
{:optional, name} -> {:optional, name} ->
[name] [name]
_ -> _ ->
[] []
end), end),
arg_defaults: arg_defaults:
Enum.reduce(entity.args, %{}, fn Enum.reduce(entity.args, %{}, fn
{:optional, name, default}, acc -> {:optional, name, default}, acc ->
Map.put(acc, name, inspect(default)) Map.put(acc, name, inspect(default))
_, acc -> _, acc ->
acc acc
end), end),
type: :entity, type: :entity,
path: path, path: path,
options: options:
option_schema option_schema
|> schema(path ++ [entity.name]) |> schema(path ++ [entity.name])
|> add_argument_indices(entity.args) |> add_argument_indices(entity.args)
} }
] ++ build_entities(List.flatten(Keyword.values(entity.entities)), path ++ [entity.name]) |> then(fn config ->
case Map.fetch(entity, :__requires_extension__) do
{:ok, value} ->
Map.put(config, :requires_extension, value)
:error ->
config
end
end) end)
end end
@ -271,7 +301,7 @@ defmodule Utils do
path: path, path: path,
order: index, order: index,
links: Map.new(value[:links] || []), links: Map.new(value[:links] || []),
type: value[:type_name] || type(value[:type]), type: value[:type_name] || type(value[:type] |> IO.inspect()),
doc: add_default(value[:doc] || "No documentation", value[:default]), doc: add_default(value[:doc] || "No documentation", value[:default]),
required: value[:required] || false, required: value[:required] || false,
default: inspect(value[:default]) default: inspect(value[:default])
@ -511,6 +541,8 @@ defmodule Utils do
defp type(:pid), do: "Pid" defp type(:pid), do: "Pid"
defp type(:mfa), do: "MFA" defp type(:mfa), do: "MFA"
defp type(:mod_arg), do: "Module and Arguments" defp type(:mod_arg), do: "Module and Arguments"
defp type(:map), do: "Map"
defp type(nil), do: "nil"
defp type({:fun, arity}), do: "Function/#{arity}" defp type({:fun, arity}), do: "Function/#{arity}"
defp type({:one_of, choices}), do: type({:in, choices}) defp type({:one_of, choices}), do: type({:in, choices})
defp type({:in, choices}), do: Enum.map_join(choices, " | ", &inspect/1) defp type({:in, choices}), do: Enum.map_join(choices, " | ", &inspect/1)
@ -752,8 +784,8 @@ data =
|> Enum.reduce(acc, fn {extension, i}, acc -> |> Enum.reduce(acc, fn {extension, i}, acc ->
acc acc
|> Map.put_new(:extensions, []) |> Map.put_new(:extensions, [])
|> Map.update!(:extensions, fn extensions -> |> Map.update!(:extensions, fn acc ->
[Utils.build(extension, i) | extensions] [Utils.build(extension, extensions, i) | acc]
end) end)
end) end)