@@ -27,6 +27,7 @@ import Data.Argonaut (class EncodeJson, Json, encodeJson)
2727import Data.Array as Array
2828import Data.Maybe (Maybe(..))
2929import Data.Symbol (class IsSymbol, reflectSymbol)
30+import Data.URL (URL)
3031import Data.URL as URL
3132import Data.Unit (Unit)
3233import Effect (Effect)
@@ -36,42 +37,22 @@ import Prim.RowList (class RowToList)
3637import Prim.RowList as RowList
3738import Record as Record
3839import Type.Prelude (Proxy(..))
39−import Unsafe.Coerce (unsafeCoerce)
40−
41−class Verb :: Type -> Type -> Constraint
42−class Verb t resp | t -> resp where
43− verb :: String
4440
4541data GET :: Type -> Type
4642data GET resp
4743
48−instance Verb (GET resp) resp where
49− verb = "GET"
50−
5144data POST :: Type -> Type -> Type
5245data POST req resp
5346
54−instance Verb (POST req resp) resp where
55− verb = "POST"
56−
5747data PUT :: Type -> Type -> Type
5848data PUT req resp
5949
60−instance Verb (PUT req resp) resp where
61− verb = "PUT"
62−
6350data DELETE :: Type -> Type -> Type
6451data DELETE req resp
6552
66−instance Verb (DELETE req resp) (req -> Effect resp) where
67− verb = "DELETE"
68−
6953data PATCH :: Type -> Type -> Type
7054data PATCH req resp
7155
72−instance Verb (PATCH req resp) (req -> Effect resp) where
73− verb = "PATCH"
74−
7556data Slash :: forall k1 k2. k1 -> k2 -> Type
7657data Slash x y
7758
@@ -79,6 +60,18 @@ infixr 6 type Slash as /
7960
8061type Route = { path :: Array String, verb :: String }
8162
63+routeFromRequest :: Request -> Route
64+routeFromRequest req =
65+ { verb: Request.method req
66+ , path: case URL.fromString (Request.url req) of
67+ Nothing -> []
68+ Just url -> case URL.path url of
69+ URL.PathEmpty -> []
70+ URL.PathAbsolute p -> p
71+ URL.PathRelative p -> p
72+
73+ }
74+
8275class ParseRoute :: forall k. k -> Type -> Constraint
8376class ParseRoute route handler | route -> handler where
8477 parseRoute :: Route -> Maybe (handler -> Request -> Effect Response)
@@ -139,10 +132,10 @@ assert true = pure unit
139132assert false = empty
140133
141134class RunAPI row list handlers | row -> handlers where
142− runAPI :: Record handlers -> Request -> Effect Response
135+ runAPI :: Record handlers -> Route -> Request -> Effect Response
143136
144137instance RunAPI row RowList.Nil () where
145− runAPI _ _ = pure notFound
138+ runAPI _ _ _ = pure notFound
146139
147140instance
148141 ( ParseRoute t handler
@@ -153,19 +146,10 @@ instance
153146 , Row.Lacks field restHandlers
154147 ) =>
155148 RunAPI row (RowList.Cons field t rest) handlers where
156− runAPI handlers req = do
157− case URL.fromString (Request.url req) of
158− Nothing -> pure internalServerError
159− Just url -> do
160− let
161− path = case URL.path url of
162− URL.PathEmpty -> []
163− URL.PathAbsolute p -> p
164− URL.PathRelative p -> p
165− verb = Request.method req
166− case parseRoute @t { path, verb } of
167− Nothing -> runAPI @row @rest @restHandlers (Record.delete (Proxy @field) handlers) req
168− Just f -> f (Record.get (Proxy @field) handlers) req
149+ runAPI handlers route@{ path, verb } req =
150+ case parseRoute @t { path, verb } of
151+ Nothing -> runAPI @row @rest @restHandlers (Record.delete (Proxy @field) handlers) route req
152+ Just f -> f (Record.get (Proxy @field) handlers) req
169153
170154notFound :: Response
171155notFound = Response.string "" { status: 404, statusText: "Not Found", headers: [] }
@@ -173,8 +157,12 @@ notFound = Response.string "" { status: 404, statusText: "Not Found", headers: [
173157internalServerError :: Response
174158internalServerError = Response.string "" { status: 500, statusText: "Internal Server Error", headers: [] }
175159
176−run :: forall @row list handlers. RowToList row list => RunAPI row list handlers => Record handlers -> Request -> Effect Response
177−run = runAPI @row @list @handlers
178−
179−---------------------------------------------------------------------------------------------------
160+run
161+ :: forall @row list handlers
162+ . RowToList row list
163+ => RunAPI row list handlers
164+ => Record handlers
165+ -> Request
166+ -> Effect Response
167+run handlers req = runAPI @row @list @handlers handlers (routeFromRequest req) req
180168