Module

Yoga.Fastify.Om.Router

Package
purescript-yoga-fastify-om
Repository
rowtype-yoga/purescript-yoga-fastify-om

#matchRoute Source

matchRoute :: forall route ctx err. RouteDuplex' route -> Om { httpRequest :: RequestContext | ctx } err (Either RouteError route)

Match the current request URL against a route codec

Example: handler reply = do route <- matchRoute myRouteCodec case route of Right (UserProfile userId) -> showUserProfile userId reply Right Home -> showHome reply Left err -> badRequest reply

#matchRouteUrl Source

matchRouteUrl :: forall route. RouteDuplex' route -> RouteURL -> Either RouteError route

Match a specific RouteURL against a route codec (for testing/utilities)

#getRoute Source

getRoute :: forall route ctx err. RouteDuplex' route -> Om { httpRequest :: RequestContext | ctx } err (Either RouteError route)

Get the current route from context (convenience wrapper around matchRoute)

Example: handler reply = do route <- getRoute myRouteCodec case route of Right (UserProfile userId) -> showProfile userId reply Right Home -> showHome reply Left err -> badRequest reply

Re-exports from Routing.Duplex

#RouteDuplex' Source

type RouteDuplex' a = RouteDuplex a a

A 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.

#RouteDuplex Source

data RouteDuplex i o

The 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 RouteDuplex' which uses the same type for both parameters.

Constructors

Instances

#RouteDuplexBuildParams Source

class RouteDuplexBuildParams :: RowList Type -> Row Type -> Row Type -> Row Type -> Row Type -> Constraintclass RouteDuplexBuildParams (rl :: RowList Type) (r1 :: Row Type) (r2 :: Row Type) (r3 :: Row Type) (r4 :: Row Type) | rl -> r1 r2 r3 r4 where

Members

Instances

#RouteDuplexParams Source

class RouteDuplexParams :: Row Type -> Row Type -> Constraintclass RouteDuplexParams (r1 :: Row Type) (r2 :: Row Type) | r1 -> r2 where

Members

  • params :: Record r1 -> RouteDuplex' (Record r2)

    Builds a RouteDuplex from a record of query parameter parsers/printers, where each property corresponds to a query parameter with the same name.

    search =
      params
        { page: int
        , filter: optional <<< string
        }
    
    parse search "?page=3&filter=Galaxy%20Quest" ==
      Right { page: 3, filter: Just "Galaxy Quest" }
    

Instances

#suffix Source

suffix :: forall a b. RouteDuplex a b -> String -> RouteDuplex a b

Similar 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.

#string Source

string :: RouteDuplex' String -> RouteDuplex' String

This does nothing (internally it's defined as identity). It can be used to restrict a type parameter of a polymorphic RouteDuplex' a to String.

#segment Source

segment :: RouteDuplex' String

Consumes 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 "" == "/"

#root Source

root :: forall a b. RouteDuplex a b -> RouteDuplex a b

Modifies 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"

#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"

#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 (Proxy :: _ "year") (int segment)
    # prop (Proxy :: _ "month") (int segment)
    # prop (Proxy :: _ "day") (int segment)

parse (path "blog" date) "blog/2019/1/2" ==
  Right { year: 2019, month: 1, day: 2 }

#prop Source

prop :: forall sym a b r1 r2 r3 rx. IsSymbol sym => Cons sym a rx r1 => Cons sym b r2 r3 => Lacks sym r2 => Proxy sym -> RouteDuplex a b -> RouteDuplex (Record r1) (Record r2) -> RouteDuplex (Record r1) (Record r3)

See record.

#print Source

print :: forall i o. RouteDuplex i o -> i -> String

Renders a value of type i into a String representation of URI path, query and fragment (hash).

#prefix Source

prefix :: forall a b. String -> RouteDuplex a b -> RouteDuplex a b

Strips (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"

#path Source

path :: forall a b. String -> RouteDuplex a b -> RouteDuplex a b

Strips (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")

#parse Source

parse :: forall i o. RouteDuplex i o -> String -> Either RouteError o

Uses 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.

#param Source

param :: String -> RouteDuplex' String

param 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

#optional Source

optional :: forall a b. 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    == ""

#many1 Source

many1 :: forall f a b. 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 f a b. 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 []

#int Source

int :: RouteDuplex' String -> RouteDuplex' Int

Refines 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"

#hash Source

hash :: RouteDuplex' String

Consumes or prints the URI hash segment.

parse hash "abc#def" == Right "def"

#flag Source

flag :: RouteDuplex' String -> RouteDuplex' Boolean

Consumes 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

#end Source

end :: forall a b. RouteDuplex a b -> RouteDuplex a b

end 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")

#default Source

default :: forall a b. b -> RouteDuplex a b -> RouteDuplex a b

Sets 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

#boolean Source

boolean :: RouteDuplex' String -> RouteDuplex' Boolean

Refines 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"

#as Source

as :: forall s a b. (a -> s) -> (String -> Either String b) -> RouteDuplex s String -> RouteDuplex a b

Builds 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

#(:=) Source

Operator alias for Routing.Duplex.prop (non-associative / precedence 2)

Re-exports from Routing.Duplex.Generic

#GRouteDuplex Source

class GRouteDuplex :: Type -> Row Type -> Constraintclass GRouteDuplex rep (r :: Row Type) | rep -> r where

Members

Instances

#sumPrefix Source

sumPrefix :: forall a rep r. Generic a rep => GRouteDuplex rep r => Record r -> RouteDuplex' a

A variation of sum that does not implicitly add an end to each branch. This is useful for defining sub-parsers that may consume only some of the URI segments, leaving the rest for subsequent parsers.

#sum Source

sum :: forall a rep r. Generic a rep => GRouteDuplex rep r => Record r -> RouteDuplex' a

Builds a parser/printer from a record, where each record field corresponds to a constructor name for your data type.

Note: this implicitly inserts calls to end for each constructor, making the parser only valid for parsing URI suffixes. To parse URI prefixes, or to just have more explicit control, use sumPrefix.

#product Source

#(~) Source

Operator alias for Routing.Duplex.Generic.product (right-associative / precedence 0)

Re-exports from Routing.Duplex.Generic.Syntax

#GParams Source

class GParams a b c | a b -> c where

Members

Instances

#GSep Source

class GSep a b c | a b -> c where

Members

Instances

#(?) Source

Operator alias for Routing.Duplex.Generic.Syntax.gparams (non-associative / precedence 8)

#(/) Source

Operator alias for Routing.Duplex.Generic.Syntax.gsep (right-associative / precedence 1)