elm-pages 3.0.0-beta.9 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/adapter/netlify.js +207 -0
- package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2731 -2939
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -1
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1527 -422
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +16840 -13653
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
- package/generator/dead-code-review/elm.json +9 -7
- package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +59 -10
- package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +52 -36
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
- package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1527 -422
- package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25118 -21832
- package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
- package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
- package/generator/review/elm.json +10 -10
- package/generator/src/RouteBuilder.elm +93 -128
- package/generator/src/SharedTemplate.elm +8 -7
- package/generator/src/SiteConfig.elm +3 -2
- package/generator/src/basepath-middleware.js +3 -3
- package/generator/src/build.js +143 -59
- package/generator/src/cli.js +292 -88
- package/generator/src/codegen.js +29 -27
- package/generator/src/compatibility-key.js +3 -0
- package/generator/src/compile-elm.js +43 -26
- package/generator/src/config.js +2 -4
- package/generator/src/copy-dir.js +2 -2
- package/generator/src/dev-server.js +160 -102
- package/generator/src/dir-helpers.js +9 -26
- package/generator/src/elm-codegen.js +5 -4
- package/generator/src/elm-file-constants.js +2 -3
- package/generator/src/error-formatter.js +12 -11
- package/generator/src/file-helpers.js +3 -4
- package/generator/src/generate-template-module-connector.js +23 -23
- package/generator/src/init.js +9 -8
- package/generator/src/pre-render-html.js +10 -13
- package/generator/src/render-test.js +109 -0
- package/generator/src/render-worker.js +25 -28
- package/generator/src/render.js +320 -143
- package/generator/src/request-cache.js +265 -162
- package/generator/src/resolve-elm-module.js +64 -0
- package/generator/src/rewrite-client-elm-json.js +6 -5
- package/generator/src/rewrite-elm-json-help.js +56 -0
- package/generator/src/rewrite-elm-json.js +17 -7
- package/generator/src/route-codegen-helpers.js +16 -31
- package/generator/src/seo-renderer.js +1 -3
- package/generator/src/vite-utils.js +1 -2
- package/generator/static-code/elm-pages.js +10 -0
- package/generator/static-code/hmr.js +79 -13
- package/generator/template/app/Api.elm +3 -2
- package/generator/template/app/Effect.elm +155 -0
- package/generator/template/app/ErrorPage.elm +49 -6
- package/generator/template/app/Route/Blog/Slug_.elm +86 -0
- package/generator/template/app/Route/Greet.elm +107 -0
- package/generator/template/app/Route/Hello.elm +119 -0
- package/generator/template/app/Route/Index.elm +26 -25
- package/generator/template/app/Shared.elm +38 -39
- package/generator/template/app/Site.elm +4 -7
- package/generator/template/app/View.elm +9 -8
- package/generator/template/codegen/elm.codegen.json +18 -0
- package/generator/template/custom-backend-task.ts +3 -0
- package/generator/template/elm-pages.config.mjs +13 -0
- package/generator/template/elm-tooling.json +0 -3
- package/generator/template/elm.json +25 -20
- package/generator/template/index.ts +1 -2
- package/generator/template/netlify.toml +4 -1
- package/generator/template/package.json +10 -4
- package/generator/template/script/.elm-pages/compiled-ports/custom-backend-task.mjs +7 -0
- package/generator/template/script/custom-backend-task.ts +3 -0
- package/generator/template/script/elm.json +61 -0
- package/generator/template/script/src/AddRoute.elm +312 -0
- package/generator/template/script/src/Stars.elm +42 -0
- package/package.json +30 -27
- package/src/ApiRoute.elm +249 -82
- package/src/BackendTask/Custom.elm +325 -0
- package/src/BackendTask/Env.elm +90 -0
- package/src/{DataSource → BackendTask}/File.elm +171 -56
- package/src/{DataSource → BackendTask}/Glob.elm +136 -125
- package/src/BackendTask/Http.elm +679 -0
- package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
- package/src/BackendTask/Internal/Request.elm +69 -0
- package/src/BackendTask/Random.elm +79 -0
- package/src/BackendTask/Time.elm +47 -0
- package/src/BackendTask.elm +531 -0
- package/src/FatalError.elm +90 -0
- package/src/FormData.elm +21 -18
- package/src/Head/Seo.elm +4 -4
- package/src/Head.elm +112 -8
- package/src/Internal/ApiRoute.elm +7 -5
- package/src/Internal/Request.elm +84 -4
- package/src/PageServerResponse.elm +6 -1
- package/src/Pages/ConcurrentSubmission.elm +127 -0
- package/src/Pages/Form.elm +340 -0
- package/src/Pages/FormData.elm +19 -0
- package/src/Pages/GeneratorProgramConfig.elm +15 -0
- package/src/Pages/Internal/FatalError.elm +5 -0
- package/src/Pages/Internal/Msg.elm +93 -0
- package/src/Pages/Internal/NotFoundReason.elm +4 -4
- package/src/Pages/Internal/Platform/Cli.elm +586 -768
- package/src/Pages/Internal/Platform/CompatibilityKey.elm +1 -1
- package/src/Pages/Internal/Platform/Effect.elm +1 -2
- package/src/Pages/Internal/Platform/GeneratorApplication.elm +379 -0
- package/src/Pages/Internal/Platform/StaticResponses.elm +65 -276
- package/src/Pages/Internal/Platform/ToJsPayload.elm +6 -9
- package/src/Pages/Internal/Platform.elm +330 -203
- package/src/Pages/Internal/ResponseSketch.elm +2 -2
- package/src/Pages/Internal/Script.elm +17 -0
- package/src/Pages/Internal/StaticHttpBody.elm +35 -1
- package/src/Pages/Manifest.elm +52 -11
- package/src/Pages/Navigation.elm +85 -0
- package/src/Pages/PageUrl.elm +26 -12
- package/src/Pages/ProgramConfig.elm +32 -22
- package/src/Pages/Script.elm +166 -0
- package/src/Pages/SiteConfig.elm +3 -2
- package/src/Pages/StaticHttp/Request.elm +2 -2
- package/src/Pages/StaticHttpRequest.elm +23 -99
- package/src/Pages/Url.elm +3 -3
- package/src/PagesMsg.elm +88 -0
- package/src/QueryParams.elm +21 -172
- package/src/RenderRequest.elm +7 -7
- package/src/RequestsAndPending.elm +37 -20
- package/src/Result/Extra.elm +26 -0
- package/src/Scaffold/Form.elm +569 -0
- package/src/Scaffold/Route.elm +1431 -0
- package/src/Server/Request.elm +476 -1001
- package/src/Server/Response.elm +130 -36
- package/src/Server/Session.elm +181 -111
- package/src/Server/SetCookie.elm +80 -32
- package/src/Stub.elm +53 -0
- package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
- package/src/{Path.elm → UrlPath.elm} +33 -36
- package/generator/template/public/images/icon-png.png +0 -0
- package/src/DataSource/Env.elm +0 -38
- package/src/DataSource/Http.elm +0 -446
- package/src/DataSource/Internal/Request.elm +0 -20
- package/src/DataSource/Port.elm +0 -90
- package/src/DataSource.elm +0 -546
- package/src/Form/Field.elm +0 -717
- package/src/Form/FieldStatus.elm +0 -36
- package/src/Form/FieldView.elm +0 -417
- package/src/Form/FormData.elm +0 -22
- package/src/Form/Validation.elm +0 -391
- package/src/Form/Value.elm +0 -118
- package/src/Form.elm +0 -1683
- package/src/FormDecoder.elm +0 -102
- package/src/Pages/FormState.elm +0 -256
- package/src/Pages/Generate.elm +0 -1242
- package/src/Pages/Internal/Form.elm +0 -17
- package/src/Pages/Internal/Platform/Cli.elm.bak +0 -1276
- package/src/Pages/Msg.elm +0 -79
- package/src/Pages/Transition.elm +0 -70
|
@@ -6,40 +6,38 @@ module Pages.Internal.Platform.Cli exposing (Flags, Model, Msg(..), Program, cli
|
|
|
6
6
|
|
|
7
7
|
-}
|
|
8
8
|
|
|
9
|
-
import
|
|
9
|
+
import BackendTask exposing (BackendTask)
|
|
10
10
|
import BuildError exposing (BuildError)
|
|
11
11
|
import Bytes exposing (Bytes)
|
|
12
12
|
import Bytes.Encode
|
|
13
13
|
import Codec
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import Head
|
|
14
|
+
import Dict exposing (Dict)
|
|
15
|
+
import FatalError exposing (FatalError)
|
|
16
|
+
import Head exposing (Tag)
|
|
17
17
|
import Html exposing (Html)
|
|
18
18
|
import HtmlPrinter
|
|
19
19
|
import Internal.ApiRoute exposing (ApiRoute(..))
|
|
20
|
+
import Internal.Request
|
|
20
21
|
import Json.Decode as Decode
|
|
21
22
|
import Json.Encode
|
|
22
23
|
import PageServerResponse exposing (PageServerResponse)
|
|
23
24
|
import Pages.Flags
|
|
24
|
-
import Pages.
|
|
25
|
+
import Pages.Internal.FatalError
|
|
25
26
|
import Pages.Internal.NotFoundReason as NotFoundReason exposing (NotFoundReason)
|
|
26
27
|
import Pages.Internal.Platform.CompatibilityKey
|
|
27
28
|
import Pages.Internal.Platform.Effect as Effect exposing (Effect)
|
|
28
|
-
import Pages.Internal.Platform.StaticResponses as StaticResponses
|
|
29
|
+
import Pages.Internal.Platform.StaticResponses as StaticResponses
|
|
29
30
|
import Pages.Internal.Platform.ToJsPayload as ToJsPayload
|
|
30
31
|
import Pages.Internal.ResponseSketch as ResponseSketch
|
|
31
|
-
import Pages.Internal.StaticHttpBody as StaticHttpBody
|
|
32
|
-
import Pages.Msg
|
|
33
32
|
import Pages.ProgramConfig exposing (ProgramConfig)
|
|
34
33
|
import Pages.SiteConfig exposing (SiteConfig)
|
|
35
34
|
import Pages.StaticHttp.Request
|
|
36
|
-
import
|
|
37
|
-
import Path exposing (Path)
|
|
35
|
+
import PagesMsg exposing (PagesMsg)
|
|
38
36
|
import RenderRequest exposing (RenderRequest)
|
|
39
37
|
import RequestsAndPending exposing (RequestsAndPending)
|
|
40
|
-
import Task
|
|
41
38
|
import TerminalText as Terminal
|
|
42
39
|
import Url exposing (Url)
|
|
40
|
+
import UrlPath exposing (UrlPath)
|
|
43
41
|
|
|
44
42
|
|
|
45
43
|
{-| -}
|
|
@@ -55,10 +53,8 @@ currentCompatibilityKey =
|
|
|
55
53
|
|
|
56
54
|
{-| -}
|
|
57
55
|
type alias Model route =
|
|
58
|
-
{ staticResponses :
|
|
56
|
+
{ staticResponses : BackendTask FatalError Effect
|
|
59
57
|
, errors : List BuildError
|
|
60
|
-
, allRawResponses : RequestsAndPending
|
|
61
|
-
, unprocessedPages : List ( Path, route )
|
|
62
58
|
, maybeRequestJson : RenderRequest route
|
|
63
59
|
, isDevServer : Bool
|
|
64
60
|
}
|
|
@@ -66,12 +62,7 @@ type alias Model route =
|
|
|
66
62
|
|
|
67
63
|
{-| -}
|
|
68
64
|
type Msg
|
|
69
|
-
= GotDataBatch
|
|
70
|
-
(List
|
|
71
|
-
{ request : Pages.StaticHttp.Request.Request
|
|
72
|
-
, response : RequestsAndPending.Response
|
|
73
|
-
}
|
|
74
|
-
)
|
|
65
|
+
= GotDataBatch Decode.Value
|
|
75
66
|
| GotBuildError BuildError
|
|
76
67
|
|
|
77
68
|
|
|
@@ -112,7 +103,7 @@ cliApplication config =
|
|
|
112
103
|
|> Tuple.mapSecond (perform site renderRequest config)
|
|
113
104
|
, update =
|
|
114
105
|
\msg model ->
|
|
115
|
-
update
|
|
106
|
+
update msg model
|
|
116
107
|
|> Tuple.mapSecond (perform site model.maybeRequestJson config)
|
|
117
108
|
, subscriptions =
|
|
118
109
|
\_ ->
|
|
@@ -159,35 +150,11 @@ cliApplication config =
|
|
|
159
150
|
)
|
|
160
151
|
|> mergeResult
|
|
161
152
|
)
|
|
162
|
-
, config.gotBatchSub
|
|
163
|
-
|> Sub.map
|
|
164
|
-
(\newBatch ->
|
|
165
|
-
Decode.decodeValue batchDecoder newBatch
|
|
166
|
-
|> Result.map GotDataBatch
|
|
167
|
-
|> Result.mapError
|
|
168
|
-
(\error ->
|
|
169
|
-
("From location 2: "
|
|
170
|
-
++ (error
|
|
171
|
-
|> Decode.errorToString
|
|
172
|
-
)
|
|
173
|
-
)
|
|
174
|
-
|> BuildError.internal
|
|
175
|
-
|> GotBuildError
|
|
176
|
-
)
|
|
177
|
-
|> mergeResult
|
|
178
|
-
)
|
|
153
|
+
, config.gotBatchSub |> Sub.map GotDataBatch
|
|
179
154
|
]
|
|
180
155
|
}
|
|
181
156
|
|
|
182
157
|
|
|
183
|
-
batchDecoder : Decode.Decoder (List { request : Pages.StaticHttp.Request.Request, response : RequestsAndPending.Response })
|
|
184
|
-
batchDecoder =
|
|
185
|
-
Decode.map2 (\request response -> { request = request, response = response })
|
|
186
|
-
(Decode.field "request" requestDecoder)
|
|
187
|
-
(Decode.field "response" RequestsAndPending.decoder)
|
|
188
|
-
|> Decode.list
|
|
189
|
-
|
|
190
|
-
|
|
191
158
|
mergeResult : Result a a -> a
|
|
192
159
|
mergeResult r =
|
|
193
160
|
case r of
|
|
@@ -244,61 +211,16 @@ perform site renderRequest config effect =
|
|
|
244
211
|
Effect.Batch list ->
|
|
245
212
|
flatten site renderRequest config list
|
|
246
213
|
|
|
247
|
-
Effect.FetchHttp
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
[ { request = unmasked
|
|
258
|
-
, response = okResponse
|
|
259
|
-
}
|
|
260
|
-
]
|
|
261
|
-
|> Task.perform GotDataBatch
|
|
262
|
-
|
|
263
|
-
Err error ->
|
|
264
|
-
{ title = "Static HTTP Error"
|
|
265
|
-
, message =
|
|
266
|
-
[ Terminal.text "I got an error making an HTTP request to this URL: "
|
|
267
|
-
|
|
268
|
-
-- TODO include HTTP method, headers, and body
|
|
269
|
-
, Terminal.yellow unmasked.url
|
|
270
|
-
, Terminal.text <| Json.Encode.encode 2 <| StaticHttpBody.encode unmasked.body
|
|
271
|
-
, Terminal.text "\n\n"
|
|
272
|
-
, case error of
|
|
273
|
-
Pages.Http.BadStatus metadata body ->
|
|
274
|
-
Terminal.text <|
|
|
275
|
-
String.join "\n"
|
|
276
|
-
[ "Bad status: " ++ String.fromInt metadata.statusCode
|
|
277
|
-
, "Status message: " ++ metadata.statusText
|
|
278
|
-
, "Body: " ++ body
|
|
279
|
-
]
|
|
280
|
-
|
|
281
|
-
Pages.Http.BadUrl _ ->
|
|
282
|
-
-- TODO include HTTP method, headers, and body
|
|
283
|
-
Terminal.text <| "Invalid url: " ++ unmasked.url
|
|
284
|
-
|
|
285
|
-
Pages.Http.Timeout ->
|
|
286
|
-
Terminal.text "Timeout"
|
|
287
|
-
|
|
288
|
-
Pages.Http.NetworkError ->
|
|
289
|
-
Terminal.text "Network error"
|
|
290
|
-
]
|
|
291
|
-
, fatal = True
|
|
292
|
-
, path = "" -- TODO wire in current path here
|
|
293
|
-
}
|
|
294
|
-
|> Task.succeed
|
|
295
|
-
|> Task.perform GotBuildError
|
|
296
|
-
|
|
297
|
-
else
|
|
298
|
-
ToJsPayload.DoHttp unmasked unmasked.useCache
|
|
299
|
-
|> Codec.encoder (ToJsPayload.successCodecNew2 canonicalSiteUrl "")
|
|
300
|
-
|> config.toJsPort
|
|
301
|
-
|> Cmd.map never
|
|
214
|
+
Effect.FetchHttp requests ->
|
|
215
|
+
requests
|
|
216
|
+
|> List.map
|
|
217
|
+
(\request ->
|
|
218
|
+
( Pages.StaticHttp.Request.hash request, request )
|
|
219
|
+
)
|
|
220
|
+
|> ToJsPayload.DoHttp
|
|
221
|
+
|> Codec.encoder (ToJsPayload.successCodecNew2 canonicalSiteUrl "")
|
|
222
|
+
|> config.toJsPort
|
|
223
|
+
|> Cmd.map never
|
|
302
224
|
|
|
303
225
|
Effect.SendSinglePage info ->
|
|
304
226
|
let
|
|
@@ -335,9 +257,6 @@ perform site renderRequest config effect =
|
|
|
335
257
|
|> config.sendPageData
|
|
336
258
|
|> Cmd.map never
|
|
337
259
|
|
|
338
|
-
Effect.Continue ->
|
|
339
|
-
Cmd.none
|
|
340
|
-
|
|
341
260
|
|
|
342
261
|
flagsDecoder :
|
|
343
262
|
Decode.Decoder
|
|
@@ -353,15 +272,8 @@ flagsDecoder =
|
|
|
353
272
|
, compatibilityKey = compatibilityKey
|
|
354
273
|
}
|
|
355
274
|
)
|
|
356
|
-
--(Decode.field "staticHttpCache"
|
|
357
|
-
-- (Decode.dict
|
|
358
|
-
-- (Decode.string
|
|
359
|
-
-- |> Decode.map Just
|
|
360
|
-
-- )
|
|
361
|
-
-- )
|
|
362
|
-
--)
|
|
363
275
|
-- TODO remove hardcoding and decode staticHttpCache here
|
|
364
|
-
(Decode.succeed
|
|
276
|
+
(Decode.succeed (Json.Encode.object []))
|
|
365
277
|
(Decode.field "mode" Decode.string |> Decode.map (\mode -> mode == "dev-server"))
|
|
366
278
|
(Decode.field "compatibilityKey" Decode.int)
|
|
367
279
|
|
|
@@ -375,9 +287,9 @@ init :
|
|
|
375
287
|
-> ( Model route, Effect )
|
|
376
288
|
init site renderRequest config flags =
|
|
377
289
|
case Decode.decodeValue flagsDecoder flags of
|
|
378
|
-
Ok {
|
|
290
|
+
Ok { isDevServer, compatibilityKey } ->
|
|
379
291
|
if compatibilityKey == currentCompatibilityKey then
|
|
380
|
-
initLegacy site renderRequest {
|
|
292
|
+
initLegacy site renderRequest { isDevServer = isDevServer } config
|
|
381
293
|
|
|
382
294
|
else
|
|
383
295
|
let
|
|
@@ -396,9 +308,7 @@ init site renderRequest config flags =
|
|
|
396
308
|
)
|
|
397
309
|
in
|
|
398
310
|
updateAndSendPortIfDone
|
|
399
|
-
|
|
400
|
-
config
|
|
401
|
-
{ staticResponses = StaticResponses.empty
|
|
311
|
+
{ staticResponses = StaticResponses.empty Effect.NoEffect
|
|
402
312
|
, errors =
|
|
403
313
|
[ { title = "Incompatible NPM and Elm package versions"
|
|
404
314
|
, message = [ Terminal.text <| message ]
|
|
@@ -406,17 +316,13 @@ init site renderRequest config flags =
|
|
|
406
316
|
, path = ""
|
|
407
317
|
}
|
|
408
318
|
]
|
|
409
|
-
, allRawResponses = Dict.empty
|
|
410
|
-
, unprocessedPages = []
|
|
411
319
|
, maybeRequestJson = renderRequest
|
|
412
320
|
, isDevServer = False
|
|
413
321
|
}
|
|
414
322
|
|
|
415
323
|
Err error ->
|
|
416
324
|
updateAndSendPortIfDone
|
|
417
|
-
|
|
418
|
-
config
|
|
419
|
-
{ staticResponses = StaticResponses.empty
|
|
325
|
+
{ staticResponses = StaticResponses.empty Effect.NoEffect
|
|
420
326
|
, errors =
|
|
421
327
|
[ { title = "Internal Error"
|
|
422
328
|
, message = [ Terminal.text <| "Failed to parse flags: " ++ Decode.errorToString error ]
|
|
@@ -424,8 +330,6 @@ init site renderRequest config flags =
|
|
|
424
330
|
, path = ""
|
|
425
331
|
}
|
|
426
332
|
]
|
|
427
|
-
, allRawResponses = Dict.empty
|
|
428
|
-
, unprocessedPages = []
|
|
429
333
|
, maybeRequestJson = renderRequest
|
|
430
334
|
, isDevServer = False
|
|
431
335
|
}
|
|
@@ -474,140 +378,506 @@ isActionDecoder =
|
|
|
474
378
|
initLegacy :
|
|
475
379
|
SiteConfig
|
|
476
380
|
-> RenderRequest route
|
|
477
|
-
-> {
|
|
381
|
+
-> { isDevServer : Bool }
|
|
478
382
|
-> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
|
|
479
383
|
-> ( Model route, Effect )
|
|
480
|
-
initLegacy site renderRequest {
|
|
384
|
+
initLegacy site ((RenderRequest.SinglePage includeHtml singleRequest _) as renderRequest) { isDevServer } config =
|
|
481
385
|
let
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
386
|
+
globalHeadTags : BackendTask FatalError (List Tag)
|
|
387
|
+
globalHeadTags =
|
|
388
|
+
(config.globalHeadTags |> Maybe.withDefault (\_ -> BackendTask.succeed [])) HtmlPrinter.htmlToString
|
|
389
|
+
|
|
390
|
+
staticResponsesNew : BackendTask FatalError Effect
|
|
391
|
+
staticResponsesNew =
|
|
392
|
+
case singleRequest of
|
|
393
|
+
RenderRequest.Page serverRequestPayload ->
|
|
486
394
|
let
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
395
|
+
isAction : Maybe ActionRequest
|
|
396
|
+
isAction =
|
|
397
|
+
renderRequest
|
|
398
|
+
|> RenderRequest.maybeRequestPayload
|
|
399
|
+
|> Maybe.andThen (Decode.decodeValue isActionDecoder >> Result.withDefault Nothing)
|
|
400
|
+
|
|
401
|
+
currentUrl : Url
|
|
402
|
+
currentUrl =
|
|
403
|
+
{ protocol = Url.Https
|
|
404
|
+
, host = site.canonicalUrl
|
|
405
|
+
, port_ = Nothing
|
|
406
|
+
, path = serverRequestPayload.path |> UrlPath.toRelative
|
|
407
|
+
, query = Nothing
|
|
408
|
+
, fragment = Nothing
|
|
409
|
+
}
|
|
490
410
|
in
|
|
491
|
-
case
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
isAction =
|
|
496
|
-
renderRequest
|
|
497
|
-
|> RenderRequest.maybeRequestPayload
|
|
498
|
-
|> Maybe.andThen (Decode.decodeValue isActionDecoder >> Result.withDefault Nothing)
|
|
499
|
-
in
|
|
500
|
-
StaticResponses.renderSingleRoute
|
|
501
|
-
(case isAction of
|
|
502
|
-
Just _ ->
|
|
503
|
-
config.action serverRequestPayload.frontmatter
|
|
504
|
-
|> DataSource.andThen
|
|
505
|
-
(\something ->
|
|
506
|
-
case something of
|
|
507
|
-
PageServerResponse.ErrorPage _ _ ->
|
|
508
|
-
DataSource.succeed something
|
|
509
|
-
|> DataSource.map (\_ -> ())
|
|
510
|
-
|
|
511
|
-
PageServerResponse.RenderPage _ _ ->
|
|
512
|
-
DataSource.map3 (\_ _ _ -> ())
|
|
513
|
-
(config.data serverRequestPayload.frontmatter)
|
|
514
|
-
config.sharedData
|
|
515
|
-
globalHeadTags
|
|
516
|
-
|
|
517
|
-
PageServerResponse.ServerResponse _ ->
|
|
518
|
-
DataSource.succeed something
|
|
519
|
-
|> DataSource.map (\_ -> ())
|
|
520
|
-
)
|
|
411
|
+
--case isAction of
|
|
412
|
+
-- Just actionRequest ->
|
|
413
|
+
(if isDevServer then
|
|
414
|
+
config.handleRoute serverRequestPayload.frontmatter
|
|
521
415
|
|
|
416
|
+
else
|
|
417
|
+
BackendTask.succeed Nothing
|
|
418
|
+
)
|
|
419
|
+
|> BackendTask.andThen
|
|
420
|
+
(\pageFound ->
|
|
421
|
+
case pageFound of
|
|
522
422
|
Nothing ->
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
423
|
+
--sendSinglePageProgress site model.allRawResponses config model payload
|
|
424
|
+
(case isAction of
|
|
425
|
+
Just _ ->
|
|
426
|
+
config.action
|
|
427
|
+
(RenderRequest.maybeRequestPayload renderRequest
|
|
428
|
+
|> Maybe.map Internal.Request.toRequest
|
|
429
|
+
|> Maybe.withDefault Internal.Request.fakeRequest
|
|
430
|
+
)
|
|
431
|
+
serverRequestPayload.frontmatter
|
|
432
|
+
|> BackendTask.map Just
|
|
530
433
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
434
|
+
Nothing ->
|
|
435
|
+
BackendTask.succeed Nothing
|
|
436
|
+
)
|
|
437
|
+
|> BackendTask.andThen
|
|
438
|
+
(\something ->
|
|
439
|
+
let
|
|
440
|
+
actionHeaders2 : Maybe { statusCode : Int, headers : List ( String, String ) }
|
|
441
|
+
actionHeaders2 =
|
|
442
|
+
case something of
|
|
443
|
+
Just (PageServerResponse.RenderPage responseThing _) ->
|
|
444
|
+
Just responseThing
|
|
445
|
+
|
|
446
|
+
Just (PageServerResponse.ServerResponse responseThing) ->
|
|
447
|
+
Just
|
|
448
|
+
{ headers = responseThing.headers
|
|
449
|
+
, statusCode = responseThing.statusCode
|
|
450
|
+
}
|
|
534
451
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
(DataSource.map2 (\_ _ -> ())
|
|
538
|
-
(apiRequest.matchesToResponse path)
|
|
539
|
-
globalHeadTags
|
|
540
|
-
)
|
|
452
|
+
_ ->
|
|
453
|
+
Nothing
|
|
541
454
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
455
|
+
maybeRedirectResponse : Maybe Effect
|
|
456
|
+
maybeRedirectResponse =
|
|
457
|
+
actionHeaders2
|
|
458
|
+
|> Maybe.andThen
|
|
459
|
+
(\responseMetadata ->
|
|
460
|
+
toRedirectResponse config
|
|
461
|
+
serverRequestPayload
|
|
462
|
+
includeHtml
|
|
463
|
+
responseMetadata
|
|
464
|
+
responseMetadata
|
|
465
|
+
)
|
|
466
|
+
in
|
|
467
|
+
case maybeRedirectResponse of
|
|
468
|
+
Just redirectResponse ->
|
|
469
|
+
redirectResponse
|
|
470
|
+
|> BackendTask.succeed
|
|
548
471
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
472
|
+
Nothing ->
|
|
473
|
+
BackendTask.map3
|
|
474
|
+
(\pageData sharedData tags ->
|
|
475
|
+
let
|
|
476
|
+
renderedResult : Effect
|
|
477
|
+
renderedResult =
|
|
478
|
+
case pageData of
|
|
479
|
+
PageServerResponse.RenderPage responseInfo pageData_ ->
|
|
480
|
+
let
|
|
481
|
+
currentPage : { path : UrlPath, route : route }
|
|
482
|
+
currentPage =
|
|
483
|
+
{ path = serverRequestPayload.path, route = urlToRoute config currentUrl }
|
|
484
|
+
|
|
485
|
+
maybeActionData : Maybe actionData
|
|
486
|
+
maybeActionData =
|
|
487
|
+
case something of
|
|
488
|
+
Just (PageServerResponse.RenderPage _ actionThing) ->
|
|
489
|
+
Just actionThing
|
|
490
|
+
|
|
491
|
+
_ ->
|
|
492
|
+
Nothing
|
|
493
|
+
|
|
494
|
+
pageModel : userModel
|
|
495
|
+
pageModel =
|
|
496
|
+
config.init
|
|
497
|
+
Pages.Flags.PreRenderFlags
|
|
498
|
+
sharedData
|
|
499
|
+
pageData_
|
|
500
|
+
maybeActionData
|
|
501
|
+
(Just
|
|
502
|
+
{ path =
|
|
503
|
+
{ path = currentPage.path
|
|
504
|
+
, query = Nothing
|
|
505
|
+
, fragment = Nothing
|
|
506
|
+
}
|
|
507
|
+
, metadata = currentPage.route
|
|
508
|
+
, pageUrl = Nothing
|
|
509
|
+
}
|
|
510
|
+
)
|
|
511
|
+
|> Tuple.first
|
|
512
|
+
|
|
513
|
+
viewValue : { title : String, body : List (Html (PagesMsg userMsg)) }
|
|
514
|
+
viewValue =
|
|
515
|
+
(config.view Dict.empty Dict.empty Nothing currentPage Nothing sharedData pageData_ maybeActionData |> .view) pageModel
|
|
516
|
+
|
|
517
|
+
responseMetadata : { statusCode : Int, headers : List ( String, String ) }
|
|
518
|
+
responseMetadata =
|
|
519
|
+
actionHeaders2 |> Maybe.withDefault responseInfo
|
|
520
|
+
in
|
|
521
|
+
(case isAction of
|
|
522
|
+
Just actionRequestKind ->
|
|
523
|
+
let
|
|
524
|
+
actionDataResult : Maybe (PageServerResponse actionData errorPage)
|
|
525
|
+
actionDataResult =
|
|
526
|
+
something
|
|
527
|
+
in
|
|
528
|
+
case actionDataResult of
|
|
529
|
+
Just (PageServerResponse.RenderPage ignored2 actionData_) ->
|
|
530
|
+
case actionRequestKind of
|
|
531
|
+
ActionResponseRequest ->
|
|
532
|
+
( ignored2.headers
|
|
533
|
+
, ResponseSketch.HotUpdate pageData_ sharedData (Just actionData_)
|
|
534
|
+
|> config.encodeResponse
|
|
535
|
+
|> Bytes.Encode.encode
|
|
536
|
+
)
|
|
537
|
+
|
|
538
|
+
ActionOnlyRequest ->
|
|
539
|
+
---- TODO need to encode action data when only that is requested (not ResponseSketch?)
|
|
540
|
+
( ignored2.headers
|
|
541
|
+
, actionData_
|
|
542
|
+
|> config.encodeAction
|
|
543
|
+
|> Bytes.Encode.encode
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
_ ->
|
|
547
|
+
( responseMetadata.headers
|
|
548
|
+
, Bytes.Encode.encode (Bytes.Encode.unsignedInt8 0)
|
|
549
|
+
)
|
|
550
|
+
|
|
551
|
+
Nothing ->
|
|
552
|
+
( responseMetadata.headers
|
|
553
|
+
, ResponseSketch.HotUpdate pageData_ sharedData Nothing
|
|
554
|
+
|> config.encodeResponse
|
|
555
|
+
|> Bytes.Encode.encode
|
|
556
|
+
)
|
|
557
|
+
)
|
|
558
|
+
|> (\( actionHeaders, byteEncodedPageData ) ->
|
|
559
|
+
let
|
|
560
|
+
rendered : { view : userModel -> { title : String, body : List (Html (PagesMsg userMsg)) }, head : List Tag }
|
|
561
|
+
rendered =
|
|
562
|
+
config.view Dict.empty Dict.empty Nothing currentPage Nothing sharedData pageData_ maybeActionData
|
|
563
|
+
in
|
|
564
|
+
PageServerResponse.toRedirect responseMetadata
|
|
565
|
+
|> Maybe.map
|
|
566
|
+
(\{ location } ->
|
|
567
|
+
location
|
|
568
|
+
|> ResponseSketch.Redirect
|
|
569
|
+
|> config.encodeResponse
|
|
570
|
+
|> Bytes.Encode.encode
|
|
571
|
+
)
|
|
572
|
+
-- TODO handle other cases besides redirects?
|
|
573
|
+
|> Maybe.withDefault byteEncodedPageData
|
|
574
|
+
|> (\encodedData ->
|
|
575
|
+
{ route = currentPage.path |> UrlPath.toRelative
|
|
576
|
+
, contentJson = Dict.empty
|
|
577
|
+
, html = viewValue.body |> bodyToString
|
|
578
|
+
, errors = []
|
|
579
|
+
, head = rendered.head ++ tags
|
|
580
|
+
, title = viewValue.title
|
|
581
|
+
, staticHttpCache = Dict.empty
|
|
582
|
+
, is404 = False
|
|
583
|
+
, statusCode =
|
|
584
|
+
case includeHtml of
|
|
585
|
+
RenderRequest.OnlyJson ->
|
|
586
|
+
200
|
|
587
|
+
|
|
588
|
+
RenderRequest.HtmlAndJson ->
|
|
589
|
+
responseMetadata.statusCode
|
|
590
|
+
, headers =
|
|
591
|
+
-- TODO should `responseInfo.headers` be used? Is there a problem in the case where there is both an action and data response in one? Do we need to make sure it is performed as two separate HTTP requests to ensure that the cookies are set correctly in that case?
|
|
592
|
+
actionHeaders
|
|
593
|
+
|> combineHeaders
|
|
594
|
+
}
|
|
595
|
+
|> ToJsPayload.PageProgress
|
|
596
|
+
|> Effect.SendSinglePageNew encodedData
|
|
597
|
+
)
|
|
598
|
+
)
|
|
599
|
+
|
|
600
|
+
PageServerResponse.ServerResponse serverResponse ->
|
|
601
|
+
--PageServerResponse.ServerResponse serverResponse
|
|
602
|
+
-- TODO handle error?
|
|
603
|
+
let
|
|
604
|
+
responseMetadata : PageServerResponse.Response
|
|
605
|
+
responseMetadata =
|
|
606
|
+
case something of
|
|
607
|
+
Just (PageServerResponse.ServerResponse responseThing) ->
|
|
608
|
+
responseThing
|
|
609
|
+
|
|
610
|
+
_ ->
|
|
611
|
+
serverResponse
|
|
612
|
+
in
|
|
613
|
+
toRedirectResponse config serverRequestPayload includeHtml serverResponse responseMetadata
|
|
614
|
+
|> Maybe.withDefault
|
|
615
|
+
({ body = serverResponse |> PageServerResponse.toJson
|
|
616
|
+
, staticHttpCache = Dict.empty
|
|
617
|
+
, statusCode = serverResponse.statusCode
|
|
618
|
+
}
|
|
619
|
+
|> ToJsPayload.SendApiResponse
|
|
620
|
+
|> Effect.SendSinglePage
|
|
621
|
+
)
|
|
622
|
+
|
|
623
|
+
PageServerResponse.ErrorPage error record ->
|
|
624
|
+
let
|
|
625
|
+
currentPage : { path : UrlPath, route : route }
|
|
626
|
+
currentPage =
|
|
627
|
+
{ path = serverRequestPayload.path, route = urlToRoute config currentUrl }
|
|
628
|
+
|
|
629
|
+
pageModel : userModel
|
|
630
|
+
pageModel =
|
|
631
|
+
config.init
|
|
632
|
+
Pages.Flags.PreRenderFlags
|
|
633
|
+
sharedData
|
|
634
|
+
pageData2
|
|
635
|
+
Nothing
|
|
636
|
+
(Just
|
|
637
|
+
{ path =
|
|
638
|
+
{ path = currentPage.path
|
|
639
|
+
, query = Nothing
|
|
640
|
+
, fragment = Nothing
|
|
641
|
+
}
|
|
642
|
+
, metadata = currentPage.route
|
|
643
|
+
, pageUrl = Nothing
|
|
644
|
+
}
|
|
645
|
+
)
|
|
646
|
+
|> Tuple.first
|
|
647
|
+
|
|
648
|
+
pageData2 : pageData
|
|
649
|
+
pageData2 =
|
|
650
|
+
config.errorPageToData error
|
|
651
|
+
|
|
652
|
+
viewValue : { title : String, body : List (Html (PagesMsg userMsg)) }
|
|
653
|
+
viewValue =
|
|
654
|
+
(config.view Dict.empty Dict.empty Nothing currentPage Nothing sharedData pageData2 Nothing |> .view) pageModel
|
|
655
|
+
in
|
|
656
|
+
(ResponseSketch.HotUpdate pageData2 sharedData Nothing
|
|
657
|
+
|> config.encodeResponse
|
|
658
|
+
|> Bytes.Encode.encode
|
|
659
|
+
)
|
|
660
|
+
|> (\encodedData ->
|
|
661
|
+
{ route = currentPage.path |> UrlPath.toRelative
|
|
662
|
+
, contentJson = Dict.empty
|
|
663
|
+
, html = viewValue.body |> bodyToString
|
|
664
|
+
, errors = []
|
|
665
|
+
, head = tags
|
|
666
|
+
, title = viewValue.title
|
|
667
|
+
, staticHttpCache = Dict.empty
|
|
668
|
+
, is404 = False
|
|
669
|
+
, statusCode =
|
|
670
|
+
case includeHtml of
|
|
671
|
+
RenderRequest.OnlyJson ->
|
|
672
|
+
200
|
|
673
|
+
|
|
674
|
+
RenderRequest.HtmlAndJson ->
|
|
675
|
+
config.errorStatusCode error
|
|
676
|
+
, headers = record.headers |> combineHeaders
|
|
677
|
+
}
|
|
678
|
+
|> ToJsPayload.PageProgress
|
|
679
|
+
|> Effect.SendSinglePageNew encodedData
|
|
680
|
+
)
|
|
681
|
+
in
|
|
682
|
+
renderedResult
|
|
683
|
+
)
|
|
684
|
+
(config.data
|
|
685
|
+
(RenderRequest.maybeRequestPayload renderRequest
|
|
686
|
+
|> Maybe.map Internal.Request.toRequest
|
|
687
|
+
|> Maybe.withDefault Internal.Request.fakeRequest
|
|
688
|
+
)
|
|
689
|
+
serverRequestPayload.frontmatter
|
|
690
|
+
)
|
|
691
|
+
config.sharedData
|
|
692
|
+
globalHeadTags
|
|
693
|
+
)
|
|
694
|
+
|> BackendTask.onError
|
|
695
|
+
(\((Pages.Internal.FatalError.FatalError fatalError) as error) ->
|
|
696
|
+
let
|
|
697
|
+
isPreRendered : Bool
|
|
698
|
+
isPreRendered =
|
|
699
|
+
let
|
|
700
|
+
keys : Int
|
|
701
|
+
keys =
|
|
702
|
+
RenderRequest.maybeRequestPayload renderRequest |> Maybe.map (Decode.decodeValue (Decode.keyValuePairs Decode.value)) |> Maybe.withDefault (Ok []) |> Result.withDefault [] |> List.map Tuple.first |> List.length
|
|
703
|
+
in
|
|
704
|
+
-- TODO this is a bit hacky, would be nice to clean up the way of checking whether this is server-rendered or pre-rendered
|
|
705
|
+
keys <= 1
|
|
706
|
+
in
|
|
707
|
+
if isDevServer || isPreRendered then
|
|
708
|
+
-- we want to stop the build for pre-rendered routes, and give a dev server error popup in the dev server
|
|
709
|
+
BackendTask.fail error
|
|
710
|
+
|
|
711
|
+
else
|
|
712
|
+
--only render the production ErrorPage in production server-rendered Routes
|
|
713
|
+
config.sharedData
|
|
714
|
+
|> BackendTask.andThen
|
|
715
|
+
(\justSharedData ->
|
|
716
|
+
let
|
|
717
|
+
errorPage : errorPage
|
|
718
|
+
errorPage =
|
|
719
|
+
config.internalError fatalError.body
|
|
720
|
+
|
|
721
|
+
dataThing : pageData
|
|
722
|
+
dataThing =
|
|
723
|
+
errorPage
|
|
724
|
+
|> config.errorPageToData
|
|
725
|
+
|
|
726
|
+
statusCode : Int
|
|
727
|
+
statusCode =
|
|
728
|
+
config.errorStatusCode errorPage
|
|
729
|
+
|
|
730
|
+
byteEncodedPageData : Bytes
|
|
731
|
+
byteEncodedPageData =
|
|
732
|
+
ResponseSketch.HotUpdate
|
|
733
|
+
dataThing
|
|
734
|
+
justSharedData
|
|
735
|
+
-- TODO remove shared action data
|
|
736
|
+
Nothing
|
|
737
|
+
|> config.encodeResponse
|
|
738
|
+
|> Bytes.Encode.encode
|
|
556
739
|
|
|
557
|
-
|
|
558
|
-
|
|
740
|
+
pageModel : userModel
|
|
741
|
+
pageModel =
|
|
742
|
+
config.init
|
|
743
|
+
Pages.Flags.PreRenderFlags
|
|
744
|
+
justSharedData
|
|
745
|
+
dataThing
|
|
746
|
+
Nothing
|
|
747
|
+
(Just
|
|
748
|
+
{ path =
|
|
749
|
+
{ path = currentPage.path
|
|
750
|
+
, query = Nothing
|
|
751
|
+
, fragment = Nothing
|
|
752
|
+
}
|
|
753
|
+
, metadata = currentPage.route
|
|
754
|
+
, pageUrl = Nothing
|
|
755
|
+
}
|
|
756
|
+
)
|
|
757
|
+
|> Tuple.first
|
|
758
|
+
|
|
759
|
+
currentPage : { path : UrlPath, route : route }
|
|
760
|
+
currentPage =
|
|
761
|
+
{ path = serverRequestPayload.path, route = urlToRoute config currentUrl }
|
|
762
|
+
|
|
763
|
+
viewValue : { title : String, body : List (Html (PagesMsg userMsg)) }
|
|
764
|
+
viewValue =
|
|
765
|
+
(config.view Dict.empty Dict.empty Nothing currentPage Nothing justSharedData dataThing Nothing |> .view)
|
|
766
|
+
pageModel
|
|
767
|
+
in
|
|
768
|
+
{ route = UrlPath.toAbsolute currentPage.path
|
|
769
|
+
, contentJson = Dict.empty
|
|
770
|
+
, html = viewValue.body |> bodyToString
|
|
771
|
+
, errors = []
|
|
772
|
+
, head = [] -- TODO render head tags --config.view Dict.empty Dict.empty Nothing pathAndRoute Nothing justSharedData pageData Nothing |> .head
|
|
773
|
+
, title = viewValue.title
|
|
774
|
+
, staticHttpCache = Dict.empty
|
|
775
|
+
, is404 = False
|
|
776
|
+
, statusCode = statusCode
|
|
777
|
+
, headers = Dict.empty
|
|
778
|
+
}
|
|
779
|
+
|> ToJsPayload.PageProgress
|
|
780
|
+
|> Effect.SendSinglePageNew byteEncodedPageData
|
|
781
|
+
|> BackendTask.succeed
|
|
782
|
+
)
|
|
783
|
+
)
|
|
784
|
+
|
|
785
|
+
Just notFoundReason ->
|
|
786
|
+
render404Page config
|
|
787
|
+
Nothing
|
|
788
|
+
-- TODO do I need sharedDataResult?
|
|
789
|
+
--(Result.toMaybe sharedDataResult)
|
|
790
|
+
isDevServer
|
|
791
|
+
serverRequestPayload.path
|
|
792
|
+
notFoundReason
|
|
793
|
+
|> BackendTask.succeed
|
|
794
|
+
)
|
|
559
795
|
|
|
560
|
-
|
|
561
|
-
|
|
796
|
+
RenderRequest.Api ( path, ApiRoute apiHandler ) ->
|
|
797
|
+
BackendTask.map2
|
|
798
|
+
(\response _ ->
|
|
799
|
+
case response of
|
|
800
|
+
Just okResponse ->
|
|
801
|
+
{ body = okResponse
|
|
802
|
+
, staticHttpCache = Dict.empty -- TODO do I need to serialize the full cache here, or can I handle that from the JS side?
|
|
803
|
+
, statusCode = 200
|
|
804
|
+
}
|
|
805
|
+
|> ToJsPayload.SendApiResponse
|
|
806
|
+
|> Effect.SendSinglePage
|
|
807
|
+
|
|
808
|
+
Nothing ->
|
|
809
|
+
render404Page config
|
|
810
|
+
-- TODO do I need sharedDataResult here?
|
|
811
|
+
Nothing
|
|
812
|
+
isDevServer
|
|
813
|
+
(UrlPath.fromString path)
|
|
814
|
+
NotFoundReason.NoMatchingRoute
|
|
815
|
+
--Err error ->
|
|
816
|
+
-- [ error ]
|
|
817
|
+
-- |> ToJsPayload.Errors
|
|
818
|
+
-- |> Effect.SendSinglePage
|
|
819
|
+
)
|
|
820
|
+
(apiHandler.matchesToResponse
|
|
821
|
+
(renderRequest
|
|
822
|
+
|> RenderRequest.maybeRequestPayload
|
|
823
|
+
|> Maybe.withDefault Json.Encode.null
|
|
824
|
+
)
|
|
825
|
+
path
|
|
826
|
+
)
|
|
827
|
+
globalHeadTags
|
|
828
|
+
|
|
829
|
+
RenderRequest.NotFound notFoundPath ->
|
|
830
|
+
(BackendTask.map2
|
|
831
|
+
(\_ _ ->
|
|
832
|
+
render404Page config
|
|
833
|
+
Nothing
|
|
834
|
+
--(Result.toMaybe sharedDataResult)
|
|
835
|
+
--model
|
|
836
|
+
isDevServer
|
|
837
|
+
notFoundPath
|
|
838
|
+
NotFoundReason.NoMatchingRoute
|
|
839
|
+
)
|
|
840
|
+
(BackendTask.succeed [])
|
|
841
|
+
globalHeadTags
|
|
842
|
+
-- TODO is there a way to resolve sharedData but get it as a Result if it fails?
|
|
843
|
+
--config.sharedData
|
|
844
|
+
)
|
|
562
845
|
|
|
563
846
|
initialModel : Model route
|
|
564
847
|
initialModel =
|
|
565
|
-
{ staticResponses =
|
|
848
|
+
{ staticResponses = staticResponsesNew
|
|
566
849
|
, errors = []
|
|
567
|
-
, allRawResponses = staticHttpCache
|
|
568
|
-
, unprocessedPages = unprocessedPages
|
|
569
850
|
, maybeRequestJson = renderRequest
|
|
570
851
|
, isDevServer = isDevServer
|
|
571
852
|
}
|
|
572
853
|
in
|
|
573
|
-
StaticResponses.nextStep initialModel
|
|
574
|
-
|> nextStepToEffect
|
|
575
|
-
config
|
|
854
|
+
StaticResponses.nextStep (Json.Encode.object []) initialModel.staticResponses initialModel
|
|
855
|
+
|> nextStepToEffect
|
|
576
856
|
initialModel
|
|
577
857
|
|
|
578
858
|
|
|
579
859
|
updateAndSendPortIfDone :
|
|
580
|
-
|
|
581
|
-
-> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
|
|
582
|
-
-> Model route
|
|
860
|
+
Model route
|
|
583
861
|
-> ( Model route, Effect )
|
|
584
|
-
updateAndSendPortIfDone
|
|
585
|
-
StaticResponses.nextStep
|
|
862
|
+
updateAndSendPortIfDone model =
|
|
863
|
+
StaticResponses.nextStep (Json.Encode.object [])
|
|
864
|
+
model.staticResponses
|
|
586
865
|
model
|
|
587
|
-
|
|
588
|
-
|> nextStepToEffect site config model
|
|
866
|
+
|> nextStepToEffect model
|
|
589
867
|
|
|
590
868
|
|
|
591
869
|
{-| -}
|
|
592
870
|
update :
|
|
593
|
-
|
|
594
|
-
-> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
|
|
595
|
-
-> Msg
|
|
871
|
+
Msg
|
|
596
872
|
-> Model route
|
|
597
873
|
-> ( Model route, Effect )
|
|
598
|
-
update
|
|
874
|
+
update msg model =
|
|
599
875
|
case msg of
|
|
600
876
|
GotDataBatch batch ->
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|> StaticResponses.batchUpdate batch
|
|
606
|
-
in
|
|
607
|
-
StaticResponses.nextStep
|
|
608
|
-
updatedModel
|
|
609
|
-
Nothing
|
|
610
|
-
|> nextStepToEffect site config updatedModel
|
|
877
|
+
StaticResponses.nextStep batch
|
|
878
|
+
model.staticResponses
|
|
879
|
+
model
|
|
880
|
+
|> nextStepToEffect model
|
|
611
881
|
|
|
612
882
|
GotBuildError buildError ->
|
|
613
883
|
let
|
|
@@ -618,560 +888,45 @@ update site config msg model =
|
|
|
618
888
|
buildError :: model.errors
|
|
619
889
|
}
|
|
620
890
|
in
|
|
621
|
-
StaticResponses.nextStep
|
|
891
|
+
StaticResponses.nextStep (Json.Encode.object [])
|
|
892
|
+
updatedModel.staticResponses
|
|
622
893
|
updatedModel
|
|
623
|
-
|
|
624
|
-
|> nextStepToEffect site config updatedModel
|
|
894
|
+
|> nextStepToEffect updatedModel
|
|
625
895
|
|
|
626
896
|
|
|
627
897
|
nextStepToEffect :
|
|
628
|
-
|
|
629
|
-
->
|
|
630
|
-
-> Model route
|
|
631
|
-
-> ( StaticResponses, StaticResponses.NextStep route )
|
|
898
|
+
Model route
|
|
899
|
+
-> StaticResponses.NextStep route Effect
|
|
632
900
|
-> ( Model route, Effect )
|
|
633
|
-
nextStepToEffect
|
|
901
|
+
nextStepToEffect model nextStep =
|
|
634
902
|
case nextStep of
|
|
635
|
-
StaticResponses.Continue
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
newRoutes
|
|
642
|
-
|> List.map
|
|
643
|
-
(\route ->
|
|
644
|
-
( Path.join (config.routeToPath route)
|
|
645
|
-
, route
|
|
646
|
-
)
|
|
647
|
-
)
|
|
648
|
-
|
|
649
|
-
Nothing ->
|
|
650
|
-
model.unprocessedPages
|
|
651
|
-
|
|
652
|
-
updatedModel : Model route
|
|
653
|
-
updatedModel =
|
|
654
|
-
{ model
|
|
655
|
-
| allRawResponses = updatedAllRawResponses
|
|
656
|
-
, staticResponses = updatedStaticResponsesModel
|
|
657
|
-
, unprocessedPages = updatedUnprocessedPages
|
|
658
|
-
}
|
|
659
|
-
in
|
|
660
|
-
if List.isEmpty httpRequests then
|
|
661
|
-
nextStepToEffect site
|
|
662
|
-
config
|
|
663
|
-
updatedModel
|
|
664
|
-
(StaticResponses.nextStep
|
|
665
|
-
updatedModel
|
|
666
|
-
Nothing
|
|
667
|
-
)
|
|
668
|
-
|
|
669
|
-
else
|
|
670
|
-
( updatedModel
|
|
671
|
-
, (httpRequests
|
|
672
|
-
|> List.map Effect.FetchHttp
|
|
673
|
-
)
|
|
674
|
-
|> Effect.Batch
|
|
675
|
-
)
|
|
676
|
-
|
|
677
|
-
StaticResponses.Finish toJsPayload ->
|
|
678
|
-
case toJsPayload of
|
|
679
|
-
StaticResponses.ApiResponse ->
|
|
680
|
-
let
|
|
681
|
-
apiResponse : Effect
|
|
682
|
-
apiResponse =
|
|
683
|
-
case model.maybeRequestJson of
|
|
684
|
-
RenderRequest.SinglePage _ requestPayload _ ->
|
|
685
|
-
let
|
|
686
|
-
sharedDataResult : Result BuildError sharedData
|
|
687
|
-
sharedDataResult =
|
|
688
|
-
StaticHttpRequest.resolve
|
|
689
|
-
config.sharedData
|
|
690
|
-
model.allRawResponses
|
|
691
|
-
|> Result.mapError (StaticHttpRequest.toBuildError "")
|
|
692
|
-
in
|
|
693
|
-
case requestPayload of
|
|
694
|
-
RenderRequest.Api ( path, ApiRoute apiHandler ) ->
|
|
695
|
-
let
|
|
696
|
-
thing : DataSource (Maybe ApiRoute.Response)
|
|
697
|
-
thing =
|
|
698
|
-
apiHandler.matchesToResponse path
|
|
699
|
-
in
|
|
700
|
-
StaticHttpRequest.resolve
|
|
701
|
-
thing
|
|
702
|
-
model.allRawResponses
|
|
703
|
-
|> Result.mapError (StaticHttpRequest.toBuildError "TODO - path from request")
|
|
704
|
-
|> (\response ->
|
|
705
|
-
case response of
|
|
706
|
-
Ok (Just okResponse) ->
|
|
707
|
-
{ body = okResponse
|
|
708
|
-
, staticHttpCache = Dict.empty -- TODO do I need to serialize the full cache here, or can I handle that from the JS side?
|
|
709
|
-
|
|
710
|
-
-- model.allRawResponses |> Dict.Extra.filterMap (\_ v -> v)
|
|
711
|
-
, statusCode = 200
|
|
712
|
-
}
|
|
713
|
-
|> ToJsPayload.SendApiResponse
|
|
714
|
-
|> Effect.SendSinglePage
|
|
715
|
-
|
|
716
|
-
Ok Nothing ->
|
|
717
|
-
render404Page config (Result.toMaybe sharedDataResult) model (Path.fromString path) NotFoundReason.NoMatchingRoute
|
|
718
|
-
|
|
719
|
-
Err error ->
|
|
720
|
-
[ error ]
|
|
721
|
-
|> ToJsPayload.Errors
|
|
722
|
-
|> Effect.SendSinglePage
|
|
723
|
-
)
|
|
724
|
-
|
|
725
|
-
RenderRequest.Page payload ->
|
|
726
|
-
let
|
|
727
|
-
pageFoundResult : Result BuildError (Maybe NotFoundReason)
|
|
728
|
-
pageFoundResult =
|
|
729
|
-
StaticHttpRequest.resolve
|
|
730
|
-
(if model.isDevServer then
|
|
731
|
-
-- TODO OPTIMIZATION this is redundant
|
|
732
|
-
config.handleRoute payload.frontmatter
|
|
733
|
-
|
|
734
|
-
else
|
|
735
|
-
DataSource.succeed Nothing
|
|
736
|
-
)
|
|
737
|
-
model.allRawResponses
|
|
738
|
-
|> Result.mapError (StaticHttpRequest.toBuildError (payload.path |> Path.toAbsolute))
|
|
739
|
-
in
|
|
740
|
-
case pageFoundResult of
|
|
741
|
-
Ok Nothing ->
|
|
742
|
-
sendSinglePageProgress site model.allRawResponses config model payload
|
|
743
|
-
|
|
744
|
-
Ok (Just notFoundReason) ->
|
|
745
|
-
render404Page config
|
|
746
|
-
--Nothing
|
|
747
|
-
(Result.toMaybe sharedDataResult)
|
|
748
|
-
model
|
|
749
|
-
payload.path
|
|
750
|
-
notFoundReason
|
|
751
|
-
|
|
752
|
-
Err error ->
|
|
753
|
-
[ error ] |> ToJsPayload.Errors |> Effect.SendSinglePage
|
|
754
|
-
|
|
755
|
-
RenderRequest.NotFound path ->
|
|
756
|
-
render404Page config
|
|
757
|
-
--Nothing
|
|
758
|
-
(Result.toMaybe sharedDataResult)
|
|
759
|
-
model
|
|
760
|
-
path
|
|
761
|
-
NotFoundReason.NoMatchingRoute
|
|
762
|
-
in
|
|
763
|
-
( model
|
|
764
|
-
, apiResponse
|
|
765
|
-
)
|
|
766
|
-
|
|
767
|
-
StaticResponses.Errors errors ->
|
|
768
|
-
( model
|
|
769
|
-
, errors |> ToJsPayload.Errors |> Effect.SendSinglePage
|
|
770
|
-
)
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
sendSinglePageProgress :
|
|
774
|
-
SiteConfig
|
|
775
|
-
-> RequestsAndPending
|
|
776
|
-
-> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
|
|
777
|
-
-> Model route
|
|
778
|
-
-> { path : Path, frontmatter : route }
|
|
779
|
-
-> Effect
|
|
780
|
-
sendSinglePageProgress site contentJson config model info =
|
|
781
|
-
let
|
|
782
|
-
( page, route ) =
|
|
783
|
-
( info.path, info.frontmatter )
|
|
784
|
-
in
|
|
785
|
-
case model.maybeRequestJson of
|
|
786
|
-
RenderRequest.SinglePage includeHtml _ _ ->
|
|
787
|
-
let
|
|
788
|
-
isAction : Maybe ActionRequest
|
|
789
|
-
isAction =
|
|
790
|
-
model.maybeRequestJson
|
|
791
|
-
|> RenderRequest.maybeRequestPayload
|
|
792
|
-
|> Maybe.andThen (Decode.decodeValue isActionDecoder >> Result.withDefault Nothing)
|
|
793
|
-
|
|
794
|
-
pageFoundResult : Result BuildError (Maybe NotFoundReason)
|
|
795
|
-
pageFoundResult =
|
|
796
|
-
-- TODO OPTIMIZATION this is redundant
|
|
797
|
-
StaticHttpRequest.resolve
|
|
798
|
-
(if model.isDevServer then
|
|
799
|
-
config.handleRoute route
|
|
800
|
-
|
|
801
|
-
else
|
|
802
|
-
DataSource.succeed Nothing
|
|
803
|
-
)
|
|
804
|
-
model.allRawResponses
|
|
805
|
-
|> Result.mapError (StaticHttpRequest.toBuildError currentUrl.path)
|
|
806
|
-
|
|
807
|
-
renderedResult : Result BuildError (PageServerResponse { head : List Head.Tag, view : String, title : String } errorPage)
|
|
808
|
-
renderedResult =
|
|
809
|
-
case includeHtml of
|
|
810
|
-
RenderRequest.OnlyJson ->
|
|
811
|
-
pageDataResult
|
|
812
|
-
|> Result.map
|
|
813
|
-
(\okPageData ->
|
|
814
|
-
case okPageData of
|
|
815
|
-
PageServerResponse.RenderPage responseInfo _ ->
|
|
816
|
-
PageServerResponse.RenderPage
|
|
817
|
-
{ statusCode = responseInfo.statusCode
|
|
818
|
-
, headers = responseInfo.headers
|
|
819
|
-
}
|
|
820
|
-
{ head = []
|
|
821
|
-
, view = "This page was not rendered because it is a JSON-only request."
|
|
822
|
-
, title = "This page was not rendered because it is a JSON-only request."
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
PageServerResponse.ServerResponse serverResponse ->
|
|
826
|
-
PageServerResponse.ServerResponse serverResponse
|
|
827
|
-
|
|
828
|
-
PageServerResponse.ErrorPage error record ->
|
|
829
|
-
PageServerResponse.ErrorPage error record
|
|
830
|
-
)
|
|
831
|
-
|
|
832
|
-
RenderRequest.HtmlAndJson ->
|
|
833
|
-
Result.map2 Tuple.pair pageDataResult sharedDataResult
|
|
834
|
-
|> Result.map
|
|
835
|
-
(\( pageData_, sharedData ) ->
|
|
836
|
-
case pageData_ of
|
|
837
|
-
PageServerResponse.RenderPage responseInfo pageData ->
|
|
838
|
-
let
|
|
839
|
-
currentPage : { path : Path, route : route }
|
|
840
|
-
currentPage =
|
|
841
|
-
{ path = page, route = urlToRoute config currentUrl }
|
|
842
|
-
|
|
843
|
-
maybeActionData : Maybe actionData
|
|
844
|
-
maybeActionData =
|
|
845
|
-
case isAction of
|
|
846
|
-
Just _ ->
|
|
847
|
-
case actionDataResult of
|
|
848
|
-
Ok (PageServerResponse.RenderPage _ actionData) ->
|
|
849
|
-
Just actionData
|
|
850
|
-
|
|
851
|
-
_ ->
|
|
852
|
-
Nothing
|
|
853
|
-
|
|
854
|
-
Nothing ->
|
|
855
|
-
Nothing
|
|
856
|
-
|
|
857
|
-
pageModel : userModel
|
|
858
|
-
pageModel =
|
|
859
|
-
config.init
|
|
860
|
-
Pages.Flags.PreRenderFlags
|
|
861
|
-
sharedData
|
|
862
|
-
pageData
|
|
863
|
-
maybeActionData
|
|
864
|
-
(Just
|
|
865
|
-
{ path =
|
|
866
|
-
{ path = currentPage.path
|
|
867
|
-
, query = Nothing
|
|
868
|
-
, fragment = Nothing
|
|
869
|
-
}
|
|
870
|
-
, metadata = currentPage.route
|
|
871
|
-
, pageUrl = Nothing
|
|
872
|
-
}
|
|
873
|
-
)
|
|
874
|
-
|> Tuple.first
|
|
875
|
-
|
|
876
|
-
viewValue : { title : String, body : List (Html (Pages.Msg.Msg userMsg)) }
|
|
877
|
-
viewValue =
|
|
878
|
-
(config.view Dict.empty Dict.empty Nothing currentPage Nothing sharedData pageData maybeActionData |> .view) pageModel
|
|
879
|
-
in
|
|
880
|
-
PageServerResponse.RenderPage responseInfo
|
|
881
|
-
{ head = config.view Dict.empty Dict.empty Nothing currentPage Nothing sharedData pageData maybeActionData |> .head
|
|
882
|
-
, view = viewValue.body |> bodyToString
|
|
883
|
-
, title = viewValue.title
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
PageServerResponse.ServerResponse serverResponse ->
|
|
887
|
-
PageServerResponse.ServerResponse serverResponse
|
|
888
|
-
|
|
889
|
-
PageServerResponse.ErrorPage error record ->
|
|
890
|
-
let
|
|
891
|
-
currentPage : { path : Path, route : route }
|
|
892
|
-
currentPage =
|
|
893
|
-
{ path = page, route = urlToRoute config currentUrl }
|
|
894
|
-
|
|
895
|
-
pageModel : userModel
|
|
896
|
-
pageModel =
|
|
897
|
-
config.init
|
|
898
|
-
Pages.Flags.PreRenderFlags
|
|
899
|
-
sharedData
|
|
900
|
-
pageData
|
|
901
|
-
Nothing
|
|
902
|
-
(Just
|
|
903
|
-
{ path =
|
|
904
|
-
{ path = currentPage.path
|
|
905
|
-
, query = Nothing
|
|
906
|
-
, fragment = Nothing
|
|
907
|
-
}
|
|
908
|
-
, metadata = currentPage.route
|
|
909
|
-
, pageUrl = Nothing
|
|
910
|
-
}
|
|
911
|
-
)
|
|
912
|
-
|> Tuple.first
|
|
913
|
-
|
|
914
|
-
pageData : pageData
|
|
915
|
-
pageData =
|
|
916
|
-
config.errorPageToData error
|
|
917
|
-
|
|
918
|
-
viewValue : { title : String, body : List (Html (Pages.Msg.Msg userMsg)) }
|
|
919
|
-
viewValue =
|
|
920
|
-
(config.view Dict.empty Dict.empty Nothing currentPage Nothing sharedData pageData Nothing |> .view) pageModel
|
|
921
|
-
in
|
|
922
|
-
PageServerResponse.RenderPage
|
|
923
|
-
{ statusCode = config.errorStatusCode error
|
|
924
|
-
, headers = record.headers
|
|
925
|
-
}
|
|
926
|
-
{ head = config.view Dict.empty Dict.empty Nothing currentPage Nothing sharedData pageData Nothing |> .head
|
|
927
|
-
, view = viewValue.body |> List.map (HtmlPrinter.htmlToString Nothing) |> String.join "\n"
|
|
928
|
-
, title = viewValue.title
|
|
929
|
-
}
|
|
930
|
-
)
|
|
931
|
-
|
|
932
|
-
currentUrl : Url
|
|
933
|
-
currentUrl =
|
|
934
|
-
{ protocol = Url.Https
|
|
935
|
-
, host = site.canonicalUrl
|
|
936
|
-
, port_ = Nothing
|
|
937
|
-
, path = page |> Path.toRelative
|
|
938
|
-
, query = Nothing
|
|
939
|
-
, fragment = Nothing
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
pageDataResult : Result BuildError (PageServerResponse pageData errorPage)
|
|
943
|
-
pageDataResult =
|
|
944
|
-
-- TODO OPTIMIZATION can these three be included in StaticResponses.Finish?
|
|
945
|
-
StaticHttpRequest.resolve
|
|
946
|
-
(case isAction of
|
|
947
|
-
Just _ ->
|
|
948
|
-
config.action (urlToRoute config currentUrl)
|
|
949
|
-
|> DataSource.andThen
|
|
950
|
-
(\something ->
|
|
951
|
-
case something of
|
|
952
|
-
PageServerResponse.ErrorPage a b ->
|
|
953
|
-
PageServerResponse.ErrorPage a b
|
|
954
|
-
|> DataSource.succeed
|
|
955
|
-
|
|
956
|
-
PageServerResponse.RenderPage _ _ ->
|
|
957
|
-
-- TODO the headers/response codes are ignored from the action here
|
|
958
|
-
-- is that okay? Should you always do a redirect or another kind of
|
|
959
|
-
-- server response if you want to control the headers/response code for an action (like logout & redirect, for example)?
|
|
960
|
-
config.data (urlToRoute config currentUrl)
|
|
961
|
-
|
|
962
|
-
PageServerResponse.ServerResponse a ->
|
|
963
|
-
PageServerResponse.ServerResponse a
|
|
964
|
-
|> DataSource.succeed
|
|
965
|
-
)
|
|
966
|
-
|
|
967
|
-
Nothing ->
|
|
968
|
-
config.data (urlToRoute config currentUrl)
|
|
969
|
-
)
|
|
970
|
-
contentJson
|
|
971
|
-
|> Result.mapError (StaticHttpRequest.toBuildError currentUrl.path)
|
|
972
|
-
|
|
973
|
-
actionDataResult : Result BuildError (PageServerResponse actionData errorPage)
|
|
974
|
-
actionDataResult =
|
|
975
|
-
-- TODO OPTIMIZATION can these three be included in StaticResponses.Finish?
|
|
976
|
-
StaticHttpRequest.resolve
|
|
977
|
-
(config.action (urlToRoute config currentUrl))
|
|
978
|
-
contentJson
|
|
979
|
-
|> Result.mapError (StaticHttpRequest.toBuildError currentUrl.path)
|
|
980
|
-
|
|
981
|
-
sharedDataResult : Result BuildError sharedData
|
|
982
|
-
sharedDataResult =
|
|
983
|
-
StaticHttpRequest.resolve
|
|
984
|
-
config.sharedData
|
|
985
|
-
contentJson
|
|
986
|
-
|> Result.mapError (StaticHttpRequest.toBuildError currentUrl.path)
|
|
987
|
-
|
|
988
|
-
globalHeadTags : DataSource (List Head.Tag)
|
|
989
|
-
globalHeadTags =
|
|
990
|
-
(config.globalHeadTags |> Maybe.withDefault (\_ -> DataSource.succeed [])) HtmlPrinter.htmlToString
|
|
991
|
-
|
|
992
|
-
siteDataResult : Result BuildError (List Head.Tag)
|
|
993
|
-
siteDataResult =
|
|
994
|
-
StaticHttpRequest.resolve
|
|
995
|
-
globalHeadTags
|
|
996
|
-
model.allRawResponses
|
|
997
|
-
|> Result.mapError (StaticHttpRequest.toBuildError "Site.elm")
|
|
998
|
-
in
|
|
999
|
-
case Result.map3 (\a b c -> ( a, b, c )) pageFoundResult renderedResult siteDataResult of
|
|
1000
|
-
Ok ( maybeNotFoundReason, renderedOrApiResponse, siteData ) ->
|
|
1001
|
-
case maybeNotFoundReason of
|
|
1002
|
-
Nothing ->
|
|
1003
|
-
let
|
|
1004
|
-
( actionHeaders, byteEncodedPageData ) =
|
|
1005
|
-
case pageDataResult of
|
|
1006
|
-
Ok pageServerResponse ->
|
|
1007
|
-
case pageServerResponse of
|
|
1008
|
-
PageServerResponse.RenderPage ignored1 pageData ->
|
|
1009
|
-
-- TODO want to encode both shared and page data in dev server and HTML-embedded data
|
|
1010
|
-
-- but not for writing out the content.dat files - would be good to optimize this redundant data out
|
|
1011
|
-
--if model.isDevServer then
|
|
1012
|
-
case isAction of
|
|
1013
|
-
Just actionRequestKind ->
|
|
1014
|
-
case actionDataResult of
|
|
1015
|
-
Ok (PageServerResponse.RenderPage ignored2 actionData) ->
|
|
1016
|
-
case actionRequestKind of
|
|
1017
|
-
ActionResponseRequest ->
|
|
1018
|
-
( ignored2.headers
|
|
1019
|
-
, sharedDataResult
|
|
1020
|
-
|> Result.map (\sharedData -> ResponseSketch.HotUpdate pageData sharedData (Just actionData))
|
|
1021
|
-
|> Result.withDefault (ResponseSketch.RenderPage pageData (Just actionData))
|
|
1022
|
-
|> config.encodeResponse
|
|
1023
|
-
|> Bytes.Encode.encode
|
|
1024
|
-
)
|
|
1025
|
-
|
|
1026
|
-
ActionOnlyRequest ->
|
|
1027
|
-
---- TODO need to encode action data when only that is requested (not ResponseSketch?)
|
|
1028
|
-
( ignored2.headers
|
|
1029
|
-
, actionData
|
|
1030
|
-
|> config.encodeAction
|
|
1031
|
-
|> Bytes.Encode.encode
|
|
1032
|
-
)
|
|
1033
|
-
|
|
1034
|
-
_ ->
|
|
1035
|
-
( ignored1.headers
|
|
1036
|
-
, Bytes.Encode.encode (Bytes.Encode.unsignedInt8 0)
|
|
1037
|
-
)
|
|
1038
|
-
|
|
1039
|
-
Nothing ->
|
|
1040
|
-
( ignored1.headers
|
|
1041
|
-
, sharedDataResult
|
|
1042
|
-
|> Result.map (\something -> ResponseSketch.HotUpdate pageData something Nothing)
|
|
1043
|
-
|> Result.withDefault (ResponseSketch.RenderPage pageData Nothing)
|
|
1044
|
-
|> config.encodeResponse
|
|
1045
|
-
|> Bytes.Encode.encode
|
|
1046
|
-
)
|
|
1047
|
-
|
|
1048
|
-
--else
|
|
1049
|
-
-- pageData
|
|
1050
|
-
-- |> ResponseSketch.RenderPage
|
|
1051
|
-
-- |> config.encodeResponse
|
|
1052
|
-
-- |> Bytes.Encode.encode
|
|
1053
|
-
PageServerResponse.ServerResponse serverResponse ->
|
|
1054
|
-
-- TODO handle error?
|
|
1055
|
-
( serverResponse.headers
|
|
1056
|
-
, PageServerResponse.toRedirect serverResponse
|
|
1057
|
-
|> Maybe.map
|
|
1058
|
-
(\{ location } ->
|
|
1059
|
-
location
|
|
1060
|
-
|> ResponseSketch.Redirect
|
|
1061
|
-
|> config.encodeResponse
|
|
1062
|
-
)
|
|
1063
|
-
-- TODO handle other cases besides redirects?
|
|
1064
|
-
|> Maybe.withDefault (Bytes.Encode.unsignedInt8 0)
|
|
1065
|
-
|> Bytes.Encode.encode
|
|
1066
|
-
)
|
|
1067
|
-
|
|
1068
|
-
PageServerResponse.ErrorPage error { headers } ->
|
|
1069
|
-
-- TODO this case should never happen
|
|
1070
|
-
( headers
|
|
1071
|
-
, sharedDataResult
|
|
1072
|
-
|> Result.map
|
|
1073
|
-
(\sharedData ->
|
|
1074
|
-
ResponseSketch.HotUpdate (config.errorPageToData error)
|
|
1075
|
-
sharedData
|
|
1076
|
-
Nothing
|
|
1077
|
-
)
|
|
1078
|
-
|> Result.map config.encodeResponse
|
|
1079
|
-
|> Result.map Bytes.Encode.encode
|
|
1080
|
-
|> Result.withDefault (Bytes.Encode.encode (Bytes.Encode.unsignedInt8 0))
|
|
1081
|
-
)
|
|
1082
|
-
|
|
1083
|
-
_ ->
|
|
1084
|
-
-- TODO handle error?
|
|
1085
|
-
( []
|
|
1086
|
-
, Bytes.Encode.encode (Bytes.Encode.unsignedInt8 0)
|
|
1087
|
-
)
|
|
1088
|
-
in
|
|
1089
|
-
case renderedOrApiResponse of
|
|
1090
|
-
PageServerResponse.RenderPage responseInfo rendered ->
|
|
1091
|
-
{ route = page |> Path.toRelative
|
|
1092
|
-
, contentJson = Dict.empty
|
|
1093
|
-
, html = rendered.view
|
|
1094
|
-
, errors = []
|
|
1095
|
-
, head = rendered.head ++ siteData
|
|
1096
|
-
, title = rendered.title
|
|
1097
|
-
, staticHttpCache = Dict.empty
|
|
1098
|
-
, is404 = False
|
|
1099
|
-
, statusCode = responseInfo.statusCode
|
|
1100
|
-
, headers =
|
|
1101
|
-
-- TODO should `responseInfo.headers` be used? Is there a problem in the case where there is both an action and data response in one? Do we need to make sure it is performed as two separate HTTP requests to ensure that the cookies are set correctly in that case?
|
|
1102
|
-
actionHeaders
|
|
1103
|
-
}
|
|
1104
|
-
|> ToJsPayload.PageProgress
|
|
1105
|
-
|> Effect.SendSinglePageNew byteEncodedPageData
|
|
1106
|
-
|
|
1107
|
-
PageServerResponse.ServerResponse serverResponse ->
|
|
1108
|
-
PageServerResponse.toRedirect serverResponse
|
|
1109
|
-
|> Maybe.map
|
|
1110
|
-
(\_ ->
|
|
1111
|
-
{ route = page |> Path.toRelative
|
|
1112
|
-
, contentJson = Dict.empty
|
|
1113
|
-
, html = "This is intentionally blank HTML"
|
|
1114
|
-
, errors = []
|
|
1115
|
-
, head = []
|
|
1116
|
-
, title = "This is an intentionally blank title"
|
|
1117
|
-
, staticHttpCache = Dict.empty
|
|
1118
|
-
, is404 = False
|
|
1119
|
-
, statusCode =
|
|
1120
|
-
case includeHtml of
|
|
1121
|
-
RenderRequest.OnlyJson ->
|
|
1122
|
-
-- if this is a redirect for a `content.dat`, we don't want to send an *actual* redirect status code because the redirect needs to be handled in Elm (not by the Browser)
|
|
1123
|
-
200
|
|
1124
|
-
|
|
1125
|
-
RenderRequest.HtmlAndJson ->
|
|
1126
|
-
serverResponse.statusCode
|
|
1127
|
-
, headers = serverResponse.headers
|
|
1128
|
-
}
|
|
1129
|
-
|> ToJsPayload.PageProgress
|
|
1130
|
-
|> Effect.SendSinglePageNew byteEncodedPageData
|
|
1131
|
-
)
|
|
1132
|
-
|> Maybe.withDefault
|
|
1133
|
-
({ body = serverResponse |> PageServerResponse.toJson
|
|
1134
|
-
, staticHttpCache = Dict.empty
|
|
1135
|
-
, statusCode = serverResponse.statusCode
|
|
1136
|
-
}
|
|
1137
|
-
|> ToJsPayload.SendApiResponse
|
|
1138
|
-
|> Effect.SendSinglePage
|
|
1139
|
-
)
|
|
1140
|
-
|
|
1141
|
-
PageServerResponse.ErrorPage error responseInfo ->
|
|
1142
|
-
-- TODO this case should never happen
|
|
1143
|
-
{ route = page |> Path.toRelative
|
|
1144
|
-
, contentJson = Dict.empty
|
|
1145
|
-
, html = "UNEXPECTED!" --HtmlPrinter.htmlToString rendered.body
|
|
1146
|
-
, errors = []
|
|
1147
|
-
, head = [] -- rendered.head ++ siteData -- TODO this should call ErrorPage.head maybe?
|
|
1148
|
-
, title = "UNEXPECTED CASE" --rendered.title
|
|
1149
|
-
, staticHttpCache = Dict.empty
|
|
1150
|
-
, is404 = False
|
|
1151
|
-
, statusCode = config.errorStatusCode error
|
|
1152
|
-
, headers = responseInfo.headers
|
|
1153
|
-
}
|
|
1154
|
-
|> ToJsPayload.PageProgress
|
|
1155
|
-
|> Effect.SendSinglePageNew byteEncodedPageData
|
|
903
|
+
StaticResponses.Continue httpRequests updatedStaticResponsesModel ->
|
|
904
|
+
( { model
|
|
905
|
+
| staticResponses = updatedStaticResponsesModel
|
|
906
|
+
}
|
|
907
|
+
, Effect.FetchHttp httpRequests
|
|
908
|
+
)
|
|
1156
909
|
|
|
1157
|
-
|
|
1158
|
-
|
|
910
|
+
StaticResponses.FinishedWithErrors errors ->
|
|
911
|
+
( model
|
|
912
|
+
, errors |> ToJsPayload.Errors |> Effect.SendSinglePage
|
|
913
|
+
)
|
|
1159
914
|
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
915
|
+
StaticResponses.Finish finalValue ->
|
|
916
|
+
( model
|
|
917
|
+
, finalValue
|
|
918
|
+
)
|
|
1164
919
|
|
|
1165
920
|
|
|
1166
921
|
render404Page :
|
|
1167
922
|
ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
|
|
1168
923
|
-> Maybe sharedData
|
|
1169
|
-
->
|
|
1170
|
-
->
|
|
924
|
+
-> Bool
|
|
925
|
+
-> UrlPath
|
|
1171
926
|
-> NotFoundReason
|
|
1172
927
|
-> Effect
|
|
1173
|
-
render404Page config sharedData
|
|
1174
|
-
case (
|
|
928
|
+
render404Page config sharedData isDevServer path notFoundReason =
|
|
929
|
+
case ( isDevServer, sharedData ) of
|
|
1175
930
|
( False, Just justSharedData ) ->
|
|
1176
931
|
let
|
|
1177
932
|
byteEncodedPageData : Bytes
|
|
@@ -1198,11 +953,11 @@ render404Page config sharedData model path notFoundReason =
|
|
|
1198
953
|
pageData =
|
|
1199
954
|
config.errorPageToData config.notFoundPage
|
|
1200
955
|
|
|
1201
|
-
pathAndRoute : { path :
|
|
956
|
+
pathAndRoute : { path : UrlPath, route : route }
|
|
1202
957
|
pathAndRoute =
|
|
1203
958
|
{ path = path, route = config.notFoundRoute }
|
|
1204
959
|
|
|
1205
|
-
viewValue : { title : String, body : List (Html (
|
|
960
|
+
viewValue : { title : String, body : List (Html (PagesMsg userMsg)) }
|
|
1206
961
|
viewValue =
|
|
1207
962
|
(config.view Dict.empty
|
|
1208
963
|
Dict.empty
|
|
@@ -1216,7 +971,7 @@ render404Page config sharedData model path notFoundReason =
|
|
|
1216
971
|
)
|
|
1217
972
|
pageModel
|
|
1218
973
|
in
|
|
1219
|
-
{ route =
|
|
974
|
+
{ route = UrlPath.toAbsolute path
|
|
1220
975
|
, contentJson = Dict.empty
|
|
1221
976
|
, html = viewValue.body |> bodyToString
|
|
1222
977
|
, errors = []
|
|
@@ -1225,7 +980,7 @@ render404Page config sharedData model path notFoundReason =
|
|
|
1225
980
|
, staticHttpCache = Dict.empty
|
|
1226
981
|
, is404 = True
|
|
1227
982
|
, statusCode = 404
|
|
1228
|
-
, headers =
|
|
983
|
+
, headers = Dict.empty
|
|
1229
984
|
}
|
|
1230
985
|
|> ToJsPayload.PageProgress
|
|
1231
986
|
|> Effect.SendSinglePageNew byteEncodedPageData
|
|
@@ -1245,7 +1000,7 @@ render404Page config sharedData model path notFoundReason =
|
|
|
1245
1000
|
}
|
|
1246
1001
|
|> NotFoundReason.document config.pathPatterns
|
|
1247
1002
|
in
|
|
1248
|
-
{ route =
|
|
1003
|
+
{ route = UrlPath.toAbsolute path
|
|
1249
1004
|
, contentJson = Dict.empty
|
|
1250
1005
|
, html = bodyToString notFoundDocument.body
|
|
1251
1006
|
, errors = []
|
|
@@ -1257,7 +1012,7 @@ render404Page config sharedData model path notFoundReason =
|
|
|
1257
1012
|
--model.allRawResponses |> Dict.Extra.filterMap (\_ v -> v)
|
|
1258
1013
|
, is404 = True
|
|
1259
1014
|
, statusCode = 404
|
|
1260
|
-
, headers =
|
|
1015
|
+
, headers = Dict.empty
|
|
1261
1016
|
}
|
|
1262
1017
|
|> ToJsPayload.PageProgress
|
|
1263
1018
|
|> Effect.SendSinglePageNew byteEncodedPageData
|
|
@@ -1275,3 +1030,66 @@ urlToRoute config url =
|
|
|
1275
1030
|
|
|
1276
1031
|
else
|
|
1277
1032
|
config.urlToRoute url
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
toRedirectResponse :
|
|
1036
|
+
ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
|
|
1037
|
+
-> { b | path : UrlPath }
|
|
1038
|
+
-> RenderRequest.IncludeHtml
|
|
1039
|
+
-> { c | headers : List ( String, String ), statusCode : Int }
|
|
1040
|
+
-> { response | statusCode : Int, headers : List ( String, String ) }
|
|
1041
|
+
-> Maybe Effect
|
|
1042
|
+
toRedirectResponse config serverRequestPayload includeHtml serverResponse responseMetadata =
|
|
1043
|
+
PageServerResponse.toRedirect responseMetadata
|
|
1044
|
+
|> Maybe.map
|
|
1045
|
+
(\_ ->
|
|
1046
|
+
let
|
|
1047
|
+
( _, byteEncodedPageData ) =
|
|
1048
|
+
( serverResponse.headers
|
|
1049
|
+
, PageServerResponse.toRedirect serverResponse
|
|
1050
|
+
|> Maybe.map
|
|
1051
|
+
(\{ location } ->
|
|
1052
|
+
location
|
|
1053
|
+
|> ResponseSketch.Redirect
|
|
1054
|
+
|> config.encodeResponse
|
|
1055
|
+
)
|
|
1056
|
+
|> Maybe.withDefault (Bytes.Encode.unsignedInt8 0)
|
|
1057
|
+
|> Bytes.Encode.encode
|
|
1058
|
+
)
|
|
1059
|
+
in
|
|
1060
|
+
{ route = serverRequestPayload.path |> UrlPath.toRelative
|
|
1061
|
+
, contentJson = Dict.empty
|
|
1062
|
+
, html = "This is intentionally blank HTML"
|
|
1063
|
+
, errors = []
|
|
1064
|
+
, head = []
|
|
1065
|
+
, title = "This is an intentionally blank title"
|
|
1066
|
+
, staticHttpCache = Dict.empty
|
|
1067
|
+
, is404 = False
|
|
1068
|
+
, statusCode =
|
|
1069
|
+
case includeHtml of
|
|
1070
|
+
RenderRequest.OnlyJson ->
|
|
1071
|
+
-- if this is a redirect for a `content.dat`, we don't want to send an *actual* redirect status code because the redirect needs to be handled in Elm (not by the Browser)
|
|
1072
|
+
200
|
|
1073
|
+
|
|
1074
|
+
RenderRequest.HtmlAndJson ->
|
|
1075
|
+
responseMetadata.statusCode
|
|
1076
|
+
, headers = responseMetadata.headers |> combineHeaders
|
|
1077
|
+
}
|
|
1078
|
+
|> ToJsPayload.PageProgress
|
|
1079
|
+
|> Effect.SendSinglePageNew byteEncodedPageData
|
|
1080
|
+
)
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
combineHeaders : List ( String, String ) -> Dict String (List String)
|
|
1084
|
+
combineHeaders headers =
|
|
1085
|
+
headers
|
|
1086
|
+
|> List.foldl
|
|
1087
|
+
(\( key, value ) dict ->
|
|
1088
|
+
Dict.update key
|
|
1089
|
+
(Maybe.map ((::) value)
|
|
1090
|
+
>> Maybe.withDefault [ value ]
|
|
1091
|
+
>> Just
|
|
1092
|
+
)
|
|
1093
|
+
dict
|
|
1094
|
+
)
|
|
1095
|
+
Dict.empty
|