elm-pages 3.0.0-beta.2 → 3.0.0-beta.20

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