{-# LANGUAGE ExtendedDefaultRules #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE StandaloneDeriving #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-} -- | The -- part of the swagger specification. For construction please consider -- using "Data.Swagger.Build.Api". module Data.Swagger.Model.Api ( ApiDecl (..) , API (..) , Operation (..) , Parameter (..) , ParamType (..) , Response (..) , Model (..) , Property (..) , DataType (..) , Primitive (..) , Items (..) , PrimType (..) , File (..) , ModelId , PropertyName ) where import Control.Applicative import Data.Aeson hiding (Array) import Data.Aeson.Types (Pair) import Data.Swagger.Model.Authorisation (Scope) import Data.Swagger.Model.Util import Data.Text (Text) import Prelude default (Text) -- | Cf. data ApiDecl = ApiDecl { swaggerVersion :: Text , basePath :: Text , apis :: [API] , apiVersion :: Maybe Text , resourcePath :: Maybe Text , models :: Maybe [(Text, Model)] , apiProduces :: Maybe [Text] , apiConsumes :: Maybe [Text] , apiAuthorisations :: Maybe [(Text, [Scope])] } deriving Show -- | Cf. data API = API { path :: Text , operations :: [Operation] , apiDescription :: Maybe Text } deriving Show -- | Cf. data Operation = Operation { method :: Text , nickname :: Text , returnType :: Either () DataType , parameters :: [Parameter] , summary :: Maybe Text , notes :: Maybe Text , authorisations :: Maybe [(Text, [Scope])] , responses :: Maybe [Response] , produces :: Maybe [Text] , consumes :: Maybe [Text] , deprecated :: Maybe Bool } deriving Show -- | Cf. data Parameter = Parameter { paramType :: ParamType , inputType :: Either File DataType , paramName :: Text , description :: Maybe Text , required :: Maybe Bool , allowMultiple :: Maybe Bool } deriving Show data ParamType = Path | Query | Body | Header | Form deriving (Eq, Show) -- | Cf. data Response = Response { code :: Int , message :: Text , responseModel :: Maybe ModelId } deriving Show type ModelId = Text type PropertyName = Text -- | Cf. data Model = Model { modelId :: ModelId , properties :: [(PropertyName, Property)] , modelDescription :: Maybe Text , requiredProps :: Maybe [PropertyName] , subTypes :: Maybe [Model] , discriminator :: Maybe PropertyName } deriving Show -- | Cf. data Property = Property { propertyType :: DataType , propDescription :: Maybe Text } deriving Show data DataType where Prim :: (Show a, ToJSON a) => Primitive a -> DataType Array :: (Show a, ToJSON a) => Items a -> Maybe Bool -> DataType Ref :: ModelId -> DataType deriving instance Show DataType -- | Cf. data Primitive a = Primitive { primType :: PrimType , defaultValue :: Maybe a , enum :: Maybe [a] , minVal :: Maybe a , maxVal :: Maybe a } deriving Show data Items a = PrimItems (Primitive a) | ModelItems ModelId deriving Show data PrimType = PrimInt32 | PrimInt64 | PrimFloat | PrimDouble | PrimString | PrimByte | PrimBool | PrimDate | PrimDateTime deriving Show data File = File deriving Show ----------------------------------------------------------------------------- -- JSON instances instance ToJSON ApiDecl where toJSON a = object $ "swaggerVersion" .= swaggerVersion a # "apiVersion" .= apiVersion a # "basePath" .= basePath a # "resourcePath" .= resourcePath a # "apis" .= apis a # "models" .= (fromPairs <$> models a) # "produces" .= apiProduces a # "consumes" .= apiConsumes a # "authorizations" .= (fromAuth <$> apiAuthorisations a) # [] instance ToJSON API where toJSON a = object $ "path" .= path a # "description" .= apiDescription a # "operations" .= operations a # [] instance ToJSON Operation where toJSON a = object $ "method" .= method a # "summary" .= summary a # "notes" .= notes a # "nickname" .= nickname a # "authorizations" .= (fromAuth <$> authorisations a) # "parameters" .= parameters a # "responseMessages" .= responses a # "produces" .= produces a # "consumes" .= consumes a # "deprecated" .= deprecated a # either (const ["type" .= "void"]) (fromType False) (returnType a) instance ToJSON Parameter where toJSON a = object $ "paramType" .= paramType a # "name" .= paramName a # "description" .= description a # "required" .= required a # "allowMultiple" .= allowMultiple a # either (const ["type" .= "File"]) (fromType False) (inputType a) instance ToJSON ParamType where toJSON Path = "path" toJSON Query = "query" toJSON Body = "body" toJSON Header = "header" toJSON Form = "form" instance ToJSON Response where toJSON a = object $ "code" .= code a # "message" .= message a # "responseModel" .= responseModel a # [] instance ToJSON Model where toJSON a = object $ "id" .= modelId a # "description" .= modelDescription a # "required" .= requiredProps a # "properties" .= fromPairs (properties a) # "subTypes" .= (map modelId <$> subTypes a) # "discriminator" .= discriminator a # [] instance ToJSON Property where toJSON a = object $ "description" .= propDescription a # fromType True (propertyType a) fromType :: Bool -> DataType -> [Pair] fromType _ (Prim p) = fromPrim p fromType _ (Array i b) = fromArray i b fromType False (Ref r) = ["type" .= r] fromType True (Ref r) = ["$ref" .= r] fromPrim :: ToJSON a => Primitive a -> [Pair] fromPrim p = "defaultValue" .= defaultValue p # "enum" .= enum p # "minimum" .= minVal p # "maximum" .= maxVal p # fromPrimType (primType p) fromArray :: ToJSON a => Items a -> Maybe Bool -> [Pair] fromArray i b = "type" .= "array" # "items" .= fromPairs (fromItems i) # "uniqueItems" .= b # [] fromPrimType :: PrimType -> [Pair] fromPrimType PrimInt32 = ["type" .= "integer", "format" .= "int32" ] fromPrimType PrimInt64 = ["type" .= "integer", "format" .= "int64" ] fromPrimType PrimFloat = ["type" .= "number", "format" .= "float" ] fromPrimType PrimDouble = ["type" .= "number", "format" .= "double" ] fromPrimType PrimString = ["type" .= "string"] fromPrimType PrimByte = ["type" .= "string", "format" .= "byte" ] fromPrimType PrimBool = ["type" .= "boolean"] fromPrimType PrimDate = ["type" .= "string", "format" .= "date" ] fromPrimType PrimDateTime = ["type" .= "string", "format" .= "date-time" ] fromItems :: ToJSON a => Items a -> [Pair] fromItems (ModelItems i) = [ "$ref" .= i ] fromItems (PrimItems p) = fromPrim p fromAuth :: [(Text, [Scope])] -> Value fromAuth = fromPairs . map (\x -> (fst x, map toJSON (snd x)))