packages feed

apiary 1.1.4 → 1.2.0

raw patch · 22 files changed

+624/−607 lines, 22 filesdep +vaultdep −conduitdep −wai-testdep ~waidep ~wai-extraPVP ok

version bump matches the API change (PVP)

Dependencies added: vault

Dependencies removed: conduit, wai-test

Dependency ranges changed: wai, wai-extra

API changes (from Hackage documentation)

- Control.Monad.Apiary.Filter: Action :: Doc
- Control.Monad.Apiary.Filter: DocAny :: Doc -> Doc
- Control.Monad.Apiary.Filter: DocDropNext :: Doc -> Doc
- Control.Monad.Apiary.Filter: DocFetch :: Text -> TypeRep -> (Maybe Html) -> Doc -> Doc
- Control.Monad.Apiary.Filter: DocGroup :: Text -> Doc -> Doc
- Control.Monad.Apiary.Filter: DocPath :: Text -> Doc -> Doc
- Control.Monad.Apiary.Filter: DocRest :: Text -> (Maybe Html) -> Doc -> Doc
- Control.Monad.Apiary.Filter: Document :: Text -> Doc -> Doc
- Control.Monad.Apiary.Filter: instance HasDesc Proxy
- Control.Monad.Apiary.Filter: instance HasDesc QueryKey
- Control.Monad.Apiary.Filter: instance HasDesc SProxy
- Data.Apiary.Dict: instance [overlap ok] Member k v ((k ':= v) : kvs)
- Data.Apiary.Dict: instance [overlap ok] Member k v kvs => Member k v ((k' ':= v') : kvs)
- Data.Apiary.Document.Html: instance Default DefaultDocumentConfig
- Data.Apiary.Extension: class MonadHas e m
- Data.Apiary.Method: instance Eq Method
- Data.Apiary.Method: instance Hashable Method
- Data.Apiary.Method: instance IsString Method
- Data.Apiary.Method: instance Ord Method
- Data.Apiary.Method: instance Read Method
- Data.Apiary.Method: instance Show Method
- Web.Apiary.Heroku: instance Default HerokuConfig
- Web.Apiary.Heroku: instance Extension Heroku
+ Control.Monad.Apiary.Action: adjustVault :: (a -> a) -> Key a -> ActionT exts prms m ()
+ Control.Monad.Apiary.Action: appendBuilder :: Monad m => Builder -> ActionT exts prms m ()
+ Control.Monad.Apiary.Action: appendBytes :: Monad m => ByteString -> ActionT exts prms m ()
+ Control.Monad.Apiary.Action: appendChar :: Monad m => Char -> ActionT exts prms m ()
+ Control.Monad.Apiary.Action: appendLazyBytes :: Monad m => ByteString -> ActionT exts prms m ()
+ Control.Monad.Apiary.Action: appendLazyText :: Monad m => Text -> ActionT exts prms m ()
+ Control.Monad.Apiary.Action: appendShowing :: (Monad m, Show a) => a -> ActionT exts prms m ()
+ Control.Monad.Apiary.Action: appendString :: Monad m => String -> ActionT exts prms m ()
+ Control.Monad.Apiary.Action: appendText :: Monad m => Text -> ActionT exts prms m ()
+ Control.Monad.Apiary.Action: deleteVault :: Key a -> ActionT exts prms m ()
+ Control.Monad.Apiary.Action: insertVault :: Key a -> a -> ActionT exts prms m ()
+ Control.Monad.Apiary.Action: lookupVault :: Key a -> ActionT exts prms m (Maybe a)
+ Control.Monad.Apiary.Action: modifyVault :: (Vault -> Vault) -> ActionT exts prms m ()
+ Control.Monad.Apiary.Filter: instance [overlap ok] HasDesc Proxy
+ Control.Monad.Apiary.Filter: instance [overlap ok] HasDesc QueryKey
+ Control.Monad.Apiary.Filter: instance [overlap ok] HasDesc SProxy
+ Data.Apiary.Dict: instance [overlap ok] (KnownSymbol k, Member k v kvs) => Member k v ((k' ':= v') : kvs)
+ Data.Apiary.Dict: instance [overlap ok] KnownSymbol k => Member k v ((k ':= v) : kvs)
+ Data.Apiary.Document.Html: instance [overlap ok] Default DefaultDocumentConfig
+ Data.Apiary.Extension: class Monad m => MonadExts es m | m -> es
+ Data.Apiary.Extension: extMiddleware' :: Extension e => e -> Middleware'
+ Data.Apiary.Extension: getExts :: MonadExts es m => m (Extensions es)
+ Data.Apiary.Extension: type Middleware' = forall exts. ActionT exts [] IO () -> ActionT exts [] IO ()
+ Data.Apiary.Method: instance [overlap ok] Eq Method
+ Data.Apiary.Method: instance [overlap ok] Hashable Method
+ Data.Apiary.Method: instance [overlap ok] IsString Method
+ Data.Apiary.Method: instance [overlap ok] Ord Method
+ Data.Apiary.Method: instance [overlap ok] Read Method
+ Data.Apiary.Method: instance [overlap ok] Show Method
+ Web.Apiary.Develop: file :: MonadIO m => FilePath -> Maybe FilePart -> ActionT exts prms m ()
+ Web.Apiary.Develop: file' :: MonadIO m => FilePath -> Maybe FilePart -> ActionT exts prms m ()
+ Web.Apiary.Heroku: instance [overlap ok] Default HerokuConfig
+ Web.Apiary.Heroku: instance [overlap ok] Extension Heroku
- Control.Monad.Apiary.Filter: function' :: (Monad actM, NotMember key prms) => (Doc -> Doc) -> (Request -> Maybe (proxy key, prm)) -> ApiaryT exts ((key := prm) : prms) actM m () -> ApiaryT exts prms actM m ()
+ Control.Monad.Apiary.Filter: function' :: (KnownSymbol key, Monad actM, NotMember key prms) => (Doc -> Doc) -> (Request -> Maybe (proxy key, prm)) -> ApiaryT exts ((key := prm) : prms) actM m () -> ApiaryT exts prms actM m ()
- Data.Apiary.Dict: insert :: NotMember k kvs => proxy k -> v -> Dict kvs -> Dict ((k := v) : kvs)
+ Data.Apiary.Dict: insert :: (KnownSymbol k, NotMember k kvs) => proxy k -> v -> Dict kvs -> Dict ((k := v) : kvs)
- Data.Apiary.Extension: class Extension a where extMiddleware _ = id
+ Data.Apiary.Extension: class Extension e where extMiddleware _ = id extMiddleware' _ = id
- Data.Apiary.Extension: extMiddleware :: Extension a => a -> Middleware
+ Data.Apiary.Extension: extMiddleware :: Extension e => e -> Middleware
- Data.Apiary.Extension: getExt :: MonadHas e m => proxy e -> m e
+ Data.Apiary.Extension: getExt :: (MonadExts es m, Has e es) => proxy e -> m e
- Data.Apiary.Param: strategy :: (Strategy w, NotMember k prms, MonadPlus m) => w a -> proxy' k -> [Maybe a] -> Dict prms -> m (Dict (SNext w k a prms))
+ Data.Apiary.Param: strategy :: (Strategy w, KnownSymbol k, NotMember k prms, MonadPlus m) => w a -> proxy' k -> [Maybe a] -> Dict prms -> m (Dict (SNext w k a prms))

Files

CHANGELOG.md view
@@ -1,3 +1,18 @@+# 1.2.0+* good bye wai-2.+* add Web.Apiary.Develop module for develop static file.+* *change* response body function behaviour(append to set).+* add append* functions.+* remove MonadHas class. add MonadExt class.+* add action vault for extension.+* change binary package to cereal package.++## apiary-websockets+* fix actionWithWebSockets don't exec action.++## apiary-session/apiary-clientsession/apiary-authenticate+* new session system.+ # 1.1.4 * enhance API documentation. * add MonadHas class.
apiary.cabal view
@@ -1,5 +1,5 @@ name:                apiary-version:             1.1.4+version:             1.2.0 synopsis:            Simple and type safe web framework that can be automatically generate API documentation. description:   Simple and type safe web framework that can be automatically generate API documentation.@@ -40,7 +40,7 @@   .     * Auto generate API documentation(example: <http://best-haskell.herokuapp.com/api/documentation>).   .-  more examples: <https://github.com/philopon/apiary/blob/v1.1.4/examples/>+  more examples: <https://github.com/philopon/apiary/blob/v1.2.0/examples/>   .   live demo: <http://best-haskell.herokuapp.com/> (source code: <https://github.com/philopon/best-haskell>) @@ -63,14 +63,10 @@                    , CHANGELOG.md cabal-version:       >=1.10 -flag wai3-  description: use wai-3.0-  default: True- library   exposed-modules:     Web.Apiary+                       Web.Apiary.Develop                        Web.Apiary.Heroku-                       Web.Apiary.Wai                         Control.Monad.Apiary                        Control.Monad.Apiary.Filter@@ -110,6 +106,7 @@                      , blaze-html           >=0.7   && <0.8                      , blaze-markup         >=0.6   && <0.7                      , case-insensitive     >=1.1   && <1.3+                     , vault                >=0.3   && <0.4                       , data-default-class   >=0.0   && <0.1                      , unordered-containers >=0.2   && <0.3@@ -119,15 +116,10 @@                      , unix-compat          >=0.4   && <0.5                      , http-date            >=0.0   && <0.1 -  if flag(wai3)-    build-depends:     wai                  >=3.0   && <3.1+                     , wai                  >=3.0   && <3.1                      , wai-extra            >=3.0   && <3.1-    cpp-options:       -DWAI3-  else-    build-depends:     wai                  >=2.1   && <2.2-                     , wai-extra            >=2.1   && <2.2-                     , conduit              >=1.1   && <1.2 +  default-extensions:  OverlappingInstances   hs-source-dirs:      src   ghc-options:         -O2 -Wall   ghc-prof-options:    -O2 -Wall -auto-all@@ -146,12 +138,8 @@                      , bytestring           >=0.10  && <0.11                      , http-types           >=0.8   && <0.9                      , HUnit                >=1.2   && <1.3-  if flag(wai3)-    build-depends:     wai                  >=3.0   && <3.1+                     , wai                  >=3.0   && <3.1                      , wai-extra            >=3.0   && <3.1-  else-    build-depends:     wai                  >=2.1   && <2.2-                     , wai-test             >=2.0   && <2.1    hs-source-dirs:      test   ghc-options:         -O2 -Wall -fno-warn-missing-signatures
src/Control/Monad/Apiary/Action.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE CPP #-}- module Control.Monad.Apiary.Action      ( ActionT     -- * stop action@@ -21,8 +19,13 @@     , text,  lazyText     , showing     , string, char+    , appendBuilder+    , appendBytes, appendLazyBytes+    , appendText, appendLazyText+    , appendShowing+    , appendString, appendChar     , file-    , devFile+    , file'      -- ** monolithic action     -- *** redirect@@ -43,19 +46,22 @@     , getReqBodyParams     , getReqBodyFiles     -- ** setter-    , file'+    , devFile     , devFile'     , stream     , rawResponse     , StreamingBody+    -- ** vault+    , lookupVault+    , modifyVault+    , insertVault+    , adjustVault+    , deleteVault     -- ** redirect     , redirectWith     ) where  import Control.Monad.Apiary.Action.Internal-+import Network.Wai import Data.Apiary.Document.Html -#ifdef WAI3-import Network.Wai-#endif
src/Control/Monad/Apiary/Action/Internal.hs view
@@ -1,54 +1,53 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE TupleSections #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE DataKinds #-}-{-# LANGUAGE CPP #-}+{-# LANGUAGE GADTs #-}  module Control.Monad.Apiary.Action.Internal where -import Language.Haskell.TH-import Language.Haskell.TH.Quote+import qualified Language.Haskell.TH as TH+import Language.Haskell.TH.Quote(QuasiQuoter(..)) -import System.PosixCompat.Files+import qualified System.PosixCompat.Files as Files -import Control.Applicative-import Control.Monad-import Control.Monad.Trans-import Control.Monad.Base-import Control.Monad.Reader-import Control.Monad.Catch+import Control.Applicative (Applicative(..), Alternative(..), (<$>))+import Control.Monad (MonadPlus(..), liftM)+import Control.Monad.Trans(MonadIO(..), MonadTrans(..))+import Control.Monad.Base(MonadBase(..), liftBaseDefault)+import Control.Monad.Reader(MonadReader(..), ReaderT)+import Control.Monad.Catch(MonadThrow(..), MonadCatch(..), MonadMask(..)) import Control.Monad.Trans.Control+    (MonadTransControl(..), MonadBaseControl(..)+    , ComposeSt+    , defaultLiftBaseWith, defaultRestoreM) -import Network.Mime hiding (Extension)-import Network.HTTP.Date-import Network.HTTP.Types as Http-import Network.Wai+import Network.Mime(defaultMimeLookup)+import Network.HTTP.Date(parseHTTPDate, epochTimeToHTTPDate, formatHTTPDate)+import qualified Network.HTTP.Types as HTTP+import qualified Network.Wai as Wai import qualified Network.Wai.Parse as P -import Data.Monoid hiding (All)-import Data.Apiary.Extension-import Data.Apiary.Dict-import Data.Apiary.Param-import Data.Apiary.Compat-import Data.Apiary.Document-import Data.Apiary.Document.Html-import Data.Default.Class+import Data.Monoid(Monoid(..), (<>))+import qualified Data.Apiary.Dict as Dict+import Data.Apiary.Param(Param, File(..))+import Data.Apiary.Compat(SProxy(..))+import Data.Apiary.Document(Documents)+import Data.Apiary.Document.Html(defaultDocumentToHtml, DefaultDocumentConfig)+import Data.Default.Class(Default(..)) -import Blaze.ByteString.Builder-import Text.Blaze.Html.Renderer.Utf8+import Blaze.ByteString.Builder(Builder)+import Text.Blaze.Html.Renderer.Utf8(renderHtmlBuilder) import qualified Blaze.ByteString.Builder as B import qualified Blaze.ByteString.Builder.Char.Utf8 as B import qualified Data.ByteString as S@@ -56,22 +55,18 @@ import qualified Data.ByteString.Lazy.Char8 as LC import qualified Data.Text as T import qualified Data.Text.Lazy as TL--#ifndef WAI3-import Data.Conduit-type StreamingBody = Source IO (Flush Builder)-#endif+import qualified Data.Vault.Lazy as V  data ApiaryConfig = ApiaryConfig     { -- | call when no handler matched.-      notFound            :: Application+      notFound            :: Wai.Application       -- | used unless call 'status' function.-    , defaultStatus       :: Status+    , defaultStatus       :: HTTP.Status       -- | initial headers.-    , defaultHeaders      :: ResponseHeaders+    , defaultHeaders      :: HTTP.ResponseHeaders     , defaultContentType  :: S.ByteString-    , failStatus          :: Status-    , failHeaders         :: ResponseHeaders+    , failStatus          :: HTTP.Status+    , failHeaders         :: HTTP.ResponseHeaders       -- | used by 'Control.Monad.Apiary.Filter.root' filter.     , rootPattern         :: [T.Text]     , mimeType            :: FilePath -> S.ByteString@@ -84,20 +79,16 @@     contentType "text/html"     builder . renderHtmlBuilder $ defaultDocumentToHtml conf d -defaultNotFound :: Application-#ifdef WAI3-defaultNotFound _ f = f      $ responseLBS status404 [("Content-Type", "text/plain")] "404 Page Notfound.\n"-#else-defaultNotFound _   = return $ responseLBS status404 [("Content-Type", "text/plain")] "404 Page Notfound.\n"-#endif+defaultNotFound :: Wai.Application+defaultNotFound _ f = f      $ Wai.responseLBS HTTP.status404 [("Content-Type", "text/plain")] "404 Page Notfound.\n"  instance Default ApiaryConfig where     def = ApiaryConfig          { notFound            = defaultNotFound-        , defaultStatus       = ok200+        , defaultStatus       = HTTP.ok200         , defaultHeaders      = []         , defaultContentType  = "text/plain"-        , failStatus          = internalServerError500+        , failStatus          = HTTP.internalServerError500         , failHeaders         = []         , rootPattern         = ["index.html", "index.htm"]         , mimeType            = defaultMimeLookup . T.pack@@ -106,35 +97,34 @@ --------------------------------------------------------------------------------  data ResponseBody-    = ResponseFile FilePath (Maybe FilePart)+    = ResponseFile FilePath (Maybe Wai.FilePart)     | ResponseBuilder Builder-    | ResponseStream StreamingBody-    | ResponseRaw (IO S.ByteString -> (S.ByteString -> IO ()) -> IO ()) Response-    | ResponseFunc (Status -> ResponseHeaders -> Response)+    | ResponseStream Wai.StreamingBody+    | ResponseRaw (IO S.ByteString -> (S.ByteString -> IO ()) -> IO ()) Wai.Response+    | ResponseFunc (HTTP.Status -> HTTP.ResponseHeaders -> Wai.Response)  instance Monoid ResponseBody where     mempty = ResponseBuilder mempty     ResponseBuilder a `mappend` ResponseBuilder b = ResponseBuilder $ a <> b     _ `mappend` b = b -toResponse :: ActionState -> Response+toResponse :: ActionState -> Wai.Response toResponse ActionState{..} = case actionResponse of-    ResponseFile  f p -> responseFile    actionStatus headers f p-    ResponseBuilder b -> responseBuilder actionStatus headers b-#ifdef WAI3-    ResponseStream  s -> responseStream  actionStatus headers s-#else-    ResponseStream  s -> responseSource  actionStatus headers s-#endif-    ResponseRaw   f r -> responseRaw f r+    ResponseFile  f p -> Wai.responseFile    actionStatus headers f p+    ResponseBuilder b -> Wai.responseBuilder actionStatus headers b+    ResponseStream  s -> Wai.responseStream  actionStatus headers s+    ResponseRaw   f r -> Wai.responseRaw f r     ResponseFunc    f -> f actionStatus headers   where     headers = ("Content-Type", actionContentType) : actionHeaders +--------------------------------------------------------------------------------+ data ActionState = ActionState     { actionResponse    :: ResponseBody-    , actionStatus      :: Status-    , actionHeaders     :: ResponseHeaders+    , actionStatus      :: HTTP.Status+    , actionHeaders     :: HTTP.ResponseHeaders+    , actionVault       :: V.Vault     , actionContentType :: S.ByteString     , actionReqBody     :: Maybe ([Param], [File])     , actionFetches     :: [T.Text]@@ -145,6 +135,7 @@     { actionResponse    = ResponseBuilder mempty     , actionStatus      = defaultStatus  conf     , actionHeaders     = defaultHeaders conf+    , actionVault       = V.empty     , actionContentType = defaultContentType conf     , actionReqBody     = Nothing     , actionFetches     = []@@ -152,10 +143,32 @@ {-# INLINE initialState #-}  --------------------------------------------------------------------------------+data Extensions (es :: [*]) where+    NoExtension  :: Extensions '[]+    AddExtension :: Extension e => (e :: *) -> Extensions es -> Extensions (e ': es) +type Middleware' = forall exts. ActionT exts '[] IO () -> ActionT exts '[] IO ()++class Extension e where+    extMiddleware :: e -> Wai.Middleware+    extMiddleware _ = id+    {-# INLINE extMiddleware #-}++    extMiddleware'  :: e -> Middleware'+    extMiddleware'  _ = id+    {-# INLINE extMiddleware' #-}++class Monad m => MonadExts es m | m -> es where+    getExts :: m (Extensions es)++instance Monad m => MonadExts es (ReaderT (Extensions es) m) where+    getExts = ask++--------------------------------------------------------------------------------+ data ActionEnv exts = ActionEnv     { actionConfig    :: ApiaryConfig-    , actionRequest   :: Request+    , actionRequest   :: Wai.Request     , actionDocuments :: Documents     , actionExts      :: Extensions exts     }@@ -163,10 +176,10 @@ data Action a      = Continue ActionState a     | Pass-    | Stop Response+    | Stop Wai.Response  newtype ActionT exts prms m a = ActionT { unActionT :: forall b. -    Dict prms+    Dict.Dict prms     -> ActionEnv exts     -> ActionState     -> (a -> ActionState -> m (Action b))@@ -174,14 +187,14 @@     } deriving (Functor)  runActionT :: Monad m => ActionT exts prms m a-           -> Dict prms -> ActionEnv exts -> ActionState+           -> Dict.Dict prms -> ActionEnv exts -> ActionState            -> m (Action a) runActionT m dict env st = unActionT m dict env st $ \a !st' ->     return (Continue st' a) {-# INLINE runActionT #-}  actionT :: Monad m -        => (Dict prms -> ActionEnv exts -> ActionState -> m (Action a))+        => (Dict.Dict prms -> ActionEnv exts -> ActionState -> m (Action a))         -> ActionT exts prms m a actionT f = ActionT $ \dict env !st cont -> f dict env st >>= \case     Pass            -> return Pass@@ -195,85 +208,17 @@ hoistActionT run m = actionT $ \d e s -> run (runActionT m d e s) {-# INLINE hoistActionT #-} -newtype ActionT' exts m a = ActionT' { unActionT' :: forall b. -    ActionEnv exts-    -> ActionState-    -> (a -> ActionState -> m (Action b))-    -> m (Action b)-    } deriving (Functor)--applyDict :: Dict prms -> ActionT exts prms m a -> ActionT' exts m a-applyDict d (ActionT m) = ActionT' (m d)+applyDict :: Dict.Dict prms -> ActionT exts prms m a -> ActionT exts '[] m a+applyDict d (ActionT m) = ActionT $ const (m d) {-# INLINE applyDict #-} -actionT' :: Monad m -         => (ActionEnv exts -> ActionState -> m (Action a))-         -> ActionT' exts m a-actionT' f = ActionT' $ \env !st cont -> f env st >>= \case-    Pass            -> return Pass-    Stop s          -> return $ Stop s-    Continue !st' a -> cont a st'-{-# INLINE actionT' #-}--runActionT' :: Monad m => ActionT' exts m a-            -> ActionEnv exts -> ActionState-            -> m (Action a)-runActionT' m env st = unActionT' m env st $ \a !st' -> return (Continue st' a)-{-# INLINE runActionT' #-}--hoistActionT' :: (Monad m, Monad n)-              => (forall b. m b -> n b) -> ActionT' exts m a -> ActionT' exts n a-hoistActionT' run m = actionT' $ \e s -> run (runActionT' m e s)-{-# INLINE hoistActionT' #-}--execActionT' :: ApiaryConfig -> Extensions exts -> Documents -> ActionT' exts IO () -> Application-#ifdef WAI3-execActionT' config exts doc m request send = -#else-execActionT' config exts doc m request = let send = return in-#endif-    runActionT' m (ActionEnv config request doc exts) (initialState config) >>= \case-#ifdef WAI3+execActionT :: ApiaryConfig -> Extensions exts -> Documents -> ActionT exts '[] IO () -> Wai.Application+execActionT config exts doc m request send = +    runActionT m Dict.empty (ActionEnv config request doc exts) (initialState config) >>= \case         Pass         -> notFound config request send-#else-        Pass         -> notFound config request-#endif         Stop s       -> send s         Continue r _ -> send $ toResponse r -instance Applicative (ActionT' exts m) where-    pure x = ActionT' $ \_ !st cont -> cont x st-    mf <*> ma = ActionT' $ \env st cont ->-        unActionT' mf env st  $ \f !st'  ->-        unActionT' ma env st' $ \a !st'' ->-        cont (f a) st''-    {-# INLINE pure #-}-    {-# INLINE (<*>) #-}--instance Monad m => Monad (ActionT' exts m) where-    return x = ActionT' $ \_ !st cont -> cont x st-    m >>= k  = ActionT' $ \env !st cont ->-        unActionT' m env st $ \a !st' ->-        unActionT' (k a) env st' cont-    fail s = ActionT' $ \(ActionEnv{actionConfig = c}) _ _ -> return $-        Stop (responseLBS (failStatus c) (failHeaders c) $ LC.pack s)-    {-# INLINE return #-}-    {-# INLINE (>>=) #-}--instance (Monad m, Functor m) => Alternative (ActionT' exts m) where-    empty = mzero-    (<|>) = mplus-    {-# INLINE empty #-}-    {-# INLINE (<|>) #-}--instance Monad m => MonadPlus (ActionT' exts m) where-    mzero = ActionT' $ \_ _ _ -> return Pass-    mplus m n = ActionT' $ \e !s cont -> unActionT' m e s cont >>= \case-        Continue !st a -> return $ Continue st a-        Stop stp       -> return $ Stop stp-        Pass           -> unActionT' n e s cont-    {-# INLINE mzero #-}-    {-# INLINE mplus #-} --------------------------------------------------------------------------------  instance Applicative (ActionT exts prms m) where@@ -289,7 +234,7 @@         unActionT m dict env st $ \a !st' ->         unActionT (k a) dict env st' cont     fail s = ActionT $ \_ (ActionEnv{actionConfig = c}) _ _ -> return $-        Stop (responseLBS (failStatus c) (failHeaders c) $ LC.pack s)+        Stop (Wai.responseLBS (failStatus c) (failHeaders c) $ LC.pack s)  instance MonadIO m => MonadIO (ActionT exts prms m) where     liftIO m = ActionT $ \_ _ !st cont ->@@ -353,26 +298,25 @@     ask     = lift ask     local f = hoistActionT $ local f -instance (Monad m, Has e exts) => MonadHas e (ActionT exts prms m) where-    getExt p = liftM (getExtension p . actionExts) getEnv+instance Monad m => MonadExts exts (ActionT exts prms m) where+    getExts = liftM actionExts getEnv  --------------------------------------------------------------------------------  getEnv :: Monad m => ActionT exts prms m (ActionEnv exts) getEnv = ActionT $ \_ e s c -> c e s--getRequest' :: Monad m => ActionT' exts m Request-getRequest' = ActionT' $ \e s c -> c (actionRequest e) s+{-# INLINE getEnv #-}  -- | get raw request. since 0.1.0.0.-getRequest :: Monad m => ActionT exts prms m Request+getRequest :: Monad m => ActionT exts prms m Wai.Request getRequest = liftM actionRequest getEnv  getConfig :: Monad m => ActionT exts prms m ApiaryConfig getConfig = liftM actionConfig getEnv -getParams :: Monad m => ActionT exts prms m (Dict prms)+getParams :: Monad m => ActionT exts prms m (Dict.Dict prms) getParams = ActionT $ \d _ s c -> c d s+{-# INLINE getParams #-}  -- | get parameter. since 1.0.0. --@@ -380,17 +324,17 @@ -- -- > param [key|foo|] ---param :: (Member k v prms, Monad m) => proxy k -> ActionT exts prms m v-param p = liftM (get p) getParams+param :: (Dict.Member k v prms, Monad m) => proxy k -> ActionT exts prms m v+param p = liftM (Dict.get p) getParams -paramsE :: [String] -> ExpQ+paramsE :: [String] -> TH.ExpQ paramsE ps = do-    ns <- mapM (\p -> (,) <$> newName "x" <*> pure p) ps-    let bs  = map (\(v, k) -> bindS (varP v) (prm k)) ns-        tpl = noBindS [| return $(tupE $ map (varE . fst) ns) |]-    doE $ bs ++ [tpl]+    ns <- mapM (\p -> (,) <$> TH.newName "x" <*> pure p) ps+    let bs  = map (\(v, k) -> TH.bindS (TH.varP v) (prm k)) ns+        tpl = TH.noBindS [| return $(TH.tupE $ map (TH.varE . fst) ns) |]+    TH.doE $ bs ++ [tpl]   where-    prm  n = [| param (SProxy :: SProxy $(litT $ strTyLit n)) |]+    prm  n = [| param (SProxy :: SProxy $(TH.litT $ TH.strTyLit n)) |]  -- | get parameters. since 1.0.0. --@@ -417,8 +361,8 @@   where     convFile (p, P.FileInfo{..}) = File p fileName fileContentType fileContent -getQueryParams :: Monad m => ActionT exts prms m Http.Query-getQueryParams = queryString <$> getRequest+getQueryParams :: Monad m => ActionT exts prms m HTTP.Query+getQueryParams = Wai.queryString <$> getRequest  -- | parse request body and return params. since 1.0.0. getReqBodyParams :: MonadIO m => ActionT exts prms m [Param]@@ -428,41 +372,35 @@ getReqBodyFiles :: MonadIO m => ActionT exts prms m [File] getReqBodyFiles = snd <$> getRequestBody ---------------------------------------------------------------------------------+-- | get all request headers. since 0.6.0.0.+getHeaders :: Monad m => ActionT exts prms m HTTP.RequestHeaders+getHeaders = Wai.requestHeaders `liftM` getRequest -modifyState' :: Monad m => (ActionState -> ActionState) -> ActionT' exts m ()-modifyState' f = ActionT' $ \_ s c -> c () (f s)+--------------------------------------------------------------------------------  modifyState :: Monad m => (ActionState -> ActionState) -> ActionT exts prms m () modifyState f = ActionT $ \_ _ s c -> c () (f s) -getState :: ActionT exts prms m ActionState-getState = ActionT $ \_ _ s c -> c s s- -- | set status code. since 0.1.0.0.-status :: Monad m => Status -> ActionT exts prms m ()+status :: Monad m => HTTP.Status -> ActionT exts prms m () status st = modifyState (\s -> s { actionStatus = st } ) --- | get all request headers. since 0.6.0.0.-getHeaders :: Monad m => ActionT exts prms m RequestHeaders-getHeaders = requestHeaders `liftM` getRequest- -- | modify response header. since 0.1.0.0. -- -- Don't set Content-Type using this function. Use @contentType@.-modifyHeader :: Monad m => (ResponseHeaders -> ResponseHeaders) -> ActionT exts prms m ()+modifyHeader :: Monad m => (HTTP.ResponseHeaders -> HTTP.ResponseHeaders) -> ActionT exts prms m () modifyHeader f = modifyState (\s -> s {actionHeaders = f $ actionHeaders s } )  -- | add response header. since 0.1.0.0. -- -- Don't set Content-Type using this function. Use @contentType@.-addHeader :: Monad m => HeaderName -> S.ByteString -> ActionT exts prms m ()+addHeader :: Monad m => HTTP.HeaderName -> S.ByteString -> ActionT exts prms m () addHeader h v = modifyHeader ((h,v):)  -- | set response headers. since 0.1.0.0. -- -- Don't set Content-Type using this function. Use @contentType@.-setHeaders :: Monad m => ResponseHeaders -> ActionT exts prms m ()+setHeaders :: Monad m => HTTP.ResponseHeaders -> ActionT exts prms m () setHeaders hs = modifyHeader (const hs)  type ContentType = S.ByteString@@ -473,6 +411,29 @@ contentType :: Monad m => ContentType -> ActionT exts prms m () contentType c = modifyState (\s -> s { actionContentType = c } ) +getState :: ActionT exts prms m ActionState+getState = ActionT $ \_ _ s c -> c s s++-- | lookup extensional state. since v1.2.0.+lookupVault :: V.Key a -> ActionT exts prms m (Maybe a)+lookupVault k = V.lookup k . actionVault <$> getState++-- | modify extensional state. since v1.2.0.+modifyVault :: (V.Vault -> V.Vault) -> ActionT exts prms m ()+modifyVault f = ActionT $ \_ _ s c -> c () (s {actionVault = f $ actionVault s})++-- | insert extensional state. since v1.2.0.+insertVault :: V.Key a -> a -> ActionT exts prms m ()+insertVault k i = modifyVault $ V.insert k i++-- | adjust extensional state. since v1.2.0.+adjustVault :: (a -> a) -> V.Key a -> ActionT exts prms m ()+adjustVault f k = modifyVault $ V.adjust f k++-- | delete extensional state. since v1.2.0.+deleteVault :: V.Key a -> ActionT exts prms m ()+deleteVault k = modifyVault $ V.delete k+ --------------------------------------------------------------------------------  -- | stop handler and send current state. since 0.3.3.0.@@ -480,7 +441,7 @@ stop = ActionT $ \_ _ s _ -> return $ Stop (toResponse s)  -- | stop with response. since 0.4.2.0.-stopWith :: Monad m => Response -> ActionT exts prms m a+stopWith :: Monad m => Wai.Response -> ActionT exts prms m a stopWith a = ActionT $ \_ _ _ _ -> return $ Stop a  -- | redirect handler@@ -489,7 +450,7 @@ -- -- rename from redirect in 0.6.2.0. redirectWith :: Monad m-             => Status+             => HTTP.Status              -> S.ByteString -- ^ Location redirect to              -> ActionT exts prms m () redirectWith st url = do@@ -507,7 +468,7 @@  -- | redirect with 301 Moved Permanently. since 0.3.3.0. redirectPermanently :: Monad m => S.ByteString -> ActionT exts prms m ()-redirectPermanently = redirectWith movedPermanently301+redirectPermanently = redirectWith HTTP.movedPermanently301  -- | redirect with: --@@ -517,10 +478,10 @@ -- since 0.6.2.0. redirect :: Monad m => S.ByteString -> ActionT exts prms m () redirect to = do-    v <- httpVersion <$> getRequest-    if v == http11-        then redirectWith seeOther303 to-        else redirectWith status302   to+    v <- Wai.httpVersion <$> getRequest+    if v == HTTP.http11+        then redirectWith HTTP.seeOther303 to+        else redirectWith HTTP.status302   to  -- | redirect with: --@@ -530,10 +491,10 @@ -- since 0.3.3.0. redirectTemporary :: Monad m => S.ByteString -> ActionT exts prms m () redirectTemporary to = do-    v <- httpVersion <$> getRequest-    if v == http11-        then redirectWith temporaryRedirect307 to-        else redirectWith status302            to+    v <- Wai.httpVersion <$> getRequest+    if v == HTTP.http11+        then redirectWith HTTP.temporaryRedirect307 to+        else redirectWith HTTP.status302            to  -- | set raw response constructor. since 0.10. --@@ -544,7 +505,7 @@ -- producer = response (\s h -> responseProducer s h) -- @ ---rawResponse :: Monad m => (Status -> ResponseHeaders -> Response) -> ActionT exts prms m ()+rawResponse :: Monad m => (HTTP.Status -> HTTP.ResponseHeaders -> Wai.Response) -> ActionT exts prms m () rawResponse f = modifyState (\s -> s { actionResponse = ResponseFunc f } )  -- | reset response body to no response. since v0.15.2.@@ -552,74 +513,104 @@ reset = modifyState (\s -> s { actionResponse = mempty } )  -- | set response body file content, without set Content-Type. since 0.1.0.0.-file' :: MonadIO m => FilePath -> Maybe FilePart -> ActionT exts prms m ()+file' :: MonadIO m => FilePath -> Maybe Wai.FilePart -> ActionT exts prms m () file' f p = modifyState (\s -> s { actionResponse = ResponseFile f p } )  -- | set response body file content and detect Content-Type by extension. since 0.1.0.0. -- -- file modification check since 0.17.2.-file :: MonadIO m => FilePath -> Maybe FilePart -> ActionT exts prms m ()+file :: MonadIO m => FilePath -> Maybe Wai.FilePart -> ActionT exts prms m () file f p = do     mbims <- (>>= parseHTTPDate) . lookup "If-Modified-Since" <$> getHeaders-    e <- liftIO $ fileExist f+    e <- liftIO $ Files.fileExist f     t <- if e-         then liftIO $ Just . epochTimeToHTTPDate . modificationTime <$> getFileStatus f+         then liftIO $ Just . epochTimeToHTTPDate . Files.modificationTime <$> Files.getFileStatus f          else return Nothing     case mbims of-        Just ims | maybe False (ims >=) t -> reset >> status status304 >> stop+        Just ims | maybe False (ims >=) t -> reset >> status HTTP.status304 >> stop         _ -> do             mime <- mimeType <$> getConfig             contentType (mime f)             maybe (return ()) (addHeader "Last-Modified" . formatHTTPDate) t             file' f p -{-# WARNING devFile' "use file' in production." #-} devFile' :: MonadIO m => FilePath -> ActionT exts prms m ()-devFile' f = liftIO (fileExist f) >>= \e ->+devFile' f = liftIO (Files.fileExist f) >>= \e ->     if e     then liftIO (L.readFile f) >>= lazyBytes     else mzero  -- | send file contents as lazy bytestring response. since v1.1.4.-{-# WARNING devFile "use file in production." #-} devFile :: MonadIO m => FilePath -> ActionT exts prms m () devFile f = do     mime <- mimeType <$> getConfig     contentType (mime f)     devFile' f --- | append response body from builder. since 0.1.0.0.+-- | set response body from builder. since 0.1.0.0. builder :: Monad m => Builder -> ActionT exts prms m ()-builder b = modifyState (\s -> s { actionResponse = actionResponse s <> ResponseBuilder b } )+builder b = modifyState (\s -> s { actionResponse = ResponseBuilder b } ) --- | append response body from strict bytestring. since 0.15.2.+-- | set response body from strict bytestring. since 0.15.2. bytes :: Monad m => S.ByteString -> ActionT exts prms m () bytes = builder . B.fromByteString --- | append response body from lazy bytestring. since 0.15.2.+-- | set response body from lazy bytestring. since 0.15.2. lazyBytes :: Monad m => L.ByteString -> ActionT exts prms m () lazyBytes = builder . B.fromLazyByteString --- | append response body from strict text. encoding UTF-8. since 0.15.2.+-- | set response body from strict text. encoding UTF-8. since 0.15.2. text :: Monad m => T.Text -> ActionT exts prms m () text = builder . B.fromText --- | append response body from lazy text. encoding UTF-8. since 0.15.2.+-- | set response body from lazy text. encoding UTF-8. since 0.15.2. lazyText :: Monad m => TL.Text -> ActionT exts prms m () lazyText = builder . B.fromLazyText --- | append response body from show. encoding UTF-8. since 0.15.2.+-- | set response body from show. encoding UTF-8. since 0.15.2. showing :: (Monad m, Show a) => a -> ActionT exts prms m () showing = builder . B.fromShow --- | append response body from string. encoding UTF-8. since 0.15.2.+-- | set response body from string. encoding UTF-8. since 0.15.2. string :: Monad m => String -> ActionT exts prms m () string = builder . B.fromString --- | append response body from char. encoding UTF-8. since 0.15.2.+-- | set response body from char. encoding UTF-8. since 0.15.2. char :: Monad m => Char -> ActionT exts prms m () char = builder . B.fromChar +-- | append response body from builder. since 1.2.0.+appendBuilder :: Monad m => Builder -> ActionT exts prms m ()+appendBuilder b = modifyState (\s -> s { actionResponse = actionResponse s <> ResponseBuilder b } )++-- | append response body from strict bytestring. since 1.2.0.+appendBytes :: Monad m => S.ByteString -> ActionT exts prms m ()+appendBytes = appendBuilder . B.fromByteString++-- | append response body from lazy bytestring. since 1.2.0.+appendLazyBytes :: Monad m => L.ByteString -> ActionT exts prms m ()+appendLazyBytes = appendBuilder . B.fromLazyByteString++-- | append response body from strict text. encoding UTF-8. since 1.2.0.+appendText :: Monad m => T.Text -> ActionT exts prms m ()+appendText = appendBuilder . B.fromText++-- | append response body from lazy text. encoding UTF-8. since 1.2.0.+appendLazyText :: Monad m => TL.Text -> ActionT exts prms m ()+appendLazyText = appendBuilder . B.fromLazyText++-- | append response body from show. encoding UTF-8. since 1.2.0.+appendShowing :: (Monad m, Show a) => a -> ActionT exts prms m ()+appendShowing = appendBuilder . B.fromShow++-- | append response body from string. encoding UTF-8. since 1.2.0.+appendString :: Monad m => String -> ActionT exts prms m ()+appendString = appendBuilder . B.fromString++-- | append response body from char. encoding UTF-8. since 1.2.0.+appendChar :: Monad m => Char -> ActionT exts prms m ()+appendChar = appendBuilder . B.fromChar+ -- | set response body source. since 0.9.0.0.-stream :: Monad m => StreamingBody -> ActionT exts prms m ()+stream :: Monad m => Wai.StreamingBody -> ActionT exts prms m () stream str = modifyState (\s -> s { actionResponse = ResponseStream str })
src/Control/Monad/Apiary/Filter.hs view
@@ -1,16 +1,10 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE DataKinds #-}  module Control.Monad.Apiary.Filter (     -- * http method@@ -48,30 +42,38 @@     , Doc(..)     ) where -import Network.Wai as Wai+import qualified Network.Wai as Wai import Network.Wai.Parse (parseContentType, parseHttpAccept)-import qualified Network.HTTP.Types as Http+import qualified Network.HTTP.Types as HTTP -import Control.Applicative-import Control.Monad-import Control.Monad.Trans+import Control.Applicative((<$>))+import Control.Monad(mzero)+import Control.Monad.Trans(MonadIO)  import Control.Monad.Apiary.Action.Internal+    (getParams, getQueryParams, getRequestBody, getRequest, ContentType, contentType) import Control.Monad.Apiary.Filter.Internal-import Control.Monad.Apiary.Filter.Internal.Capture.TH-import Control.Monad.Apiary.Internal+    ( function, function', function_+    , Doc(DocMethod, DocPrecondition, DocRoot, DocQuery, DocAccept))+import Control.Monad.Apiary.Filter.Internal.Capture.TH(capture)+import Control.Monad.Apiary.Internal(ApiaryT, focus', focus, PathElem(RootPath)) import qualified Control.Monad.Apiary.Filter.Internal.Capture as Capture -import Text.Blaze.Html+import Text.Blaze.Html(Html, toHtml) import qualified Data.ByteString.Char8 as SC-import qualified Data.Text          as T-import qualified Data.CaseInsensitive as CI-import Data.Monoid-import Data.Apiary.Compat-import Data.Apiary.Dict+import qualified Data.Text             as T+import qualified Data.CaseInsensitive  as CI+import Data.Monoid((<>))+import Data.Apiary.Compat(KnownSymbol, Symbol, symbolVal, Proxy(..), SProxy(..))+import Data.Apiary.Dict(NotMember, Elem((:=)))+import qualified Data.Apiary.Dict as Dict  import Data.Apiary.Param-import Data.Apiary.Method+    ( ReqParam, StrategyRep(..), QueryRep(NoValue)+    , Strategy(..), reqParamRep, reqParams+    , pFirst, pOne, pOption, pOptional, pMany, pSome+    )+import Data.Apiary.Method(Method)  -- | filter by HTTP method. since 0.1.0.0. --@@ -84,23 +86,23 @@  -- | filter by ssl accessed. since 0.1.0.0. ssl :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()-ssl = function_ (DocPrecondition "SSL required") isSecure+ssl = function_ (DocPrecondition "SSL required") Wai.isSecure  -- | http version filter. since 0.5.0.0.-httpVersion :: Monad actM => Http.HttpVersion -> Html -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()+httpVersion :: Monad actM => HTTP.HttpVersion -> Html -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () httpVersion v h = function_ (DocPrecondition h) $ (v ==) . Wai.httpVersion  -- | http/0.9 only accepted fiter. since 0.5.0.0. http09 :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()-http09 = Control.Monad.Apiary.Filter.httpVersion Http.http09 "HTTP/0.9 only"+http09 = Control.Monad.Apiary.Filter.httpVersion HTTP.http09 "HTTP/0.9 only"  -- | http/1.0 only accepted fiter. since 0.5.0.0. http10 :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()-http10 = Control.Monad.Apiary.Filter.httpVersion Http.http10 "HTTP/1.0 only"+http10 = Control.Monad.Apiary.Filter.httpVersion HTTP.http10 "HTTP/1.0 only"  -- | http/1.1 only accepted fiter. since 0.5.0.0. http11 :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()-http11 = Control.Monad.Apiary.Filter.httpVersion Http.http11 "HTTP/1.1 only"+http11 = Control.Monad.Apiary.Filter.httpVersion HTTP.http11 "HTTP/1.1 only"  -- | filter by 'Control.Monad.Apiary.Action.rootPattern' of 'Control.Monad.Apiary.Action.ApiaryConfig'. root :: (Monad m, Monad actM) => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()@@ -209,7 +211,7 @@     qs      <- getQueryParams     (ps,fs) <- getRequestBody     let n = maybe False id . fmap (maybe True id) . lookup (SC.pack $ symbolVal k) $ reqParams (Proxy :: Proxy Bool) qs ps fs-    insert k n <$> getParams+    Dict.insert k n <$> getParams  -------------------------------------------------------------------------------- @@ -217,21 +219,21 @@ header :: (KnownSymbol k, Monad actM, NotMember k prms)        => proxy k -> ApiaryT exts (k := SC.ByteString ': prms) actM m () -> ApiaryT exts prms actM m () header k = focus' (DocPrecondition $ "has header: " <> toHtml (symbolVal k)) Nothing id $ do-    n <- maybe mzero return . lookup (CI.mk . SC.pack $ symbolVal k) . requestHeaders =<< getRequest-    insert k n <$> getParams+    n <- maybe mzero return . lookup (CI.mk . SC.pack $ symbolVal k) . Wai.requestHeaders =<< getRequest+    Dict.insert k n <$> getParams  -- | check whether to exists specified valued header or not. since 0.6.0.0. eqHeader :: (KnownSymbol k, Monad actM)          => proxy k -> SC.ByteString -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () eqHeader k v = focus' (DocPrecondition $ "header: " <> toHtml (symbolVal k) <> " = " <> toHtml (show v)) Nothing id $ do-    v' <- maybe mzero return . lookup (CI.mk . SC.pack $ symbolVal k) . requestHeaders =<< getRequest+    v' <- maybe mzero return . lookup (CI.mk . SC.pack $ symbolVal k) . Wai.requestHeaders =<< getRequest     if v == v' then getParams else mzero   -- | require Accept header and set response Content-Type. since 0.16.0. accept :: Monad actM => ContentType -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () accept ect = focus (DocAccept ect) $-    (lookup "Accept" . requestHeaders <$> getRequest) >>= \case+    (lookup "Accept" . Wai.requestHeaders <$> getRequest) >>= \case         Nothing -> mzero         Just ac ->              let ex@(et, _) = parseContentType ect
src/Control/Monad/Apiary/Filter/Internal.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-}@@ -7,29 +9,31 @@     , Doc(..)     ) where -import Network.Wai+import qualified Network.Wai as Wai -import Control.Monad-import Control.Monad.Apiary.Internal-import Control.Monad.Apiary.Action+import Control.Monad(mzero)+import Control.Monad.Apiary.Internal(ApiaryT, focus)+import Control.Monad.Apiary.Action(getParams, getRequest) -import Data.Apiary.Dict-import Data.Apiary.Document.Internal+import Data.Apiary.Compat(KnownSymbol)+import Data.Apiary.Dict(Dict, NotMember, Elem((:=)))+import qualified Data.Apiary.Dict as Dict+import Data.Apiary.Document.Internal(Doc(..))  -- | low level filter function. function :: Monad actM => (Doc -> Doc)-         -> (Dict prms -> Request -> Maybe (Dict prms'))+         -> (Dict prms -> Wai.Request -> Maybe (Dict prms'))          -> ApiaryT exts prms' actM m () -> ApiaryT exts prms actM m () function d f = focus d $ getParams >>= \p -> getRequest >>= \r -> case f p r of     Nothing -> mzero     Just c' -> return c'  -- | filter and append argument.-function' :: (Monad actM, NotMember key prms) => (Doc -> Doc) -> (Request -> Maybe (proxy key, prm))+function' :: (KnownSymbol key, Monad actM, NotMember key prms) => (Doc -> Doc) -> (Wai.Request -> Maybe (proxy key, prm))           -> ApiaryT exts (key := prm ': prms) actM m () -> ApiaryT exts prms actM m ()-function' d f = function d $ \c r -> f r >>= \(k, p) -> return $ insert k p c+function' d f = function d $ \c r -> f r >>= \(k, p) -> return $ Dict.insert k p c  -- | filter only(not modify arguments).-function_ :: Monad actM => (Doc -> Doc) -> (Request -> Bool) +function_ :: Monad actM => (Doc -> Doc) -> (Wai.Request -> Bool)            -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () function_ d f = function d $ \c r -> if f r then Just c else Nothing
src/Control/Monad/Apiary/Filter/Internal/Capture.hs view
@@ -1,31 +1,29 @@-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE DataKinds #-}  module Control.Monad.Apiary.Filter.Internal.Capture where -import Control.Applicative-import Control.Monad+import Control.Applicative((<$>), (<$))+import Control.Monad(liftM, mzero) import Control.Monad.Apiary.Action.Internal+    (getParams, actionFetches, getState, modifyState) import Control.Monad.Apiary.Internal+    (ApiaryT, focus', PathElem(Exact, FetchPath, RestPath, EndPath)) import Control.Monad.Apiary.Filter.Internal+    (Doc(DocPath, DocFetch, DocAny, DocRest)) -import Data.Apiary.Compat-import Data.Apiary.Param-import Data.Apiary.Dict+import Data.Apiary.Compat(KnownSymbol, symbolVal, Proxy(..))+import Data.Apiary.Param(Path, pathRep, readPathAs)+import Data.Apiary.Dict(Elem((:=)))+import qualified Data.Apiary.Dict as Dict  import qualified Data.Text as T-import Text.Blaze.Html+import Text.Blaze.Html(Html)  -- | check first path and drill down. since 0.11.0. path :: Monad actM => T.Text -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()@@ -36,18 +34,18 @@ endPath = focus' id Nothing (EndPath:) getParams  -- | get first path and drill down. since 0.11.0.-fetch' :: (NotMember k prms, KnownSymbol k, Path p, Monad actM) => proxy k -> proxy' p -> Maybe Html+fetch' :: (Dict.NotMember k prms, KnownSymbol k, Path p, Monad actM) => proxy k -> proxy' p -> Maybe Html        -> ApiaryT exts (k := p ': prms) actM m () -> ApiaryT exts prms actM m () fetch' k p h = focus' (DocFetch (T.pack $ symbolVal k) (pathRep p) h) Nothing (FetchPath:) $ liftM actionFetches getState >>= \case     []   -> mzero     f:fs -> case readPathAs p f of         Just r  -> do             modifyState (\s -> s {actionFetches = fs})-            insert k r <$> getParams+            Dict.insert k r <$> getParams         Nothing -> mzero  -fetch :: forall proxy k p exts prms actM m. (NotMember k prms, KnownSymbol k, Path p, Monad actM)+fetch :: forall proxy k p exts prms actM m. (Dict.NotMember k prms, KnownSymbol k, Path p, Monad actM)       => proxy (k := p) -> Maybe Html       -> ApiaryT exts (k := p ': prms) actM m () -> ApiaryT exts prms actM m () fetch _ h = fetch' k p h@@ -58,8 +56,8 @@ anyPath :: (Monad m, Monad actM) => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () anyPath = focus' DocAny Nothing (RestPath:) getParams -restPath :: (NotMember k prms, KnownSymbol k, Monad m, Monad actM)+restPath :: (Dict.NotMember k prms, KnownSymbol k, Monad m, Monad actM)          => proxy k -> Maybe Html -> ApiaryT exts (k := [T.Text] ': prms) actM m () -> ApiaryT exts prms actM m () restPath k h = focus' (DocRest (T.pack $ symbolVal k) h) Nothing (RestPath:) $ getParams >>= \l -> liftM actionFetches getState >>= \case-    [] -> return $ insert k [] l-    fs -> insert k fs l <$ modifyState (\s -> s {actionFetches = []})+    [] -> return $ Dict.insert k [] l+    fs -> Dict.insert k fs l <$ modifyState (\s -> s {actionFetches = []})
src/Control/Monad/Apiary/Filter/Internal/Capture/TH.hs view
@@ -1,22 +1,22 @@-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE DataKinds #-} -module Control.Monad.Apiary.Filter.Internal.Capture.TH where+module Control.Monad.Apiary.Filter.Internal.Capture.TH(capture) where -import Control.Arrow-import Control.Applicative+import Control.Arrow(first)+import Control.Applicative((<$>)) -import Language.Haskell.TH-import Language.Haskell.TH.Quote+import qualified Language.Haskell.TH as TH+import Language.Haskell.TH.Quote(QuasiQuoter(..))  import qualified Control.Monad.Apiary.Filter.Internal.Capture as Capture  import qualified Data.Text as T-import Data.String-import Data.List-import Data.Apiary.Compat+import Data.String(IsString(..))+import Data.List(isInfixOf)+import Data.Apiary.Compat(Proxy(..), SProxy(..))  preCap :: String -> [String] preCap ""  = []@@ -27,39 +27,37 @@ splitPath :: String -> [String] splitPath = map T.unpack . T.splitOn "/" . T.pack ---            S h  -> [|Just $(stringE h)|]---            N n  -> [|Just $(varE n)|]-description :: String -> Q (String, ExpQ)+description :: String -> TH.Q (String, TH.ExpQ) description s = case break (`elem` "([") s of     (t, []) -> return (t, [|Nothing|])     (t, st) -> case break (`elem` ")]") st of         (_:'$':b, ")") -> do-            reportWarning "DEPRECATED () description. use []."-            v <- lookupValueName b-            maybe (fail $ b ++ " not found.") (\n -> return (t, [|Just $(varE n)|])) v+            TH.reportWarning "DEPRECATED () description. use []."+            v <- TH.lookupValueName b+            maybe (fail $ b ++ " not found.") (\n -> return (t, [|Just $(TH.varE n)|])) v         (_:b,     ")") -> do-            reportWarning "DEPRECATED () description. use []."-            return (t, [|Just $(stringE b)|])-        (_:'$':b, "]") -> lookupValueName b >>=-            maybe (fail $ b ++ " not found.") (\n -> return (t, [|Just $(varE n)|]))-        (_:b,     "]") -> return (t, [|Just $(stringE b)|])+            TH.reportWarning "DEPRECATED () description. use []."+            return (t, [|Just $(TH.stringE b)|])+        (_:'$':b, "]") -> TH.lookupValueName b >>=+            maybe (fail $ b ++ " not found.") (\n -> return (t, [|Just $(TH.varE n)|]))+        (_:b,     "]") -> return (t, [|Just $(TH.stringE b)|])         (_, _)         -> fail "capture: syntax error."  -mkCap :: [String] -> ExpQ+mkCap :: [String] -> TH.ExpQ mkCap [] = [|Capture.endPath|] mkCap (('*':'*':[]):as) = [|Capture.anyPath . $(mkCap as) |] mkCap (('*':'*':tS):as) = do     (k, d) <- description tS-    [|Capture.restPath (SProxy :: SProxy $(litT $ strTyLit k)) $d . $(mkCap as) |]+    [|Capture.restPath (SProxy :: SProxy $(TH.litT $ TH.strTyLit k)) $d . $(mkCap as) |] mkCap (str:as)     | "::" `isInfixOf` fst (break (`elem` "([") str) = do         (key, d) <- first T.pack <$> description str         let v = T.unpack . T.strip . fst $ T.breakOn    "::" key             t = T.unpack . T.strip . snd $ T.breakOnEnd "::" key-        ty <- lookupTypeName t >>= maybe (fail $ t ++ " not found.") return-        [|(Capture.fetch' (SProxy :: SProxy $(litT $ strTyLit v)) (Proxy :: Proxy $(conT ty)) $d) . $(mkCap as)|]+        ty <- TH.lookupTypeName t >>= maybe (fail $ t ++ " not found.") return+        [|(Capture.fetch' (SProxy :: SProxy $(TH.litT $ TH.strTyLit v)) (Proxy :: Proxy $(TH.conT ty)) $d) . $(mkCap as)|] -    | otherwise = [|(Capture.path (fromString $(stringE str))) . $(mkCap as) |]+    | otherwise = [|(Capture.path (fromString $(TH.stringE str))) . $(mkCap as) |]  -- | capture QuasiQuoter. since 0.1.0.0. --
src/Control/Monad/Apiary/Internal.hs view
@@ -1,40 +1,39 @@-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE ImpredicativeTypes #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE OverloadedStrings #-}--{-# LANGUAGE DataKinds #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ImpredicativeTypes #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}  module Control.Monad.Apiary.Internal where -import Network.Wai+import qualified Network.Wai as Wai -import Control.Applicative-import Control.Monad-import Control.Monad.Trans+import Control.Applicative(Applicative(..), (<$>))+import Control.Monad(liftM, MonadPlus(..))+import Control.Monad.Trans(MonadIO(liftIO), MonadTrans(lift)) import Control.Monad.Trans.Control-import Control.Monad.Base+    ( MonadTransControl(..), MonadBaseControl(..)+    , ComposeSt, defaultLiftBaseWith, defaultRestoreM+    )+import Control.Monad.Base(MonadBase(..)) import Control.Monad.Apiary.Action.Internal+    (ActionT, ApiaryConfig, getRequest+    , modifyState, actionFetches, Extensions(NoExtension)+    , execActionT, hoistActionT, applyDict, rootPattern+    ) -import Data.List import qualified Data.Apiary.Dict as D-import Data.Apiary.Extension-import Data.Apiary.Extension.Internal-import Data.Apiary.Document.Internal-import Data.Monoid hiding (All)-import Text.Blaze.Html+import Data.Apiary.Method(Method, renderMethod)+import Data.Apiary.Extension ( Has, MonadExts(..), getExt, noExtension )+import Data.Apiary.Extension.Internal(Initializer(..), allMiddleware, allMiddleware')+import Data.Apiary.Document.Internal(Doc(..), docsToDocuments)+import Data.Monoid(Monoid(..), (<>))++import Data.List(foldl')+import Text.Blaze.Html(Html) import qualified Data.Text as T import qualified Data.ByteString as S-import Data.Apiary.Method import qualified Data.HashMap.Strict as H  data Router exts actM = Router@@ -44,6 +43,8 @@     , pathMethod :: PathMethod exts actM     } +type ActionT' exts actM a = ActionT exts '[] actM a+ data PathMethod exts actM = PathMethod     { methodMap :: H.HashMap S.ByteString (ActionT' exts actM ())     , anyMethod :: Maybe (ActionT' exts actM ())@@ -100,7 +101,7 @@ data ApiaryWriter exts actM = ApiaryWriter     { writerRouter :: Router exts actM -> Router exts actM     , writerDoc    :: [Doc] -> [Doc]-    , writerMw     :: Middleware+    , writerMw     :: Wai.Middleware     }  instance Monoid (ApiaryWriter exts actM) where@@ -121,18 +122,18 @@ apiaryT f = ApiaryT $ \rdr cont -> f rdr >>= \(a, w) -> cont a w  routerToAction :: Monad actM => Router exts actM -> ActionT' exts actM ()-routerToAction router = getRequest' >>= go+routerToAction router = getRequest >>= go   where-    go req = loop id router (pathInfo req)+    go req = loop id router (Wai.pathInfo req)       where-        method = requestMethod req+        method = Wai.requestMethod req          pmAction nxt (PathMethod mm am) =             let a = maybe nxt id am             in maybe a (`mplus` a) $ H.lookup method mm          loop fch (Router _ _ anp pm) [] = do-            modifyState' (\s -> s { actionFetches = fch [] } )+            modifyState (\s -> s { actionFetches = fch [] } )             pmAction (maybe mzero (pmAction mzero) anp) pm           loop fch (Router c mbcp anp _) (p:ps) = case mbcp of@@ -140,7 +141,7 @@             Just cp -> cld $ loop (fch . (p:)) cp ps `mplus` ana           where             ana = do-                modifyState' (\s -> s {actionFetches = fch $ p:ps} ) +                modifyState (\s -> s {actionFetches = fch $ p:ps} )                  maybe mzero (pmAction mzero) anp             cld nxt = case H.lookup p c of                 Nothing -> nxt@@ -149,7 +150,7 @@ -- | run Apiary monad. runApiaryTWith :: (Monad actM, Monad m)                => (forall b. actM b -> IO b)-               -> (Application -> m a)+               -> (Wai.Application -> m a)                -> Initializer m '[] exts                -> ApiaryConfig                -> ApiaryT exts '[] actM m ()@@ -159,11 +160,12 @@     let doc = docsToDocuments $ writerDoc wtr []         rtr = writerRouter wtr emptyRouter         mw  = allMiddleware exts . writerMw wtr-        app = mw $ execActionT' conf exts doc (hoistActionT' runAct $ routerToAction rtr)+        mw' = allMiddleware' exts+        app = mw $ execActionT conf exts doc (mw' $ hoistActionT runAct $ routerToAction rtr)     run $! app  runApiaryWith :: Monad m-              => (Application -> m a)+              => (Wai.Application -> m a)               -> Initializer m '[] exts               -> ApiaryConfig               -> ApiaryT exts '[] IO m ()@@ -171,7 +173,7 @@ runApiaryWith = runApiaryTWith id  runApiary :: Monad m-          => (Application -> m a)+          => (Wai.Application -> m a)           -> ApiaryConfig           -> ApiaryT '[] '[] IO m ()           -> m a@@ -220,9 +222,9 @@     liftBaseWith = defaultLiftBaseWith StMApiary'     restoreM     = defaultRestoreM   unStMApiary' -instance (Has e exts, Monad actM) => MonadHas e (ApiaryT exts prms actM m) where-    getExt p = getExtension p . envExts <$> getApiaryEnv-    {-# INLINE getExt #-}+instance Monad actM => MonadExts exts (ApiaryT exts prms actM m) where+    getExts = envExts <$> getApiaryEnv+    {-# INLINE getExts #-}  -------------------------------------------------------------------------------- @@ -275,7 +277,7 @@         id  -- | add middleware.-middleware :: Monad actM => Middleware -> ApiaryT exts prms actM m ()+middleware :: Monad actM => Wai.Middleware -> ApiaryT exts prms actM m () middleware mw = addRoute (ApiaryWriter id id mw)  --------------------------------------------------------------------------------
src/Data/Apiary/Compat.hs view
@@ -1,11 +1,11 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE Rank2Types #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE PolyKinds #-}+{-# LANGUAGE CPP #-}  -- | compatibility module for ghc-7.8 & ghc-7.6. module Data.Apiary.Compat@@ -33,9 +33,10 @@  symbolVal :: forall n proxy. KnownSymbol n => proxy n -> String symbolVal _ = fromSing (sing :: Sing n)+{-# INLINE symbolVal #-} -data Proxy a = Proxy+data Proxy (a :: k) = Proxy #endif --- | Symbol Proxy for ghc-7.6.+-- | Symbol Proxy for ghc-7.6 Template Haskell. data SProxy (a :: Symbol) = SProxy
src/Data/Apiary/Dict.hs view
@@ -1,18 +1,14 @@-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE OverlappingInstances #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE CPP #-}  -- | type sefe dictionaly. module Data.Apiary.Dict@@ -29,33 +25,35 @@     , Members     ) where -import Data.Apiary.Compat+import Data.Apiary.Compat(KnownSymbol, Symbol, symbolVal, SProxy(..)) -import Language.Haskell.TH-import Language.Haskell.TH.Quote-import GHC.Exts+import qualified Language.Haskell.TH as TH+import Language.Haskell.TH.Quote(QuasiQuoter(..)) +import qualified Data.HashMap.Strict as H+import qualified Data.Text as T++import GHC.Exts(Any, Constraint)+import Unsafe.Coerce+ -- | (kind) Dict element. data Elem = forall a. Symbol := a -data Dict (ks :: [Elem]) where-    Empty :: Dict '[]-    Insert :: proxy (k :: Symbol) -> v -> Dict ks -> Dict (k := v ': ks)-+newtype Dict (ks :: [Elem]) = Dict (H.HashMap T.Text Any)  class Member (k :: Symbol) (v :: *) (kvs :: [Elem]) | k kvs -> v where      -- | get value of key.     ---    -- > ghci> get (SProxy :: SProxy "bar") $ insert (SProxy :: SProxy "bar") (0.5 :: Double) $ insert (SProxy :: SProxy "foo") (12 :: Int) empty+    -- > ghci> get (Proxy :: Proxy "bar") $ insert (Proxy :: Proxy "bar") (0.5 :: Double) $ insert (Proxy :: Proxy "foo") (12 :: Int) empty     -- > 0.5     ---    -- > ghci> get (SProxy :: SProxy "foo") $ insert (SProxy :: SProxy "bar") (0.5 :: Double) $ insert (SProxy :: SProxy "foo") (12 :: Int) empty+    -- > ghci> get (Proxy :: Proxy "foo") $ insert (Proxy :: Proxy "bar") (0.5 :: Double) $ insert (Proxy :: Proxy "foo") (12 :: Int) empty     -- > 12     --     -- ghc raise compile error when key is not exists.     ---    -- > ghci> get (SProxy :: SProxy "baz") $ insert (SProxy :: SProxy "bar") (0.5 :: Double) $ insert (SProxy :: SProxy "foo") (12 :: Int) empty+    -- > ghci> get (Proxy :: Proxy "baz") $ insert (Proxy :: Proxy "bar") (0.5 :: Double) $ insert (Proxy :: Proxy "foo") (12 :: Int) empty     -- > <interactive>:15:1:     -- >     No instance for (Member "baz" a0 '[]) arising from a use of ‘it’     -- >     In the first argument of ‘print’, namely ‘it’@@ -63,12 +61,15 @@      get :: proxy k -> Dict kvs -> v -instance Member k v (k := v ': kvs) where-    get _ (Insert _ v _) = v+getImpl :: KnownSymbol k => proxy k -> Dict any -> b+getImpl p (Dict d) = maybe (error "Dict: no value.") unsafeCoerce $ H.lookup (T.pack $ symbolVal p) d -instance Member k v kvs => Member k v (k' := v' ': kvs) where-    get p (Insert _ _ d) = get p d+instance KnownSymbol k => Member k v (k := v ': kvs) where+    get = getImpl +instance (KnownSymbol k, Member k v kvs) => Member k v (k' := v' ': kvs) where+    get = getImpl+ -- | type family version Member for NotMember constraint. #if __GLASGOW_HASKELL__ && __GLASGOW_HASKELL__ >= 708 type family Member' (k::Symbol) (kvs :: [Elem]) :: Bool where@@ -92,42 +93,42 @@  -- | empty Dict. empty :: Dict '[]-empty = Empty+empty = Dict H.empty  -- | insert element. -- --- > ghci> :t insert (SProxy :: SProxy "foo") (12 :: Int) empty--- > insert (SProxy :: SProxy "foo") (12 :: Int) empty+-- > ghci> :t insert (Proxy :: Proxy "foo") (12 :: Int) empty+-- > insert (Proxy :: Proxy "foo") (12 :: Int) empty -- >   :: Dict '["foo" ':= Int] -- --- > ghci> :t insert (SProxy :: SProxy "bar") (0.5 :: Double) $ insert (SProxy :: SProxy "foo") (12 :: Int) empty--- > insert (SProxy :: SProxy "bar") (0.5 :: Double) $ insert (SProxy :: SProxy "foo") (12 :: Int) empty+-- > ghci> :t insert (Proxy :: Proxy "bar") (0.5 :: Double) $ insert (Proxy :: Proxy "foo") (12 :: Int) empty+-- > insert (Proxy :: Proxy "bar") (0.5 :: Double) $ insert (Proxy :: Proxy "foo") (12 :: Int) empty -- >   :: Dict '["bar" ':= Double, "foo" ':= Int] -- -- ghc raise compile error when insert duplicated key(> ghc-7.8 only). ----- > ghci> :t insert (SProxy :: SProxy "foo") (0.5 :: Double) $ insert (SProxy :: SProxy "foo") (12 :: Int) empty+-- > ghci> :t insert (Proxy :: Proxy "foo") (0.5 :: Double) $ insert (Proxy :: Proxy "foo") (12 :: Int) empty -- >  -- > <interactive>:1:1: -- >     Couldn't match type ‘'True’ with ‘'False’ -- >     Expected type: 'False -- >       Actual type: Member' "foo" '["foo" ':= Int]--- >     In the expression: insert (SProxy :: SProxy "foo") (0.5 :: Double)+-- >     In the expression: insert (Proxy :: Proxy "foo") (0.5 :: Double) -- >     In the expression:--- >       insert (SProxy :: SProxy "foo") (0.5 :: Double)--- >       $ insert (SProxy :: SProxy "foo") (12 :: Int) empty+-- >       insert (Proxy :: Proxy "foo") (0.5 :: Double)+-- >       $ insert (Proxy :: Proxy "foo") (12 :: Int) empty -insert :: NotMember k kvs => proxy k -> v -> Dict kvs -> Dict (k := v ': kvs)-insert = Insert+insert :: (KnownSymbol k, NotMember k kvs) => proxy k -> v -> Dict kvs -> Dict (k := v ': kvs)+insert p v (Dict d) = Dict (H.insert (T.pack $ symbolVal p) (unsafeCoerce v) d)  -- | construct string literal proxy. ----- prop> [key|foo|] == (SProxy :: SProxy "foo")+-- prop> [key|foo|] == (Proxy :: Proxy "foo") -- key :: QuasiQuoter key = QuasiQuoter-    { quoteExp  = \s -> [| SProxy :: SProxy $(litT $ strTyLit s) |]+    { quoteExp  = \s -> [| SProxy :: SProxy $(TH.litT $ TH.strTyLit s) |]     , quotePat  = error "key qq only exp or type."-    , quoteType = \s -> [t| SProxy $(litT $ strTyLit s) |]+    , quoteType = \s -> [t| SProxy $(TH.litT $ TH.strTyLit s) |]     , quoteDec  = error "key qq only exp or type."     }
src/Data/Apiary/Document/Html.hs view
@@ -1,6 +1,6 @@+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE OverloadedStrings #-}  module Data.Apiary.Document.Html     ( defaultDocumentToHtml@@ -10,17 +10,20 @@     , rpHtml     ) where -import Language.Haskell.TH-import Language.Haskell.TH.Syntax(addDependentFile)+import qualified Language.Haskell.TH as TH+import qualified Language.Haskell.TH.Syntax as TH (addDependentFile) -import Data.Monoid hiding (Any)-import Data.Default.Class+import Data.Monoid(Monoid(..), (<>))+import Data.Default.Class(Default(..)) -import Data.Apiary.Param-import Data.Apiary.Method+import Data.Apiary.Param(QueryRep(Strict, Nullable, Check, NoValue), strategyInfo)+import Data.Apiary.Method(renderMethod) import Data.Apiary.Document+    ( Route(Path, Fetch, Rest, Any, End), Documents(..)+    , QueryDoc(..), MethodDoc(..), PathDoc(..)+    ) -import Text.Blaze.Html+import Text.Blaze.Html(Html, toHtml, (!), preEscapedToHtml, toValue) import Text.Blaze.Internal(attribute) import qualified Data.Text as T import qualified Data.Text.Encoding as T@@ -78,8 +81,30 @@     def = DefaultDocumentConfig "API documentation" Nothing True Nothing  defaultDocumentToHtml :: DefaultDocumentConfig -> Documents -> Html-defaultDocumentToHtml DefaultDocumentConfig{..} docs =-    H.docTypeHtml $ H.head headH <> H.body body <> footer+defaultDocumentToHtml DefaultDocumentConfig{..} docs = H.docTypeHtml $ do+    H.head $ do+        H.title (toHtml documentTitle)+        if documentUseCDN then cdns else embeds+        $(TH.runIO (readFile "static/jquery.cookie-1.4.1.min.js") >>= \c -> [|H.script $ preEscapedToHtml (c::String)|])+        -- , H.script "" ! A.src "/static/api-documentation.js"+        -- , H.link ! A.rel "stylesheet" ! A.href "/static/api-documentation.css"+        $(TH.addDependentFile "static/api-documentation.min.js"  >> TH.runIO (readFile "static/api-documentation.min.js")   >>= \c -> [|H.script $ preEscapedToHtml (c::String)|])+        $(TH.addDependentFile "static/api-documentation.min.css" >> TH.runIO (readFile "static/api-documentation.min.css")  >>= \c -> [|H.style  $ preEscapedToHtml (c::String)|])+        maybe mempty analytics documentGoogleAnalytics++    H.body $ do+        H.div ! A.class_ "container" $ do+            H.div ! A.class_ "page-header" $ H.h1 (toHtml documentTitle)+            maybe mempty (H.div ! A.class_ "description") documentDescription+            H.div ! A.id "no-group" $ do+                mcMap (pathH "") (noGroup docs)+                mcMap groupH     (groups docs)++    H.footer $ do+        ("This API documentation generated by " :: Html)+        H.a ! A.href "https://github.com/philopon/apiary" $ "apiary"+        (" web framework." :: Html)+   where     css u = H.link ! A.rel "stylesheet" ! A.href u     js  u = H.script ! A.src u $ mempty@@ -88,14 +113,13 @@      mcMap f = mconcat . map f -    cdns = mconcat-        [ css "http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"-        , js  "http://code.jquery.com/jquery-2.1.1.min.js"-        , js  "http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"-        ]+    cdns = do+        css "http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"+        js  "http://code.jquery.com/jquery-2.1.1.min.js"+        js  "http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"      embeds = $( do-        let embed f p = runIO (readFile p) >>= \c -> [|$(varE f) $ preEscapedToHtml (c :: String)|]+        let embed f p = TH.runIO (readFile p) >>= \c -> [|$(TH.varE f) $ preEscapedToHtml (c :: String)|]         [| mconcat              [ $(embed 'H.style  "static/bootstrap.min.css")             , $(embed 'H.script "static/jquery-2.1.1.min.js")@@ -103,91 +127,66 @@             ]          |]) -    headH = mconcat-        [ H.title (toHtml documentTitle)-        , if documentUseCDN then cdns else embeds-        , $(runIO (readFile "static/jquery.cookie-1.4.1.min.js") >>= \c -> [|H.script $ preEscapedToHtml (c::String)|])-        , $(addDependentFile "static/api-documentation.min.js"  >> runIO (readFile "static/api-documentation.min.js")   >>= \c -> [|H.script $ preEscapedToHtml (c::String)|])-        , $(addDependentFile "static/api-documentation.min.css" >> runIO (readFile "static/api-documentation.min.css")  >>= \c -> [|H.style  $ preEscapedToHtml (c::String)|])-        , maybe mempty analytics documentGoogleAnalytics-        ]--    htmlQR (Strict   r) = toHtml (show r)-    htmlQR (Nullable r) = H.span (toHtml (show r) <> "?") ! A.title (toValue (show r) <> "(nullable)")-    htmlQR  Check       = "check"-    htmlQR  NoValue     = "-"--    query (QueryDoc p s q t) = H.tr . mconcat $-        [ H.td (toHtml p)-        , H.td (toHtml $ strategyInfo s)-        , H.td (htmlQR q)-        , H.td $ maybe noDescription id t-        ]+    groupH (g, p) = H.div ! A.id (toValue $ T.append "group-" g) $ do+        H.h2 $ toHtml g+        mcMap (pathH g) p -    queriesH [] = mempty-    queriesH qs =-        H.div $-        H.table ! A.class_ "query-parameters table table-condensed" $ mconcat-        [ H.caption "Query parameters"-        , H.tr $ mconcat [ H.th ! A.class_ "col-sm-1 col-md-1" $ "name"-                         , H.th ! A.class_ "col-sm-1 col-md-1" $ "num"-                         , H.th ! A.class_ "col-sm-1 col-md-1" $ "type"-                         , H.th "description"-                         ]-        , mcMap query qs-        ]+    pathH grp (PathDoc r ms) = do+        let (idnt, route, rdoc) = routeToHtml r+        H.div ! A.class_ "panel panel-default" $ do+            H.div ! A.class_ "panel-heading clearfix"+                  ! dataToggle "collapse"+                  ! dataTarget (toValue $ T.concat ["[id='collapse-", grp, "-", idnt, "']"]) $ do+                H.h3  ! A.class_ "panel-title pull-left" $ route+                H.div ! A.class_ "methods" $+                    mcMap ( (\m -> H.div ! A.class_ "pull-right" $ toHtml (T.decodeUtf8 m))+                          . renderMethod . fst) (reverse ms) -    preconds [] = mempty-    preconds p  =-        H.div ! A.class_ "well well-sm precondition" $ mconcat-            [ H.p "Preconditions:"-            , H.ul $ mcMap (\h -> H.li h) p-            ]+            H.div ! A.id (toValue $ T.concat ["collapse-", grp, "-", idnt])+                  ! A.class_ "panel-collapse collapse" $ do+                rdoc+                H.div ! A.class_ "panel-body" $ mcMap method ms -    method (m, ms) = H.div ! A.class_ "method" $ mconcat-        [ H.h4 . toHtml $ T.decodeUtf8 $ renderMethod m-        , mcMap action ms-        ]+    method (m, ms) = H.div ! A.class_ "method" $ do+        H.h4 . toHtml $ T.decodeUtf8 $ renderMethod m+        mcMap action ms -    action (MethodDoc qs pc a d) = H.div ! A.class_ "action col-sm-offset-1 col-md-offset-1" $ mconcat-        [ preconds $ maybe pc (\ac -> H.span ("Accept: " <> H.span (toHtml $ T.decodeUtf8 ac)) ! A.class_ "precondition-accept" : pc) a-        , H.div (H.p $ toHtml d)-        , queriesH qs-        ]+    action (MethodDoc qs pc a d) =+        H.div ! A.class_ "action col-sm-offset-1 col-md-offset-1" $ do+            preconds $+                maybe pc +                (\ac -> H.span ("Accept: " <> H.span (toHtml $ T.decodeUtf8 ac))+                                          ! A.class_ "precondition-accept" : pc) a+            H.div (H.p $ toHtml d)+            queriesH qs -    pathH grp (PathDoc r ms) =-        let (idnt, route, rdoc) = routeToHtml r-        in H.div ! A.class_ "panel panel-default" $ mconcat-            [ H.div ! A.class_ "panel-heading clearfix"-                ! dataToggle "collapse" ! dataTarget (toValue $ T.concat ["[id='collapse-", grp, "-", idnt, "']"]) $ mconcat-                [ H.h3 ! A.class_ "panel-title pull-left" $ route-                , H.div ! A.class_ "methods" $-                    mcMap ((\m -> H.div ! A.class_ "pull-right" $ toHtml (T.decodeUtf8 m)) . renderMethod . fst) (reverse ms)-                ]-            , H.div ! A.id (toValue $ T.concat ["collapse-", grp, "-", idnt]) ! A.class_ "panel-collapse collapse" $-                rdoc <> (H.div ! A.class_ "panel-body" $ mcMap method ms)-            ]+    preconds [] = mempty+    preconds p  = H.div ! A.class_ "well well-sm precondition" $ do+            H.p "Preconditions:"+            H.ul $ mcMap (\h -> H.li h) p -    groupH (g, p) =-        let gs = mcMap (pathH g) p-        in H.div ! A.id (toValue $ T.append "group-" g) $ mconcat [H.h2 $ toHtml g, gs]+    queriesH [] = mempty+    queriesH qs = H.div $ do+        H.table ! A.class_ "query-parameters table table-condensed" $ do+            H.caption "Query parameters"+            H.tr $ do+                H.th ! A.class_ "col-sm-1 col-md-1" $ "name"+                H.th ! A.class_ "col-sm-1 col-md-1" $ "num"+                H.th ! A.class_ "col-sm-1 col-md-1" $ "type"+                H.th "description"+            mcMap query qs -    doc (Documents n g) =-        let ng = mcMap (pathH "") n-            gs = mcMap groupH g-        in (H.div ! A.id "no-group") ng <> gs+    query (QueryDoc p s q t) = H.tr $ do+        H.td (toHtml p)+        H.td (toHtml $ strategyInfo s)+        H.td (htmlQR q)+        H.td $ maybe noDescription id t -    body  = H.div ! A.class_ "container" $ mconcat-        [ H.div ! A.class_ "page-header" $ H.h1 (toHtml documentTitle)-        , maybe mempty (H.div ! A.class_ "description") documentDescription-        , doc docs-        ]+    htmlQR (Strict   r) = toHtml (show r)+    htmlQR (Nullable r) = H.span (toHtml (show r) <> "?") ! A.title (toValue (show r) <> "(nullable)")+    htmlQR  Check       = "check"+    htmlQR  NoValue     = "-" -    footer = H.footer $ mconcat-        [ "This API documentation generated by "-        , H.a ! A.href "https://github.com/philopon/apiary" $ "apiary"-        , " web framework."-        ]  -- | construct Html as route parameter. since 0.13.0. rpHtml :: Html -> Html
src/Data/Apiary/Document/Internal.hs view
@@ -1,23 +1,20 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE LambdaCase #-} {-# LANGUAGE TupleSections #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE LambdaCase #-}  module Data.Apiary.Document.Internal where -import Control.Applicative+import Control.Applicative((<$>)) -import Data.Typeable-import Data.Maybe-import Data.List-import Data.Function+import Data.Typeable(TypeRep)+import Data.Maybe(mapMaybe)+import Data.List(groupBy)+import Data.Function(on) -import Data.Apiary.Param-import Data.Apiary.Method+import Data.Apiary.Param(StrategyRep, QueryRep)+import Data.Apiary.Method(Method) -import Text.Blaze.Html+import Text.Blaze.Html(Html) import qualified Data.Text as T import qualified Data.ByteString as S 
src/Data/Apiary/Extension.hs view
@@ -1,12 +1,11 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE Rank2Types #-}-{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}  module Data.Apiary.Extension     ( Has(getExtension)-    , MonadHas(..)+    , MonadExts(..), getExt+    , Middleware'     , Extension(..)     , Extensions     , noExtension@@ -20,10 +19,13 @@     , (+>)     ) where -import Data.Apiary.Extension.Internal+import Control.Monad(liftM)+import Data.Apiary.Extension.Internal(Has, getExtension, Initializer(Initializer))+import Control.Monad.Apiary.Action.Internal+    (MonadExts(getExts), Extension(..), Extensions(AddExtension), Middleware') -class MonadHas e m where-    getExt :: proxy e -> m e+getExt :: (MonadExts es m, Has e es) => proxy e -> m e+getExt p = getExtension p `liftM` getExts  type Initializer' m a = forall i. Initializer m i (a ': i) 
src/Data/Apiary/Extension/Internal.hs view
@@ -1,21 +1,21 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE OverlappingInstances #-}+{-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE Rank2Types #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-} {-# LANGUAGE CPP #-}  module Data.Apiary.Extension.Internal where -import Network.Wai+#if __GLASGOW_HASKELL__ >= 708 import qualified Control.Category as Cat--data Extensions (es :: [*]) where-    NoExtension  :: Extensions '[]-    AddExtension :: Extension e => (e :: *) -> Extensions es -> Extensions (e ': es)+#endif+import qualified Network.Wai as Wai+import Control.Monad.Apiary.Action.Internal+    ( Extensions(AddExtension, NoExtension)+    , Extension(extMiddleware, extMiddleware'), Middleware')  class Has a (as :: [*]) where     getExtension :: proxy a -> Extensions as -> a@@ -29,12 +29,12 @@ newtype Initializer m i o = Initializer      {unInitializer :: forall a. Extensions i -> (Extensions o -> m a) -> m a} -class Extension a where-    extMiddleware  :: a -> Middleware-    extMiddleware  _ = id+allMiddleware' :: Extensions es -> Middleware'+allMiddleware' NoExtension         = id+allMiddleware' (AddExtension e es) = extMiddleware' e . allMiddleware' es -allMiddleware :: Extensions es -> Middleware-allMiddleware NoExtension         = id+allMiddleware :: Extensions es -> Wai.Middleware+allMiddleware NoExtension = id allMiddleware (AddExtension e es) = extMiddleware e . allMiddleware es  #if __GLASGOW_HASKELL__ >= 708
src/Data/Apiary/Method.hs view
@@ -1,11 +1,11 @@-{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-}  module Data.Apiary.Method where -import Data.String+import Data.Hashable(Hashable(..))+import Data.String(IsString(..)) import qualified Data.ByteString.Char8 as S-import Data.Hashable import qualified Data.ByteString.Unsafe as U  data Method
src/Data/Apiary/Param.hs view
@@ -1,20 +1,12 @@-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE DataKinds #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE OverlappingInstances #-}-{-# LANGUAGE Rank2Types #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE DataKinds #-}  module Data.Apiary.Param     ( -- * route path parameter@@ -57,21 +49,25 @@     , pOptional     ) where -import Control.Monad-import Control.Arrow+import Control.Monad(when, unless, MonadPlus(mzero))+import Control.Arrow(second) -import qualified Network.HTTP.Types as Http+import qualified Network.HTTP.Types as HTTP -import Data.Int-import Data.Maybe-import Data.Word+import Data.Int(Int8, Int16, Int32, Int64)+import Data.Word(Word, Word8, Word16, Word32, Word64)+import Data.Maybe(isJust, catMaybes)+import Data.Apiary.Dict(Elem((:=)), NotMember, Dict)+import qualified Data.Apiary.Dict as Dict import Data.Apiary.Compat-import Data.Apiary.Dict+    ( Typeable, mkTyConApp, typeRepTyCon, typeOf, TypeRep, typeRep, Proxy(..)+    , Symbol, KnownSymbol+    )  import Data.String(IsString)-import Data.Time.Calendar+import Data.Time.Calendar(Day, fromGregorian) import qualified Data.Text.Read as TR-import Data.Text.Encoding.Error+import           Data.Text.Encoding.Error(lenientDecode) import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Data.Text.Lazy as TL@@ -316,7 +312,7 @@ pFile = Proxy  class ReqParam a where-    reqParams   :: proxy a -> Http.Query -> [Param] -> [File] -> [(S.ByteString, Maybe a)]+    reqParams   :: proxy a -> HTTP.Query -> [Param] -> [File] -> [(S.ByteString, Maybe a)]     reqParamRep :: proxy a -> QueryRep  instance ReqParam File where@@ -335,50 +331,50 @@  class Strategy (w :: * -> *) where     type SNext w (k::Symbol) a (prms :: [Elem]) :: [Elem]-    strategy :: (NotMember k prms, MonadPlus m) => w a -> proxy' k -> [Maybe a] -> Dict prms -> m (Dict (SNext w k a prms))+    strategy :: (KnownSymbol k, NotMember k prms, MonadPlus m) => w a -> proxy' k -> [Maybe a] -> Dict prms -> m (Dict (SNext w k a prms))     strategyRep :: w a -> StrategyRep  data First a = First instance Strategy First where     type SNext First k a ps = k := a ': ps-    strategy _ k (Just a:_) d = return $ insert k a d+    strategy _ k (Just a:_) d = return $ Dict.insert k a d     strategy _ _ _          _ = mzero     strategyRep _ = StrategyRep "first"  data One a = One instance Strategy One where     type SNext One k a ps = k := a ': ps-    strategy _ k [Just a] d = return $ insert k a d+    strategy _ k [Just a] d = return $ Dict.insert k a d     strategy _ _ _        _ = mzero     strategyRep _ = StrategyRep "one"  data Many a = Many instance Strategy Many where     type SNext Many k a ps = k := [a] ': ps-    strategy _ k as d = if all isJust as then return $ insert k (catMaybes as) d else mzero+    strategy _ k as d = if all isJust as then return $ Dict.insert k (catMaybes as) d else mzero     strategyRep _ = StrategyRep "many"  data Some a = Some instance Strategy Some where     type SNext Some k a ps = k := [a] ': ps     strategy _ _ [] _ = mzero-    strategy _ k as d = if all isJust as then return $ insert k (catMaybes as) d else mzero+    strategy _ k as d = if all isJust as then return $ Dict.insert k (catMaybes as) d else mzero     strategyRep _ = StrategyRep "some"  data Option a = Option instance Strategy Option where     type SNext Option k a ps = k := Maybe a ': ps-    strategy _ k (Just a:_)  d = return $ insert k (Just a) d+    strategy _ k (Just a:_)  d = return $ Dict.insert k (Just a) d     strategy _ _ (Nothing:_) _ = mzero-    strategy _ k []          d = return $ insert k Nothing d+    strategy _ k []          d = return $ Dict.insert k Nothing d     strategyRep _ = StrategyRep "option"  data Optional a = Optional T.Text a instance Strategy Optional where     type SNext Optional k a ps = k := a ': ps-    strategy _              k (Just a:_)  d = return $ insert k a d+    strategy _              k (Just a:_)  d = return $ Dict.insert k a d     strategy _              _ (Nothing:_) _ = mzero-    strategy (Optional _ a) k []          d = return $ insert k a d+    strategy (Optional _ a) k []          d = return $ Dict.insert k a d     strategyRep (Optional a _) = StrategyRep $ "default:" `T.append` a  pFirst :: proxy a -> First a
src/Web/Apiary.hs view
@@ -54,7 +54,12 @@     , text,  lazyText     , showing     , string, char-    , file, devFile+    , appendBuilder+    , appendBytes, appendLazyBytes+    , appendText, appendLazyText+    , appendShowing+    , appendString, appendChar+    , file, file'     , redirect, redirectPermanently, redirectTemporary     , defaultDocumentationAction     , DefaultDocumentConfig(..)@@ -82,7 +87,7 @@     )  import Data.Apiary.Method(Method(..))-import Data.Apiary.Extension(Has, MonadHas(..), Extensions, Initializer, Initializer', (+>))+import Data.Apiary.Extension(Has, MonadExts(..), getExt, Extensions, Initializer, Initializer', (+>)) import Data.Apiary.Dict(key, Member, Members, NotMember, Elem((:=)))  import Network.HTTP.Types.Status hiding (mkStatus)
+ src/Web/Apiary/Develop.hs view
@@ -0,0 +1,18 @@+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}++module Web.Apiary.Develop {-# WARNING "use Web.Apiary in production." #-}+    ( file, file'+    , module Web.Apiary+    ) where++import Web.Apiary hiding (file, file')+import Control.Monad.Apiary.Action (devFile, devFile')++-- | send file contents as lazy bytestring response with detect+-- Content-Type. since v1.2.0.+file :: MonadIO m => FilePath -> Maybe FilePart -> ActionT exts prms m ()+file f _ = devFile f++-- | send file contents as lazy bytestring response. since v1.2.0.+file' :: MonadIO m => FilePath -> Maybe FilePart -> ActionT exts prms m ()+file' f _ = devFile' f
src/Web/Apiary/Heroku.hs view
@@ -1,10 +1,9 @@ {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TypeOperators #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE Rank2Types #-}-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE DataKinds #-}  module Web.Apiary.Heroku     ( Heroku@@ -14,32 +13,33 @@     , runHeroku, runHerokuWith, runHerokuTWith     -- * extension functions     , getHerokuEnv, getHerokuEnv'--    -- * reexports-    -- | exclude run* functions.-    , module Web.Apiary     ) where -import System.Environment+import System.Environment(getEnv) import System.Process-import System.Exit+    ( proc, CreateProcess(..), createProcess+    , StdStream(CreatePipe), waitForProcess)+import System.Exit (ExitCode(ExitSuccess)) -import Control.Exception-import Control.Arrow hiding (app)-import Control.Applicative-import Control.Monad.Trans+import qualified Network.Wai as Wai -import Data.IORef-import Data.Apiary.Compat-import Data.Default.Class+import Control.Exception(catch, try, SomeException)+import Control.Arrow(second)+import Control.Applicative((<$>), (<$), Applicative(..))+import Control.Monad.Trans(MonadIO(..))++import Data.IORef(IORef, newIORef, readIORef, writeIORef)+import Data.Default.Class(Default(def)) import qualified Data.HashMap.Strict as H import qualified Data.Text    as T import qualified Data.Text.IO as T -import Network.Wai-import Control.Monad.Apiary+import Control.Monad.Apiary(ApiaryT, runApiaryTWith, ApiaryConfig) import Data.Apiary.Extension-import Web.Apiary hiding (runApiary, runApiaryWith, runApiaryTWith)+    ( Has, Extension, Extensions, getExtension, noExtension+    , Initializer, Initializer', initializer', (+>)+    )+import Data.Apiary.Compat(Proxy(..))  data Heroku = Heroku      { herokuEnv    :: IORef (Maybe (H.HashMap T.Text T.Text))@@ -72,7 +72,7 @@ -- runHerokuTWith :: (MonadIO m, Monad actM)                => (forall b. actM b -> IO b)-               -> (Int -> Application -> m a)+               -> (Int -> Wai.Application -> m a)                -> Initializer m '[Heroku] exts                -> HerokuConfig                -> ApiaryT exts '[] actM m ()@@ -83,7 +83,7 @@     runApiaryTWith runAct (run port) (initHeroku conf +> ir) (herokuApiaryConfig conf) m  runHerokuWith :: MonadIO m-              => (Int -> Application -> m a)+              => (Int -> Wai.Application -> m a)               -> Initializer m '[Heroku] exts               -> HerokuConfig               -> ApiaryT exts '[] IO m ()@@ -97,7 +97,7 @@ -- * set port by PORT environment variable. -- * getHerokuEnv function(get config from environment variable or @ heroku config @ command). runHeroku :: MonadIO m-          => (Int -> Application -> m a)+          => (Int -> Wai.Application -> m a)           -> HerokuConfig           -> ApiaryT '[Heroku] '[] IO m ()           -> m a
− src/Web/Apiary/Wai.hs
@@ -1,6 +0,0 @@--- | reexporting Network.Wai to reduce dependencies from apiary-* packages.-module Web.Apiary.Wai-    ( module Network.Wai-    ) where--import Network.Wai
test/Application.hs view
@@ -133,10 +133,10 @@ captureApp :: Application captureApp = runApp $ do     [capture|/foo|]  . action $ contentType "text/plain" >> bytes "foo"-    [capture|/int::Int|] . method GET . action $ contentType "text/plain" >> bytes "Int " >> param [key|int|] >>= showing-    [capture|/d::Double|] . action $ contentType "text/plain" >> bytes "Double " >> param [key|d|] >>= showing-    [capture|/bar/s::L.ByteString/i::Int|] . action $ contentType "text/plain" >> param [key|s|] >>= lazyBytes >> char ' ' >> param [key|i|] >>= showing-    [capture|/s::L.ByteString|] . action $ contentType "text/plain" >> bytes "fall " >> param [key|s|] >>= lazyBytes+    [capture|/int::Int|] . method GET . action $ contentType "text/plain" >> bytes "Int " >> param [key|int|] >>= appendShowing+    [capture|/d::Double|] . action $ contentType "text/plain" >> bytes "Double " >> param [key|d|] >>= appendShowing+    [capture|/bar/s::L.ByteString/i::Int|] . action $ contentType "text/plain" >> param [key|s|] >>= lazyBytes >> appendChar ' ' >> param [key|i|] >>= appendShowing+    [capture|/s::L.ByteString|] . action $ contentType "text/plain" >> bytes "fall " >> param [key|s|] >>= appendLazyBytes  captureTest :: Test captureTest = testGroup "capture" $ map ($ captureApp)@@ -153,15 +153,15 @@ --------------------------------------------------------------------------------  queryApp f g h = runApp $ do-    _ <- (f [key|foo|] pInt)    . action $ contentType "text/plain" >> bytes "foo Int " >> param [key|foo|] >>= showing-    _ <- (g [key|foo|] pString) . action $ contentType "text/plain" >> bytes "foo String " >> param [key|foo|] >>= showing-    (h [key|foo|] (pMaybe pString)) . action $ contentType "text/plain" >> bytes "foo Maybe String " >> param [key|foo|] >>= showing+    _ <- (f [key|foo|] pInt)    . action $ contentType "text/plain" >> bytes "foo Int " >> param [key|foo|] >>= appendShowing+    _ <- (g [key|foo|] pString) . action $ contentType "text/plain" >> bytes "foo String " >> param [key|foo|] >>= appendShowing+    (h [key|foo|] (pMaybe pString)) . action $ contentType "text/plain" >> bytes "foo Maybe String " >> param [key|foo|] >>= appendShowing  queryOptionalApp :: Application queryOptionalApp = runApp $ do-    ([key|foo|] =?!: (5 :: Int))                   . action $ contentType "text/plain" >> bytes "foo Int " >> param [key|foo|] >>= showing-    ([key|foo|] =?!: ("bar" :: String))            . action $ contentType "text/plain" >> bytes "foo String " >> param [key|foo|] >>= showing-    ([key|foo|] =?!: (Just "baz" :: Maybe String)) . action $ contentType "text/plain" >> bytes "foo Maybe String " >> param [key|foo|] >>= showing+    ([key|foo|] =?!: (5 :: Int))                   . action $ contentType "text/plain" >> bytes "foo Int " >> param [key|foo|] >>= appendShowing+    ([key|foo|] =?!: ("bar" :: String))            . action $ contentType "text/plain" >> bytes "foo String " >> param [key|foo|] >>= appendShowing+    ([key|foo|] =?!: (Just "baz" :: Maybe String)) . action $ contentType "text/plain" >> bytes "foo Maybe String " >> param [key|foo|] >>= appendShowing  queryFirstTest :: Test queryFirstTest = testGroup "First" $ map ($ queryApp (=:) (=:) (=:))@@ -234,7 +234,7 @@     switchQuery [key|foo|] . switchQuery [key|bar|] . action $ do         contentType "text/plain"         param [key|foo|] >>= showing-        param [key|bar|] >>= showing+        param [key|bar|] >>= appendShowing  switchQueryTest :: Test switchQueryTest = testGroup "switch" $ map ($ switchQueryApp)@@ -266,9 +266,9 @@         i <- param [key|i|]         contentType "text/plain"         when (i == 1) $ bytes "one\n"-        if i `mod` 2 == 0 then bytes "even\n" else bytes "odd\n"+        if i `mod` 2 == 0 then appendBytes "even\n" else appendBytes "odd\n"         when (i == 2) stop-        bytes "after stop"+        appendBytes "after stop"  stopTest :: Test stopTest = testGroup "stop" $ map ($ stopApp)