natefaubion / purescript-routing-duplex

Unified parsing and printing for routes in PureScript

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to handle hash in a route

rnons opened this issue · comments

A continuation of purescript-contrib/purescript-routing#60 (comment)

I'm trying to use purescript-routing-duplex and pushed to https://github.com/rnons/purescript-routing-issue-60/tree/duplex, but even this case doesn't work now

image

Route is defined like this

data Region = East | West
derive instance eqRegion :: Eq Region
derive instance genericRegion :: Generic Region _

data PageRoute
  = Root
  | RegionRoute Region

derive instance eqPageRoute :: Eq PageRoute
derive instance genericPageRoute :: Generic PageRoute _

pageRoute :: RouteDuplex' PageRoute
pageRoute =
  root $ RDG.sum
    { "Root": noArgs
    , "RegionRoute": regionRoute
    }
  where
  regionRoute :: RouteDuplex' Region
  regionRoute = RDG.sum
    { "East": noArgs
    , "West": noArgs
    }

I changed regionRoute to

  regionRoute :: RouteDuplex' Region
  regionRoute = RDG.sum
    { "East": path "east" noArgs
    , "West": path "west" noArgs
    }

Now http://localhost:8080/west works, but http://localhost:8080/west#abc still not.

Fixed with 343bf5a

Thank you for the detailed reproduction.

Thanks for the fix, it works now.

I have another question, say if my data Region is a sum type of 40+ constructors, what's the best way to write regionRoute? I guess there is a parse function somewhere, but didn't find it

I'm not sure exactly what you mean by a parse function.

 regionRoute :: RouteDuplex' Region
 regionRoute = RDG.sum
   { "East": path "east" noArgs
   , "West": path "west" noArgs
   -- naturally I don't want to write 40+ lines of this
   }

I already have readRegion :: String -> Maybe Region, what I'm missing is how to use readRegion inside regionRoute

When I was using purescript-routing, I can write

regionMatcher :: Match Region
regionMatcher = Match \route ->
  case route of
    Cons (Path i) rs -> case readRegion i of
      Just region -> pure $ Tuple rs region
      _ -> invalid $ free $ Fail "Invalid region"
    _ -> invalid $ free ExpectedPathPart

You can use as.

region :: RouteDuplex' String -> RouteDuplex' Region
region = as showRegion (readRegion >>> maybe (Left "Not a region") Right)

pageRoute :: RouteDuplex' PageRoute
pageRoute =
  root $ RDG.sum
    { "Root": noArgs
    , "RegionRoute": region segment
    }

Cool, thank you. Will give it a try.