@@ -56,6 +56,9 @@ import Data.OpenApi.Internal.AesonUtils (AesonDefaultValue (..), HasSwaggerAeson
5656 sopSwaggerGenericToJSON , sopSwaggerGenericToJSONWithOpts )
5757import Data.OpenApi.Internal.Utils
5858import Generics.SOP.TH (deriveGeneric )
59+ import Data.Version
60+ import Control.Monad (unless )
61+ import Text.ParserCombinators.ReadP (readP_to_S )
5962
6063-- $setup
6164-- >>> :seti -XDataKinds
@@ -99,8 +102,19 @@ data OpenApi = OpenApi
99102
100103 -- | Additional external documentation.
101104 , _openApiExternalDocs :: Maybe ExternalDocs
105+
106+ , -- | The spec of OpenApi this spec adheres to. Must be between 'lowerOpenApiSpecVersion' and 'upperOpenApiSpecVersion'
107+ _openApiOpenapi :: OpenApiSpecVersion
102108 } deriving (Eq , Show , Generic , Data , Typeable )
103109
110+ -- | This is the lower version of the OpenApi Spec this library can parse or produce
111+ lowerOpenApiSpecVersion :: Version
112+ lowerOpenApiSpecVersion = makeVersion [3 , 0 , 0 ]
113+
114+ -- | This is the upper version of the OpenApi Spec this library can parse or produce
115+ upperOpenApiSpecVersion :: Version
116+ upperOpenApiSpecVersion = makeVersion [3 , 0 , 3 ]
117+
104118-- | The object provides metadata about the API.
105119-- The metadata MAY be used by the clients if needed,
106120-- and MAY be presented in editing or documentation generation tools for convenience.
@@ -962,6 +976,8 @@ data AdditionalProperties
962976 | AdditionalPropertiesSchema (Referenced Schema )
963977 deriving (Eq , Show , Data , Typeable )
964978
979+ newtype OpenApiSpecVersion = OpenApiSpecVersion { getVersion :: Version } deriving (Eq , Show , Generic , Data , Typeable )
980+
965981-------------------------------------------------------------------------------
966982-- Generic instances
967983-------------------------------------------------------------------------------
@@ -984,11 +1000,19 @@ deriveGeneric ''OpenApi
9841000deriveGeneric ''Example
9851001deriveGeneric ''Encoding
9861002deriveGeneric ''Link
1003+ deriveGeneric ''OpenApiSpecVersion
9871004
9881005-- =======================================================================
9891006-- Monoid instances
9901007-- =======================================================================
9911008
1009+ instance Semigroup OpenApiSpecVersion where
1010+ (<>) (OpenApiSpecVersion a) (OpenApiSpecVersion b) = OpenApiSpecVersion $ max a b
1011+
1012+ instance Monoid OpenApiSpecVersion where
1013+ mempty = OpenApiSpecVersion (makeVersion [3 ,0 ,0 ])
1014+ mappend = (<>)
1015+
9921016instance Semigroup OpenApi where
9931017 (<>) = genericMappend
9941018instance Monoid OpenApi where
@@ -1126,6 +1150,7 @@ instance SwaggerMonoid ExternalDocs
11261150instance SwaggerMonoid Operation
11271151instance (Eq a , Hashable a ) => SwaggerMonoid (InsOrdHashSet a )
11281152instance SwaggerMonoid SecurityDefinitions
1153+ instance SwaggerMonoid OpenApiSpecVersion
11291154
11301155instance SwaggerMonoid MimeList
11311156deriving instance SwaggerMonoid URL
@@ -1258,6 +1283,9 @@ instance FromJSON OAuth2AuthorizationCodeFlow where
12581283-- Manual ToJSON instances
12591284-- =======================================================================
12601285
1286+ instance ToJSON OpenApiSpecVersion where
1287+ toJSON (OpenApiSpecVersion v)= toJSON . showVersion $ v
1288+
12611289instance ToJSON MediaType where
12621290 toJSON = toJSON . show
12631291 toEncoding = toEncoding . show
@@ -1425,6 +1453,22 @@ instance ToJSON Callback where
14251453-- Manual FromJSON instances
14261454-- =======================================================================
14271455
1456+ instance FromJSON OpenApiSpecVersion where
1457+ parseJSON = withText " OpenApiSpecVersion" $ \ str ->
1458+ let validatedVersion :: Either String Version
1459+ validatedVersion = do
1460+ parsedVersion <- readVersion str
1461+ unless ((parsedVersion >= lowerOpenApiSpecVersion) && (parsedVersion <= upperOpenApiSpecVersion)) $
1462+ Left (" The provided version " <> showVersion parsedVersion <> " is out of the allowed range >=" <> showVersion lowerOpenApiSpecVersion <> " && <=" <> showVersion upperOpenApiSpecVersion)
1463+ return parsedVersion
1464+ in
1465+ either fail (return . OpenApiSpecVersion ) validatedVersion
1466+ where
1467+ readVersion :: Text -> Either String Version
1468+ readVersion v = case readP_to_S parseVersion (Text. unpack v) of
1469+ [] -> Left $ " Failed to parse as a version string " <> Text. unpack v
1470+ solutions -> Right (fst . last $ solutions)
1471+
14281472instance FromJSON MediaType where
14291473 parseJSON = withText " MediaType" $ \ str ->
14301474 maybe (fail $ " Invalid media type literal " <> Text. unpack str) pure $ parseAccept $ encodeUtf8 str
@@ -1594,8 +1638,10 @@ instance HasSwaggerAesonOptions SecurityScheme where
15941638 swaggerAesonOptions _ = mkSwaggerAesonOptions " securityScheme" & saoSubObject ?~ " type"
15951639instance HasSwaggerAesonOptions Schema where
15961640 swaggerAesonOptions _ = mkSwaggerAesonOptions " schema" & saoSubObject ?~ " paramSchema"
1641+ instance HasSwaggerAesonOptions OpenApiSpecVersion where
1642+ swaggerAesonOptions _ = mkSwaggerAesonOptions " openapi"
15971643instance HasSwaggerAesonOptions OpenApi where
1598- swaggerAesonOptions _ = mkSwaggerAesonOptions " swagger" & saoAdditionalPairs .~ [( " openapi " , " 3.0.0 " )]
1644+ swaggerAesonOptions _ = mkSwaggerAesonOptions " swagger"
15991645instance HasSwaggerAesonOptions Example where
16001646 swaggerAesonOptions _ = mkSwaggerAesonOptions " example"
16011647instance HasSwaggerAesonOptions Encoding where
@@ -1604,6 +1650,9 @@ instance HasSwaggerAesonOptions Encoding where
16041650instance HasSwaggerAesonOptions Link where
16051651 swaggerAesonOptions _ = mkSwaggerAesonOptions " link"
16061652
1653+ instance AesonDefaultValue Version where
1654+ defaultValue = Just (makeVersion [3 ,0 ,0 ])
1655+ instance AesonDefaultValue OpenApiSpecVersion
16071656instance AesonDefaultValue Server
16081657instance AesonDefaultValue Components
16091658instance AesonDefaultValue OAuth2ImplicitFlow
0 commit comments