Skip to content

Commit f86920b

Browse files
committed
Allow ignoring query parameters at route branches
1 parent e37c186 commit f86920b

File tree

1 file changed

+53
-20
lines changed

1 file changed

+53
-20
lines changed

lib/route/src/Obelisk/Route.hs

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ module Obelisk.Route
5757
-- * Collating Routes
5858
, SegmentResult (..)
5959
, pathComponentEncoder
60+
, pathComponentEncoderIgnoringQuery
6061

6162
, FullRoute (..)
6263
, _FullRoute_Frontend
@@ -80,6 +81,7 @@ module Obelisk.Route
8081
, enum1Encoder
8182
, checkEnum1EncoderFunc
8283
, unitEncoder
84+
, unitEncoderLenient
8385
, pathOnlyEncoder
8486
, addPathSegmentEncoder
8587
, pathParamEncoder
@@ -119,6 +121,7 @@ module Obelisk.Route
119121
, queryParametersTextEncoder
120122
, integralEncoder
121123
, pathSegmentEncoder
124+
, pathOnlyEncoderIgnoringQuery
122125
, queryOnlyEncoder
123126
, Decoder(..)
124127
, dmapEncoder
@@ -577,32 +580,56 @@ checkEnum1EncoderFunc f = do
577580

578581
-- | This type is used by pathComponentEncoder to allow the user to indicate how to treat
579582
-- various cases when encoding a dependent sum of type `(R p)`.
580-
data SegmentResult check parse a =
581-
PathEnd (Encoder check parse a (Map Text (Maybe Text)))
583+
data SegmentResult check parse a b =
584+
PathEnd (Encoder check parse a b)
582585
-- ^ Indicate that the path is finished, with an Encoder that translates the
583586
-- corresponding value into query parameters
584-
| PathSegment Text (Encoder check parse a PageName)
587+
| PathSegment Text (Encoder check parse a ([Text], b))
585588
-- ^ Indicate that the key should be represented by an additional path segment with
586589
-- the given 'Text', and give an Encoder for translating the corresponding value into
587590
-- the remainder of the route.
588591

592+
pathComponentEncoderIgnoringQuery
593+
:: ( Universe (Some p)
594+
, GShow p
595+
, GCompare p
596+
, MonadError Text check
597+
, MonadError Text parse
598+
)
599+
=> (forall a. p a -> SegmentResult check parse a ())
600+
-> Encoder check parse (R p) PageName
601+
pathComponentEncoderIgnoringQuery = pathComponentEncoder' $ \case
602+
PathEnd e -> first (unitEncoder []) . coidl . unitEncoderLenient mempty . e
603+
PathSegment _ e -> pathOnlyEncoderIgnoringQuery . idr . e
604+
605+
pathComponentEncoder
606+
:: ( Universe (Some p)
607+
, GShow p
608+
, GCompare p
609+
, MonadError Text check
610+
, MonadError Text parse
611+
)
612+
=> (forall a. p a -> SegmentResult check parse a (Map Text (Maybe Text)))
613+
-> Encoder check parse (R p) PageName
614+
pathComponentEncoder = pathComponentEncoder' $ \case
615+
PathEnd e -> first (unitEncoder []) . coidl . e
616+
PathSegment _ e -> e
617+
589618
-- | Encode a dependent sum of type `(R p)` into a PageName (i.e. the path and query part of a URL) by using the
590619
-- supplied function to decide how to encode the constructors of p using the SegmentResult type. It is important
591620
-- that the number of values of type `(Some p)` be relatively small in order for checking to complete quickly.
592-
pathComponentEncoder
593-
:: forall check parse p.
594-
( Universe (Some p)
621+
pathComponentEncoder'
622+
:: ( Universe (Some p)
595623
, GShow p
596624
, GCompare p
597625
, MonadError Text check
598-
, MonadError Text parse )
599-
=> (forall a. p a -> SegmentResult check parse a)
626+
, MonadError Text parse
627+
)
628+
=> (forall a. SegmentResult check parse a b -> Encoder check parse a PageName)
629+
-> (forall a. p a -> SegmentResult check parse a b)
600630
-> Encoder check parse (R p) PageName
601-
pathComponentEncoder f = Encoder $ do
602-
let extractEncoder = \case
603-
PathEnd e -> first (unitEncoder []) . coidl . e
604-
PathSegment _ e -> e
605-
extractPathSegment = \case
631+
pathComponentEncoder' extractEncoder f = Encoder $ do
632+
let extractPathSegment = \case
606633
PathEnd _ -> Nothing
607634
PathSegment t _ -> Just t
608635
EncoderFunc f' <- checkEnum1EncoderFunc (extractEncoder . f)
@@ -737,6 +764,12 @@ unitEncoder expected = unsafeMkEncoder $ EncoderImpl
737764
, _encoderImpl_encode = \_ -> expected
738765
}
739766

767+
unitEncoderLenient :: (Applicative check, Applicative parse) => r -> Encoder check parse () r
768+
unitEncoderLenient expected = unsafeMkEncoder $ EncoderImpl
769+
{ _encoderImpl_decode = \_ -> pure ()
770+
, _encoderImpl_encode = \_ -> expected
771+
}
772+
740773
singlePathSegmentEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse Text PageName
741774
singlePathSegmentEncoder = pathOnlyEncoder . singletonListEncoder
742775

@@ -976,8 +1009,8 @@ instance (UniverseSome br, UniverseSome fr) => UniverseSome (FullRoute br fr) w
9761009
mkFullRouteEncoder
9771010
:: (GCompare br, GCompare fr, GShow br, GShow fr, UniverseSome br, UniverseSome fr)
9781011
=> R (FullRoute br fr) -- ^ 404 handler
979-
-> (forall a. br a -> SegmentResult (Either Text) (Either Text) a) -- ^ How to encode a single backend route segment
980-
-> (forall a. fr a -> SegmentResult (Either Text) (Either Text) a) -- ^ How to encode a single frontend route segment
1012+
-> (forall a. br a -> SegmentResult (Either Text) (Either Text) a (Map Text (Maybe Text))) -- ^ How to encode a single backend route segment
1013+
-> (forall a. fr a -> SegmentResult (Either Text) (Either Text) a (Map Text (Maybe Text))) -- ^ How to encode a single frontend route segment
9811014
-> Encoder (Either Text) Identity (R (FullRoute br fr)) PageName
9821015
mkFullRouteEncoder missing backendSegment frontendSegment = handleEncoder (const missing) $
9831016
pathComponentEncoder $ \case
@@ -1027,7 +1060,7 @@ obeliskRouteEncoder :: forall check parse appRoute.
10271060
, MonadError Text check
10281061
, check ~ parse --TODO: Get rid of this
10291062
)
1030-
=> (forall a. appRoute a -> SegmentResult check parse a)
1063+
=> (forall a. appRoute a -> SegmentResult check parse a (Map Text (Maybe Text)))
10311064
-> Encoder check parse (R (ObeliskRoute appRoute)) PageName
10321065
obeliskRouteEncoder appRouteSegment = pathComponentEncoder $ \r ->
10331066
obeliskRouteSegment r appRouteSegment
@@ -1038,15 +1071,15 @@ obeliskRouteEncoder appRouteSegment = pathComponentEncoder $ \r ->
10381071
obeliskRouteSegment :: forall check parse appRoute a.
10391072
(MonadError Text check, MonadError Text parse)
10401073
=> ObeliskRoute appRoute a
1041-
-> (forall b. appRoute b -> SegmentResult check parse b)
1042-
-> SegmentResult check parse a
1074+
-> (forall b. appRoute b -> SegmentResult check parse b (Map Text (Maybe Text)))
1075+
-> SegmentResult check parse a (Map Text (Maybe Text))
10431076
obeliskRouteSegment r appRouteSegment = case r of
10441077
ObeliskRoute_App appRoute -> appRouteSegment appRoute
10451078
ObeliskRoute_Resource resourceRoute -> resourceRouteSegment resourceRoute
10461079

10471080
-- | A function which gives a sane default for how to encode Obelisk resource routes. It's given in this form, because it will
10481081
-- be combined with other such segment encoders before 'pathComponentEncoder' turns it into a proper 'Encoder'.
1049-
resourceRouteSegment :: (MonadError Text check, MonadError Text parse) => ResourceRoute a -> SegmentResult check parse a
1082+
resourceRouteSegment :: (MonadError Text check, MonadError Text parse) => ResourceRoute a -> SegmentResult check parse a (Map Text (Maybe Text))
10501083
resourceRouteSegment = \case
10511084
ResourceRoute_Static -> PathSegment "static" pathOnlyEncoderIgnoringQuery
10521085
ResourceRoute_Ghcjs -> PathSegment "ghcjs" pathOnlyEncoder
@@ -1074,7 +1107,7 @@ instance GShow appRoute => GShow (ObeliskRoute appRoute) where
10741107
data IndexOnlyRoute :: * -> * where
10751108
IndexOnlyRoute :: IndexOnlyRoute ()
10761109

1077-
indexOnlyRouteSegment :: (Applicative check, MonadError Text parse) => IndexOnlyRoute a -> SegmentResult check parse a
1110+
indexOnlyRouteSegment :: (Applicative check, MonadError Text parse) => IndexOnlyRoute a -> SegmentResult check parse a (Map Text (Maybe Text))
10781111
indexOnlyRouteSegment = \case
10791112
IndexOnlyRoute -> PathEnd $ unitEncoder mempty
10801113

0 commit comments

Comments
 (0)