Yes, that is the solution to my problem. I will run it each time I run open-generator.
Sorry for late response. Iām glad you like my ideas. Would you like me to re-base and open a PR with what I have so far? Or would you rather start from scratch?
Very good idea. Even generation of requests will be easier that way.
No problem. I already started working on a major refactoring. Iāve changed so much a PR wouldnāt make much sense.
First release
As the matter of fact I planned on publishing a first version here on discourse today. It does not yet support allOf
and recursive types, but it would be great to have some first feedback. The current changes include:
- Drop support for Elm 0.18;
- Drop
Main.elm
; - Put all models in a single file;
- Nest generated code in a module called
Api
, i.e.Api.Data
for models andApi.Request.*
for operations; - Introduce the
Request
type for improved customization of requests (operations).
You can download the jar here. Use it by running
java -jar openapi-generator-cli.jar generate -i /your/openapi.yaml -g elm -o /path/to/write/to
# smoke test the output
cd /path/to/write/to
elm make src/**/*.elm
When you run into an issue and would like to report it, please provide a minimal fully working yaml/json file so I can easily reproduce the issue.
Any comments/suggestions/errors are welcome!
Thank you! I tested it on my project. There are a generic object in the api, a class called ProblemDetails that belongs to Asp.Net Core 3.0, so I need to delete the following from the swagger.json
,
"extensions": {
"type": "object",
"nullable": true,
"additionalProperties": {}
}
Once I removed that and generate, it will create the non-ok recursive definition:
type alias FormElement =
{ name : String
:
, elements : Maybe (List FormElement)
}
After removing the field elements in the elm code and in the encoder+decoder, the Elm compiler complains about more things. I use Elm 0.19.
You can find the swagger.json file at https://send.firefox.com/download/bcfa78a4c3bbf523/#Fq54jecJJPXS2jp6x1KyWA
Thanks for your report @mattiasw.
- I think it would only make sense to map the
additionalProperties: {}
to aDict String ()
as it can be of any type. However, this makes it quite useless; - Recursion is still on its way;
- The other issues I have fixed.
Please try this updated jar. Thanks.
@eriktimmers Thank you for your hard work. Yes, you are correct. All problems are solved.
Regarding the extensions field for ProblemDetails, I think it should not even be there. There is a specification for it: https://tools.ietf.org/html/rfc7807 and I actually think that NSwag and/or Aspnet handles it incorrectly. I think the intention is that all key-value pairs in extensions should be lifted to top level in ProblemDetails.
Improvement suggestion: NSwag also includes the names for enums, and they could be used for creating union types. In my case, the names are String, Number and Bool. The union names should probably be something like EValueType_String, EValueType_Number , EValueType_Boo
l. Here is a similar request: https://github.com/swagger-api/swagger-ui/issues/5272
"EValueType": {
"type": "integer",
"description": "",
"x-enumNames": [
"String",
"Number",
"Bool"
],
"enum": [
0,
1,
2
]
},
Let me know when you fixed the recursion too, and I will remove all remnants of the old generated code.
Thanks, @mattiasw. I wanted to refactor anyway so I have a good test case now.
I am not sure about the x-enumNames
yet. They donāt seem part of the official spec and Iām not sure I want to support custom extensions at this point. Why is the enum not generated using the names in the first place?
I am almost done with the allOf
support. After that Iāll start working on the recursion. My PR for that has just been merged into the generator.
The x-enumNames feature seems only to be used by nswag currently, so I understand low prio.
Most likely, it is only needed for C#, which represents enums as numbers internally. It is only really useful in the intersection C# on the server, and a client language with enums or union types. So, it wouldnāt surprise me if the only openapi generator that supports it is the one for typescript, https://www.typescriptlang.org/docs/handbook/enums.html
Keep us posted. To make it easier to find by other elm:ers, it is also listed at https://korban.net/elm/catalog/ but maybe you can add some elm specific information somewhere.
Even if C# uses numbers internally the (de)serialization could handle strings, right? But OK, I do not know the details for that.
Hereās a new release including support for allOf
. Using allOf
adds all properties to another type. If the original type also has a discriminator
(1) the original type is added using composition and (2) a custom type is creating with all the possible sub-types and a fallback base type (see my edited comment above).
The indentation of the generated files stopped working, so you generate something like this:
type alias BOAttachment =
{ filename : String
, url : String
}
Used to work fine.
Thatās weird. āWorks on my machineā. Can you try on another device?
Hereās a new one with support for recursive types! Please give it a try!
I still have the indentation problem. I am using the swagger.json file I linked to previously. After adding elm-format, it compiles fine. Remove it, and Data.elm fails.
The recursive structure seems ok and compiles, however, I have not tested it yet in my code.
This is the Windows cmd file I run
java -jar openapi-generator-cli-4.jar generate -g elm -i swagger.json -o src/Swagger/
cd src/Swagger/
call elm-format --yes ./src/
call elm make src/Api.elm src/Api/Data.elm src/Api/Request/Acc.elm src/Api/Request/Account.elm src/Api/Request/Attachment.elm src/Api/Request/Cmd.elm src/Api/Request/CmdAdmin.elm src/Api/Request/CmdGuest.elm src/Api/Request/Frm.elm src/Api/Request/Grid.elm src/Api/Request/Home.elm src/Api/Request/Ins.elm src/Api/Request/InsPdf.elm src/Api/Request/InsView.elm src/Api/Request/LoggedOut.elm src/Api/Request/NoAccount.elm src/Api/Request/SignIn.elm src/Api/Request/UserContext.elm src/Api/Request/Usr.elm src/Api/Request/Version.elm
cd ..
cd ..
Iāll see if I can reproduce it on another machine.
Forgot to export the recursion type. Try this one instead.
Another update!
- Add missing catch-all type for
allOf
s; - Drop support for post-processing of files;
- Only import UUID/Time when actually used.
Applied the code generated with openapi-generator-cli-6.jar to the whole project. Two bugs detected, first one in this entry.
The type is enum over ints, however the code assumes the server sends values as string:
"EValueType": {
"type": "integer",
"description": "",
"x-enumNames": [
"String",
"Number",
"Bool"
],
"enum": [
0,
1,
2
]
},
I had to patch the generated code like this:
eValueTypeDecoder : Json.Decode.Decoder EValueType
eValueTypeDecoder =
Json.Decode.string
|> Json.Decode.andThen
(\str ->
case str of
"0" ->
Json.Decode.succeed EValueType0
"1" ->
Json.Decode.succeed EValueType1
"2" ->
Json.Decode.succeed EValueType2
other ->
Json.Decode.fail <| "Unknown type: " ++ other
)
to
eValueTypeDecoder : Json.Decode.Decoder EValueType
eValueTypeDecoder =
Json.Decode.int
|> Json.Decode.andThen
(\str ->
case str of
0 ->
Json.Decode.succeed EValueType0
1 ->
Json.Decode.succeed EValueType1
2 ->
Json.Decode.succeed EValueType2
other ->
Json.Decode.fail <| "Unknown type: " -- ++ other
)
Also, I expected the Error case to pop up just like during network problem, but instead I had to debug the javascript to find out why it failed.
The urls contains a double // in url, for example http://localhost:5000//Acc/current/forms
Fixed by removing the initial / in the path on all files in Request directory.
cmdGet : String -> Api.Request Api.Data.Form
cmdGet cmdName =
Api.request
"GET"
"/Cmd/{cmdName}"
[ ( "cmdName", identity cmdName ) ]
[]
[]
Nothing
Api.Data.formDecoder
to
cmdGet : String -> Api.Request Api.Data.Form
cmdGet cmdName =
Api.request
"GET"
"Cmd/{cmdName}"
[ ( "cmdName", identity cmdName ) ]
[]
[]
Nothing
The indentation problem is still there, but I run elm-format every time, so not important.
Also, any special reason you have the parameters for Api.send in that order? If you swap them, same order as v1 Http.send, all I have to do is replace my Http.send to Api.send in the rest of the project.
@mattiasw thanks for the feedback!
Good point. Iāll make it work with integers as well.
Can you elaborate on this? I donāt understand what you mean.
I think you should fix the base path in your OpenAPI JSON. It should not end with /
if you want to get rid of the //
. The path in the request itself is correct.
I still would like to have this fixed. Were you able to run this on a second machine? I still havenāt been able to reproduce this.
Nope I did that by accident. Already fixed it in my unreleased code.
Iāve also started working on a Gitbook for some background, guidance and technical details on the OpenAPI Generator and Elm. Would be great if you could have a look when itās ready.
Thanks @eriktimmers for the quick response!
Look at the screenshot above, that is how I found that Elm expected a string, and got an int. I expected it would have been by an Err-msg, i.e. that my client would have presented it as any Http-ajax-error message, for example a network timeout.
In the swagger.json file, there is no /, it says:
"servers": [
{
"url": "http://localhost:5000"
}
],