@@ -1,6 +1,6 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE DataKinds #-}
23{-# LANGUAGE DeriveDataTypeable #-}
3−{-# LANGUAGE DeriveFunctor #-}
44{-# LANGUAGE DeriveGeneric #-}
55{-# LANGUAGE DeriveTraversable #-}
66{-# LANGUAGE FlexibleContexts #-}
@@ -14,87 +14,91 @@
1414{-# LANGUAGE TemplateHaskell #-}
1515{-# LANGUAGE TypeFamilies #-}
1616{-# LANGUAGE UndecidableInstances #-}
17−module Data.Swagger.Internal where
17+module Data.OpenApi.Internal where
1818
1919import Prelude ()
2020import Prelude.Compat
2121
22−import Control.Lens ((&), (.~), (?~))
2322import Control.Applicative
24−import Data.Aeson hiding (Encoding)
25−import qualified Data.Aeson.Types as JSON
26−import Data.Data (Data(..), Typeable, mkConstr, mkDataType, Fixity(..), Constr, DataType, constrIndex)
27−import Data.Hashable (Hashable)
28−import qualified Data.HashMap.Strict as HashMap
29−import Data.HashSet.InsOrd (InsOrdHashSet)
30−import Data.Map (Map)
31−import qualified Data.Map as Map
32−import Data.Monoid (Monoid (..))
33−import Data.Semigroup.Compat (Semigroup (..))
34−import Data.Scientific (Scientific)
35−import Data.String (IsString(..))
36−import Data.Text (Text)
37−import qualified Data.Text as Text
38−import GHC.Generics (Generic)
39−import Network.Socket (HostName, PortNumber)
40−import Network.HTTP.Media (MediaType)
41−import Text.Read (readMaybe)
23+import Control.Lens ((&), (.~), (?~))
24+import Data.Aeson hiding (Encoding)
25+#if MIN_VERSION_aeson(2,0,0)
26+import qualified Data.Aeson.KeyMap as KeyMap
27+#endif
28+import qualified Data.Aeson.Types as JSON
29+import Data.Data (Constr, Data (..), DataType, Fixity (..), Typeable,
30+ constrIndex, mkConstr, mkDataType)
31+import Data.Hashable (Hashable (..))
32+import qualified Data.HashMap.Strict as HashMap
33+import Data.HashSet.InsOrd (InsOrdHashSet)
34+import Data.Map (Map)
35+import qualified Data.Map as Map
36+import Data.Monoid (Monoid (..))
37+import Data.Scientific (Scientific)
38+import Data.Semigroup.Compat (Semigroup (..))
39+import Data.String (IsString (..))
40+import Data.Text (Text)
41+import qualified Data.Text as Text
42+import Data.Text.Encoding (encodeUtf8)
43+import GHC.Generics (Generic)
44+import Network.HTTP.Media (MediaType, mainType, parameters, parseAccept, subType, (//),
45+ (/:))
46+import Network.Socket (HostName, PortNumber)
47+import Text.Read (readMaybe)
4248
4349import Data.HashMap.Strict.InsOrd (InsOrdHashMap)
4450import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
4551
52+import Data.OpenApi.Aeson.Compat (deleteKey)
53+import Data.OpenApi.Internal.AesonUtils (AesonDefaultValue (..), HasSwaggerAesonOptions (..),
54+ mkSwaggerAesonOptions, saoAdditionalPairs, saoSubObject,
55+ sopSwaggerGenericParseJSON, sopSwaggerGenericToEncoding,
56+ sopSwaggerGenericToJSON, sopSwaggerGenericToJSONWithOpts)
57+import Data.OpenApi.Internal.Utils
4658import Generics.SOP.TH (deriveGeneric)
47−import Data.Swagger.Internal.AesonUtils (sopSwaggerGenericToJSON
48− ,sopSwaggerGenericToJSONWithOpts
49− ,sopSwaggerGenericParseJSON
50− ,HasSwaggerAesonOptions(..)
51− ,AesonDefaultValue(..)
52− ,mkSwaggerAesonOptions
53− ,saoAdditionalPairs
54− ,saoSubObject)
55−import Data.Swagger.Internal.Utils
56−import Data.Swagger.Internal.AesonUtils (sopSwaggerGenericToEncoding)
5759
5860-- $setup
5961-- >>> :seti -XDataKinds
6062-- >>> import Data.Aeson
63+-- >>> import Data.ByteString.Lazy.Char8 as BSL
64+-- >>> import Data.OpenApi.Internal.Utils
6165
6266-- | A list of definitions that can be used in references.
6367type Definitions = InsOrdHashMap Text
6468
6569-- | This is the root document object for the API specification.
66−data Swagger = Swagger
70+data OpenApi = OpenApi
6771 { -- | Provides metadata about the API.
6872 -- The metadata can be used by the clients if needed.
69− _swaggerInfo :: Info
73+ _openApiInfo :: Info
7074
7175 -- | An array of Server Objects, which provide connectivity information
7276 -- to a target server. If the servers property is not provided, or is an empty array,
7377 -- the default value would be a 'Server' object with a url value of @/@.
74− , _swaggerServers :: [Server]
78+ , _openApiServers :: [Server]
7579
7680 -- | The available paths and operations for the API.
77− , _swaggerPaths :: InsOrdHashMap FilePath PathItem
81+ , _openApiPaths :: InsOrdHashMap FilePath PathItem
7882
7983 -- | An element to hold various schemas for the specification.
80− , _swaggerComponents :: Components
84+ , _openApiComponents :: Components
8185
8286 -- | A declaration of which security mechanisms can be used across the API.
8387 -- The list of values includes alternative security requirement objects that can be used.
8488 -- Only one of the security requirement objects need to be satisfied to authorize a request.
8589 -- Individual operations can override this definition.
8690 -- To make security optional, an empty security requirement can be included in the array.
87− , _swaggerSecurity :: [SecurityRequirement]
91+ , _openApiSecurity :: [SecurityRequirement]
8892
8993 -- | A list of tags used by the specification with additional metadata.
9094 -- The order of the tags can be used to reflect on their order by the parsing tools.
9195 -- Not all tags that are used by the 'Operation' Object must be declared.
9296 -- The tags that are not declared MAY be organized randomly or based on the tools' logic.
9397 -- Each tag name in the list MUST be unique.
94− , _swaggerTags :: InsOrdHashSet Tag
98+ , _openApiTags :: InsOrdHashSet Tag
9599
96100 -- | Additional external documentation.
97− , _swaggerExternalDocs :: Maybe ExternalDocs
101+ , _openApiExternalDocs :: Maybe ExternalDocs
98102 } deriving (Eq, Show, Generic, Data, Typeable)
99103
100104-- | The object provides metadata about the API.
@@ -191,10 +195,10 @@ data Components = Components
191195 , _componentsParameters :: Definitions Param
192196 , _componentsExamples :: Definitions Example
193197 , _componentsRequestBodies :: Definitions RequestBody
194− , _componentsHeader :: Definitions Header
195− , _componentsSecuritySchemes :: Definitions SecurityScheme
196−-- , _componentsLinks
197−-- , _componentsCallbacks
198+ , _componentsHeaders :: Definitions Header
199+ , _componentsSecuritySchemes :: SecurityDefinitions
200+ , _componentsLinks :: Definitions Link
201+ , _componentsCallbacks :: Definitions Callback
198202 } deriving (Eq, Show, Generic, Data, Typeable)
199203
200204-- | Describes the operations available on a single path.
@@ -284,7 +288,11 @@ data Operation = Operation
284288 -- | The list of possible responses as they are returned from executing this operation.
285289 , _operationResponses :: Responses
286290
287− -- TODO callbacks
291+ -- | A map of possible out-of band callbacks related to the parent operation.
292+ -- The key is a unique identifier for the 'Callback' Object.
293+ -- Each value in the map is a 'Callback' Object that describes a request
294+ -- that may be initiated by the API provider and the expected responses.
295+ , _operationCallbacks :: InsOrdHashMap Text (Referenced Callback)
288296
289297 -- | Declares this operation to be deprecated.
290298 -- Usage of the declared operation should be refrained.
@@ -304,6 +312,22 @@ data Operation = Operation
304312 , _operationServers :: [Server]
305313 } deriving (Eq, Show, Generic, Data, Typeable)
306314
315+-- This instance should be in @http-media@.
316+instance Data MediaType where
317+ gunfold k z c = case constrIndex c of
318+ 1 -> k (k (k (z (\main sub params -> foldl (/:) (main // sub) (Map.toList params)))))
319+ _ -> error $ "Data.Data.gunfold: Constructor " ++ show c ++ " is not of type MediaType."
320+
321+ toConstr _ = mediaTypeConstr
322+
323+ dataTypeOf _ = mediaTypeData
324+
325+mediaTypeConstr = mkConstr mediaTypeData "MediaType" [] Prefix
326+mediaTypeData = mkDataType "MediaType" [mediaTypeConstr]
327+
328+instance Hashable MediaType where
329+ hashWithSalt salt mt = salt `hashWithSalt` show mt
330+
307331-- | Describes a single request body.
308332data RequestBody = RequestBody
309333 { -- | A brief description of the request body. This could contain examples of use.
@@ -313,9 +337,11 @@ data RequestBody = RequestBody
313337 -- | The content of the request body.
314338 -- The key is a media type or media type range and the value describes it.
315339 -- For requests that match multiple keys, only the most specific key is applicable.
316− -- e.g. @text/plain@ overrides @text/*@
317− , _requestBodyContent :: InsOrdHashMap {-MediaType-} Text MediaTypeObject -- FIXME Data MediaType
340+ -- e.g. @text/plain@ overrides @text/\*@
341+ , _requestBodyContent :: InsOrdHashMap MediaType MediaTypeObject
318342
343+ -- | Determines if the request body is required in the request.
344+ -- Defaults to 'False'.
319345 , _requestBodyRequired :: Maybe Bool
320346 } deriving (Eq, Show, Generic, Data, Typeable)
321347
@@ -338,6 +364,29 @@ data MediaTypeObject = MediaTypeObject
338364 , _mediaTypeObjectEncoding :: InsOrdHashMap Text Encoding
339365 } deriving (Eq, Show, Generic, Data, Typeable)
340366
367+-- | In order to support common ways of serializing simple parameters, a set of style values are defined.
368+data Style
369+ = StyleMatrix
370+ -- ^ Path-style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7).
371+ | StyleLabel
372+ -- ^ Label style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7).
373+ | StyleForm
374+ -- ^ Form style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7).
375+ -- This option replaces @collectionFormat@ with a @csv@ (when @explode@ is false) or @multi@
376+ -- (when explode is true) value from OpenAPI 2.0.
377+ | StyleSimple
378+ -- ^ Simple style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7).
379+ -- This option replaces @collectionFormat@ with a @csv@ value from OpenAPI 2.0.
380+ | StyleSpaceDelimited
381+ -- ^ Space separated array values.
382+ -- This option replaces @collectionFormat@ equal to @ssv@ from OpenAPI 2.0.
383+ | StylePipeDelimited
384+ -- ^ Pipe separated array values.
385+ -- This option replaces @collectionFormat@ equal to @pipes@ from OpenAPI 2.0.
386+ | StyleDeepObject
387+ -- ^ Provides a simple way of rendering nested objects using form parameters.
388+ deriving (Eq, Show, Generic, Data, Typeable)
389+
341390data Encoding = Encoding
342391 { -- | The Content-Type for encoding a specific property.
343392 -- Default value depends on the property type: for @string@
@@ -345,8 +394,8 @@ data Encoding = Encoding
345394 -- for other primitive types – @text/plain@; for object - @application/json@;
346395 -- for array – the default is defined based on the inner type.
347396 -- The value can be a specific media type (e.g. @application/json@),
348− -- a wildcard media type (e.g. @image/*@), or a comma-separated list of the two types.
349− _encodingContentType :: Maybe Text
397+ -- a wildcard media type (e.g. @image/\*@), or a comma-separated list of the two types.
398+ _encodingContentType :: Maybe MediaType
350399
351400 -- | A map allowing additional information to be provided as headers,
352401 -- for example @Content-Disposition@. @Content-Type@ is described separately
@@ -355,11 +404,11 @@ data Encoding = Encoding
355404 , _encodingHeaders :: InsOrdHashMap Text (Referenced Header)
356405
357406 -- | Describes how a specific property value will be serialized depending on its type.
358− -- See Parameter Object for details on the style property.
407+ -- See 'Param' Object for details on the style property.
359408 -- The behavior follows the same values as query parameters, including default values.
360409 -- This property SHALL be ignored if the request body media type
361410 -- is not @application/x-www-form-urlencoded@.
362− , _encodingStyle :: Maybe Text -- TODO enum
411+ , _encodingStyle :: Maybe Style
363412
364413 -- | When this is true, property values of type @array@ or @object@ generate
365414 -- separate parameters for each value of the array,
@@ -385,18 +434,15 @@ mimeListConstr :: Constr
385434mimeListConstr = mkConstr mimeListDataType "MimeList" ["getMimeList"] Prefix
386435
387436mimeListDataType :: DataType
388−mimeListDataType = mkDataType "Data.Swagger.MimeList" [mimeListConstr]
437+mimeListDataType = mkDataType "Data.OpenApi.MimeList" [mimeListConstr]
389438
390439instance Data MimeList where
391440 gunfold k z c = case constrIndex c of
392− 1 -> k (z (\xs -> MimeList (map fromString xs)))
441+ 1 -> k (z (MimeList . map fromString))
393442 _ -> error $ "Data.Data.gunfold: Constructor " ++ show c ++ " is not of type MimeList."
394443 toConstr (MimeList _) = mimeListConstr
395444 dataTypeOf _ = mimeListDataType
396445
397−-- TODO style
398−-- TODO example
399−
400446-- | Describes a single operation parameter.
401447-- A unique parameter is defined by a combination of a name and location.
402448data Param = Param
@@ -406,7 +452,7 @@ data Param = Param
406452
407453 -- | A brief description of the parameter.
408454 -- This could contain examples of use.
409− -- GFM syntax can be used for rich text representation.
455+ -- CommonMark syntax MAY be used for rich text representation.
410456 , _paramDescription :: Maybe Text
411457
412458 -- | Determines whether this parameter is mandatory.
@@ -424,10 +470,49 @@ data Param = Param
424470 -- | Sets the ability to pass empty-valued parameters.
425471 -- This is valid only for 'ParamQuery' parameters and allows sending
426472 -- a parameter with an empty value. Default value is @false@.
427− , _paramOtherSchemaAllowEmptyValue :: Maybe Bool
473+ , _paramAllowEmptyValue :: Maybe Bool
474+
475+ -- | Determines whether the parameter value SHOULD allow reserved characters,
476+ -- as defined by [RFC3986](https://tools.ietf.org/html/rfc3986#section-2.2)
477+ -- @:/?#[]@!$&'()*+,;=@ to be included without percent-encoding.
478+ -- This property only applies to parameters with an '_paramIn' value of 'ParamQuery'.
479+ -- The default value is 'False'.
480+ , _paramAllowReserved :: Maybe Bool
428481
429482 -- | Parameter schema.
430483 , _paramSchema :: Maybe (Referenced Schema)
484+
485+ -- | Describes how the parameter value will be serialized depending
486+ -- on the type of the parameter value. Default values (based on value of '_paramIn'):
487+ -- for 'ParamQuery' - 'StyleForm'; for 'ParamPath' - 'StyleSimple'; for 'ParamHeader' - 'StyleSimple';
488+ -- for 'ParamCookie' - 'StyleForm'.
489+ , _paramStyle :: Maybe Style
490+
491+ -- | When this is true, parameter values of type @array@ or @object@
492+ -- generate separate parameters for each value of the array or key-value pair of the map.
493+ -- For other types of parameters this property has no effect.
494+ -- When style is @form@, the default value is true. For all other styles, the default value is false.
495+ , _paramExplode :: Maybe Bool
496+
497+ -- | Example of the parameter's potential value.
498+ -- The example SHOULD match the specified schema and encoding properties if present.
499+ -- The '_paramExample' field is mutually exclusive of the '_paramExamples' field.
500+ -- Furthermore, if referencing a schema that contains an example, the example value
501+ -- SHALL override the example provided by the schema. To represent examples of media types
502+ -- that cannot naturally be represented in JSON or YAML, a string value can contain
503+ -- the example with escaping where necessary.
504+ , _paramExample :: Maybe Value
505+
506+ -- | Examples of the parameter's potential value.
507+ -- Each example SHOULD contain a value in the correct format as specified
508+ -- in the parameter encoding. The '_paramExamples' field is mutually exclusive of the '_paramExample' field.
509+ -- Furthermore, if referencing a schema that contains an example,
510+ -- the examples value SHALL override the example provided by the schema.
511+ , _paramExamples :: InsOrdHashMap Text (Referenced Example)
512+
513+ -- TODO
514+ -- _paramContent :: InsOrdHashMap MediaType MediaTypeObject
515+ -- should be singleton. mutually exclusive with _paramSchema.
431516 } deriving (Eq, Show, Generic, Data, Typeable)
432517
433518data Example = Example
@@ -452,138 +537,64 @@ data Example = Example
452537 , _exampleExternalValue :: Maybe URL
453538 } deriving (Eq, Show, Generic, Typeable, Data)
454539
455−-- | Items for @'SwaggerArray'@ schemas.
540+data ExpressionOrValue
541+ = Expression Text
542+ | Value Value
543+ deriving (Eq, Show, Generic, Typeable, Data)
544+
545+-- | The Link object represents a possible design-time link for a response.
546+-- The presence of a link does not guarantee the caller's ability to successfully invoke it,
547+-- rather it provides a known relationship and traversal mechanism between responses and other operations.
548+data Link = Link
549+ { -- | A relative or absolute URI reference to an OAS operation.
550+ -- This field is mutually exclusive of the '_linkOperationId' field,
551+ -- and MUST point to an 'Operation' Object. Relative '_linkOperationRef'
552+ -- values MAY be used to locate an existing 'Operation' Object in the OpenAPI definition.
553+ _linkOperationRef :: Maybe Text
554+
555+ -- | The name of an /existing/, resolvable OAS operation, as defined with a unique
556+ -- '_operationOperationId'. This field is mutually exclusive of the '_linkOperationRef' field.
557+ , _linkOperationId :: Maybe Text
558+
559+ -- | A map representing parameters to pass to an operation as specified with '_linkOperationId'
560+ -- or identified via '_linkOperationRef'. The key is the parameter name to be used, whereas
561+ -- the value can be a constant or an expression to be evaluated and passed to the linked operation.
562+ -- The parameter name can be qualified using the parameter location @[{in}.]{name}@
563+ -- for operations that use the same parameter name in different locations (e.g. path.id).
564+ , _linkParameters :: InsOrdHashMap Text ExpressionOrValue
565+
566+ -- | A literal value or @{expression}@ to use as a request body when calling the target operation.
567+ , _linkRequestBody :: Maybe ExpressionOrValue
568+
569+ -- | A description of the link.
570+ , _linkDescription :: Maybe Text
571+
572+ -- | A server object to be used by the target operation.
573+ , _linkServer :: Maybe Server
574+ } deriving (Eq, Show, Generic, Typeable, Data)
575+
576+-- | Items for @'OpenApiArray'@ schemas.
456577--
457−-- @'SwaggerItemsPrimitive'@ should be used only for query params, headers and path pieces.
458−-- The @'CollectionFormat' t@ parameter specifies how elements of an array should be displayed.
459−-- Note that @fmt@ in @'SwaggerItemsPrimitive' fmt schema@ specifies format for elements of type @schema@.
460−-- This is different from the original Swagger's <http://swagger.io/specification/#itemsObject Items Object>.
578+-- __Warning__: OpenAPI 3.0 does not support tuple arrays. However, OpenAPI 3.1 will, as
579+-- it will incorporate Json Schema mostly verbatim.
461580--
462−-- @'SwaggerItemsObject'@ should be used to specify homogenous array @'Schema'@s.
581+-- @'OpenApiItemsObject'@ should be used to specify homogenous array @'Schema'@s.
463582--
464−-- @'SwaggerItemsArray'@ should be used to specify tuple @'Schema'@s.
465−data SwaggerItems t where
466− SwaggerItemsPrimitive :: Maybe (CollectionFormat k) -> ParamSchema k-> SwaggerItems k
467− SwaggerItemsObject :: Referenced Schema -> SwaggerItems 'SwaggerKindSchema
468− SwaggerItemsArray :: [Referenced Schema] -> SwaggerItems 'SwaggerKindSchema
469− deriving (Typeable)
470−
471−deriving instance Eq (SwaggerItems t)
472−deriving instance Show (SwaggerItems t)
473−--deriving instance Typeable (SwaggerItems t)
474−
475−swaggerItemsPrimitiveConstr :: Constr
476−swaggerItemsPrimitiveConstr = mkConstr swaggerItemsDataType "SwaggerItemsPrimitive" [] Prefix
477−
478−swaggerItemsObjectConstr :: Constr
479−swaggerItemsObjectConstr = mkConstr swaggerItemsDataType "SwaggerItemsObject" [] Prefix
480−
481−swaggerItemsArrayConstr :: Constr
482−swaggerItemsArrayConstr = mkConstr swaggerItemsDataType "SwaggerItemsArray" [] Prefix
483−
484−swaggerItemsDataType :: DataType
485−swaggerItemsDataType = mkDataType "Data.Swagger.SwaggerItems" [swaggerItemsPrimitiveConstr]
486−
487−-- Note: unfortunately we have to write these Data instances by hand,
488−-- to get better contexts / avoid duplicate name when using standalone deriving
489−
490−instance Data t => Data (SwaggerItems ('SwaggerKindNormal t)) where
491− -- TODO: define gfoldl
492− gunfold k z c = case constrIndex c of
493− 1 -> k (k (z SwaggerItemsPrimitive))
494− _ -> error $ "Data.Data.gunfold: Constructor " ++ show c ++ " is not of type (SwaggerItems t)."
495− toConstr _ = swaggerItemsPrimitiveConstr
496− dataTypeOf _ = swaggerItemsDataType
497−
498−-- SwaggerItems SwaggerKindParamOtherSchema can be constructed using SwaggerItemsPrimitive only
499−instance Data (SwaggerItems 'SwaggerKindParamOtherSchema) where
500− -- TODO: define gfoldl
501− gunfold k z c = case constrIndex c of
502− 1 -> k (k (z SwaggerItemsPrimitive))
503− _ -> error $ "Data.Data.gunfold: Constructor " ++ show c ++ " is not of type (SwaggerItems SwaggerKindParamOtherSchema)."
504− toConstr _ = swaggerItemsPrimitiveConstr
505− dataTypeOf _ = swaggerItemsDataType
506−
507−instance Data (SwaggerItems 'SwaggerKindSchema) where
508− gfoldl _ _ (SwaggerItemsPrimitive _ _) = error " Data.Data.gfoldl: Constructor SwaggerItemsPrimitive used to construct SwaggerItems SwaggerKindSchema"
509− gfoldl k z (SwaggerItemsObject ref) = z SwaggerItemsObject `k` ref
510− gfoldl k z (SwaggerItemsArray ref) = z SwaggerItemsArray `k` ref
511−
512− gunfold k z c = case constrIndex c of
513− 2 -> k (z SwaggerItemsObject)
514− 3 -> k (z SwaggerItemsArray)
515− _ -> error $ "Data.Data.gunfold: Constructor " ++ show c ++ " is not of type (SwaggerItems SwaggerKindSchema)."
516−
517− toConstr (SwaggerItemsPrimitive _ _) = error "Not supported"
518− toConstr (SwaggerItemsObject _) = swaggerItemsObjectConstr
519− toConstr (SwaggerItemsArray _) = swaggerItemsArrayConstr
520−
521− dataTypeOf _ = swaggerItemsDataType
522−
523−-- | Type used as a kind to avoid overlapping instances.
524−data SwaggerKind t
525− = SwaggerKindNormal t
526− | SwaggerKindParamOtherSchema
527− | SwaggerKindSchema
528− deriving (Typeable)
529−
530−deriving instance Typeable 'SwaggerKindNormal
531−deriving instance Typeable 'SwaggerKindParamOtherSchema
532−deriving instance Typeable 'SwaggerKindSchema
533−
534−-- TODO remove
535−type family SwaggerKindType (k :: SwaggerKind *) :: *
536−type instance SwaggerKindType ('SwaggerKindNormal t) = t
537−type instance SwaggerKindType 'SwaggerKindSchema = Schema
538−--type instance SwaggerKindType 'SwaggerKindParamOtherSchema = ParamOtherSchema
539−
540−data SwaggerType t where
541− SwaggerString :: SwaggerType t
542− SwaggerNumber :: SwaggerType t
543− SwaggerInteger :: SwaggerType t
544− SwaggerBoolean :: SwaggerType t
545− SwaggerArray :: SwaggerType t
546− SwaggerFile :: SwaggerType 'SwaggerKindParamOtherSchema
547− SwaggerNull :: SwaggerType 'SwaggerKindSchema
548− SwaggerObject :: SwaggerType 'SwaggerKindSchema
549− deriving (Typeable)
550−
551−deriving instance Eq (SwaggerType t)
552−deriving instance Show (SwaggerType t)
553−
554−swaggerTypeConstr :: Data (SwaggerType t) => SwaggerType t -> Constr
555−swaggerTypeConstr t = mkConstr (dataTypeOf t) (show t) [] Prefix
556−
557−swaggerTypeDataType :: {- Data (SwaggerType t) => -} SwaggerType t -> DataType
558−swaggerTypeDataType _ = mkDataType "Data.Swagger.SwaggerType" swaggerTypeConstrs
559−
560−swaggerCommonTypes :: [SwaggerType k]
561−swaggerCommonTypes = [SwaggerString, SwaggerNumber, SwaggerInteger, SwaggerBoolean, SwaggerArray]
562−
563−swaggerParamTypes :: [SwaggerType 'SwaggerKindParamOtherSchema]
564−swaggerParamTypes = swaggerCommonTypes ++ [SwaggerFile]
565−
566−swaggerSchemaTypes :: [SwaggerType 'SwaggerKindSchema]
567−swaggerSchemaTypes = swaggerCommonTypes ++ [error "SwaggerFile is invalid SwaggerType Schema", SwaggerNull, SwaggerObject]
568−
569−swaggerTypeConstrs :: [Constr]
570−swaggerTypeConstrs = map swaggerTypeConstr (swaggerCommonTypes :: [SwaggerType 'SwaggerKindSchema])
571− ++ [swaggerTypeConstr SwaggerFile, swaggerTypeConstr SwaggerNull, swaggerTypeConstr SwaggerObject]
572−
573−instance Typeable t => Data (SwaggerType ('SwaggerKindNormal t)) where
574− gunfold = gunfoldEnum "SwaggerType" swaggerCommonTypes
575− toConstr = swaggerTypeConstr
576− dataTypeOf = swaggerTypeDataType
577−
578−instance Data (SwaggerType 'SwaggerKindParamOtherSchema) where
579− gunfold = gunfoldEnum "SwaggerType ParamOtherSchema" swaggerParamTypes
580− toConstr = swaggerTypeConstr
581− dataTypeOf = swaggerTypeDataType
582−
583−instance Data (SwaggerType 'SwaggerKindSchema) where
584− gunfold = gunfoldEnum "SwaggerType Schema" swaggerSchemaTypes
585− toConstr = swaggerTypeConstr
586− dataTypeOf = swaggerTypeDataType
583+-- @'OpenApiItemsArray'@ should be used to specify tuple @'Schema'@s.
584+data OpenApiItems where
585+ OpenApiItemsObject :: Referenced Schema -> OpenApiItems
586+ OpenApiItemsArray :: [Referenced Schema] -> OpenApiItems
587+ deriving (Eq, Show, Typeable, Data)
588+
589+data OpenApiType where
590+ OpenApiString :: OpenApiType
591+ OpenApiNumber :: OpenApiType
592+ OpenApiInteger :: OpenApiType
593+ OpenApiBoolean :: OpenApiType
594+ OpenApiArray :: OpenApiType
595+ OpenApiNull :: OpenApiType
596+ OpenApiObject :: OpenApiType
597+ deriving (Eq, Show, Typeable, Generic, Data)
587598
588599data ParamLocation
589600 = -- | Parameters that are appended to the URL.
@@ -601,42 +612,6 @@ data ParamLocation
601612
602613type Format = Text
603614
604−-- | Determines the format of the array.
605−data CollectionFormat t where
606− -- Comma separated values: @foo,bar@.
607− CollectionCSV :: CollectionFormat t
608− -- Space separated values: @foo bar@.
609− CollectionSSV :: CollectionFormat t
610− -- Tab separated values: @foo\\tbar@.
611− CollectionTSV :: CollectionFormat t
612− -- Pipe separated values: @foo|bar@.
613− CollectionPipes :: CollectionFormat t
614− -- Corresponds to multiple parameter instances
615− -- instead of multiple values for a single instance @foo=bar&foo=baz@.
616− -- This is valid only for parameters in @'ParamQuery'@ or @'ParamFormData'@.
617− CollectionMulti :: CollectionFormat 'SwaggerKindParamOtherSchema
618− deriving (Typeable)
619−
620−deriving instance Eq (CollectionFormat t)
621−deriving instance Show (CollectionFormat t)
622−
623−collectionFormatConstr :: CollectionFormat t -> Constr
624−collectionFormatConstr cf = mkConstr collectionFormatDataType (show cf) [] Prefix
625−
626−collectionFormatDataType :: DataType
627−collectionFormatDataType = mkDataType "Data.Swagger.CollectionFormat" $
628− map collectionFormatConstr collectionCommonFormats
629−
630−collectionCommonFormats :: [CollectionFormat t]
631−collectionCommonFormats = [ CollectionCSV, CollectionSSV, CollectionTSV, CollectionPipes ]
632−
633−instance Data t => Data (CollectionFormat ('SwaggerKindNormal t)) where
634− gunfold = gunfoldEnum "CollectionFormat" collectionCommonFormats
635− toConstr = collectionFormatConstr
636− dataTypeOf _ = collectionFormatDataType
637−
638−deriving instance Data (CollectionFormat 'SwaggerKindParamOtherSchema)
639−
640615type ParamName = Text
641616
642617data Schema = Schema
@@ -663,9 +638,33 @@ data Schema = Schema
663638 , _schemaMaxProperties :: Maybe Integer
664639 , _schemaMinProperties :: Maybe Integer
665640
666− , _schemaParamSchema :: ParamSchema 'SwaggerKindSchema
641+ , -- | Declares the value of the parameter that the server will use if none is provided,
642+ -- for example a @"count"@ to control the number of results per page might default to @100@
643+ -- if not supplied by the client in the request.
644+ -- (Note: "default" has no meaning for required parameters.)
645+ -- Unlike JSON Schema this value MUST conform to the defined type for this parameter.
646+ _schemaDefault :: Maybe Value
647+
648+ , _schemaType :: Maybe OpenApiType
649+ , _schemaFormat :: Maybe Format
650+ , _schemaItems :: Maybe OpenApiItems
651+ , _schemaMaximum :: Maybe Scientific
652+ , _schemaExclusiveMaximum :: Maybe Bool
653+ , _schemaMinimum :: Maybe Scientific
654+ , _schemaExclusiveMinimum :: Maybe Bool
655+ , _schemaMaxLength :: Maybe Integer
656+ , _schemaMinLength :: Maybe Integer
657+ , _schemaPattern :: Maybe Pattern
658+ , _schemaMaxItems :: Maybe Integer
659+ , _schemaMinItems :: Maybe Integer
660+ , _schemaUniqueItems :: Maybe Bool
661+ , _schemaEnum :: Maybe [Value]
662+ , _schemaMultipleOf :: Maybe Scientific
667663 } deriving (Eq, Show, Generic, Data, Typeable)
668664
665+-- | Regex pattern for @string@ type.
666+type Pattern = Text
667+
669668data Discriminator = Discriminator
670669 { -- | The name of the property in the payload that will hold the discriminator value.
671670 _discriminatorPropertyName :: Text
@@ -681,41 +680,9 @@ data NamedSchema = NamedSchema
681680 , _namedSchemaSchema :: Schema
682681 } deriving (Eq, Show, Generic, Data, Typeable)
683682
684−-- | Regex pattern for @string@ type.
685−type Pattern = Text
686−
687−-- TODO examples for params
688−
689−data ParamSchema (t :: SwaggerKind *) = ParamSchema
690− { -- | Declares the value of the parameter that the server will use if none is provided,
691− -- for example a @"count"@ to control the number of results per page might default to @100@
692− -- if not supplied by the client in the request.
693− -- (Note: "default" has no meaning for required parameters.)
694− -- Unlike JSON Schema this value MUST conform to the defined type for this parameter.
695− _paramSchemaDefault :: Maybe Value
696−
697− , _paramSchemaType :: Maybe (SwaggerType t)
698− , _paramSchemaFormat :: Maybe Format
699− , _paramSchemaItems :: Maybe (SwaggerItems t)
700− , _paramSchemaMaximum :: Maybe Scientific
701− , _paramSchemaExclusiveMaximum :: Maybe Bool
702− , _paramSchemaMinimum :: Maybe Scientific
703− , _paramSchemaExclusiveMinimum :: Maybe Bool
704− , _paramSchemaMaxLength :: Maybe Integer
705− , _paramSchemaMinLength :: Maybe Integer
706− , _paramSchemaPattern :: Maybe Pattern
707− , _paramSchemaMaxItems :: Maybe Integer
708− , _paramSchemaMinItems :: Maybe Integer
709− , _paramSchemaUniqueItems :: Maybe Bool
710− , _paramSchemaEnum :: Maybe [Value]
711− , _paramSchemaMultipleOf :: Maybe Scientific
712− } deriving (Eq, Show, Generic, Typeable)
713−
714−deriving instance (Typeable k, Data (Maybe (SwaggerType k)), Data (SwaggerItems k)) => Data (ParamSchema k)
715−
716683data Xml = Xml
717684 { -- | Replaces the name of the element/attribute used for the described schema property.
718− -- When defined within the @'SwaggerItems'@ (items), it will affect the name of the individual XML elements within the list.
685+ -- When defined within the @'OpenApiItems'@ (items), it will affect the name of the individual XML elements within the list.
719686 -- When defined alongside type being array (outside the items),
720687 -- it will affect the wrapping element and only if wrapped is true.
721688 -- If wrapped is false, it will be ignored.
@@ -767,25 +734,46 @@ data Response = Response
767734 -- | A map containing descriptions of potential response payloads.
768735 -- The key is a media type or media type range and the value describes it.
769736 -- For responses that match multiple keys, only the most specific key is applicable.
770− -- e.g. @text/plain@ overrides @text/*@.
771− , _responseContent :: InsOrdHashMap Text MediaTypeObject
737+ -- e.g. @text/plain@ overrides @text/\*@.
738+ , _responseContent :: InsOrdHashMap MediaType MediaTypeObject
772739
773740 -- | Maps a header name to its definition.
774741 , _responseHeaders :: InsOrdHashMap HeaderName (Referenced Header)
775742
776− -- TODO links
743+ -- | A map of operations links that can be followed from the response.
744+ -- The key of the map is a short name for the link, following the naming
745+ -- constraints of the names for 'Component' Objects.
746+ , _responseLinks :: InsOrdHashMap Text (Referenced Link)
777747 } deriving (Eq, Show, Generic, Data, Typeable)
778748
779749instance IsString Response where
780− fromString s = Response (fromString s) mempty mempty
750+ fromString s = Response (fromString s) mempty mempty mempty
751+
752+-- | A map of possible out-of band callbacks related to the parent operation.
753+-- Each value in the map is a 'PathItem' Object that describes a set of requests that
754+-- may be initiated by the API provider and the expected responses.
755+-- The key value used to identify the path item object is an expression, evaluated at runtime,
756+-- that identifies a URL to use for the callback operation.
757+newtype Callback = Callback (InsOrdHashMap Text PathItem)
758+ deriving (Eq, Show, Generic, Data, Typeable)
781759
782760type HeaderName = Text
783761
762+-- | Header fields have the same meaning as for 'Param'.
763+--
764+-- Style is always treated as 'StyleSimple', as it is the only value allowed for headers.
784765data Header = Header
785766 { -- | A short description of the header.
786− _headerDescription :: Maybe Text
767+ _headerDescription :: Maybe HeaderName
768+
769+ , _headerRequired :: Maybe Bool
770+ , _headerDeprecated :: Maybe Bool
771+ , _headerAllowEmptyValue :: Maybe Bool
772+ , _headerExplode :: Maybe Bool
773+ , _headerExample :: Maybe Value
774+ , _headerExamples :: InsOrdHashMap Text (Referenced Example)
787775
788− , _headerParamSchema :: ParamSchema ('SwaggerKindNormal Header)
776+ , _headerSchema :: Maybe (Referenced Schema)
789777 } deriving (Eq, Show, Generic, Data, Typeable)
790778
791779-- | The location of the API key.
@@ -809,17 +797,17 @@ type AuthorizationURL = Text
809797-- | The token URL to be used for OAuth2 flow. This SHOULD be in the form of a URL.
810798type TokenURL = Text
811799
812−data OAuth2ImplicitFlow = OAuth2ImplicitFlow
813− { _oAuth2ImplicitFlowAuthorizationUrl :: AuthorizationURL
814− } deriving (Eq, Show, Generic, Data, Typeable)
800+newtype OAuth2ImplicitFlow
801+ = OAuth2ImplicitFlow {_oAuth2ImplicitFlowAuthorizationUrl :: AuthorizationURL}
802+ deriving (Eq, Show, Generic, Data, Typeable)
815803
816−data OAuth2PasswordFlow = OAuth2PasswordFlow
817− { _oAuth2PasswordFlowTokenUrl :: TokenURL
818− } deriving (Eq, Show, Generic, Data, Typeable)
804+newtype OAuth2PasswordFlow
805+ = OAuth2PasswordFlow {_oAuth2PasswordFlowTokenUrl :: TokenURL}
806+ deriving (Eq, Show, Generic, Data, Typeable)
819807
820−data OAuth2ClientCredentialsFlow = OAuth2ClientCredentialsFlow
821− { _oAuth2ClientCredentialsFlowTokenUrl :: TokenURL
822− } deriving (Eq, Show, Generic, Data, Typeable)
808+newtype OAuth2ClientCredentialsFlow
809+ = OAuth2ClientCredentialsFlow {_oAuth2ClientCredentialsFlowTokenUrl :: TokenURL}
810+ deriving (Eq, Show, Generic, Data, Typeable)
823811
824812data OAuth2AuthorizationCodeFlow = OAuth2AuthorizationCodeFlow
825813 { _oAuth2AuthorizationCodeFlowAuthorizationUrl :: AuthorizationURL
@@ -852,8 +840,50 @@ data OAuth2Flows = OAuth2Flows
852840 , _oAuth2FlowsAuthorizationCode :: Maybe (OAuth2Flow OAuth2AuthorizationCodeFlow)
853841 } deriving (Eq, Show, Generic, Data, Typeable)
854842
843+type BearerFormat = Text
844+
845+data HttpSchemeType
846+ = HttpSchemeBearer (Maybe BearerFormat)
847+ | HttpSchemeBasic
848+ | HttpSchemeCustom Text
849+ deriving (Eq, Show, Generic, Data, Typeable)
850+
851+-- |
852+--
853+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp (HttpSchemeBearer Nothing))
854+-- {
855+-- "scheme": "bearer",
856+-- "type": "http"
857+-- }
858+--
859+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp (HttpSchemeBearer (Just "jwt")))
860+-- {
861+-- "bearerFormat": "jwt",
862+-- "scheme": "bearer",
863+-- "type": "http"
864+-- }
865+--
866+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp HttpSchemeBasic)
867+-- {
868+-- "scheme": "basic",
869+-- "type": "http"
870+-- }
871+--
872+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp (HttpSchemeCustom "CANARY"))
873+-- {
874+-- "scheme": "CANARY",
875+-- "type": "http"
876+-- }
877+--
878+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeApiKey (ApiKeyParams "id" ApiKeyCookie))
879+-- {
880+-- "in": "cookie",
881+-- "name": "id",
882+-- "type": "apiKey"
883+-- }
884+--
855885data SecuritySchemeType
856− = SecuritySchemeHttp
886+ = SecuritySchemeHttp HttpSchemeType
857887 | SecuritySchemeApiKey ApiKeyParams
858888 | SecuritySchemeOAuth2 OAuth2Flows
859889 | SecuritySchemeOpenIdConnect URL
@@ -867,6 +897,10 @@ data SecurityScheme = SecurityScheme
867897 , _securitySchemeDescription :: Maybe Text
868898 } deriving (Eq, Show, Generic, Data, Typeable)
869899
900+newtype SecurityDefinitions
901+ = SecurityDefinitions (Definitions SecurityScheme)
902+ deriving (Eq, Show, Generic, Data, Typeable)
903+
870904-- | Lists the required security schemes to execute this operation.
871905-- The object can have multiple security schemes declared in it which are all required
872906-- (that is, there is a logical AND between the schemes).
@@ -884,7 +918,7 @@ data Tag = Tag
884918 _tagName :: TagName
885919
886920 -- | A short description for the tag.
887− -- GFM syntax can be used for rich text representation.
921+ -- [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
888922 , _tagDescription :: Maybe Text
889923
890924 -- | Additional external documentation for this tag.
@@ -899,7 +933,7 @@ instance IsString Tag where
899933-- | Allows referencing an external resource for extended documentation.
900934data ExternalDocs = ExternalDocs
901935 { -- | A short description of the target documentation.
902− -- GFM syntax can be used for rich text representation.
936+ -- [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
903937 _externalDocsDescription :: Maybe Text
904938
905939 -- | The URL for the target documentation.
@@ -932,6 +966,7 @@ data AdditionalProperties
932966-- Generic instances
933967-------------------------------------------------------------------------------
934968
969+deriveGeneric ''Server
935970deriveGeneric ''Components
936971deriveGeneric ''Header
937972deriveGeneric ''OAuth2Flow
@@ -945,18 +980,18 @@ deriveGeneric ''MediaTypeObject
945980deriveGeneric ''Responses
946981deriveGeneric ''SecurityScheme
947982deriveGeneric ''Schema
948−deriveGeneric ''ParamSchema
949−deriveGeneric ''Swagger
983+deriveGeneric ''OpenApi
950984deriveGeneric ''Example
951985deriveGeneric ''Encoding
986+deriveGeneric ''Link
952987
953988-- =======================================================================
954989-- Monoid instances
955990-- =======================================================================
956991
957−instance Semigroup Swagger where
992+instance Semigroup OpenApi where
958993 (<>) = genericMappend
959−instance Monoid Swagger where
994+instance Monoid OpenApi where
960995 mempty = genericMempty
961996 mappend = (<>)
962997
@@ -990,12 +1025,6 @@ instance Monoid Schema where
9901025 mempty = genericMempty
9911026 mappend = (<>)
9921027
993−instance Semigroup (ParamSchema t) where
994− (<>) = genericMappend
995−instance Monoid (ParamSchema t) where
996− mempty = genericMempty
997− mappend = (<>)
998−
9991028instance Semigroup Param where
10001029 (<>) = genericMappend
10011030instance Monoid Param where
@@ -1044,12 +1073,38 @@ instance Monoid Operation where
10441073 mempty = genericMempty
10451074 mappend = (<>)
10461075
1076+instance Semigroup (OAuth2Flow p) where
1077+ l@OAuth2Flow{ _oAath2RefreshUrl = lUrl, _oAuth2Scopes = lScopes }
1078+ <> OAuth2Flow { _oAath2RefreshUrl = rUrl, _oAuth2Scopes = rScopes } =
1079+ l { _oAath2RefreshUrl = swaggerMappend lUrl rUrl, _oAuth2Scopes = lScopes <> rScopes }
1080+
1081+-- swaggerMappend has First-like semantics, and here we need mappend'ing under Maybes.
10471082instance Semigroup OAuth2Flows where
1048− (<>) = genericMappend
1083+ l <> r = OAuth2Flows
1084+ { _oAuth2FlowsImplicit = _oAuth2FlowsImplicit l <> _oAuth2FlowsImplicit r
1085+ , _oAuth2FlowsPassword = _oAuth2FlowsPassword l <> _oAuth2FlowsPassword r
1086+ , _oAuth2FlowsClientCredentials = _oAuth2FlowsClientCredentials l <> _oAuth2FlowsClientCredentials r
1087+ , _oAuth2FlowsAuthorizationCode = _oAuth2FlowsAuthorizationCode l <> _oAuth2FlowsAuthorizationCode r
1088+ }
1089+
10491090instance Monoid OAuth2Flows where
10501091 mempty = genericMempty
10511092 mappend = (<>)
10521093
1094+instance Semigroup SecurityScheme where
1095+ SecurityScheme (SecuritySchemeOAuth2 lFlows) lDesc
1096+ <> SecurityScheme (SecuritySchemeOAuth2 rFlows) rDesc =
1097+ SecurityScheme (SecuritySchemeOAuth2 $ lFlows <> rFlows) (swaggerMappend lDesc rDesc)
1098+ l <> _ = l
1099+
1100+instance Semigroup SecurityDefinitions where
1101+ (SecurityDefinitions sd1) <> (SecurityDefinitions sd2) =
1102+ SecurityDefinitions $ InsOrdHashMap.unionWith (<>) sd1 sd2
1103+
1104+instance Monoid SecurityDefinitions where
1105+ mempty = SecurityDefinitions InsOrdHashMap.empty
1106+ mappend = (<>)
1107+
10531108instance Semigroup RequestBody where
10541109 (<>) = genericMappend
10551110instance Monoid RequestBody where
@@ -1064,19 +1119,19 @@ instance SwaggerMonoid Info
10641119instance SwaggerMonoid Components
10651120instance SwaggerMonoid PathItem
10661121instance SwaggerMonoid Schema
1067−instance SwaggerMonoid (ParamSchema t)
10681122instance SwaggerMonoid Param
10691123instance SwaggerMonoid Responses
10701124instance SwaggerMonoid Response
10711125instance SwaggerMonoid ExternalDocs
10721126instance SwaggerMonoid Operation
10731127instance (Eq a, Hashable a) => SwaggerMonoid (InsOrdHashSet a)
1128+instance SwaggerMonoid SecurityDefinitions
10741129
10751130instance SwaggerMonoid MimeList
10761131deriving instance SwaggerMonoid URL
10771132
1078−instance SwaggerMonoid (SwaggerType t) where
1079− swaggerMempty = SwaggerString
1133+instance SwaggerMonoid OpenApiType where
1134+ swaggerMempty = OpenApiString
10801135 swaggerMappend _ y = y
10811136
10821137instance SwaggerMonoid ParamLocation where
@@ -1096,6 +1151,12 @@ instance Monoid a => SwaggerMonoid (Referenced a) where
10961151-- Simple Generic-based ToJSON instances
10971152-- =======================================================================
10981153
1154+instance ToJSON Style where
1155+ toJSON = genericToJSON (jsonPrefix "Style")
1156+
1157+instance ToJSON OpenApiType where
1158+ toJSON = genericToJSON (jsonPrefix "Swagger")
1159+
10991160instance ToJSON ParamLocation where
11001161 toJSON = genericToJSON (jsonPrefix "Param")
11011162
@@ -1108,9 +1169,6 @@ instance ToJSON Contact where
11081169instance ToJSON License where
11091170 toJSON = genericToJSON (jsonPrefix "License")
11101171
1111−instance ToJSON Server where
1112− toJSON = genericToJSON (jsonPrefix "Server")
1113−
11141172instance ToJSON ServerVariable where
11151173 toJSON = genericToJSON (jsonPrefix "ServerVariable")
11161174
@@ -1148,6 +1206,12 @@ instance ToJSON OAuth2AuthorizationCodeFlow where
11481206-- Simple Generic-based FromJSON instances
11491207-- =======================================================================
11501208
1209+instance FromJSON Style where
1210+ parseJSON = genericParseJSON (jsonPrefix "Style")
1211+
1212+instance FromJSON OpenApiType where
1213+ parseJSON = genericParseJSON (jsonPrefix "Swagger")
1214+
11511215instance FromJSON ParamLocation where
11521216 parseJSON = genericParseJSON (jsonPrefix "Param")
11531217
@@ -1160,9 +1224,6 @@ instance FromJSON Contact where
11601224instance FromJSON License where
11611225 parseJSON = genericParseJSON (jsonPrefix "License")
11621226
1163−instance FromJSON Server where
1164− parseJSON = genericParseJSON (jsonPrefix "Server")
1165−
11661227instance FromJSON ServerVariable where
11671228 parseJSON = genericParseJSON (jsonPrefix "ServerVariable")
11681229
@@ -1197,7 +1258,14 @@ instance FromJSON OAuth2AuthorizationCodeFlow where
11971258-- Manual ToJSON instances
11981259-- =======================================================================
11991260
1200−instance (Eq p, ToJSON p, AesonDefaultValue p) =>ToJSON (OAuth2Flow p) where
1261+instance ToJSON MediaType where
1262+ toJSON = toJSON . show
1263+ toEncoding = toEncoding . show
1264+
1265+instance ToJSONKey MediaType where
1266+ toJSONKey = JSON.toJSONKeyText (Text.pack . show)
1267+
1268+instance (Eq p, ToJSON p, AesonDefaultValue p) => ToJSON (OAuth2Flow p) where
12011269 toJSON = sopSwaggerGenericToJSON
12021270 toEncoding = sopSwaggerGenericToEncoding
12031271
@@ -1206,34 +1274,50 @@ instance ToJSON OAuth2Flows where
12061274 toEncoding = sopSwaggerGenericToEncoding
12071275
12081276instance ToJSON SecuritySchemeType where
1209− toJSON SecuritySchemeHttp
1210− = object [ "type" .= ("http" :: Text) ]
1277+ toJSON (SecuritySchemeHttp ty) = case ty of
1278+ HttpSchemeBearer mFmt ->
1279+ object $ [ "type" .= ("http" :: Text)
1280+ , "scheme" .= ("bearer" :: Text)
1281+ ] <> maybe [] (\t -> ["bearerFormat" .= t]) mFmt
1282+ HttpSchemeBasic ->
1283+ object [ "type" .= ("http" :: Text)
1284+ , "scheme" .= ("basic" :: Text)
1285+ ]
1286+ HttpSchemeCustom t ->
1287+ object [ "type" .= ("http" :: Text)
1288+ , "scheme" .= t
1289+ ]
12111290 toJSON (SecuritySchemeApiKey params)
12121291 = toJSON params
12131292 <+> object [ "type" .= ("apiKey" :: Text) ]
1214− toJSON (SecuritySchemeOAuth2 params)
1215− = toJSON params
1216− <+> object [ "type" .= ("oauth2" :: Text) ]
1293+ toJSON (SecuritySchemeOAuth2 params) = object
1294+ [ "type" .= ("oauth2" :: Text)
1295+ , "flows" .= toJSON params
1296+ ]
12171297 toJSON (SecuritySchemeOpenIdConnect url) = object
12181298 [ "type" .= ("openIdConnect" :: Text)
12191299 , "openIdConnectUrl" .= url
12201300 ]
12211301
1222−instance ToJSON Swagger where
1302+instance ToJSON OpenApi where
12231303 toJSON a = sopSwaggerGenericToJSON a &
1224− if InsOrdHashMap.null (_swaggerPaths a)
1304+ if InsOrdHashMap.null (_openApiPaths a)
12251305 then (<+> object ["paths" .= object []])
12261306 else id
12271307 toEncoding = sopSwaggerGenericToEncoding
12281308
1229−instance ToJSON SecurityScheme where
1309+instance ToJSON Server where
12301310 toJSON = sopSwaggerGenericToJSON
12311311 toEncoding = sopSwaggerGenericToEncoding
12321312
1233−instance ToJSON Schema where
1313+instance ToJSON SecurityScheme where
12341314 toJSON = sopSwaggerGenericToJSON
12351315 toEncoding = sopSwaggerGenericToEncoding
12361316
1317+instance ToJSON Schema where
1318+ toJSON = sopSwaggerGenericToJSONWithOpts $
1319+ mkSwaggerAesonOptions "schema" & saoSubObject ?~ "items"
1320+
12371321instance ToJSON Header where
12381322 toJSON = sopSwaggerGenericToJSON
12391323 toEncoding = sopSwaggerGenericToEncoding
@@ -1241,20 +1325,21 @@ instance ToJSON Header where
12411325-- | As for nullary schema for 0-arity type constructors, see
12421326-- <https://github.com/GetShopTV/swagger2/issues/167>.
12431327--
1244−-- >>> encode (SwaggerItemsArray [])
1245−-- "{\"example\":[],\"items\":{},\"maxItems\":0}"
1328+-- >>> BSL.putStrLn $ encodePretty (OpenApiItemsArray [])
1329+-- {
1330+-- "example": [],
1331+-- "items": {},
1332+-- "maxItems": 0
1333+-- }
12461334--
1247−instance ToJSON (ParamSchema t) => ToJSON (SwaggerItems t) where
1248− toJSON (SwaggerItemsPrimitive fmt schema) = object
1249− [ "collectionFormat" .= fmt
1250− , "items" .= schema ]
1251− toJSON (SwaggerItemsObject x) = object [ "items" .= x ]
1252− toJSON (SwaggerItemsArray []) = object
1335+instance ToJSON OpenApiItems where
1336+ toJSON (OpenApiItemsObject x) = object [ "items" .= x ]
1337+ toJSON (OpenApiItemsArray []) = object
12531338 [ "items" .= object []
12541339 , "maxItems" .= (0 :: Int)
12551340 , "example" .= Array mempty
12561341 ]
1257− toJSON (SwaggerItemsArray x) = object [ "items" .= x ]
1342+ toJSON (OpenApiItemsArray x) = object [ "items" .= x ]
12581343
12591344instance ToJSON Components where
12601345 toJSON = sopSwaggerGenericToJSON
@@ -1299,6 +1384,13 @@ instance ToJSON Encoding where
12991384 toJSON = sopSwaggerGenericToJSON
13001385 toEncoding = sopSwaggerGenericToEncoding
13011386
1387+instance ToJSON Link where
1388+ toJSON = sopSwaggerGenericToJSON
1389+ toEncoding = sopSwaggerGenericToEncoding
1390+
1391+instance ToJSON SecurityDefinitions where
1392+ toJSON (SecurityDefinitions sd) = toJSON sd
1393+
13021394instance ToJSON Reference where
13031395 toJSON (Reference ref) = object [ "$ref" .= ref ]
13041396
@@ -1312,37 +1404,31 @@ instance ToJSON (Referenced Response) where toJSON = referencedToJSON "#/compone
13121404instance ToJSON (Referenced RequestBody) where toJSON = referencedToJSON "#/components/requestBodies/"
13131405instance ToJSON (Referenced Example) where toJSON = referencedToJSON "#/components/examples/"
13141406instance ToJSON (Referenced Header) where toJSON = referencedToJSON "#/components/headers/"
1315−
1316−instance ToJSON (SwaggerType t) where
1317− toJSON SwaggerArray = "array"
1318− toJSON SwaggerString = "string"
1319− toJSON SwaggerInteger = "integer"
1320− toJSON SwaggerNumber = "number"
1321− toJSON SwaggerBoolean = "boolean"
1322− toJSON SwaggerFile = "file"
1323− toJSON SwaggerNull = "null"
1324− toJSON SwaggerObject = "object"
1325−
1326−instance ToJSON (CollectionFormat t) where
1327− toJSON CollectionCSV = "csv"
1328− toJSON CollectionSSV = "ssv"
1329− toJSON CollectionTSV = "tsv"
1330− toJSON CollectionPipes = "pipes"
1331− toJSON CollectionMulti = "multi"
1332−
1333−instance ToJSON (ParamSchema k) where
1334− -- TODO: this is a bit fishy, why we need sub object only in `ToJSON`?
1335− toJSON = sopSwaggerGenericToJSONWithOpts $
1336− mkSwaggerAesonOptions "paramSchema" & saoSubObject ?~ "items"
1407+instance ToJSON (Referenced Link) where toJSON = referencedToJSON "#/components/links/"
1408+instance ToJSON (Referenced Callback) where toJSON = referencedToJSON "#/components/callbacks/"
13371409
13381410instance ToJSON AdditionalProperties where
13391411 toJSON (AdditionalPropertiesAllowed b) = toJSON b
13401412 toJSON (AdditionalPropertiesSchema s) = toJSON s
13411413
1414+instance ToJSON ExpressionOrValue where
1415+ toJSON (Expression expr) = toJSON expr
1416+ toJSON (Value val) = toJSON val
1417+
1418+instance ToJSON Callback where
1419+ toJSON (Callback ps) = toJSON ps
1420+
13421421-- =======================================================================
13431422-- Manual FromJSON instances
13441423-- =======================================================================
13451424
1425+instance FromJSON MediaType where
1426+ parseJSON = withText "MediaType" $ \str ->
1427+ maybe (fail $ "Invalid media type literal " <> Text.unpack str) pure $ parseAccept $ encodeUtf8 str
1428+
1429+instance FromJSONKey MediaType where
1430+ fromJSONKey = FromJSONKeyTextParser (parseJSON . String)
1431+
13461432instance (Eq p, FromJSON p, AesonDefaultValue p) => FromJSON (OAuth2Flow p) where
13471433 parseJSON = sopSwaggerGenericParseJSON
13481434
@@ -1353,14 +1439,22 @@ instance FromJSON SecuritySchemeType where
13531439 parseJSON js@(Object o) = do
13541440 (t :: Text) <- o .: "type"
13551441 case t of
1356− "http" -> pure SecuritySchemeHttp
1442+ "http" -> do
1443+ scheme <- o .: "scheme"
1444+ SecuritySchemeHttp <$> case scheme of
1445+ "bearer" -> HttpSchemeBearer <$> (o .:! "bearerFormat")
1446+ "basic" -> pure HttpSchemeBasic
1447+ t -> pure $ HttpSchemeCustom t
13571448 "apiKey" -> SecuritySchemeApiKey <$> parseJSON js
1358− "oauth2" -> SecuritySchemeOAuth2 <$> parseJSON js
1449+ "oauth2" -> SecuritySchemeOAuth2 <$> (o .: "flows")
13591450 "openIdConnect" -> SecuritySchemeOpenIdConnect <$> (o .: "openIdConnectUrl")
13601451 _ -> empty
13611452 parseJSON _ = empty
13621453
1363−instance FromJSON Swagger where
1454+instance FromJSON OpenApi where
1455+ parseJSON = sopSwaggerGenericParseJSON
1456+
1457+instance FromJSON Server where
13641458 parseJSON = sopSwaggerGenericParseJSON
13651459
13661460instance FromJSON SecurityScheme where
@@ -1369,48 +1463,28 @@ instance FromJSON SecurityScheme where
13691463instance FromJSON Schema where
13701464 parseJSON = fmap nullaryCleanup . sopSwaggerGenericParseJSON
13711465 where nullaryCleanup :: Schema -> Schema
1372− nullaryCleanup s@Schema{_schemaParamSchema=ps} =
1373− if _paramSchemaItems ps == Just (SwaggerItemsArray [])
1466+ nullaryCleanup s =
1467+ if _schemaItems s == Just (OpenApiItemsArray [])
13741468 then s { _schemaExample = Nothing
1375− , _schemaParamSchema = ps { _paramSchemaMaxItems = Nothing } }
1469+ , _schemaMaxItems = Nothing
1470+ }
13761471 else s
13771472
13781473instance FromJSON Header where
13791474 parseJSON = sopSwaggerGenericParseJSON
13801475
1381−instance (FromJSON (CollectionFormat ('SwaggerKindNormal t)), FromJSON (ParamSchema ('SwaggerKindNormal t))) => FromJSON (SwaggerItems ('SwaggerKindNormal t)) where
1382− parseJSON = withObject "SwaggerItemsPrimitive" $ \o -> SwaggerItemsPrimitive
1383− <$> o .:? "collectionFormat"
1384− <*> (o .: "items" >>= parseJSON)
1385−
1386−instance FromJSON (SwaggerItems 'SwaggerKindParamOtherSchema) where
1387− parseJSON = withObject "SwaggerItemsPrimitive" $ \o -> SwaggerItemsPrimitive
1388− <$> o .:? "collectionFormat"
1389− <*> ((o .: "items" >>= parseJSON) <|> fail ("foo" ++ show o))
1390−
1391−-- |
1392−--
1393−-- >>> decode "{}" :: Maybe (SwaggerItems 'SwaggerKindSchema)
1394−-- Just (SwaggerItemsArray [])
1395−--
1396−-- >>> eitherDecode "{\"$ref\":\"#/definitions/example\"}" :: Either String (SwaggerItems 'SwaggerKindSchema)
1397−-- Right (SwaggerItemsObject (Ref (Reference {getReference = "example"})))
1398−--
1399−-- >>> eitherDecode "[{\"$ref\":\"#/definitions/example\"}]" :: Either String (SwaggerItems 'SwaggerKindSchema)
1400−-- Right (SwaggerItemsArray [Ref (Reference {getReference = "example"})])
1401−--
1402−instance FromJSON (SwaggerItems 'SwaggerKindSchema) where
1476+instance FromJSON OpenApiItems where
14031477 parseJSON js@(Object obj)
1404− | null obj = pure $ SwaggerItemsArray [] -- Nullary schema.
1405− | otherwise = SwaggerItemsObject <$> parseJSON js
1406− parseJSON js@(Array _) = SwaggerItemsArray <$> parseJSON js
1478+ | null obj = pure $ OpenApiItemsArray [] -- Nullary schema.
1479+ | otherwise = OpenApiItemsObject <$> parseJSON js
1480+ parseJSON js@(Array _) = OpenApiItemsArray <$> parseJSON js
14071481 parseJSON _ = empty
14081482
14091483instance FromJSON Components where
14101484 parseJSON = sopSwaggerGenericParseJSON
14111485
14121486instance FromJSON MimeList where
1413− parseJSON js = (MimeList . map fromString) <$> parseJSON js
1487+ parseJSON js = MimeList . map fromString <$> parseJSON js
14141488
14151489instance FromJSON Param where
14161490 parseJSON = sopSwaggerGenericParseJSON
@@ -1418,7 +1492,7 @@ instance FromJSON Param where
14181492instance FromJSON Responses where
14191493 parseJSON (Object o) = Responses
14201494 <$> o .:? "default"
1421− <*> (parseJSON (Object (HashMap.delete "default" o)))
1495+ <*> parseJSON (Object (deleteKey "default" o))
14221496 parseJSON _ = empty
14231497
14241498instance FromJSON Example where
@@ -1433,6 +1507,9 @@ instance FromJSON Operation where
14331507instance FromJSON PathItem where
14341508 parseJSON = sopSwaggerGenericParseJSON
14351509
1510+instance FromJSON SecurityDefinitions where
1511+ parseJSON js = SecurityDefinitions <$> parseJSON js
1512+
14361513instance FromJSON RequestBody where
14371514 parseJSON = sopSwaggerGenericParseJSON
14381515
@@ -1442,6 +1519,9 @@ instance FromJSON MediaTypeObject where
14421519instance FromJSON Encoding where
14431520 parseJSON = sopSwaggerGenericParseJSON
14441521
1522+instance FromJSON Link where
1523+ parseJSON = sopSwaggerGenericParseJSON
1524+
14451525instance FromJSON Reference where
14461526 parseJSON (Object o) = Reference <$> o .: "$ref"
14471527 parseJSON _ = empty
@@ -1465,44 +1545,30 @@ instance FromJSON (Referenced Response) where parseJSON = referencedParseJSON "#
14651545instance FromJSON (Referenced RequestBody) where parseJSON = referencedParseJSON "#/components/requestBodies/"
14661546instance FromJSON (Referenced Example) where parseJSON = referencedParseJSON "#/components/examples/"
14671547instance FromJSON (Referenced Header) where parseJSON = referencedParseJSON "#/components/headers/"
1548+instance FromJSON (Referenced Link) where parseJSON = referencedParseJSON "#/components/links/"
1549+instance FromJSON (Referenced Callback) where parseJSON = referencedParseJSON "#/components/callbacks/"
14681550
14691551instance FromJSON Xml where
14701552 parseJSON = genericParseJSON (jsonPrefix "xml")
14711553
1472−instance FromJSON (SwaggerType 'SwaggerKindSchema) where
1473− parseJSON = parseOneOf [SwaggerString, SwaggerInteger, SwaggerNumber, SwaggerBoolean, SwaggerArray, SwaggerNull, SwaggerObject]
1474−
1475−instance FromJSON (SwaggerType 'SwaggerKindParamOtherSchema) where
1476− parseJSON = parseOneOf [SwaggerString, SwaggerInteger, SwaggerNumber, SwaggerBoolean, SwaggerArray, SwaggerFile]
1477−
1478−instance FromJSON (SwaggerType ('SwaggerKindNormal t)) where
1479− parseJSON = parseOneOf [SwaggerString, SwaggerInteger, SwaggerNumber, SwaggerBoolean, SwaggerArray]
1480−
1481−instance FromJSON (CollectionFormat ('SwaggerKindNormal t)) where
1482− parseJSON = parseOneOf [CollectionCSV, CollectionSSV, CollectionTSV, CollectionPipes]
1483−
1484−-- NOTE: There aren't collections of 'Schema'
1485−--instance FromJSON (CollectionFormat (SwaggerKindSchema)) where
1486−-- parseJSON = parseOneOf [CollectionCSV, CollectionSSV, CollectionTSV, CollectionPipes]
1487−
1488−instance FromJSON (CollectionFormat 'SwaggerKindParamOtherSchema) where
1489− parseJSON = parseOneOf [CollectionCSV, CollectionSSV, CollectionTSV, CollectionPipes, CollectionMulti]
1490−
1491−instance (FromJSON (SwaggerType ('SwaggerKindNormal t)), FromJSON (SwaggerItems ('SwaggerKindNormal t))) => FromJSON (ParamSchema ('SwaggerKindNormal t)) where
1492− parseJSON = sopSwaggerGenericParseJSON
1493−instance FromJSON (ParamSchema 'SwaggerKindParamOtherSchema) where
1494− parseJSON = sopSwaggerGenericParseJSON
1495−instance FromJSON (ParamSchema 'SwaggerKindSchema) where
1496− parseJSON = sopSwaggerGenericParseJSON
1497−
14981554instance FromJSON AdditionalProperties where
14991555 parseJSON (Bool b) = pure $ AdditionalPropertiesAllowed b
15001556 parseJSON js = AdditionalPropertiesSchema <$> parseJSON js
15011557
1558+-- | All strings are parsed as expressions
1559+instance FromJSON ExpressionOrValue where
1560+ parseJSON (String expr) = pure $ Expression expr
1561+ parseJSON v = pure $ Value v
1562+
1563+instance FromJSON Callback where
1564+ parseJSON = fmap Callback . parseJSON
1565+
1566+instance HasSwaggerAesonOptions Server where
1567+ swaggerAesonOptions _ = mkSwaggerAesonOptions "server"
15021568instance HasSwaggerAesonOptions Components where
15031569 swaggerAesonOptions _ = mkSwaggerAesonOptions "components"
15041570instance HasSwaggerAesonOptions Header where
1505− swaggerAesonOptions _ = mkSwaggerAesonOptions "header" & saoSubObject ?~ "paramSchema"
1571+ swaggerAesonOptions _ = mkSwaggerAesonOptions "header"
15061572instance AesonDefaultValue p => HasSwaggerAesonOptions (OAuth2Flow p) where
15071573 swaggerAesonOptions _ = mkSwaggerAesonOptions "oauth2" & saoSubObject ?~ "params"
15081574instance HasSwaggerAesonOptions OAuth2Flows where
@@ -1525,23 +1591,18 @@ instance HasSwaggerAesonOptions SecurityScheme where
15251591 swaggerAesonOptions _ = mkSwaggerAesonOptions "securityScheme" & saoSubObject ?~ "type"
15261592instance HasSwaggerAesonOptions Schema where
15271593 swaggerAesonOptions _ = mkSwaggerAesonOptions "schema" & saoSubObject ?~ "paramSchema"
1528−instance HasSwaggerAesonOptions Swagger where
1529− swaggerAesonOptions _ = mkSwaggerAesonOptions "swagger" & saoAdditionalPairs .~ [("openapi", "3.0.3")]
1594+instance HasSwaggerAesonOptions OpenApi where
1595+ swaggerAesonOptions _ = mkSwaggerAesonOptions "swagger" & saoAdditionalPairs .~ [("openapi", "3.0.0")]
15301596instance HasSwaggerAesonOptions Example where
15311597 swaggerAesonOptions _ = mkSwaggerAesonOptions "example"
15321598instance HasSwaggerAesonOptions Encoding where
15331599 swaggerAesonOptions _ = mkSwaggerAesonOptions "encoding"
15341600
1535−instance HasSwaggerAesonOptions (ParamSchema ('SwaggerKindNormal t)) where
1536− swaggerAesonOptions _ = mkSwaggerAesonOptions "paramSchema" & saoSubObject ?~ "items"
1537−instance HasSwaggerAesonOptions (ParamSchema 'SwaggerKindParamOtherSchema) where
1538− swaggerAesonOptions _ = mkSwaggerAesonOptions "paramSchema" & saoSubObject ?~ "items"
1539−-- NOTE: Schema doesn't have 'items' sub object!
1540−instance HasSwaggerAesonOptions (ParamSchema 'SwaggerKindSchema) where
1541− swaggerAesonOptions _ = mkSwaggerAesonOptions "paramSchema"
1601+instance HasSwaggerAesonOptions Link where
1602+ swaggerAesonOptions _ = mkSwaggerAesonOptions "link"
15421603
1604+instance AesonDefaultValue Server
15431605instance AesonDefaultValue Components
1544−instance AesonDefaultValue (ParamSchema s)
15451606instance AesonDefaultValue OAuth2ImplicitFlow
15461607instance AesonDefaultValue OAuth2PasswordFlow
15471608instance AesonDefaultValue OAuth2ClientCredentialsFlow
@@ -1549,7 +1610,10 @@ instance AesonDefaultValue OAuth2AuthorizationCodeFlow
15491610instance AesonDefaultValue p => AesonDefaultValue (OAuth2Flow p)
15501611instance AesonDefaultValue Responses
15511612instance AesonDefaultValue SecuritySchemeType
1552−instance AesonDefaultValue (SwaggerType a)
1613+instance AesonDefaultValue OpenApiType
15531614instance AesonDefaultValue MimeList where defaultValue = Just mempty
15541615instance AesonDefaultValue Info
15551616instance AesonDefaultValue ParamLocation
1617+instance AesonDefaultValue Link
1618+instance AesonDefaultValue SecurityDefinitions where
1619+ defaultValue = Just mempty