Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use swagger2 for data model #9

Merged
merged 35 commits into from
Dec 31, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
5c8efdd
Add some commonly ignored files to .gitignore
fizruk Dec 22, 2015
b999260
Clear everything and add HasSwagger with instances for Post
fizruk Dec 22, 2015
967ab8d
Add HasSwagger instances for :<|> and :>
fizruk Dec 22, 2015
c728775
Add HasSwagger instance for Capture
fizruk Dec 22, 2015
2bdb1bb
Add HasSwagger instance for QueryParam
fizruk Dec 22, 2015
4bb54ba
Add HasSwagger instance for QueryParams
fizruk Dec 22, 2015
67f3081
Add HasSwagger instance for QueryFlag
fizruk Dec 22, 2015
574263a
Add HasSwagger instances for matrix params and flags
fizruk Dec 22, 2015
4ee2108
Add HasSwagger instance for Header
fizruk Dec 22, 2015
88254ce
Add HasSwagger instance for ReqBody
fizruk Dec 22, 2015
48366a1
Fix trailing slashes
fizruk Dec 22, 2015
94e2876
Fix HasSwagger Raw instance
fizruk Dec 22, 2015
c21193e
Allow HList in Headers as servant does
fizruk Dec 22, 2015
57c5e80
Add HasSwagger instance for Get
fizruk Dec 22, 2015
2a87201
Add test suite with Todo API example
fizruk Dec 22, 2015
8d27745
Add HasSwagger instances for the rest of servant methods
fizruk Dec 22, 2015
bcbf7c1
Remove matrix params support
fizruk Dec 23, 2015
14bbed4
Add swagger2 to extra-deps
fizruk Dec 23, 2015
6e9ad19
Use type synonyms for HeaderName and HttpStatusCode
fizruk Dec 23, 2015
ba4b4da
Insert 404 responses for Captures with auto description
fizruk Dec 23, 2015
30e7838
Insert 400 responses for query params, headers and body with auto des…
fizruk Dec 23, 2015
1729bd1
Update Todo API example with 404 response
fizruk Dec 23, 2015
e2423d0
Add addTag helper to tag sub APIs of Swagger spec
fizruk Dec 25, 2015
9ddf117
Add Hackage API test example with sub API tags
fizruk Dec 25, 2015
4c4a8dd
Clean up Hackage API example and remove warnings
fizruk Dec 25, 2015
2348a84
Factor out traversal for sub API operations
fizruk Dec 25, 2015
32e4772
Use IsIn for IsSubAPI check
fizruk Dec 25, 2015
7b15a0f
Change addTag to operate on a single Operation, update Hackage example
fizruk Dec 25, 2015
fe93150
Add setResponse helper
fizruk Dec 25, 2015
15ae187
Add custom schema example for Hackage API example
fizruk Dec 30, 2015
5ce1f9d
Update example/ project
fizruk Dec 30, 2015
86eb05c
Update for swagger2-1.1.1
fizruk Dec 30, 2015
307b3f2
Update README example
fizruk Dec 30, 2015
0872c3f
Ignore swagger.json
fizruk Dec 30, 2015
1a2c62b
Expand README on trying out and contributing
fizruk Dec 30, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,20 @@
dist/
/foo.json
servant-client-0.4.4/
.stack-work
cabal-dev
*.o
*.hi
*.chi
*.chs.h
*.dyn_o
*.dyn_hi
.virtualenv
.hpc
.hsenv
.cabal-sandbox/
cabal.sandbox.config
*.prof
*.aux
*.hp
.stack-work/
swagger.json
159 changes: 71 additions & 88 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,73 +14,61 @@

<p align="center">
<img src="http://s16.postimg.org/rndz1wbyt/servant.png" />
</p>
</p>

<hr>

Given the following `servant` API, `servant-swagger` generates the following json.

### [Input](example/File.hs)

```haskell
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
module Main where

import Servant.API
import Servant.Server
import Servant.Swagger
import Data.Proxy
import Control.Lens
import Data.Aeson
import qualified Data.ByteString.Lazy.Char8 as BL8
import Data.Proxy
import Data.Swagger
import GHC.Generics
import Control.Lens
import Servant
import Servant.Swagger

-- Types
data Todo = Todo {
created :: Int
data Todo = Todo
{ created :: Int
, description :: String
} deriving (Show, Eq, Generic)

instance ToJSON Todo
instance FromJSON Todo

newtype TodoId = TodoId String deriving (FromText)
newtype TodoId = TodoId String deriving (FromText, Generic)

-- API
type API = "todo" :> Capture "id" TodoId :> Get '[JSON] Todo

-- Swagger Doc
swagDoc :: SwaggerAPI
swagDoc = swagger (Proxy :: Proxy API) mempty (BasePath "/") info schemes Nothing []
where
schemes = [ Http ]
license' = APILicense "MIT" (Just "http://mit.com")
info =
Info
(APITitle "Todo API") (APIVersion "1.0")
(APIDescription "This is a an API that tests servant-swagger support for a Todo")
(Just license')
Nothing
Nothing
swagDoc :: Swagger
swagDoc = toSwagger (Proxy :: Proxy API)
& info.infoTitle .~ "Todo API"
& info.infoVersion .~ "1.0"
& info.infoDescription ?~ "This is an API that tests servant-swagger support for a Todo"
& info.infoLicense ?~ License "MIT" (Just (URL "http://mit.com"))

-- Documentation and annotations
instance ToSwaggerParamType TodoId where toSwaggerParamType = const StringSwagParam
instance ToSwaggerDescription TodoId where toSwaggerDescription = const "TodoId param"

instance ToSwaggerModel Todo where
toSwagModel Proxy =
emptyModel
& swagModelName .~ ModelName "Todo"
& swagProperties .~ [ ("created", IntegerSwag)
, ("description", StringSwag)
, ("extraTodos", Model $ ModelSwag (ModelName "Todo") False)
]
& swagDescription ?~ Description "This is some real Todo right here"
& swagModelExample ?~ toJSON (Todo 100 "get milk")
& swagModelRequired .~ ["description"]
instance ToParamSchema TodoId

instance ToSchema Todo where
declareNamedSchema proxy = do
(name, schema) <- genericDeclareNamedSchema defaultSchemaOptions proxy
return (name, schema
& schemaDescription ?~ "This is some real Todo right here"
& schemaExample ?~ toJSON (Todo 100 "get milk"))

-- Main, create swaggger.json
main :: IO ()
Expand All @@ -90,94 +78,89 @@ main = BL8.writeFile "swagger.json" (encode swagDoc)
### Output

```json
{
{
"swagger":"2.0",
"basePath":"/",
"schemes":[
"http"
],
"info":{
"info":{
"version":"1.0",
"title":"Todo API",
"license":{
"license":{
"url":"http://mit.com",
"name":"MIT"
},
"description":"This is a an API that tests servant-swagger support for a Todo"
"description":"This is an API that tests servant-swagger support for a Todo"
},
"definitions":{
"Todo":{
"example":{
"definitions":{
"Todo":{
"example":{
"created":100,
"description":"get milk"
},
"required":[
"required":[
"created",
"description"
],
"type":"object",
"description":"This is some real Todo right here",
"properties":{
"created":{
"format":"int32",
"properties":{
"created":{
"maximum":9223372036854775807,
"minimum":-9223372036854775808,
"type":"integer"
},
"description":{
"description":{
"type":"string"
},
"extraTodos":{
"$ref":"#/definitions/Todo"
}
}
}
},
"paths":{
"/todo/{id}":{
"get":{
"summary":"",
"consumes":[

],
"responses":{
"200":{
"schema":{
"paths":{
"/todo/{id}":{
"get":{
"responses":{
"404":{
"description":"id not found"
},
"200":{
"schema":{
"$ref":"#/definitions/Todo"
},
"headers":{

},
"description":"OK"
"description":""
}
},
"produces":[
"produces":[
"application/json"
],
"parameters":[
{
"parameters":[
{
"required":true,
"in":"path",
"name":"id",
"type":"string",
"description":"TodoId param"
"type":"string"
}
],
"description":"",
"tags":[

]
}
}
},
"tags":[

]
}
}
```

## Try it out
- All generated swagger docs can be interactively viewed on <a href="http://editor.swagger.io/">Swagger Editor</a>

## Limitations
- Quite a few, TODO: add this
All generated swagger specifications can be interactively viewed on [Swagger Editor](http://editor.swagger.io/).

Ready-to-use specification can be served as JSON and interactive API documentation
can be displayed using [Swagger UI](https://github.com/swagger-api/swagger-ui).

Many Swagger tools, including server and client code generation for many languages, can be found on
[Swagger's Tools and Integrations page](http://swagger.io/open-source-integrations/).

## FAQ
- Q: How is this project different from the `swagger` package on `hackage` ?
- A: This package is based on the latest Swagger 2.0 API

## Contributing

We are happy to receive bug reports, fixes, documentation enhancements, and other improvements.

Please report bugs via the [github issue tracker](https://github.com/dmjio/servant-swagger/issues).

64 changes: 26 additions & 38 deletions example/File.hs
Original file line number Diff line number Diff line change
@@ -1,63 +1,51 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
module Main where

import Servant.API
import Servant.Server
import Servant.Swagger
import Data.Proxy
import Control.Lens
import Data.Aeson
import qualified Data.ByteString.Lazy.Char8 as BL8
import Data.Proxy
import Data.Swagger
import GHC.Generics
import Control.Lens
import Servant
import Servant.Swagger

-- Types
data Todo = Todo {
created :: Int
data Todo = Todo
{ created :: Int
, description :: String
} deriving (Show, Eq, Generic)

instance ToJSON Todo
instance FromJSON Todo

newtype TodoId = TodoId String deriving (FromText)
newtype TodoId = TodoId String deriving (FromText, Generic)

-- API
type API = "todo" :> Capture "id" TodoId :> Get '[JSON] Todo

-- Swagger Doc
swagDoc :: SwaggerAPI
swagDoc = swagger (Proxy :: Proxy API) mempty (BasePath "/") info schemes Nothing []
where
schemes = [ Http ]
license' = APILicense "MIT" (Just "http://mit.com")
info =
Info
(APITitle "Todo API") (APIVersion "1.0")
(APIDescription "This is a an API that tests servant-swagger support for a Todo")
(Just license')
Nothing
Nothing
swagDoc :: Swagger
swagDoc = toSwagger (Proxy :: Proxy API)
& info.infoTitle .~ "Todo API"
& info.infoVersion .~ "1.0"
& info.infoDescription ?~ "This is an API that tests servant-swagger support for a Todo"
& info.infoLicense ?~ License "MIT" (Just (URL "http://mit.com"))

-- Documentation and annotations
instance ToSwaggerParamType TodoId where toSwaggerParamType = const StringSwagParam
instance ToSwaggerDescription TodoId where toSwaggerDescription = const "TodoId param"

instance ToSwaggerModel Todo where
toSwagModel Proxy =
emptyModel
& swagModelName .~ ModelName "Todo"
& swagProperties .~ [ ("created", IntegerSwag)
, ("description", StringSwag)
, ("extraTodos", Model $ ModelSwag (ModelName "Todo") False)
]
& swagDescription ?~ Description "This is some real Todo right here"
& swagModelExample ?~ toJSON (Todo 100 "get milk")
& swagModelRequired .~ ["description"]
instance ToParamSchema TodoId

instance ToSchema Todo where
declareNamedSchema proxy = do
(name, schema) <- genericDeclareNamedSchema defaultSchemaOptions proxy
return (name, schema
& schemaDescription ?~ "This is some real Todo right here"
& schemaExample ?~ toJSON (Todo 100 "get milk"))

-- Main, create swaggger.json
main :: IO ()
main = BL8.writeFile "swagger.json" (encode swagDoc)

Loading