|
1 | 1 | defmodule ElixirScribe do |
2 | | - @moduledoc false |
| 2 | + @moduledoc """ |
| 3 | + The Elixir Scribe Generator configuration and defaults. |
| 4 | +
|
| 5 | + Some of the defaults will be possible to customize via your app configuration: |
| 6 | +
|
| 7 | + * [Configure Default Resource Actions](#module-configure-default-resource-actions) - Provide your own list of built-in default actions that will be used each time you invoke one of the generators. |
| 8 | + * [Configure Default Resource Actions Aliases](#module-configure-resource-actions-aliases) - Use aliases to rename the built-in default actions to your preferred names. |
| 9 | + * [Configure Default Source Code Templates](#module-configure-default-source-code-templates) - Provide your own source code templates to be used by the Elixir Scribe generators |
| 10 | +
|
| 11 | + > #### Private Module {: .warning} |
| 12 | + > All functions in this module lack documentation because they **MUST** be considered private and used internally only. |
| 13 | +
|
| 14 | + ## Configure Default Resource Actions |
| 15 | +
|
| 16 | + The default actions supported by `scribe.gen.domain` and `scribe.gen.html`: |
| 17 | +
|
| 18 | + * `list` - Lists all items of a Resource in the database |
| 19 | + * `new` - Builds a new changeset for a Resource |
| 20 | + * `read` - Reads a specific Resource from the database |
| 21 | + * `edit` - Builds a changeset to track changes made to a Resource |
| 22 | + * `create` - Creates a new Resource in the database |
| 23 | + * `update` - Updates an existing Resource |
| 24 | + * `delete` - Deletes an existing Resource |
| 25 | +
|
| 26 | + For example, for an API you can discard the default resource actions `new` and `edit`: |
| 27 | +
|
| 28 | + ```elixir |
| 29 | + config :elixir_scribe, |
| 30 | + default_resource_actions: ["list", "read", "create", "update", "delete"] |
| 31 | + ``` |
| 32 | +
|
| 33 | + Or, maybe you want to use the default resource actions, plus some other ones that you always need when creating a new resource: |
| 34 | +
|
| 35 | + ```elixir |
| 36 | + config :elixir_scribe, |
| 37 | + default_resource_actions: ["import", "export", "list", "new", "read", "edit", "create", "update", "delete"] |
| 38 | + ``` |
| 39 | +
|
| 40 | + > #### Custom Resource Actions Order {: .error} |
| 41 | + > Order of actions **MATTERS**, otherwise routes will not work as expected. |
| 42 | + > |
| 43 | + > Note how `import` and `export` were added to the begin of the list to ensure they are matched correctly by the router when serving the `GET` request. |
| 44 | +
|
| 45 | + > #### Custom Resource Actions {: .warning} |
| 46 | + > Any custom action name provided via the configuration will be mapped to a default template, unless you provide your custom template(s) for it at the correct path in your app `priv/templates/*`. Check how to customize the templates at [Configure Default Source Code Templates](#module-configure-default-source-code-templates). |
| 47 | + > |
| 48 | + > This custom action names will be added to your router as `GET` requests. You need to customize the router as needed. |
| 49 | +
|
| 50 | +
|
| 51 | + ## Configure Resource Actions Aliases |
| 52 | +
|
| 53 | + In your app configuration for `:elixir_scribe` you can map any of the built-in default actions to actions names of your preference, which it's the same as renaming them. |
| 54 | +
|
| 55 | + The below example maps the built-in default actions `read` to `show` and `list` to `index`. |
| 56 | +
|
| 57 | + ```elixir |
| 58 | + config :elixir_scribe, |
| 59 | + resource_actions_aliases: %{ |
| 60 | + "read" => "show", |
| 61 | + "list" => "index", |
| 62 | + } |
| 63 | + ``` |
| 64 | +
|
| 65 | + ## Configure Default Source Code Templates |
| 66 | +
|
| 67 | + The paths to look for template files for generators defaults to checking the current app's `priv` directory, and falls back to Elixir Scribe and Phoenix's `priv` directory: |
| 68 | +
|
| 69 | + * `priv/templates/*` |
| 70 | + * `elixir_scribe/priv/templates/*` |
| 71 | + * `phoenix/priv/templates/*` |
| 72 | +
|
| 73 | + Provide your own templates to customize the functionality offered by the built-in ones by copying them to your `priv/templates/*` directory, and then modify them as you see fit. |
| 74 | +
|
| 75 | + For example, when using custom resource actions, the Elixir Scribe generators will default to generating code that raises an error with a message alerting you that the logic hasn’t been implemented yet. You can avoid this by providing your own custom source code template for each of your custom actions. |
| 76 | +
|
| 77 | + """ |
| 78 | + |
| 79 | + @doc false |
| 80 | + def base_template_paths(), do: [".", :elixir_scribe, :phoenix] |
| 81 | + |
| 82 | + @doc false |
| 83 | + def app_name() do |
| 84 | + Mix.Project.config() |> Keyword.get(:app) |> Atom.to_string() |
| 85 | + end |
| 86 | + |
| 87 | + @doc false |
| 88 | + def app_path(:lib_core), do: Path.join(["lib", app_name()]) |
| 89 | + |
| 90 | + @doc false |
| 91 | + def app_path(:test_core), do: Path.join(["test", app_name()]) |
| 92 | + |
| 93 | + @doc false |
| 94 | + def app_path(:lib_web), do: app_path(:lib_core) <> "_web" |
| 95 | + |
| 96 | + @doc false |
| 97 | + def app_path(:test_web), do: app_path(:test_core) <> "_web" |
| 98 | + |
| 99 | + @web_template_path "priv/templates/scribe.gen.html" |
| 100 | + @doc false |
| 101 | + def web_template_path(), do: @web_template_path |
| 102 | + |
| 103 | + @html_template_path @web_template_path |> Path.join("html") |
| 104 | + @doc false |
| 105 | + def html_template_path(), do: @html_template_path |
| 106 | + |
| 107 | + @controller_template_path @web_template_path |> Path.join("controllers") |
| 108 | + @doc false |
| 109 | + def controller_template_path(), do: @controller_template_path |
| 110 | + |
| 111 | + @controller_test_template_path Path.join([@web_template_path, "tests", "controllers"]) |
| 112 | + @doc false |
| 113 | + def controller_test_template_path(), do: @controller_test_template_path |
| 114 | + |
| 115 | + @domain_template_path "priv/templates/scribe.gen.domain" |
| 116 | + @doc false |
| 117 | + def domain_template_path(), do: @domain_template_path |
| 118 | + |
| 119 | + @domain_tests_template_path @domain_template_path |> Path.join("tests") |
| 120 | + @doc false |
| 121 | + def domain_tests_template_path(), do: @domain_tests_template_path |
| 122 | + |
| 123 | + @domain_api_template_path @domain_template_path |> Path.join("apis") |
| 124 | + @doc false |
| 125 | + def domain_api_template_path(), do: @domain_api_template_path |
| 126 | + |
| 127 | + @resource_actions_template_path @domain_template_path |> Path.join("actions") |
| 128 | + @doc false |
| 129 | + def resource_actions_template_path(), do: @resource_actions_template_path |
| 130 | + |
| 131 | + @resource_test_actions_template_path @domain_tests_template_path |> Path.join("actions") |
| 132 | + @doc false |
| 133 | + def resource_test_actions_template_path(), do: @resource_test_actions_template_path |
| 134 | + |
| 135 | + # @IMPORTANT: Order of actions MATTERS, otherwise routes will not work as |
| 136 | + # expected. Don't allow override from config, but allow to set aliases. |
| 137 | + @default_resource_actions ["list", "new", "read", "edit", "create", "update", "delete"] |
| 138 | + @doc false |
| 139 | + def resource_actions() do |
| 140 | + Application.get_env(:elixir_scribe, :default_resource_actions, @default_resource_actions) |
| 141 | + end |
| 142 | + |
| 143 | + @doc false |
| 144 | + def resource_actions_aliases() do |
| 145 | + Application.get_env(:elixir_scribe, :resource_actions_aliases, %{}) |
| 146 | + end |
| 147 | + |
| 148 | + @doc false |
| 149 | + def resource_action_alias(action) do |
| 150 | + resource_actions_aliases() |> Map.get(action, action) |
| 151 | + end |
| 152 | + |
| 153 | + @resource_html_actions ["read", "new", "edit", "list"] |
| 154 | + @doc false |
| 155 | + def resource_html_actions() do |
| 156 | + Application.get_env(:elixir_scribe, :resource_html_actions, @resource_html_actions) |
| 157 | + end |
| 158 | + |
| 159 | + @resource_plural_actions ["index", "list"] |
| 160 | + @doc false |
| 161 | + def resource_plural_actions() do |
| 162 | + Application.get_env(:elixir_scribe, :resource_plural_actions, @resource_plural_actions) |
| 163 | + end |
| 164 | + |
| 165 | + @doc false |
| 166 | + def schema_template_folder_name(%ElixirScribe.Generator.SchemaContract{} = schema) do |
| 167 | + if schema.generate? do |
| 168 | + "schema_access" |
| 169 | + else |
| 170 | + "no_schema_access" |
| 171 | + end |
| 172 | + end |
| 173 | + |
| 174 | + @app_file_extensions [".ex", ".exs", "html.heex"] |
| 175 | + @doc false |
| 176 | + def app_file_extensions(), do: @app_file_extensions |
| 177 | + |
| 178 | + @app_file_types ["", "controller", "controller_test", "test"] |
| 179 | + @doc false |
| 180 | + def app_file_types(), do: @app_file_types |
| 181 | + |
| 182 | + @app_path_types [:lib_core, :lib_web, :test_core, :test_web] |
| 183 | + @doc false |
| 184 | + def app_path_types(), do: @app_path_types |
| 185 | + |
| 186 | + # @TODO Remove once `mix phx.gem.schema` is ported to `mix scribe.gen.schema`. |
| 187 | + @doc false |
| 188 | + def to_phoenix_schema(%ElixirScribe.Generator.SchemaContract{} = schema) do |
| 189 | + attrs = Map.from_struct(schema) |
| 190 | + struct(Mix.Phoenix.Schema, attrs) |
| 191 | + end |
3 | 192 | end |
0 commit comments