packages feed

openapi3 3.0.2.0 → 3.1.0

raw patch · 11 files changed

+715/−184 lines, 11 filesdep ~basedep ~hashabledep ~hspec

Dependency ranges changed: base, hashable, hspec, template-haskell

Files

CHANGELOG.md view
@@ -1,3 +1,15 @@+Unreleased+----------++3.1.0+-----++- Use `format: date-time` for `ToParamSchema ZonedTime` instance (see+  [#20](https://github.com/biocad/openapi3/pull/20)).+- Support generating schema for any polymorphic types via `Typeable` (see+  [#19](https://github.com/biocad/openapi3/pull/19)).+- Allow `hashable-1.3.1`, prettify doctests (see [#18](https://github.com/biocad/openapi3/pull/18)).+ 3.0.2.0 ------- 
openapi3.cabal view
@@ -1,6 +1,6 @@ cabal-version:       >=1.10 name:                openapi3-version:             3.0.2.0+version:             3.1.0  synopsis:            OpenAPI 3.0 data model category:            Web, Swagger, OpenApi@@ -25,8 +25,9 @@ tested-with:   GHC ==8.4.4    || ==8.6.5-   || ==8.8.3-   || ==8.10.1+   || ==8.8.4+   || ==8.10.4+   || ==9.0.1  custom-setup   setup-depends:@@ -57,10 +58,10 @@    -- GHC boot libraries   build-depends:-      base             >=4.11.1.0  && <4.15+      base             >=4.11.1.0  && <4.16     , bytestring       >=0.10.8.2  && <0.11     , containers       >=0.5.11.0  && <0.7-    , template-haskell >=2.13.0.0  && <2.17+    , template-haskell >=2.13.0.0  && <2.18     , time             >=1.8.0.2   && <1.10     , transformers     >=0.5.5.0   && <0.6 @@ -76,9 +77,7 @@     -- cookie 0.4.3 is needed by GHC 7.8 due to time>=1.4 constraint     , cookie                    >=0.4.3    && <0.5     , generics-sop              >=0.5.1.0  && <0.6-      -- <1.3.1 is a temporary measure, until we fix doctests not to depend on key order-      -- see https://github.com/haskell/aeson/issues/837-    , hashable                  >=1.2.7.0  && <1.3.1+    , hashable                  >=1.2.7.0  && <1.4     , http-media                >=0.8.0.0  && <0.9     , insert-ordered-containers >=0.2.3    && <0.3     , lens                      >=4.16.1   && <5.1
src/Data/OpenApi.hs view
@@ -137,6 +137,7 @@ -- >>> import Data.Proxy -- >>> import GHC.Generics -- >>> import qualified Data.ByteString.Lazy.Char8 as BSL+-- >>> import Data.OpenApi.Internal.Utils -- >>> :set -XDeriveGeneric -- >>> :set -XOverloadedStrings -- >>> :set -XOverloadedLists@@ -153,8 +154,16 @@ -- -- In this library you can use @'mempty'@ for a default/empty value. For instance: ----- >>> BSL.putStrLn $ encode (mempty :: OpenApi)--- {"openapi":"3.0.0","info":{"version":"","title":""},"components":{}}+-- >>> BSL.putStrLn $ encodePretty (mempty :: OpenApi)+-- {+--     "components": {},+--     "info": {+--         "title": "",+--         "version": ""+--     },+--     "openapi": "3.0.0",+--     "paths": {}+-- } -- -- As you can see some spec properties (e.g. @"version"@) are there even when the spec is empty. -- That is because these properties are actually required ones.@@ -162,13 +171,20 @@ -- You /should/ always override the default (empty) value for these properties, -- although it is not strictly necessary: ----- >>> BSL.putStrLn $ encode mempty { _infoTitle = "Todo API", _infoVersion = "1.0" }--- {"version":"1.0","title":"Todo API"}+-- >>> BSL.putStrLn $ encodePretty mempty { _infoTitle = "Todo API", _infoVersion = "1.0" }+-- {+--     "title": "Todo API",+--     "version": "1.0"+-- } -- -- You can merge two values using @'mappend'@ or its infix version @('<>')@: ----- >>> BSL.putStrLn $ encode $ mempty { _infoTitle = "Todo API" } <> mempty { _infoVersion = "1.0" }--- {"version":"1.0","title":"Todo API"}+-- >>> BSL.putStrLn $ encodePretty $ mempty { _infoTitle = "Todo API" } <> mempty { _infoVersion = "1.0" }+-- {+--     "title": "Todo API",+--     "version": "1.0"+-- }+ -- -- This can be useful for combining specifications of endpoints into a whole API specification: --@@ -194,14 +210,48 @@ -- make it fairly simple to construct/modify any part of the specification: -- -- >>> :{--- BSL.putStrLn $ encode $ (mempty :: OpenApi)+-- BSL.putStrLn $ encodePretty $ (mempty :: OpenApi) --   & components . schemas .~ [ ("User", mempty & type_ ?~ OpenApiString) ] --   & paths .~ --     [ ("/user", mempty & get ?~ (mempty --         & at 200 ?~ ("OK" & _Inline.content.at "application/json" ?~ (mempty & schema ?~ Ref (Reference "User"))) --         & at 404 ?~ "User info not found")) ] -- :}--- {"openapi":"3.0.0","info":{"version":"","title":""},"paths":{"/user":{"get":{"responses":{"404":{"description":"User info not found"},"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"description":"OK"}}}}},"components":{"schemas":{"User":{"type":"string"}}}}+-- {+--     "components": {+--         "schemas": {+--             "User": {+--                 "type": "string"+--             }+--         }+--     },+--     "info": {+--         "title": "",+--         "version": ""+--     },+--     "openapi": "3.0.0",+--     "paths": {+--         "/user": {+--             "get": {+--                 "responses": {+--                     "200": {+--                         "content": {+--                             "application/json": {+--                                 "schema": {+--                                     "$ref": "#/components/schemas/User"+--                                 }+--                             }+--                         },+--                         "description": "OK"+--                     },+--                     "404": {+--                         "description": "User info not found"+--                     }+--                 }+--             }+--         }+--     }+-- } -- -- In the snippet above we declare an API with a single path @/user@. This path provides method @GET@ -- which produces @application/json@ output. It should respond with code @200@ and body specified@@ -213,23 +263,34 @@ -- common field is @'description'@. Many components of a Swagger specification -- can have descriptions, and you can use the same name for them: ----- >>> BSL.putStrLn $ encode $ (mempty :: Response) & description .~ "No content"--- {"description":"No content"}+-- >>> BSL.putStrLn $ encodePretty $ (mempty :: Response) & description .~ "No content"+-- {+--     "description": "No content"+-- } -- >>> :{--- BSL.putStrLn $ encode $ (mempty :: Schema)+-- BSL.putStrLn $ encodePretty $ (mempty :: Schema) --   & type_       ?~ OpenApiBoolean --   & description ?~ "To be or not to be" -- :}--- {"type":"boolean","description":"To be or not to be"}+-- {+--     "description": "To be or not to be",+--     "type": "boolean"+-- } -- -- Additionally, to simplify working with @'Response'@, both @'Operation'@ and @'Responses'@ -- have direct access to it via @'at' code@. Example: -- -- >>> :{--- BSL.putStrLn $ encode $ (mempty :: Operation)+-- BSL.putStrLn $ encodePretty $ (mempty :: Operation) --   & at 404 ?~ "Not found" -- :}--- {"responses":{"404":{"description":"Not found"}}}+-- {+--     "responses": {+--         "404": {+--             "description": "Not found"+--         }+--     }+-- } -- -- You might've noticed that @'type_'@ has an extra underscore in its name -- compared to, say, @'description'@ field accessor.@@ -276,10 +337,27 @@ -- >>> data Person = Person { name :: String, age :: Integer } deriving Generic -- >>> instance ToJSON Person -- >>> instance ToSchema Person--- >>> BSL.putStrLn $ encode (Person "David" 28)--- {"age":28,"name":"David"}--- >>> BSL.putStrLn $ encode $ toSchema (Proxy :: Proxy Person)--- {"required":["name","age"],"type":"object","properties":{"age":{"type":"integer"},"name":{"type":"string"}}}+-- >>> BSL.putStrLn $ encodePretty (Person "David" 28)+-- {+--     "age": 28,+--     "name": "David"+-- }+-- >>> BSL.putStrLn $ encodePretty $ toSchema (Proxy :: Proxy Person)+-- {+--     "properties": {+--         "age": {+--             "type": "integer"+--         },+--         "name": {+--             "type": "string"+--         }+--     },+--     "required": [+--         "name",+--         "age"+--     ],+--     "type": "object"+-- } -- -- This package implements OpenAPI 3.0 spec, which supports @oneOf@ in schemas, allowing any sum types -- to be faithfully represented. All sum encodings supported by @aeson@ are supported here as well, with@@ -290,8 +368,50 @@ -- >>> data Error = ErrorNoUser { userId :: Int } | ErrorAccessDenied { requiredPermission :: String } deriving Generic -- >>> instance ToJSON Error -- >>> instance ToSchema Error--- >>> BSL.putStrLn $ encode $ toSchema (Proxy :: Proxy Error)--- {"oneOf":[{"required":["userId","tag"],"type":"object","properties":{"tag":{"type":"string","enum":["ErrorNoUser"]},"userId":{"maximum":9223372036854775807,"minimum":-9223372036854775808,"type":"integer"}}},{"required":["requiredPermission","tag"],"type":"object","properties":{"tag":{"type":"string","enum":["ErrorAccessDenied"]},"requiredPermission":{"type":"string"}}}],"type":"object"}+-- >>> BSL.putStrLn $ encodePretty $ toSchema (Proxy :: Proxy Error)+-- {+--     "oneOf": [+--         {+--             "properties": {+--                 "tag": {+--                     "enum": [+--                         "ErrorNoUser"+--                     ],+--                     "type": "string"+--                 },+--                 "userId": {+--                     "maximum": 9223372036854775807,+--                     "minimum": -9223372036854775808,+--                     "type": "integer"+--                 }+--             },+--             "required": [+--                 "userId",+--                 "tag"+--             ],+--             "type": "object"+--         },+--         {+--             "properties": {+--                 "requiredPermission": {+--                     "type": "string"+--                 },+--                 "tag": {+--                     "enum": [+--                         "ErrorAccessDenied"+--                     ],+--                     "type": "string"+--                 }+--             },+--             "required": [+--                 "requiredPermission",+--                 "tag"+--             ],+--             "type": "object"+--         }+--     ],+--     "type": "object"+-- }  -- $manipulation -- Sometimes you have to work with an imported or generated @'Swagger'@.
src/Data/OpenApi/Internal.hs view
@@ -60,6 +60,8 @@ -- $setup -- >>> :seti -XDataKinds -- >>> import Data.Aeson+-- >>> import Data.ByteString.Lazy.Char8 as BSL+-- >>> import Data.OpenApi.Internal.Utils  -- | A list of definitions that can be used in references. type Definitions = InsOrdHashMap Text@@ -848,20 +850,37 @@  -- | ----- >>> encode (SecuritySchemeHttp (HttpSchemeBearer Nothing))--- "{\"scheme\":\"bearer\",\"type\":\"http\"}"+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp (HttpSchemeBearer Nothing))+-- {+--     "scheme": "bearer",+--     "type": "http"+-- } ----- >>> encode (SecuritySchemeHttp (HttpSchemeBearer (Just "jwt")))--- "{\"scheme\":\"bearer\",\"type\":\"http\",\"bearerFormat\":\"jwt\"}"+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp (HttpSchemeBearer (Just "jwt")))+-- {+--     "bearerFormat": "jwt",+--     "scheme": "bearer",+--     "type": "http"+-- } ----- >>> encode (SecuritySchemeHttp HttpSchemeBasic)--- "{\"scheme\":\"basic\",\"type\":\"http\"}"+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp HttpSchemeBasic)+-- {+--     "scheme": "basic",+--     "type": "http"+-- } ----- >>> encode (SecuritySchemeHttp (HttpSchemeCustom "CANARY"))--- "{\"scheme\":\"CANARY\",\"type\":\"http\"}"+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeHttp (HttpSchemeCustom "CANARY"))+-- {+--     "scheme": "CANARY",+--     "type": "http"+-- } ----- >>> encode (SecuritySchemeApiKey (ApiKeyParams "id" ApiKeyCookie))--- "{\"in\":\"cookie\",\"name\":\"id\",\"type\":\"apiKey\"}"+-- >>> BSL.putStrLn $ encodePretty (SecuritySchemeApiKey (ApiKeyParams "id" ApiKeyCookie))+-- {+--     "in": "cookie",+--     "name": "id",+--     "type": "apiKey"+-- } -- data SecuritySchemeType   = SecuritySchemeHttp HttpSchemeType@@ -1305,8 +1324,12 @@ -- | As for nullary schema for 0-arity type constructors, see -- <https://github.com/GetShopTV/swagger2/issues/167>. ----- >>> encode (OpenApiItemsArray [])--- "{\"example\":[],\"items\":{},\"maxItems\":0}"+-- >>> BSL.putStrLn $ encodePretty (OpenApiItemsArray [])+-- {+--     "example": [],+--     "items": {},+--     "maxItems": 0+-- } -- instance ToJSON OpenApiItems where   toJSON (OpenApiItemsObject x) = object [ "items" .= x ]
src/Data/OpenApi/Internal/ParamSchema.hs view
@@ -46,7 +46,7 @@ import Data.OpenApi.SchemaOptions  import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as BSL+import qualified Data.ByteString.Lazy.Char8 as BSL import GHC.TypeLits (TypeError, ErrorMessage(..))  -- | Default schema for binary data (any sequence of octets).@@ -112,8 +112,10 @@ class ToParamSchema a where   -- | Convert a type into a plain parameter schema.   ---  -- >>> encode $ toParamSchema (Proxy :: Proxy Integer)-  -- "{\"type\":\"integer\"}"+  -- >>> BSL.putStrLn $ encodePretty $ toParamSchema (Proxy :: Proxy Integer)+  -- {+  --     "type": "integer"+  -- }   toParamSchema :: Proxy a -> Schema   default toParamSchema :: (Generic a, GToParamSchema (Rep a)) => Proxy a -> Schema   toParamSchema = genericToParamSchema defaultSchemaOptions@@ -155,8 +157,12 @@  -- | Default plain schema for @'Bounded'@, @'Integral'@ types. ----- >>> encode $ toParamSchemaBoundedIntegral (Proxy :: Proxy Int8)--- "{\"maximum\":127,\"minimum\":-128,\"type\":\"integer\"}"+-- >>> BSL.putStrLn $ encodePretty $ toParamSchemaBoundedIntegral (Proxy :: Proxy Int8)+-- {+--     "maximum": 127,+--     "minimum": -128,+--     "type": "integer"+-- } toParamSchemaBoundedIntegral :: forall a t. (Bounded a, Integral a) => Proxy a -> Schema toParamSchemaBoundedIntegral _ = mempty   & type_ ?~ OpenApiInteger@@ -210,9 +216,9 @@  -- | -- >>> toParamSchema (Proxy :: Proxy ZonedTime) ^. format--- Just "yyyy-mm-ddThh:MM:ss+hhMM"+-- Just "date-time" instance ToParamSchema ZonedTime where-  toParamSchema _ = timeParamSchema "yyyy-mm-ddThh:MM:ss+hhMM"+  toParamSchema _ = timeParamSchema "date-time"  -- | -- >>> toParamSchema (Proxy :: Proxy UTCTime) ^. format@@ -275,8 +281,13 @@   toParamSchema _ = toParamSchema (Proxy :: Proxy (Set a))  -- |--- >>> encode $ toParamSchema (Proxy :: Proxy ())--- "{\"type\":\"string\",\"enum\":[\"_\"]}"+-- >>> BSL.putStrLn $ encodePretty $ toParamSchema (Proxy :: Proxy ())+-- {+--     "enum": [+--         "_"+--     ],+--     "type": "string"+-- } instance ToParamSchema () where   toParamSchema _ = mempty     & type_ ?~ OpenApiString@@ -291,8 +302,14 @@ -- -- >>> :set -XDeriveGeneric -- >>> data Color = Red | Blue deriving Generic--- >>> encode $ genericToParamSchema defaultSchemaOptions (Proxy :: Proxy Color)--- "{\"type\":\"string\",\"enum\":[\"Red\",\"Blue\"]}"+-- >>> BSL.putStrLn $ encodePretty $ genericToParamSchema defaultSchemaOptions (Proxy :: Proxy Color)+-- {+--     "enum": [+--         "Red",+--         "Blue"+--     ],+--     "type": "string"+-- } genericToParamSchema :: forall a t. (Generic a, GToParamSchema (Rep a)) => SchemaOptions -> Proxy a -> Schema genericToParamSchema opts _ = gtoParamSchema opts (Proxy :: Proxy (Rep a)) mempty @@ -334,3 +351,4 @@  -- $setup -- >>> import Data.Aeson (encode)+-- >>> import Data.OpenApi.Internal.Utils
src/Data/OpenApi/Internal/Schema.hs view
@@ -42,6 +42,7 @@ import Data.Int import Data.IntSet (IntSet) import Data.IntMap (IntMap)+import Data.List (sort) import Data.List.NonEmpty.Compat (NonEmpty) import Data.Map (Map) import Data.Maybe (fromMaybe)@@ -134,7 +135,7 @@ -- -- instance ToSchema Coord -- @-class ToSchema a where+class Typeable a => ToSchema a where   -- | Convert a type into an optionally named schema   -- together with all used definitions.   -- Note that the schema itself is included in definitions@@ -156,13 +157,19 @@ -- -- >>> toNamedSchema (Proxy :: Proxy String) ^. name -- Nothing--- >>> BSL.putStrLn $ encode (toNamedSchema (Proxy :: Proxy String) ^. schema)--- {"type":"string"}+-- >>> BSL.putStrLn $ encodePretty (toNamedSchema (Proxy :: Proxy String) ^. schema)+-- {+--     "type": "string"+-- } -- -- >>> toNamedSchema (Proxy :: Proxy Day) ^. name -- Just "Day"--- >>> BSL.putStrLn $ encode (toNamedSchema (Proxy :: Proxy Day) ^. schema)--- {"example":"2016-07-22","format":"date","type":"string"}+-- >>> BSL.putStrLn $ encodePretty (toNamedSchema (Proxy :: Proxy Day) ^. schema)+-- {+--     "example": "2016-07-22",+--     "format": "date",+--     "type": "string"+-- } toNamedSchema :: ToSchema a => Proxy a -> NamedSchema toNamedSchema = undeclare . declareNamedSchema @@ -178,22 +185,35 @@  -- | Convert a type into a schema. ----- >>> BSL.putStrLn $ encode $ toSchema (Proxy :: Proxy Int8)--- {"maximum":127,"minimum":-128,"type":"integer"}+-- >>> BSL.putStrLn $ encodePretty $ toSchema (Proxy :: Proxy Int8)+-- {+--     "maximum": 127,+--     "minimum": -128,+--     "type": "integer"+-- } ----- >>> BSL.putStrLn $ encode $ toSchema (Proxy :: Proxy [Day])--- {"items":{"$ref":"#/components/schemas/Day"},"type":"array"}+-- >>> BSL.putStrLn $ encodePretty $ toSchema (Proxy :: Proxy [Day])+-- {+--     "items": {+--         "$ref": "#/components/schemas/Day"+--     },+--     "type": "array"+-- } toSchema :: ToSchema a => Proxy a -> Schema toSchema = _namedSchemaSchema . toNamedSchema  -- | Convert a type into a referenced schema if possible. -- Only named schemas can be referenced, nameless schemas are inlined. ----- >>> BSL.putStrLn $ encode $ toSchemaRef (Proxy :: Proxy Integer)--- {"type":"integer"}+-- >>> BSL.putStrLn $ encodePretty $ toSchemaRef (Proxy :: Proxy Integer)+-- {+--     "type": "integer"+-- } ----- >>> BSL.putStrLn $ encode $ toSchemaRef (Proxy :: Proxy Day)--- {"$ref":"#/components/schemas/Day"}+-- >>> BSL.putStrLn $ encodePretty $ toSchemaRef (Proxy :: Proxy Day)+-- {+--     "$ref": "#/components/schemas/Day"+-- } toSchemaRef :: ToSchema a => Proxy a -> Referenced Schema toSchemaRef = undeclare . declareSchemaRef @@ -261,8 +281,15 @@  -- | Convert a type into a schema without references. ----- >>> BSL.putStrLn $ encode $ toInlinedSchema (Proxy :: Proxy [Day])--- {"items":{"example":"2016-07-22","format":"date","type":"string"},"type":"array"}+-- >>> BSL.putStrLn $ encodePretty $ toInlinedSchema (Proxy :: Proxy [Day])+-- {+--     "items": {+--         "example": "2016-07-22",+--         "format": "date",+--         "type": "string"+--     },+--     "type": "array"+-- } -- -- __WARNING:__ @'toInlinedSchema'@ will produce infinite schema -- when inlining recursive schemas.@@ -295,19 +322,64 @@ -- | Make an unrestrictive sketch of a @'Schema'@ based on a @'ToJSON'@ instance. -- Produced schema can be used for further refinement. ----- >>> BSL.putStrLn $ encode $ sketchSchema "hello"--- {"example":"hello","type":"string"}+-- >>> BSL.putStrLn $ encodePretty $ sketchSchema "hello"+-- {+--     "example": "hello",+--     "type": "string"+-- } ----- >>> BSL.putStrLn $ encode $ sketchSchema (1, 2, 3)--- {"example":[1,2,3],"items":{"type":"number"},"type":"array"}+-- >>> BSL.putStrLn $ encodePretty $ sketchSchema (1, 2, 3)+-- {+--     "example": [+--         1,+--         2,+--         3+--     ],+--     "items": {+--         "type": "number"+--     },+--     "type": "array"+-- } ----- >>> BSL.putStrLn $ encode $ sketchSchema ("Jack", 25)--- {"example":["Jack",25],"items":[{"type":"string"},{"type":"number"}],"type":"array"}+-- >>> BSL.putStrLn $ encodePretty $ sketchSchema ("Jack", 25)+-- {+--     "example": [+--         "Jack",+--         25+--     ],+--     "items": [+--         {+--             "type": "string"+--         },+--         {+--             "type": "number"+--         }+--     ],+--     "type": "array"+-- } -- -- >>> data Person = Person { name :: String, age :: Int } deriving (Generic) -- >>> instance ToJSON Person--- >>> BSL.putStrLn $ encode $ sketchSchema (Person "Jack" 25)--- {"example":{"age":25,"name":"Jack"},"required":["age","name"],"type":"object","properties":{"age":{"type":"number"},"name":{"type":"string"}}}+-- >>> BSL.putStrLn $ encodePretty $ sketchSchema (Person "Jack" 25)+-- {+--     "example": {+--         "age": 25,+--         "name": "Jack"+--     },+--     "properties": {+--         "age": {+--             "type": "number"+--         },+--         "name": {+--             "type": "string"+--         }+--     },+--     "required": [+--         "age",+--         "name"+--     ],+--     "type": "object"+-- } sketchSchema :: ToJSON a => a -> Schema sketchSchema = sketch . toJSON   where@@ -333,25 +405,139 @@           _               -> Nothing     go (Object o) = mempty       & type_         ?~ OpenApiObject-      & required      .~ HashMap.keys o+      & required      .~ sort (HashMap.keys o)       & properties    .~ fmap (Inline . go) (InsOrdHashMap.fromHashMap o)  -- | Make a restrictive sketch of a @'Schema'@ based on a @'ToJSON'@ instance. -- Produced schema uses as much constraints as possible. ----- >>> BSL.putStrLn $ encode $ sketchStrictSchema "hello"--- {"maxLength":5,"pattern":"hello","minLength":5,"type":"string","enum":["hello"]}+-- >>> BSL.putStrLn $ encodePretty $ sketchStrictSchema "hello"+-- {+--     "enum": [+--         "hello"+--     ],+--     "maxLength": 5,+--     "minLength": 5,+--     "pattern": "hello",+--     "type": "string"+-- } ----- >>> BSL.putStrLn $ encode $ sketchStrictSchema (1, 2, 3)--- {"minItems":3,"uniqueItems":true,"items":[{"maximum":1,"minimum":1,"multipleOf":1,"type":"number","enum":[1]},{"maximum":2,"minimum":2,"multipleOf":2,"type":"number","enum":[2]},{"maximum":3,"minimum":3,"multipleOf":3,"type":"number","enum":[3]}],"maxItems":3,"type":"array","enum":[[1,2,3]]}+-- >>> BSL.putStrLn $ encodePretty $ sketchStrictSchema (1, 2, 3)+-- {+--     "enum": [+--         [+--             1,+--             2,+--             3+--         ]+--     ],+--     "items": [+--         {+--             "enum": [+--                 1+--             ],+--             "maximum": 1,+--             "minimum": 1,+--             "multipleOf": 1,+--             "type": "number"+--         },+--         {+--             "enum": [+--                 2+--             ],+--             "maximum": 2,+--             "minimum": 2,+--             "multipleOf": 2,+--             "type": "number"+--         },+--         {+--             "enum": [+--                 3+--             ],+--             "maximum": 3,+--             "minimum": 3,+--             "multipleOf": 3,+--             "type": "number"+--         }+--     ],+--     "maxItems": 3,+--     "minItems": 3,+--     "type": "array",+--     "uniqueItems": true+-- } ----- >>> BSL.putStrLn $ encode $ sketchStrictSchema ("Jack", 25)--- {"minItems":2,"uniqueItems":true,"items":[{"maxLength":4,"pattern":"Jack","minLength":4,"type":"string","enum":["Jack"]},{"maximum":25,"minimum":25,"multipleOf":25,"type":"number","enum":[25]}],"maxItems":2,"type":"array","enum":[["Jack",25]]}+-- >>> BSL.putStrLn $ encodePretty $ sketchStrictSchema ("Jack", 25)+-- {+--     "enum": [+--         [+--             "Jack",+--             25+--         ]+--     ],+--     "items": [+--         {+--             "enum": [+--                 "Jack"+--             ],+--             "maxLength": 4,+--             "minLength": 4,+--             "pattern": "Jack",+--             "type": "string"+--         },+--         {+--             "enum": [+--                 25+--             ],+--             "maximum": 25,+--             "minimum": 25,+--             "multipleOf": 25,+--             "type": "number"+--         }+--     ],+--     "maxItems": 2,+--     "minItems": 2,+--     "type": "array",+--     "uniqueItems": true+-- } -- -- >>> data Person = Person { name :: String, age :: Int } deriving (Generic) -- >>> instance ToJSON Person--- >>> BSL.putStrLn $ encode $ sketchStrictSchema (Person "Jack" 25)--- {"minProperties":2,"required":["age","name"],"maxProperties":2,"type":"object","enum":[{"age":25,"name":"Jack"}],"properties":{"age":{"maximum":25,"minimum":25,"multipleOf":25,"type":"number","enum":[25]},"name":{"maxLength":4,"pattern":"Jack","minLength":4,"type":"string","enum":["Jack"]}}}+-- >>> BSL.putStrLn $ encodePretty $ sketchStrictSchema (Person "Jack" 25)+-- {+--     "enum": [+--         {+--             "age": 25,+--             "name": "Jack"+--         }+--     ],+--     "maxProperties": 2,+--     "minProperties": 2,+--     "properties": {+--         "age": {+--             "enum": [+--                 25+--             ],+--             "maximum": 25,+--             "minimum": 25,+--             "multipleOf": 25,+--             "type": "number"+--         },+--         "name": {+--             "enum": [+--                 "Jack"+--             ],+--             "maxLength": 4,+--             "minLength": 4,+--             "pattern": "Jack",+--             "type": "string"+--         }+--     },+--     "required": [+--         "age",+--         "name"+--     ],+--     "type": "object"+-- } sketchStrictSchema :: ToJSON a => a -> Schema sketchStrictSchema = go . toJSON   where@@ -383,7 +569,7 @@         allUnique = sz == HashSet.size (HashSet.fromList (V.toList xs))     go js@(Object o) = mempty       & type_         ?~ OpenApiObject-      & required      .~ names+      & required      .~ sort names       & properties    .~ fmap (Inline . go) (InsOrdHashMap.fromHashMap o)       & maxProperties ?~ fromIntegral (length names)       & minProperties ?~ fromIntegral (length names)@@ -424,7 +610,7 @@ instance ToSchema Double      where declareNamedSchema = plain . paramSchemaToSchema instance ToSchema Float       where declareNamedSchema = plain . paramSchemaToSchema -instance HasResolution a => ToSchema (Fixed a) where declareNamedSchema = plain . paramSchemaToSchema+instance (Typeable (Fixed a), HasResolution a) => ToSchema (Fixed a) where declareNamedSchema = plain . paramSchemaToSchema  instance ToSchema a => ToSchema (Maybe a) where   declareNamedSchema _ = declareNamedSchema (Proxy :: Proxy a)@@ -441,12 +627,18 @@   declareNamedSchema p = pure $ named "UUID" $ paramSchemaToSchema p     & example ?~ toJSON (UUID.toText UUID.nil) -instance (ToSchema a, ToSchema b) => ToSchema (a, b)-instance (ToSchema a, ToSchema b, ToSchema c) => ToSchema (a, b, c)-instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d) => ToSchema (a, b, c, d)-instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e) => ToSchema (a, b, c, d, e)-instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e, ToSchema f) => ToSchema (a, b, c, d, e, f)-instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e, ToSchema f, ToSchema g) => ToSchema (a, b, c, d, e, f, g)+instance (ToSchema a, ToSchema b) => ToSchema (a, b) where+  declareNamedSchema = fmap unname . genericDeclareNamedSchema defaultSchemaOptions+instance (ToSchema a, ToSchema b, ToSchema c) => ToSchema (a, b, c) where+  declareNamedSchema = fmap unname . genericDeclareNamedSchema defaultSchemaOptions+instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d) => ToSchema (a, b, c, d) where+  declareNamedSchema = fmap unname . genericDeclareNamedSchema defaultSchemaOptions+instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e) => ToSchema (a, b, c, d, e) where+  declareNamedSchema = fmap unname . genericDeclareNamedSchema defaultSchemaOptions+instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e, ToSchema f) => ToSchema (a, b, c, d, e, f) where+  declareNamedSchema = fmap unname . genericDeclareNamedSchema defaultSchemaOptions+instance (ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e, ToSchema f, ToSchema g) => ToSchema (a, b, c, d, e, f, g) where+  declareNamedSchema = fmap unname . genericDeclareNamedSchema defaultSchemaOptions  timeSchema :: T.Text -> Schema timeSchema fmt = mempty@@ -465,7 +657,7 @@   declareNamedSchema _ = pure $ named "LocalTime" $ timeSchema "yyyy-mm-ddThh:MM:ss"     & example ?~ toJSON (LocalTime (fromGregorian 2016 7 22) (TimeOfDay 7 40 0)) --- | Format @"date"@ corresponds to @yyyy-mm-ddThh:MM:ss(Z|+hh:MM)@ format.+-- | Format @"date-time"@ corresponds to @yyyy-mm-ddThh:MM:ss(Z|+hh:MM)@ format. instance ToSchema ZonedTime where   declareNamedSchema _ = pure $ named "ZonedTime" $ timeSchema "date-time"     & example ?~ toJSON (ZonedTime (LocalTime (fromGregorian 2016 7 22) (TimeOfDay 7 40 0)) (hoursToTimeZone 3))@@ -497,7 +689,7 @@ instance ToSchema IntSet where declareNamedSchema _ = declareNamedSchema (Proxy :: Proxy (Set Int))  -- | NOTE: This schema does not account for the uniqueness of keys.-instance ToSchema a => ToSchema (IntMap a) where+instance (ToSchema a) => ToSchema (IntMap a) where   declareNamedSchema _ = declareNamedSchema (Proxy :: Proxy [(Int, a)])  instance (ToJSONKey k, ToSchema k, ToSchema v) => ToSchema (Map k v) where@@ -553,8 +745,12 @@  -- | Default schema for @'Bounded'@, @'Integral'@ types. ----- >>> BSL.putStrLn $ encode $ toSchemaBoundedIntegral (Proxy :: Proxy Int16)--- {"maximum":32767,"minimum":-32768,"type":"integer"}+-- >>> BSL.putStrLn $ encodePretty $ toSchemaBoundedIntegral (Proxy :: Proxy Int16)+-- {+--     "maximum": 32767,+--     "minimum": -32768,+--     "type": "integer"+-- } toSchemaBoundedIntegral :: forall a. (Bounded a, Integral a) => Proxy a -> Schema toSchemaBoundedIntegral _ = mempty   & type_ ?~ OpenApiInteger@@ -586,8 +782,27 @@ -- >>> instance ToSchema ButtonState -- >>> instance ToJSONKey ButtonState where toJSONKey = toJSONKeyText (T.pack . show) -- >>> type ImageUrl = T.Text--- >>> BSL.putStrLn $ encode $ toSchemaBoundedEnumKeyMapping (Proxy :: Proxy (Map ButtonState ImageUrl))--- {"type":"object","properties":{"Focus":{"type":"string"},"Disabled":{"type":"string"},"Active":{"type":"string"},"Neutral":{"type":"string"},"Hover":{"type":"string"}}}+-- >>> BSL.putStrLn $ encodePretty $ toSchemaBoundedEnumKeyMapping (Proxy :: Proxy (Map ButtonState ImageUrl))+-- {+--     "properties": {+--         "Active": {+--             "type": "string"+--         },+--         "Disabled": {+--             "type": "string"+--         },+--         "Focus": {+--             "type": "string"+--         },+--         "Hover": {+--             "type": "string"+--         },+--         "Neutral": {+--             "type": "string"+--         }+--     },+--     "type": "object"+-- } -- -- Note: this is only useful when @key@ is encoded with 'ToJSONKeyText'. -- If it is encoded with 'ToJSONKeyValue' then a regular schema for @[(key, value)]@ is used.@@ -614,8 +829,27 @@ -- >>> instance ToSchema ButtonState -- >>> instance ToJSONKey ButtonState where toJSONKey = toJSONKeyText (T.pack . show) -- >>> type ImageUrl = T.Text--- >>> BSL.putStrLn $ encode $ toSchemaBoundedEnumKeyMapping (Proxy :: Proxy (Map ButtonState ImageUrl))--- {"type":"object","properties":{"Focus":{"type":"string"},"Disabled":{"type":"string"},"Active":{"type":"string"},"Neutral":{"type":"string"},"Hover":{"type":"string"}}}+-- >>> BSL.putStrLn $ encodePretty $ toSchemaBoundedEnumKeyMapping (Proxy :: Proxy (Map ButtonState ImageUrl))+-- {+--     "properties": {+--         "Active": {+--             "type": "string"+--         },+--         "Disabled": {+--             "type": "string"+--         },+--         "Focus": {+--             "type": "string"+--         },+--         "Hover": {+--             "type": "string"+--         },+--         "Neutral": {+--             "type": "string"+--         }+--     },+--     "type": "object"+-- } -- -- Note: this is only useful when @key@ is encoded with 'ToJSONKeyText'. -- If it is encoded with 'ToJSONKeyValue' then a regular schema for @[(key, value)]@ is used.@@ -625,7 +859,7 @@ toSchemaBoundedEnumKeyMapping = flip evalDeclare mempty . declareSchemaBoundedEnumKeyMapping  -- | A configurable generic @'Schema'@ creator.-genericDeclareSchema :: (Generic a, GToSchema (Rep a)) =>+genericDeclareSchema :: (Generic a, GToSchema (Rep a), Typeable a) =>   SchemaOptions -> Proxy a -> Declare (Definitions Schema) Schema genericDeclareSchema opts proxy = _namedSchemaSchema <$> genericDeclareNamedSchema opts proxy @@ -633,10 +867,25 @@ -- This function applied to @'defaultSchemaOptions'@ -- is used as the default for @'declareNamedSchema'@ -- when the type is an instance of @'Generic'@.-genericDeclareNamedSchema :: forall a. (Generic a, GToSchema (Rep a)) =>+--+-- Default implementation will use the name from 'Typeable' instance, including concrete+-- instantioations of type variables.+--+-- For example:+--+-- >>> _namedSchemaName $ undeclare $ genericDeclareNamedSchema defaultSchemaOptions (Proxy :: Proxy (Either Int Bool))+-- Just "Either_Int_Bool"+genericDeclareNamedSchema :: forall a. (Generic a, GToSchema (Rep a), Typeable a) =>   SchemaOptions -> Proxy a -> Declare (Definitions Schema) NamedSchema-genericDeclareNamedSchema opts _ = gdeclareNamedSchema opts (Proxy :: Proxy (Rep a)) mempty+genericDeclareNamedSchema opts _ =+  rename (Just $ T.pack name) <$> gdeclareNamedSchema opts (Proxy :: Proxy (Rep a)) mempty+  where+    unspace ' ' = '_'+    unspace x = x+    orig = fmap unspace $ show $ typeRep @a+    name = datatypeNameModifier opts orig + -- | Derive a 'Generic'-based name for a datatype and assign it to a given 'Schema'. genericNameSchema :: forall a d f.   (Generic a, Rep a ~ D1 d f, Datatype d)@@ -861,58 +1110,13 @@  data Proxy3 a b c = Proxy3 --- | This class allows to generate schemas for polymorphic types (of kind @Type -> Type@).------ Intended usage:------ >>> data Foo a = Foo { foo :: a, bar :: Int } deriving (Eq, Show, Generic, ToSchema1)--- >>> :{--- instance (ToSchema a, Typeable a) => ToSchema (Foo a) where---   declareNamedSchema _ = declareNamedSchema @(BySchema1 Foo a) Proxy--- :}------ >>> toNamedSchema @(Foo Int) Proxy ^. name--- Just "Foo_Int"--- >>> toNamedSchema @(Foo Bool) Proxy ^. name--- Just "Foo_Bool"--- >>> toNamedSchema @(Foo (Foo T.Text)) Proxy ^. name--- Just "Foo_(Foo_Text)"-class ToSchema1 (f :: * -> *) where-  declareNamedSchema1 :: (Generic (f a), GToSchema (Rep (f a)), ToSchema a) => Proxy f -> Proxy a -> Declare (Definitions Schema) NamedSchema--  -- It would be cleaner to have GToSchema constraint only on default signature and not in the class method-  -- above, however sadly GHC does not like it.-  default declareNamedSchema1 :: forall a. (ToSchema a, Generic (f a), GToSchema (Rep (f a))) => Proxy f -> Proxy a -> Declare (Definitions Schema) NamedSchema-  declareNamedSchema1 _ _ = genericDeclareNamedSchema @(f a) defaultSchemaOptions Proxy--{- | For GHC 8.6+ it's more convenient to use @DerivingVia@ to derive instances of 'ToSchema'-using 'ToSchema1' instance, like this:--#if __GLASGOW_HASKELL__ >= 806->>> data Foo a = Foo { foo :: a, bar :: Int } deriving (Eq, Show, Generic, ToSchema1)->>> deriving via BySchema1 Foo a instance (ToSchema a, Typeable a) => ToSchema (Foo a)-#else-> data Foo a = Foo { foo :: a, bar :: Int } deriving (Eq, Show, Generic, ToSchema1)-> deriving via BySchema1 Foo a instance (ToSchema a, Typeable a) => ToSchema (Foo a)-#endif--}-newtype BySchema1 f a = BySchema1 (f a)--instance (ToSchema1 f, Generic (f a), GToSchema (Rep (f a)), Typeable (f a), ToSchema a) => ToSchema (BySchema1 f a) where-  declareNamedSchema _ = do-    sch <- declareNamedSchema1 @f @a Proxy Proxy-    let tName = T.replace " " "_" $ T.pack $ show $ typeRep @(f a)-    return $ rename (Just tName) sch- {- $setup >>> import Data.OpenApi >>> import Data.Aeson (encode) >>> import Data.Aeson.Types (toJSONKeyText)+>>> import Data.OpenApi.Internal.Utils >>> :set -XScopedTypeVariables >>> :set -XDeriveAnyClass >>> :set -XStandaloneDeriving >>> :set -XTypeApplications-#if __GLASGOW_HASKELL__ >= 806->>> :set -XDerivingVia-#endif -}
src/Data/OpenApi/Internal/Schema/Validation.hs view
@@ -31,7 +31,6 @@ import           Control.Monad                       (forM, forM_, when)  import           Data.Aeson                          hiding (Result)-import           Data.Aeson.Encode.Pretty            (encodePretty) import           Data.Foldable                       (for_, sequenceA_,                                                       traverse_) import           Data.HashMap.Strict                 (HashMap)@@ -50,6 +49,7 @@  import           Data.OpenApi.Declare import           Data.OpenApi.Internal+import           Data.OpenApi.Internal.Utils import           Data.OpenApi.Internal.Schema import           Data.OpenApi.Lens @@ -103,33 +103,33 @@ -- <BLANKLINE> -- Swagger Schema: -- {---     "required": [---         "name",---         "phone"---     ],---     "type": "object", --     "properties": {---         "phone": {---             "$ref": "#/components/schemas/Phone"---         }, --         "name": { --             "type": "string"+--         },+--         "phone": {+--             "$ref": "#/components/schemas/Phone" --         }---     }+--     },+--     "required": [+--         "name",+--         "phone"+--     ],+--     "type": "object" -- } -- <BLANKLINE> -- Swagger Description Context: -- { --     "Phone": {---         "required": [---             "value"---         ],---         "type": "object", --         "properties": { --             "value": { --                 "type": "string" --             }---         }+--         },+--         "required": [+--             "value"+--         ],+--         "type": "object" --     } -- } -- <BLANKLINE>
src/Data/OpenApi/Internal/Utils.hs view
@@ -13,6 +13,8 @@ import Control.Lens.TH import Data.Aeson import Data.Aeson.Types+import qualified Data.Aeson.Encode.Pretty as P+import qualified Data.ByteString.Lazy as BSL import Data.Char import Data.Data import Data.Hashable (Hashable)@@ -132,3 +134,6 @@   swaggerMempty = Nothing   swaggerMappend x Nothing = x   swaggerMappend _ y = y++encodePretty :: ToJSON a => a -> BSL.ByteString+encodePretty = P.encodePretty' $ P.defConfig { P.confCompare = P.compare }
src/Data/OpenApi/Operation.hs view
@@ -55,13 +55,16 @@ -- >>> import Data.Proxy -- >>> import Data.Time -- >>> import qualified Data.ByteString.Lazy.Char8 as BSL+-- >>> import Data.OpenApi.Internal.Utils  -- | Prepend path piece to all operations of the spec. -- Leading and trailing slashes are trimmed/added automatically. -- -- >>> let api = (mempty :: OpenApi) & paths .~ [("/info", mempty)]--- >>> BSL.putStrLn $ encode $ prependPath "user/{user_id}" api ^. paths--- {"/user/{user_id}/info":{}}+-- >>> BSL.putStrLn $ encodePretty $ prependPath "user/{user_id}" api ^. paths+-- {+--     "/user/{user_id}/info": {}+-- } prependPath :: FilePath -> OpenApi -> OpenApi prependPath path = paths %~ InsOrdHashMap.mapKeys (path </>)   where@@ -82,10 +85,63 @@ -- >>> let ok = (mempty :: Operation) & at 200 ?~ "OK" -- >>> let api = (mempty :: OpenApi) & paths .~ [("/user", mempty & get ?~ ok & post ?~ ok)] -- >>> let sub = (mempty :: OpenApi) & paths .~ [("/user", mempty & get ?~ mempty)]--- >>> BSL.putStrLn $ encode api--- {"openapi":"3.0.0","info":{"version":"","title":""},"paths":{"/user":{"get":{"responses":{"200":{"description":"OK"}}},"post":{"responses":{"200":{"description":"OK"}}}}},"components":{}}--- >>> BSL.putStrLn $ encode $ api & operationsOf sub . at 404 ?~ "Not found"--- {"openapi":"3.0.0","info":{"version":"","title":""},"paths":{"/user":{"get":{"responses":{"404":{"description":"Not found"},"200":{"description":"OK"}}},"post":{"responses":{"200":{"description":"OK"}}}}},"components":{}}+-- >>> BSL.putStrLn $ encodePretty api+-- {+--     "components": {},+--     "info": {+--         "title": "",+--         "version": ""+--     },+--     "openapi": "3.0.0",+--     "paths": {+--         "/user": {+--             "get": {+--                 "responses": {+--                     "200": {+--                         "description": "OK"+--                     }+--                 }+--             },+--             "post": {+--                 "responses": {+--                     "200": {+--                         "description": "OK"+--                     }+--                 }+--             }+--         }+--     }+-- }+-- >>> BSL.putStrLn $ encodePretty $ api & operationsOf sub . at 404 ?~ "Not found"+-- {+--     "components": {},+--     "info": {+--         "title": "",+--         "version": ""+--     },+--     "openapi": "3.0.0",+--     "paths": {+--         "/user": {+--             "get": {+--                 "responses": {+--                     "200": {+--                         "description": "OK"+--                     },+--                     "404": {+--                         "description": "Not found"+--                     }+--                 }+--             },+--             "post": {+--                 "responses": {+--                     "200": {+--                         "description": "OK"+--                     }+--                 }+--             }+--         }+--     }+-- } operationsOf :: OpenApi -> Traversal' OpenApi Operation operationsOf sub = paths.itraversed.withIndex.subops   where@@ -123,8 +179,26 @@ -- -- FIXME doc ----- >>> BSL.putStrLn $ encode $ runDeclare (declareResponse "application/json" (Proxy :: Proxy Day)) mempty--- [{"Day":{"example":"2016-07-22","format":"date","type":"string"}},{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Day"}}}}]+-- >>> BSL.putStrLn $ encodePretty $ runDeclare (declareResponse "application/json" (Proxy :: Proxy Day)) mempty+-- [+--     {+--         "Day": {+--             "example": "2016-07-22",+--             "format": "date",+--             "type": "string"+--         }+--     },+--     {+--         "content": {+--             "application/json": {+--                 "schema": {+--                     "$ref": "#/components/schemas/Day"+--                 }+--             }+--         },+--         "description": ""+--     }+-- ] declareResponse :: ToSchema a => MediaType -> Proxy a -> Declare (Definitions Schema) Response declareResponse cType proxy = do   s <- declareSchemaRef proxy@@ -143,8 +217,41 @@ -- -- >>> let api = (mempty :: OpenApi) & paths .~ [("/user", mempty & get ?~ mempty)] -- >>> let res = declareResponse "application/json" (Proxy :: Proxy Day)--- >>> BSL.putStrLn $ encode $ api & setResponse 200 res--- {"openapi":"3.0.0","info":{"version":"","title":""},"paths":{"/user":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Day"}}},"description":""}}}}},"components":{"schemas":{"Day":{"example":"2016-07-22","format":"date","type":"string"}}}}+-- >>> BSL.putStrLn $ encodePretty $ api & setResponse 200 res+-- {+--     "components": {+--         "schemas": {+--             "Day": {+--                 "example": "2016-07-22",+--                 "format": "date",+--                 "type": "string"+--             }+--         }+--     },+--     "info": {+--         "title": "",+--         "version": ""+--     },+--     "openapi": "3.0.0",+--     "paths": {+--         "/user": {+--             "get": {+--                 "responses": {+--                     "200": {+--                         "content": {+--                             "application/json": {+--                                 "schema": {+--                                     "$ref": "#/components/schemas/Day"+--                                 }+--                             }+--                         },+--                         "description": ""+--                     }+--                 }+--             }+--         }+--     }+-- } -- -- See also @'setResponseWith'@. setResponse :: HttpStatusCode -> Declare (Definitions Schema) Response -> OpenApi -> OpenApi
src/Data/OpenApi/Optics.hs view
@@ -22,43 +22,88 @@ -- Example from the "Data.OpenApi" module using @optics@: -- -- >>> :{--- BSL.putStrLn $ encode $ (mempty :: OpenApi)+-- BSL.putStrLn $ encodePretty $ (mempty :: OpenApi) --   & #components % #schemas .~ [ ("User", mempty & #type ?~ OpenApiString) ] --   & #paths .~ --     [ ("/user", mempty & #get ?~ (mempty --         & at 200 ?~ ("OK" & #_Inline % #content % at "application/json" ?~ (mempty & #schema ?~ Ref (Reference "User"))) --         & at 404 ?~ "User info not found")) ] -- :}--- {"openapi":"3.0.0","info":{"version":"","title":""},"paths":{"/user":{"get":{"responses":{"404":{"description":"User info not found"},"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"description":"OK"}}}}},"components":{"schemas":{"User":{"type":"string"}}}}+-- {+--     "components": {+--         "schemas": {+--             "User": {+--                 "type": "string"+--             }+--         }+--     },+--     "info": {+--         "title": "",+--         "version": ""+--     },+--     "openapi": "3.0.0",+--     "paths": {+--         "/user": {+--             "get": {+--                 "responses": {+--                     "200": {+--                         "content": {+--                             "application/json": {+--                                 "schema": {+--                                     "$ref": "#/components/schemas/User"+--                                 }+--                             }+--                         },+--                         "description": "OK"+--                     },+--                     "404": {+--                         "description": "User info not found"+--                     }+--                 }+--             }+--         }+--     }+-- } -- -- For convenience optics are defined as /labels/. It means that field accessor -- names can be overloaded for different types. One such common field is -- @#description@. Many components of a Swagger specification can have -- descriptions, and you can use the same name for them: ----- >>> BSL.putStrLn $ encode $ (mempty :: Response) & #description .~ "No content"--- {"description":"No content"}+-- >>> BSL.putStrLn $ encodePretty $ (mempty :: Response) & #description .~ "No content"+-- {+--     "description": "No content"+-- } -- >>> :{--- BSL.putStrLn $ encode $ (mempty :: Schema)+-- BSL.putStrLn $ encodePretty $ (mempty :: Schema) --   & #type        ?~ OpenApiBoolean --   & #description ?~ "To be or not to be" -- :}--- {"type":"boolean","description":"To be or not to be"}+-- {+--     "description": "To be or not to be",+--     "type": "boolean"+-- } -- -- Additionally, to simplify working with @'Response'@, both @'Operation'@ and -- @'Responses'@ have direct access to it via @'Optics.Core.At.at'@. Example: -- -- >>> :{--- BSL.putStrLn $ encode $ (mempty :: Operation)+-- BSL.putStrLn $ encodePretty $ (mempty :: Operation) --   & at 404 ?~ "Not found" -- :}--- {"responses":{"404":{"description":"Not found"}}}---+-- {+--     "responses": {+--         "404": {+--             "description": "Not found"+--         }+--     }+-- } module Data.OpenApi.Optics () where  import Data.Aeson (Value) import Data.Scientific (Scientific) import Data.OpenApi.Internal+import Data.OpenApi.Internal.Utils import Data.Text (Text) import Optics.Core import Optics.TH
src/Data/OpenApi/Schema.hs view
@@ -13,8 +13,6 @@   toSchemaRef,   schemaName,   toInlinedSchema,-  ToSchema1(..),-  BySchema1(..),    -- * Generic schema encoding   genericDeclareNamedSchema,