mirror of
https://github.com/dillonkearns/elm-pages-v3-beta.git
synced 2024-12-25 04:43:03 +03:00
Add DataSource.validate.
This commit is contained in:
parent
e83d6caf8a
commit
b809af6e45
@ -5,6 +5,7 @@ module DataSource exposing
|
||||
, Body, emptyBody, stringBody, jsonBody
|
||||
, andThen, resolve, combine
|
||||
, map2, map3, map4, map5, map6, map7, map8, map9
|
||||
, validate
|
||||
)
|
||||
|
||||
{-| StaticHttp requests are an alternative to doing Elm HTTP requests the traditional way using the `elm/http` package.
|
||||
@ -63,7 +64,8 @@ and describe your use case!
|
||||
import Dict exposing (Dict)
|
||||
import Dict.Extra
|
||||
import Json.Encode as Encode
|
||||
import Pages.Internal.ApplicationType exposing (ApplicationType)
|
||||
import KeepOrDiscard exposing (KeepOrDiscard)
|
||||
import Pages.Internal.ApplicationType as ApplicationType exposing (ApplicationType)
|
||||
import Pages.Internal.StaticHttpBody as Body
|
||||
import Pages.Secrets
|
||||
import Pages.StaticHttp.Request as HashRequest
|
||||
@ -144,14 +146,56 @@ map fn requestInfo =
|
||||
Request partiallyStripped ( urls, lookupFn ) ->
|
||||
Request partiallyStripped
|
||||
( urls
|
||||
, \appType rawResponses ->
|
||||
map fn (lookupFn appType rawResponses)
|
||||
, \keepOrDiscard appType rawResponses ->
|
||||
map fn (lookupFn keepOrDiscard appType rawResponses)
|
||||
)
|
||||
|
||||
Done stripped value ->
|
||||
Done stripped (fn value)
|
||||
|
||||
|
||||
dontSaveData : DataSource a -> DataSource a
|
||||
dontSaveData requestInfo =
|
||||
case requestInfo of
|
||||
RequestError _ ->
|
||||
requestInfo
|
||||
|
||||
Request partiallyStripped ( urls, lookupFn ) ->
|
||||
Request partiallyStripped
|
||||
( urls
|
||||
, \keepOrDiscard appType rawResponses ->
|
||||
lookupFn KeepOrDiscard.Discard appType rawResponses
|
||||
)
|
||||
|
||||
Done _ _ ->
|
||||
requestInfo
|
||||
|
||||
|
||||
validate :
|
||||
(unvalidated -> validated)
|
||||
-> (unvalidated -> DataSource (Result String ()))
|
||||
-> DataSource unvalidated
|
||||
-> DataSource validated
|
||||
validate markValidated validateDataSource unvalidatedDataSource =
|
||||
unvalidatedDataSource
|
||||
|> andThen
|
||||
(\unvalidated ->
|
||||
unvalidated
|
||||
|> validateDataSource
|
||||
|> andThen
|
||||
(\result ->
|
||||
case result of
|
||||
Ok () ->
|
||||
succeed <| markValidated unvalidated
|
||||
|
||||
Err error ->
|
||||
fail error
|
||||
)
|
||||
|> dontSaveData
|
||||
)
|
||||
|> dontSaveData
|
||||
|
||||
|
||||
{-| Helper to remove an inner layer of Request wrapping.
|
||||
-}
|
||||
resolve : DataSource (List (DataSource value)) -> DataSource (List value)
|
||||
@ -234,28 +278,28 @@ map2 fn request1 request2 =
|
||||
( Request newDict1 ( urls1, lookupFn1 ), Request newDict2 ( urls2, lookupFn2 ) ) ->
|
||||
Request (combineReducedDicts newDict1 newDict2)
|
||||
( urls1 ++ urls2
|
||||
, \appType rawResponses ->
|
||||
, \keepOrDiscard appType rawResponses ->
|
||||
map2 fn
|
||||
(lookupFn1 appType rawResponses)
|
||||
(lookupFn2 appType rawResponses)
|
||||
(lookupFn1 keepOrDiscard appType rawResponses)
|
||||
(lookupFn2 keepOrDiscard appType rawResponses)
|
||||
)
|
||||
|
||||
( Request dict1 ( urls1, lookupFn1 ), Done stripped2 value2 ) ->
|
||||
Request dict1
|
||||
( urls1
|
||||
, \appType rawResponses ->
|
||||
, \keepOrDiscard appType rawResponses ->
|
||||
map2 fn
|
||||
(lookupFn1 appType rawResponses)
|
||||
(lookupFn1 keepOrDiscard appType rawResponses)
|
||||
(Done stripped2 value2)
|
||||
)
|
||||
|
||||
( Done stripped2 value2, Request dict1 ( urls1, lookupFn1 ) ) ->
|
||||
Request dict1
|
||||
( urls1
|
||||
, \appType rawResponses ->
|
||||
, \keepOrDiscard appType rawResponses ->
|
||||
map2 fn
|
||||
(Done stripped2 value2)
|
||||
(lookupFn1 appType rawResponses)
|
||||
(lookupFn1 keepOrDiscard appType rawResponses)
|
||||
)
|
||||
|
||||
( Done stripped1 value1, Done stripped2 value2 ) ->
|
||||
@ -274,21 +318,22 @@ combineReducedDicts dict1 dict2 =
|
||||
|> Dict.Extra.fromListDedupe Pages.StaticHttpRequest.merge
|
||||
|
||||
|
||||
lookup : ApplicationType -> DataSource value -> RequestsAndPending -> Result Pages.StaticHttpRequest.Error ( Dict String WhatToDo, value )
|
||||
lookup : KeepOrDiscard -> ApplicationType -> DataSource value -> RequestsAndPending -> Result Pages.StaticHttpRequest.Error ( Dict String WhatToDo, value )
|
||||
lookup =
|
||||
lookupHelp Dict.empty
|
||||
|
||||
|
||||
lookupHelp : Dict String WhatToDo -> ApplicationType -> DataSource value -> RequestsAndPending -> Result Pages.StaticHttpRequest.Error ( Dict String WhatToDo, value )
|
||||
lookupHelp strippedSoFar appType requestInfo rawResponses =
|
||||
lookupHelp : Dict String WhatToDo -> KeepOrDiscard -> ApplicationType -> DataSource value -> RequestsAndPending -> Result Pages.StaticHttpRequest.Error ( Dict String WhatToDo, value )
|
||||
lookupHelp strippedSoFar keepOrDiscard appType requestInfo rawResponses =
|
||||
case requestInfo of
|
||||
RequestError error ->
|
||||
Err error
|
||||
|
||||
Request strippedResponses ( urls, lookupFn ) ->
|
||||
lookupHelp (combineReducedDicts strippedResponses strippedSoFar)
|
||||
keepOrDiscard
|
||||
appType
|
||||
(addUrls urls (lookupFn appType rawResponses))
|
||||
(addUrls urls (lookupFn keepOrDiscard appType rawResponses))
|
||||
rawResponses
|
||||
|
||||
Done stripped value ->
|
||||
@ -354,8 +399,10 @@ andThen fn requestInfo =
|
||||
-- TODO should this be non-empty Dict? Or should it be passed down some other way?
|
||||
Request Dict.empty
|
||||
( lookupUrls requestInfo
|
||||
, \appType rawResponses ->
|
||||
lookup appType
|
||||
, \keepOrDiscard appType rawResponses ->
|
||||
lookup
|
||||
keepOrDiscard
|
||||
appType
|
||||
requestInfo
|
||||
rawResponses
|
||||
|> (\result ->
|
||||
@ -407,7 +454,7 @@ succeed : a -> DataSource a
|
||||
succeed value =
|
||||
Request Dict.empty
|
||||
( []
|
||||
, \_ _ ->
|
||||
, \_ _ _ ->
|
||||
Done Dict.empty value
|
||||
)
|
||||
|
||||
|
@ -69,6 +69,7 @@ import Internal.OptimizedDecoder
|
||||
import Json.Decode
|
||||
import Json.Decode.Exploration
|
||||
import Json.Encode as Encode
|
||||
import KeepOrDiscard
|
||||
import OptimizedDecoder as Decode exposing (Decoder)
|
||||
import Pages.Internal.ApplicationType as ApplicationType
|
||||
import Pages.Internal.StaticHttpBody as Body
|
||||
@ -246,7 +247,7 @@ unoptimizedRequest requestWithSecrets expect =
|
||||
ExpectJson decoder ->
|
||||
Request Dict.empty
|
||||
( [ requestWithSecrets ]
|
||||
, \appType rawResponseDict ->
|
||||
, \keepOrDiscard appType rawResponseDict ->
|
||||
case appType of
|
||||
ApplicationType.Cli ->
|
||||
rawResponseDict
|
||||
@ -256,8 +257,13 @@ unoptimizedRequest requestWithSecrets expect =
|
||||
Just rawResponse ->
|
||||
Ok
|
||||
( Dict.singleton (Secrets.maskedLookup requestWithSecrets |> HashRequest.hash)
|
||||
(Pages.StaticHttpRequest.StripResponse
|
||||
(Decode.map (\_ -> ()) decoder)
|
||||
(case keepOrDiscard of
|
||||
KeepOrDiscard.Keep ->
|
||||
Pages.StaticHttpRequest.StripResponse
|
||||
(Decode.map (\_ -> ()) decoder)
|
||||
|
||||
KeepOrDiscard.Discard ->
|
||||
Pages.StaticHttpRequest.CliOnly
|
||||
)
|
||||
, rawResponse
|
||||
)
|
||||
@ -291,12 +297,20 @@ unoptimizedRequest requestWithSecrets expect =
|
||||
)
|
||||
|> Result.map
|
||||
(\finalRequest ->
|
||||
( strippedResponses
|
||||
|> Dict.insert
|
||||
(Secrets.maskedLookup requestWithSecrets |> HashRequest.hash)
|
||||
(Pages.StaticHttpRequest.StripResponse
|
||||
(Decode.map (\_ -> ()) decoder)
|
||||
)
|
||||
( case keepOrDiscard of
|
||||
KeepOrDiscard.Keep ->
|
||||
strippedResponses
|
||||
|> Dict.insert
|
||||
(Secrets.maskedLookup requestWithSecrets |> HashRequest.hash)
|
||||
(Pages.StaticHttpRequest.StripResponse
|
||||
(Decode.map (\_ -> ()) decoder)
|
||||
)
|
||||
|
||||
KeepOrDiscard.Discard ->
|
||||
strippedResponses
|
||||
|> Dict.insert
|
||||
(Secrets.maskedLookup requestWithSecrets |> HashRequest.hash)
|
||||
Pages.StaticHttpRequest.CliOnly
|
||||
, finalRequest
|
||||
)
|
||||
)
|
||||
@ -310,7 +324,8 @@ unoptimizedRequest requestWithSecrets expect =
|
||||
case maybeResponse of
|
||||
Just rawResponse ->
|
||||
Ok
|
||||
( Dict.singleton (Secrets.maskedLookup requestWithSecrets |> HashRequest.hash)
|
||||
( -- TODO should this be an empty Dict? Shouldn't matter in the browser.
|
||||
Dict.singleton (Secrets.maskedLookup requestWithSecrets |> HashRequest.hash)
|
||||
Pages.StaticHttpRequest.UseRawResponse
|
||||
, rawResponse
|
||||
)
|
||||
@ -353,14 +368,15 @@ unoptimizedRequest requestWithSecrets expect =
|
||||
ExpectUnoptimizedJson decoder ->
|
||||
Request Dict.empty
|
||||
( [ requestWithSecrets ]
|
||||
, \_ rawResponseDict ->
|
||||
, \keepOrDiscard _ rawResponseDict ->
|
||||
rawResponseDict
|
||||
|> RequestsAndPending.get (Secrets.maskedLookup requestWithSecrets |> HashRequest.hash)
|
||||
|> (\maybeResponse ->
|
||||
case maybeResponse of
|
||||
Just rawResponse ->
|
||||
Ok
|
||||
( Dict.singleton (Secrets.maskedLookup requestWithSecrets |> HashRequest.hash)
|
||||
( -- TODO check keepOrDiscard
|
||||
Dict.singleton (Secrets.maskedLookup requestWithSecrets |> HashRequest.hash)
|
||||
Pages.StaticHttpRequest.UseRawResponse
|
||||
, rawResponse
|
||||
)
|
||||
@ -388,7 +404,8 @@ unoptimizedRequest requestWithSecrets expect =
|
||||
)
|
||||
|> Result.map
|
||||
(\finalRequest ->
|
||||
( strippedResponses
|
||||
( -- TODO check keepOrDiscard
|
||||
strippedResponses
|
||||
|> Dict.insert
|
||||
(Secrets.maskedLookup requestWithSecrets |> HashRequest.hash)
|
||||
Pages.StaticHttpRequest.UseRawResponse
|
||||
@ -402,14 +419,15 @@ unoptimizedRequest requestWithSecrets expect =
|
||||
ExpectString mapStringFn ->
|
||||
Request Dict.empty
|
||||
( [ requestWithSecrets ]
|
||||
, \_ rawResponseDict ->
|
||||
, \keepOrDiscard _ rawResponseDict ->
|
||||
rawResponseDict
|
||||
|> RequestsAndPending.get (Secrets.maskedLookup requestWithSecrets |> HashRequest.hash)
|
||||
|> (\maybeResponse ->
|
||||
case maybeResponse of
|
||||
Just rawResponse ->
|
||||
Ok
|
||||
( Dict.singleton (Secrets.maskedLookup requestWithSecrets |> HashRequest.hash) Pages.StaticHttpRequest.UseRawResponse
|
||||
( -- TODO check keepOrDiscard
|
||||
Dict.singleton (Secrets.maskedLookup requestWithSecrets |> HashRequest.hash) Pages.StaticHttpRequest.UseRawResponse
|
||||
, rawResponse
|
||||
)
|
||||
|
||||
@ -426,7 +444,8 @@ unoptimizedRequest requestWithSecrets expect =
|
||||
|> Result.mapError Pages.StaticHttpRequest.DecoderError
|
||||
|> Result.map
|
||||
(\finalRequest ->
|
||||
( strippedResponses
|
||||
( -- TODO check keepOrDiscard
|
||||
strippedResponses
|
||||
|> Dict.insert (Secrets.maskedLookup requestWithSecrets |> HashRequest.hash) Pages.StaticHttpRequest.UseRawResponse
|
||||
, finalRequest
|
||||
)
|
||||
|
6
src/KeepOrDiscard.elm
Normal file
6
src/KeepOrDiscard.elm
Normal file
@ -0,0 +1,6 @@
|
||||
module KeepOrDiscard exposing (KeepOrDiscard(..))
|
||||
|
||||
|
||||
type KeepOrDiscard
|
||||
= Keep
|
||||
| Discard
|
@ -2,8 +2,10 @@ module Pages.StaticHttpRequest exposing (Error(..), RawRequest(..), Status(..),
|
||||
|
||||
import BuildError exposing (BuildError)
|
||||
import Dict exposing (Dict)
|
||||
import Dict.Extra
|
||||
import Internal.OptimizedDecoder
|
||||
import Json.Decode.Exploration
|
||||
import KeepOrDiscard exposing (KeepOrDiscard)
|
||||
import OptimizedDecoder
|
||||
import Pages.Internal.ApplicationType exposing (ApplicationType)
|
||||
import Pages.StaticHttp.Request
|
||||
@ -16,7 +18,7 @@ type RawRequest value
|
||||
= Request
|
||||
(Dict String WhatToDo)
|
||||
( List (Secrets.Value Pages.StaticHttp.Request.Request)
|
||||
, ApplicationType -> RequestsAndPending -> RawRequest value
|
||||
, KeepOrDiscard -> ApplicationType -> RequestsAndPending -> RawRequest value
|
||||
)
|
||||
| RequestError Error
|
||||
| Done (Dict String WhatToDo) value
|
||||
@ -24,6 +26,7 @@ type RawRequest value
|
||||
|
||||
type WhatToDo
|
||||
= UseRawResponse
|
||||
| CliOnly
|
||||
| StripResponse (OptimizedDecoder.Decoder ())
|
||||
|
||||
|
||||
@ -39,7 +42,13 @@ merge whatToDo1 whatToDo2 =
|
||||
( _, StripResponse strip1 ) ->
|
||||
StripResponse strip1
|
||||
|
||||
_ ->
|
||||
( _, CliOnly ) ->
|
||||
whatToDo1
|
||||
|
||||
( CliOnly, _ ) ->
|
||||
whatToDo2
|
||||
|
||||
( UseRawResponse, UseRawResponse ) ->
|
||||
UseRawResponse
|
||||
|
||||
|
||||
@ -51,13 +60,14 @@ strippedResponses =
|
||||
strippedResponsesEncode : ApplicationType -> RawRequest value -> RequestsAndPending -> Dict String String
|
||||
strippedResponsesEncode appType rawRequest requestsAndPending =
|
||||
strippedResponses appType rawRequest requestsAndPending
|
||||
|> Dict.map
|
||||
|> Dict.Extra.filterMap
|
||||
(\k whatToDo ->
|
||||
case whatToDo of
|
||||
UseRawResponse ->
|
||||
Dict.get k requestsAndPending
|
||||
|> Maybe.withDefault Nothing
|
||||
|> Maybe.withDefault ""
|
||||
|> Just
|
||||
|
||||
StripResponse decoder ->
|
||||
Dict.get k requestsAndPending
|
||||
@ -65,6 +75,10 @@ strippedResponsesEncode appType rawRequest requestsAndPending =
|
||||
|> Maybe.withDefault ""
|
||||
|> Json.Decode.Exploration.stripString (Internal.OptimizedDecoder.jde decoder)
|
||||
|> Result.withDefault "ERROR"
|
||||
|> Just
|
||||
|
||||
CliOnly ->
|
||||
Nothing
|
||||
)
|
||||
|
||||
|
||||
@ -75,7 +89,7 @@ strippedResponsesHelp usedSoFar appType request rawResponses =
|
||||
usedSoFar
|
||||
|
||||
Request partiallyStrippedResponses ( _, lookupFn ) ->
|
||||
case lookupFn appType rawResponses of
|
||||
case lookupFn KeepOrDiscard.Keep appType rawResponses of
|
||||
followupRequest ->
|
||||
strippedResponsesHelp
|
||||
(Dict.merge
|
||||
@ -144,7 +158,7 @@ resolve appType request rawResponses =
|
||||
Err error
|
||||
|
||||
Request _ ( _, lookupFn ) ->
|
||||
case lookupFn appType rawResponses of
|
||||
case lookupFn KeepOrDiscard.Keep appType rawResponses of
|
||||
nextRequest ->
|
||||
resolve appType nextRequest rawResponses
|
||||
|
||||
@ -166,7 +180,7 @@ resolveUrlsHelp appType request rawResponses soFar =
|
||||
)
|
||||
|
||||
Request _ ( urlList, lookupFn ) ->
|
||||
case lookupFn appType rawResponses of
|
||||
case lookupFn KeepOrDiscard.Keep appType rawResponses of
|
||||
nextRequest ->
|
||||
resolveUrlsHelp appType nextRequest rawResponses (soFar ++ urlList)
|
||||
|
||||
@ -210,7 +224,7 @@ cacheRequestResolutionHelp foundUrls appType request rawResponses =
|
||||
HasPermanentError error
|
||||
|
||||
Request _ ( urlList, lookupFn ) ->
|
||||
case lookupFn appType rawResponses of
|
||||
case lookupFn KeepOrDiscard.Keep appType rawResponses of
|
||||
nextRequest ->
|
||||
cacheRequestResolutionHelp urlList appType nextRequest rawResponses
|
||||
|
||||
|
@ -29,7 +29,7 @@ import SimulatedEffect.Cmd
|
||||
import SimulatedEffect.Http as Http
|
||||
import SimulatedEffect.Ports
|
||||
import SimulatedEffect.Task
|
||||
import Test exposing (Test, describe, test)
|
||||
import Test exposing (Test, describe, only, test)
|
||||
import Test.Http
|
||||
|
||||
|
||||
@ -767,6 +767,46 @@ TODO
|
||||
]
|
||||
)
|
||||
]
|
||||
, test "validate DataSource is not stored for any pages" <|
|
||||
\() ->
|
||||
startWithRoutes [ "hello" ]
|
||||
[ [ "hello" ] ]
|
||||
[]
|
||||
[ ( [ "hello" ]
|
||||
, DataSource.succeed "hello"
|
||||
|> DataSource.validate identity
|
||||
(\word ->
|
||||
DataSource.Http.get (Secrets.succeed ("https://api.spellchecker.com?word=" ++ word))
|
||||
(Decode.field "isCorrect" Decode.bool
|
||||
|> Decode.map
|
||||
(\isCorrect ->
|
||||
if isCorrect then
|
||||
Ok ()
|
||||
|
||||
else
|
||||
Err "Spelling error"
|
||||
)
|
||||
)
|
||||
)
|
||||
|> DataSource.map (\_ -> ())
|
||||
)
|
||||
]
|
||||
|> ProgramTest.simulateHttpOk
|
||||
"GET"
|
||||
"https://api.spellchecker.com?word=hello"
|
||||
"""{ "isCorrect": true }"""
|
||||
|> ProgramTest.expectOutgoingPortValues
|
||||
"toJsPort"
|
||||
(Codec.decoder (ToJsPayload.successCodecNew2 "" ""))
|
||||
(\actualPorts ->
|
||||
case actualPorts of
|
||||
[ ToJsPayload.PageProgress portData ] ->
|
||||
portData.contentJson
|
||||
|> Expect.equalDicts Dict.empty
|
||||
|
||||
_ ->
|
||||
Expect.fail <| "Expected exactly 1 port of type PageProgress. Instead, got \n" ++ Debug.toString actualPorts
|
||||
)
|
||||
]
|
||||
, describe "generateFiles"
|
||||
[ test "initial requests are sent out" <|
|
||||
|
Loading…
Reference in New Issue
Block a user