git.iko.soy/typeable/openapi3
on ee1ebb7 help sign in
260 lines 8.9 kB history raw
1-- |
2-- Swagger™ is a project used to describe and document RESTful APIs.
3--
4-- The Swagger specification defines a set of files required to describe such an API.
5-- These files can then be used by the Swagger-UI project to display the API
6-- and Swagger-Codegen to generate clients in various languages.
7-- Additional utilities can also take advantage of the resulting files, such as testing tools.
8module Data.Swagger (
9 -- * How to use this library
10 -- $howto
12 -- ** @'Monoid'@ instances
13 -- $monoids
15 -- ** Lenses and prisms
16 -- $lens
18 -- ** Schema specification
19 -- $schema
21 -- * Re-exports
22 module Data.Swagger.Lens,
23 module Data.Swagger.ParamSchema,
24 module Data.Swagger.Schema,
26 -- * Swagger specification
27 Swagger(..),
28 Host(..),
29 Scheme(..),
31 -- ** Info types
32 Info(..),
33 Contact(..),
34 License(..),
36 -- ** PathItem
37 PathItem(..),
39 -- ** Operations
40 Operation(..),
41 Tag(..),
42 TagName,
44 -- ** Types and formats
45 SwaggerType(..),
46 Format,
47 Definitions,
48 CollectionFormat(..),
50 -- ** Parameters
51 Param(..),
52 ParamAnySchema(..),
53 ParamOtherSchema(..),
54 ParamLocation(..),
55 ParamName,
56 Header(..),
57 HeaderName,
58 Example(..),
60 -- ** Schemas
61 ParamSchema(..),
62 Schema(..),
63 NamedSchema(..),
64 SwaggerItems(..),
65 Xml(..),
67 -- ** Responses
68 Responses(..),
69 Response(..),
70 HttpStatusCode,
72 -- ** Security
73 SecurityScheme(..),
74 SecuritySchemeType(..),
75 SecurityRequirement(..),
77 -- *** API key
78 ApiKeyParams(..),
79 ApiKeyLocation(..),
81 -- *** OAuth2
82 OAuth2Params(..),
83 OAuth2Flow(..),
84 AuthorizationURL,
85 TokenURL,
87 -- ** External documentation
88 ExternalDocs(..),
90 -- ** References
91 Reference(..),
92 Referenced(..),
94 -- ** Miscellaneous
95 MimeList(..),
96 URL(..),
97) where
99import Data.Swagger.Lens
100import Data.Swagger.ParamSchema
101import Data.Swagger.Schema
103import Data.Swagger.Internal
105-- $setup
106-- >>> import Control.Lens
107-- >>> import Data.Aeson
108-- >>> import Data.Monoid
109-- >>> import Data.Proxy
110-- >>> import GHC.Generics
111-- >>> :set -XDeriveGeneric
112-- >>> :set -XOverloadedStrings
113-- >>> :set -XOverloadedLists
114-- >>> :set -fno-warn-missing-methods
116-- $howto
117--
118-- This section explains how to use this library to work with Swagger specification.
120-- $monoids
121--
122-- Virtually all types representing Swagger specification have @'Monoid'@ instances.
123-- The @'Monoid'@ type class provides two methods — @'mempty'@ and @'mappend'@.
124--
125-- In this library you can use @'mempty'@ for a default/empty value. For instance:
126--
127-- >>> encode (mempty :: Swagger)
128-- "{\"swagger\":\"2.0\",\"info\":{\"version\":\"\",\"title\":\"\"}}"
129--
130-- As you can see some spec properties (e.g. @"version"@) are there even when the spec is empty.
131-- That is because these properties are actually required ones.
132--
133-- You /should/ always override the default (empty) value for these properties,
134-- although it is not strictly necessary:
135--
136-- >>> encode mempty { _infoTitle = "Todo API", _infoVersion = "1.0" }
137-- "{\"version\":\"1.0\",\"title\":\"Todo API\"}"
138--
139-- You can merge two values using @'mappend'@ or its infix version @('<>')@:
140--
141-- >>> encode $ mempty { _infoTitle = "Todo API" } <> mempty { _infoVersion = "1.0" }
142-- "{\"version\":\"1.0\",\"title\":\"Todo API\"}"
143--
144-- This can be useful for combining specifications of endpoints into a whole API specification:
145--
146-- @
147-- \-\- /account subAPI specification
148-- accountAPI :: Swagger
149--
150-- \-\- /task subAPI specification
151-- taskAPI :: Swagger
152--
153-- \-\- while API specification is just a combination
154-- \-\- of subAPIs' specifications
155-- api :: Swagger
156-- api = accountAPI <> taskAPI
157-- @
159-- $lens
160--
161-- Since @'Swagger'@ has a fairly complex structure, lenses and prisms are used
162-- to work comfortly with it. In combination with @'Monoid'@ instances, lenses
163-- make it fairly simple to construct/modify any part of the specification:
164--
165-- >>> :{
166-- encode $ (mempty :: Swagger)
167-- & definitions .~ [ ("User", mempty & type_ .~ SwaggerString) ]
168-- & paths .~
169-- [ ("/user", mempty & get ?~ (mempty
170-- & produces ?~ MimeList ["application/json"]
171-- & at 200 ?~ ("OK" & _Inline.schema ?~ Ref (Reference "User"))
172-- & at 404 ?~ "User info not found")) ]
173-- :}
174-- "{\"swagger\":\"2.0\",\"info\":{\"version\":\"\",\"title\":\"\"},\"definitions\":{\"User\":{\"type\":\"string\"}},\"paths\":{\"/user\":{\"get\":{\"responses\":{\"404\":{\"description\":\"User info not found\"},\"200\":{\"schema\":{\"$ref\":\"#/definitions/User\"},\"description\":\"OK\"}},\"produces\":[\"application/json\"]}}}}"
175--
176-- In the snippet above we declare API with a single path @/user@ providing method @GET@
177-- which produces @application/json@ output and should respond with code @200@ and body specified
178-- by schema @User@ which is defined in @'definitions'@ property of swagger specification.
179--
180-- For convenience, @swagger2@ uses /classy field lenses/. It means that
181-- field accessor names can be overloaded for different types. One such
182-- common field is @'description'@. Many components of Swagger specification
183-- can have descriptions, and you can use the same name for them:
184--
185-- >>> encode $ (mempty :: Response) & description .~ "No content"
186-- "{\"description\":\"No content\"}"
187-- >>> :{
188-- encode $ (mempty :: Schema)
189-- & type_ .~ SwaggerBoolean
190-- & description ?~ "To be or not to be"
191-- :}
192-- "{\"type\":\"boolean\",\"description\":\"To be or not to be\"}"
193--
194-- @'ParamSchema'@ is basically the /base schema specification/ and many types contain it (see @'HasParamSchema'@).
195-- So for convenience, all @'ParamSchema'@ fields are transitively made fields of the type that has it.
196-- For example, you can use @'type_'@ to access @'SwaggerType'@ of @'Header'@ schema without having to use @'paramSchema'@:
197--
198-- >>> encode $ (mempty :: Header) & type_ .~ SwaggerNumber
199-- "{\"type\":\"number\"}"
200--
201-- Additionally, to simplify working with @'Response'@, both @'Operation'@ and @'Responses'@
202-- have direct access to it via @'at' code@. Example:
203--
204-- >>> :{
205-- encode $ (mempty :: Operation)
206-- & at 404 ?~ "Not found"
207-- :}
208-- "{\"responses\":{\"404\":{\"description\":\"Not found\"}}}"
209--
210-- You might've noticed that @'type_'@ has an extra underscore in its name
211-- compared to, say, @'description'@ field accessor.
212-- This is because @type@ is a keyword in Haskell.
213-- A few other field accessors are modified in this way:
214--
215-- - @'in_'@, @'type_'@, @'default_'@ (as keywords);
216-- - @'maximum_'@ and @'minimum_'@ (as conflicting with @Prelude@);
217-- - @'enum_'@ (as conflicting with @Control.Lens@).
219-- $schema
220--
221-- @'ParamSchema'@ and @'Schema'@ are the two core types for data model specification.
222--
223-- @'ParamSchema' t@ specifies all the common properties, available for every data schema.
224-- The @t@ parameter imposes some restrictions on @type@ and @items@ properties (see @'SwaggerType'@ and @'SwaggerItems'@).
225--
226-- @'Schema'@ is used for request and response bodies and allows specifying objects
227-- with properties in addition to what @'ParamSchema'@ provides.
228--
229-- In most cases you will have a Haskell data type for which you would like to
230-- define a corresponding schema. To facilitate this use case
231-- @swagger2@ provides two classes for schema encoding.
232-- Both these classes provide means to encode /types/ as Swagger /schemas/.
233--
234-- @'ToParamSchema'@ is intended to be used for primitive API endpoint parameters,
235-- such as query parameters, headers and URL path pieces.
236-- Its corresponding value-encoding class is @'ToHttpApiData'@ (from @http-api-data@ package).
237--
238-- @'ToSchema'@ is used for request and response bodies and mostly differ from
239-- primitive parameters by allowing objects/mappings in addition to primitive types and arrays.
240-- Its corresponding value-encoding class is @'ToJSON'@ (from @aeson@ package).
241--
242-- While lenses and prisms make it easy to define schemas, it might be that you don't need to:
243-- @'ToSchema'@ and @'ToParamSchema'@ classes both have default @'Generic'@-based implementations!
244--
245-- @'ToSchema'@ default implementation is also aligned with @'ToJSON'@ default implementation with
246-- the only difference being for sum encoding. @'ToJSON'@ defaults sum encoding to @'defaultTaggedObject'@,
247-- while @'ToSchema'@ defaults to something which corresponds to @'ObjectWithSingleField'@. This is due to
248-- @'defaultTaggedObject'@ behavior being hard to specify in Swagger.
249--
250-- Here's an example showing @'ToJSON'@–@'ToSchema'@ correspondance:
251--
252-- >>> data Person = Person { name :: String, age :: Integer } deriving Generic
253-- >>> instance ToJSON Person
254-- >>> instance ToSchema Person
255-- >>> encode (Person "David" 28)
256-- "{\"age\":28,\"name\":\"David\"}"
257-- >>> encode $ toSchema (Proxy :: Proxy Person)
258-- "{\"required\":[\"name\",\"age\"],\"type\":\"object\",\"properties\":{\"age\":{\"type\":\"integer\"},\"name\":{\"type\":\"string\"}}}"
259--