Closed kindaro closed 6 months ago
Actually, it looks like this change will entail a wide refactoring. There are some places where local references are hard coded, like so:
-- | Maps the subtypes of components to the entries of the 'ReferenceMap' and filters references (the lookup table should only contain concrete values).
buildReferencesForComponentType ::
Text ->
(a -> ComponentReference) ->
Map.Map Text (OAT.Referencable a) ->
[(Text, ComponentReference)]
buildReferencesForComponentType componentName constructor =
fmap (BF.first (("#/components/" <> componentName <> "/") <>))
. Maybe.mapMaybe (convertReferencableToReference constructor)
. Map.toList
It seems best to make a new sum type for references.
Alright, I know how to solve this.
I am going to write a JSON parser that follows references, either within our outside the given file. It shall have type ByteString → IO Value
. Then I am going to wire it into the program instead of decodeFileEither
here:
-- | Decodes an OpenAPI File
decodeOpenApi :: Text -> IO OAT.OpenApiSpecification
decodeOpenApi fileName = do
res <- decodeFileEither $ T.unpack fileName
case res of
Left exc -> die $ "Could not parse OpenAPI specification '" <> T.unpack fileName <> "': " <> show exc
Right o -> pure o
This code is already in IO
, so we can read all the referenced files and even follow HTTP links right here.
This will also make the code that currently handles references needless, so I shall remove that code.
@kindaro Before you spend too much time going down this rabit hole: is the example that you showed even a valid OpenAPI spec?
Yes. Here is the relevant piece of OpenAPI specification.
By the way, I just noticed: OpenAPI specification says that references are only allowed in specific places of an OpenAPI document. But I think it will be easier for us to unfold references everywhere in JSON, than to sift through the whole specification and make sure we throw an error when a reference is found where it is not allowed. If we are somewhat more lenient than specified, this is even better, right?
Turns out we cannot simply unfold all references, because cyclic references are allowed by the specification and handy in practice, but trying to unfold them will not end. See https://github.com/OAI/OpenAPI-Specification/issues/822 for discussion and examples of cyclic references.
Instead, it seems I should need to build some kind of a «map» that accounts for all files connected by references, and all references that show up in those files. It is not super clear how to do this yet. One problem is that references can be relative. Textually identical references that show up in different files can refer to different stuff, and textually different references that show up in different files can refer to the same thing. If we want to have a map with references being keys and pieces of Data.Aeson.Value
being values, it seems we should «normalize» references so that textually different references refer to different stuff, and textually identical references refer to the same thing, before building our map. It is not super clear how to perform such a normalization.
I am going to try to fix this issue, but I cannot promise anything. If you do not hear from me within a week, I must have decided to try something else instead.
Based on this I assume that the plan to implement this here has been abandoned, so I'll close this issue for the moment. I think it would be neat to have this in the generator but I do not have the time currently to implement it myself. If someone has a PR implementing this, I'll definitely have a look.
see for yourself
Apply the following diff:
Create the following file:
specifications/petstore-Category.yaml
Run
openapi3-code-generator-exe petstore.yaml
.what I see
As you see,
out/src/OpenAPI/Types/Category.hs
is never generated. Consequently, the generated package does not build.what I want to see
Everything builds.
why I think it should
This can be done.
openapi-generator generate --input-spec petstore.yaml --generator-name 'haskell-http-client'
successfully generates a Haskell package that builds and includes a data typePetstoreCategory
according to specification. It seems we only need to tweak the parser of references and teach it to go get the file being referred.what I am going to do
I am going to try to fix this issue, but I cannot promise anything. If you do not hear from me within a week, I must have decided to try something else instead.