Remove Handler type in favor of a type variable for ServerRequest type.

This commit is contained in:
Dillon Kearns 2021-12-31 11:14:23 -08:00
parent 04ebcc0190
commit 3aae8c1adf
10 changed files with 103 additions and 126 deletions

View File

@ -5,6 +5,7 @@ import DataSource exposing (DataSource)
import DataSource.Http import DataSource.Http
import DataSource.ServerRequest as ServerRequest exposing (ServerRequest) import DataSource.ServerRequest as ServerRequest exposing (ServerRequest)
import Html exposing (Html) import Html exposing (Html)
import Json.Decode
import Json.Encode import Json.Encode
import OptimizedDecoder as Decode import OptimizedDecoder as Decode
import QueryParams import QueryParams
@ -28,9 +29,31 @@ routes getStaticRoutes htmlToString =
, logout , logout
, greet , greet
, fileLength , fileLength
, jsonError
] ]
jsonError : Server.Request.ServerRequest ServerResponse.ServerResponse
jsonError =
Server.Request.oneOf
[ Server.Request.jsonBodyResult (Decode.field "name" Decode.string)
|> Server.Request.map
(\result ->
case result of
Ok firstName ->
ServerResponse.stringBody
("Hello " ++ firstName)
Err decodeError ->
decodeError
|> Json.Decode.errorToString
|> ServerResponse.stringBody
|> ServerResponse.withStatusCode 400
)
, Server.Request.succeed (ServerResponse.stringBody "Hello anonymous!")
]
greet : ApiRoute ApiRoute.Response greet : ApiRoute ApiRoute.Response
greet = greet =
ApiRoute.succeed ApiRoute.succeed
@ -46,7 +69,7 @@ greet =
field "first" field "first"
) )
] ]
|> Server.Request.thenRespond |> Server.Request.map
(\firstName -> (\firstName ->
ServerResponse.stringBody ("Hello " ++ firstName) ServerResponse.stringBody ("Hello " ++ firstName)
|> DataSource.succeed |> DataSource.succeed
@ -65,7 +88,7 @@ fileLength =
(\{ field, optionalField, fileField } -> (\{ field, optionalField, fileField } ->
fileField "file" fileField "file"
) )
|> Server.Request.thenRespond |> Server.Request.map
(\file -> (\file ->
ServerResponse.json ServerResponse.json
(Json.Encode.object (Json.Encode.object
@ -94,12 +117,10 @@ fileLength =
redirectRoute : ApiRoute ApiRoute.Response redirectRoute : ApiRoute ApiRoute.Response
redirectRoute = redirectRoute =
ApiRoute.succeed ApiRoute.succeed
(Server.Request.succeed () (Server.Request.succeed
|> Server.Request.thenRespond (DataSource.succeed
(\() -> (ServerResponse.temporaryRedirect "/")
DataSource.succeed )
(ServerResponse.temporaryRedirect "/")
)
) )
|> ApiRoute.literal "api" |> ApiRoute.literal "api"
|> ApiRoute.slash |> ApiRoute.slash
@ -128,21 +149,19 @@ serverRequestDataSource isAvailable =
noArgs : ApiRoute ApiRoute.Response noArgs : ApiRoute ApiRoute.Response
noArgs = noArgs =
ApiRoute.succeed ApiRoute.succeed
(Server.Request.succeed () (Server.Request.succeed
|> Server.Request.thenRespond (DataSource.Http.get
(\() -> (Secrets.succeed "https://api.github.com/repos/dillonkearns/elm-pages")
DataSource.Http.get (Decode.field "stargazers_count" Decode.int)
(Secrets.succeed "https://api.github.com/repos/dillonkearns/elm-pages") |> DataSource.map
(Decode.field "stargazers_count" Decode.int) (\stars ->
|> DataSource.map Json.Encode.object
(\stars -> [ ( "repo", Json.Encode.string "elm-pages" )
Json.Encode.object , ( "stars", Json.Encode.int stars )
[ ( "repo", Json.Encode.string "elm-pages" ) ]
, ( "stars", Json.Encode.int stars ) |> ServerResponse.json
] )
|> ServerResponse.json )
)
)
) )
|> ApiRoute.literal "api" |> ApiRoute.literal "api"
|> ApiRoute.slash |> ApiRoute.slash
@ -179,20 +198,18 @@ nonHybridRoute =
logout : ApiRoute ApiRoute.Response logout : ApiRoute ApiRoute.Response
logout = logout =
ApiRoute.succeed ApiRoute.succeed
(Server.Request.succeed () (Server.Request.succeed
|> Server.Request.thenRespond (DataSource.succeed
(\() -> (ServerResponse.stringBody "You are logged out"
DataSource.succeed |> ServerResponse.withHeader "Set-Cookie"
(ServerResponse.stringBody "You are logged out" (SetCookie.setCookie "username" ""
|> ServerResponse.withHeader "Set-Cookie" |> SetCookie.httpOnly
(SetCookie.setCookie "username" "" |> SetCookie.withPath "/"
|> SetCookie.httpOnly |> SetCookie.withImmediateExpiration
|> SetCookie.withPath "/" |> SetCookie.toString
|> SetCookie.withImmediateExpiration
|> SetCookie.toString
)
) )
) )
)
) )
|> ApiRoute.literal "api" |> ApiRoute.literal "api"
|> ApiRoute.slash |> ApiRoute.slash
@ -204,21 +221,19 @@ repoStars : ApiRoute ApiRoute.Response
repoStars = repoStars =
ApiRoute.succeed ApiRoute.succeed
(\repoName -> (\repoName ->
Server.Request.succeed () Server.Request.succeed
|> Server.Request.thenRespond (DataSource.Http.get
(\() -> (Secrets.succeed ("https://api.github.com/repos/dillonkearns/" ++ repoName))
DataSource.Http.get (Decode.field "stargazers_count" Decode.int)
(Secrets.succeed ("https://api.github.com/repos/dillonkearns/" ++ repoName)) |> DataSource.map
(Decode.field "stargazers_count" Decode.int) (\stars ->
|> DataSource.map Json.Encode.object
(\stars -> [ ( "repo", Json.Encode.string repoName )
Json.Encode.object , ( "stars", Json.Encode.int stars )
[ ( "repo", Json.Encode.string repoName ) ]
, ( "stars", Json.Encode.int stars ) |> ServerResponse.json
] )
|> ServerResponse.json )
)
)
) )
|> ApiRoute.literal "api" |> ApiRoute.literal "api"
|> ApiRoute.slash |> ApiRoute.slash

View File

@ -39,22 +39,19 @@ type alias Data =
Maybe Request.File Maybe Request.File
data : RouteParams -> Request.Handler (PageServerResponse Data) data : RouteParams -> Request.ServerRequest (DataSource (PageServerResponse Data))
data routeParams = data routeParams =
Request.oneOfHandler Request.oneOf
[ Request.expectMultiPartFormPost [ Request.expectMultiPartFormPost
(\{ field, optionalField, fileField } -> (\{ field, optionalField, fileField } ->
fileField "file" fileField "file"
) )
|> Request.thenRespond |> Request.map
(\file -> (\file ->
DataSource.succeed (PageServerResponse.RenderPage (Just file)) DataSource.succeed (PageServerResponse.RenderPage (Just file))
) )
, Request.succeed () , Request.succeed
|> Request.thenRespond (DataSource.succeed (PageServerResponse.RenderPage Nothing))
(\() ->
DataSource.succeed (PageServerResponse.RenderPage Nothing)
)
] ]

View File

@ -39,13 +39,13 @@ page =
|> Page.buildNoState { view = view } |> Page.buildNoState { view = view }
data : RouteParams -> Request.Handler (PageServerResponse Data) data : RouteParams -> Request.ServerRequest (DataSource (PageServerResponse Data))
data routeParams = data routeParams =
Request.oneOfHandler Request.oneOf
[ Request.map2 Data [ Request.map2 Data
(Request.expectQueryParam "name") (Request.expectQueryParam "name")
Request.requestTime Request.requestTime
|> Request.thenRespond |> Request.map
(\requestData -> (\requestData ->
requestData requestData
|> PageServerResponse.RenderPage |> PageServerResponse.RenderPage
@ -54,18 +54,16 @@ data routeParams =
, Request.map2 Data , Request.map2 Data
(Request.expectCookie "username") (Request.expectCookie "username")
Request.requestTime Request.requestTime
|> Request.thenRespond |> Request.map
(\requestData -> (\requestData ->
requestData requestData
|> PageServerResponse.RenderPage |> PageServerResponse.RenderPage
|> DataSource.succeed |> DataSource.succeed
) )
, Request.succeed () , Request.succeed
|> Request.thenRespond (DataSource.succeed
(\() -> (PageServerResponse.ServerResponse (ServerResponse.temporaryRedirect "/login"))
DataSource.succeed )
(PageServerResponse.ServerResponse (ServerResponse.temporaryRedirect "/login"))
)
] ]

View File

@ -44,11 +44,11 @@ type alias Request =
} }
data : RouteParams -> Request.Handler (PageServerResponse Data) data : RouteParams -> Request.ServerRequest (DataSource (PageServerResponse Data))
data routeParams = data routeParams =
Request.oneOfHandler Request.oneOf
[ Request.expectFormPost (\{ field } -> field "name") [ Request.expectFormPost (\{ field } -> field "name")
|> Request.thenRespond |> Request.map
(\name -> (\name ->
PageServerResponse.ServerResponse PageServerResponse.ServerResponse
("/greet" ("/greet"
@ -63,7 +63,7 @@ data routeParams =
|> DataSource.succeed |> DataSource.succeed
) )
, Request.cookie "username" , Request.cookie "username"
|> Request.thenRespond |> Request.map
(\name -> (\name ->
name name
|> Data |> Data

View File

@ -49,11 +49,11 @@ type alias LoggedInInfo =
} }
data : RouteParams -> Request.Handler (PageServerResponse Data) data : RouteParams -> Request.ServerRequest (DataSource (PageServerResponse Data))
data routeParams = data routeParams =
Request.oneOfHandler Request.oneOf
[ Request.expectCookie "username" [ Request.expectCookie "username"
|> Request.thenRespond |> Request.map
(\username -> (\username ->
username username
|> LoggedInInfo |> LoggedInInfo
@ -62,18 +62,16 @@ data routeParams =
|> DataSource.map LoggedIn |> DataSource.map LoggedIn
|> DataSource.map PageServerResponse.RenderPage |> DataSource.map PageServerResponse.RenderPage
) )
, Request.succeed () , Request.succeed
|> Request.thenRespond (NotLoggedIn
(\() -> |> DataSource.succeed
NotLoggedIn |> DataSource.map PageServerResponse.RenderPage
|> DataSource.succeed --"/login"
|> DataSource.map PageServerResponse.RenderPage -- |> ServerResponse.temporaryRedirect
--"/login" -- --|> ServerResponse.withStatusCode 404
-- |> ServerResponse.temporaryRedirect -- |> PageServerResponse.ServerResponse
-- --|> ServerResponse.withStatusCode 404 -- |> DataSource.succeed
-- |> PageServerResponse.ServerResponse )
-- |> DataSource.succeed
)
] ]

View File

@ -95,10 +95,10 @@ type alias Request =
-- |> DataSource.map PageServerResponse.RenderPage -- |> DataSource.map PageServerResponse.RenderPage
data : RouteParams -> Request.Handler (PageServerResponse Data) data : RouteParams -> Request.ServerRequest (DataSource (PageServerResponse Data))
data routeParams = data routeParams =
Request.succeed () Request.succeed ()
|> Request.thenRespond |> Request.map
(\() -> (\() ->
PageServerResponse.ServerResponse (ServerResponse.stringBody "Hello, this is a string") PageServerResponse.ServerResponse (ServerResponse.stringBody "Hello, this is a string")
|> DataSource.succeed |> DataSource.succeed

View File

@ -335,7 +335,7 @@ preRenderWithFallback { data, head, pages } =
{-| -} {-| -}
serverRender : serverRender :
{ data : routeParams -> Server.Request.Handler (PageServerResponse data) { data : routeParams -> Server.Request.ServerRequest (DataSource (PageServerResponse data))
, head : StaticPayload data routeParams -> List Head.Tag , head : StaticPayload data routeParams -> List Head.Tag
} }
-> Builder routeParams data -> Builder routeParams data

View File

@ -182,7 +182,7 @@ type alias Data =
${ ${
serverRender serverRender
? `data : RouteParams -> Request.Handler (PageServerResponse Data) ? `data : RouteParams -> Request.ServerRequest (DataSource (PageServerResponse Data))
data routeParams =` data routeParams =`
: withFallback : withFallback
? `data : RouteParams -> DataSource (PageServerResponse Data) ? `data : RouteParams -> DataSource (PageServerResponse Data)

View File

@ -87,7 +87,7 @@ stripTrailingSlash path =
{-| -} {-| -}
serverRender : ApiRouteBuilder (Server.Request.Handler ServerResponse) constructor -> ApiRoute Response serverRender : ApiRouteBuilder (Server.Request.ServerRequest (DataSource ServerResponse)) constructor -> ApiRoute Response
serverRender ((ApiRouteBuilder patterns pattern _ toString constructor) as fullHandler) = serverRender ((ApiRouteBuilder patterns pattern _ toString constructor) as fullHandler) =
ApiRoute ApiRoute
{ regex = Regex.fromString ("^" ++ pattern ++ "$") |> Maybe.withDefault Regex.never { regex = Regex.fromString ("^" ++ pattern ++ "$") |> Maybe.withDefault Regex.never

View File

@ -2,8 +2,7 @@ module Server.Request exposing
( ServerRequest(..) ( ServerRequest(..)
, Method(..) , Method(..)
, succeed , succeed
, Handler, Handlers , requestTime, optionalHeader, expectContentType, expectJsonBody, acceptMethod, jsonBodyResult
, oneOfHandler, requestTime, thenRespond, optionalHeader, expectContentType, expectJsonBody, acceptMethod, jsonBodyResult
, map, map2, oneOf, andMap , map, map2, oneOf, andMap
, expectQueryParam , expectQueryParam
, cookie, expectCookie , cookie, expectCookie
@ -162,33 +161,16 @@ succeed value =
ServerRequest (OptimizedDecoder.succeed ( Ok value, [] )) ServerRequest (OptimizedDecoder.succeed ( Ok value, [] ))
{-| -}
type Handlers response
= Handlers response
{-| -}
type Handler response
= Handler (OptimizedDecoder.Decoder (Result ( ValidationError, List ValidationError ) (DataSource response)))
{-| TODO internal only {-| TODO internal only
-} -}
getDecoder : Handler response -> OptimizedDecoder.Decoder (Result ( ValidationError, List ValidationError ) (DataSource response)) getDecoder : ServerRequest (DataSource response) -> OptimizedDecoder.Decoder (Result ( ValidationError, List ValidationError ) (DataSource response))
getDecoder (Handler decoder) = getDecoder (ServerRequest decoder) =
decoder decoder
{-| -}
thenRespond : (request -> DataSource response) -> ServerRequest request -> Handler response
thenRespond thenDataSource (ServerRequest requestDecoder) =
requestDecoder
|> OptimizedDecoder.map |> OptimizedDecoder.map
(\( result, validationErrors ) -> (\( result, validationErrors ) ->
case ( result, validationErrors ) of case ( result, validationErrors ) of
( Ok value, [] ) -> ( Ok value, [] ) ->
value value
|> thenDataSource
|> Ok |> Ok
( Err fatalError, errors ) -> ( Err fatalError, errors ) ->
@ -197,7 +179,6 @@ thenRespond thenDataSource (ServerRequest requestDecoder) =
( Ok _, firstError :: rest ) -> ( Ok _, firstError :: rest ) ->
Err ( firstError, rest ) Err ( firstError, rest )
) )
|> Handler
type ValidationError type ValidationError
@ -275,18 +256,6 @@ oneOf serverRequests =
) )
{-| -}
oneOfHandler : List (Handler a) -> Handler a
oneOfHandler serverRequests =
Handler
(oneOfInternalHandler []
(List.map
(\(Handler decoder) -> decoder)
serverRequests
)
)
{-| Decode an argument and provide it to a function in a decoder. {-| Decode an argument and provide it to a function in a decoder.
decoder : Decoder String decoder : Decoder String