diff --git a/examples/pokedex/src/Api.elm b/examples/pokedex/src/Api.elm index 36f6029c..c05bf938 100644 --- a/examples/pokedex/src/Api.elm +++ b/examples/pokedex/src/Api.elm @@ -20,12 +20,11 @@ routes : -> (Html Never -> String) -> List (ApiRoute.ApiRoute ApiRoute.Response) routes getStaticRoutes htmlToString = - [ -- route1 - --, route2 - nonHybridRoute + [ nonHybridRoute , noArgs , redirectRoute , serverRequestInfo + , repoStars ] @@ -39,7 +38,7 @@ serverRequestInfo = |> ApiRoute.literal "api" |> ApiRoute.slash |> ApiRoute.literal "request" - |> ApiRoute.singleServerless + |> ApiRoute.serverless redirectRoute : ApiRoute ApiRoute.Response @@ -51,7 +50,7 @@ redirectRoute = |> ApiRoute.literal "api" |> ApiRoute.slash |> ApiRoute.literal "redirect" - |> ApiRoute.singleServerless + |> ApiRoute.serverless serverRequestDataSource = @@ -90,7 +89,7 @@ noArgs = |> ApiRoute.literal "api" |> ApiRoute.slash |> ApiRoute.literal "stars" - |> ApiRoute.singleServerless + |> ApiRoute.serverless nonHybridRoute = @@ -119,6 +118,31 @@ nonHybridRoute = ) +repoStars : ApiRoute ApiRoute.Response +repoStars = + ApiRoute.succeed + (\repoName -> + DataSource.Http.get + (Secrets.succeed ("https://api.github.com/repos/dillonkearns/" ++ repoName)) + (Decode.field "stargazers_count" Decode.int) + |> DataSource.map + (\stars -> + Json.Encode.object + [ ( "repo", Json.Encode.string repoName ) + , ( "stars", Json.Encode.int stars ) + ] + |> ServerResponse.json + ) + ) + |> ApiRoute.literal "api" + |> ApiRoute.slash + |> ApiRoute.literal "repo" + |> ApiRoute.slash + |> ApiRoute.capture + --|> ApiRoute.literal ".json" + |> ApiRoute.serverless + + route1 = ApiRoute.succeed (\repoName -> @@ -138,30 +162,3 @@ route1 = |> ApiRoute.slash |> ApiRoute.capture |> ApiRoute.literal ".json" - |> ApiRoute.buildTimeRoutes - (\route -> - DataSource.succeed - [ route "elm-graphql" - ] - ) - - -route2 : ApiRoute ApiRoute.Response -route2 = - ApiRoute.succeed - (DataSource.succeed route1Pattern) - |> ApiRoute.literal "api-patterns.json" - |> ApiRoute.single - - -route1Pattern : String -route1Pattern = - case route1 of - ----Internal.ApiRoute.ApiRouteBuilder String (List String -> a) (List String -> String) (List String -> constructor) - --Internal.ApiRoute.ApiRouteBuilder pattern _ _ _ -> - -- pattern - -- - Internal.ApiRoute.ApiRoute record -> - --record.regex - -- |> Debug.toString - record.pattern |> Debug.toString diff --git a/generator/src/render-worker.js b/generator/src/render-worker.js index a8174eb1..52bc6e00 100644 --- a/generator/src/render-worker.js +++ b/generator/src/render-worker.js @@ -79,7 +79,7 @@ async function outputString( break; } case "api-response": { - const body = fromElm.body; + const body = fromElm.body.body; console.log(`Generated ${pathname}`); fs.writeFileSyncSafe(path.join("dist", pathname), body); if (pathname === "/all-paths.json") { diff --git a/src/ApiRoute.elm b/src/ApiRoute.elm index 691d2e0c..79e71253 100644 --- a/src/ApiRoute.elm +++ b/src/ApiRoute.elm @@ -1,6 +1,6 @@ module ApiRoute exposing ( ApiRoute, ApiRouteBuilder, Response, buildTimeRoutes, capture, int, literal, single, slash, succeed, getBuildTimeRoutes - , singleServerless, toJson + , serverless, toJson ) {-| ApiRoute's are defined in `src/Api.elm` and are a way to generate files, like RSS feeds, sitemaps, or any text-based file that you output with an Elm function! You get access @@ -72,33 +72,27 @@ encodeServerResponse serverResponse = ] -{-| -} -singleServerless : ApiRouteBuilder (DataSource ServerResponse) (List String) -> ApiRoute Response -singleServerless ((ApiRouteBuilder patterns pattern _ toString constructor) as fullHandler) = +serverless : ApiRouteBuilder (DataSource ServerResponse) constructor -> ApiRoute Response +serverless ((ApiRouteBuilder patterns pattern _ toString constructor) as fullHandler) = ApiRoute { regex = Regex.fromString ("^" ++ pattern ++ "$") |> Maybe.withDefault Regex.never , matchesToResponse = \path -> - let - routeFound : DataSource Bool - routeFound = - DataSource.succeed ((path |> normalizePath) == (pattern |> normalizePath)) - in - routeFound - |> DataSource.andThen - (\found -> - if found then - Internal.ApiRoute.tryMatch path fullHandler - |> Maybe.map (DataSource.map (encodeServerResponse >> Just)) - |> Maybe.withDefault (DataSource.succeed Nothing) - - else - DataSource.succeed Nothing - ) + Internal.ApiRoute.tryMatch path fullHandler + |> Maybe.map (DataSource.map (encodeServerResponse >> Just)) + |> Maybe.withDefault + (DataSource.succeed Nothing) , buildTimeRoutes = DataSource.succeed [] , handleRoute = \path -> - DataSource.succeed (path == pattern) + DataSource.succeed + (case Internal.ApiRoute.tryMatch path fullHandler of + Just _ -> + True + + Nothing -> + False + ) , pattern = patterns , kind = "serverless" } diff --git a/tests/ApiRouteTests.elm b/tests/ApiRouteTests.elm index 72abbd20..d4e952f8 100644 --- a/tests/ApiRouteTests.elm +++ b/tests/ApiRouteTests.elm @@ -5,6 +5,7 @@ import DataSource import Expect import Internal.ApiRoute exposing (tryMatch, withRoutes) import Pattern exposing (Pattern(..)) +import ServerResponse import Test exposing (Test, describe, test) @@ -15,50 +16,50 @@ all = \() -> succeed (\userId -> - { body = "Data for user " ++ userId } + "Data for user " ++ userId ) |> capture |> tryMatch "123" - |> Expect.equal (Just { body = "Data for user 123" }) + |> Expect.equal (Just "Data for user 123") , test "file with extension" <| \() -> succeed (\userId -> - { body = "Data for user " ++ userId } + "Data for user " ++ userId ) |> capture |> literal ".json" |> tryMatch "124.json" - |> Expect.equal (Just { body = "Data for user 124" }) + |> Expect.equal (Just "Data for user 124") , test "file path with multiple segments" <| \() -> succeed (\userId -> - { body = "Data for user " ++ userId } + "Data for user " ++ userId ) |> literal "users" |> slash |> capture |> literal ".json" |> tryMatch "users/123.json" - |> Expect.equal (Just { body = "Data for user 123" }) + |> Expect.equal (Just "Data for user 123") , test "integer matcher" <| \() -> succeed (\userId -> - { body = "Data for user " ++ String.fromInt userId } + "Data for user " ++ String.fromInt userId ) |> literal "users" |> slash |> int |> literal ".json" |> tryMatch "users/123.json" - |> Expect.equal (Just { body = "Data for user 123" }) + |> Expect.equal (Just "Data for user 123") , test "routes" <| \() -> succeed (\userId -> - { body = "Data for user " ++ userId } + "Data for user " ++ userId ) |> literal "users" |> slash @@ -78,18 +79,25 @@ all = [ test "no dynamic segments" <| \() -> succeed - (DataSource.succeed { body = "" }) + ("" + |> ServerResponse.stringBody + |> DataSource.succeed + ) |> literal "no-dynamic-segments.json" - |> ApiRoute.singleServerless + |> ApiRoute.serverless |> Internal.ApiRoute.toPattern |> Expect.equal (Pattern [ Pattern.Literal "no-dynamic-segments.json" ] Pattern.NoPendingSlash) , test "two literal segments" <| \() -> - ApiRoute.succeed (DataSource.succeed { body = "" }) + ApiRoute.succeed + ("" + |> ServerResponse.stringBody + |> DataSource.succeed + ) |> ApiRoute.literal "api" |> ApiRoute.slash |> ApiRoute.literal "stars" - |> ApiRoute.singleServerless + |> ApiRoute.serverless |> Internal.ApiRoute.toPattern |> Expect.equal (Pattern @@ -102,7 +110,7 @@ all = \() -> succeed (\userId -> - DataSource.succeed { body = "Data for user " ++ userId } + DataSource.succeed ("Data for user " ++ userId) ) |> literal "users" |> slash @@ -133,7 +141,7 @@ all = \() -> succeed (\_ _ -> - { body = "Data for user" } + "Data for user" ) |> literal "repos" |> slash @@ -155,7 +163,7 @@ all = \() -> succeed (\username repo branch -> - { body = [ username, repo, branch ] |> String.join " - " } + [ username, repo, branch ] |> String.join " - " ) |> literal "repos" |> slash