Routing.Duplex
- Package
- purescript-routing-duplex
- Repository
- natefaubion/purescript-routing-duplex
#RouteDuplex Source
data RouteDuplex i oThe core abstraction of this library. The values of this type can be used both for parsing
values of type o from String as well as printing values of type i into String.
For most purposes, you'll likely want RouterDuplex' which uses the same
type for both parameters.
Constructors
RouteDuplex (i -> RoutePrinter) (RouteParser o)
Instances
Functor (RouteDuplex i)Apply (RouteDuplex i)Applicative (RouteDuplex i)Profunctor RouteDuplex(IsSymbol sym, Cons sym (RouteDuplex String String -> RouteDuplex a b) rx1 r1, Cons sym a rx2 r2, Cons sym b r3 rx3, Lacks sym r3, RouteDuplexBuildParams rest r1 r2 rx3 r4) => RouteDuplexBuildParams (Cons sym (RouteDuplex String String -> RouteDuplex a b) rest) r1 r2 r3 r4
#RouteDuplex' Source
type RouteDuplex' a = RouteDuplex a aA type restricted variant of RouteDuplex where input and output are
the same type. This type will typically be your custom Route data type
representing valid routes within your application.
#parse Source
parse :: forall o i. RouteDuplex i o -> String -> Either RouteError oUses a given codec to parse a value of type o out of String representing
the path, query and fragment (hash) of a URI (see
URI - generic syntax)
or produce a RouteError if parsing fails.
#print Source
print :: forall o i. RouteDuplex i o -> i -> StringRenders a value of type i into a String representation of URI path,
query and fragment (hash).
#prefix Source
prefix :: forall b a. String -> RouteDuplex a b -> RouteDuplex a bStrips (when parsing) or adds (when printing) a given string segment of the
path. Note: this combinator only deals with a single segment.
If you pass it a string containing '/' it will percent encode it and treat it as single segment.
E.g. prefix "/api/v1" will attempt to match single segment "%2Fapi%2Fv1" which is probably not what you want.
See path if you want to deal with prefixes consisting of multiple segments.
parse (prefix "api" segment) "api/a" == Right "a"
parse (prefix "/api/v1" segment)) "/api/v1/a" == Left (Expected "/api/v1" "")
-- contrast with `path`
parse (path "/api/v1" segment)) "/api/v1/a" == Right "a"
#suffix Source
suffix :: forall b a. RouteDuplex a b -> String -> RouteDuplex a bSimilar to prefix. Strips (when parsing) or adds (when printing) a given
string segment from the end of the path. The same precautions for prefix apply here.
#path Source
path :: forall b a. String -> RouteDuplex a b -> RouteDuplex a bStrips (when parsing) or adds (when printing) a given String prefix,
potentially consisting of multiple path segments. Constrast this with prefix,
which only deals with single segment.
parse (path "/api/v1" segment) "/api/v1/a" == Right "a"
parse (path "/api/v1" segment) "/api/v2/a" == Left (Expected "v1" "v2")
#root Source
root :: forall b a. RouteDuplex a b -> RouteDuplex a bModifies a given codec to require a prefix of '/'. You can think of it as stripping and adding the '/' at the beginning of path, failing if it's not there.
parse (root segment) "/abc" == Right "abc"
parse (root segment) "abc" == Left (Expected "" "abc")
print (root segment) "abc" == "/abc"
#end Source
end :: forall b a. RouteDuplex a b -> RouteDuplex a bend codec will only suceed if codec succeeds and there are no
additional path segments remaining to be processed.
parse (end segment) "abc" == Right "abc"
parse (end segment) "abc/def" == Left (ExpectedEndOfPath "def")
#segment Source
segment :: RouteDuplex' StringConsumes or prints a single path segment. Note: URI encoding and decoding is done automatically.
parse segment "abc" == Right "abc"
parse segment "abc%20def" == Right "abc def" -- automatic decoding of uri components
parse segment "abc/def" == Right "abc"
parse segment "/abc" == Right "" -- the empty string before the first '/'
parse (root segment) "/abc" == Right "abc"
print segment "hello there" == "hello%20there"
print segment "" == "/"
#param Source
param :: String -> RouteDuplex' Stringparam name consumes or prints a query parameter with the given name.
Parsing will fail if the parameter is not there.
parse (param "search") "?search=keyword" == Right "keyword"
parse (param "search") "/" == Left (MissingParam "search")
parse (optional (param "search")) "/" == Right Nothing
#flag Source
flag :: RouteDuplex' String -> RouteDuplex' BooleanConsumes or prints a query flag (i.e. parameter without value).
Note: that this combinator ignores the value of the parameter. It only cares about its presence/absence.
Presence is interpreted as true, absence as false.
parse (flag (param "x")) "?x" == Right true
parse (flag (param "x")) "?x=true", == Right true
parse (flag (param "x")) "?x=false", == Right true -- value is ignored, what matters is presence of the parameter x
parse (flag (param "x")) "?y", == Right false
#many1 Source
many1 :: forall b a f. Foldable f => Alt f => Applicative f => RouteDuplex a b -> RouteDuplex (f a) (f b)Repeatedly applies a given codec to parse one or more values from path segments. Parsing will fail if no segment can be parsed.
parse (many1 (int segment)) "1/2/3/x" == Right [1,2,3]
parse (many1 (int segment)) "x", == Left (Expected "Int" "x") :: Either RouteError (Array Int)
#many Source
many :: forall b a f. Foldable f => Alternative f => RouteDuplex a b -> RouteDuplex (f a) (f b)Similar to many1, except also succeeds when no values can be parsed.
parse (many (int segment)) "1/2/3/x" == Right [1,2,3]
parse (many (int segment)) "x", == Right []
#rest Source
rest :: RouteDuplex' (Array String)Consumes or prints all the remaining segments.
parse rest "" == Right []
parse (path "a/b" rest) "a/b/c/d" == Right ["c", "d"]
print rest ["a", "b"] == "a/b"
#default Source
default :: forall b a. b -> RouteDuplex a b -> RouteDuplex a bSets a default value which will be returned when parsing fails. Does not influence printing in any way.
parse (default 0 $ int segment) "1" == Right 1
parse (default 0 $ int segment) "x" == Right 0
#optional Source
optional :: forall b a. RouteDuplex a b -> RouteDuplex (Maybe a) (Maybe b)Augments the behavior of a given codec by making it return Nothing if parsing
fails, or Just value if it succeeds.
parse (optional segment) "a" == Right (Just "a")
parse (optional segment) "" == Right Nothing
print (optional segment) (Just "a") == "a"
print (optional segment) Nothing == ""
#as Source
as :: forall b a s. (a -> s) -> (String -> Either String b) -> RouteDuplex s String -> RouteDuplex a bBuilds a codec for a custom type out of printer and parser functions.
data Sort = Asc | Desc
sortToString :: Sort -> String
sortToString = case _ of
Asc -> "asc"
Desc -> "desc"
sortFromString :: String -> Either String Sort
sortFromString = case _ of
"asc" -> Right Asc
"desc" -> Right Desc
val -> Left $ "Not a sort: " <> val
sort :: RouteDuplex' String -> RouteDuplex' Sort
sort = as sortToString sortFromString
#int Source
int :: RouteDuplex' String -> RouteDuplex' IntRefines a codec of Strings to Ints.
parse (int segment) "1" == Right 1
parse (int segment) "x" == Left (Expected "Int" "x")
print (int segment) 1 == "1"
#boolean Source
boolean :: RouteDuplex' String -> RouteDuplex' BooleanRefines a codec of Strings to Booleans, where true and false are the
strings "true" and "false", and other strings are rejected.
parse (boolean segment) "true" == Right true
parse (boolean segment) "x" == Left (Expected "Boolean" "x")
print (boolean segment) true == "true"
#string Source
string :: RouteDuplex' String -> RouteDuplex' StringThis does nothing (internally it's defined as identity).
It can be used to restrict a type parameter of a polymorphic RouteDuplex' a to String.
#record Source
record :: forall r. RouteDuplex r (Record ())Combined with prop or :=, builds a Record where the order of
parsing and printing matters.
date =
record
# prop (SProxy :: _ "year") (int segment)
# prop (SProxy :: _ "month") (int segment)
# prop (SProxy :: _ "day") (int segment)
parse (path "blog" date) "blog/2019/1/2" ==
Right { year: 2019, month: 1, day: 2 }
#prop Source
prop :: forall rx r3 r2 r1 b a sym. IsSymbol sym => Cons sym a rx r1 => Cons sym b r2 r3 => Lacks sym r2 => SProxy sym -> RouteDuplex a b -> RouteDuplex (Record r1) (Record r2) -> RouteDuplex (Record r1) (Record r3)See record.
#RouteDuplexParams Source
class RouteDuplexParams (r1 :: Row Type) (r2 :: Row Type) | r1 -> r2 whereMembers
params :: Record r1 -> RouteDuplex' (Record r2)
Instances
(RowToList r1 rl, RouteDuplexBuildParams rl r1 r2 () r2) => RouteDuplexParams r1 r2
#RouteDuplexBuildParams Source
class RouteDuplexBuildParams (rl :: RowList) (r1 :: Row Type) (r2 :: Row Type) (r3 :: Row Type) (r4 :: Row Type) | rl -> r1 r2 r3 r4 whereMembers
buildParams :: RLProxy rl -> Record r1 -> RouteDuplex (Record r2) (Record r3) -> RouteDuplex (Record r2) (Record r4)
Instances
(IsSymbol sym, Cons sym (RouteDuplex String String -> RouteDuplex a b) rx1 r1, Cons sym a rx2 r2, Cons sym b r3 rx3, Lacks sym r3, RouteDuplexBuildParams rest r1 r2 rx3 r4) => RouteDuplexBuildParams (Cons sym (RouteDuplex String String -> RouteDuplex a b) rest) r1 r2 r3 r4RouteDuplexBuildParams Nil r1 r2 r3 r3
Builds a
RouteDuplexfrom a record of query parameter parsers/printers, where each property corresponds to a query parameter with the same name.