From 473557681afe69156b00baa0475364d89c3a4fcd Mon Sep 17 00:00:00 2001 From: Dillon Kearns Date: Mon, 24 Apr 2023 10:18:07 -0700 Subject: [PATCH] Fix issue with inifinite loop, now give proper error message for frontmatter decoding errors. --- src/BackendTask/File.elm | 27 +++++++++++---- src/BackendTask/Internal/Request.elm | 51 ++++++++++++++++++++++++++-- src/FatalError.elm | 5 ++- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/src/BackendTask/File.elm b/src/BackendTask/File.elm index 5d42787c..551c4dc7 100644 --- a/src/BackendTask/File.elm +++ b/src/BackendTask/File.elm @@ -65,7 +65,7 @@ frontmatter frontmatterDecoder = import BackendTask exposing (BackendTask) import BackendTask.File as File - import Decode as Decode exposing (Decoder) + import Decode exposing (Decoder) blogPost : BackendTask BlogPostMetadata blogPost = @@ -101,7 +101,7 @@ It's common to parse the body with a markdown parser or other format. import BackendTask exposing (BackendTask) import BackendTask.File as File - import Decode as Decode exposing (Decoder) + import Decode exposing (Decoder) import Html exposing (Html) example : @@ -174,7 +174,7 @@ just the metadata. import BackendTask exposing (BackendTask) import BackendTask.File as File - import Decode as Decode exposing (Decoder) + import Decode exposing (Decoder) blogPost : BackendTask BlogPostMetadata blogPost = @@ -198,7 +198,7 @@ the [`BackendTask`](BackendTask) API along with [`BackendTask.Glob`](BackendTask import BackendTask exposing (BackendTask) import BackendTask.File as File - import Decode as Decode exposing (Decoder) + import Decode exposing (Decoder) blogPostFiles : BackendTask (List String) blogPostFiles = @@ -231,8 +231,23 @@ onlyFrontmatter : } frontmatter onlyFrontmatter frontmatterDecoder filePath = - read filePath - (frontmatter frontmatterDecoder) + BackendTask.Internal.Request.request2 + { name = "read-file" + , body = BackendTask.Http.stringBody "" filePath + , expect = frontmatter frontmatterDecoder + , errorDecoder = Decode.field "errorCode" (errorDecoder filePath) + , onError = + \frontmatterDecodeError -> + { fatal = + { title = "BackendTask.File Decoder Error" + , body = + "I encountered a Json Decoder error from a call to BackendTask.File.onlyFrontmatter.\n\n" + ++ Decode.errorToString frontmatterDecodeError + } + |> FatalError.build + , recoverable = DecodingError frontmatterDecodeError + } + } {-| Same as `bodyWithFrontmatter` except it doesn't include the frontmatter. diff --git a/src/BackendTask/Internal/Request.elm b/src/BackendTask/Internal/Request.elm index 4890fc1e..3104ea6a 100644 --- a/src/BackendTask/Internal/Request.elm +++ b/src/BackendTask/Internal/Request.elm @@ -1,7 +1,9 @@ -module BackendTask.Internal.Request exposing (request) +module BackendTask.Internal.Request exposing (request, request2) import BackendTask exposing (BackendTask) -import BackendTask.Http exposing (Body, Expect) +import BackendTask.Http exposing (Body, Error(..), Expect) +import Json.Decode exposing (Decoder) +import Json.Encode as Encode request : @@ -22,7 +24,50 @@ request ({ name, body, expect } as params) = } expect |> BackendTask.onError - (\_ -> + (\error -> + let + _ = + Debug.log "BackendTask.Internal.Request" error + in -- TODO avoid crash here, this should be handled as an internal error request params ) + + +request2 : + { name : String + , body : Body + , expect : Decoder a + , errorDecoder : Decoder error + , onError : Json.Decode.Error -> error + } + -> BackendTask error a +request2 ({ name, body, expect, onError, errorDecoder } as params) = + -- elm-review: known-unoptimized-recursion + BackendTask.Http.request + { url = "elm-pages-internal://" ++ name + , method = "GET" + , headers = [] + , body = body + , timeoutInMs = Nothing + , retries = Nothing + } + (BackendTask.Http.expectJson Json.Decode.value) + |> BackendTask.onError + (\error -> + BackendTask.succeed Encode.null + ) + |> BackendTask.andThen + (\decodeValue -> + case Json.Decode.decodeValue errorDecoder decodeValue of + Ok a -> + BackendTask.fail a + + Err _ -> + case Json.Decode.decodeValue expect decodeValue of + Ok a -> + BackendTask.succeed a + + Err e -> + BackendTask.fail (onError e) + ) diff --git a/src/FatalError.elm b/src/FatalError.elm index 3d5256f8..2451ef4f 100644 --- a/src/FatalError.elm +++ b/src/FatalError.elm @@ -1,4 +1,7 @@ -module FatalError exposing (FatalError, fromString, recoverable) +module FatalError exposing + ( FatalError, fromString, recoverable + , build + ) {-| The Elm language doesn't have the concept of exceptions or special control flow for errors. It just has Custom Types, and by convention types like `Result` and the `Err` variant are used to represent possible failure states