Skip to content
Merged
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
1 change: 1 addition & 0 deletions nix/tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ let
(generateCode { fileName = "spot_api.yml"; extraFlags = [ "--opaque-schema=\"aggTrade\"" ]; })
(generateCode { fileName = "uber.json"; })
(generateCode { fileName = "z_complex_self_made_example.yml"; })
(generateCode { fileName = "petstore.yaml"; extraFlags = [ "--module-name=\"Petstore.API\"" ]; })
];
codeForSpecsLevelTwo = [
(generateCode { fileName = "official-petstore.yaml"; })
Expand Down
41 changes: 23 additions & 18 deletions openapi3-code-generator/src/OpenAPI/Generate/IO.hs
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,18 @@ permitProceed settings = do
getHsBootFiles :: OAO.Settings -> [([String], String)] -> FilesWithContent
getHsBootFiles settings modelModules =
let outputDirectory = T.unpack $ OAO.settingOutputDir settings
moduleName = T.unpack $ OAO.settingModuleName settings
moduleName = OAO.settingModuleName settings
moduleNameStr = OAO.getModuleName moduleName
modulePathInfo = OAO.mkModulePathInfo moduleName
in BF.bimap
((outputDirectory </>) . (srcDirectory </>) . (moduleName </>) . (<> ".hs-boot") . foldr1 (</>))
((\suffix -> outputDirectory </> srcDirectory </> OAO.getModuleInfoPath modulePathInfo (Just suffix) ".hs-boot") . foldr1 (</>))
( T.unpack
. T.unlines
. ( \xs -> case xs of
x : xs' ->
x
: "import qualified Data.Aeson"
: "import qualified " <> T.pack moduleName <> ".Common"
: "import qualified " <> T.pack moduleNameStr <> ".Common"
: xs'
_ -> xs
)
Expand Down Expand Up @@ -202,63 +204,66 @@ data OutputFiles = OutputFiles
generateFilesToCreate :: OAT.OpenApiSpecification -> OAO.Settings -> IO OutputFiles
generateFilesToCreate spec settings = do
let outputDirectory = T.unpack $ OAO.settingOutputDir settings
moduleName = T.unpack $ OAO.settingModuleName settings
moduleName = OAO.settingModuleName settings
modulePathInfo = OAO.mkModulePathInfo moduleName
moduleNameStr = OAO.getModuleName moduleName
packageName = T.unpack $ OAO.settingPackageName settings
env = OAM.createEnvironment settings $ Ref.buildReferenceMap spec
logMessages = mapM_ (putStrLn . T.unpack) . OAL.filterAndTransformLogs (OAO.settingLogLevel settings)
showAndReplace = replaceOpenAPI moduleName . show
((operationsQ, operationDependencies), logs) = OAM.runGenerator env $ defineOperations moduleName spec
showAndReplace = replaceOpenAPI moduleNameStr . show
((operationsQ, operationDependencies), logs) = OAM.runGenerator env $ defineOperations moduleNameStr spec
logMessages logs
operationModules <- runQ operationsQ
configurationInfo <- runQ $ defineConfigurationInformation moduleName spec
let (modelsQ, logsModels) = OAM.runGenerator env $ defineModels moduleName spec operationDependencies
configurationInfo <- runQ $ defineConfigurationInformation moduleNameStr spec
let (modelsQ, logsModels) = OAM.runGenerator env $ defineModels moduleNameStr spec operationDependencies
logMessages logsModels
modelModules <- fmap (BF.second showAndReplace) <$> runQ modelsQ
let (securitySchemesQ, logs') = OAM.runGenerator env $ defineSecuritySchemes moduleName spec
let (securitySchemesQ, logs') = OAM.runGenerator env $ defineSecuritySchemes moduleNameStr spec
logMessages logs'
securitySchemes' <- runQ securitySchemesQ
let modules =
fmap (BF.bimap ("Operations" :) showAndReplace) operationModules
<> modelModules
<> [ (["Configuration"], showAndReplace configurationInfo),
(["SecuritySchemes"], showAndReplace securitySchemes'),
(["Common"], replaceOpenAPI moduleName $ replaceVersionNumber $(embedFile "src/OpenAPI/Common.hs"))
(["Common"], replaceOpenAPI moduleNameStr $ replaceVersionNumber $(embedFile "src/OpenAPI/Common.hs"))
]
modulesToExport =
fmap
( (moduleName <>)
( (moduleNameStr <>)
. ("." <>)
. joinWithPoint
. fst
)
modules
mainFile = outputDirectory </> srcDirectory </> (moduleName ++ ".hs")
mainModuleContent = show $ Doc.createModuleHeaderWithReexports moduleName modulesToExport "The main module which exports all functionality."
mainFile = outputDirectory </> srcDirectory </> OAO.getModuleInfoPath modulePathInfo Nothing ".hs"
mainModuleContent = show $ Doc.createModuleHeaderWithReexports moduleNameStr modulesToExport "The main module which exports all functionality."
hsBootFiles = getHsBootFiles settings modelModules
pure $
OutputFiles
( BF.second (unlines . lines)
<$> (mainFile, mainModuleContent)
: (BF.first ((outputDirectory </>) . (srcDirectory </>) . (moduleName </>) . (<> ".hs") . foldr1 (</>)) <$> modules)
: (BF.first ((\suffix -> outputDirectory </> srcDirectory </> OAO.getModuleInfoPath modulePathInfo (Just suffix) ".hs") . foldr1 (</>)) <$> modules)
<> hsBootFiles
)
(BF.first (outputDirectory </>) <$> cabalProjectFiles packageName moduleName modulesToExport)
(BF.first (outputDirectory </>) <$> cabalProjectFiles packageName moduleNameStr modulesToExport)
(BF.first (outputDirectory </>) <$> stackProjectFiles)
(BF.first (outputDirectory </>) <$> nixProjectFiles packageName)

writeFiles :: OAO.Settings -> OutputFiles -> IO ()
writeFiles settings OutputFiles {..} = do
let outputDirectory = T.unpack $ OAO.settingOutputDir settings
moduleName = T.unpack $ OAO.settingModuleName settings
modulePathInfo = OAO.mkModulePathInfo $ OAO.settingModuleName settings
moduleDir = OAO.getModuleInfoDir modulePathInfo
incremental = OAO.settingIncremental settings
write = mapM_ $ if incremental then writeFileIncremental else writeFileWithLog
putStrLn "Remove old output directory"
unless incremental $
void $
tryIOError (removeDirectoryRecursive outputDirectory)
putStrLn "Output directory removed, create missing directories"
createDirectoryIfMissing True (outputDirectory </> srcDirectory </> moduleName </> "Operations")
createDirectoryIfMissing True (outputDirectory </> srcDirectory </> moduleName </> "Types")
createDirectoryIfMissing True (outputDirectory </> srcDirectory </> moduleDir </> "Operations")
createDirectoryIfMissing True (outputDirectory </> srcDirectory </> moduleDir </> "Types")
putStrLn "Directories created"
write outputFilesModuleFiles
write outputFilesCabalFiles
Expand Down
7 changes: 4 additions & 3 deletions openapi3-code-generator/src/OpenAPI/Generate/OptParse.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
module OpenAPI.Generate.OptParse
( Settings (..),
getSettings,
module OAT,
)
where

Expand All @@ -19,7 +20,7 @@ import qualified Data.Text as T
import qualified OpenAPI.Generate.Log as OAL
import OpenAPI.Generate.OptParse.Configuration
import OpenAPI.Generate.OptParse.Flags
import OpenAPI.Generate.OptParse.Types
import OpenAPI.Generate.OptParse.Types as OAT
import Options.Applicative
import Options.Applicative.Help (string)
import Path
Expand All @@ -42,7 +43,7 @@ data Settings = Settings
-- | Name of the stack project
settingPackageName :: !Text,
-- | Name of the module
settingModuleName :: !Text,
settingModuleName :: !ModuleName,
-- | The minimum log level to output
settingLogLevel :: !OAL.LogSeverity,
-- | Overwrite output directory without question
Expand Down Expand Up @@ -127,7 +128,7 @@ combineToSettings Flags {..} mConf configurationFilePath = do
let settingOpenApiSpecification = fromMaybe "openapi-specification.yml" $ flagOpenApiSpecification <|> mConfigOpenApiSpecification
settingOutputDir = fromMaybe "out" $ flagOutputDir <|> mConfigOutputDir
settingPackageName = fromMaybe "openapi" $ flagPackageName <|> mc configPackageName
settingModuleName = fromMaybe "OpenAPI" $ flagModuleName <|> mc configModuleName
settingModuleName = mkModuleName . T.unpack $ fromMaybe "OpenAPI" (flagModuleName <|> mc configModuleName)
settingLogLevel = fromMaybe OAL.InfoSeverity $ flagLogLevel <|> mc configLogLevel
settingForce = fromMaybe False $ flagForce <|> mc configForce
settingIncremental = fromMaybe False $ flagIncremental <|> mc configIncremental
Expand Down
51 changes: 51 additions & 0 deletions openapi3-code-generator/src/OpenAPI/Generate/OptParse/Types.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,60 @@
{-# LANGUAGE OverloadedStrings #-}

module OpenAPI.Generate.OptParse.Types
( FixedValueStrategy (..),
ModuleName,
ModulePathInfo,
mkModuleName,
getModuleName,
mkModulePathInfo,
getModuleInfoPath,
getModuleInfoDir,
)
where

import Autodocodec
import qualified Data.Maybe as Maybe
import qualified Data.Text as T
import System.FilePath ((</>))

newtype ModuleName = ModuleName String
deriving (Show, Eq)

newtype ModulePathInfo = ModulePathInfo (Maybe FilePath, FilePath)

mkModuleName :: String -> ModuleName
mkModuleName = ModuleName

getModuleName :: ModuleName -> String
getModuleName (ModuleName moduleNameStr) = moduleNameStr

mkModulePathInfo :: ModuleName -> ModulePathInfo
mkModulePathInfo (ModuleName moduleNameStr) =
let (dirMay, fileNoExtensionMay) =
foldl
( \acc next ->
let dMay = case acc of
(Nothing, Just prev) -> Just prev
(Just dir, Just prev) -> Just $ dir </> prev
(dMay', Nothing) -> dMay'
in (dMay, Just $ T.unpack next)
)
(Nothing, Nothing)
. T.splitOn "."
. T.pack
$ moduleNameStr
in ModulePathInfo (dirMay, Maybe.fromMaybe moduleNameStr fileNoExtensionMay)

getModuleInfoPath :: ModulePathInfo -> Maybe String -> String -> FilePath
getModuleInfoPath (ModulePathInfo (dirMay, fileNoExtension)) suffixMay extension =
let file = case suffixMay of
Nothing -> fileNoExtension <> extension
Just suffix -> fileNoExtension </> suffix <> extension
in maybe file (</> file) dirMay

getModuleInfoDir :: ModulePathInfo -> FilePath
getModuleInfoDir (ModulePathInfo (dirMay, fileNoExtension)) =
maybe fileNoExtension (</> fileNoExtension) dirMay

data FixedValueStrategy = FixedValueStrategyExclude | FixedValueStrategyInclude
deriving (Eq, Bounded, Enum)
Expand Down
Loading