Skip to content

Commit 194d421

Browse files
halostatuemrmstn
andauthored
Further Elixir Client Improvements (#12775)
* Further Elixir Client Improvements Resolves #12731 and is the completion of the work that I started with #12751. The changes here are extensive and likely resolve an issue that I have seen with the Ory SDK (ory/sdk#194). I have also been unable to run the integration suite for Elixir as I am (trying) to run everything in Docker (`./run-in-docker.sh`) as I *do not* have a suitable Java development environment set up, and do not do enough Java work to really justify it. - Updated the README for Elixir projects. Aside from some improved readability of the template by use of link references instead of inline links, I have also fixed the examples: - The `deps` example should have been putting a version constraint related to `appVersion`. - The `config` example should have been using `packageName` instead of `appName`. This particular issue repeats. - In all Elixir files: - Changed the function `@docs` formatting: - changed the ehading level for `Parameters` and `Returns` to h3 (`###` instead of `##`). This will make somewhat better looking documentation that does not over-emphasize these details (which are *not* documented in a normal Elixir way, but this is somewhat to be expected with a code generator.) It may be desirable, after testing, to change this to `h4` instead of `h3`. - Put parameter names and most return types in in-line code blocks (`` `hello` ``). - Put return types, when there are multiple types, in a Markdown list. - Fixed a lot of the spacing. Most files will be *closer* to Elixir standard formatting than they were. Because of the limitations of Mustache, it is still recommended that people who generate Elixir clients run `mix format` at least once on their codebase. - `api.mustache`: - Removed an awkward function pipeline call. If we specified at least Elixir 1.12 (something that I do not recommend as we have recently jumped from requiring Elixir 1.6 to Elixir 1.10), there is a better way to specify this now with `Kernel.then/2`. In the meantime, assigning the constructed request structure to a variable and then making a separate pipeline for the request execution and handling makes for *much* easier to read generated code. - Fixed the extra space issue with `evaluate_response` call tuple values; `{{=<% %>=}}` changes the tag types, so this change is intentional. - In `config.exs.mustache`, `runtime.exs.mustache`, `mix.exs.mustache`, and `connection.ex.mustache`, use `packageName` instead of `appName` for configuration specification. If `packageName` and `appName` differed, we would end up with cases like ory/sdk#194. - `connection.ex.mustache` has been almost entirely rewritten. The changes started in order to eliminate a `@doc` compile-time warning, but shifted to remove the old way of building Tesla client structs with `use Tesla`. It works, but is no longer the recommended way of building Tesla clients. - The *recommended* way of building a Tesla Client would now be `Tesla.client(Connection.middleware(), Connection.adapter())`. - Exposed both `Connection.adapter/0` and `Connection.middleware/1` for use. `Connection.middleware/1` has special handling for the cases where OAuth2 or HTTP Basic Auth are defined in the application, but do not currently handle any other auth methods. - `deserializer.ex.mustache` has mostly been reformatted. There are things that I do not like about it (I do not like pipelines with one line), and I have expanded one function capture into an anonymous function for readability. - `request_builder.ex.mustache` has been updated with better function and parameter descriptions and names. Please note that if `request |> method(:delete) |> method(:post)` is supposed to produce a `POST` operation, we will need to change from `Map.put_new/3` to `Map.put/3`. - Reordered `evaluate_response/2` so that it is the function documented, and made `decode/2` and `response_mapping/3` private functions. As far as I can tell, I have *not* changed the functionality. * Address issues found in code review - The example dependency code in the README had dropped the opening brace for the tuple. This has been resolved. - The default formatting of the API pipelines has been adjusted to minimize possible changes from `mix format`. * Update modules/openapi-generator/src/main/resources/elixir/api.mustache Co-authored-by: Michael Ramstein <633688+mrmstn@users.noreply.github.com> * Update modules/openapi-generator/src/main/resources/elixir/connection.ex.mustache Co-authored-by: Michael Ramstein <633688+mrmstn@users.noreply.github.com> * Update modules/openapi-generator/src/main/resources/elixir/connection.ex.mustache Co-authored-by: Michael Ramstein <633688+mrmstn@users.noreply.github.com> * Update templates based on review comments Co-authored-by: Michael Ramstein <633688+mrmstn@users.noreply.github.com>
1 parent c59759f commit 194d421

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+1729
-1183
lines changed

modules/openapi-generator/src/main/resources/elixir/README.md.mustache

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,46 @@
22

33
{{appDescription}}
44

5-
### Building
5+
## Building
66

77
To install the required dependencies and to build the elixir project, run:
8-
```
8+
9+
```console
910
mix local.hex --force
1011
mix do deps.get, compile
1112
```
1213

1314
## Installation
1415

15-
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
16-
by adding `{{#underscored}}{{packageName}}{{/underscored}}` to your list of dependencies in `mix.exs`:
16+
If [available in Hex][], the package can be installed by adding `{{#underscored}}{{packageName}}{{/underscored}}` to
17+
your list of dependencies in `mix.exs`:
1718

1819
```elixir
19-
def deps do
20-
[{:{{#underscored}}{{packageName}}{{/underscored}}, "~> 0.1.0"}]
21-
end
20+
{{=<% %>=}}def deps do
21+
[{<%#atom%><%#underscored%><%packageName%><%/underscored%><%/atom%>, "~> <%appVersion%>"}]
22+
end<%={{ }}=%>
2223
```
2324

24-
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
25-
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
26-
be found at [https://hexdocs.pm/{{#underscored}}{{packageName}}{{/underscored}}](https://hexdocs.pm/{{#underscored}}{{packageName}}{{/underscored}}).
27-
25+
Documentation can be generated with [ExDoc][] and published on [HexDocs][]. Once published, the docs can be found at
26+
[https://hexdocs.pm/{{#underscored}}{{packageName}}{{/underscored}}][docs].
2827

2928
## Configuration
3029

31-
You can override the URL of your server (e.g. if you have a separate development and production server in your configuration files.
30+
You can override the URL of your server (e.g. if you have a separate development and production server in your
31+
configuration files).
32+
33+
```elixir
34+
config :{{#underscored}}{{packageName}}{{/underscored}}, base_url: "{{{basePath}}}"
35+
```
36+
37+
Multiple clients for the same API with different URLs can be created passing different `base_url`s when calling
38+
`{{moduleName}}.Connection.new/1`:
39+
3240
```elixir
33-
config :{{#underscored}}{{appName}}{{/underscored}}, base_url: "{{{basePath}}}"
34-
```
41+
client = {{moduleName}}.Connection.new(base_url: "{{{basePath}}}")
42+
```
43+
44+
[exdoc]: https://github.com/elixir-lang/ex_doc
45+
[hexdocs]: https://hexdocs.pm
46+
[available in hex]: https://hex.pm/docs/publish
47+
[docs]: https://hexdocs.pm/{{#underscored}}{{packageName}}{{/underscored}}

modules/openapi-generator/src/main/resources/elixir/api.mustache

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ defmodule {{moduleName}}.Api.{{classname}} do
66

77
alias {{moduleName}}.Connection
88
import {{moduleName}}.RequestBuilder
9-
109
{{#operations}}
11-
{{#operation}}
10+
{{#operation}}
1211

1312
@doc """
1413
{{#summary}}
@@ -18,25 +17,26 @@ defmodule {{moduleName}}.Api.{{classname}} do
1817
{{&notes}}
1918
{{/notes}}
2019

21-
## Parameters
20+
### Parameters
2221

23-
- connection ({{&moduleName}}.Connection): Connection to server
22+
- `connection` ({{&moduleName}}.Connection): Connection to server
2423
{{#requiredParams}}
25-
- {{#underscored}}{{&paramName}}{{/underscored}} ({{&dataType}}): {{&description}}
24+
- `{{#underscored}}{{&paramName}}{{/underscored}}` ({{&dataType}}): {{&description}}
2625
{{/requiredParams}}
27-
- opts (KeywordList): [optional] Optional parameters
26+
- `opts` (keyword): Optional parameters
2827
{{#optionalParams}}
2928
{{#isBodyParam}}
30-
- :body ({{dataType}}): {{&description}}
29+
- `:body` ({{dataType}}): {{&description}}
3130
{{/isBodyParam}}
3231
{{^isBodyParam}}
33-
- {{#underscored}}:{{&paramName}}{{/underscored}} ({{&dataType}}): {{&description}}
32+
- `{{#atom}}{{#underscored}}{{&paramName}}{{/underscored}}{{/atom}}` ({{&dataType}}): {{&description}}
3433
{{/isBodyParam}}
3534
{{/optionalParams}}
36-
## Returns
3735

38-
{:ok, {{#isArray}}[%{{&returnBaseType}}{}, ...]{{/isArray}}{{#isMap}}%{}{{/isMap}}{{^returnType}}nil{{/returnType}}{{#returnSimpleType}}{{#returnType}}{{{.}}}{{/returnType}}{{/returnSimpleType}}} on success
39-
{:error, Tesla.Env.t} on failure
36+
### Returns
37+
38+
- `{:ok, {{#isArray}}[%{{&returnBaseType}}{}, ...]{{/isArray}}{{#isMap}}%{}{{/isMap}}{{^returnType}}nil{{/returnType}}{{#returnSimpleType}}{{#returnType}}{{{.}}}{{/returnType}}{{/returnSimpleType}}}` on success
39+
- `{:error, Tesla.Env.t}` on failure
4040
"""
4141
{{{typespec}}}
4242
def {{{operationId}}}(connection, {{#requiredParams}}{{#underscored}}{{{paramName}}}{{/underscored}}, {{/requiredParams}}{{^hasOptionalParams}}_{{/hasOptionalParams}}opts \\ []) do
@@ -52,29 +52,33 @@ defmodule {{moduleName}}.Api.{{classname}} do
5252
{{/isBodyParam}}
5353
{{#-last}}
5454
}
55+
5556
{{/-last}}
5657
{{/optionalParams}}
57-
%{}
58-
|> method(:{{#underscored}}{{httpMethod}}{{/underscored}})
59-
|> url("{{replacedPathName}}")
58+
request =
59+
%{}
60+
|> method({{#atom}}{{#underscored}}{{httpMethod}}{{/underscored}}{{/atom}})
61+
|> url("{{replacedPathName}}")
6062
{{#requiredParams}}
6163
{{^isPathParam}}
62-
|> add_param({{#isBodyParam}}:body{{/isBodyParam}}{{#isFormParam}}{{#isMultipart}}{{#isFile}}:file{{/isFile}}{{^isFile}}:form{{/isFile}}{{/isMultipart}}{{^isMultipart}}:form{{/isMultipart}}{{/isFormParam}}{{#isQueryParam}}:query{{/isQueryParam}}{{#isHeaderParam}}:headers{{/isHeaderParam}}, {{#isBodyParam}}:body, {{/isBodyParam}}{{^isBodyParam}}{{#atom}}{{baseName}}{{/atom}}, {{/isBodyParam}}{{#underscored}}{{paramName}}{{/underscored}})
64+
|> add_param({{#isBodyParam}}:body{{/isBodyParam}}{{#isFormParam}}{{#isMultipart}}{{#isFile}}:file{{/isFile}}{{^isFile}}:form{{/isFile}}{{/isMultipart}}{{^isMultipart}}:form{{/isMultipart}}{{/isFormParam}}{{#isQueryParam}}:query{{/isQueryParam}}{{#isHeaderParam}}:headers{{/isHeaderParam}}, {{#isBodyParam}}:body{{/isBodyParam}}{{^isBodyParam}}{{#atom}}{{baseName}}{{/atom}}{{/isBodyParam}}, {{#underscored}}{{paramName}}{{/underscored}})
6365
{{/isPathParam}}
6466
{{/requiredParams}}
6567
{{#optionalParams}}
6668
{{#-first}}
67-
|> add_optional_params(optional_params, opts)
69+
|> add_optional_params(optional_params, opts)
6870
{{/-first}}
6971
{{/optionalParams}}
7072
{{#requiresHttpcWorkaround}}
71-
|> ensure_body()
73+
|> ensure_body()
7274
{{/requiresHttpcWorkaround}}
73-
|> Enum.into([])
74-
|> (&Connection.request(connection, &1)).()
75+
|> Enum.into([])
76+
77+
connection
78+
|> Connection.request(request)
7579
|> evaluate_response({{#responses}}{{#-first}}[
7680
{{/-first}}
77-
{ {{& codeMappingKey}}, {{decodedStruct}}}{{^-last}},{{/-last}}
81+
{{=<% %>=}}{<%& codeMappingKey%>, <%decodedStruct%>}<%={{ }}=%>{{^-last}},{{/-last}}
7882
{{#-last}} ]{{/-last}}{{/responses}})
7983
end
8084
{{/operation}}

modules/openapi-generator/src/main/resources/elixir/config.exs.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# General application configuration
88
import Config
99

10-
config :{{#underscored}}{{appName}}{{/underscored}}, base_url: "{{{basePath}}}"
10+
config {{#atom}}{{#underscored}}{{packageName}}{{/underscored}}{{/atom}}, base_url: "{{{basePath}}}"
1111

1212
# Import environment specific config. This must remain at the bottom
1313
# of this file so it overrides the configuration defined above.

0 commit comments

Comments
 (0)