module Data.Swagger.Build.Api
(
Api.ApiDecl
, Api.API
, Api.Operation
, Api.Parameter
, Api.ParamType (..)
, Api.Response
, Api.Model
, Api.Property
, Api.DataType
, Api.Primitive
, Api.Items
, int32
, int32'
, int64
, int64'
, float
, float'
, bool
, bool'
, double
, double'
, string
, string'
, bytes
, bytes'
, date
, date'
, dateTime
, dateTime'
, Data.Swagger.Build.Api.def
, Data.Swagger.Build.Api.enum
, Data.Swagger.Build.Api.min
, Data.Swagger.Build.Api.max
, ref
, array
, unique
, ApiDeclSt
, ApiDeclBuilder
, ApiSt
, ApiBuilder
, OperationSt
, OperationBuilder
, ParameterSt
, ParameterBuilder
, ResponseSt
, ResponseBuilder
, ModelSt
, ModelBuilder
, PropertySt
, PropertyBuilder
, declare
, Data.Swagger.Build.Api.apiVersion
, Data.Swagger.Build.Api.resourcePath
, api
, model
, operation
, returns
, parameter
, file
, body
, Data.Swagger.Build.Api.summary
, Data.Swagger.Build.Api.notes
, response
, Data.Swagger.Build.Util.produces
, authorisation
, Data.Swagger.Build.Util.Auth (..)
, multiple
, defineModel
, property
, children
, Data.Swagger.Build.Util.description
, optional
, Data.Swagger.Build.Util.consumes
, Data.Swagger.Build.Api.deprecated
, Data.Swagger.Build.Util.end
) where
import Control.Applicative hiding (optional)
import Control.Monad.Trans.State.Strict
import Data.Function (on)
import Data.Int
import Data.List (groupBy)
import Data.Maybe (catMaybes)
import Data.Text (Text)
import Data.Time (UTCTime)
import Data.Swagger.Build.Util
import Data.Swagger.Model.Api as Api
import Data.Swagger.Model.Authorisation (Scope)
import Prelude
prim :: PrimType -> Primitive a
prim t = Primitive t Nothing Nothing Nothing Nothing
int32 :: (Primitive Int32 -> Primitive Int32) -> DataType
int32 f = Prim . f $ prim PrimInt32
int64 :: (Primitive Int64 -> Primitive Int64) -> DataType
int64 f = Prim . f $ prim PrimInt64
float :: (Primitive Float -> Primitive Float) -> DataType
float f = Prim . f $ prim PrimFloat
double :: (Primitive Double -> Primitive Double) -> DataType
double f = Prim . f $ prim PrimDouble
string :: (Primitive String -> Primitive String) -> DataType
string f = Prim . f $ prim PrimString
bytes :: (Primitive String -> Primitive String) -> DataType
bytes f = Prim . f $ prim PrimByte
bool :: (Primitive Bool -> Primitive Bool) -> DataType
bool f = Prim . f $ prim PrimBool
date :: (Primitive UTCTime -> Primitive UTCTime) -> DataType
date f = Prim . f $ prim PrimDate
dateTime :: (Primitive UTCTime -> Primitive UTCTime) -> DataType
dateTime f = Prim . f $ prim PrimDateTime
int32' :: DataType
int32' = int32 id
int64' :: DataType
int64' = int64 id
float' :: DataType
float' = float id
double' :: DataType
double' = double id
string' :: DataType
string' = string id
bytes' :: DataType
bytes' = bytes id
bool' :: DataType
bool' = bool id
date' :: DataType
date' = date id
dateTime' :: DataType
dateTime' = dateTime id
def :: a -> Primitive a -> Primitive a
def a t = t { defaultValue = Just a }
enum :: [a] -> Primitive a -> Primitive a
enum a t = t { Api.enum = Just a }
min :: a -> Primitive a -> Primitive a
min a t = t { minVal = Just a }
max :: a -> Primitive a -> Primitive a
max a t = t { maxVal = Just a }
ref :: Model -> DataType
ref = Ref . modelId
array :: DataType -> DataType
array (Prim t) = Array (PrimItems t) Nothing
array (Ref t) = Array (ModelItems t :: Items ()) Nothing
array t@(Array _ _) = t
unique :: DataType -> DataType
unique (Array t _) = Array t (Just True)
unique t = t
type ApiDeclSt = Common '["produces", "consumes", "models", "authorisations"] ApiDecl
type ApiDeclBuilder = State ApiDeclSt ()
declare :: Text -> Text -> ApiDeclBuilder -> ApiDecl
declare b v s = value $ execState s start
where
start = common $ ApiDecl v b [] Nothing Nothing Nothing Nothing Nothing Nothing
mmmm c = map (\m -> (modelId m, m)) <$> modls c
value c = (other c) { apiProduces = prod c
, apiConsumes = cons c
, models = mmmm c
, apiAuthorisations = toAuthObj <$> auths c
}
apiVersion :: Text -> ApiDeclBuilder
apiVersion v = modify $ \c -> c { other = (other c) { Api.apiVersion = Just v } }
resourcePath :: Text -> ApiDeclBuilder
resourcePath p = modify $ \c -> c { other = (other c) { Api.resourcePath = Just p } }
type ApiSt = Common '["description"] API
type ApiBuilder = State ApiSt ()
api :: Text -> ApiBuilder -> ApiDeclBuilder
api p s = modify $ \c -> do
let d = other c
c { other = d { apis = value (execState s start) : apis d } }
where
start = common $ API p [] Nothing
value c = (other c) { apiDescription = descr c }
type OperationSt = Common '["produces", "consumes", "authorisations"] Operation
type OperationBuilder = State OperationSt ()
operation :: Text -> Text -> OperationBuilder -> ApiBuilder
operation m n s = modify $ \c -> do
let o = value (execState s start)
a = other c
c { other = a { operations = o : operations a } }
where
start = common $ Operation m n (Left ()) [] Nothing Nothing Nothing Nothing Nothing Nothing Nothing
value c = (other c) { Api.produces = prod c
, Api.consumes = cons c
, authorisations = toAuthObj <$> auths c
}
type ParameterSt = Common '["description", "required"] Parameter
type ParameterBuilder = State ParameterSt ()
returns :: DataType -> OperationBuilder
returns t = modify $ \c -> c { other = (other c) { returnType = Right t } }
parameter :: ParamType -> Text -> DataType -> ParameterBuilder -> OperationBuilder
parameter p n t s = modify $ \c -> do
let op = other c
c { other = op { parameters = value (execState s start) : parameters op } }
where
start = common $ Parameter p (Right t) n Nothing Nothing Nothing
value c = (other c) { Api.description = descr c, Api.required = reqrd c }
file :: Text -> ParameterBuilder -> OperationBuilder
file n s = modify $ \c -> do
let op = other c
c { other = op { Api.consumes = Just ["multipart/form-data"]
, parameters = value (execState s start) : parameters op
}
}
where
start = common $ Parameter Form (Left File) n Nothing Nothing Nothing
value c = (other c) { Api.description = descr c, Api.required = reqrd c }
body :: DataType -> ParameterBuilder -> OperationBuilder
body = parameter Body "body"
summary :: Text -> OperationBuilder
summary t = modify $ \c -> c { other = (other c) { Api.summary = Just t } }
notes :: Text -> OperationBuilder
notes t = modify $ \c -> c { other = (other c) { Api.notes = Just t } }
type ResponseSt = Common '["models"] Response
type ResponseBuilder = State ResponseSt ()
response :: Int -> Text -> ResponseBuilder -> OperationBuilder
response i m s = modify $ \x -> do
let r = value $ execState s start
o = other x
x { other = o { responses = maybe (Just [r]) (Just . (r:)) (responses o) } }
where
start = common $ Response i m Nothing
value c = (other c) { responseModel = modelId . head <$> modls c }
deprecated :: OperationBuilder
deprecated = modify $ \c -> c { other = (other c) { Api.deprecated = Just True } }
multiple :: ParameterBuilder
multiple = modify $ \c -> c { other = (other c) { allowMultiple = Just True } }
type ModelSt = Common '["description"] Model
type ModelBuilder = State ModelSt ()
type PropertySt = Common '["description", "required"] Property
type PropertyBuilder = State PropertySt ()
defineModel :: ModelId -> ModelBuilder -> Model
defineModel m s = value (execState s start)
where
start = common $ Model m [] Nothing Nothing Nothing Nothing
value c = (other c) { modelDescription = descr c }
property :: PropertyName -> DataType -> PropertyBuilder -> ModelBuilder
property n t s = modify $ \c -> do
let r = execState s $ common (Property t Nothing)
p = (other r) { propDescription = descr r }
m = other c
x = maybe (Just [n]) (Just . (n:)) (requiredProps m)
y = if Just True /= reqrd r then requiredProps m else x
c { other = m { properties = (n, p) : properties m , requiredProps = y } }
children :: PropertyName -> [Model] -> ModelBuilder
children d tt = modify $ \c -> c { other = (other c) { subTypes = Just tt, discriminator = Just d } }
toAuthObj :: [(Text, Maybe Scope)] -> [(Text, [Scope])]
toAuthObj = map (\g -> (fst (head g), catMaybes $ map snd g)) . groupBy ((==) `on` fst)