From 38d6b6547709a76ea3b593277b2058ca0eb95d08 Mon Sep 17 00:00:00 2001 From: Dillon Kearns Date: Sat, 24 Apr 2021 16:01:31 -0700 Subject: [PATCH] Add serverless request Page builder. --- examples/docs/functions/render/index.js | 9 +++- examples/docs/src/Page/Time.elm | 11 +++-- examples/docs/src/ServerRequest.elm | 5 ++- generator/src/Page.elm | 43 ++++++++++++++++++- .../src/generate-template-module-connector.js | 21 ++++----- 5 files changed, 69 insertions(+), 20 deletions(-) diff --git a/examples/docs/functions/render/index.js b/examples/docs/functions/render/index.js index a1577605..957b291f 100644 --- a/examples/docs/functions/render/index.js +++ b/examples/docs/functions/render/index.js @@ -7,11 +7,17 @@ exports.handler = */ async function (event, context) { console.log(JSON.stringify(event)); + global.staticHttpCache = {}; const compiledElmPath = path.join(__dirname, "elm-pages-cli.js"); const renderer = require("../../../../generator/src/render"); try { - const renderResult = await renderer(compiledElmPath, event.path, event); + const renderResult = await renderer( + compiledElmPath, + event.path, + event, + function () {} + ); if (renderResult.kind === "json") { return { @@ -33,6 +39,7 @@ exports.handler = }; } } catch (error) { + console.error(error); return { body: `

Error

${error}
`, statusCode: 500, diff --git a/examples/docs/src/Page/Time.elm b/examples/docs/src/Page/Time.elm index d8364396..57be7546 100644 --- a/examples/docs/src/Page/Time.elm +++ b/examples/docs/src/Page/Time.elm @@ -1,12 +1,15 @@ module Page.Time exposing (Data, Model, Msg, page) import DataSource +import DataSource.Http import Document exposing (Document) import Element exposing (Element) import Head import Head.Seo as Seo +import OptimizedDecoder import Page exposing (Page, PageWithState, StaticPayload) import Pages.ImagePath as ImagePath +import Secrets import Shared @@ -28,16 +31,18 @@ type alias RouteParams = page : Page RouteParams Data page = - Page.singleRoute + Page.serverlessRoute { head = head - , data = data + , data = \_ _ -> data + , routeFound = \_ -> DataSource.succeed True } |> Page.buildNoState { view = view } data : DataSource.DataSource String data = - DataSource.succeed "TIME RESPONSE" + DataSource.Http.get (Secrets.succeed "http://localhost:8080/") + OptimizedDecoder.string diff --git a/examples/docs/src/ServerRequest.elm b/examples/docs/src/ServerRequest.elm index 6dadb597..3e55a119 100644 --- a/examples/docs/src/ServerRequest.elm +++ b/examples/docs/src/ServerRequest.elm @@ -1,6 +1,7 @@ module ServerRequest exposing (ServerRequest, expectHeader, init, optionalHeader, staticData, toStaticHttp) import DataSource +import DataSource.Http import Internal.OptimizedDecoder exposing (OptimizedDecoder) import OptimizedDecoder import Secrets @@ -17,7 +18,7 @@ init constructor = staticData : DataSource.DataSource String staticData = - DataSource.get (Secrets.succeed "$$elm-pages$$headers") + DataSource.Http.get (Secrets.succeed "$$elm-pages$$headers") (OptimizedDecoder.field "headers" (OptimizedDecoder.field "accept-language" OptimizedDecoder.string) ) @@ -25,7 +26,7 @@ staticData = toStaticHttp : ServerRequest decodesTo -> DataSource.DataSource decodesTo toStaticHttp (ServerRequest decoder) = - DataSource.get (Secrets.succeed "$$elm-pages$$headers") decoder + DataSource.Http.get (Secrets.succeed "$$elm-pages$$headers") decoder expectHeader : String -> ServerRequest (String -> value) -> ServerRequest value diff --git a/generator/src/Page.elm b/generator/src/Page.elm index a03c9aa1..50d52e94 100644 --- a/generator/src/Page.elm +++ b/generator/src/Page.elm @@ -2,10 +2,11 @@ module Page exposing ( Builder(..) , StaticPayload , withData, noData + , prerenderedRoute, singleRoute , Page, buildNoState , PageWithState, buildWithLocalState, buildWithSharedState , DynamicContext - , prerenderedRoute, singleRoute) + , serverlessRoute) {-| @@ -32,7 +33,7 @@ But before the user even requests the page, we have the following data: - `static` - this is the static data for this specific page. If you use `noData`, then this will be `()`, meaning there is no page-specific static data. @docs withData, noData -@docs prerenderedRoute, singleRoute +@docs prerenderedRoute, singleRoute, serverlessRoute ## Stateless Page Modules @@ -51,6 +52,7 @@ import DataSource exposing (DataSource) import Document exposing (Document) import Head import Pages.PagePath exposing (PagePath) +import ServerRequest exposing (ServerRequest) import Shared @@ -69,6 +71,7 @@ type alias PageWithState routeParams templateData templateModel templateMsg = , init : StaticPayload templateData routeParams -> ( templateModel, Cmd templateMsg ) , update : StaticPayload templateData routeParams -> Maybe Browser.Navigation.Key -> templateMsg -> templateModel -> Shared.Model -> ( templateModel, Cmd templateMsg, Maybe Shared.SharedMsg ) , subscriptions : routeParams -> PagePath -> templateModel -> Shared.Model -> Sub templateMsg + , handleRoute : Maybe (routeParams -> DataSource Bool) } @@ -94,6 +97,8 @@ type Builder routeParams templateData , head : StaticPayload templateData routeParams -> List Head.Tag + , serverless : Bool + , handleRoute : Maybe (routeParams -> DataSource Bool) } @@ -115,6 +120,7 @@ buildNoState { view } builderState = , init = \_ -> ( (), Cmd.none ) , update = \_ _ _ _ _ -> ( (), Cmd.none, Nothing ) , subscriptions = \_ _ _ _ -> Sub.none + , handleRoute = record.handleRoute } @@ -157,6 +163,7 @@ buildWithLocalState config builderState = , subscriptions = \routeParams path templateModel sharedModel -> config.subscriptions routeParams path templateModel + , handleRoute = record.handleRoute } @@ -198,6 +205,7 @@ buildWithSharedState config builderState = msg templateModel , subscriptions = config.subscriptions + , handleRoute = record.handleRoute } @@ -213,6 +221,8 @@ withData { data, head, staticRoutes } = { data = data , staticRoutes = staticRoutes , head = head + , serverless = False + , handleRoute = Nothing } @@ -227,6 +237,8 @@ noData { head, staticRoutes } = { data = \_ -> DataSource.succeed () , staticRoutes = staticRoutes , head = head + , serverless = False + , handleRoute = Nothing } @@ -240,6 +252,8 @@ singleRoute { data, head } = { data = \_ -> data , staticRoutes = DataSource.succeed [ {} ] , head = head + , serverless = False + , handleRoute = Nothing } @@ -254,4 +268,29 @@ prerenderedRoute { data, head, routes } = { data = data , staticRoutes = routes , head = head + , serverless = False + , handleRoute = Nothing } + + +{-| -} +serverlessRoute : + { data : (ServerRequest decodedRequest -> DataSource decodedRequest) -> routeParams -> DataSource data + , routeFound : routeParams -> DataSource Bool + , head : StaticPayload data routeParams -> List Head.Tag + } + -> Builder routeParams data +serverlessRoute { data, head, routeFound } = + WithData + { data = data ServerRequest.toStaticHttp + , staticRoutes = DataSource.succeed [] + , head = head + , serverless = True + , handleRoute = Just routeFound + } + + +type RouteFound + = Found + -- TODO other status codes, like 403? + | NotFound404 diff --git a/generator/src/generate-template-module-connector.js b/generator/src/generate-template-module-connector.js index 3848a64e..5d0ebb2e 100644 --- a/generator/src/generate-template-module-connector.js +++ b/generator/src/generate-template-module-connector.js @@ -451,17 +451,11 @@ getStaticRoutes = DataSource.combine [ ${templates .map((name) => { - if (isParameterizedRoute(name)) { - return `Page.${moduleName( - name - )}.page.staticRoutes |> DataSource.map (List.map Route.${pathNormalizedName( - name - )})`; - } else { - return `DataSource.succeed [ Route.${routeHelpers.routeVariant( - name - )} {} ]`; - } + return `Page.${moduleName( + name + )}.page.staticRoutes |> DataSource.map (List.map Route.${pathNormalizedName( + name + )})`; }) .join("\n , ")} ] @@ -634,7 +628,10 @@ function handleRoute(name) { "." )}.page.staticRoutes |> DataSource.map (List.member routeParams)`; } else { - return `DataSource.succeed True`; + return `Page.${name.join(".")}.page.handleRoute + |> Maybe.map (\\handler -> handler routeParams) + |> Maybe.withDefault (DataSource.succeed True) +`; } }