Compare commits
52 Commits
Author | SHA1 | Date |
---|---|---|
Julian K. Arni | 3e91a24e4c | |
Julian K. Arni | 1862b77a32 | |
Julian Arni | 9d6dd2996f | |
Ondrej Palkovsky | becc013002 | |
Julian K. Arni | bf47b2d86f | |
Julian K. Arni | 230f51bf22 | |
Julian K. Arni | 9c35e21fd1 | |
Julian K. Arni | 9cea7902df | |
Julian K. Arni | f525f5b14f | |
Julian K. Arni | 9ad82654da | |
Julian Arni | 5568d14eef | |
Eric Nething | c83ec084b3 | |
Julian K. Arni | 363f8c48fe | |
Julian K. Arni | 6adecc9d09 | |
Julian Arni | 4e28a45da4 | |
Julian K. Arni | c60588ade1 | |
Julian K. Arni | 48c2cc638a | |
Julian K. Arni | fe8408e272 | |
Julian K. Arni | 397db6b4b5 | |
Julian K. Arni | ef3cf9f757 | |
Julian K. Arni | afc0f31f91 | |
Julian K. Arni | 162f5bbd9c | |
AndrewRademacher | 051e6118dd | |
Julian K. Arni | 867530fb59 | |
Julian Arni | b4be241fc9 | |
Julian K. Arni | ca1b21ebff | |
Julian K. Arni | 28d48ce320 | |
Julian K. Arni | 4397154f49 | |
Julian K. Arni | cb75ed4073 | |
Julian K. Arni | 52adac2039 | |
Julian K. Arni | 85f5dfadde | |
Alp Mestanogullari | 4bcf5158e7 | |
Alp Mestanogullari | e5341d708f | |
Julian K. Arni | 17b99b933f | |
Julian K. Arni | b74d699f6c | |
Julian K. Arni | 1eacd565f1 | |
Julian K. Arni | b5b4d9ad60 | |
Christian Marie | a67cbbc224 | |
Christian Marie | fb97bee5ee | |
bwo | 3b4df6775b | |
Christian Marie | 1efe9f1a2a | |
Alp Mestanogullari | e3c3ba2aeb | |
Alp Mestanogullari | 76b21f787c | |
Philipp Kant | d1ee5c7a63 | |
Philipp Kant | 3565641359 | |
Alp Mestanogullari | 452ddf02e4 | |
Julian K. Arni | 9f319963e9 | |
Julian K. Arni | c11012dcbf | |
Julian K. Arni | 0c52b23168 | |
Julian K. Arni | c86e32433a | |
Julian K. Arni | 1fc048e9db | |
Julian K. Arni | 358f7691e5 |
|
@ -1,8 +1,8 @@
|
|||
dist
|
||||
bin
|
||||
lib
|
||||
share
|
||||
packages
|
||||
/dist
|
||||
/bin
|
||||
/lib
|
||||
/share
|
||||
/packages
|
||||
*-packages.conf.d
|
||||
cabal-dev
|
||||
add-source-timestamps
|
||||
|
|
|
@ -16,33 +16,17 @@
|
|||
set -o nounset
|
||||
set -o errexit
|
||||
|
||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
DRY_RUN=false
|
||||
POSITION="none"
|
||||
SOURCES_TXT="$( dirname $DIR)/sources.txt"
|
||||
|
||||
declare -a SOURCES
|
||||
readarray -t SOURCES < "$SOURCES_TXT"
|
||||
DIR=$( dirname $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ))
|
||||
. "${DIR}/scripts/lib/common.sh"
|
||||
|
||||
usage () {
|
||||
echo " bump-versions <POSITION> [-d|--dry-run]"
|
||||
echo " bump-versions.sh <POSITION> [-d|--dry-run]"
|
||||
echo " | [-h|--help]"
|
||||
echo " Bumps the specified positional version of all servant packages."
|
||||
echo " POSITION is a number between 0 and 3, inclusive."
|
||||
exit 0
|
||||
}
|
||||
|
||||
join () { local IFS="$1"; shift; echo "$*"; }
|
||||
|
||||
versions_equal () {
|
||||
local NUM=$(find . -name 'servant*.cabal' | xargs grep "^version:" | awk '{ print $2 }' | uniq -c | wc -l)
|
||||
if [ 1 -eq $NUM ] ; then
|
||||
return 0
|
||||
else
|
||||
echo "versions of packages are not all the same!" && exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
if [ $# -eq 0 ] ; then
|
||||
echo "expecting one or more arguments. Got 0"
|
||||
usage
|
||||
|
@ -71,8 +55,11 @@ while [ "${1:-unset}" != "unset" ] ; do
|
|||
done
|
||||
|
||||
if $DRY_RUN ; then
|
||||
bumper --dry-run -"$POSITION" $(join , "${SOURCES[@]}")
|
||||
echo "Would have bumped position ${POSITION} on these packages:"
|
||||
( cd "$ROOT" && bumper --dry-run -"$POSITION" $(join , "${SOURCES[@]}") )
|
||||
else
|
||||
bumper -"$POSITION" $(join , "${SOURCES[@]}")
|
||||
( cd "$ROOT" && bumper -"$POSITION" $(join , "${SOURCES[@]}") )
|
||||
fi
|
||||
|
||||
# Trailing newline, bumper does not ship with its own.
|
||||
echo
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#!/bin/bash -
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: lib/common.sh
|
||||
#
|
||||
# DESCRIPTION: Common functions for servant's shell scripts
|
||||
# Meant to be sourced rather than run.
|
||||
#
|
||||
# REQUIREMENTS: bash >= 4
|
||||
#===============================================================================
|
||||
|
||||
|
||||
DIR=$( dirname $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ))
|
||||
ROOT=$( dirname $DIR )
|
||||
DRY_RUN=false
|
||||
POSITION="none"
|
||||
SOURCES_TXT="$( dirname $DIR)/sources.txt"
|
||||
CABAL=${CABAL:-cabal}
|
||||
|
||||
declare -a SOURCES
|
||||
readarray -t SOURCES < "$SOURCES_TXT"
|
||||
|
||||
join () { local IFS="$1"; shift; echo "$*"; }
|
||||
|
||||
versions_equal () {
|
||||
local NUM=$(cd "$ROOT" && find . -name 'servant*.cabal' | xargs grep "^version:" | awk '{ print $2 }' | uniq -c | wc -l)
|
||||
if [ 1 -eq $NUM ] ; then
|
||||
return 0
|
||||
else
|
||||
echo "versions of packages are not all the same!" && exit 1
|
||||
fi
|
||||
}
|
|
@ -14,11 +14,7 @@ set -o nounset
|
|||
set -o errexit
|
||||
|
||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
SOURCES_TXT="$( dirname $DIR)/sources.txt"
|
||||
CABAL=${CABAL:-cabal}
|
||||
|
||||
declare -a SOURCES
|
||||
readarray -t SOURCES < "$SOURCES_TXT"
|
||||
. "$DIR"/lib/common.sh
|
||||
|
||||
prepare_sandbox () {
|
||||
$CABAL sandbox init
|
||||
|
|
|
@ -15,13 +15,10 @@ set -o nounset
|
|||
set -o errexit
|
||||
|
||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
GHC_FLAGS="-Werror"
|
||||
SOURCES_TXT="$( dirname $DIR)/sources.txt"
|
||||
CABAL=${CABAL:-cabal}
|
||||
|
||||
declare -a SOURCES
|
||||
readarray -t SOURCES < "$SOURCES_TXT"
|
||||
. "$DIR"/lib/common.sh
|
||||
|
||||
# TODO: Remove missing-methods after https://github.com/bos/aeson/issues/290
|
||||
GHC_FLAGS="-Werror -fno-warn-missing-methods"
|
||||
|
||||
prepare_sandbox () {
|
||||
$CABAL sandbox init
|
||||
|
|
|
@ -12,11 +12,7 @@ set -o nounset
|
|||
set -o errexit
|
||||
|
||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
BASE_DIR="$( dirname $DIR)"
|
||||
SOURCES_TXT="$BASE_DIR/sources.txt"
|
||||
|
||||
declare -a SOURCES
|
||||
readarray -t SOURCES < "$SOURCES_TXT"
|
||||
. "$DIR"/lib/common.sh
|
||||
|
||||
for s in ${SOURCES[@]} ; do
|
||||
echo $s
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
#!/bin/bash -
|
||||
#===============================================================================
|
||||
#
|
||||
# FILE: upload.sh
|
||||
#
|
||||
# USAGE: ./upload.sh <USER> <PASSWORD>
|
||||
#
|
||||
# DESCRIPTION: Uploads all servant packages to Hackage
|
||||
#
|
||||
# REQUIREMENTS: cabal, bash >= 4
|
||||
# AUTHOR: Julian K. Arni
|
||||
# CREATED: 05.06.2015 13:05
|
||||
#===============================================================================
|
||||
|
||||
set -o nounset
|
||||
set -o errexit
|
||||
|
||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
. "$DIR"/lib/common.sh
|
||||
|
||||
usage () {
|
||||
echo " upload.sh <USER> <PASSWORD>"
|
||||
echo " Uploads all servant packages to Hackage"
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
upload_package () {
|
||||
local package="$1"
|
||||
local user="$2"
|
||||
local pass="$3"
|
||||
local cabalFile="$package.cabal"
|
||||
pushd "$package"
|
||||
local version=$(grep -i '^version:' $cabalFile | awk '{ print $2 }')
|
||||
local sdist="dist/${package}-${version}.tar.gz"
|
||||
cabal sdist
|
||||
echo "User is: $user"
|
||||
cabal upload --user="$user" --password="$pass" "$sdist"
|
||||
popd
|
||||
}
|
||||
|
||||
|
||||
if [ $# -ne 2 ] ; then
|
||||
echo "expecting two arguments."
|
||||
usage
|
||||
fi
|
||||
|
||||
versions_equal
|
||||
|
||||
for s in ${SOURCES[@]} ; do
|
||||
upload_package "$s" "$1" "$2"
|
||||
done
|
|
@ -2,7 +2,7 @@
|
|||
-- documentation, see http://haskell.org/cabal/users-guide/
|
||||
|
||||
name: servant-blaze
|
||||
version: 0.4.1
|
||||
version: 0.4.4.7
|
||||
synopsis: Blaze-html support for servant
|
||||
-- description:
|
||||
homepage: http://haskell-servant.github.io/
|
||||
|
@ -15,6 +15,10 @@ category: Web
|
|||
build-type: Simple
|
||||
-- extra-source-files:
|
||||
cabal-version: >=1.10
|
||||
bug-reports: http://github.com/haskell-servant/servant/issues
|
||||
source-repository head
|
||||
type: git
|
||||
location: http://github.com/haskell-servant/servant.git
|
||||
|
||||
library
|
||||
exposed-modules: Servant.HTML.Blaze
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
Copyright (c) 2015, Julian K. Arni
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of Julian K. Arni nor the names of other
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,2 @@
|
|||
import Distribution.Simple
|
||||
main = defaultMain
|
|
@ -0,0 +1,29 @@
|
|||
-- Initial servant-cassava.cabal generated by cabal init. For further
|
||||
-- documentation, see http://haskell.org/cabal/users-guide/
|
||||
|
||||
name: servant-cassava
|
||||
version: 0.4.4.7
|
||||
synopsis: Servant CSV content-type for cassava
|
||||
-- description:
|
||||
homepage: http://haskell-servant.github.io/
|
||||
license: BSD3
|
||||
license-file: LICENSE
|
||||
author: Julian K. Arni
|
||||
maintainer: jkarni@gmail.com
|
||||
-- copyright:
|
||||
-- category:
|
||||
build-type: Simple
|
||||
-- extra-source-files:
|
||||
cabal-version: >=1.10
|
||||
|
||||
library
|
||||
exposed-modules: Servant.CSV.Cassava
|
||||
-- other-modules:
|
||||
-- other-extensions:
|
||||
build-depends: base >=4.6 && <5
|
||||
, cassava >0.4 && <0.5
|
||||
, servant == 0.4.*
|
||||
, http-media
|
||||
, vector
|
||||
hs-source-dirs: src
|
||||
default-language: Haskell2010
|
|
@ -0,0 +1,88 @@
|
|||
{-# LANGUAGE DeriveDataTypeable #-}
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
{-# LANGUAGE FlexibleInstances #-}
|
||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE ScopedTypeVariables #-}
|
||||
|
||||
-- | A @CSV@ empty datatype with `MimeRender` and `MimeUnrender` instances for
|
||||
-- @cassava@'s encoding and decoding classes.
|
||||
--
|
||||
-- >>> type Eg = Get '[(CSV', MyEncodeOptions)] [(Int, String)]
|
||||
--
|
||||
-- Default encoding and decoding options are also provided, along with the
|
||||
-- @CSV@ type synonym that uses them.
|
||||
--
|
||||
-- >>> type EgDefault = Get '[CSV] [(Int, String)]
|
||||
module Servant.CSV.Cassava where
|
||||
|
||||
import Data.Csv
|
||||
import Data.Proxy (Proxy (..))
|
||||
import Data.Typeable (Typeable)
|
||||
import Data.Vector (Vector)
|
||||
import GHC.Generics (Generic)
|
||||
import qualified Network.HTTP.Media as M
|
||||
import Servant.API (Accept (..), MimeRender (..),
|
||||
MimeUnrender (..))
|
||||
|
||||
data CSV' deriving (Typeable, Generic)
|
||||
|
||||
type CSV = (CSV', DefaultDecodeOpts)
|
||||
|
||||
-- | @text/csv;charset=utf-8@
|
||||
instance Accept (CSV', a) where
|
||||
contentType _ = "text" M.// "csv" M./: ("charset", "utf-8")
|
||||
|
||||
-- * Encoding
|
||||
|
||||
-- ** Instances
|
||||
|
||||
-- | Encode with 'encodeByNameWith'. The 'Header' param is used for determining
|
||||
-- the order of headers and fields.
|
||||
instance ( ToNamedRecord a, EncodeOpts opt
|
||||
) => MimeRender (CSV', opt) (Header, [a]) where
|
||||
mimeRender _ (hdr, vals) = encodeByNameWith (encodeOpts p) hdr vals
|
||||
where p = Proxy :: Proxy opt
|
||||
|
||||
-- | Encode with 'encodeDefaultOrderedByNameWith'
|
||||
instance ( DefaultOrdered a, ToNamedRecord a, EncodeOpts opt
|
||||
) => MimeRender (CSV', opt) [a] where
|
||||
mimeRender _ = encodeDefaultOrderedByNameWith (encodeOpts p)
|
||||
where p = Proxy :: Proxy opt
|
||||
|
||||
|
||||
-- ** Encode Options
|
||||
|
||||
class EncodeOpts a where
|
||||
encodeOpts :: Proxy a -> EncodeOptions
|
||||
|
||||
data DefaultEncodeOpts deriving (Typeable, Generic)
|
||||
|
||||
instance EncodeOpts DefaultEncodeOpts where
|
||||
encodeOpts _ = defaultEncodeOptions
|
||||
|
||||
-- * Decoding
|
||||
|
||||
-- ** Instances
|
||||
|
||||
-- | Decode with 'decodeByNameWith'
|
||||
instance ( FromNamedRecord a, DecodeOpts opt
|
||||
) => MimeUnrender (CSV', opt) (Header, Vector a) where
|
||||
mimeUnrender _ = decodeByNameWith (decodeOpts p)
|
||||
where p = Proxy :: Proxy opt
|
||||
|
||||
-- | Decode with 'decodeWith'. Assumes data has headers, which are stripped.
|
||||
instance ( FromRecord a, DecodeOpts opt
|
||||
) => MimeUnrender (CSV', opt) (Vector a) where
|
||||
mimeUnrender _ = decodeWith (decodeOpts p) HasHeader
|
||||
where p = Proxy :: Proxy opt
|
||||
|
||||
-- ** Decode Options
|
||||
|
||||
class DecodeOpts a where
|
||||
decodeOpts :: Proxy a -> DecodeOptions
|
||||
|
||||
data DefaultDecodeOpts deriving (Typeable, Generic)
|
||||
|
||||
instance DecodeOpts DefaultDecodeOpts where
|
||||
decodeOpts _ = defaultDecodeOptions
|
|
@ -1,5 +1,5 @@
|
|||
name: servant-client
|
||||
version: 0.4.1
|
||||
version: 0.4.4.7
|
||||
synopsis: automatical derivation of querying functions for servant webservices
|
||||
description:
|
||||
This library lets you derive automatically Haskell functions that
|
||||
|
|
|
@ -252,7 +252,7 @@ instance
|
|||
(MimeUnrender ct a) => HasClient (Post (ct ': cts) a) where
|
||||
type Client (Post (ct ': cts) a) = EitherT ServantError IO a
|
||||
clientWithRoute Proxy req baseurl =
|
||||
snd <$> performRequestCT (Proxy :: Proxy ct) H.methodPost req [200,201] baseurl
|
||||
snd <$> performRequestCT (Proxy :: Proxy ct) H.methodPost req [200, 201, 202] baseurl
|
||||
|
||||
-- | If you have a 'Post xs ()' endpoint, the client expects a 204 No Content
|
||||
-- HTTP header.
|
||||
|
@ -275,7 +275,7 @@ instance
|
|||
) => HasClient (Post (ct ': cts) (Headers ls a)) where
|
||||
type Client (Post (ct ': cts) (Headers ls a)) = EitherT ServantError IO (Headers ls a)
|
||||
clientWithRoute Proxy req baseurl = do
|
||||
(hdrs, resp) <- performRequestCT (Proxy :: Proxy ct) H.methodPost req [200, 201] baseurl
|
||||
(hdrs, resp) <- performRequestCT (Proxy :: Proxy ct) H.methodPost req [200, 201, 202] baseurl
|
||||
return $ Headers { getResponse = resp
|
||||
, getHeadersHList = buildHeadersTo hdrs
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
0.4.3
|
||||
-----
|
||||
* docsWith will no longer eat your documentation (https://github.com/haskell-servant/servant/pull/124)
|
||||
|
||||
0.4
|
||||
---
|
||||
* `Delete` now is like `Get`, `Post`, `Put`, and `Patch` and returns a response body
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: servant-docs
|
||||
version: 0.4.1
|
||||
version: 0.4.4.7
|
||||
synopsis: generate API docs for your servant webservice
|
||||
description:
|
||||
Library for generating API docs from a servant API definition.
|
||||
|
@ -70,6 +70,7 @@ test-suite spec
|
|||
base
|
||||
, aeson
|
||||
, hspec
|
||||
, lens
|
||||
, servant
|
||||
, servant-docs
|
||||
, string-conversions
|
||||
|
|
|
@ -22,18 +22,20 @@ module Servant.Docs.Internal where
|
|||
#if !MIN_VERSION_base(4,8,0)
|
||||
import Control.Applicative
|
||||
#endif
|
||||
import Control.Lens
|
||||
import Control.Lens (makeLenses, over, traversed, (%~),
|
||||
(&), (.~), (<>~), (^.), _1, _2,
|
||||
_last, (|>))
|
||||
import Data.ByteString.Conversion (ToByteString, toByteString)
|
||||
import Data.ByteString.Lazy.Char8 (ByteString)
|
||||
import qualified Data.CaseInsensitive as CI
|
||||
import Data.Hashable
|
||||
import Data.Hashable (Hashable)
|
||||
import Data.HashMap.Strict (HashMap)
|
||||
import Data.List
|
||||
import Data.Maybe
|
||||
import Data.Monoid
|
||||
import Data.Ord (comparing)
|
||||
import Data.Proxy
|
||||
import Data.ByteString.Conversion (ToByteString, toByteString)
|
||||
import Data.String.Conversions
|
||||
import Data.Proxy (Proxy(Proxy))
|
||||
import Data.String.Conversions (cs)
|
||||
import Data.Text (Text, pack, unpack)
|
||||
import GHC.Exts (Constraint)
|
||||
import GHC.Generics
|
||||
|
@ -338,7 +340,7 @@ extraInfo p action =
|
|||
docsWith :: HasDocs layout => [DocIntro] -> ExtraInfo layout -> Proxy layout -> API
|
||||
docsWith intros (ExtraInfo endpoints) p =
|
||||
docs p & apiIntros <>~ intros
|
||||
& apiEndpoints %~ HM.unionWith combineAction endpoints
|
||||
& apiEndpoints %~ HM.unionWith (flip combineAction) endpoints
|
||||
|
||||
|
||||
-- | Generate the docs for a given API that implements 'HasDocs' with with any
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||
module Servant.DocsSpec where
|
||||
|
||||
import Control.Lens
|
||||
import Data.Aeson
|
||||
import Data.Monoid
|
||||
import Data.Proxy
|
||||
import Data.String.Conversions (cs)
|
||||
import GHC.Generics
|
||||
|
@ -21,7 +23,27 @@ spec = describe "Servant.Docs" $ do
|
|||
|
||||
describe "markdown" $ do
|
||||
let md = markdown (docs (Proxy :: Proxy TestApi1))
|
||||
tests md
|
||||
|
||||
describe "markdown with extra info" $ do
|
||||
let
|
||||
extra = extraInfo
|
||||
(Proxy :: Proxy (Get '[JSON, PlainText] Int))
|
||||
(defAction & notes <>~ [DocNote "Get an Integer" ["get an integer in Json or plain text"]])
|
||||
<>
|
||||
extraInfo
|
||||
(Proxy :: Proxy (ReqBody '[JSON] String :> Post '[JSON] Datatype1))
|
||||
(defAction & notes <>~ [DocNote "Post data" ["Posts some Json data"]])
|
||||
md = markdown (docsWith [] extra (Proxy :: Proxy TestApi1))
|
||||
tests md
|
||||
it "contains the extra info provided" $ do
|
||||
md `shouldContain` "Get an Integer"
|
||||
md `shouldContain` "Post data"
|
||||
md `shouldContain` "get an integer in Json or plain text"
|
||||
md `shouldContain` "Posts some Json data"
|
||||
|
||||
where
|
||||
tests md = do
|
||||
it "mentions supported content-types" $ do
|
||||
md `shouldContain` "application/json"
|
||||
md `shouldContain` "text/plain;charset=utf-8"
|
||||
|
@ -34,10 +56,11 @@ spec = describe "Servant.Docs" $ do
|
|||
md `shouldContain` "POST"
|
||||
md `shouldContain` "GET"
|
||||
|
||||
it "contains response samples" $ do
|
||||
it "contains response samples" $
|
||||
md `shouldContain` "{\"dt1field1\":\"field 1\",\"dt1field2\":13}"
|
||||
it "contains request body samples" $ do
|
||||
it "contains request body samples" $
|
||||
md `shouldContain` "17"
|
||||
|
||||
-- * APIs
|
||||
|
||||
data Datatype1 = Datatype1 { dt1field1 :: String
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
0.4.3
|
||||
-----
|
||||
* Clarify some variable names in the examples + semantic html pedantry
|
|
@ -5,6 +5,7 @@
|
|||
{-# LANGUAGE FlexibleInstances #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE ScopedTypeVariables #-}
|
||||
{-# OPTIONS_GHC -fno-warn-unused-binds #-}
|
||||
import Data.Aeson
|
||||
import Data.ByteString (ByteString)
|
||||
import Data.Text (Text)
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
{-# LANGUAGE DeriveGeneric #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# OPTIONS_GHC -fno-warn-unused-binds #-}
|
||||
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
|
||||
import Control.Applicative
|
||||
import Control.Monad
|
||||
import Control.Monad.IO.Class
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: servant-examples
|
||||
version: 0.4.1
|
||||
version: 0.4.4.7
|
||||
synopsis: Example programs for servant
|
||||
description: Example programs for servant,
|
||||
showcasing solutions to common needs.
|
||||
|
@ -12,12 +12,16 @@ maintainer: alpmestan@gmail.com
|
|||
category: Web
|
||||
build-type: Simple
|
||||
cabal-version: >=1.10
|
||||
bug-reports: http://github.com/haskell-servant/servant/issues
|
||||
source-repository head
|
||||
type: git
|
||||
location: http://github.com/haskell-servant/servant.git
|
||||
|
||||
executable tutorial
|
||||
main-is: tutorial.hs
|
||||
other-modules: T1, T2, T3, T4, T5, T6, T7, T8, T9, T10
|
||||
build-depends:
|
||||
aeson >= 0.8
|
||||
aeson >= 0.10
|
||||
, base >= 4.7 && < 5
|
||||
, bytestring
|
||||
, directory
|
||||
|
@ -41,6 +45,7 @@ executable tutorial
|
|||
|
||||
executable t8-main
|
||||
main-is: t8-main.hs
|
||||
other-modules: T3, T8
|
||||
hs-source-dirs: tutorial
|
||||
default-language: Haskell2010
|
||||
build-depends:
|
||||
|
|
|
@ -17,17 +17,12 @@ data User = User
|
|||
, registration_date :: Day
|
||||
} deriving (Eq, Show, Generic)
|
||||
|
||||
-- orphan ToJSON instance for Day. necessary to derive one for User
|
||||
instance ToJSON Day where
|
||||
-- display a day in YYYY-mm-dd format
|
||||
toJSON d = toJSON (showGregorian d)
|
||||
|
||||
instance ToJSON User
|
||||
|
||||
type UserAPI = "users" :> Get '[JSON] [User]
|
||||
|
||||
users :: [User]
|
||||
users =
|
||||
users =
|
||||
[ User "Isaac Newton" 372 "isaac@newton.co.uk" (fromGregorian 1683 3 1)
|
||||
, User "Albert Einstein" 136 "ae@mc2.org" (fromGregorian 1905 12 1)
|
||||
]
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
{-# LANGUAGE FlexibleInstances #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||
module T10 where
|
||||
|
||||
import Data.ByteString.Lazy (ByteString)
|
||||
|
|
|
@ -17,11 +17,6 @@ data User = User
|
|||
, registration_date :: Day
|
||||
} deriving (Eq, Show, Generic)
|
||||
|
||||
-- orphan ToJSON instance for Day. necessary to derive one for User
|
||||
instance ToJSON Day where
|
||||
-- display a day in YYYY-mm-dd format
|
||||
toJSON d = toJSON (showGregorian d)
|
||||
|
||||
instance ToJSON User
|
||||
|
||||
type UserAPI = "users" :> Get '[JSON] [User]
|
||||
|
|
|
@ -70,7 +70,7 @@ server = position
|
|||
:<|> marketing
|
||||
|
||||
where position :: Int -> Int -> EitherT ServantErr IO Position
|
||||
position x y = return (Position x y)
|
||||
position a b = return (Position a b)
|
||||
|
||||
hello :: Maybe String -> EitherT ServantErr IO HelloMessage
|
||||
hello mname = return . HelloMessage $ case mname of
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
{-# LANGUAGE TypeOperators #-}
|
||||
{-# LANGUAGE FlexibleInstances #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
|
||||
module T4 where
|
||||
|
||||
import Data.Aeson
|
||||
|
@ -25,23 +26,23 @@ instance ToJSON Person
|
|||
|
||||
-- HTML serialization of a single person
|
||||
instance ToHtml Person where
|
||||
toHtml p =
|
||||
toHtml person =
|
||||
tr_ $ do
|
||||
td_ (toHtml $ firstName p)
|
||||
td_ (toHtml $ lastName p)
|
||||
td_ (toHtml . show $ age p)
|
||||
td_ (toHtml $ firstName person)
|
||||
td_ (toHtml $ lastName person)
|
||||
td_ (toHtml . show $ age person)
|
||||
|
||||
toHtmlRaw = toHtml
|
||||
|
||||
-- HTML serialization of a list of persons
|
||||
instance ToHtml [Person] where
|
||||
toHtml persons = table_ $ do
|
||||
toHtml ps = table_ $ do
|
||||
tr_ $ do
|
||||
td_ "first name"
|
||||
td_ "last name"
|
||||
td_ "age"
|
||||
th_ "first name"
|
||||
th_ "last name"
|
||||
th_ "age"
|
||||
|
||||
foldMap toHtml persons
|
||||
foldMap toHtml ps
|
||||
|
||||
toHtmlRaw = toHtml
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
|
||||
module T8 where
|
||||
|
||||
import Control.Monad.Trans.Either
|
||||
import Data.Aeson
|
||||
import Servant
|
||||
import Servant.Client
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
{-# LANGUAGE DeriveGeneric #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
|
||||
module T9 where
|
||||
|
||||
import Control.Applicative
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# OPTIONS_GHC -fno-warn-unused-binds #-}
|
||||
import Data.Aeson
|
||||
import Data.Text
|
||||
import GHC.Generics
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
0.4.3
|
||||
-----
|
||||
* Content type now set to JSON when a request body is sent (#122)
|
||||
|
||||
0.4
|
||||
---
|
||||
* `Delete` now is like `Get`, `Post`, `Put`, and `Patch` and returns a response body
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: servant-jquery
|
||||
version: 0.4.1
|
||||
version: 0.4.4.7
|
||||
synopsis: Automatically derive (jquery) javascript functions to query servant webservices
|
||||
description:
|
||||
Automatically derive jquery-based javascript functions to query servant webservices.
|
||||
|
|
|
@ -65,13 +65,14 @@ generateJS req = "\n" <>
|
|||
|
||||
dataBody =
|
||||
if req ^. reqBody
|
||||
then "\n , data: JSON.stringify(body)\n"
|
||||
then " , data: JSON.stringify(body)\n" <>
|
||||
" , contentType: 'application/json'\n"
|
||||
else ""
|
||||
|
||||
reqheaders =
|
||||
if null hs
|
||||
then ""
|
||||
else "\n , headers: { " ++ headersStr ++ " }\n"
|
||||
else " , headers: { " ++ headersStr ++ " }\n"
|
||||
|
||||
where headersStr = intercalate ", " $ map headerStr hs
|
||||
headerStr header = "\"" ++
|
||||
|
|
|
@ -11,19 +11,20 @@
|
|||
module Servant.JQuery.Internal where
|
||||
|
||||
#if !MIN_VERSION_base(4,8,0)
|
||||
import Control.Applicative
|
||||
import Control.Applicative
|
||||
#endif
|
||||
import Control.Lens
|
||||
import Data.Char (toLower)
|
||||
import qualified Data.CharSet as Set
|
||||
import Control.Lens (makeLenses, (%~), (&), (.~)
|
||||
, (<>~), (^.), _last)
|
||||
import Data.Char (toLower)
|
||||
import qualified Data.CharSet as Set
|
||||
import qualified Data.CharSet.Unicode.Category as Set
|
||||
import Data.List
|
||||
import Data.Monoid
|
||||
import Data.Proxy
|
||||
import qualified Data.Text as T
|
||||
import GHC.Exts (Constraint)
|
||||
import GHC.TypeLits
|
||||
import Servant.API
|
||||
import Data.List
|
||||
import Data.Monoid
|
||||
import Data.Proxy
|
||||
import qualified Data.Text as T
|
||||
import GHC.Exts (Constraint)
|
||||
import GHC.TypeLits
|
||||
import Servant.API
|
||||
|
||||
type Arg = String
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
-- documentation, see http://haskell.org/cabal/users-guide/
|
||||
|
||||
name: servant-lucid
|
||||
version: 0.4.1
|
||||
version: 0.4.4.7
|
||||
synopsis: Servant support for lucid
|
||||
-- description:
|
||||
homepage: http://haskell-servant.github.io/
|
||||
|
@ -15,6 +15,10 @@ category: Web
|
|||
build-type: Simple
|
||||
-- extra-source-files:
|
||||
cabal-version: >=1.10
|
||||
bug-reports: http://github.com/haskell-servant/servant/issues
|
||||
source-repository head
|
||||
type: git
|
||||
location: http://github.com/haskell-servant/servant.git
|
||||
|
||||
library
|
||||
exposed-modules: Servant.HTML.Lucid
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
Copyright (c) 2015, Alp Mestanogullari
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of Alp Mestanogullari nor the names of other
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,2 @@
|
|||
import Distribution.Simple
|
||||
main = defaultMain
|
|
@ -0,0 +1,17 @@
|
|||
{ mkDerivation, aeson, base, bytestring, http-types, QuickCheck
|
||||
, servant, servant-server, stdenv, transformers, wai, warp
|
||||
}:
|
||||
mkDerivation {
|
||||
pname = "servant-mock";
|
||||
version = "0.5";
|
||||
src = ./.;
|
||||
isLibrary = true;
|
||||
isExecutable = true;
|
||||
buildDepends = [
|
||||
aeson base bytestring http-types QuickCheck servant servant-server
|
||||
transformers wai warp
|
||||
];
|
||||
homepage = "http://github.com/haskell-servant/servant";
|
||||
description = "Derive a mock server for free from your servant API types";
|
||||
license = stdenv.lib.licenses.bsd3;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
import Data.Aeson
|
||||
import GHC.Generics
|
||||
import Network.Wai.Handler.Warp
|
||||
import Servant
|
||||
import Servant.Mock
|
||||
import Test.QuickCheck.Arbitrary
|
||||
|
||||
newtype User = User { username :: String }
|
||||
deriving (Eq, Show, Arbitrary, Generic)
|
||||
|
||||
instance ToJSON User
|
||||
|
||||
type API = "user" :> Get '[JSON] User
|
||||
|
||||
api :: Proxy API
|
||||
api = Proxy
|
||||
|
||||
main :: IO ()
|
||||
main = run 8080 (serve api $ mock api)
|
|
@ -0,0 +1,46 @@
|
|||
name: servant-mock
|
||||
version: 0.4.4.7
|
||||
synopsis: Derive a mock server for free from your servant API types
|
||||
description:
|
||||
Derive a mock server for free from your servant API types
|
||||
.
|
||||
See the @Servant.Mock@ module for the documentation and an example.
|
||||
homepage: http://github.com/haskell-servant/servant
|
||||
license: BSD3
|
||||
license-file: LICENSE
|
||||
author: Alp Mestanogullari
|
||||
maintainer: alpmestan@gmail.com
|
||||
copyright: 2015 Alp Mestanogullari
|
||||
category: Web
|
||||
build-type: Simple
|
||||
cabal-version: >=1.10
|
||||
|
||||
flag example
|
||||
description: Build the example too
|
||||
manual: True
|
||||
default: False
|
||||
|
||||
library
|
||||
exposed-modules:
|
||||
Servant.Mock
|
||||
build-depends:
|
||||
base >=4.7 && <5,
|
||||
bytestring >= 0.10 && <0.11,
|
||||
http-types >= 0.8 && <0.10,
|
||||
servant >= 0.4,
|
||||
servant-server >= 0.4,
|
||||
transformers >= 0.3 && <0.5,
|
||||
QuickCheck >= 2.8 && <2.9,
|
||||
wai >= 3.0 && <3.3
|
||||
hs-source-dirs: src
|
||||
default-language: Haskell2010
|
||||
|
||||
executable mock-app
|
||||
main-is: main.hs
|
||||
hs-source-dirs: example
|
||||
default-language: Haskell2010
|
||||
build-depends: aeson, base, servant-mock, servant-server, QuickCheck, warp
|
||||
if flag(example)
|
||||
buildable: True
|
||||
else
|
||||
buildable: False
|
|
@ -0,0 +1,18 @@
|
|||
let
|
||||
pkgs = import <nixpkgs> {};
|
||||
|
||||
haskellPackages = pkgs.haskellPackages.override {
|
||||
overrides = self: super: {
|
||||
servant = pkgs.haskell.lib.dontCheck (pkgs.haskell.lib.appendConfigureFlag (self.callPackage ../servant {}) "--ghc-options=-Werror");
|
||||
servant-client = pkgs.haskell.lib.dontCheck (pkgs.haskell.lib.appendConfigureFlag (self.callPackage ../servant-client {}) "--ghc-options=-Werror");
|
||||
servant-docs = pkgs.haskell.lib.dontCheck (pkgs.haskell.lib.appendConfigureFlag (self.callPackage ../servant-docs {}) "--ghc-options=-Werror");
|
||||
servant-js = pkgs.haskell.lib.dontCheck (pkgs.haskell.lib.appendConfigureFlag (self.callPackage ../servant-js {}) "--ghc-options=-Werror");
|
||||
servant-server = pkgs.haskell.lib.dontCheck (pkgs.haskell.lib.appendConfigureFlag (self.callPackage ../servant-server {}) "--ghc-options=-Werror");
|
||||
servant-examples = pkgs.haskell.lib.dontCheck (pkgs.haskell.lib.appendConfigureFlag (self.callPackage ../servant-examples {}) "--ghc-options=-Werror");
|
||||
servant-blaze = pkgs.haskell.lib.dontCheck (pkgs.haskell.lib.appendConfigureFlag (self.callPackage ../servant-blaze {}) "--ghc-options=-Werror");
|
||||
servant-lucid = pkgs.haskell.lib.dontCheck (pkgs.haskell.lib.appendConfigureFlag (self.callPackage ../servant-lucid {}) "--ghc-options=-Werror");
|
||||
servant-mock = pkgs.haskell.lib.appendConfigureFlag (self.callPackage ./. {}) "--ghc-options=-Werror";
|
||||
};
|
||||
};
|
||||
|
||||
in haskellPackages.servant-mock.env
|
|
@ -0,0 +1,178 @@
|
|||
{-# LANGUAGE CPP #-}
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE FlexibleInstances #-}
|
||||
{-# LANGUAGE ScopedTypeVariables #-}
|
||||
{-# LANGUAGE TypeFamilies #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||
-- |
|
||||
-- Module : Servant.Mock
|
||||
-- Copyright : 2015 Alp Mestanogullari
|
||||
-- License : BSD3
|
||||
--
|
||||
-- Maintainer : Alp Mestanogullari <alpmestan@gmail.com>
|
||||
-- Stability : experimental
|
||||
-- Portability : portable
|
||||
--
|
||||
-- Automatically derive a mock webserver that implements some API type,
|
||||
-- just from the said API type's definition.
|
||||
--
|
||||
-- Using this module couldn't be simpler. Given some API type, like:
|
||||
--
|
||||
-- > type API = "user" :> Get '[JSON] User
|
||||
--
|
||||
-- that describes your web application, all you have to do is define
|
||||
-- a 'Proxy' to it:
|
||||
--
|
||||
-- > myAPI :: Proxy API
|
||||
-- > myAPI = Proxy
|
||||
--
|
||||
-- and call 'mock', which has the following type:
|
||||
--
|
||||
-- @
|
||||
-- 'mock' :: 'HasMock' api => 'Proxy' api -> 'Server' api
|
||||
-- @
|
||||
--
|
||||
-- What this says is, given some API type @api@ that it knows it can
|
||||
-- "mock", 'mock' hands you an implementation of the API type. It does so
|
||||
-- by having each request handler generate a random value of the
|
||||
-- appropriate type (@User@ in our case). All you need for this to work is
|
||||
-- to provide 'Arbitrary' instances for the data types returned as response
|
||||
-- bodies, hence appearing next to 'Delete', 'Get', 'Patch', 'Post' and 'Put'.
|
||||
--
|
||||
-- To put this all to work and run the mock server, just call 'serve' on the
|
||||
-- result of 'mock' to get an 'Application' that you can then run with warp.
|
||||
--
|
||||
-- @
|
||||
-- main :: IO ()
|
||||
-- main = Network.Wai.Handler.Warp.run 8080 $
|
||||
-- 'serve' myAPI ('mock' myAPI)
|
||||
-- @
|
||||
module Servant.Mock ( HasMock(..) ) where
|
||||
|
||||
#if !MIN_VERSION_base(4,8,0)
|
||||
import Control.Applicative
|
||||
#endif
|
||||
import Control.Monad.IO.Class
|
||||
import Data.ByteString.Lazy.Char8 (pack)
|
||||
import Data.Proxy
|
||||
import GHC.TypeLits
|
||||
import Network.HTTP.Types.Status
|
||||
import Network.Wai
|
||||
import Servant
|
||||
import Servant.API.ContentTypes
|
||||
import Test.QuickCheck.Arbitrary (Arbitrary (..), vector)
|
||||
import Test.QuickCheck.Gen (Gen, generate)
|
||||
|
||||
-- | 'HasMock' defines an interpretation of API types
|
||||
-- than turns them into random-response-generating
|
||||
-- request handlers, hence providing an instance for
|
||||
-- all the combinators of the core /servant/ library.
|
||||
class HasServer api => HasMock api where
|
||||
-- | Calling this method creates request handlers of
|
||||
-- the right type to implement the API described by
|
||||
-- @api@ that just generate random response values of
|
||||
-- the right type. E.g:
|
||||
--
|
||||
-- @
|
||||
-- type API = "user" :> Get '[JSON] User
|
||||
-- :<|> "book" :> Get '[JSON] Book
|
||||
--
|
||||
-- api :: Proxy API
|
||||
-- api = Proxy
|
||||
--
|
||||
-- -- let's say we will start with the frontend,
|
||||
-- -- and hence need a placeholder server
|
||||
-- server :: Server API
|
||||
-- server = mock api
|
||||
-- @
|
||||
--
|
||||
-- What happens here is that @'Server' API@
|
||||
-- actually "means" 2 request handlers, of the following types:
|
||||
--
|
||||
-- @
|
||||
-- getUser :: EitherT ServantErr IO User
|
||||
-- getBook :: EitherT ServantErr IO Book
|
||||
-- @
|
||||
--
|
||||
-- So under the hood, 'mock' uses the 'IO' bit to generate
|
||||
-- random values of type 'User' and 'Book' every time these
|
||||
-- endpoints are requested.
|
||||
mock :: Proxy api -> Server api
|
||||
|
||||
instance (HasMock a, HasMock b) => HasMock (a :<|> b) where
|
||||
mock _ = mock (Proxy :: Proxy a) :<|> mock (Proxy :: Proxy b)
|
||||
|
||||
instance (KnownSymbol path, HasMock rest) => HasMock (path :> rest) where
|
||||
mock _ = mock (Proxy :: Proxy rest)
|
||||
|
||||
instance (KnownSymbol s, FromText a, HasMock rest) => HasMock (Capture s a :> rest) where
|
||||
mock _ = \_ -> mock (Proxy :: Proxy rest)
|
||||
|
||||
instance (AllCTUnrender ctypes a, HasMock rest) => HasMock (ReqBody ctypes a :> rest) where
|
||||
mock _ = \_ -> mock (Proxy :: Proxy rest)
|
||||
|
||||
instance (KnownSymbol s, FromText a, HasMock rest)
|
||||
=> HasMock (QueryParam s a :> rest) where
|
||||
mock _ = \_ -> mock (Proxy :: Proxy rest)
|
||||
|
||||
instance (KnownSymbol s, FromText a, HasMock rest)
|
||||
=> HasMock (QueryParams s a :> rest) where
|
||||
mock _ = \_ -> mock (Proxy :: Proxy rest)
|
||||
|
||||
instance (KnownSymbol s, HasMock rest) => HasMock (QueryFlag s :> rest) where
|
||||
mock _ = \_ -> mock (Proxy :: Proxy rest)
|
||||
|
||||
instance (KnownSymbol s, FromText a, HasMock rest)
|
||||
=> HasMock (MatrixParam s a :> rest) where
|
||||
mock _ = \_ -> mock (Proxy :: Proxy rest)
|
||||
|
||||
instance (KnownSymbol s, FromText a, HasMock rest)
|
||||
=> HasMock (MatrixParams s a :> rest) where
|
||||
mock _ = \_ -> mock (Proxy :: Proxy rest)
|
||||
|
||||
instance (KnownSymbol s, HasMock rest) => HasMock (MatrixFlag s :> rest) where
|
||||
mock _ = \_ -> mock (Proxy :: Proxy rest)
|
||||
|
||||
instance (KnownSymbol h, FromText a, HasMock rest) => HasMock (Header h a :> rest) where
|
||||
mock _ = \_ -> mock (Proxy :: Proxy rest)
|
||||
|
||||
instance (Arbitrary a, AllCTRender ctypes a) => HasMock (Delete ctypes a) where
|
||||
mock _ = mockArbitrary
|
||||
|
||||
instance (Arbitrary a, AllCTRender ctypes a) => HasMock (Get ctypes a) where
|
||||
mock _ = mockArbitrary
|
||||
|
||||
instance (Arbitrary a, AllCTRender ctypes a) => HasMock (Patch ctypes a) where
|
||||
mock _ = mockArbitrary
|
||||
|
||||
instance (Arbitrary a, AllCTRender ctypes a) => HasMock (Post ctypes a) where
|
||||
mock _ = mockArbitrary
|
||||
|
||||
instance (Arbitrary a, AllCTRender ctypes a) => HasMock (Put ctypes a) where
|
||||
mock _ = mockArbitrary
|
||||
|
||||
instance HasMock Raw where
|
||||
mock _ = \_ respond -> do
|
||||
bdy <- genBody
|
||||
respond $ responseLBS status200 [] bdy
|
||||
|
||||
where genBody = pack <$> generate (vector 100 :: Gen [Char])
|
||||
|
||||
mockArbitrary :: (MonadIO m, Arbitrary a) => m a
|
||||
mockArbitrary = liftIO (generate arbitrary)
|
||||
|
||||
-- utility instance
|
||||
instance (Arbitrary (HList ls), Arbitrary a)
|
||||
=> Arbitrary (Headers ls a) where
|
||||
arbitrary = Headers <$> arbitrary <*> arbitrary
|
||||
|
||||
instance Arbitrary (HList '[]) where
|
||||
arbitrary = pure HNil
|
||||
|
||||
instance (Arbitrary a, Arbitrary (HList hs))
|
||||
=> Arbitrary (HList (Header h a ': hs)) where
|
||||
arbitrary = HCons <$> fmap Header arbitrary <*> arbitrary
|
||||
|
||||
|
|
@ -1,3 +1,8 @@
|
|||
0.4.3
|
||||
-----
|
||||
|
||||
* Bump aeson upper-bound to < 0.11
|
||||
|
||||
0.4.1
|
||||
-----
|
||||
* Bump attoparsec upper bound to < 0.14
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
This library lets you *implement* an HTTP server with handlers for each endpoint of a servant API, handling most of the boilerplate for you.
|
||||
|
||||
## Getting started
|
||||
## Tutorial
|
||||
|
||||
We've written a [Getting Started](http://haskell-servant.github.io/getting-started/) guide that introduces the core types and features of servant. After this article, you should be able to write your first servant webservices, learning the rest from the haddocks' examples.
|
||||
We've written a [tutorial](http://haskell-servant.github.io/tutorial/) that introduces the core types and features of servant.
|
||||
|
||||
## Repositories and Haddocks
|
||||
|
||||
- The core [servant](http://github.com/haskell-servant) package - [docs](http://hackage.haskell.org/package/servant)
|
||||
- The core [servant](http://github.com/haskell-servant/servant/tree/master/servant) package - [docs](http://hackage.haskell.org/package/servant)
|
||||
- Implementing an HTTP server for a webservice API with [servant-server](http://github.com/haskell-servant/servant/tree/master/servant-server) - [docs](http://hackage.haskell.org/package/servant-server)
|
||||
- (Haskell) client-side function generation with [servant-client](http://github.com/haskell-servant/servant/tree/master/servant-client) - [docs](http://hackage.haskell.org/package/servant-client)
|
||||
- (Javascript) client-side function generation with [servant-jquery](http://github.com/haskell-servant/servant/tree/master/servant-jquery) - [docs](http://hackage.haskell.org/package/servant-jquery)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: servant-server
|
||||
version: 0.4.1
|
||||
version: 0.4.4.7
|
||||
synopsis: A family of combinators for defining webservices APIs and serving them
|
||||
description:
|
||||
A family of combinators for defining webservices APIs and serving them
|
||||
|
@ -25,9 +25,10 @@ tested-with: GHC >= 7.8
|
|||
extra-source-files:
|
||||
CHANGELOG.md
|
||||
README.md
|
||||
bug-reports: http://github.com/haskell-servant/servant/issues
|
||||
source-repository head
|
||||
type: git
|
||||
location: http://github.com/haskell-servant/servant-server.git
|
||||
location: http://github.com/haskell-servant/servant.git
|
||||
|
||||
|
||||
library
|
||||
|
@ -40,25 +41,26 @@ library
|
|||
Servant.Utils.StaticFiles
|
||||
build-depends:
|
||||
base >= 4.7 && < 5
|
||||
, aeson >= 0.7 && < 0.10
|
||||
, aeson >= 0.7 && < 0.12
|
||||
, attoparsec >= 0.12 && < 0.14
|
||||
, bytestring >= 0.10 && < 0.11
|
||||
, either >= 4.3 && < 4.5
|
||||
, http-types >= 0.8 && < 0.9
|
||||
, http-types >= 0.8 && < 0.10
|
||||
, network-uri >= 2.6 && < 2.7
|
||||
, mtl >= 2 && < 3
|
||||
, mmorph >= 1
|
||||
, safe >= 0.3 && < 0.4
|
||||
, servant == 0.4.*
|
||||
, split >= 0.2 && < 0.3
|
||||
, string-conversions >= 0.3 && < 0.4
|
||||
, string-conversions >= 0.3 && < 0.5
|
||||
, system-filepath >= 0.4 && < 0.5
|
||||
, filepath >= 1
|
||||
, text >= 1.2 && < 1.3
|
||||
, transformers >= 0.3 && < 0.5
|
||||
, wai >= 3.0 && < 3.1
|
||||
, wai >= 3.0 && < 3.3
|
||||
, wai-app-static >= 3.0 && < 3.2
|
||||
, warp >= 3.0 && < 3.1
|
||||
, warp >= 3.0 && < 3.3
|
||||
|
||||
hs-source-dirs: src
|
||||
default-language: Haskell2010
|
||||
ghc-options: -Wall
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
0.4.3
|
||||
-----
|
||||
* Add missing HasLink instance for Header (https://github.com/haskell-servant/servant/issues/128)
|
||||
|
||||
0.4.1
|
||||
-----
|
||||
* Allow whitespace after parsing JSON
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
name: servant
|
||||
version: 0.4.1
|
||||
version: 0.4.4.7
|
||||
synopsis: A family of combinators for defining webservices APIs
|
||||
description:
|
||||
A family of combinators for defining webservices APIs and serving them
|
||||
.
|
||||
You can learn about the basics in the <http://haskell-servant.github.io/tutorial tutorial>.
|
||||
.
|
||||
<https://github.com/haskell-servant/servant-server/blob/master/example/greet.hs Here>'s a runnable example, with comments, that defines a dummy API and
|
||||
implements a webserver that serves this API, using the <http://hackage.haskell.org/package/servant-server servant-server> package.
|
||||
.
|
||||
<https://github.com/haskell-servant/servant/blob/master/servant/CHANGELOG.md CHANGELOG>
|
||||
homepage: http://haskell-servant.github.io/
|
||||
Bug-reports: http://github.com/haskell-servant/servant/issues
|
||||
|
@ -46,16 +43,16 @@ library
|
|||
Servant.Common.Text
|
||||
Servant.Utils.Links
|
||||
build-depends:
|
||||
base >=4.7 && <5
|
||||
base >=4.7 && <4.9
|
||||
, aeson >= 0.7
|
||||
, attoparsec >= 0.12
|
||||
, bytestring == 0.10.*
|
||||
, bytestring-conversion == 0.3.*
|
||||
, case-insensitive >= 1.2
|
||||
, http-media >= 0.4 && < 0.7
|
||||
, http-types == 0.8.*
|
||||
, http-types >= 0.8 && < 0.10
|
||||
, text >= 1 && < 2
|
||||
, string-conversions >= 0.3 && < 0.4
|
||||
, string-conversions >= 0.3 && < 0.5
|
||||
, network-uri >= 2.6
|
||||
hs-source-dirs: src
|
||||
default-language: Haskell2010
|
||||
|
|
|
@ -166,7 +166,7 @@ instance ( AllMimeRender ctyps a, IsNonEmpty ctyps
|
|||
handleAcceptH _ (AcceptHeader accept) val = M.mapAcceptMedia lkup accept
|
||||
where pctyps = Proxy :: Proxy ctyps
|
||||
amrs = allMimeRender pctyps val
|
||||
lkup = fmap (\(a,b) -> (a, (cs $ show a, b))) amrs
|
||||
lkup = fmap (\(a,b) -> (a, (fromStrict $ M.renderHeader a, b))) amrs
|
||||
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
|
|
@ -339,6 +339,10 @@ instance (ToText v, HasLink sub)
|
|||
toLink (Proxy :: Proxy sub) $
|
||||
addSegment (escape . unpack $ toText v) l
|
||||
|
||||
instance HasLink sub => HasLink (Header sym a :> sub) where
|
||||
type MkLink (Header sym a :> sub) = MkLink sub
|
||||
toLink _ = toLink (Proxy :: Proxy sub)
|
||||
|
||||
-- Verb (terminal) instances
|
||||
instance HasLink (Get y r) where
|
||||
type MkLink (Get y r) = URI
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||
|
||||
module Servant.API.ContentTypesSpec where
|
||||
|
||||
#if !MIN_VERSION_base(4,8,0)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
servant
|
||||
servant-cassava
|
||||
servant-client
|
||||
servant-docs
|
||||
servant-jquery
|
||||
|
@ -6,3 +7,4 @@ servant-server
|
|||
servant-examples
|
||||
servant-blaze
|
||||
servant-lucid
|
||||
servant-mock
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
packages:
|
||||
- servant/
|
||||
- servant-blaze/
|
||||
- servant-client/
|
||||
- servant-docs/
|
||||
- servant-examples/
|
||||
- servant-jquery/
|
||||
- servant-lucid/
|
||||
- servant-mock/
|
||||
- servant-server/
|
||||
extra-deps:
|
||||
- engine-io-wai-1.0.2
|
||||
- attoparsec-0.13.0.1
|
||||
- aeson-0.10.0.0
|
||||
resolver: nightly-2015-07-24
|
Loading…
Reference in New Issue