packages feed

nested-routes 9.0.0 → 9.0.0.1

raw patch · 4 files changed

+101/−92 lines, 4 filesdep +waidep ~wai-middleware-content-typedep ~wai-middleware-verbsdep ~wai-transformersPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: wai

Dependency ranges changed: wai-middleware-content-type, wai-middleware-verbs, wai-transformers

API changes (from Hackage documentation)

- Web.Routes.Nested: auth :: (Monad m) => sec -> AuthScope -> RouterT content (SecurityToken sec) m ()
+ Web.Routes.Nested: auth :: Monad m => sec -> AuthScope -> RouterT content (SecurityToken sec) m ()
- Web.Routes.Nested: extractAuth :: (MonadIO m, MonadThrow m) => (Request -> [sec] -> m ()) -> Request -> RouterT x (SecurityToken sec) m a -> m ()
+ Web.Routes.Nested: extractAuth :: MonadIO m => MonadThrow m => (Request -> [sec] -> m ()) -> Request -> RouterT x (SecurityToken sec) m a -> m ()
- Web.Routes.Nested: extractAuthSym :: (MonadIO m) => [Text] -> RouterT x (SecurityToken sec) m a -> m [sec]
+ Web.Routes.Nested: extractAuthSym :: MonadIO m => [Text] -> RouterT x (SecurityToken sec) m a -> m [sec]
- Web.Routes.Nested: extractMatch :: (MonadIO m) => [Text] -> RouterT r sec m a -> m (Maybe r)
+ Web.Routes.Nested: extractMatch :: MonadIO m => [Text] -> RouterT r sec m a -> m (Maybe r)
- Web.Routes.Nested: extractMatchAny :: (MonadIO m) => [Text] -> RouterT r sec m a -> m (Maybe r)
+ Web.Routes.Nested: extractMatchAny :: MonadIO m => [Text] -> RouterT r sec m a -> m (Maybe r)
- Web.Routes.Nested: extractNearestVia :: (MonadIO m) => [Text] -> (RouterT r sec m a -> m (RootedPredTrie Text r)) -> RouterT r sec m a -> m (Maybe r)
+ Web.Routes.Nested: extractNearestVia :: MonadIO m => [Text] -> (RouterT r sec m a -> m (RootedPredTrie Text r)) -> RouterT r sec m a -> m (Maybe r)
- Web.Routes.Nested: match :: (Monad m, Match xs' xs childContent resultContent) => UrlChunks xs -> childContent -> RouterT resultContent sec m ()
+ Web.Routes.Nested: match :: Monad m => Match xs' xs childContent resultContent => UrlChunks xs -> childContent -> RouterT resultContent sec m ()
- Web.Routes.Nested: matchAny :: (Monad m) => childContent -> RouterT childContent sec m ()
+ Web.Routes.Nested: matchAny :: Monad m => childContent -> RouterT childContent sec m ()
- Web.Routes.Nested: matchGroup :: (Monad m, MatchGroup xs' xs childContent resultContent childSec resultSec) => UrlChunks xs -> RouterT childContent childSec m () -> RouterT resultContent resultSec m ()
+ Web.Routes.Nested: matchGroup :: Monad m => MatchGroup xs' xs childContent resultContent childSec resultSec => UrlChunks xs -> RouterT childContent childSec m () -> RouterT resultContent resultSec m ()
- Web.Routes.Nested: matchHere :: (Monad m) => childContent -> RouterT childContent sec m ()
+ Web.Routes.Nested: matchHere :: Monad m => childContent -> RouterT childContent sec m ()
- Web.Routes.Nested: route :: (MonadIO m) => RouterT (MiddlewareT m) sec m a -> MiddlewareT m
+ Web.Routes.Nested: route :: MonadIO m => RouterT (MiddlewareT m) sec m a -> MiddlewareT m
- Web.Routes.Nested: routeAuth :: (MonadIO m, MonadThrow m) => (Request -> [sec] -> m ()) -> RouterT (MiddlewareT m) (SecurityToken sec) m a -> MiddlewareT m
+ Web.Routes.Nested: routeAuth :: MonadIO m => MonadThrow m => (Request -> [sec] -> m ()) -> RouterT (MiddlewareT m) (SecurityToken sec) m a -> MiddlewareT m

Files

nested-routes.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: c01d97006f99cd2296688bd70d1bff61663c843911d5c92a8484e2e578934d31+-- hash: 23396eb133d1c0b4eabee7dbb44fc9b6739eb73776e937055a72d9bd86144294  name:           nested-routes-version:        9.0.0+version:        9.0.0.1 synopsis:       Declarative, compositional Wai responses description:    Please see the README on Github at <https://git.localcooking.com/tooling/pred-trie#readme> category:       Web@@ -46,9 +46,10 @@     , text     , tries >=0.0.5     , unordered-containers-    , wai-middleware-content-type >=0.6.0-    , wai-middleware-verbs >=0.3.2-    , wai-transformers >=0.0.7+    , wai >=3.2.1+    , wai-middleware-content-type >=0.6.1.1+    , wai-middleware-verbs >=0.4.0.1+    , wai-transformers >=0.1.0   default-language: Haskell2010  test-suite spec@@ -83,7 +84,8 @@     , text     , tries >=0.0.5     , unordered-containers-    , wai-middleware-content-type >=0.6.0-    , wai-middleware-verbs >=0.3.2-    , wai-transformers >=0.0.7+    , wai >=3.2.1+    , wai-middleware-content-type >=0.6.1.1+    , wai-middleware-verbs >=0.4.0.1+    , wai-transformers >=0.1.0   default-language: Haskell2010
src/Web/Routes/Nested.hs view
@@ -79,7 +79,8 @@ import           Web.Routes.Nested.Match import           Web.Routes.Nested.Types            (RouterT, execRouterT, Tries (..), ExtrudeSoundly) import           Web.Routes.Nested.Types-import           Network.Wai.Trans                  (MiddlewareT, Request, pathInfo)+import           Network.Wai                        (Request, pathInfo)+import           Network.Wai.Trans                  (MiddlewareT) import           Network.Wai.Middleware.Verbs import           Network.Wai.Middleware.ContentType hiding (responseStatus, responseHeaders, responseData) @@ -134,11 +135,11 @@ --   Generally, if the routes you are building get grouped --   by a predicate with 'matchGroup', --   then we would need another level of arity /before/ the @Double@.-match :: ( Monad m-         , Match xs' xs childContent resultContent-         ) => UrlChunks xs -- ^ Predicative path to match against-           -> childContent -- ^ The response to send-           -> RouterT resultContent sec m ()+match :: Monad m+      => Match xs' xs childContent resultContent+      => UrlChunks xs -- ^ Predicative path to match against+      -> childContent -- ^ The response to send+      -> RouterT resultContent sec m () match !ts !vl =   tell' $ Tries (singleton ts vl)                 mempty@@ -148,9 +149,9 @@ {-# INLINEABLE match #-}  -- | Create a handle for the /current/ route - an alias for @\h -> match o_ h@.-matchHere :: ( Monad m-             ) => childContent -- ^ The response to send-               -> RouterT childContent sec m ()+matchHere :: Monad m+          => childContent -- ^ The response to send+          -> RouterT childContent sec m () matchHere = match origin_  {-# INLINEABLE matchHere #-}@@ -159,9 +160,9 @@ -- | Match against any route, as a last resort against all failing matches - --   use this for a catch-all at some level in their routes, something --   like a @not-found 404@ page is useful.-matchAny :: ( Monad m-            ) => childContent -- ^ The response to send-              -> RouterT childContent sec m ()+matchAny :: Monad m+         => childContent -- ^ The response to send+         -> RouterT childContent sec m () matchAny !vl =   tell' $ Tries mempty                 (singleton origin_ vl)@@ -174,11 +175,11 @@ -- | Prepends a common route to an existing set of routes. You should note that --   doing this with a parser or regular expression will necessitate the existing --   arity in the handlers before the progam can compile.-matchGroup :: ( Monad m-              , MatchGroup xs' xs childContent resultContent childSec resultSec-              ) => UrlChunks xs -- ^ Predicative path to match against-                -> RouterT childContent  childSec  m () -- ^ Child routes to nest-                -> RouterT resultContent resultSec m ()+matchGroup :: Monad m+           => MatchGroup xs' xs childContent resultContent childSec resultSec+           => UrlChunks xs -- ^ Predicative path to match against+           -> RouterT childContent  childSec  m () -- ^ Child routes to nest+           -> RouterT resultContent resultSec m () matchGroup !ts cs = do   (Tries trieContent' trieNotFound trieSec) <- lift $ execRouterT cs   tell' $ Tries (extrude ts trieContent')@@ -205,14 +206,14 @@  -- | Sets the security role and error handler for a set of routes, optionally -- including its parent route.-auth :: ( Monad m-        ) => sec -- ^ Your security token-          -> AuthScope-          -> RouterT content (SecurityToken sec) m ()+auth :: Monad m+     => sec -- ^ Your security token+     -> AuthScope+     -> RouterT content (SecurityToken sec) m () auth !token !scope =-  tell' $ Tries mempty+  tell'  (Tries mempty                 mempty-                (singleton origin_ $ SecurityToken token scope)+                (singleton origin_ (SecurityToken token scope)))   {-# INLINEABLE auth #-}@@ -227,9 +228,9 @@ --   with 'routeAuth': -- --   > route routes . routeAuth routes-route :: ( MonadIO m-         ) => RouterT (MiddlewareT m) sec m a -- ^ The Router-           -> MiddlewareT m+route :: MonadIO m+      => RouterT (MiddlewareT m) sec m a -- ^ The Router+      -> MiddlewareT m route hs app req resp = do   let path = pathInfo req   mightMatch <- extractMatch path hs@@ -247,11 +248,11 @@ --   an exception based on the current 'Network.Wai.Middleware.Request' and --   the /layers/ of 'auth' tokens passed in your router, turn your router --   into a 'Control.Monad.guard' for middlewares, basically.-routeAuth :: ( MonadIO m-             , MonadThrow m-             ) => (Request -> [sec] -> m ()) -- ^ authorization method-               -> RouterT (MiddlewareT m) (SecurityToken sec) m a -- ^ The Router-               -> MiddlewareT m+routeAuth :: MonadIO m+          => MonadThrow m+          => (Request -> [sec] -> m ()) -- ^ authorization method+          -> RouterT (MiddlewareT m) (SecurityToken sec) m a -- ^ The Router+          -> MiddlewareT m routeAuth authorize hs app req resp = do   extractAuth authorize req hs   route hs app req resp@@ -259,10 +260,10 @@ -- * Extraction -------------------------------  -- | Extracts only the normal 'match', 'matchGroup' and 'matchHere' routes.-extractMatch :: ( MonadIO m-                ) => [T.Text] -- ^ The path to match against-                  -> RouterT r sec m a -- ^ The Router-                  -> m (Maybe r)+extractMatch :: MonadIO m+             => [T.Text] -- ^ The path to match against+             -> RouterT r sec m a -- ^ The Router+             -> m (Maybe r) extractMatch path !hs = do   Tries{trieContent} <- execRouterT hs   let mResult = lookupWithLRPT trimFileExt path trieContent@@ -278,10 +279,10 @@   -- | Extracts only the 'matchAny' responses; something like the greatest-lower-bound.-extractMatchAny :: ( MonadIO m-                   ) => [T.Text] -- ^ The path to match against-                     -> RouterT r sec m a -- ^ The Router-                     -> m (Maybe r)+extractMatchAny :: MonadIO m+                => [T.Text] -- ^ The path to match against+                -> RouterT r sec m a -- ^ The Router+                -> m (Maybe r) extractMatchAny path = extractNearestVia path (\x -> trieCatchAll <$> execRouterT x)  {-# INLINEABLE extractMatchAny #-}@@ -290,10 +291,10 @@  -- | Find the security tokens / authorization roles affiliated with --   a request for a set of routes.-extractAuthSym :: ( MonadIO m-                  ) => [T.Text] -- ^ The path to match against-                    -> RouterT x (SecurityToken sec) m a -- ^ The Router-                    -> m [sec]+extractAuthSym :: MonadIO m+               => [T.Text] -- ^ The path to match against+               -> RouterT x (SecurityToken sec) m a -- ^ The Router+               -> m [sec] extractAuthSym path hs = do   Tries{trieSecurity} <- execRouterT hs   liftIO . stToIO $ do@@ -306,12 +307,12 @@ {-# INLINEABLE extractAuthSym #-}  -- | Extracts only the security handling logic, and turns it into a guard.-extractAuth :: ( MonadIO m-               , MonadThrow m-               ) => (Request -> [sec] -> m ()) -- ^ authorization method-                 -> Request-                 -> RouterT x (SecurityToken sec) m a-                 -> m ()+extractAuth :: MonadIO m+            => MonadThrow m+            => (Request -> [sec] -> m ()) -- ^ authorization method+            -> Request+            -> RouterT x (SecurityToken sec) m a+            -> m () extractAuth authorize req hs = do   ss <- extractAuthSym (pathInfo req) hs   authorize req ss@@ -322,11 +323,11 @@ -- | Given a way to draw out a special-purpose trie from our route set, route --   to the responses based on a /furthest-route-reached/ method, or like a --   greatest-lower-bound.-extractNearestVia :: ( MonadIO m-                     ) => [T.Text] -- ^ The path to match against-                       -> (RouterT r sec m a -> m (RootedPredTrie T.Text r))-                       -> RouterT r sec m a-                       -> m (Maybe r)+extractNearestVia :: MonadIO m+                  => [T.Text] -- ^ The path to match against+                  -> (RouterT r sec m a -> m (RootedPredTrie T.Text r))+                  -> RouterT r sec m a+                  -> m (Maybe r) extractNearestVia path extr hs = do   trie <- extr hs   pure (mid <$> Interface.match path trie)@@ -353,19 +354,19 @@  -- | A quirky function for processing the last element of a lookup path, only -- on /literal/ matches.-lookupWithLPT :: ( Hashable s-                 , Eq s-                 ) => (s -> s) -> NonEmpty s -> PredTrie s a -> Maybe ([s], a)+lookupWithLPT :: Hashable s+              => Eq s+              => (s -> s) -> NonEmpty s -> PredTrie s a -> Maybe ([s], a) lookupWithLPT f tss (PredTrie (HashMapStep ls) (PredStep ps)) =   getFirst $ First (goLit f tss ls)           <> foldMap (First . goPred f tss) ps -goLit :: ( Hashable s-         , Eq s-         ) => (s -> s)-           -> NonEmpty s-           -> HM.HashMap s (HashMapChildren PredTrie s a)-           -> Maybe ([s], a)+goLit :: Hashable s+      => Eq s+      => (s -> s)+      -> NonEmpty s+      -> HM.HashMap s (HashMapChildren PredTrie s a)+      -> Maybe ([s], a) goLit f (t:|ts) xs = do   (HashMapChildren mx mxs) <- getFirst $ First (HM.lookup t xs)                                       <> First (  if null ts@@ -375,12 +376,12 @@   then ([f t],) <$> mx   else first (t:) <$> (lookupWithLPT f (fromList ts) =<< mxs) -goPred :: ( Hashable s-          , Eq s-          ) => (s -> s)-            -> NonEmpty s-            -> Pred PredTrie s a-            -> Maybe ([s], a)+goPred :: Hashable s+       => Eq s+       => (s -> s)+       -> NonEmpty s+       -> Pred PredTrie s a+       -> Maybe ([s], a) goPred f (t:|ts) (Pred predicate mx xs) = do   d <- predicate t   if null ts@@ -392,9 +393,9 @@ {-# INLINEABLE lookupWithLPT #-}  -lookupWithLRPT :: ( Hashable s-                 , Eq s-                 ) => (s -> s) -> [s] -> RootedPredTrie s a -> Maybe ([s], a)+lookupWithLRPT :: Hashable s+               => Eq s+               => (s -> s) -> [s] -> RootedPredTrie s a -> Maybe ([s], a) lookupWithLRPT _ [] (RootedPredTrie mx _) = ([],) <$> mx lookupWithLRPT f ts (RootedPredTrie _ xs) = lookupWithLPT f (fromList ts) xs @@ -403,7 +404,7 @@ {-# INLINEABLE lookupWithLRPT #-}  -tell' :: (Monoid w, S.MonadState w m) => w -> m ()+tell' :: Monoid w => S.MonadState w m => w -> m () tell' x = S.modify' (<> x)  {-# INLINEABLE tell' #-}
src/Web/Routes/Nested/Types.hs view
@@ -29,9 +29,10 @@   ) where  import           Web.Routes.Nested.Match             (UrlChunks)-import           Network.Wai.Middleware.Verbs        (VerbListenerT, execVerbListenerT, lookupVerb, getVerb)+import           Network.Wai.Middleware.Verbs        (VerbListenerT, execVerbListenerT, getVerbFromRequest) import           Network.Wai.Middleware.ContentType  (FileExtListenerT, fileExtsToMiddleware) import           Network.Wai.Trans                   (MiddlewareT)+import           Network.Wai                         (strictRequestBody) import           Data.Trie.Pred.Base                 (RootedPredTrie (..)) import           Data.Trie.Pred.Interface.Types      (Extrude (..), CatMaybes) @@ -39,10 +40,11 @@ import qualified Data.Text                           as T import           Data.Function.Poly                  (ArityTypeListIso) import           Data.Singleton.Class                (Extractable)+import qualified Data.HashMap.Lazy                   as HM import           Control.Monad.Trans                 (MonadTrans) import           Control.Monad.IO.Class              (MonadIO) import qualified Control.Monad.State                 as S-import           Control.Monad.Trans.Control.Aligned (MonadBaseControl)+import           Control.Monad.Trans.Control.Aligned (MonadBaseControl (liftBaseWith))   @@ -57,9 +59,7 @@ instance Monoid (Tries x s) where   mempty = Tries mempty mempty mempty   mappend (Tries x1 x2 x3) (Tries y1 y2 y3) =-    ((Tries $! x1 <> y1)-            $! x2 <> y2)-            $! x3 <> y3+    Tries (x1 <> y1) (x2 <> y2) (x3 <> y3)  -- | The (syntactic) monad for building a router with functions like --   "Web.Routes.Nested.match".@@ -97,9 +97,14 @@ --   is satisfiable (i.e. @Accept@ headers are O.K., etc.) action :: MonadBaseControl IO m stM        => Extractable stM-       => ActionT m () -> MiddlewareT m+       => ActionT m ()+       -> MiddlewareT m action xs app req respond = do-  vmap <- fmap fileExtsToMiddleware <$> execVerbListenerT xs-  case lookupVerb (getVerb req) vmap of-    Nothing  -> app req respond-    Just mid -> mid app req respond+  vmap <- execVerbListenerT xs+  case HM.lookup (getVerbFromRequest req) vmap of+    Nothing -> app req respond+    Just eR -> do+      c <- case eR of+        Left c' -> pure c'+        Right f -> f <$> liftBaseWith (\_ -> strictRequestBody req)+      fileExtsToMiddleware c app req respond
test/Web/Routes/NestedSpec/Basic.hs view
@@ -9,7 +9,8 @@ module Web.Routes.NestedSpec.Basic where  import Web.Routes.Nested (o_, p_, l_, r_, (</>), match, matchHere, matchGroup, auth, AuthScope (..), textOnly, routeAuth)-import Network.Wai.Trans (Middleware, Application, Request, catchMiddlewareT)+import Network.Wai (Middleware, Application, Request)+import Network.Wai.Trans (catchMiddlewareT) import Network.HTTP.Types (status401, status404, status200) import Text.Regex (mkRegex) import Data.Attoparsec.Text (double)