Skip to content

(WIP) Support for providing of parameters at path level and overriding them… #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 28 additions & 11 deletions openapi3-code-generator/src/OpenAPI/Generate/Internal/Operation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ getInFromParameterObject :: OAT.ParameterObject -> OAT.ParameterObjectLocation
getInFromParameterObject = OAT.in'

-- | Generates the parameter type for an operation. See 'ParameterCardinality' for further information.
generateParameterTypeFromOperation :: Text -> OAT.OperationObject -> OAM.Generator ParameterCardinality
generateParameterTypeFromOperation operationName = getParametersFromOperationConcrete >=> generateParameterType operationName
generateParameterTypeFromOperation :: [OAT.Referencable OAT.ParameterObject] -> Text -> OAT.OperationObject -> OAM.Generator ParameterCardinality
generateParameterTypeFromOperation pathParams operationName = getParametersFromOperationConcrete pathParams >=> generateParameterType operationName

generateParameterType :: Text -> [(OAT.ParameterObject, [Text])] -> OAM.Generator ParameterCardinality
generateParameterType operationName parameters = OAM.nested "parameters" $ do
Expand Down Expand Up @@ -159,12 +159,20 @@ getParameterLocationPrefix =
)
. getInFromParameterObject

-- | Extracts all parameters of an operation
--
-- Concrete objects are always added. References try to get resolved to a concrete object.
-- If this fails, the parameter is skipped and a warning gets produced.
getParametersFromOperationConcrete :: OAT.OperationObject -> OAM.Generator [(OAT.ParameterObject, [Text])]
getParametersFromOperationConcrete =
-- | Override parameters defined at path level with parameters which are defined at operation level
overrideParameters :: [(OAT.ParameterObject, [Text])] -> [(OAT.ParameterObject, [Text])] -> [(OAT.ParameterObject, [Text])]
overrideParameters pathParams operationParams =
-- According to OpenAPI specification, the unique parameter is identified by a combination of name and location.
-- So, we are using (name, in') as key in these maps.
let mkParamsMap parameters = Map.fromList [((getNameFromParameter (fst p), getInFromParameterObject (fst p)), p) | p <- parameters]
pathParamsMap = mkParamsMap pathParams
operationParamsMap = mkParamsMap operationParams
-- prefer operation parameters
allParamsMap = Map.union operationParamsMap pathParamsMap
in Map.elems allParamsMap

getConcreteParameters :: [OAT.Referencable OAT.ParameterObject] -> OAM.Generator [(OAT.ParameterObject, [Text])]
getConcreteParameters =
OAM.nested "parameters"
. fmap Maybe.catMaybes
. mapM
Expand All @@ -179,7 +187,16 @@ getParametersFromOperationConcrete =
pure $ (,["components", "parameters", name]) <$> p
)
. zip ([0 ..] :: [Int])
. getParametersFromOperationReference

-- | Extracts all parameters of an operation
--
-- Concrete objects are always added. References try to get resolved to a concrete object.
-- If this fails, the parameter is skipped and a warning gets produced.
getParametersFromOperationConcrete :: [OAT.Referencable OAT.ParameterObject] -> OAT.OperationObject -> OAM.Generator [(OAT.ParameterObject, [Text])]
getParametersFromOperationConcrete pathParameters operation = do
operationParameters <- getConcreteParameters $ getParametersFromOperationReference operation
concretePathParameters <- getConcreteParameters pathParameters
pure $ overrideParameters concretePathParameters operationParameters

getSchemaFromParameterObjectSchema :: OAT.ParameterObjectSchema -> OAM.Generator (Maybe OAS.Schema)
getSchemaFromParameterObjectSchema (OAT.SimpleParameterObjectSchema OAT.SimpleParameterSchema {..}) = pure $ Just schema
Expand Down Expand Up @@ -282,9 +299,9 @@ defineOperationFunction useExplicitConfiguration fnName parameterCardinality req
if getInFromParameterObject parameter == OAT.PathParameterObjectLocation
then ([paramExpr], [])
else ([], [paramExpr])
MultipleParameters paramDefinition ->
MultipleParameters paramDefinition -> do
let toParamExpr f = BF.first (\name -> [|$(varE name) $(varE paramName)|]) <$> f paramDefinition
in pure (toParamExpr parameterTypeDefinitionPathParams, toParamExpr parameterTypeDefinitionQueryParams)
pure (toParamExpr parameterTypeDefinitionPathParams, toParamExpr parameterTypeDefinitionQueryParams)
let queryParameters' = generateQueryParams queryParameters
request = generateParameterizedRequestPath pathParameters requestPath
methodLit = stringE $ T.unpack method
Expand Down
11 changes: 8 additions & 3 deletions openapi3-code-generator/src/OpenAPI/Generate/Operation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,16 @@ import qualified OpenAPI.Generate.OptParse as OAO
import qualified OpenAPI.Generate.Response as OAR
import qualified OpenAPI.Generate.Types as OAT

getParametersFromPath :: OAT.PathItemObject -> [OAT.Referencable OAT.ParameterObject]
getParametersFromPath = OAT.parameters

-- | Defines the operations for all paths and their methods
defineOperationsForPath :: String -> Text -> OAT.PathItemObject -> OAM.Generator (Q [Dep.ModuleDefinition], Dep.Models)
defineOperationsForPath mainModuleName requestPath pathItemObject = OAM.nested requestPath $ do
operationsToGenerate <- OAM.getSetting OAO.settingOperationsToGenerate
fmap (BF.bimap sequence Set.unions)
. mapAndUnzipM
(uncurry (defineModuleForOperation mainModuleName requestPath))
(uncurry (defineModuleForOperation mainModuleName requestPath (getParametersFromPath pathItemObject)))
$ filterEmptyAndOmittedOperations
operationsToGenerate
[ ("GET", OAT.get pathItemObject),
Expand Down Expand Up @@ -68,13 +71,15 @@ defineModuleForOperation ::
-- | The path to the request (This is the key from the map of Operations)
-- It may contain placeholder variables in the form of /my/{var}/path/
Text ->
-- | Path parameter definition
[OAT.Referencable OAT.ParameterObject] ->
-- | HTTP Method (GET,POST,etc)
Text ->
-- | The Operation Object
OAT.OperationObject ->
-- | commented function definition and implementation
OAM.Generator (Q Dep.ModuleDefinition, Dep.Models)
defineModuleForOperation mainModuleName requestPath method operation = OAM.nested method $ do
defineModuleForOperation mainModuleName requestPath pathParams method operation = OAM.nested method $ do
operationIdName <- getOperationName requestPath method operation
convertToCamelCase <- OAM.getSetting OAO.settingConvertToCamelCase
let operationIdAsText = T.pack $ show operationIdName
Expand All @@ -84,7 +89,7 @@ defineModuleForOperation mainModuleName requestPath method operation = OAM.neste
(bodySchema, bodyPath) <- getBodySchemaFromOperation operation
(responseTypeName, responseTransformerExp, responseBodyDefinitions, responseBodyDependencies) <- OAR.getResponseDefinitions operation appendToOperationName
(bodyType, (bodyDefinition, bodyDependencies)) <- OAM.resetPath bodyPath $ getBodyType bodySchema appendToOperationName
parameterCardinality <- generateParameterTypeFromOperation operationIdAsText operation
parameterCardinality <- generateParameterTypeFromOperation pathParams operationIdAsText operation
paramDescriptions <-
(<> ["The request body to send" | not $ null bodyType])
<$> ( case parameterCardinality of
Expand Down
2 changes: 1 addition & 1 deletion openapi3-code-generator/src/OpenAPI/Generate/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ data ParameterObjectLocation
| HeaderParameterObjectLocation
| PathParameterObjectLocation
| CookieParameterObjectLocation
deriving (Show, Eq, Generic)
deriving (Show, Eq, Ord, Generic)

instance FromJSON ParameterObjectLocation where
parseJSON = withText "ParameterObjectLocation" $ \case
Expand Down