@@ -30,6 +30,7 @@ import Prelude
3030import PureStack.Route
3131
3232import Bun.Request (Request)
33+import Bun.Request as Bun
3334import Bun.Request as Request
3435import Bun.Response as Bun.Response
3536import Control.Alternative (class Plus, empty)
@@ -60,7 +61,12 @@ import Record.Builder (Builder)
6061import Record.Builder as Builder
6162import Type.Proxy (Proxy(..))
6263
63−type Route = { path :: Array String, verb :: String, query :: Map String (Array String) }
64+type Route =
65+ { path :: Array String
66+ , verb :: String
67+ , query :: Map String (Array String)
68+ , originalRequest :: Bun.Request
69+ }
6470
6571routeFromRequest :: Request -> Route
6672routeFromRequest req =
@@ -77,67 +83,81 @@ routeFromRequest req =
7783 , query: case url of
7884 Nothing -> Map.empty
7985 Just u -> URL.query u
86+ , originalRequest: req
8087 }
8188
8289type Server a = ExceptT Response Aff a
8390
8491newtype Nt m = Nt (forall x. m x -> Server x)
8592
86−class ServeRoute :: forall k. k -> Type -> (Type -> Type) -> Constraint
87−class ServeRoute route handler m | route -> handler, handler -> m where
88− serveRoute :: Route -> Maybe (Nt m -> handler -> Request -> Server Response)
93+class ServeRoute :: forall k. k -> Type -> Row Type -> (Type -> Type) -> Constraint
94+class ServeRoute route handler middlewares m | route middlewares -> handler, handler -> m where
95+ serveRoute :: Route -> Maybe (Nt m -> handler -> Record middlewares -> Request -> Server Response)
8996
90−instance (ServeRoute rest handler m, IsSymbol path) => ServeRoute (path / rest) handler m where
97+instance (ServeRoute rest handler middlewares m, IsSymbol path) => ServeRoute (path / rest) handler middlewares m where
9198 serveRoute route@{ path } = do
9299 { head: h, tail } <- Array.uncons path
93100 assert $ h == (reflectSymbol @path Proxy)
94101 serveRoute @rest route { path = tail }
95102
96103else instance
97− ( ServeRoute rest handler m
104+ ( ServeRoute rest handler middlewares m
98105 , ServeQuery row list
99106 , RowToList row list
100107 ) =>
101− ServeRoute (Record row / rest) (Record row -> handler) m where
108+ ServeRoute (Record row / rest) (Record row -> handler) middlewares m where
102109 serveRoute route@{ query } = do
103110 builder <- serveQuery @row @list query
104111 serveRoute @rest route <#> (\f nt handler req -> f nt (handler $ Builder.buildFromScratch builder) req)
105112
106−else instance (ServeRoute rest handler m, ParsePathPiece t) => ServeRoute (t / rest) (t -> handler) m where
113+else instance
114+ ( ServeRoute rest handler middlewares m
115+ , IsSymbol field
116+ , Row.Cons field (Bun.Request -> m x) tail middlewares
117+ ) =>
118+ ServeRoute (Middleware field / rest) (x -> handler) middlewares m where
119+ serveRoute route@{ originalRequest } = do
120+ serveRoute @rest route <#>
121+ ( \f nt@(Nt ntf) handler middlewares req -> do
122+ x <- ntf $ Record.get (Proxy @field) middlewares originalRequest
123+ f nt (handler x) middlewares req
124+ )
125+
126+else instance (ServeRoute rest handler middlewares m, ParsePathPiece t) => ServeRoute (t / rest) (t -> handler) middlewares m where
107127 serveRoute route@{ path } = do
108128 { head: h, tail } <- Array.uncons path
109129 t <- parsePathPiece @t h
110− serveRoute @rest route { path = tail } <#> (\f nt handler req -> f nt (handler t) req)
130+ serveRoute @rest route { path = tail } <#> (\f nt handler mws req -> f nt (handler t) mws req)
111131
112−else instance MethodName (meth Unit Unit) => ServeRoute (meth Unit Unit) (m Unit) m where
132+else instance MethodName (meth Unit Unit) => ServeRoute (meth Unit Unit) (m Unit) middlewares m where
113133 serveRoute { path, verb } = do
114134 assert $ verb == methodName @(meth Unit Unit)
115135 assert $ path == []
116− pure $ \(Nt nt) handler _req -> do
136+ pure $ \(Nt nt) handler _middlewares _req -> do
117137 nt handler
118138 pure $ ok
119−else instance (ToResponse resp, MethodName (meth Unit resp)) => ServeRoute (meth Unit resp) (m resp) m where
139+else instance (ToResponse resp, MethodName (meth Unit resp)) => ServeRoute (meth Unit resp) (m resp) middlewares m where
120140 serveRoute { path, verb } = do
121141 assert $ verb == methodName @(meth Unit resp)
122142 assert $ path == []
123− pure $ \(Nt nt) handler _req -> do
143+ pure $ \(Nt nt) handler _middlewares _req -> do
124144 resp <- nt handler
125145 pure $ toResponse resp
126−else instance (FromRequest req, MethodName (meth resp Unit)) => ServeRoute (meth resp Unit) (req -> m Unit) m where
146+else instance (FromRequest req, MethodName (meth resp Unit)) => ServeRoute (meth resp Unit) (req -> m Unit) middlewares m where
127147 serveRoute { path, verb } = do
128148 assert $ verb == methodName @(meth resp Unit)
129149 assert $ path == []
130− pure $ \(Nt nt) handler req -> do
150+ pure $ \(Nt nt) handler _middlewares req -> do
131151 liftAff (fromRequest req) >>= case _ of
132152 Nothing -> pure $ badRequest
133153 Just r -> do
134154 nt $ handler r
135155 pure $ ok
136−else instance (FromRequest req, ToResponse resp, MethodName (meth req resp)) => ServeRoute (meth req resp) (req -> m resp) m where
156+else instance (FromRequest req, ToResponse resp, MethodName (meth req resp)) => ServeRoute (meth req resp) (req -> m resp) middlewares m where
137157 serveRoute { path, verb } = do
138158 assert $ verb == methodName @(meth req resp)
139159 assert $ path == []
140− pure $ \(Nt nt) handler req -> do
160+ pure $ \(Nt nt) handler _middlewares req -> do
141161 liftAff (fromRequest req) >>= case _ of
142162 Nothing -> pure $ badRequest
143163 Just r -> do
@@ -145,12 +165,12 @@ else instance (FromRequest req, ToResponse resp, MethodName (meth req resp)) =>
145165 pure $ toResponse resp
146166
147167else instance
148− ( ServeAPI routes list handlers m
168+ ( ServeAPI routes list handlers middlewares m
149169 , RowToList routes list
150170 ) =>
151− ServeRoute routes (Record handlers) m where
152− serveRoute route = pure $ \nt handlers req ->
153− serveAPI @routes @list nt handlers route req
171+ ServeRoute routes (Record handlers) middlewares m where
172+ serveRoute route = pure $ \nt handlers middlewares req ->
173+ serveAPI @routes @list nt handlers middlewares route req
154174
155175class ServeQuery :: Row Type -> RowList Type -> Constraint
156176class ServeQuery row list | list -> row where
@@ -337,26 +357,26 @@ assert :: forall m. Applicative m => Plus m => Boolean -> m Unit
337357assert true = pure unit
338358assert false = empty
339359
340−class ServeAPI :: Row Type -> RowList Type -> Row Type -> (Type -> Type) -> Constraint
341−class ServeAPI row list handlers m | row -> handlers, handlers -> m where
342− serveAPI :: Nt m -> Record handlers -> Route -> Request -> Server Response
360+class ServeAPI :: Row Type -> RowList Type -> Row Type -> Row Type -> (Type -> Type) -> Constraint
361+class ServeAPI row list handlers middlewares m | row -> handlers, handlers -> m where
362+ serveAPI :: Nt m -> Record handlers -> Record middlewares -> Route -> Request -> Server Response
343363
344−instance ServeAPI row RowList.Nil () m where
345− serveAPI _ _ _ _ = pure notFound
364+instance ServeAPI row RowList.Nil () middlewares m where
365+ serveAPI _ _ _ _ _ = pure notFound
346366
347367instance
348− ( ServeRoute t handler m
368+ ( ServeRoute t handler middlewares m
349369 , Row.Cons field t tail row
350− , ServeAPI row rest restHandlers m
370+ , ServeAPI row rest restHandlers middlewares m
351371 , IsSymbol field
352372 , Row.Cons field handler restHandlers handlers
353373 , Row.Lacks field restHandlers
354374 ) =>
355− ServeAPI row (RowList.Cons field t rest) handlers m where
356− serveAPI nt handlers route req =
375+ ServeAPI row (RowList.Cons field t rest) handlers middlewares m where
376+ serveAPI nt handlers middlewares route req =
357377 case serveRoute @t route of
358− Nothing -> serveAPI @row @rest @restHandlers nt (Record.delete (Proxy @field) handlers) route req
359− Just f -> f nt (Record.get (Proxy @field) handlers) req
378+ Nothing -> serveAPI @row @rest @restHandlers @middlewares nt (Record.delete (Proxy @field) handlers) middlewares route req
379+ Just f -> f nt (Record.get (Proxy @field) handlers) middlewares req
360380
361381notFound :: Response
362382notFound = Response { body: EmptyResponseBody, status: 404, statusText: "Not Found", headers: Object.empty }
@@ -373,16 +393,16 @@ ok = Response { body: EmptyResponseBody, status: 200, statusText: "OK", headers:
373393-- | The first argument is used to run an arbitrary monad in handlers. To use the 'Server' monad
374394-- | instead you can just pass `identity` as the first argument.
375395run
376− :: forall @row list handlers m
396+ :: forall @row list handlers m middlewares
377397 . RowToList row list
378− => ServeAPI row list handlers m
398+ => ServeAPI row list handlers middlewares m
379399 => (forall x. m x -> Server x)
380− -> { handlers :: Record handlers }
400+ -> { handlers :: Record handlers, middlewares :: Record middlewares }
381401 -> Request
382402 -> Aff Bun.Response.Response
383−run nt { handlers } req = do
403+run nt { handlers, middlewares } req = do
384404 Response { body, headers, status, statusText } <-
385− map (either identity identity) $ runExceptT $ serveAPI @row @list @handlers (Nt nt) handlers (routeFromRequest req) req
405+ map (either identity identity) $ runExceptT $ serveAPI @row @list @handlers (Nt nt) handlers middlewares (routeFromRequest req) req
386406 let opts = { headers, status, statusText }
387407 pure $ case body of
388408 EmptyResponseBody -> Bun.Response.string "" opts