packages feed

apiary 0.15.2 → 0.16.0

raw patch · 19 files changed

+912/−599 lines, 19 filesdep +HUnitdep +timedep +transformersdep −reflectionPVP ok

version bump matches the API change (PVP)

Dependencies added: HUnit, time, transformers

Dependencies removed: reflection

API changes (from Hackage documentation)

- Control.Monad.Apiary: runApiaryT :: (Monad n, Monad m) => (forall b. n b -> IO b) -> ApiaryConfig -> ApiaryT '[] n m a -> m Application
- Control.Monad.Apiary: type Apiary c = ApiaryT c IO Identity
- Control.Monad.Apiary.Filter: CONNECT :: Method
- Control.Monad.Apiary.Filter: DELETE :: Method
- Control.Monad.Apiary.Filter: GET :: Method
- Control.Monad.Apiary.Filter: HEAD :: Method
- Control.Monad.Apiary.Filter: NonStandard :: ByteString -> Method
- Control.Monad.Apiary.Filter: OPTIONS :: Method
- Control.Monad.Apiary.Filter: PATCH :: Method
- Control.Monad.Apiary.Filter: POST :: Method
- Control.Monad.Apiary.Filter: PUT :: Method
- Control.Monad.Apiary.Filter: TRACE :: Method
- Control.Monad.Apiary.Filter: data Method
- Control.Monad.Apiary.Filter.Internal.Strategy: instance Reifies * u Int => Strategy (LimitSome u)
- Control.Monad.Apiary.Filter.Internal.Strategy: instance Typeable2 LimitSome
- Control.Monad.Apiary.Filter.Internal.Strategy: reflectLimit :: Reifies n Int => proxy (LimitSome n a) -> Int
- Data.Apiary.SList: instance (All Show as) => Show (SList as)
- Data.Apiary.SList: sSnoc :: SList as -> a -> SList (Snoc as a)
+ Control.Monad.Apiary: apiaryExt :: (Has e exts, Monad actM) => proxy e -> ApiaryT exts prms actM m e
+ Control.Monad.Apiary: middleware :: Monad actM => Middleware -> ApiaryT exts prms actM m ()
+ Control.Monad.Apiary: runApiaryTWith :: (Monad actM, Monad m) => Initializer '[] m exts -> ApiaryConfig -> (forall b. actM b -> IO b) -> ApiaryT exts '[] actM m () -> m Application
+ Control.Monad.Apiary: runApiaryWith :: Monad m => Initializer '[] m exts -> ApiaryConfig -> ApiaryT exts '[] IO m () -> m Application
+ Control.Monad.Apiary: server :: Monad m => (Application -> m a) -> m Application -> m a
+ Control.Monad.Apiary.Action: getExt :: (Has e exts, Monad m) => proxy e -> ActionT exts m e
+ Control.Monad.Apiary.Filter: (=?!:) :: (MonadIO actM, ReqParam p, Show p) => QueryKey -> p -> ApiaryT exts (p : prms) actM m () -> ApiaryT exts prms actM m ()
+ Control.Monad.Apiary.Filter: accept :: Monad actM => ContentType -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
+ Control.Monad.Apiary.Filter.Internal.Strategy: Check :: Check a
+ Control.Monad.Apiary.Filter.Internal.Strategy: First :: First a
+ Control.Monad.Apiary.Filter.Internal.Strategy: LimitSome :: {-# UNPACK #-} !Int -> LimitSome a
+ Control.Monad.Apiary.Filter.Internal.Strategy: Many :: Many a
+ Control.Monad.Apiary.Filter.Internal.Strategy: One :: One a
+ Control.Monad.Apiary.Filter.Internal.Strategy: Option :: Option a
+ Control.Monad.Apiary.Filter.Internal.Strategy: Optional :: Text -> a -> Optional a
+ Control.Monad.Apiary.Filter.Internal.Strategy: Some :: Some a
+ Control.Monad.Apiary.Filter.Internal.Strategy: data Optional a
+ Control.Monad.Apiary.Filter.Internal.Strategy: instance Strategy LimitSome
+ Control.Monad.Apiary.Filter.Internal.Strategy: instance Strategy Optional
+ Control.Monad.Apiary.Filter.Internal.Strategy: instance Typeable1 LimitSome
+ Control.Monad.Apiary.Filter.Internal.Strategy: instance Typeable1 Optional
+ Control.Monad.Apiary.Filter.Internal.Strategy: pLimitSome :: Int -> proxy a -> LimitSome a
+ Control.Monad.Apiary.Filter.Internal.Strategy: pOptional :: Show a => a -> Optional a
+ Data.Apiary.Extension: (+>) :: Monad m => Initializer i m x -> Initializer x m o -> Initializer i m o
+ Data.Apiary.Extension: addExtension :: e -> Extensions es -> Extensions (e : es)
+ Data.Apiary.Extension: class Has a (as :: [*])
+ Data.Apiary.Extension: data Extensions (es :: [*])
+ Data.Apiary.Extension: data Initializer i m o
+ Data.Apiary.Extension: getExtension :: Has a as => proxy a -> Extensions as -> a
+ Data.Apiary.Extension: initializer :: Monad m => m e -> Initializer' m e
+ Data.Apiary.Extension: noExtension :: Monad m => Initializer '[] m '[]
+ Data.Apiary.Extension: preAction :: Monad m => m a -> Initializer i m i
+ Data.Apiary.Extension: type Initializer' m a = forall i. Initializer i m (a : i)
+ Data.Apiary.Extension.Internal: AddExtension :: (e :: *) -> Extensions es -> Extensions (e : es)
+ Data.Apiary.Extension.Internal: Initializer :: (Extensions i -> m (Extensions o)) -> Initializer i m o
+ Data.Apiary.Extension.Internal: NoExtension :: Extensions '[]
+ Data.Apiary.Extension.Internal: class Has a (as :: [*])
+ Data.Apiary.Extension.Internal: data Extensions (es :: [*])
+ Data.Apiary.Extension.Internal: getExtension :: Has a as => proxy a -> Extensions as -> a
+ Data.Apiary.Extension.Internal: instance [overlap ok] Has a ((':) * a as)
+ Data.Apiary.Extension.Internal: instance [overlap ok] Has a as => Has a ((':) * a' as)
+ Data.Apiary.Extension.Internal: newtype Initializer i m o
+ Data.Apiary.Extension.Internal: unInitializer :: Initializer i m o -> Extensions i -> m (Extensions o)
+ Data.Apiary.Param: instance [overlap ok] Path Day
+ Data.Apiary.Param: instance [overlap ok] Query Day
+ Data.Apiary.SList: apply' :: Apply xs r -> SList xs -> r
+ Data.Apiary.SList: instance [overlap ok] (All Show as) => Show (SList as)
+ Data.Apiary.SList: type Fn c a = Apply (Reverse c) a
- Control.Monad.Apiary: action :: Monad n => Fn c (ActionT n ()) -> ApiaryT c n m ()
+ Control.Monad.Apiary: action :: Monad actM => Fn prms (ActionT exts actM ()) -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary: action' :: Monad n => (SList c -> ActionT n ()) -> ApiaryT c n m ()
+ Control.Monad.Apiary: action' :: Monad actM => (SList prms -> ActionT exts actM ()) -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary: actionWithPreAction :: Monad n => (SList xs -> ActionT n a) -> Fn xs (ActionT n ()) -> ApiaryT xs n m ()
+ Control.Monad.Apiary: actionWithPreAction :: Monad actM => (SList xs -> ActionT exts actM a) -> Fn xs (ActionT exts actM ()) -> ApiaryT exts xs actM m ()
- Control.Monad.Apiary: apiaryConfig :: Monad n => ApiaryT c n m ApiaryConfig
+ Control.Monad.Apiary: apiaryConfig :: Monad actM => ApiaryT exts prms actM m ApiaryConfig
- Control.Monad.Apiary: data ApiaryT c n m a
+ Control.Monad.Apiary: data ApiaryT exts prms actM m a
- Control.Monad.Apiary: document :: Text -> ApiaryT c n m a -> ApiaryT c n m a
+ Control.Monad.Apiary: document :: Text -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary: group :: Text -> ApiaryT c n m a -> ApiaryT c n m a
+ Control.Monad.Apiary: group :: Text -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary: noDoc :: ApiaryT c n m a -> ApiaryT c n m a
+ Control.Monad.Apiary: noDoc :: ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary: precondition :: Html -> ApiaryT c n m a -> ApiaryT c n m a
+ Control.Monad.Apiary: precondition :: Html -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary: runApiary :: ApiaryConfig -> Apiary '[] a -> Application
+ Control.Monad.Apiary: runApiary :: Monad m => ApiaryConfig -> ApiaryT '[] '[] IO m () -> m Application
- Control.Monad.Apiary.Action: addHeader :: Monad m => HeaderName -> ByteString -> ActionT m ()
+ Control.Monad.Apiary.Action: addHeader :: Monad m => HeaderName -> ByteString -> ActionT exts m ()
- Control.Monad.Apiary.Action: builder :: Monad m => Builder -> ActionT m ()
+ Control.Monad.Apiary.Action: builder :: Monad m => Builder -> ActionT exts m ()
- Control.Monad.Apiary.Action: bytes :: Monad m => ByteString -> ActionT m ()
+ Control.Monad.Apiary.Action: bytes :: Monad m => ByteString -> ActionT exts m ()
- Control.Monad.Apiary.Action: char :: Monad m => Char -> ActionT m ()
+ Control.Monad.Apiary.Action: char :: Monad m => Char -> ActionT exts m ()
- Control.Monad.Apiary.Action: contentType :: Monad m => ContentType -> ActionT m ()
+ Control.Monad.Apiary.Action: contentType :: Monad m => ContentType -> ActionT exts m ()
- Control.Monad.Apiary.Action: data ActionT m a
+ Control.Monad.Apiary.Action: data ActionT exts m a
- Control.Monad.Apiary.Action: defaultDocumentationAction :: Monad m => DefaultDocumentConfig -> ActionT m ()
+ Control.Monad.Apiary.Action: defaultDocumentationAction :: Monad m => DefaultDocumentConfig -> ActionT exts m ()
- Control.Monad.Apiary.Action: file :: Monad m => FilePath -> Maybe FilePart -> ActionT m ()
+ Control.Monad.Apiary.Action: file :: Monad m => FilePath -> Maybe FilePart -> ActionT exts m ()
- Control.Monad.Apiary.Action: file' :: Monad m => FilePath -> Maybe FilePart -> ActionT m ()
+ Control.Monad.Apiary.Action: file' :: Monad m => FilePath -> Maybe FilePart -> ActionT exts m ()
- Control.Monad.Apiary.Action: getHeaders :: Monad m => ActionT m RequestHeaders
+ Control.Monad.Apiary.Action: getHeaders :: Monad m => ActionT exts m RequestHeaders
- Control.Monad.Apiary.Action: getReqFiles :: MonadIO m => ActionT m [File]
+ Control.Monad.Apiary.Action: getReqFiles :: MonadIO m => ActionT exts m [File]
- Control.Monad.Apiary.Action: getReqParams :: MonadIO m => ActionT m [Param]
+ Control.Monad.Apiary.Action: getReqParams :: MonadIO m => ActionT exts m [Param]
- Control.Monad.Apiary.Action: getRequest :: Monad m => ActionT m Request
+ Control.Monad.Apiary.Action: getRequest :: Monad m => ActionT exts m Request
- Control.Monad.Apiary.Action: lazyBytes :: Monad m => ByteString -> ActionT m ()
+ Control.Monad.Apiary.Action: lazyBytes :: Monad m => ByteString -> ActionT exts m ()
- Control.Monad.Apiary.Action: lazyText :: Monad m => Text -> ActionT m ()
+ Control.Monad.Apiary.Action: lazyText :: Monad m => Text -> ActionT exts m ()
- Control.Monad.Apiary.Action: lbs :: Monad m => ByteString -> ActionT m ()
+ Control.Monad.Apiary.Action: lbs :: Monad m => ByteString -> ActionT exts m ()
- Control.Monad.Apiary.Action: modifyHeader :: Monad m => (ResponseHeaders -> ResponseHeaders) -> ActionT m ()
+ Control.Monad.Apiary.Action: modifyHeader :: Monad m => (ResponseHeaders -> ResponseHeaders) -> ActionT exts m ()
- Control.Monad.Apiary.Action: rawResponse :: Monad m => (Status -> ResponseHeaders -> Response) -> ActionT m ()
+ Control.Monad.Apiary.Action: rawResponse :: Monad m => (Status -> ResponseHeaders -> Response) -> ActionT exts m ()
- Control.Monad.Apiary.Action: redirect :: Monad m => ByteString -> ActionT m ()
+ Control.Monad.Apiary.Action: redirect :: Monad m => ByteString -> ActionT exts m ()
- Control.Monad.Apiary.Action: redirectFound :: Monad m => ByteString -> ActionT m ()
+ Control.Monad.Apiary.Action: redirectFound :: Monad m => ByteString -> ActionT exts m ()
- Control.Monad.Apiary.Action: redirectPermanently :: Monad m => ByteString -> ActionT m ()
+ Control.Monad.Apiary.Action: redirectPermanently :: Monad m => ByteString -> ActionT exts m ()
- Control.Monad.Apiary.Action: redirectSeeOther :: Monad m => ByteString -> ActionT m ()
+ Control.Monad.Apiary.Action: redirectSeeOther :: Monad m => ByteString -> ActionT exts m ()
- Control.Monad.Apiary.Action: redirectTemporary :: Monad m => ByteString -> ActionT m ()
+ Control.Monad.Apiary.Action: redirectTemporary :: Monad m => ByteString -> ActionT exts m ()
- Control.Monad.Apiary.Action: redirectWith :: Monad m => Status -> ByteString -> ActionT m ()
+ Control.Monad.Apiary.Action: redirectWith :: Monad m => Status -> ByteString -> ActionT exts m ()
- Control.Monad.Apiary.Action: reset :: Monad m => ActionT m ()
+ Control.Monad.Apiary.Action: reset :: Monad m => ActionT exts m ()
- Control.Monad.Apiary.Action: setHeaders :: Monad m => ResponseHeaders -> ActionT m ()
+ Control.Monad.Apiary.Action: setHeaders :: Monad m => ResponseHeaders -> ActionT exts m ()
- Control.Monad.Apiary.Action: showing :: (Monad m, Show a) => a -> ActionT m ()
+ Control.Monad.Apiary.Action: showing :: (Monad m, Show a) => a -> ActionT exts m ()
- Control.Monad.Apiary.Action: source :: Monad m => StreamingBody -> ActionT m ()
+ Control.Monad.Apiary.Action: source :: Monad m => StreamingBody -> ActionT exts m ()
- Control.Monad.Apiary.Action: status :: Monad m => Status -> ActionT m ()
+ Control.Monad.Apiary.Action: status :: Monad m => Status -> ActionT exts m ()
- Control.Monad.Apiary.Action: stop :: Monad m => ActionT m a
+ Control.Monad.Apiary.Action: stop :: Monad m => ActionT exts m a
- Control.Monad.Apiary.Action: stopWith :: Monad m => Response -> ActionT m a
+ Control.Monad.Apiary.Action: stopWith :: Monad m => Response -> ActionT exts m a
- Control.Monad.Apiary.Action: stream :: Monad m => StreamingBody -> ActionT m ()
+ Control.Monad.Apiary.Action: stream :: Monad m => StreamingBody -> ActionT exts m ()
- Control.Monad.Apiary.Action: string :: Monad m => String -> ActionT m ()
+ Control.Monad.Apiary.Action: string :: Monad m => String -> ActionT exts m ()
- Control.Monad.Apiary.Action: text :: Monad m => Text -> ActionT m ()
+ Control.Monad.Apiary.Action: text :: Monad m => Text -> ActionT exts m ()
- Control.Monad.Apiary.Filter: (=!:) :: (MonadIO n, ReqParam a) => QueryKey -> proxy a -> ApiaryT (Snoc as a) n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: (=!:) :: (MonadIO actM, ReqParam p) => QueryKey -> proxy p -> ApiaryT exts (p : prms) actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: (=*:) :: (MonadIO n, ReqParam a) => QueryKey -> proxy a -> ApiaryT (Snoc as [a]) n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: (=*:) :: (MonadIO actM, ReqParam p) => QueryKey -> proxy p -> ApiaryT exts ([p] : prms) actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: (=+:) :: (MonadIO n, ReqParam a) => QueryKey -> proxy a -> ApiaryT (Snoc as [a]) n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: (=+:) :: (MonadIO actM, ReqParam p) => QueryKey -> proxy p -> ApiaryT exts ([p] : prms) actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: (=:) :: (MonadIO n, ReqParam a) => QueryKey -> proxy a -> ApiaryT (Snoc as a) n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: (=:) :: (MonadIO actM, ReqParam p) => QueryKey -> proxy p -> ApiaryT exts (p : prms) actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: (=?:) :: (MonadIO n, ReqParam a) => QueryKey -> proxy a -> ApiaryT (Snoc as (Maybe a)) n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: (=?:) :: (MonadIO actM, ReqParam p) => QueryKey -> proxy p -> ApiaryT exts (Maybe p : prms) actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: (?:) :: (MonadIO n, ReqParam a) => QueryKey -> proxy a -> ApiaryT as n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: (?:) :: (MonadIO actM, ReqParam p) => QueryKey -> proxy p -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: anyPath :: (Functor m, Monad m, Monad n) => ApiaryT c n m b -> ApiaryT c n m b
+ Control.Monad.Apiary.Filter: anyPath :: (Monad m, Monad actM) => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: endPath :: (Functor n, Monad n) => ApiaryT c n m a -> ApiaryT c n m a
+ Control.Monad.Apiary.Filter: endPath :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: eqHeader :: Monad n => HeaderName -> ByteString -> ApiaryT as n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: eqHeader :: Monad actM => HeaderName -> ByteString -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: fetch :: (Path a, Functor n, Monad n) => proxy a -> Maybe Html -> ApiaryT (Snoc as a) n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: fetch :: (Path p, Monad actM) => proxy p -> Maybe Html -> ApiaryT exts (p : prms) actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: hasHeader :: Monad n => HeaderName -> ApiaryT as n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: hasHeader :: Monad actM => HeaderName -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: hasQuery :: MonadIO n => QueryKey -> ApiaryT c n m a -> ApiaryT c n m a
+ Control.Monad.Apiary.Filter: hasQuery :: MonadIO actM => QueryKey -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: header :: Monad n => HeaderName -> ApiaryT (Snoc as ByteString) n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: header :: Monad actM => HeaderName -> ApiaryT exts (ByteString : prms) actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: header' :: (Strategy w, Monad n) => (forall x. Proxy x -> Proxy (w x)) -> (Header -> Bool) -> Maybe Html -> ApiaryT (SNext w as ByteString) n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: header' :: (Strategy w, Monad actM) => (forall x. Proxy x -> w x) -> (Header -> Bool) -> Maybe Html -> ApiaryT exts (SNext w prms ByteString) actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: headers :: Monad n => HeaderName -> ApiaryT (Snoc as [ByteString]) n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: headers :: Monad actM => HeaderName -> ApiaryT exts ([ByteString] : prms) actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: http09 :: Monad n => ApiaryT c n m b -> ApiaryT c n m b
+ Control.Monad.Apiary.Filter: http09 :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: http10 :: Monad n => ApiaryT c n m b -> ApiaryT c n m b
+ Control.Monad.Apiary.Filter: http10 :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: http11 :: Monad n => ApiaryT c n m b -> ApiaryT c n m b
+ Control.Monad.Apiary.Filter: http11 :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: httpVersion :: Monad n => HttpVersion -> Html -> ApiaryT c n m b -> ApiaryT c n m b
+ Control.Monad.Apiary.Filter: httpVersion :: Monad actM => HttpVersion -> Html -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: method :: Monad n => Method -> ApiaryT c n m a -> ApiaryT c n m a
+ Control.Monad.Apiary.Filter: method :: Monad actM => Method -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: path :: Monad n => Text -> ApiaryT c n m a -> ApiaryT c n m a
+ Control.Monad.Apiary.Filter: path :: Monad actM => Text -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: query :: (ReqParam a, Strategy w, MonadIO n) => QueryKey -> proxy (w a) -> ApiaryT (SNext w as a) n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter: query :: (ReqParam a, Strategy w, MonadIO actM) => QueryKey -> w a -> ApiaryT exts (SNext w prms a) actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: root :: (Functor m, Monad m, Monad n) => ApiaryT c n m b -> ApiaryT c n m b
+ Control.Monad.Apiary.Filter: root :: (Monad m, Monad actM) => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: ssl :: Monad n => ApiaryT c n m a -> ApiaryT c n m a
+ Control.Monad.Apiary.Filter: ssl :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter: stdMethod :: Monad n => Method -> ApiaryT c n m a -> ApiaryT c n m a
+ Control.Monad.Apiary.Filter: stdMethod :: Monad actM => Method -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter.Internal: focus :: Monad n => (Doc -> Doc) -> (SList c -> ActionT n (SList c')) -> ApiaryT c' n m a -> ApiaryT c n m a
+ Control.Monad.Apiary.Filter.Internal: focus :: Monad actM => (Doc -> Doc) -> (SList prms -> ActionT exts actM (SList prms')) -> ApiaryT exts prms' actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter.Internal: function :: Monad n => (Doc -> Doc) -> (SList c -> Request -> Maybe (SList c')) -> ApiaryT c' n m b -> ApiaryT c n m b
+ Control.Monad.Apiary.Filter.Internal: function :: Monad actM => (Doc -> Doc) -> (SList prms -> Request -> Maybe (SList prms')) -> ApiaryT exts prms' actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter.Internal: function' :: Monad n => (Doc -> Doc) -> (Request -> Maybe a) -> ApiaryT (Snoc as a) n m b -> ApiaryT as n m b
+ Control.Monad.Apiary.Filter.Internal: function' :: Monad actM => (Doc -> Doc) -> (Request -> Maybe prm) -> ApiaryT exts (prm : prms) actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter.Internal: function_ :: Monad n => (Doc -> Doc) -> (Request -> Bool) -> ApiaryT c n m b -> ApiaryT c n m b
+ Control.Monad.Apiary.Filter.Internal: function_ :: Monad actM => (Doc -> Doc) -> (Request -> Bool) -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()
- Control.Monad.Apiary.Filter.Internal.Strategy: data LimitSome u a
+ Control.Monad.Apiary.Filter.Internal.Strategy: data LimitSome a
- Control.Monad.Apiary.Filter.Internal.Strategy: getQuery :: (v -> Maybe a) -> proxy (w a) -> ((k, v) -> Bool) -> [(k, v)] -> [Maybe a]
+ Control.Monad.Apiary.Filter.Internal.Strategy: getQuery :: (v -> Maybe a) -> w a -> ((k, v) -> Bool) -> [(k, v)] -> [Maybe a]
- Control.Monad.Apiary.Filter.Internal.Strategy: pCheck :: proxy a -> Proxy (Check a)
+ Control.Monad.Apiary.Filter.Internal.Strategy: pCheck :: proxy a -> Check a
- Control.Monad.Apiary.Filter.Internal.Strategy: pFirst :: proxy a -> Proxy (First a)
+ Control.Monad.Apiary.Filter.Internal.Strategy: pFirst :: proxy a -> First a
- Control.Monad.Apiary.Filter.Internal.Strategy: pMany :: proxy a -> Proxy (Many a)
+ Control.Monad.Apiary.Filter.Internal.Strategy: pMany :: proxy a -> Many a
- Control.Monad.Apiary.Filter.Internal.Strategy: pOne :: proxy a -> Proxy (One a)
+ Control.Monad.Apiary.Filter.Internal.Strategy: pOne :: proxy a -> One a
- Control.Monad.Apiary.Filter.Internal.Strategy: pOption :: proxy a -> Proxy (Option a)
+ Control.Monad.Apiary.Filter.Internal.Strategy: pOption :: proxy a -> Option a
- Control.Monad.Apiary.Filter.Internal.Strategy: pSome :: proxy a -> Proxy (Some a)
+ Control.Monad.Apiary.Filter.Internal.Strategy: pSome :: proxy a -> Some a
- Control.Monad.Apiary.Filter.Internal.Strategy: readStrategy :: Strategy w => (v -> Maybe a) -> ((k, v) -> Bool) -> proxy (w a) -> [(k, v)] -> SList as -> Maybe (SList (SNext w as a))
+ Control.Monad.Apiary.Filter.Internal.Strategy: readStrategy :: Strategy w => (v -> Maybe a) -> ((k, v) -> Bool) -> w a -> [(k, v)] -> SList as -> Maybe (SList (SNext w as a))
- Control.Monad.Apiary.Filter.Internal.Strategy: strategyRep :: Strategy w => proxy w -> StrategyRep
+ Control.Monad.Apiary.Filter.Internal.Strategy: strategyRep :: Strategy w => w a -> StrategyRep
- Data.Apiary.Param: class Typeable a => Path a where pathRep = typeRep
+ Data.Apiary.Param: class Path a
- Data.Apiary.Param: class Typeable a => Query a where queryRep = Strict . qTypeRep qTypeRep = typeRep
+ Data.Apiary.Param: class Query a where queryRep = Strict . qTypeRep
- Data.Apiary.SList: apply :: Fn xs r -> SList xs -> r
+ Data.Apiary.SList: apply :: Fn c r -> SList c -> r

Files

CHANGELOG.md view
@@ -1,3 +1,11 @@+# 0.16.0+* new Extension API.+* add middleware function.+* remove Typeable restriction from Path/Query class.+* add Optional strategy, (=?!:) query fetcher.+* add accept filter.+* add Path/Query instances to Day.+ # 0.15.2 * you can set status and response headers anywhere. * deprecate lbs.
apiary.cabal view
@@ -1,5 +1,5 @@ name:                apiary-version:             0.15.2+version:             0.16.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.@@ -13,7 +13,7 @@   import qualified Data.ByteString.Lazy.Char8 as L   .   main :: IO ()-  main = run 3000 . runApiary def $ do+  main = server (run 3000) . runApiary def $ do   &#32;&#32;[capture|/:Int|] . (&#34;name&#34; =: pLazyByteString) . method GET . action $ \\age name -> do   &#32;&#32;&#32;&#32;&#32;&#32;guard (age >= 18)   &#32;&#32;&#32;&#32;&#32;&#32;contentType &#34;text/html&#34;@@ -31,15 +31,15 @@   404 Page Notfound.   @   .-    * High performance(benchmark: <https://github.com/philopon/apiary/blob/v0.15.2/bench>).+    * High performance(benchmark: <https://github.com/philopon/apiary-benchmark/tree/v0.16.0>).   .     * Nestable route handling(Apiary Monad; capture, method and more.).   .     * Type safe route filter.   .-    * Auto generate API documentation(example: <https://github.com/philopon/apiary/blob/v0.15.2/examples/api.hs>, <https://rawgit.com/philopon/apiary/v0.15.2/examples/api.html>).+    * Auto generate API documentation(example: <https://github.com/philopon/apiary/blob/v0.16.0/examples/api.hs>, <https://rawgit.com/philopon/apiary/v0.16.0/examples/api.html>).   .-  more examples: <https://github.com/philopon/apiary/blob/v0.15.2/examples/>+  more examples: <https://github.com/philopon/apiary/blob/v0.16.0/examples/>  license:             MIT license-file:        LICENSE@@ -74,6 +74,8 @@                        Control.Monad.Apiary.Filter.Internal.Strategy                        Control.Monad.Apiary.Action +                       Data.Apiary.Extension+                       Data.Apiary.Extension.Internal                        Data.Apiary.SList                        Data.Apiary.Param                        Data.Apiary.Method@@ -88,25 +90,28 @@                        Web.Apiary.TH   build-depends:       base                 >=4.6   && <4.8                      , template-haskell     >=2.8   && <2.10++                     , transformers         >=0.2   && <0.5+                     , transformers-base    >=0.4   && <0.5                      , mtl                  >=2.1   && <2.3                      , monad-control        >=0.3   && <0.4-                     , transformers-base    >=0.4   && <0.5+                     , exceptions           >=0.6   && <0.7 +                     , http-types           >=0.8   && <0.9+                     , mime-types           >=0.1   && <0.2+                      , text                 >=1.1   && <1.2                      , bytestring           >=0.10  && <0.11+                     , bytestring-lexing    >=0.4   && <0.5                      , blaze-builder        >=0.3   && <0.4-                     , data-default-class   >=0.0   && <0.1-                     , reflection           >=1.4   && <1.6--                     , http-types           >=0.8   && <0.9-                     , mime-types           >=0.1   && <0.2-                     , exceptions           >=0.6   && <0.7                      , blaze-html           >=0.7   && <0.8                      , blaze-markup         >=0.6   && <0.7                      , case-insensitive     >=1.1   && <1.3++                     , data-default-class   >=0.0   && <0.1                      , unordered-containers >=0.2   && <0.3                      , hashable             >=1.1   && <1.3-                     , bytestring-lexing    >=0.4   && <0.5+                     , time                 >=1.4   && <1.5    if impl(ghc < 7.8)     build-depends:     tagged               >=0.7   && <0.8@@ -127,13 +132,17 @@  test-suite test-framework   main-is:             main.hs+  other-modules:       Application+                     , Method   type:                exitcode-stdio-1.0   build-depends:       base                 >=4.6   && <4.8+                     , mtl                  >=2.1   && <2.3                      , test-framework       >=0.8   && <0.9                      , test-framework-hunit >=0.3   && <0.4                      , apiary                      , 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-extra            >=3.0   && <3.1
src/Control/Monad/Apiary.hs view
@@ -1,11 +1,15 @@ module Control.Monad.Apiary-    ( ApiaryT, Apiary+    ( ApiaryT, server+    , runApiaryTWith+    , runApiaryWith     , runApiary-    , runApiaryT     -- * getter     , apiaryConfig+    , apiaryExt     -- * execute action     , action, action'+    -- * middleware+    , middleware     -- * API documentation     , group     , document
src/Control/Monad/Apiary/Action.hs view
@@ -14,6 +14,7 @@     , getReqParams     , File(..)     , getReqFiles+    , getExt      -- ** setter     , status
src/Control/Monad/Apiary/Action/Internal.hs view
@@ -12,6 +12,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ConstraintKinds #-}  module Control.Monad.Apiary.Action.Internal where @@ -23,12 +24,13 @@ import Control.Monad.Catch import Control.Monad.Trans.Control -import Network.Mime+import Network.Mime hiding (Extension) import Network.HTTP.Types import Network.Wai import qualified Network.Wai.Parse as P -import Data.Monoid+import Data.Monoid hiding (All)+import Data.Apiary.Extension import Data.Apiary.Param import Data.Apiary.Document import Data.Apiary.Document.Html@@ -63,7 +65,7 @@     , mimeType            :: FilePath -> S.ByteString     } -defaultDocumentationAction :: Monad m => DefaultDocumentConfig -> ActionT m ()+defaultDocumentationAction :: Monad m => DefaultDocumentConfig -> ActionT exts m () defaultDocumentationAction conf = do     d <- getDocuments     contentType "text/html"@@ -134,10 +136,11 @@  -------------------------------------------------------------------------------- -data ActionEnv = ActionEnv+data ActionEnv exts = ActionEnv     { actionConfig    :: ApiaryConfig     , actionRequest   :: Request     , actionDocuments :: Documents+    , actionExts      :: Extensions exts     }  data Action a @@ -145,23 +148,23 @@     | Pass     | Stop Response -newtype ActionT m a = ActionT { unActionT :: forall b. -    ActionEnv+newtype ActionT exts m a = ActionT { unActionT :: forall b. +    ActionEnv exts     -> ActionState     -> (a -> ActionState -> m (Action b))     -> m (Action b)     } -runActionT :: Monad m => ActionT m a-           -> ActionEnv -> ActionState+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 #-}  actionT :: Monad m -        => (ActionEnv -> ActionState -> m (Action a))-        -> ActionT m a+        => (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@@ -170,17 +173,17 @@  -- | n must be Monad, so cant be MFunctor. hoistActionT :: (Monad m, Monad n)-             => (forall b. m b -> n b) -> ActionT m a -> ActionT n a+             => (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 -> Documents -> ActionT IO () -> Application+execActionT :: ApiaryConfig -> Extensions exts -> Documents -> ActionT exts IO () -> Application #ifdef WAI3-execActionT config doc m request send = +execActionT config exts doc m request send =  #else-execActionT config doc m request = let send = return in+execActionT config exts doc m request = let send = return in #endif-    runActionT m (ActionEnv config request doc) (initialState config) >>= \case+    runActionT m (ActionEnv config request doc exts) (initialState config) >>= \case #ifdef WAI3         Pass         -> notFound config request send #else@@ -191,18 +194,18 @@  -------------------------------------------------------------------------------- -instance Functor (ActionT m) where+instance Functor (ActionT exts m) where     fmap f m = ActionT $ \env st cont ->         unActionT m env st (\a !s' -> cont (f a) s') -instance Applicative (ActionT m) where+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'' -instance Monad m => Monad (ActionT m) where+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' ->@@ -210,24 +213,24 @@     fail s = ActionT $ \(ActionEnv{actionConfig = c}) _ _ -> return $         Stop (responseLBS (failStatus c) (failHeaders c) $ LC.pack s) -instance MonadIO m => MonadIO (ActionT m) where+instance MonadIO m => MonadIO (ActionT exts m) where     liftIO m = ActionT $ \_ !st cont ->         liftIO m >>= \a -> cont a st -instance MonadTrans ActionT where+instance MonadTrans (ActionT exts) where     lift m = ActionT $ \_ !st cont ->         m >>= \a -> cont a st -instance MonadThrow m => MonadThrow (ActionT m) where+instance MonadThrow m => MonadThrow (ActionT exts m) where     throwM e = ActionT $ \_ !st cont ->         throwM e >>= \a -> cont a st -instance MonadCatch m => MonadCatch (ActionT m) where+instance MonadCatch m => MonadCatch (ActionT exts m) where     catch m h = ActionT $ \env !st cont ->         catch (unActionT m env st cont) (\e -> unActionT (h e) env st cont)     {-# INLINE catch #-} -instance MonadMask m => MonadMask (ActionT m) where+instance MonadMask m => MonadMask (ActionT exts m) where     mask a = ActionT $ \env !st cont ->         mask $ \u -> unActionT (a $ q u) env st cont       where@@ -239,13 +242,13 @@     {-# INLINE mask #-}     {-# INLINE uninterruptibleMask #-} -instance (Monad m, Functor m) => Alternative (ActionT m) where+instance (Monad m, Functor m) => Alternative (ActionT exts m) where     empty = mzero     (<|>) = mplus     {-# INLINE empty #-}     {-# INLINE (<|>) #-} -instance Monad m => MonadPlus (ActionT m) where+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@@ -254,40 +257,43 @@     {-# INLINE mzero #-}     {-# INLINE mplus #-} -instance MonadBase b m => MonadBase b (ActionT m) where+instance MonadBase b m => MonadBase b (ActionT exts m) where     liftBase = liftBaseDefault -instance MonadTransControl ActionT where-    newtype StT ActionT a = StActionT { unStActionT :: Action a }+instance MonadTransControl (ActionT exts) where+    newtype StT (ActionT exts) a = StActionT { unStActionT :: Action a }     liftWith f = actionT $ \e !s ->          liftM (\a -> Continue s a) (f $ \t -> liftM StActionT $ runActionT t e s)     restoreT m = actionT $ \_ _ -> liftM unStActionT m -instance MonadBaseControl b m => MonadBaseControl b (ActionT m) where-    newtype StM (ActionT m) a = StMT { unStMT :: ComposeSt ActionT m a }+instance MonadBaseControl b m => MonadBaseControl b (ActionT exts m) where+    newtype StM (ActionT exts m) a = StMT { unStMT :: ComposeSt (ActionT exts) m a }     liftBaseWith = defaultLiftBaseWith StMT     restoreM     = defaultRestoreM unStMT -instance MonadReader r m => MonadReader r (ActionT m) where+instance MonadReader r m => MonadReader r (ActionT exts m) where     ask     = lift ask     local f = hoistActionT $ local f  -------------------------------------------------------------------------------- -getEnv :: Monad m => ActionT m ActionEnv+getEnv :: Monad m => ActionT exts m (ActionEnv exts) getEnv = ActionT $ \e s c -> c e s  -- | get raw request. since 0.1.0.0.-getRequest :: Monad m => ActionT m Request+getRequest :: Monad m => ActionT exts m Request getRequest = liftM actionRequest getEnv -getConfig :: Monad m => ActionT m ApiaryConfig+getConfig :: Monad m => ActionT exts m ApiaryConfig getConfig = liftM actionConfig getEnv -getDocuments :: Monad m => ActionT m Documents+getExt :: (Has e exts, Monad m) => proxy e -> ActionT exts m e+getExt p = liftM (getExtension p . actionExts) getEnv++getDocuments :: Monad m => ActionT exts m Documents getDocuments = liftM actionDocuments getEnv -getRequestBody :: MonadIO m => ActionT m ([Param], [File])+getRequestBody :: MonadIO m => ActionT exts m ([Param], [File]) getRequestBody = ActionT $ \e s c -> case actionReqBody s of     Just b  -> c b s     Nothing -> do@@ -298,57 +304,57 @@     convFile (p, P.FileInfo{..}) = File p fileName fileContentType fileContent  -- | parse request body and return params. since 0.9.0.0.-getReqParams :: MonadIO m => ActionT m [Param]+getReqParams :: MonadIO m => ActionT exts m [Param] getReqParams = fst <$> getRequestBody  -- | parse request body and return files. since 0.9.0.0.-getReqFiles :: MonadIO m => ActionT m [File]+getReqFiles :: MonadIO m => ActionT exts m [File] getReqFiles = snd <$> getRequestBody  -------------------------------------------------------------------------------- -modifyState :: Monad m => (ActionState -> ActionState) -> ActionT m ()+modifyState :: Monad m => (ActionState -> ActionState) -> ActionT exts m () modifyState f = ActionT $ \_ s c -> c () (f s) -getState :: ActionT m ActionState+getState :: ActionT exts m ActionState getState = ActionT $ \_ s c -> c s s  -- | set status code. since 0.1.0.0.-status :: Monad m => Status -> ActionT m ()+status :: Monad m => Status -> ActionT exts m () status st = modifyState (\s -> s { actionStatus = st } )  -- | get all request headers. since 0.6.0.0.-getHeaders :: Monad m => ActionT m RequestHeaders+getHeaders :: Monad m => ActionT exts m RequestHeaders getHeaders = requestHeaders `liftM` getRequest  -- | modify response header. since 0.1.0.0.-modifyHeader :: Monad m => (ResponseHeaders -> ResponseHeaders) -> ActionT m ()+modifyHeader :: Monad m => (ResponseHeaders -> ResponseHeaders) -> ActionT exts m () modifyHeader f = modifyState (\s -> s {actionHeaders = f $ actionHeaders s } )  -- | add response header. since 0.1.0.0.-addHeader :: Monad m => HeaderName -> S.ByteString -> ActionT m ()+addHeader :: Monad m => HeaderName -> S.ByteString -> ActionT exts m () addHeader h v = modifyHeader ((h,v):)  -- | set response headers. since 0.1.0.0.-setHeaders :: Monad m => ResponseHeaders -> ActionT m ()+setHeaders :: Monad m => ResponseHeaders -> ActionT exts m () setHeaders hs = modifyHeader (const hs)  type ContentType = S.ByteString  -- | set content-type header. -- if content-type header already exists, replace it. since 0.1.0.0.-contentType :: Monad m => ContentType -> ActionT m ()+contentType :: Monad m => ContentType -> ActionT exts m () contentType c = modifyHeader     (\h -> ("Content-Type", c) : filter (("Content-Type" /=) . fst) h)  --------------------------------------------------------------------------------  -- | stop handler and send current state. since 0.3.3.0.-stop :: Monad m => ActionT m a+stop :: Monad m => ActionT exts m a stop = ActionT $ \_ s _ -> return $ Stop (toResponse s)  -- | stop with response. since 0.4.2.0.-stopWith :: Monad m => Response -> ActionT m a+stopWith :: Monad m => Response -> ActionT exts m a stopWith a = ActionT $ \_ _ _ -> return $ Stop a  -- | redirect handler@@ -359,7 +365,7 @@ redirectWith :: Monad m              => Status              -> S.ByteString -- ^ Location redirect to-             -> ActionT m ()+             -> ActionT exts m () redirectWith st url = do     status st     addHeader "location" url@@ -374,7 +380,7 @@ -- 307                      TemporaryRedirect  -- | redirect with 301 Moved Permanently. since 0.3.3.0.-redirectPermanently :: Monad m => S.ByteString -> ActionT m ()+redirectPermanently :: Monad m => S.ByteString -> ActionT exts m () redirectPermanently = redirectWith movedPermanently301  -- | redirect with:@@ -383,7 +389,7 @@ -- 302 Moved Temporarily (Other) --  -- since 0.6.2.0.-redirect :: Monad m => S.ByteString -> ActionT m ()+redirect :: Monad m => S.ByteString -> ActionT exts m () redirect to = do     v <- httpVersion <$> getRequest     if v == http11@@ -396,7 +402,7 @@ -- 302 Moved Temporarily (Other) -- -- since 0.3.3.0.-redirectTemporary :: Monad m => S.ByteString -> ActionT m ()+redirectTemporary :: Monad m => S.ByteString -> ActionT exts m () redirectTemporary to = do     v <- httpVersion <$> getRequest     if v == http11@@ -408,78 +414,78 @@ -- example(use pipes-wai) -- -- @--- producer :: Monad m => Producer (Flush Builder) IO () -> ActionT m ()+-- producer :: Monad m => Producer (Flush Builder) IO () -> ActionT exts m () -- producer = response (\s h -> responseProducer s h) -- @ ---rawResponse :: Monad m => (Status -> ResponseHeaders -> Response) -> ActionT m ()+rawResponse :: Monad m => (Status -> ResponseHeaders -> Response) -> ActionT exts m () rawResponse f = modifyState (\s -> s { actionResponse = ResponseFunc f } )  -- | reset response body to no response. since v0.15.2.-reset :: Monad m => ActionT m ()+reset :: Monad m => ActionT exts m () reset = modifyState (\s -> s { actionResponse = mempty } )  -- | set response body file content, without set Content-Type. since 0.1.0.0.-file' :: Monad m => FilePath -> Maybe FilePart -> ActionT m ()+file' :: Monad m => FilePath -> Maybe FilePart -> ActionT exts 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 :: Monad m => FilePath -> Maybe FilePart -> ActionT m ()+file :: Monad m => FilePath -> Maybe FilePart -> ActionT exts m () file f p = do     mime <- mimeType <$> getConfig     contentType (mime f)     file' f p  -- | append response body from builder. since 0.1.0.0.-builder :: Monad m => Builder -> ActionT m ()+builder :: Monad m => Builder -> ActionT exts m () builder b = modifyState (\s -> s { actionResponse = actionResponse s <> ResponseBuilder b } )  -- | append response body from strict bytestring. since 0.15.2.-bytes :: Monad m => S.ByteString -> ActionT m ()+bytes :: Monad m => S.ByteString -> ActionT exts m () bytes = builder . B.fromByteString  -- | append response body from lazy bytestring. since 0.15.2.-lazyBytes :: Monad m => L.ByteString -> ActionT m ()+lazyBytes :: Monad m => L.ByteString -> ActionT exts m () lazyBytes = builder . B.fromLazyByteString  -- | append response body from strict text. encoding UTF-8. since 0.15.2.-text :: Monad m => T.Text -> ActionT m ()+text :: Monad m => T.Text -> ActionT exts m () text = builder . B.fromText  -- | append response body from lazy text. encoding UTF-8. since 0.15.2.-lazyText :: Monad m => TL.Text -> ActionT m ()+lazyText :: Monad m => TL.Text -> ActionT exts m () lazyText = builder . B.fromLazyText  -- | append response body from show. encoding UTF-8. since 0.15.2.-showing :: (Monad m, Show a) => a -> ActionT m ()+showing :: (Monad m, Show a) => a -> ActionT exts m () showing = builder . B.fromShow  -- | append response body from string. encoding UTF-8. since 0.15.2.-string :: Monad m => String -> ActionT m ()+string :: Monad m => String -> ActionT exts m () string = builder . B.fromString  -- | append response body from char. encoding UTF-8. since 0.15.2.-char :: Monad m => Char -> ActionT m ()+char :: Monad m => Char -> ActionT exts m () char = builder . B.fromChar  -- | set response body source. since 0.9.0.0.-stream :: Monad m => StreamingBody -> ActionT m ()+stream :: Monad m => StreamingBody -> ActionT exts m () stream str = modifyState (\s -> s { actionResponse = ResponseStream str })  {-# DEPRECATED source "use stream" #-}-source :: Monad m => StreamingBody -> ActionT m ()+source :: Monad m => StreamingBody -> ActionT exts m () source = stream  {-# DEPRECATED redirectFound, redirectSeeOther "use redirect" #-} -- | redirect with 302 Found. since 0.3.3.0.-redirectFound       :: Monad m => S.ByteString -> ActionT m ()+redirectFound       :: Monad m => S.ByteString -> ActionT exts m () redirectFound       = redirectWith found302  -- | redirect with 303 See Other. since 0.3.3.0.-redirectSeeOther    :: Monad m => S.ByteString -> ActionT m ()+redirectSeeOther    :: Monad m => S.ByteString -> ActionT exts m () redirectSeeOther    = redirectWith seeOther303  {-# DEPRECATED lbs "use lazyBytes" #-} -- | append response body from lazy bytestring. since 0.1.0.0.-lbs :: Monad m => L.ByteString -> ActionT m ()+lbs :: Monad m => L.ByteString -> ActionT exts m () lbs = lazyBytes
src/Control/Monad/Apiary/Filter.hs view
@@ -12,7 +12,7 @@ module Control.Monad.Apiary.Filter (     -- * filters     -- ** http method-      method, Method(..)+      method     -- ** http version     , Control.Monad.Apiary.Filter.httpVersion     , http09, http10, http11@@ -28,7 +28,7 @@     , QueryKey(..), (??)     , query     -- *** specified operators-    , (=:), (=!:), (=?:), (?:), (=*:), (=+:)+    , (=:), (=!:), (=?:), (=?!:), (?:), (=*:), (=+:)     , hasQuery      -- ** header matcher@@ -37,6 +37,7 @@     , headers     , header     , header'+    , accept      -- ** other     , ssl@@ -47,8 +48,10 @@     ) where  import Network.Wai as Wai+import Network.Wai.Parse import qualified Network.HTTP.Types as HT +import Control.Applicative import Control.Monad import Control.Monad.Trans @@ -62,12 +65,11 @@ import Text.Blaze.Html import qualified Data.ByteString as S import qualified Data.ByteString.Char8 as SC+import qualified Data.Text.Encoding as T import Data.Monoid import Data.Proxy import Data.String-import Data.Reflection -import Data.Apiary.SList import Data.Apiary.Param import Data.Apiary.Document import Data.Apiary.Method@@ -78,40 +80,40 @@ -- method GET      -- stdmethod -- method \"HOGE\" -- non standard method -- @-method :: Monad n => Method -> ApiaryT c n m a -> ApiaryT c n m a+method :: Monad actM => Method -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () method m = focus' (DocMethod m) (Just m) id return  {-# DEPRECATED stdMethod "use method" #-} -- | filter by HTTP method using StdMethod. since 0.1.0.0.-stdMethod :: Monad n => Method -> ApiaryT c n m a -> ApiaryT c n m a+stdMethod :: Monad actM => Method -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () stdMethod = method  -- | filter by ssl accessed. since 0.1.0.0.-ssl :: Monad n => ApiaryT c n m a -> ApiaryT c n m a+ssl :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () ssl = function_ (DocPrecondition "SSL required") isSecure  -- | http version filter. since 0.5.0.0.-httpVersion :: Monad n => HT.HttpVersion -> Html -> ApiaryT c n m b -> ApiaryT c n m b+httpVersion :: Monad actM => HT.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 n => ApiaryT c n m b -> ApiaryT c n m b+http09 :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () http09 = Control.Monad.Apiary.Filter.httpVersion HT.http09 "HTTP/0.9 only"  -- | http/1.0 only accepted fiter. since 0.5.0.0.-http10 :: Monad n => ApiaryT c n m b -> ApiaryT c n m b+http10 :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () http10 = Control.Monad.Apiary.Filter.httpVersion HT.http10 "HTTP/1.0 only"  -- | http/1.1 only accepted fiter. since 0.5.0.0.-http11 :: Monad n => ApiaryT c n m b -> ApiaryT c n m b+http11 :: Monad actM => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () http11 = Control.Monad.Apiary.Filter.httpVersion HT.http11 "HTTP/1.1 only"  -- | filter by 'Control.Monad.Apiary.Action.rootPattern' of 'Control.Monad.Apiary.Action.ApiaryConfig'.-root :: (Functor m, Monad m, Monad n) => ApiaryT c n m b -> ApiaryT c n m b+root :: (Monad m, Monad actM) => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () root = focus' DocRoot Nothing (RootPath:) return  -- | match all subsequent path. since 0.15.0.-anyPath :: (Functor m, Monad m, Monad n) => ApiaryT c n m b -> ApiaryT c n m b+anyPath :: (Monad m, Monad actM) => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () anyPath = focus' id Nothing (AnyPath:) return  --------------------------------------------------------------------------------@@ -136,16 +138,16 @@ -- examples: -- -- @--- query "key" (Proxy :: Proxy ('First' Int)) -- get first \'key\' query parameter as Int.--- query "key" (Proxy :: Proxy ('Option' (Maybe Int)) -- get first \'key\' query parameter as Int. allow without param or value.--- query "key" (Proxy :: Proxy ('Many' String) -- get all \'key\' query parameter as String.+-- query "key" ('First'  :: First Int) -- get first \'key\' query parameter as Int.+-- query "key" ('Option' :: Option (Maybe Int)) -- get first \'key\' query parameter as Int. allow without param or value.+-- query "key" ('Many'   :: Many String) -- get all \'key\' query parameter as String. -- @-query :: forall a as w n m b proxy. -      (ReqParam a, Strategy.Strategy w, MonadIO n)+query :: forall exts prms actM a w m. +      (ReqParam a, Strategy.Strategy w, MonadIO actM)       => QueryKey-      -> proxy (w a)-      -> ApiaryT (Strategy.SNext w as a) n m b-      -> ApiaryT as n m b+      -> w a+      -> ApiaryT exts (Strategy.SNext w prms a) actM m ()+      -> ApiaryT exts prms actM m () query QueryKey{..} p =     focus doc $ \l -> do         r     <- getRequest@@ -153,17 +155,17 @@          maybe mzero return $             Strategy.readStrategy id ((queryKey ==) . fst) p -            (reqParams (Proxy :: Proxy a) r q f) l+            (reqParams p r q f) l   where-    doc = DocQuery queryKey (Strategy.strategyRep (Proxy :: Proxy w)) (reqParamRep (Proxy :: Proxy a)) queryDesc+    doc = DocQuery queryKey (Strategy.strategyRep p) (reqParamRep (Proxy :: Proxy a)) queryDesc  -- | get first matched paramerer. since 0.5.0.0. -- -- @--- "key" =: pInt == query "key" (pFirst pInt) == query "key" (Proxy :: Proxy (First Int))+-- "key" =: pInt == query "key" (pFirst pInt) == query "key" (First :: First Int) -- @-(=:) :: (MonadIO n, ReqParam a) => QueryKey -> proxy a -     -> ApiaryT (Snoc as a) n m b -> ApiaryT as n m b+(=:) :: (MonadIO actM, ReqParam p) => QueryKey -> proxy p+     -> ApiaryT exts (p ': prms) actM m () -> ApiaryT exts prms actM m () k =: t = query k (Strategy.pFirst t)  -- | get one matched paramerer. since 0.5.0.0.@@ -171,100 +173,117 @@ -- when more one parameger given, not matched. -- -- @--- "key" =: pInt == query "key" (pOne pInt) == query "key" (Proxy :: Proxy (One Int))+-- "key" =: pInt == query "key" (pOne pInt) == query "key" (One :: One Int) -- @-(=!:) :: (MonadIO n, ReqParam a) => QueryKey -> proxy a -      -> ApiaryT (Snoc as a) n m b -> ApiaryT as n m b+(=!:) :: (MonadIO actM, ReqParam p) => QueryKey -> proxy p+      -> ApiaryT exts (p ': prms) actM m () -> ApiaryT exts prms actM m () k =!: t = query k (Strategy.pOne t)  -- | get optional first paramerer. since 0.5.0.0. ----- when illegal type parameter given, fail mather(don't give Nothing).+-- when illegal type parameter given, fail match(don't give Nothing). -- -- @--- "key" =: pInt == query "key" (pOption pInt) == query "key" (Proxy :: Proxy (Option Int))+-- "key" =: pInt == query "key" (pOption pInt) == query "key" (Option :: Option Int) -- @-(=?:) :: (MonadIO n, ReqParam a) => QueryKey -> proxy a -      -> ApiaryT (Snoc as (Maybe a)) n m b -> ApiaryT as n m b+(=?:) :: (MonadIO actM, ReqParam p) => QueryKey -> proxy p+      -> ApiaryT exts (Maybe p ': prms) actM m () -> ApiaryT exts prms actM m () k =?: t = query k (Strategy.pOption t) +-- | get optional first paramerer with default. since 0.16.0.+--+-- when illegal type parameter given, fail match(don't give Nothing).+--+-- @+-- "key" =: (0 :: Int) == query "key" (pOptional (0 :: Int)) == query "key" (Optional 0 :: Optional Int)+-- @+(=?!:) :: (MonadIO actM, ReqParam p, Show p) => QueryKey -> p+       -> ApiaryT exts (p ': prms) actM m () -> ApiaryT exts prms actM m ()+k =?!: v = query k (Strategy.pOptional v)+ -- | check parameger given and type. since 0.5.0.0. -- -- If you wan't to allow any type, give 'pVoid'. -- -- @--- "key" =: pInt == query "key" (pCheck pInt) == query "key" (Proxy :: Proxy (Check Int))+-- "key" =: pInt == query "key" (pCheck pInt) == query "key" (Check :: Check Int) -- @-(?:) :: (MonadIO n, ReqParam a) => QueryKey -> proxy a -     -> ApiaryT as n m b -> ApiaryT as n m b+(?:) :: (MonadIO actM, ReqParam p) => QueryKey -> proxy p+     -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () k ?: t = query k (Strategy.pCheck t)  -- | get many paramerer. since 0.5.0.0. -- -- @--- "key" =: pInt == query "key" (pMany pInt) == query "key" (Proxy :: Proxy (Many Int))+-- "key" =: pInt == query "key" (pMany pInt) == query "key" (Many :: Many Int) -- @-(=*:) :: (MonadIO n, ReqParam a) => QueryKey -> proxy a -      -> ApiaryT (Snoc as [a]) n m b -> ApiaryT as n m b+(=*:) :: (MonadIO actM, ReqParam p) => QueryKey -> proxy p+      -> ApiaryT exts ([p] ': prms) actM m () -> ApiaryT exts prms actM m () k =*: t = query k (Strategy.pMany t)  -- | get some paramerer. since 0.5.0.0. -- -- @--- "key" =: pInt == query "key" (pSome pInt) == query "key" (Proxy :: Proxy (Some Int))+-- "key" =: pInt == query "key" (pSome pInt) == query "key" (Some :: Some Int) -- @-(=+:) :: (MonadIO n, ReqParam a) => QueryKey -> proxy a -      -> ApiaryT (Snoc as [a]) n m b -> ApiaryT as n m b+(=+:) :: (MonadIO actM, ReqParam p) => QueryKey -> proxy p+      -> ApiaryT exts ([p] ': prms) actM m () -> ApiaryT exts prms actM m () k =+: t = query k (Strategy.pSome t)  -- | query exists checker. -- -- @--- hasQuery q = 'query' q (Proxy :: Proxy ('Check' ()))+-- hasQuery q = 'query' q (Check :: 'Check' ()) -- @ ---hasQuery :: (MonadIO n) => QueryKey -> ApiaryT c n m a -> ApiaryT c n m a-hasQuery q = query q (Proxy :: Proxy (Strategy.Check ()))+hasQuery :: MonadIO actM => QueryKey -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m ()+hasQuery q = query q (Strategy.Check :: Strategy.Check ())  --------------------------------------------------------------------------------  -- | check whether to exists specified header or not. since 0.6.0.0.-hasHeader :: Monad n => HT.HeaderName -> ApiaryT as n m b -> ApiaryT as n m b+hasHeader :: Monad actM => HT.HeaderName -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () hasHeader n = header' Strategy.pCheck ((n ==) . fst) . Just $     toHtml (show n) <> " header requred"  -- | check whether to exists specified valued header or not. since 0.6.0.0.-eqHeader :: Monad n+eqHeader :: Monad actM          => HT.HeaderName           -> S.ByteString  -- ^ header value-         -> ApiaryT as n m b-         -> ApiaryT as n m b+         -> ApiaryT exts prms actM m ()+         -> ApiaryT exts prms actM m () eqHeader k v = header' Strategy.pCheck (\(k',v') -> k == k' && v == v') . Just $     mconcat [toHtml $ show k, " header == ", toHtml $ show v]  -- | filter by header and get first. since 0.6.0.0.-header :: Monad n => HT.HeaderName-       -> ApiaryT (Snoc as S.ByteString) n m b -> ApiaryT as n m b+header :: Monad actM => HT.HeaderName+       -> ApiaryT exts (S.ByteString ': prms) actM m () -> ApiaryT exts prms actM m () header n = header' Strategy.pFirst ((n ==) . fst) . Just $     toHtml (show n) <> " header requred"  -- | filter by headers up to 100 entries. since 0.6.0.0.-headers :: Monad n => HT.HeaderName-        -> ApiaryT (Snoc as [S.ByteString]) n m b -> ApiaryT as n m b-headers n = header' limit100 ((n ==) . fst) . Just $+headers :: Monad actM => HT.HeaderName+        -> ApiaryT exts ([S.ByteString] ': prms) actM m () -> ApiaryT exts prms actM m ()+headers n = header' (Strategy.pLimitSome 100) ((n ==) . fst) . Just $     toHtml (show n) <> " header requred"-  where-    limit100 :: Proxy x -> Proxy (Strategy.LimitSome $(int 100) x)-    limit100 _ = Proxy  -- | low level header filter. since 0.6.0.0.-header' :: (Strategy.Strategy w, Monad n)-        => (forall x. Proxy x -> Proxy (w x))+header' :: (Strategy.Strategy w, Monad actM)+        => (forall x. Proxy x -> w x)         -> (HT.Header -> Bool)         -> Maybe Html-        -> ApiaryT (Strategy.SNext w as S.ByteString) n m b-        -> ApiaryT as n m b+        -> ApiaryT exts (Strategy.SNext w prms S.ByteString) actM m ()+        -> ApiaryT exts prms actM m () header' pf kf d = function pc $ \l r ->     Strategy.readStrategy Just kf (pf pByteString) (requestHeaders r) l   where     pc = maybe id DocPrecondition d++-- | 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 (DocPrecondition $ "Accept: " <> toHtml (T.decodeUtf8 ect)) $ \c ->+    (lookup "Accept" . requestHeaders <$> getRequest) >>= \case+        Nothing -> mzero+        Just ct -> if ect == fst (parseContentType ct)+                   then contentType ect >> return c+                   else mzero
src/Control/Monad/Apiary/Filter/Internal.hs view
@@ -1,3 +1,6 @@+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE DataKinds #-}+ module Control.Monad.Apiary.Filter.Internal     ( function, function', function_, focus     ) where@@ -12,19 +15,19 @@ import Data.Apiary.Document  -- | low level filter function.-function :: Monad n => (Doc -> Doc)-         -> (SList c -> Request -> Maybe (SList c'))-         -> ApiaryT c' n m b -> ApiaryT c n m b+function :: Monad actM => (Doc -> Doc)+         -> (SList prms -> Request -> Maybe (SList prms'))+         -> ApiaryT exts prms' actM m () -> ApiaryT exts prms actM m () function d f = focus d $ \c -> getRequest >>= \r -> case f c r of     Nothing -> mzero     Just c' -> return c'  -- | filter and append argument.-function' :: Monad n => (Doc -> Doc) -> (Request -> Maybe a)-          -> ApiaryT (Snoc as a) n m b -> ApiaryT as n m b-function' d f = function d $ \c r -> sSnoc c `fmap` f r+function' :: Monad actM => (Doc -> Doc) -> (Request -> Maybe prm)+          -> ApiaryT exts (prm ': prms) actM m () -> ApiaryT exts prms actM m ()+function' d f = function d $ \c r -> (::: c) `fmap` f r  -- | filter only(not modify arguments).-function_ :: Monad n => (Doc -> Doc) -> (Request -> Bool) -          -> ApiaryT c n m b -> ApiaryT c n m b+function_ :: Monad actM => (Doc -> Doc) -> (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
@@ -26,17 +26,18 @@ import Text.Blaze.Html  -- | check first path and drill down. since 0.11.0.-path :: Monad n => T.Text -> ApiaryT c n m a -> ApiaryT c n m a+path :: Monad actM => T.Text -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () path p = focus' (DocPath p) Nothing (Exact p:) return  -- | check consumed paths. since 0.11.1.-endPath :: (Functor n, Monad n) => ApiaryT c n m a -> ApiaryT c n m a+endPath :: (Monad actM) => ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () endPath = focus' id Nothing (EndPath:) return  -- | get first path and drill down. since 0.11.0.-fetch :: (Path a, Functor n, Monad n) => proxy a -> Maybe Html -> ApiaryT (Snoc as a) n m b -> ApiaryT as n m b+fetch :: (Path p, Monad actM) => proxy p -> Maybe Html+      -> ApiaryT exts (p ': prms) actM m () -> ApiaryT exts prms actM m () fetch p h = focus' (DocFetch (pathRep p) h) Nothing (FetchPath:) $ \l -> liftM actionFetches getState >>= \case     []   -> mzero     f:fs -> case readPathAs p f of-        Just r  -> sSnoc l r <$ modifyState (\s -> s {actionFetches = fs})+        Just r  -> (r ::: l) <$ modifyState (\s -> s {actionFetches = fs})         Nothing -> mzero
src/Control/Monad/Apiary/Filter/Internal/Capture/TH.hs view
@@ -10,6 +10,7 @@ import qualified Control.Monad.Apiary.Filter.Internal.Capture as Capture  import qualified Data.Text as T+import Data.String import Data.Proxy  preCap :: String -> [String]@@ -50,7 +51,7 @@             N n  -> [|Just $(varE n)|]     [|Capture.fetch (Proxy :: Proxy $(conT ty)) $d . $(mkCap as)|] mkCap (eq:as) = do-    [|(Capture.path $(stringE eq)) . $(mkCap as) |]+    [|(Capture.path (fromString $(stringE eq))) . $(mkCap as) |]  -- | capture QuasiQuoter. since 0.1.0.0. --
src/Control/Monad/Apiary/Filter/Internal/Strategy.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE ScopedTypeVariables #-}-+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE CPP #-}@@ -13,7 +13,6 @@ module Control.Monad.Apiary.Filter.Internal.Strategy where  import Data.Maybe-import Data.Reflection import qualified Data.Text as T  import Data.Apiary.Proxy@@ -24,93 +23,100 @@     type SNext w (as :: [*]) a  :: [*]     readStrategy :: (v -> Maybe a)                  -> ((k,v) -> Bool)-                 -> proxy (w a)+                 -> w a                  -> [(k, v)]                  -> SList as                   -> Maybe (SList (SNext w as a))-    strategyRep :: proxy w -> StrategyRep+    strategyRep :: forall a. w a -> StrategyRep -getQuery :: (v -> Maybe a) -> proxy (w a) -> ((k,v) -> Bool) -> [(k, v)] -> [Maybe a]+getQuery :: (v -> Maybe a) -> w a -> ((k,v) -> Bool) -> [(k, v)] -> [Maybe a] getQuery readf _ kf = map readf . map snd . filter kf  -- | get first matched key( [0,) params to Type.). since 0.5.0.0.-data Option a deriving Typeable+data Option a = Option deriving Typeable instance Strategy Option where-    type SNext Option as a = Snoc as (Maybe a)+    type SNext Option as a = Maybe a ': as     readStrategy rf k p q l =         let rs = getQuery rf p k q         in if any isNothing rs            then Nothing-           else Just . sSnoc l $ case catMaybes rs of-               []  -> Nothing+           else Just . (::: l) $ case catMaybes rs of                a:_ -> Just a+               []  -> Nothing     strategyRep _ = StrategyRep "optional" +data Optional a = Optional T.Text a deriving Typeable+instance Strategy Optional where+    type SNext Optional as a = a ': as+    readStrategy rf k p@(Optional _ def) q l =+        let rs = getQuery rf p k q+        in if any isNothing rs+           then Nothing+           else Just . (::: l) $ case catMaybes rs of+               a:_ -> a+               []  -> def+    strategyRep (Optional tr _) = StrategyRep $+        "default:" `T.append` tr+ -- | get first matched key ( [1,) params to Maybe Type.) since 0.5.0.0.-data First a deriving Typeable+data First a = First deriving Typeable instance Strategy First where-    type SNext First as a = Snoc as a+    type SNext First as a = a ': as     readStrategy rf k p q l =         case getQuery rf p k q of-            Just a:_ -> Just $ sSnoc l a+            Just a:_ -> Just $ a ::: l             _        -> Nothing     strategyRep _ = StrategyRep "first"  -- | get key ( [1,1] param to Type.) since 0.5.0.0.-data One a deriving Typeable+data One a = One deriving Typeable instance Strategy One where-    type SNext One as a = Snoc as a+    type SNext One as a = a ': as     readStrategy rf k p q l =         case getQuery rf p k q of-            [Just a] -> Just $ sSnoc l a+            [Just a] -> Just $ a ::: l             _        -> Nothing     strategyRep _ = StrategyRep "one"  -- | get parameters ( [0,) params to [Type] ) since 0.5.0.0.-data Many a deriving Typeable+data Many a = Many deriving Typeable instance Strategy Many where-    type SNext Many as a = Snoc as [a]+    type SNext Many as a = [a] ': as     readStrategy rf k p q l =         let rs = getQuery rf p k q         in if any isNothing rs            then Nothing-           else Just $ sSnoc l (catMaybes rs)+           else Just $ (catMaybes rs) ::: l     strategyRep _ = StrategyRep "many"  -- | get parameters ( [1,) params to [Type] ) since 0.5.0.0.-data Some a deriving Typeable+data Some a = Some deriving Typeable instance Strategy Some where-    type SNext Some as a = Snoc as [a]+    type SNext Some as a = [a] ': as     readStrategy rf k p q l =         let rs = getQuery rf p k q         in if any isNothing rs            then Nothing            else case catMaybes rs of                [] -> Nothing-               as -> Just $ sSnoc l as+               as -> Just $ as ::: l     strategyRep _ = StrategyRep "some"  -- | get parameters with upper limit ( [1,n] to [Type]) since 0.6.0.0.-data LimitSome u a deriving Typeable-instance (Reifies u Int) => Strategy (LimitSome u) where-    type SNext (LimitSome u) as a = Snoc as [a]-    readStrategy rf k p q l =-        let rs = take (reflectLimit p) $ getQuery rf p k q+data LimitSome a = LimitSome {-# UNPACK #-} !Int deriving Typeable+instance Strategy LimitSome where+    type SNext LimitSome as a = [a] ': as+    readStrategy rf k p@(LimitSome lim) q l =+        let rs = take lim $ getQuery rf p k q         in if any isNothing rs            then Nothing            else case catMaybes rs of                [] -> Nothing-               as -> Just $ sSnoc l as-    strategyRep _ = StrategyRep . T.pack $ "less then " ++ show (reflect (Proxy :: Proxy u))--reflectLimit :: Reifies n Int => proxy (LimitSome n a) -> Int-reflectLimit p = reflect $ asTyInt p-  where-    asTyInt :: proxy (LimitSome u a) -> Proxy u-    asTyInt _ = Proxy+               as -> Just $ as ::: l+    strategyRep (LimitSome lim) = StrategyRep . T.pack $ "less then " ++ show lim  -- | type check ( [0,) params to No argument ) since 0.5.0.0.-data Check a deriving Typeable+data Check a = Check deriving Typeable instance Strategy Check where     type SNext Check as a = as     readStrategy rf k p q l =@@ -123,25 +129,33 @@     strategyRep _ = StrategyRep "check"  -- | construct Option proxy. since 0.5.1.0.-pOption :: proxy a -> Proxy (Option a)-pOption _ = Proxy+pOption :: proxy a -> Option a+pOption _ = Option +-- | construct Optional proxy. since 0.16.0.+pOptional :: Show a => a -> Optional a+pOptional def = Optional (T.pack $ show def) def+ -- | construct First proxy. since 0.5.1.0.-pFirst :: proxy a -> Proxy (First a)-pFirst _ = Proxy+pFirst :: proxy a -> First a+pFirst _ = First  -- | construct One proxy. since 0.5.1.0.-pOne :: proxy a -> Proxy (One a)-pOne _ = Proxy+pOne :: proxy a -> One a+pOne _ = One  -- | construct Many proxy. since 0.5.1.0.-pMany :: proxy a -> Proxy (Many a)-pMany _ = Proxy+pMany :: proxy a -> Many a+pMany _ = Many  -- | construct Some proxy. since 0.5.1.0.-pSome :: proxy a -> Proxy (Some a)-pSome _ = Proxy+pSome :: proxy a -> Some a+pSome _ = Some +-- | construct LimitSome proxy. since 0.16.0.+pLimitSome :: Int -> proxy a -> LimitSome a+pLimitSome lim _ = LimitSome lim+ -- | construct Check proxy. since 0.5.1.0.-pCheck :: proxy a -> Proxy (Check a)-pCheck _ = Proxy+pCheck :: proxy a -> Check a+pCheck _ = Check
src/Control/Monad/Apiary/Internal.hs view
@@ -12,6 +12,7 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ConstraintKinds #-}  module Control.Monad.Apiary.Internal where @@ -20,40 +21,42 @@ import Control.Applicative import Control.Monad import Control.Monad.Trans-import Control.Monad.Identity import Control.Monad.Trans.Control import Control.Monad.Base import Control.Monad.Apiary.Action.Internal  import Data.List import Data.Apiary.SList+import Data.Apiary.Extension+import Data.Apiary.Extension.Internal import Data.Apiary.Document-import Data.Monoid+import Data.Monoid hiding (All) import Text.Blaze.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 n = Router-    { children   :: H.HashMap T.Text (Router n)-    , capturing  :: Maybe (Router n)-    , anyMatch   :: Maybe (PathMethod n)-    , pathMethod :: PathMethod n+data Router exts actM = Router+    { children   :: H.HashMap T.Text (Router exts actM)+    , capturing  :: Maybe (Router exts actM)+    , anyMatch   :: Maybe (PathMethod exts actM)+    , pathMethod :: PathMethod exts actM     } -data PathMethod n = PathMethod-    { methodMap :: H.HashMap S.ByteString (ActionT n ())-    , anyMethod :: Maybe (ActionT n ())+data PathMethod exts actM = PathMethod+    { methodMap :: H.HashMap S.ByteString (ActionT exts actM ())+    , anyMethod :: Maybe (ActionT exts actM ())     } -emptyRouter :: Router n+emptyRouter :: Router exts actM emptyRouter = Router H.empty Nothing Nothing emptyPathMethod -emptyPathMethod :: PathMethod n+emptyPathMethod :: PathMethod exts actM emptyPathMethod = PathMethod H.empty Nothing -insertRouter :: Monad n => [T.Text] -> Maybe S.ByteString -> [PathElem] -> ActionT n () -> Router n -> Router n+insertRouter :: Monad actM => [T.Text] -> Maybe S.ByteString -> [PathElem]+             -> ActionT exts actM () -> Router exts actM -> Router exts actM insertRouter rootPat mbMethod paths act = loop paths   where     loop [EndPath] (Router cln cap anp pm) =@@ -82,41 +85,41 @@               | EndPath               | AnyPath -data ApiaryEnv n c = ApiaryEnv-    { envFilter :: ActionT n (SList c)+data ApiaryEnv exts prms actM = ApiaryEnv+    { envFilter :: ActionT exts actM (SList prms)     , envMethod :: Maybe Method     , envPath   :: [PathElem] -> [PathElem]     , envConfig :: ApiaryConfig     , envDoc    :: Doc -> Doc+    , envExts   :: Extensions exts     } -initialEnv :: Monad n => ApiaryConfig -> ApiaryEnv n '[]-initialEnv conf = ApiaryEnv (return SNil) Nothing id conf id+initialEnv :: Monad actM => Extensions exts -> ApiaryConfig -> ApiaryEnv exts '[] actM+initialEnv exts conf = ApiaryEnv (return SNil) Nothing id conf id exts -data ApiaryWriter n = ApiaryWriter-    { writerRouter :: Router n -> Router n+data ApiaryWriter exts actM = ApiaryWriter+    { writerRouter :: Router exts actM -> Router exts actM     , writerDoc    :: [Doc] -> [Doc]+    , writerMw     :: Middleware     } -instance Monoid (ApiaryWriter n) where-    mempty = ApiaryWriter id id-    ApiaryWriter ra da `mappend` ApiaryWriter rb db = ApiaryWriter (ra . rb) (da . db)+instance Monoid (ApiaryWriter exts actM) where+    mempty = ApiaryWriter id id id+    ApiaryWriter ra da am `mappend` ApiaryWriter rb db bm+        = ApiaryWriter (ra . rb) (da . db) (am . bm)  -- | most generic Apiary monad. since 0.8.0.0.-newtype ApiaryT c n m a = ApiaryT { unApiaryT :: forall b.-    ApiaryEnv n c-    -> (a -> ApiaryWriter n -> m b)+newtype ApiaryT exts prms actM m a = ApiaryT { unApiaryT :: forall b.+    ApiaryEnv exts prms actM+    -> (a -> ApiaryWriter exts actM -> m b)     -> m b      } apiaryT :: Monad m-        => (ApiaryEnv n c -> m (a, ApiaryWriter n))-        -> ApiaryT c n m a+        => (ApiaryEnv exts prms actM -> m (a, ApiaryWriter exts actM))+        -> ApiaryT exts prms actM m a apiaryT f = ApiaryT $ \rdr cont -> f rdr >>= \(a,w) -> cont a w --- | no transformer. (ActionT IO, ApiaryT Identity)-type Apiary c = ApiaryT c IO Identity--routerToAction :: Monad n => Router n -> ActionT n ()+routerToAction :: Monad actM => Router exts actM -> ActionT exts actM () routerToAction router = getRequest >>= go   where     go req = loop id router (pathInfo req)@@ -140,23 +143,33 @@                 Nothing -> nxt                 Just cd -> loop fch cd ps `mplus` nxt -runApiaryT :: (Monad n, Monad m) => (forall b. n b -> IO b) -> ApiaryConfig-           -> ApiaryT '[] n m a -> m Application-runApiaryT run conf m = unApiaryT m (initialEnv conf) (\_ w -> return w) >>= \wtr -> do+runApiaryTWith :: (Monad actM, Monad m) => Initializer '[] m exts+               -> ApiaryConfig -> (forall b. actM b -> IO b) -> ApiaryT exts '[] actM m () -> m Application+runApiaryTWith (Initializer ir) conf run m = do+    exts <- ir NoExtension+    wtr  <- unApiaryT m (initialEnv exts conf) (\_ w -> return w)     let doc = docsToDocuments $ writerDoc wtr []         rtr = writerRouter wtr emptyRouter-    return $! execActionT conf doc (hoistActionT run $ routerToAction rtr)+        mw  = writerMw wtr+    return $! mw $ execActionT conf exts doc (hoistActionT run $ routerToAction rtr) -runApiary :: ApiaryConfig -> Apiary '[] a -> Application-runApiary conf m = runIdentity $ runApiaryT id conf m+runApiaryWith :: Monad m => Initializer '[] m exts+              -> ApiaryConfig -> ApiaryT exts '[] IO m () -> m Application+runApiaryWith ef conf m = runApiaryTWith ef conf id m +runApiary :: Monad m => ApiaryConfig -> ApiaryT '[] '[] IO m () -> m Application+runApiary = runApiaryWith noExtension++server :: Monad m => (Application -> m a) -> m Application -> m a+server = (=<<)+ -------------------------------------------------------------------------------- -instance Functor (ApiaryT c n m) where+instance Functor (ApiaryT exts prms actM m) where     fmap f m = ApiaryT $ \env cont ->         unApiaryT m env $ \a hdr -> hdr `seq` cont (f a) hdr -instance Monad n => Applicative (ApiaryT c n m) where+instance Monad actM => Applicative (ApiaryT exts prms actM m) where     pure x = ApiaryT $ \_ cont -> cont x mempty     mf <*> ma = ApiaryT $ \env cont ->         unApiaryT mf env $ \f hdr  ->@@ -164,7 +177,7 @@         let hdr'' = hdr <> hdr'         in hdr'' `seq` cont (f a) hdr'' -instance Monad n => Monad (ApiaryT c n m) where+instance Monad actM => Monad (ApiaryT exts prms actM m) where     return x = ApiaryT $ \_ cont -> cont x mempty     m >>= k = ApiaryT $ \env cont ->         unApiaryT    m  env $ \a hdr  ->@@ -172,51 +185,54 @@         let hdr'' = hdr <> hdr'         in hdr'' `seq` cont b hdr'' -instance Monad n => MonadTrans (ApiaryT c n) where+instance Monad actM => MonadTrans (ApiaryT exts prms actM) where     lift m = ApiaryT $ \_ c -> m >>= \a -> c a mempty -instance (Monad n, MonadIO m) => MonadIO (ApiaryT c n m) where+instance (Monad actM, MonadIO m) => MonadIO (ApiaryT exts prms actM m) where     liftIO m = ApiaryT $ \_ c -> liftIO m >>= \a -> c a mempty -instance (Monad n, MonadBase b m) => MonadBase b (ApiaryT c n m) where+instance (Monad actM, MonadBase b m) => MonadBase b (ApiaryT exts prms actM m) where     liftBase m = ApiaryT $ \_ c -> liftBase m >>= \a -> c a mempty -instance Monad n => MonadTransControl (ApiaryT c n) where-    newtype StT (ApiaryT c n) a = StTApiary' { unStTApiary' :: (a, ApiaryWriter n) }+instance Monad actM => MonadTransControl (ApiaryT exts prms actM) where+    newtype StT (ApiaryT exts prms actM) a = StTApiary' { unStTApiary' :: (a, ApiaryWriter exts actM) }     liftWith f = apiaryT $ \env ->         liftM (\a -> (a, mempty))          (f $ \t -> liftM StTApiary' $ unApiaryT t env (\a w -> return (a,w)))     restoreT m = apiaryT $ \_ -> liftM unStTApiary' m -instance (Monad n, MonadBaseControl b m) => MonadBaseControl b (ApiaryT c n m) where-    newtype StM (ApiaryT c n m) a = StMApiary' { unStMApiary' :: ComposeSt (ApiaryT c n) m a }+instance (Monad actM, MonadBaseControl b m) => MonadBaseControl b (ApiaryT exts prms actM m) where+    newtype StM (ApiaryT exts prms actM m) a = StMApiary' { unStMApiary' :: ComposeSt (ApiaryT exts prms actM) m a }     liftBaseWith = defaultLiftBaseWith StMApiary'     restoreM     = defaultRestoreM   unStMApiary'  -------------------------------------------------------------------------------- -getApiaryEnv :: Monad n => ApiaryT c n m (ApiaryEnv n c)+getApiaryEnv :: Monad actM => ApiaryT exts prms actM m (ApiaryEnv exts prms actM) getApiaryEnv = ApiaryT $ \env cont -> cont env mempty -apiaryConfig :: Monad n => ApiaryT c n m ApiaryConfig+apiaryConfig :: Monad actM => ApiaryT exts prms actM m ApiaryConfig apiaryConfig = liftM envConfig getApiaryEnv -addRoute :: Monad n => ApiaryWriter n -> ApiaryT c n m ()+apiaryExt :: (Has e exts, Monad actM) => proxy e -> ApiaryT exts prms actM m e+apiaryExt p = liftM (getExtension p . envExts) getApiaryEnv++addRoute :: Monad actM => ApiaryWriter exts actM -> ApiaryT exts prms actM m () addRoute r = ApiaryT $ \_ cont -> cont () r  -- | filter by action. since 0.6.1.0.-focus :: Monad n+focus :: Monad actM       => (Doc -> Doc)-      -> (SList c -> ActionT n (SList c'))-      -> ApiaryT c' n m a -> ApiaryT c n m a+      -> (SList prms -> ActionT exts actM (SList prms'))+      -> ApiaryT exts prms' actM m () -> ApiaryT exts prms actM m () focus d g m = focus' d Nothing id g m -focus' :: Monad n+focus' :: Monad actM        => (Doc -> Doc)        -> Maybe Method        -> ([PathElem] -> [PathElem])-       -> (SList c -> ActionT n (SList c'))-       -> ApiaryT c' n m a -> ApiaryT c n m a+       -> (SList prms -> ActionT exts actM (SList prms'))+       -> ApiaryT exts prms' actM m () -> ApiaryT exts prms actM m () focus' d meth pth g m = ApiaryT $ \env cont -> unApiaryT m env      { envFilter = envFilter env >>= g      , envMethod = maybe (envMethod env) Just meth@@ -225,11 +241,11 @@     } cont  -- | splice ActionT ApiaryT.-action :: Monad n => Fn c (ActionT n ()) -> ApiaryT c n m ()+action :: Monad actM => Fn prms (ActionT exts actM ()) -> ApiaryT exts prms actM m () action = action' . apply  -- | like action. but not apply arguments. since 0.8.0.0.-action' :: Monad n => (SList c -> ActionT n ()) -> ApiaryT c n m ()+action' :: Monad actM => (SList prms -> ActionT exts actM ()) -> ApiaryT exts prms actM m () action' a = do     env <- getApiaryEnv     addRoute $ ApiaryWriter@@ -237,39 +253,43 @@             (rootPattern $ envConfig env)             (renderMethod <$> envMethod env)             (envPath env [])-            (envFilter env >>= \c -> a c))+            (envFilter env >>= \prms -> a prms))         (envDoc env Action:)+        id++middleware :: Monad actM => Middleware -> ApiaryT exts prms actM m ()+middleware mw = addRoute (ApiaryWriter id id mw)+ -------------------------------------------------------------------------------- -insDoc :: (Doc -> Doc) -> ApiaryT c n m a -> ApiaryT c n m a+insDoc :: (Doc -> Doc) -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () insDoc d m = ApiaryT $ \env cont -> unApiaryT m env     { envDoc = envDoc env . d } cont  -- | API document group. since 0.12.0.0. -- -- only top level group recognized.-group :: T.Text -> ApiaryT c n m a -> ApiaryT c n m a+group :: T.Text -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () group = insDoc . DocGroup  -- | add API document. since 0.12.0.0. -- -- It use only filters prior document, -- so you should be placed document directly in front of action.-document :: T.Text -> ApiaryT c n m a -> ApiaryT c n m a+document :: T.Text -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () document = insDoc . Document  -- | add user defined precondition. since 0.13.0.-precondition :: Html -> ApiaryT c n m a -> ApiaryT c n m a+precondition :: Html -> ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () precondition = insDoc . DocPrecondition -noDoc :: ApiaryT c n m a -> ApiaryT c n m a+noDoc :: ApiaryT exts prms actM m () -> ApiaryT exts prms actM m () noDoc = insDoc DocDropNext  --------------------------------------------------------------------------------  {-# DEPRECATED actionWithPreAction "use action'" #-} -- | execute action before main action. since 0.4.2.0-actionWithPreAction :: Monad n => (SList xs -> ActionT n a)-                    -> Fn xs (ActionT n ()) -> ApiaryT xs n m ()-actionWithPreAction pa a = do-    action' $ \c -> pa c >> apply a c+actionWithPreAction :: Monad actM => (SList xs -> ActionT exts actM a)+                    -> Fn xs (ActionT exts actM ()) -> ApiaryT exts xs actM m ()+actionWithPreAction pa a = action' $ \prms -> pa prms >> apply a prms
+ src/Data/Apiary/Extension.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ConstraintKinds #-}++module Data.Apiary.Extension+    ( Has(getExtension)+    , Extensions+    , addExtension+    , Initializer, Initializer'+    , initializer, preAction, (+>)+    , noExtension+    ) where++import Data.Apiary.Extension.Internal++type Initializer' m a = forall i. Initializer i m (a ': i)++addExtension :: e -> Extensions es -> Extensions (e ': es)+addExtension = AddExtension++initializer :: Monad m => m e -> Initializer' m e+initializer m = Initializer $ \e -> do+    a <- m+    return (addExtension a e)++preAction :: Monad m => m a -> Initializer i m i+preAction f = Initializer $ \e -> f >> return e++(+>) :: Monad m => Initializer i m x -> Initializer x m o -> Initializer i m o+Initializer a +> Initializer b = Initializer $ \e -> a e >>= b++noExtension :: Monad m => Initializer '[] m '[]+noExtension = Initializer $ return
+ src/Data/Apiary/Extension/Internal.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverlappingInstances #-}+{-# LANGUAGE TypeOperators #-}++module Data.Apiary.Extension.Internal where++newtype Initializer i m o = Initializer +    {unInitializer :: Extensions i -> m (Extensions o)}++data Extensions (es :: [*]) where+    NoExtension  :: Extensions '[]+    AddExtension :: (e :: *) -> Extensions es -> Extensions (e ': es)++class Has a (as :: [*]) where+    getExtension :: proxy a -> Extensions as -> a++instance Has a (a ': as) where+    getExtension _ (AddExtension a _) = a++instance Has a as => Has a (a' ': as) where+    getExtension p (AddExtension _ as) = getExtension p as+
src/Data/Apiary/Param.hs view
@@ -18,12 +18,15 @@  import Network.Wai +import Control.Monad+ import Data.Int import Data.Word import Data.Proxy import Data.Apiary.Proxy  import Data.String(IsString)+import Data.Time.Calendar import qualified Data.Text.Read as TR import Data.Text.Encoding.Error import qualified Data.Text as T@@ -63,12 +66,12 @@     | Check     deriving (Show, Eq) -class Typeable a => Path a where+class Path a where     readPath :: T.Text  -> Maybe a     pathRep  :: proxy a -> TypeRep-    pathRep = typeRep  instance Path Char where+    pathRep = typeRep     readPath s         | T.null s  = Nothing         | otherwise = Just $ T.head s@@ -89,23 +92,23 @@  -- | javascript boolean. -- when \"false\", \"0\", \"-0\", \"\", \"null\", \"undefined\", \"NaN\" then False, else True. since 0.6.0.0.-instance Path Bool    where readPath = Just . jsToBool+instance Path Bool    where readPath = Just . jsToBool; pathRep = typeRep -instance Path Int     where readPath = readTextInt-instance Path Int8    where readPath = readTextInt-instance Path Int16   where readPath = readTextInt-instance Path Int32   where readPath = readTextInt-instance Path Int64   where readPath = readTextInt-instance Path Integer where readPath = readTextInt+instance Path Int     where readPath = readTextInt; pathRep = typeRep+instance Path Int8    where readPath = readTextInt; pathRep = typeRep+instance Path Int16   where readPath = readTextInt; pathRep = typeRep+instance Path Int32   where readPath = readTextInt; pathRep = typeRep+instance Path Int64   where readPath = readTextInt; pathRep = typeRep+instance Path Integer where readPath = readTextInt; pathRep = typeRep -instance Path Word    where readPath = readTextWord-instance Path Word8   where readPath = readTextWord-instance Path Word16  where readPath = readTextWord-instance Path Word32  where readPath = readTextWord-instance Path Word64  where readPath = readTextWord+instance Path Word    where readPath = readTextWord; pathRep = typeRep+instance Path Word8   where readPath = readTextWord; pathRep = typeRep+instance Path Word16  where readPath = readTextWord; pathRep = typeRep+instance Path Word32  where readPath = readTextWord; pathRep = typeRep+instance Path Word64  where readPath = readTextWord; pathRep = typeRep -instance Path Double  where readPath = readTextDouble-instance Path Float   where readPath = fmap realToFrac . readTextDouble+instance Path Double  where readPath = readTextDouble; pathRep = typeRep+instance Path Float   where readPath = fmap realToFrac . readTextDouble; pathRep = typeRep  instance Path  T.Text      where readPath = Just;                 pathRep _ = typeRep (Proxy :: Proxy Text) instance Path TL.Text      where readPath = Just . TL.fromStrict; pathRep _ = typeRep (Proxy :: Proxy Text)@@ -113,14 +116,14 @@ instance Path L.ByteString where readPath = Just . TL.encodeUtf8 . TL.fromStrict; pathRep _ = typeRep (Proxy :: Proxy Text) instance Path String       where readPath = Just . T.unpack;      pathRep _ = typeRep (Proxy :: Proxy Text) + -------------------------------------------------------------------------------- -class Typeable a => Query a where+class Query a where     readQuery :: Maybe S.ByteString -> Maybe a     queryRep  :: proxy a            -> QueryRep     queryRep = Strict . qTypeRep     qTypeRep  :: proxy a            -> TypeRep-    qTypeRep = typeRep  readBS :: (S.ByteString -> Maybe (a, S.ByteString))        -> S.ByteString -> Maybe a@@ -139,25 +142,25 @@  -- | javascript boolean. -- when \"false\", \"0\", \"-0\", \"\", \"null\", \"undefined\", \"NaN\" then False, else True. since 0.6.0.0.-instance Query Bool    where readQuery = fmap jsToBool+instance Query Bool    where readQuery = fmap jsToBool; qTypeRep = typeRep -instance Query Int     where readQuery = maybe Nothing readBSInt-instance Query Int8    where readQuery = maybe Nothing readBSInt-instance Query Int16   where readQuery = maybe Nothing readBSInt-instance Query Int32   where readQuery = maybe Nothing readBSInt-instance Query Int64   where readQuery = maybe Nothing readBSInt-instance Query Integer where readQuery = maybe Nothing readBSInt+instance Query Int     where readQuery = maybe Nothing readBSInt; qTypeRep = typeRep+instance Query Int8    where readQuery = maybe Nothing readBSInt; qTypeRep = typeRep+instance Query Int16   where readQuery = maybe Nothing readBSInt; qTypeRep = typeRep+instance Query Int32   where readQuery = maybe Nothing readBSInt; qTypeRep = typeRep+instance Query Int64   where readQuery = maybe Nothing readBSInt; qTypeRep = typeRep+instance Query Integer where readQuery = maybe Nothing readBSInt; qTypeRep = typeRep -instance Query Word    where readQuery = maybe Nothing readBSWord-instance Query Word8   where readQuery = maybe Nothing readBSWord-instance Query Word16  where readQuery = maybe Nothing readBSWord-instance Query Word32  where readQuery = maybe Nothing readBSWord-instance Query Word64  where readQuery = maybe Nothing readBSWord+instance Query Word    where readQuery = maybe Nothing readBSWord; qTypeRep = typeRep+instance Query Word8   where readQuery = maybe Nothing readBSWord; qTypeRep = typeRep+instance Query Word16  where readQuery = maybe Nothing readBSWord; qTypeRep = typeRep+instance Query Word32  where readQuery = maybe Nothing readBSWord; qTypeRep = typeRep+instance Query Word64  where readQuery = maybe Nothing readBSWord; qTypeRep = typeRep -instance Query Double  where readQuery = maybe Nothing readBSDouble-instance Query Float   where readQuery = maybe Nothing (fmap realToFrac . readBSDouble)+instance Query Double  where readQuery = maybe Nothing readBSDouble; qTypeRep = typeRep+instance Query Float   where readQuery = maybe Nothing (fmap realToFrac . readBSDouble); qTypeRep = typeRep -instance Query T.Text  where+instance Query T.Text where     readQuery  = fmap $ T.decodeUtf8With lenientDecode     qTypeRep _ = typeRep (Proxy :: Proxy Text) @@ -173,15 +176,57 @@     readQuery  = fmap L.fromStrict     qTypeRep _ = typeRep (Proxy :: Proxy Text) -instance Query String       where+instance Query String where     readQuery  = fmap S.unpack     qTypeRep _ = typeRep (Proxy :: Proxy Text) +-- | fuzzy date parse. three decimal split by 1 char.+-- if year < 100 then + 2000. since 0.16.0.+--+-- example:+--+-- * 2014-02-05+-- * 14-2-5+-- * 14.2.05+instance Query Day where+    readQuery = (>>= \s0 -> do+        (y, s1) <- SL.readDecimal s0+        when (S.null s1) Nothing+        (m, s2) <- SL.readDecimal (S.tail s1)+        when (S.null s2) Nothing+        (d, s3) <- SL.readDecimal (S.tail s2)+        unless (S.null s3) Nothing+        let y' = if y < 100 then 2000 + y else y+        return $ fromGregorian y' m d)+    qTypeRep _ = typeRep (Proxy :: Proxy Day)++-- | fuzzy date parse. three decimal split by 1 char.+-- if year < 100 then + 2000. since 0.16.0.+--+-- example:+--+-- * 2014-02-05+-- * 14-2-5+-- * 14.2.05+instance Path Day where+    readPath s0 = either (const Nothing) Just $ do+        (y, s1) <- TR.decimal s0+        when (T.null s1) (Left "")+        (m, s2) <- TR.decimal (T.tail s1)+        when (T.null s2) (Left "")+        (d, s3) <- TR.decimal (T.tail s2)+        unless (T.null s3) (Left "")+        let y' = if y < 100 then 2000 + y else y+        return $ fromGregorian y' m d+    pathRep _ = typeRep (Proxy :: Proxy Day)+ -- | allow no parameter. but check parameter type. instance Query a => Query (Maybe a) where     readQuery (Just a) = Just `fmap` readQuery (Just a)     readQuery Nothing  = Just Nothing     queryRep _         = Nullable $ qTypeRep (Proxy :: Proxy a)+    qTypeRep _         = maybeCon `mkTyConApp` [qTypeRep (Proxy :: Proxy a)]+      where maybeCon = typeRepTyCon $ typeOf (Nothing :: Maybe ())  -- | always success. for check existence. instance Query () where
src/Data/Apiary/SList.hs view
@@ -6,6 +6,9 @@ {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverlappingInstances #-}  module Data.Apiary.SList where @@ -17,28 +20,24 @@  infixr ::: -deriving instance All Show as => Show (SList as)--type family Fn (as :: [*]) r-type instance Fn '[] r = r-type instance Fn (x ': xs) r = x -> Fn xs r--type family Snoc (as :: [*]) a :: [*]-type instance Snoc '[] a = a ': '[]-type instance Snoc (x ': xs) a = x ': Snoc xs a- type family All (c :: * -> Constraint) (as :: [*]) :: Constraint type instance All c '[] = () type instance All c (a ': as) = (c a, All c as) -apply :: Fn xs r -> SList xs -> r-apply v SNil = v-apply f (a ::: as) = apply (f a) as+deriving instance All Show as => Show (SList as) -sSnoc :: SList as -> a -> SList (Snoc as a)-sSnoc SNil       a = a ::: SNil-sSnoc (x ::: xs) a = x ::: sSnoc xs a+type family Apply (as :: [*]) r+type instance Apply '[] r = r+type instance Apply (x ': xs) r = x -> Apply xs r +type Fn c a = Apply (Reverse c) a+apply :: Fn c r -> SList c -> r+apply f l = apply' f $ sReverse l++apply' :: Apply xs r -> SList xs -> r+apply' v SNil = v+apply' f (a ::: as) = apply' (f a) as+ type family Rev (l :: [*]) (a :: [*]) :: [*] type instance Rev '[] a = a type instance Rev (x ': xs) a = Rev xs (x ': a)@@ -51,4 +50,3 @@     rev :: SList as -> SList bs -> SList (Rev as bs)     rev SNil a = a     rev (x:::xs) a = rev xs (x:::a)-
src/Web/Apiary.hs view
@@ -3,18 +3,26 @@     , module Control.Monad.Apiary.Action     , module Control.Monad.Apiary.Filter     , module Data.Apiary.Param+    -- | Strategy Proxies+    , module Control.Monad.Apiary.Filter.Internal.Strategy+    -- | Method(..)+    , module Data.Apiary.Method+    -- | (+>)+    , module Data.Apiary.Extension     , act+     -- * reexports-    , module Data.Default.Class     , module Network.HTTP.Types.Status+    -- | def+    , module Data.Default.Class     -- | MonadIO-    , module Control.Monad.Trans-    -- | MonadPlus(..), msum, mfilter, guard+    , module Control.Monad.IO.Class+    -- | MonadPlus(..), msum, mfilter, guard, (>=>)     , module Control.Monad-    -- | Strategy Proxies-    , module Control.Monad.Apiary.Filter.Internal.Strategy     -- | FilePart(..)     , module Network.Wai+    -- | Html+    , module Text.Blaze.Html     ) where   import Web.Apiary.TH@@ -25,8 +33,11 @@ import Control.Monad.Apiary.Action import Control.Monad.Apiary.Filter import Control.Monad.Apiary.Filter.Internal.Strategy (pFirst, pOne, pOption, pCheck, pMany, pSome)-import Control.Monad.Trans(MonadIO(..))-import Control.Monad (MonadPlus(..), msum, mfilter, guard)+import Control.Monad.IO.Class(MonadIO(..))+import Control.Monad (MonadPlus(..), msum, mfilter, guard, (>=>)) -import Data.Default.Class+import Data.Default.Class(def) import Data.Apiary.Param+import Data.Apiary.Extension((+>))+import Data.Apiary.Method(Method(..))+import Text.Blaze.Html(Html)
+ test/Application.hs view
@@ -0,0 +1,324 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}++module Application where++import Test.Framework+import Test.Framework.Providers.HUnit++import Control.Monad+import Control.Monad.Identity++import Web.Apiary+import Network.Wai+import Network.Wai.Test+import qualified Network.HTTP.Types as HTTP++import qualified Data.ByteString.Lazy.Char8 as L+import qualified Data.ByteString.Char8 as S++testReq :: String -> (Request -> IO ()) -> Test+testReq str f = +    let (meth, other) = break (== ' ') str+        (p,  version) = break (== ' ') (tail other)+    in testCase str $ f (setPath (setVersion version $ (defaultRequest { requestMethod = S.pack meth })) (S.pack p))+  where+    setVersion [] r = r+    setVersion v r | v == " HTTP/1.0" = r { Network.Wai.httpVersion = HTTP.http10 }+                   | v == " HTTP/0.9" = r { Network.Wai.httpVersion = HTTP.http09 }+                   | otherwise        = r { Network.Wai.httpVersion = HTTP.http11 }+--------------------------------------------------------------------------------++assertRequest :: Int -> (Maybe S.ByteString) -> L.ByteString -> Application -> Request -> IO ()+assertRequest sc ct body app req = flip runSession app $ do+    res <- request req+    assertBody body res+    assertStatus sc res+    maybe (return ()) (flip assertContentType res) ct++assertPlain200 :: L.ByteString -> Application -> Request -> IO ()+assertPlain200 = assertRequest 200 (Just "text/plain")++assertHtml200 :: L.ByteString -> Application -> Request -> IO ()+assertHtml200 = assertRequest 200 (Just "text/html")++assertJson200 :: L.ByteString -> Application -> Request -> IO ()+assertJson200 = assertRequest 200 (Just "application/json")++assert404 :: Application -> Request -> IO ()+assert404 = assertRequest 404 (Just "text/plain") "404 Page Notfound.\n"++--------------------------------------------------------------------------------++helloWorldApp :: Application+helloWorldApp = runIdentity . runApiary def $ action $ do+    contentType "text/plain"+    bytes "hello"++helloWorldAllTest :: Test+helloWorldAllTest = testGroup "helloWorld" $ map ($ helloWorldApp)+    [ testReq "GET /"    . assertPlain200 "hello"+    , testReq "GET /foo" . assertPlain200 "hello"+    , testReq "POST /"   . assertPlain200 "hello"+    ]++--------------------------------------------------------------------------------++methodFilterApp :: Application+methodFilterApp = runIdentity . runApiary def $ do+    method "GET" . action $ contentType "text/plain" >> bytes "GET"+    method POST  . action $ contentType "text/plain" >> bytes "POST"++methodFilterTest :: Test+methodFilterTest = testGroup "methodFilter" $ map ($methodFilterApp)+    [ testReq "GET /"    . assertPlain200 "GET"+    , testReq "POST /"   . assertPlain200 "POST"+    , testReq "GET /foo" . assertPlain200 "GET"+    , testReq "DELETE /" . assert404+    ]++--------------------------------------------------------------------------------++httpVersionApp :: Application+httpVersionApp = runIdentity . runApiary def $ do+    http09 . action $ contentType "text/plain" >> bytes "09"+    http10 . action $ contentType "text/plain" >> bytes "10"+    http11 . action $ contentType "text/plain" >> bytes "11"++httpVersionTest :: Test+httpVersionTest = testGroup "httpVersionFilter" $ map ($ httpVersionApp)+    [ testReq "GET / HTTP/0.9" . assertPlain200 "09"+    , testReq "GET / HTTP/1.0" . assertPlain200 "10"+    , testReq "GET / HTTP/1.1" . assertPlain200 "11"+    ]++--------------------------------------------------------------------------------++rootFilterApp :: Application+rootFilterApp = runIdentity . runApiary def .  root . action $ do+    contentType "text/html"+    bytes "root"++rootFilterTest :: Test+rootFilterTest = testGroup "rootFilter" $ map ($ rootFilterApp)+    [ testReq "GET /"           . assertHtml200 "root"+    , testReq "POST /"          . assertHtml200 "root"+    , testReq "GET /neko"       . assert404+    , testReq "GET /index.html" . assertHtml200 "root"+    ]++--------------------------------------------------------------------------------+anyFilterApp :: Application+anyFilterApp = runIdentity . runApiary def $ [capture|/test|] . anyPath . action $ do+    contentType "text/plain"+    bytes "hello"++anyFilterTest :: Test+anyFilterTest = testGroup "anyPath" $ map ($ anyFilterApp)+    [ testReq "GET /"          . assert404+    , testReq "GET /test"      . assertPlain200 "hello"+    , testReq "POST /test/foo" . assertPlain200 "hello"+    ]++--------------------------------------------------------------------------------++captureApp :: Application+captureApp = runIdentity . runApiary def $ do+    [capture|/foo|]  . action $ contentType "text/plain" >> bytes "foo"+    [capture|/:Int|] . method GET . action $ \i -> contentType "text/plain" >> bytes "Int " >> showing i+    [capture|/:Double|] . action $ \i -> contentType "text/plain" >> bytes "Double " >> showing i+    [capture|/bar/:L.ByteString/:Int|] . action $ \s i -> contentType "text/plain" >> lazyBytes s >> char ' ' >> showing i+    [capture|/:L.ByteString|] . action $ \s -> contentType "text/plain" >> bytes "fall " >> lazyBytes s++captureTest :: Test+captureTest = testGroup "capture" $ map ($ captureApp)+    [ testReq "GET /foo"  . assertPlain200 "foo"+    , testReq "GET /12"   . assertPlain200 "Int 12"+    , testReq "GET /12.4" . assertPlain200 "Double 12.4"+    , testReq "POST /12"  . assertPlain200 "Double 12.0"+    , testReq "GET /bar"  . assertPlain200 "fall bar"+    , testReq "GET /baz"  . assertPlain200 "fall baz"+    , testReq "GET /bar/nyan/12"       . assertPlain200 "nyan 12"+    , testReq "GET /bar/nyan/12/other" . assert404+    ]++--------------------------------------------------------------------------------++queryApp f g h = runIdentity . runApiary def $ do+    _ <- (f "foo" pInt)        . action $ \i -> contentType "text/plain" >> bytes "foo Int " >> showing i+    _ <- (g "foo" pString)     . action $ \i -> contentType "text/plain" >> bytes "foo String " >> showing i+    (h "foo" (pMaybe pString)) . action $ \i -> contentType "text/plain" >> bytes "foo Maybe String " >> showing i++queryOptionalApp :: Application+queryOptionalApp = runIdentity . runApiary def $ do+    ("foo" =?!: (5 :: Int))                   . action $ \i -> contentType "text/plain" >> bytes "foo Int " >> showing i+    ("foo" =?!: ("bar" :: String))            . action $ \i -> contentType "text/plain" >> bytes "foo String " >> showing i+    ("foo" =?!: (Just "baz" :: Maybe String)) . action $ \i -> contentType "text/plain" >> bytes "foo Maybe String " >> showing i++queryCheckApp :: Application+queryCheckApp = runIdentity . runApiary def $ do+    ("foo" ?: pInt)           . action $ contentType "text/plain" >> bytes "foo Int"+    ("foo" ?: pString)        . action $ contentType "text/plain" >> bytes "foo String"+    ("foo" ?: pMaybe pString) . action $ contentType "text/plain" >> bytes "foo Maybe String"++queryFirstTest :: Test+queryFirstTest = testGroup "First" $ map ($ queryApp (=:) (=:) (=:))+    [ testReq "GET /" . assert404+    , testReq "GET /?foo" . assertPlain200 "foo Maybe String Nothing"+    , testReq "GET /?foo&foo=3" . assertPlain200 "foo Maybe String Nothing"+    , testReq "GET /?foo=12" . assertPlain200 "foo Int 12"+    , testReq "GET /?foo=a" . assertPlain200 "foo String \"a\""+    , testReq "GET /?foo=12&foo=23" . assertPlain200 "foo Int 12"+    , testReq "GET /?foo=12&foo=b" . assertPlain200 "foo Int 12"+    ]++queryOneTest :: Test+queryOneTest = testGroup "One" $ map ($ queryApp (=!:) (=!:) (=!:))+    [ testReq "GET /" . assert404+    , testReq "GET /?foo" . assertPlain200 "foo Maybe String Nothing"+    , testReq "GET /?foo&foo=3" . assert404+    , testReq "GET /?foo=12" . assertPlain200 "foo Int 12"+    , testReq "GET /?foo=a" . assertPlain200 "foo String \"a\""+    , testReq "GET /?foo=12&foo=23" . assert404+    , testReq "GET /?foo=12&foo=b" . assert404+    ]++queryOptionTest :: Test+queryOptionTest = testGroup "Option" $ map ($ queryApp (=?:) (=?:) (=?:))+    [ testReq "GET /" . assertPlain200 "foo Int Nothing"+    , testReq "GET /?foo" . assertPlain200 "foo Maybe String Just Nothing"+    , testReq "GET /?foo&foo=3" . assertPlain200 "foo Maybe String Just Nothing"+    , testReq "GET /?foo=12" . assertPlain200 "foo Int Just 12"+    , testReq "GET /?foo=a" . assertPlain200 "foo String Just \"a\""+    , testReq "GET /?foo=12&foo=23" . assertPlain200 "foo Int Just 12"+    , testReq "GET /?foo=12&foo=b" . assertPlain200 "foo String Just \"12\""+    ]++queryOptionalTest :: Test+queryOptionalTest = testGroup "Optional" $ map ($ queryOptionalApp)+    [ testReq "GET /" . assertPlain200 "foo Int 5"+    , testReq "GET /?foo" . assertPlain200 "foo Maybe String Nothing"+    , testReq "GET /?foo&foo=3" . assertPlain200 "foo Maybe String Nothing"+    , testReq "GET /?foo=12" . assertPlain200 "foo Int 12"+    , testReq "GET /?foo=a" . assertPlain200 "foo String \"a\""+    , testReq "GET /?foo=12&foo=23" . assertPlain200 "foo Int 12"+    , testReq "GET /?foo=12&foo=b" . assertPlain200 "foo String \"12\""+    ]++queryCheckTest :: Test+queryCheckTest = testGroup "Check" $ map ($ queryCheckApp)+    [ testReq "GET /" . assert404+    , testReq "GET /?foo" . assertPlain200 "foo Maybe String"+    , testReq "GET /?foo&foo=3" . assertPlain200 "foo Maybe String"+    , testReq "GET /?foo=12" . assertPlain200 "foo Int"+    , testReq "GET /?foo=a" . assertPlain200 "foo String"+    , testReq "GET /?foo=12&foo=23" . assertPlain200 "foo Int"+    , testReq "GET /?foo=12&foo=b" . assertPlain200 "foo String"+    ]++queryManyTest :: Test+queryManyTest = testGroup "Many" $ map ($ queryApp (=*:) (=*:) (=*:))+    [ testReq "GET /" . assertPlain200 "foo Int []"+    , testReq "GET /?foo" . assertPlain200 "foo Maybe String [Nothing]"+    , testReq "GET /?foo&foo=3" . assertPlain200 "foo Maybe String [Nothing,Just \"3\"]"+    , testReq "GET /?foo=12" . assertPlain200 "foo Int [12]"+    , testReq "GET /?foo=a" . assertPlain200 "foo String [\"a\"]"+    , testReq "GET /?foo=12&foo=23" . assertPlain200 "foo Int [12,23]"+    , testReq "GET /?foo=12&foo=b" . assertPlain200 "foo String [\"12\",\"b\"]"+    ]++querySomeTest :: Test+querySomeTest = testGroup "Some" $ map ($ queryApp (=+:) (=+:) (=+:))+    [ testReq "GET /" . assert404+    , testReq "GET /?foo" . assertPlain200 "foo Maybe String [Nothing]"+    , testReq "GET /?foo&foo=3" . assertPlain200 "foo Maybe String [Nothing,Just \"3\"]"+    , testReq "GET /?foo=12" . assertPlain200 "foo Int [12]"+    , testReq "GET /?foo=a" . assertPlain200 "foo String [\"a\"]"+    , testReq "GET /?foo=12&foo=23" . assertPlain200 "foo Int [12,23]"+    , testReq "GET /?foo=12&foo=b" . assertPlain200 "foo String [\"12\",\"b\"]"+    ]+++queryTest :: Test+queryTest = testGroup "query"+    [ queryFirstTest+    , queryOneTest+    , queryOptionTest+    , queryOptionalTest+    , queryCheckTest+    , queryManyTest+    , querySomeTest+    ]++--------------------------------------------------------------------------------+stopApp :: Application+stopApp = runIdentity . runApiary def $ do+    [capture|/a/:Int|] . action $ \i -> do+        contentType "text/plain"+        when (i == 1) $ bytes "one\n"+        if i `mod` 2 == 0 then bytes "even\n" else bytes "odd\n"+        when (i == 2) stop+        bytes "after stop"++stopTest :: Test+stopTest = testGroup "stop" $ map ($ stopApp)+    [ testReq "GET /a/0" . assertPlain200 "even\nafter stop"+    , testReq "GET /a/1" . assertPlain200 "one\nodd\nafter stop"+    , testReq "GET /a/2" . assertPlain200 "even\n"+    , testReq "GET /a/3" . assertPlain200 "odd\nafter stop"+    ]++--------------------------------------------------------------------------------++acceptApp :: Application+acceptApp = runIdentity . runApiary def $ [capture|/|] $ do+    accept "application/json" . action $ bytes "json"+    accept "text/html"        . action $ bytes "html"+    action                             $ bytes "other"++acceptTest :: Test+acceptTest = testGroup "accept" $ map ($ acceptApp)+    [ testReq "GET / application/json" . (\a r -> assertJson200 "json"   a $ addA "application/json" r)+    , testReq "GET / text/html"        . (\a r -> assertHtml200 "html"   a $ addA "text/html"  r)+    , testReq "GET / text/plain"       . (\a r -> assertRequest 200 Nothing "other" a $ addA "text/plain" r)+    , testReq "GET /"                  . assertRequest 200 Nothing "other"+    ]+  where+    addA :: S.ByteString -> Request -> Request+    addA ct r = r {requestHeaders = ("Accept", ct) : filter (("Accept" ==) . fst) (requestHeaders r)}++--------------------------------------------------------------------------------++multipleFilter1App :: Application+multipleFilter1App = runIdentity . runApiary def $ do+    root $ do+        method GET  . action $ contentType "text/plain" >> bytes "GET /"+        method POST . action $ contentType "text/html"  >> bytes "POST /"++    method DELETE . action   $ contentType "text/plain" >> bytes "DELETE ANY"++multipleFilter1Test :: Test+multipleFilter1Test = testGroup "multiple test1: root, method"+    [ testReq "GET /index.html" $ assertPlain200 "GET /"      multipleFilter1App+    , testReq "POST /"          $ assertHtml200 "POST /"      multipleFilter1App+    , testReq "DELETE /"        $ assertPlain200 "DELETE ANY" multipleFilter1App +    , testReq "PUT /"           $ assert404 multipleFilter1App+    ]++--------------------------------------------------------------------------------++applicationTests :: Test+applicationTests = testGroup "Application"+    [ helloWorldAllTest+    , methodFilterTest+    , httpVersionTest+    , rootFilterTest+    , anyFilterTest+    , captureTest+    , queryTest+    , stopTest+    , acceptTest+    , multipleFilter1Test+    ]+
+ test/Method.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE OverloadedStrings #-}+module Method where++import Test.Framework+import Test.Framework.Providers.HUnit+import Test.HUnit hiding (Test)++import Data.Apiary.Method+import qualified Data.ByteString as S++stdMethods :: [S.ByteString]+stdMethods =+    [ "GET"+    , "POST"+    , "HEAD"+    , "PUT"+    , "DELETE"+    , "TRACE"+    , "CONNECT"+    , "OPTIONS"+    , "PATCH"+    ]++methodTests :: Test+methodTests = testGroup "Method"+    [ testCase "renderMethod . parseMethod == id" $+        mapM_ (\s -> +            let s' = (renderMethod . parseMethod) s+            in assertBool (show s ++ " /= " ++ show s') $ s == s'+        ) ("YAMADA" : "neko" : "POSTa" : "DELET" : "CONNECt" : stdMethods)++    , testCase "parseMethod" $ do+        let assertMethod s t = assertBool (show s) $ parseMethod s == t+            assertNS s = assertMethod s (NonStandard s)+        assertMethod "GET"     GET+        assertMethod "POST"    POST+        assertMethod "HEAD"    HEAD+        assertMethod "PUT"     PUT+        assertMethod "DELETE"  DELETE+        assertMethod "TRACE"   TRACE+        assertMethod "CONNECT" CONNECT+        assertMethod "OPTIONS" OPTIONS+        assertMethod "PATCH"   PATCH+        assertNS "YAMADA"+        assertNS "neko"+        assertNS "POSTa"+        assertNS "DELET"+        assertNS "CONNECt"++    ]
test/main.hs view
@@ -1,273 +1,12 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes #-}-{-# OPTIONS_GHC -fno-warn-missing-signatures #-}  import Test.Framework-import Test.Framework.Providers.HUnit -import Web.Apiary-import Network.Wai-import Network.Wai.Test-import qualified Network.HTTP.Types as HTTP--import qualified Data.ByteString.Lazy.Char8 as L-import qualified Data.ByteString.Char8 as S--testReq :: String -> (Request -> IO ()) -> Test-testReq str f = -    let (meth, other) = break (== ' ') str-        (p,  version) = break (== ' ') (tail other)-    in testCase str $ f (setPath (setVersion version $ (defaultRequest { requestMethod = S.pack meth })) (S.pack p))-  where-    setVersion [] r = r-    setVersion v r | v == " HTTP/1.1" = r { Network.Wai.httpVersion = HTTP.http11 }-                   | v == " HTTP/1.0" = r { Network.Wai.httpVersion = HTTP.http10 }-                   | v == " HTTP/0.9" = r { Network.Wai.httpVersion = HTTP.http09 }-                   | otherwise        = error "unknown HTTP version"------------------------------------------------------------------------------------assertPlain200 :: L.ByteString -> Application -> Request -> IO ()-assertPlain200 body app req = flip runSession app $ do-    res <- request req-    assertBody body res-    assertStatus 200 res-    assertContentType "text/plain" res--assertHtml200 :: L.ByteString -> Application -> Request -> IO ()-assertHtml200 body app req = flip runSession app $ do-    res <- request req-    assertBody body res-    assertStatus 200 res-    assertContentType "text/html" res--assert404 :: Application -> Request -> IO ()-assert404 app req = flip runSession app $ do-    res <- request req-    assertBody "404 Page Notfound.\n" res-    assertStatus 404 res-    assertContentType "text/plain" res------------------------------------------------------------------------------------helloWorldApp :: Application-helloWorldApp = runApiary def $ action $ do-    contentType "text/plain"-    bytes "hello"--helloWorldAllTest :: Test-helloWorldAllTest = testGroup "helloWorld" -    [ testReq "GET /"    $ assertPlain200 "hello" helloWorldApp-    , testReq "GET /foo" $ assertPlain200 "hello" helloWorldApp-    , testReq "POST /"   $ assertPlain200 "hello" helloWorldApp-    ]------------------------------------------------------------------------------------methodFilterApp :: Application-methodFilterApp = runApiary def $ do-    method "GET" . action $ contentType "text/plain" >> bytes "GET"-    method POST  . action $ contentType "text/plain" >> bytes "POST"--methodFilterTest :: Test-methodFilterTest = testGroup "methodFilter"-    [ testReq "GET /"    $ assertPlain200 "GET" methodFilterApp-    , testReq "POST /"   $ assertPlain200 "POST" methodFilterApp-    , testReq "GET /foo" $ assertPlain200 "GET" methodFilterApp-    , testReq "DELETE /" $ assert404 methodFilterApp-    ]------------------------------------------------------------------------------------httpVersionApp :: Application-httpVersionApp = runApiary def $ do-    http09 . action $ contentType "text/plain" >> bytes "09"-    http10 . action $ contentType "text/plain" >> bytes "10"-    http11 . action $ contentType "text/plain" >> bytes "11"--httpVersionTest :: Test-httpVersionTest = testGroup "httpVersionFilter" -    [ testReq "GET / HTTP/0.9" $ assertPlain200 "09" httpVersionApp-    , testReq "GET / HTTP/1.0" $ assertPlain200 "10" httpVersionApp-    , testReq "GET / HTTP/1.1" $ assertPlain200 "11" httpVersionApp-    ]------------------------------------------------------------------------------------rootFilterApp :: Application-rootFilterApp = runApiary def .  root . action $ do-    contentType "text/html"-    bytes "root"--rootFilterTest :: Test-rootFilterTest = testGroup "rootFilter"-    [ testReq "GET /"           $ assertHtml200 "root" rootFilterApp-    , testReq "POST /"          $ assertHtml200 "root" rootFilterApp-    , testReq "GET /neko"       $ assert404 rootFilterApp-    , testReq "GET /index.html" $ assertHtml200 "root" rootFilterApp-    ]-----------------------------------------------------------------------------------anyFilterApp :: Application-anyFilterApp = runApiary def $ [capture|/test|] . anyPath . action $ do-    contentType "text/plain"-    bytes "hello"--anyFilterTest :: Test-anyFilterTest = testGroup "anyPath"-    [ testReq "GET /"          $ assert404 anyFilterApp-    , testReq "GET /test"      $ assertPlain200 "hello" anyFilterApp-    , testReq "POST /test/foo" $ assertPlain200 "hello" anyFilterApp-    ]------------------------------------------------------------------------------------captureApp :: Application-captureApp = runApiary def $ do-    [capture|/foo|]  . action $ contentType "text/plain" >> bytes "foo"-    [capture|/:Int|] . method GET . action $ \i -> contentType "text/plain" >> bytes "Int " >> showing i-    [capture|/:Double|] . action $ \i -> contentType "text/plain" >> bytes "Double " >> showing i-    [capture|/bar/:L.ByteString/:Int|] . action $ \s i -> contentType "text/plain" >> lazyBytes s >> char ' ' >> showing i-    [capture|/:L.ByteString|] . action $ \s -> contentType "text/plain" >> bytes "fall " >> lazyBytes s--captureTest :: Test-captureTest = testGroup "capture"-    [ testReq "GET /foo" $ assertPlain200 "foo" captureApp-    , testReq "GET /12"   $ assertPlain200 "Int 12" captureApp-    , testReq "GET /12.4" $ assertPlain200 "Double 12.4" captureApp-    , testReq "POST /12"  $ assertPlain200 "Double 12.0" captureApp-    , testReq "GET /bar"  $ assertPlain200 "fall bar" captureApp-    , testReq "GET /baz"  $ assertPlain200 "fall baz" captureApp-    , testReq "GET /bar/nyan/12"       $ assertPlain200 "nyan 12" captureApp-    , testReq "GET /bar/nyan/12/other" $ assert404 captureApp-    ]------------------------------------------------------------------------------------queryApp f g h = runApiary def $ do-    _ <- (f "foo" pInt)             . action $ \i -> contentType "text/plain" >> bytes "foo Int " >> showing i-    _ <- (g "foo" pString)          . action $ \i -> contentType "text/plain" >> bytes "foo String " >> showing i-    (h "foo" (pMaybe pString)) . action $ \i -> contentType "text/plain" >> bytes "foo Maybe String " >> showing i--queryCheckApp :: Application-queryCheckApp = runApiary def $ do-    ("foo" ?: pInt)           . action $ contentType "text/plain" >> bytes "foo Int"-    ("foo" ?: pString)        . action $ contentType "text/plain" >> bytes "foo String"-    ("foo" ?: pMaybe pString) . action $ contentType "text/plain" >> bytes "foo Maybe String"--queryFirstTest :: Test-queryFirstTest = testGroup "First"-    [ testReq "GET /" $ assert404 app-    , testReq "GET /?foo" $ assertPlain200 "foo Maybe String Nothing" app-    , testReq "GET /?foo&foo=3" $ assertPlain200 "foo Maybe String Nothing" app-    , testReq "GET /?foo=12" $ assertPlain200 "foo Int 12" app-    , testReq "GET /?foo=a" $ assertPlain200 "foo String \"a\"" app-    , testReq "GET /?foo=12&foo=23" $ assertPlain200 "foo Int 12" app-    , testReq "GET /?foo=12&foo=b" $ assertPlain200 "foo Int 12" app-    ]-  where app = queryApp (=:) (=:) (=:)--queryOneTest :: Test-queryOneTest = testGroup "One"-    [ testReq "GET /" $ assert404 app-    , testReq "GET /?foo" $ assertPlain200 "foo Maybe String Nothing" app-    , testReq "GET /?foo&foo=3" $ assert404 app-    , testReq "GET /?foo=12" $ assertPlain200 "foo Int 12" app-    , testReq "GET /?foo=a" $ assertPlain200 "foo String \"a\"" app-    , testReq "GET /?foo=12&foo=23" $ assert404 app-    , testReq "GET /?foo=12&foo=b" $ assert404 app-    ]-  where app = queryApp (=!:) (=!:) (=!:)--queryOptionTest :: Test-queryOptionTest = testGroup "Option"-    [ testReq "GET /" $ assertPlain200 "foo Int Nothing" app-    , testReq "GET /?foo" $ assertPlain200 "foo Maybe String Just Nothing" app-    , testReq "GET /?foo&foo=3" $ assertPlain200 "foo Maybe String Just Nothing" app-    , testReq "GET /?foo=12" $ assertPlain200 "foo Int Just 12" app-    , testReq "GET /?foo=a" $ assertPlain200 "foo String Just \"a\"" app-    , testReq "GET /?foo=12&foo=23" $ assertPlain200 "foo Int Just 12" app-    , testReq "GET /?foo=12&foo=b" $ assertPlain200 "foo String Just \"12\"" app-    ]-  where app = queryApp (=?:) (=?:) (=?:)--queryCheckTest :: Test-queryCheckTest = testGroup "Check"-    [ testReq "GET /" $ assert404 app-    , testReq "GET /?foo" $ assertPlain200 "foo Maybe String" app-    , testReq "GET /?foo&foo=3" $ assertPlain200 "foo Maybe String" app-    , testReq "GET /?foo=12" $ assertPlain200 "foo Int" app-    , testReq "GET /?foo=a" $ assertPlain200 "foo String" app-    , testReq "GET /?foo=12&foo=23" $ assertPlain200 "foo Int" app-    , testReq "GET /?foo=12&foo=b" $ assertPlain200 "foo String" app-    ]-  where app = queryCheckApp--queryManyTest :: Test-queryManyTest = testGroup "Many"-    [ testReq "GET /" $ assertPlain200 "foo Int []" app-    , testReq "GET /?foo" $ assertPlain200 "foo Maybe String [Nothing]" app-    , testReq "GET /?foo&foo=3" $ assertPlain200 "foo Maybe String [Nothing,Just \"3\"]" app-    , testReq "GET /?foo=12" $ assertPlain200 "foo Int [12]" app-    , testReq "GET /?foo=a" $ assertPlain200 "foo String [\"a\"]" app-    , testReq "GET /?foo=12&foo=23" $ assertPlain200 "foo Int [12,23]" app-    , testReq "GET /?foo=12&foo=b" $ assertPlain200 "foo String [\"12\",\"b\"]" app-    ]-  where app = queryApp (=*:) (=*:) (=*:)--querySomeTest :: Test-querySomeTest = testGroup "Some"-    [ testReq "GET /" $ assert404 app-    , testReq "GET /?foo" $ assertPlain200 "foo Maybe String [Nothing]" app-    , testReq "GET /?foo&foo=3" $ assertPlain200 "foo Maybe String [Nothing,Just \"3\"]" app-    , testReq "GET /?foo=12" $ assertPlain200 "foo Int [12]" app-    , testReq "GET /?foo=a" $ assertPlain200 "foo String [\"a\"]" app-    , testReq "GET /?foo=12&foo=23" $ assertPlain200 "foo Int [12,23]" app-    , testReq "GET /?foo=12&foo=b" $ assertPlain200 "foo String [\"12\",\"b\"]" app-    ]-  where app = queryApp (=+:) (=+:) (=+:)---queryTest :: Test-queryTest = testGroup "query"-    [ queryFirstTest-    , queryOneTest-    , queryOptionTest-    , queryCheckTest-    , queryManyTest-    , querySomeTest-    ]------------------------------------------------------------------------------------multipleFilter1App :: Application-multipleFilter1App = runApiary def $ do-    root $ do-        method GET  . action $ contentType "text/plain" >> bytes "GET /"-        method POST . action $ contentType "text/html"  >> bytes "POST /"--    method DELETE . action $ contentType "text/plain" >> bytes "DELETE ANY"--multipleFilter1Test :: Test-multipleFilter1Test = testGroup "multiple test1: root, method"-    [ testReq "GET /index.html" $ assertPlain200 "GET /"      multipleFilter1App-    , testReq "POST /"          $ assertHtml200 "POST /"      multipleFilter1App-    , testReq "DELETE /"        $ assertPlain200 "DELETE ANY" multipleFilter1App -    , testReq "PUT /"           $ assert404 multipleFilter1App-    ]-----------------------------------------------------------------------------------+import Application+import Method  main :: IO ()-main = defaultMain -    [ helloWorldAllTest-    , methodFilterTest-    , httpVersionTest-    , rootFilterTest-    , anyFilterTest-    , captureTest-    , queryTest-    , multipleFilter1Test+main = defaultMain+    [ methodTests+    , applicationTests     ]