elm-pages 2.1.6 → 2.1.10

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 (75) hide show
  1. package/generator/review/elm.json +34 -0
  2. package/generator/review/src/ReviewConfig.elm +10 -0
  3. package/generator/src/basepath-middleware.js +15 -9
  4. package/generator/src/build.js +100 -6
  5. package/generator/src/cli.js +13 -9
  6. package/generator/src/compile-elm.js +43 -0
  7. package/generator/src/dev-server.js +63 -11
  8. package/generator/src/error-formatter.js +62 -9
  9. package/generator/src/generate-template-module-connector.js +17 -4
  10. package/generator/src/init.js +4 -0
  11. package/generator/src/pre-render-html.js +19 -12
  12. package/generator/src/render-worker.js +0 -1
  13. package/generator/src/render.js +1 -2
  14. package/generator/src/seo-renderer.js +21 -2
  15. package/generator/static-code/hmr.js +43 -6
  16. package/generator/template/elm-tooling.json +9 -0
  17. package/generator/template/package.json +5 -1
  18. package/package.json +16 -9
  19. package/src/ApiRoute.elm +178 -0
  20. package/src/AriaLiveAnnouncer.elm +36 -0
  21. package/src/BuildError.elm +60 -0
  22. package/src/DataSource/File.elm +288 -0
  23. package/src/DataSource/Glob.elm +1050 -0
  24. package/src/DataSource/Http.elm +467 -0
  25. package/src/DataSource/Internal/Glob.elm +74 -0
  26. package/src/DataSource/Port.elm +87 -0
  27. package/src/DataSource/ServerRequest.elm +60 -0
  28. package/src/DataSource.elm +801 -0
  29. package/src/Head/Seo.elm +516 -0
  30. package/src/Head/Twitter.elm +109 -0
  31. package/src/Head.elm +452 -0
  32. package/src/HtmlPrinter.elm +27 -0
  33. package/src/Internal/ApiRoute.elm +89 -0
  34. package/src/Internal/OptimizedDecoder.elm +18 -0
  35. package/src/KeepOrDiscard.elm +6 -0
  36. package/src/OptimizedDecoder/Pipeline.elm +335 -0
  37. package/src/OptimizedDecoder.elm +818 -0
  38. package/src/Pages/ContentCache.elm +248 -0
  39. package/src/Pages/Flags.elm +26 -0
  40. package/src/Pages/Http.elm +10 -0
  41. package/src/Pages/Internal/ApplicationType.elm +6 -0
  42. package/src/Pages/Internal/NotFoundReason.elm +256 -0
  43. package/src/Pages/Internal/Platform/Cli.elm +1015 -0
  44. package/src/Pages/Internal/Platform/Effect.elm +14 -0
  45. package/src/Pages/Internal/Platform/StaticResponses.elm +540 -0
  46. package/src/Pages/Internal/Platform/ToJsPayload.elm +138 -0
  47. package/src/Pages/Internal/Platform.elm +745 -0
  48. package/src/Pages/Internal/RoutePattern.elm +122 -0
  49. package/src/Pages/Internal/Router.elm +116 -0
  50. package/src/Pages/Internal/StaticHttpBody.elm +54 -0
  51. package/src/Pages/Internal/String.elm +39 -0
  52. package/src/Pages/Manifest/Category.elm +240 -0
  53. package/src/Pages/Manifest.elm +412 -0
  54. package/src/Pages/PageUrl.elm +38 -0
  55. package/src/Pages/ProgramConfig.elm +73 -0
  56. package/src/Pages/Review/NoContractViolations.elm +397 -0
  57. package/src/Pages/Secrets.elm +83 -0
  58. package/src/Pages/SiteConfig.elm +13 -0
  59. package/src/Pages/StaticHttp/Request.elm +42 -0
  60. package/src/Pages/StaticHttpRequest.elm +320 -0
  61. package/src/Pages/Url.elm +60 -0
  62. package/src/Path.elm +96 -0
  63. package/src/QueryParams.elm +216 -0
  64. package/src/RenderRequest.elm +163 -0
  65. package/src/RequestsAndPending.elm +20 -0
  66. package/src/Secrets.elm +111 -0
  67. package/src/SecretsDict.elm +45 -0
  68. package/src/StructuredData.elm +236 -0
  69. package/src/TerminalText.elm +242 -0
  70. package/src/Test/Html/Internal/ElmHtml/Constants.elm +53 -0
  71. package/src/Test/Html/Internal/ElmHtml/Helpers.elm +17 -0
  72. package/src/Test/Html/Internal/ElmHtml/InternalTypes.elm +529 -0
  73. package/src/Test/Html/Internal/ElmHtml/Markdown.elm +56 -0
  74. package/src/Test/Html/Internal/ElmHtml/ToString.elm +197 -0
  75. package/src/Test/Internal/KernelConstants.elm +34 -0
@@ -0,0 +1,1015 @@
1
+ module Pages.Internal.Platform.Cli exposing (Flags, Model, Msg(..), Program, cliApplication, init, requestDecoder, update)
2
+
3
+ {-| Exposed for internal use only (used in generated code).
4
+
5
+ @docs Flags, Model, Msg, Program, cliApplication, init, requestDecoder, update
6
+
7
+ -}
8
+
9
+ import ApiRoute
10
+ import BuildError exposing (BuildError)
11
+ import Codec
12
+ import DataSource exposing (DataSource)
13
+ import DataSource.Http exposing (RequestDetails)
14
+ import Dict exposing (Dict)
15
+ import Dict.Extra
16
+ import Head
17
+ import Html exposing (Html)
18
+ import HtmlPrinter
19
+ import Http
20
+ import Internal.ApiRoute exposing (ApiRoute(..))
21
+ import Json.Decode as Decode
22
+ import Json.Encode
23
+ import Pages.ContentCache as ContentCache exposing (ContentCache)
24
+ import Pages.Flags
25
+ import Pages.Http
26
+ import Pages.Internal.ApplicationType as ApplicationType
27
+ import Pages.Internal.NotFoundReason exposing (NotFoundReason)
28
+ import Pages.Internal.Platform.Effect as Effect exposing (Effect)
29
+ import Pages.Internal.Platform.StaticResponses as StaticResponses exposing (StaticResponses)
30
+ import Pages.Internal.Platform.ToJsPayload as ToJsPayload
31
+ import Pages.Internal.StaticHttpBody as StaticHttpBody
32
+ import Pages.ProgramConfig exposing (ProgramConfig)
33
+ import Pages.SiteConfig exposing (SiteConfig)
34
+ import Pages.StaticHttp.Request
35
+ import Pages.StaticHttpRequest as StaticHttpRequest
36
+ import Path exposing (Path)
37
+ import RenderRequest exposing (RenderRequest)
38
+ import SecretsDict exposing (SecretsDict)
39
+ import Task
40
+ import TerminalText as Terminal
41
+ import Url
42
+
43
+
44
+ {-| -}
45
+ type alias Flags =
46
+ Decode.Value
47
+
48
+
49
+ {-| -}
50
+ type alias Model route =
51
+ { staticResponses : StaticResponses
52
+ , secrets : SecretsDict
53
+ , errors : List BuildError
54
+ , allRawResponses : Dict String (Maybe String)
55
+ , pendingRequests : List { masked : RequestDetails, unmasked : RequestDetails }
56
+ , unprocessedPages : List ( Path, route )
57
+ , staticRoutes : Maybe (List ( Path, route ))
58
+ , maybeRequestJson : RenderRequest route
59
+ , isDevServer : Bool
60
+ }
61
+
62
+
63
+ {-| -}
64
+ type Msg
65
+ = GotDataBatch
66
+ (List
67
+ { request : { masked : RequestDetails, unmasked : RequestDetails }
68
+ , response : String
69
+ }
70
+ )
71
+ | GotBuildError BuildError
72
+ | Continue
73
+
74
+
75
+ {-| -}
76
+ type alias Program route =
77
+ Platform.Program Flags (Model route) Msg
78
+
79
+
80
+ {-| -}
81
+ cliApplication :
82
+ ProgramConfig userMsg userModel (Maybe route) siteData pageData sharedData
83
+ -> Program (Maybe route)
84
+ cliApplication config =
85
+ let
86
+ contentCache : ContentCache
87
+ contentCache =
88
+ ContentCache.init Nothing
89
+
90
+ site : SiteConfig siteData
91
+ site =
92
+ getSiteConfig config
93
+
94
+ getSiteConfig : ProgramConfig userMsg userModel (Maybe route) siteData pageData sharedData -> SiteConfig siteData
95
+ getSiteConfig fullConfig =
96
+ case fullConfig.site of
97
+ Just mySite ->
98
+ mySite
99
+
100
+ Nothing ->
101
+ getSiteConfig fullConfig
102
+ in
103
+ Platform.worker
104
+ { init =
105
+ \flags ->
106
+ let
107
+ renderRequest : RenderRequest (Maybe route)
108
+ renderRequest =
109
+ Decode.decodeValue (RenderRequest.decoder config) flags
110
+ |> Result.withDefault RenderRequest.default
111
+ in
112
+ init site renderRequest contentCache config flags
113
+ |> Tuple.mapSecond (perform site renderRequest config config.toJsPort)
114
+ , update =
115
+ \msg model ->
116
+ update site contentCache config msg model
117
+ |> Tuple.mapSecond (perform site model.maybeRequestJson config config.toJsPort)
118
+ , subscriptions =
119
+ \_ ->
120
+ config.fromJsPort
121
+ |> Sub.map
122
+ (\jsonValue ->
123
+ let
124
+ decoder : Decode.Decoder Msg
125
+ decoder =
126
+ Decode.field "tag" Decode.string
127
+ |> Decode.andThen
128
+ (\tag ->
129
+ -- tag: "GotGlob"
130
+ -- tag: "GotFile"
131
+ case tag of
132
+ "BuildError" ->
133
+ Decode.field "data"
134
+ (Decode.map2
135
+ (\message title ->
136
+ { title = title
137
+ , message = message
138
+ , fatal = True
139
+ , path = "" -- TODO wire in current path here
140
+ }
141
+ )
142
+ (Decode.field "message" Decode.string |> Decode.map Terminal.fromAnsiString)
143
+ (Decode.field "title" Decode.string)
144
+ )
145
+ |> Decode.map GotBuildError
146
+
147
+ "GotBatch" ->
148
+ Decode.field "data"
149
+ (Decode.list
150
+ (Decode.map2
151
+ (\requests response ->
152
+ { request =
153
+ { masked = requests.masked
154
+ , unmasked = requests.unmasked
155
+ }
156
+ , response = response
157
+ }
158
+ )
159
+ (Decode.field "request" requestDecoder)
160
+ (Decode.field "response" Decode.string)
161
+ )
162
+ )
163
+ |> Decode.map GotDataBatch
164
+
165
+ _ ->
166
+ Decode.fail "Unhandled msg"
167
+ )
168
+ in
169
+ Decode.decodeValue decoder jsonValue
170
+ |> Result.mapError Decode.errorToString
171
+ |> Result.withDefault Continue
172
+ )
173
+ }
174
+
175
+
176
+ {-| -}
177
+ requestDecoder : Decode.Decoder { masked : Pages.StaticHttp.Request.Request, unmasked : Pages.StaticHttp.Request.Request }
178
+ requestDecoder =
179
+ (Codec.object (\masked unmasked -> { masked = masked, unmasked = unmasked })
180
+ |> Codec.field "masked" .masked Pages.StaticHttp.Request.codec
181
+ |> Codec.field "unmasked" .unmasked Pages.StaticHttp.Request.codec
182
+ |> Codec.buildObject
183
+ )
184
+ |> Codec.decoder
185
+
186
+
187
+ gotStaticFileDecoder : Decode.Decoder ( String, Decode.Value )
188
+ gotStaticFileDecoder =
189
+ Decode.field "data"
190
+ (Decode.map2 Tuple.pair
191
+ (Decode.field "filePath" Decode.string)
192
+ Decode.value
193
+ )
194
+
195
+
196
+ gotPortDecoder : Decode.Decoder ( String, Decode.Value )
197
+ gotPortDecoder =
198
+ Decode.field "data"
199
+ (Decode.map2 Tuple.pair
200
+ (Decode.field "portName" Decode.string)
201
+ (Decode.field "portResponse" Decode.value)
202
+ )
203
+
204
+
205
+ perform :
206
+ SiteConfig siteData
207
+ -> RenderRequest route
208
+ -> ProgramConfig userMsg userModel route siteData pageData sharedData
209
+ -> (Codec.Value -> Cmd Never)
210
+ -> Effect
211
+ -> Cmd Msg
212
+ perform site renderRequest config toJsPort effect =
213
+ -- elm-review: known-unoptimized-recursion
214
+ let
215
+ canonicalSiteUrl : String
216
+ canonicalSiteUrl =
217
+ site.canonicalUrl
218
+ in
219
+ case effect of
220
+ Effect.NoEffect ->
221
+ Cmd.none
222
+
223
+ Effect.Batch list ->
224
+ list
225
+ |> List.map (perform site renderRequest config toJsPort)
226
+ |> Cmd.batch
227
+
228
+ Effect.FetchHttp ({ unmasked, masked } as requests) ->
229
+ if unmasked.url == "$$elm-pages$$headers" then
230
+ case
231
+ renderRequest
232
+ |> RenderRequest.maybeRequestPayload
233
+ |> Maybe.map (Json.Encode.encode 0)
234
+ |> Result.fromMaybe (Pages.Http.BadUrl "$$elm-pages$$headers is only available on server-side request (not on build).")
235
+ of
236
+ Ok okResponse ->
237
+ Task.succeed
238
+ [ { request = requests
239
+ , response = okResponse
240
+ }
241
+ ]
242
+ |> Task.perform GotDataBatch
243
+
244
+ Err error ->
245
+ { title = "Static HTTP Error"
246
+ , message =
247
+ [ Terminal.text "I got an error making an HTTP request to this URL: "
248
+
249
+ -- TODO include HTTP method, headers, and body
250
+ , Terminal.yellow requests.masked.url
251
+ , Terminal.text <| Json.Encode.encode 2 <| StaticHttpBody.encode requests.masked.body
252
+ , Terminal.text "\n\n"
253
+ , case error of
254
+ Pages.Http.BadStatus metadata body ->
255
+ Terminal.text <|
256
+ String.join "\n"
257
+ [ "Bad status: " ++ String.fromInt metadata.statusCode
258
+ , "Status message: " ++ metadata.statusText
259
+ , "Body: " ++ body
260
+ ]
261
+
262
+ Pages.Http.BadUrl _ ->
263
+ -- TODO include HTTP method, headers, and body
264
+ Terminal.text <| "Invalid url: " ++ requests.masked.url
265
+
266
+ Pages.Http.Timeout ->
267
+ Terminal.text "Timeout"
268
+
269
+ Pages.Http.NetworkError ->
270
+ Terminal.text "Network error"
271
+ ]
272
+ , fatal = True
273
+ , path = "" -- TODO wire in current path here
274
+ }
275
+ |> Task.succeed
276
+ |> Task.perform GotBuildError
277
+
278
+ else if unmasked.url |> String.startsWith "file://" then
279
+ let
280
+ filePath : String
281
+ filePath =
282
+ String.dropLeft 7 unmasked.url
283
+ in
284
+ ToJsPayload.ReadFile filePath
285
+ |> Codec.encoder (ToJsPayload.successCodecNew2 canonicalSiteUrl "")
286
+ |> toJsPort
287
+ |> Cmd.map never
288
+
289
+ else if unmasked.url |> String.startsWith "glob://" then
290
+ let
291
+ globPattern : String
292
+ globPattern =
293
+ String.dropLeft 7 unmasked.url
294
+ in
295
+ ToJsPayload.Glob globPattern
296
+ |> Codec.encoder (ToJsPayload.successCodecNew2 canonicalSiteUrl "")
297
+ |> toJsPort
298
+ |> Cmd.map never
299
+
300
+ else
301
+ ToJsPayload.DoHttp { masked = masked, unmasked = unmasked }
302
+ |> Codec.encoder (ToJsPayload.successCodecNew2 canonicalSiteUrl "")
303
+ |> toJsPort
304
+ |> Cmd.map never
305
+
306
+ Effect.SendSinglePage done info ->
307
+ let
308
+ currentPagePath : String
309
+ currentPagePath =
310
+ case info of
311
+ ToJsPayload.PageProgress toJsSuccessPayloadNew ->
312
+ toJsSuccessPayloadNew.route
313
+
314
+ _ ->
315
+ ""
316
+ in
317
+ Cmd.batch
318
+ [ info
319
+ |> Codec.encoder (ToJsPayload.successCodecNew2 canonicalSiteUrl currentPagePath)
320
+ |> toJsPort
321
+ |> Cmd.map never
322
+ , if done then
323
+ Cmd.none
324
+
325
+ else
326
+ Task.succeed ()
327
+ |> Task.perform (\_ -> Continue)
328
+ ]
329
+
330
+ Effect.Continue ->
331
+ Cmd.none
332
+
333
+ Effect.ReadFile filePath ->
334
+ ToJsPayload.ReadFile filePath
335
+ |> Codec.encoder (ToJsPayload.successCodecNew2 canonicalSiteUrl "")
336
+ |> toJsPort
337
+ |> Cmd.map never
338
+
339
+ Effect.GetGlob globPattern ->
340
+ ToJsPayload.Glob globPattern
341
+ |> Codec.encoder (ToJsPayload.successCodecNew2 canonicalSiteUrl "")
342
+ |> toJsPort
343
+ |> Cmd.map never
344
+
345
+
346
+ flagsDecoder :
347
+ Decode.Decoder
348
+ { secrets : SecretsDict
349
+ , staticHttpCache : Dict String (Maybe String)
350
+ , isDevServer : Bool
351
+ }
352
+ flagsDecoder =
353
+ Decode.map3
354
+ (\secrets staticHttpCache isDevServer ->
355
+ { secrets = secrets
356
+ , staticHttpCache = staticHttpCache
357
+ , isDevServer = isDevServer
358
+ }
359
+ )
360
+ (Decode.field "secrets" SecretsDict.decoder)
361
+ (Decode.field "staticHttpCache"
362
+ (Decode.dict
363
+ (Decode.string
364
+ |> Decode.map Just
365
+ )
366
+ )
367
+ )
368
+ (Decode.field "mode" Decode.string |> Decode.map (\mode -> mode == "dev-server"))
369
+
370
+
371
+ {-| -}
372
+ init :
373
+ SiteConfig siteData
374
+ -> RenderRequest route
375
+ -> ContentCache
376
+ -> ProgramConfig userMsg userModel route siteData pageData sharedData
377
+ -> Decode.Value
378
+ -> ( Model route, Effect )
379
+ init site renderRequest contentCache config flags =
380
+ case Decode.decodeValue flagsDecoder flags of
381
+ Ok { secrets, staticHttpCache, isDevServer } ->
382
+ initLegacy site renderRequest { secrets = secrets, staticHttpCache = staticHttpCache, isDevServer = isDevServer } contentCache config flags
383
+
384
+ Err error ->
385
+ updateAndSendPortIfDone
386
+ site
387
+ contentCache
388
+ config
389
+ { staticResponses = StaticResponses.error
390
+ , secrets = SecretsDict.masked
391
+ , errors =
392
+ [ { title = "Internal Error"
393
+ , message = [ Terminal.text <| "Failed to parse flags: " ++ Decode.errorToString error ]
394
+ , fatal = True
395
+ , path = ""
396
+ }
397
+ ]
398
+ , allRawResponses = Dict.empty
399
+ , pendingRequests = []
400
+ , unprocessedPages = []
401
+ , staticRoutes = Just []
402
+ , maybeRequestJson = renderRequest
403
+ , isDevServer = False
404
+ }
405
+
406
+
407
+ initLegacy :
408
+ SiteConfig siteData
409
+ -> RenderRequest route
410
+ -> { secrets : SecretsDict, staticHttpCache : Dict String (Maybe String), isDevServer : Bool }
411
+ -> ContentCache
412
+ -> ProgramConfig userMsg userModel route siteData pageData sharedData
413
+ -> Decode.Value
414
+ -> ( Model route, Effect )
415
+ initLegacy site renderRequest { secrets, staticHttpCache, isDevServer } contentCache config flags =
416
+ let
417
+ staticResponses : StaticResponses
418
+ staticResponses =
419
+ case renderRequest of
420
+ RenderRequest.SinglePage _ singleRequest _ ->
421
+ case singleRequest of
422
+ RenderRequest.Page serverRequestPayload ->
423
+ StaticResponses.renderSingleRoute config
424
+ serverRequestPayload
425
+ (DataSource.map2 (\_ _ -> ())
426
+ (config.data serverRequestPayload.frontmatter)
427
+ config.sharedData
428
+ )
429
+ (if isDevServer then
430
+ config.handleRoute serverRequestPayload.frontmatter
431
+
432
+ else
433
+ DataSource.succeed Nothing
434
+ )
435
+
436
+ RenderRequest.Api ( path, ApiRoute apiRequest ) ->
437
+ StaticResponses.renderApiRequest
438
+ (apiRequest.matchesToResponse path)
439
+
440
+ RenderRequest.NotFound path ->
441
+ StaticResponses.renderApiRequest
442
+ (DataSource.succeed [])
443
+
444
+ unprocessedPages : List ( Path, route )
445
+ unprocessedPages =
446
+ case renderRequest of
447
+ RenderRequest.SinglePage _ serverRequestPayload _ ->
448
+ case serverRequestPayload of
449
+ RenderRequest.Page pageData ->
450
+ [ ( pageData.path, pageData.frontmatter ) ]
451
+
452
+ RenderRequest.Api _ ->
453
+ []
454
+
455
+ RenderRequest.NotFound path ->
456
+ []
457
+
458
+ unprocessedPagesState : Maybe (List ( Path, route ))
459
+ unprocessedPagesState =
460
+ case renderRequest of
461
+ RenderRequest.SinglePage _ serverRequestPayload _ ->
462
+ case serverRequestPayload of
463
+ RenderRequest.Page pageData ->
464
+ Just [ ( pageData.path, pageData.frontmatter ) ]
465
+
466
+ RenderRequest.Api _ ->
467
+ Nothing
468
+
469
+ RenderRequest.NotFound path ->
470
+ Just []
471
+
472
+ initialModel : Model route
473
+ initialModel =
474
+ { staticResponses = staticResponses
475
+ , secrets = secrets
476
+ , errors = []
477
+ , allRawResponses = staticHttpCache
478
+ , pendingRequests = []
479
+ , unprocessedPages = unprocessedPages
480
+ , staticRoutes = unprocessedPagesState
481
+ , maybeRequestJson = renderRequest
482
+ , isDevServer = isDevServer
483
+ }
484
+ in
485
+ StaticResponses.nextStep config initialModel Nothing
486
+ |> nextStepToEffect site
487
+ contentCache
488
+ config
489
+ initialModel
490
+
491
+
492
+ updateAndSendPortIfDone :
493
+ SiteConfig siteData
494
+ -> ContentCache
495
+ -> ProgramConfig userMsg userModel route siteData pageData sharedData
496
+ -> Model route
497
+ -> ( Model route, Effect )
498
+ updateAndSendPortIfDone site contentCache config model =
499
+ StaticResponses.nextStep
500
+ config
501
+ model
502
+ Nothing
503
+ |> nextStepToEffect site contentCache config model
504
+
505
+
506
+ {-| -}
507
+ update :
508
+ SiteConfig siteData
509
+ -> ContentCache
510
+ -> ProgramConfig userMsg userModel route siteData pageData sharedData
511
+ -> Msg
512
+ -> Model route
513
+ -> ( Model route, Effect )
514
+ update site contentCache config msg model =
515
+ case msg of
516
+ GotDataBatch batch ->
517
+ let
518
+ updatedModel : Model route
519
+ updatedModel =
520
+ (case batch of
521
+ [ single ] ->
522
+ { model
523
+ | pendingRequests =
524
+ model.pendingRequests
525
+ |> List.filter
526
+ (\pending ->
527
+ pending /= single.request
528
+ )
529
+ }
530
+
531
+ _ ->
532
+ { model
533
+ | pendingRequests = [] -- TODO is it safe to clear it entirely?
534
+ }
535
+ )
536
+ |> StaticResponses.batchUpdate batch
537
+ in
538
+ StaticResponses.nextStep config
539
+ updatedModel
540
+ Nothing
541
+ |> nextStepToEffect site contentCache config updatedModel
542
+
543
+ Continue ->
544
+ let
545
+ updatedModel : Model route
546
+ updatedModel =
547
+ model
548
+ in
549
+ StaticResponses.nextStep config
550
+ updatedModel
551
+ Nothing
552
+ |> nextStepToEffect site contentCache config updatedModel
553
+
554
+ GotBuildError buildError ->
555
+ let
556
+ updatedModel : Model route
557
+ updatedModel =
558
+ { model
559
+ | errors =
560
+ buildError :: model.errors
561
+ }
562
+ in
563
+ StaticResponses.nextStep config
564
+ updatedModel
565
+ Nothing
566
+ |> nextStepToEffect site contentCache config updatedModel
567
+
568
+
569
+ nextStepToEffect :
570
+ SiteConfig siteData
571
+ -> ContentCache
572
+ -> ProgramConfig userMsg userModel route siteData pageData sharedData
573
+ -> Model route
574
+ -> ( StaticResponses, StaticResponses.NextStep route )
575
+ -> ( Model route, Effect )
576
+ nextStepToEffect site contentCache config model ( updatedStaticResponsesModel, nextStep ) =
577
+ case nextStep of
578
+ StaticResponses.Continue updatedAllRawResponses httpRequests maybeRoutes ->
579
+ let
580
+ nextAndPending : List { masked : RequestDetails, unmasked : RequestDetails }
581
+ nextAndPending =
582
+ model.pendingRequests ++ httpRequests
583
+
584
+ doNow : List { masked : RequestDetails, unmasked : RequestDetails }
585
+ doNow =
586
+ nextAndPending
587
+
588
+ pending : List { masked : RequestDetails, unmasked : RequestDetails }
589
+ pending =
590
+ []
591
+
592
+ updatedRoutes : Maybe (List ( Path, route ))
593
+ updatedRoutes =
594
+ case maybeRoutes of
595
+ Just newRoutes ->
596
+ newRoutes
597
+ |> List.map
598
+ (\route ->
599
+ ( Path.join (config.routeToPath route)
600
+ , route
601
+ )
602
+ )
603
+ |> Just
604
+
605
+ Nothing ->
606
+ model.staticRoutes
607
+
608
+ updatedUnprocessedPages : List ( Path, route )
609
+ updatedUnprocessedPages =
610
+ case maybeRoutes of
611
+ Just newRoutes ->
612
+ newRoutes
613
+ |> List.map
614
+ (\route ->
615
+ ( Path.join (config.routeToPath route)
616
+ , route
617
+ )
618
+ )
619
+
620
+ Nothing ->
621
+ model.unprocessedPages
622
+
623
+ updatedModel : Model route
624
+ updatedModel =
625
+ { model
626
+ | allRawResponses = updatedAllRawResponses
627
+ , pendingRequests = pending
628
+ , staticResponses = updatedStaticResponsesModel
629
+ , staticRoutes = updatedRoutes
630
+ , unprocessedPages = updatedUnprocessedPages
631
+ }
632
+ in
633
+ if List.isEmpty doNow && updatedRoutes /= model.staticRoutes then
634
+ nextStepToEffect site
635
+ contentCache
636
+ config
637
+ updatedModel
638
+ (StaticResponses.nextStep config
639
+ updatedModel
640
+ Nothing
641
+ )
642
+
643
+ else
644
+ ( updatedModel
645
+ , (doNow
646
+ |> List.map Effect.FetchHttp
647
+ )
648
+ |> Effect.Batch
649
+ )
650
+
651
+ StaticResponses.Finish toJsPayload ->
652
+ case toJsPayload of
653
+ StaticResponses.ApiResponse ->
654
+ let
655
+ apiResponse : Effect
656
+ apiResponse =
657
+ case model.maybeRequestJson of
658
+ RenderRequest.SinglePage includeHtml requestPayload value ->
659
+ case requestPayload of
660
+ RenderRequest.Api ( path, ApiRoute apiHandler ) ->
661
+ let
662
+ thing : DataSource (Maybe ApiRoute.Response)
663
+ thing =
664
+ apiHandler.matchesToResponse path
665
+ in
666
+ StaticHttpRequest.resolve ApplicationType.Cli
667
+ thing
668
+ model.allRawResponses
669
+ |> Result.mapError (StaticHttpRequest.toBuildError "TODO - path from request")
670
+ |> (\response ->
671
+ case response of
672
+ Ok (Just okResponse) ->
673
+ { body = okResponse.body
674
+ , staticHttpCache = model.allRawResponses |> Dict.Extra.filterMap (\_ v -> v)
675
+ , statusCode = 200
676
+ }
677
+ |> ToJsPayload.SendApiResponse
678
+ |> Effect.SendSinglePage True
679
+
680
+ Ok Nothing ->
681
+ { body = "Hello1!"
682
+ , staticHttpCache = model.allRawResponses |> Dict.Extra.filterMap (\_ v -> v)
683
+ , statusCode = 404
684
+ }
685
+ |> ToJsPayload.SendApiResponse
686
+ |> Effect.SendSinglePage True
687
+
688
+ Err error ->
689
+ [ error ]
690
+ |> ToJsPayload.Errors
691
+ |> Effect.SendSinglePage True
692
+ )
693
+
694
+ RenderRequest.Page payload ->
695
+ let
696
+ pageFoundResult : Result BuildError (Maybe NotFoundReason)
697
+ pageFoundResult =
698
+ StaticHttpRequest.resolve ApplicationType.Browser
699
+ (if model.isDevServer then
700
+ config.handleRoute payload.frontmatter
701
+
702
+ else
703
+ DataSource.succeed Nothing
704
+ )
705
+ model.allRawResponses
706
+ |> Result.mapError (StaticHttpRequest.toBuildError (payload.path |> Path.toAbsolute))
707
+ in
708
+ case pageFoundResult of
709
+ Ok Nothing ->
710
+ let
711
+ currentUrl : Url.Url
712
+ currentUrl =
713
+ { protocol = Url.Https
714
+ , host = site.canonicalUrl
715
+ , port_ = Nothing
716
+ , path = payload.path |> Path.toRelative
717
+ , query = Nothing
718
+ , fragment = Nothing
719
+ }
720
+
721
+ renderedResult : Result BuildError { head : List Head.Tag, view : String, title : String }
722
+ renderedResult =
723
+ case includeHtml of
724
+ RenderRequest.OnlyJson ->
725
+ Ok
726
+ { head = []
727
+ , view = "This page was not rendered because it is a JSON-only request."
728
+ , title = "This page was not rendered because it is a JSON-only request."
729
+ }
730
+
731
+ RenderRequest.HtmlAndJson ->
732
+ Result.map2 Tuple.pair pageDataResult sharedDataResult
733
+ |> Result.map
734
+ (\( pageData, sharedData ) ->
735
+ let
736
+ pageModel : userModel
737
+ pageModel =
738
+ config.init
739
+ Pages.Flags.PreRenderFlags
740
+ sharedData
741
+ pageData
742
+ Nothing
743
+ (Just
744
+ { path =
745
+ { path = currentPage.path
746
+ , query = Nothing
747
+ , fragment = Nothing
748
+ }
749
+ , metadata = currentPage.route
750
+ , pageUrl = Nothing
751
+ }
752
+ )
753
+ |> Tuple.first
754
+
755
+ viewValue : { title : String, body : Html userMsg }
756
+ viewValue =
757
+ (config.view currentPage Nothing sharedData pageData |> .view) pageModel
758
+ in
759
+ { head = config.view currentPage Nothing sharedData pageData |> .head
760
+ , view = viewValue.body |> HtmlPrinter.htmlToString
761
+ , title = viewValue.title
762
+ }
763
+ )
764
+
765
+ staticData : Dict String String
766
+ staticData =
767
+ --toJsPayload.pages
768
+ -- |> Dict.get (Path.toRelative page)
769
+ -- |> Maybe.withDefault Dict.empty
770
+ Dict.empty
771
+
772
+ currentPage : { path : Path, route : route }
773
+ currentPage =
774
+ { path = payload.path, route = config.urlToRoute currentUrl }
775
+
776
+ pageDataResult : Result BuildError pageData
777
+ pageDataResult =
778
+ StaticHttpRequest.resolve ApplicationType.Browser
779
+ (config.data (config.urlToRoute currentUrl))
780
+ (staticData |> Dict.map (\_ v -> Just v))
781
+ |> Result.mapError (StaticHttpRequest.toBuildError currentUrl.path)
782
+
783
+ sharedDataResult : Result BuildError sharedData
784
+ sharedDataResult =
785
+ StaticHttpRequest.resolve ApplicationType.Browser
786
+ config.sharedData
787
+ (staticData |> Dict.map (\_ v -> Just v))
788
+ |> Result.mapError (StaticHttpRequest.toBuildError currentUrl.path)
789
+
790
+ siteDataResult : Result BuildError siteData
791
+ siteDataResult =
792
+ StaticHttpRequest.resolve ApplicationType.Cli
793
+ site.data
794
+ (staticData |> Dict.map (\_ v -> Just v))
795
+ |> Result.mapError (StaticHttpRequest.toBuildError "Site.elm")
796
+ in
797
+ case Result.map3 (\a b c -> ( a, b, c )) pageFoundResult renderedResult siteDataResult of
798
+ Ok ( pageFound, rendered, siteData ) ->
799
+ { route = payload.path |> Path.toRelative
800
+ , contentJson =
801
+ --toJsPayload.pages
802
+ -- |> Dict.get (Path.toRelative page)
803
+ -- |> Maybe.withDefault Dict.empty
804
+ Dict.empty
805
+ , html = rendered.view
806
+ , errors = []
807
+ , head = rendered.head
808
+ , title = rendered.title
809
+ , staticHttpCache = model.allRawResponses |> Dict.Extra.filterMap (\_ v -> v)
810
+ , is404 = False
811
+ }
812
+ |> ToJsPayload.PageProgress
813
+ |> Effect.SendSinglePage False
814
+
815
+ Err error ->
816
+ [ error ] |> ToJsPayload.Errors |> Effect.SendSinglePage True
817
+
818
+ Ok (Just notFoundReason) ->
819
+ render404Page config model payload.path notFoundReason
820
+
821
+ Err error ->
822
+ [ error ] |> ToJsPayload.Errors |> Effect.SendSinglePage True
823
+
824
+ RenderRequest.NotFound path ->
825
+ render404Page config model path Pages.Internal.NotFoundReason.NoMatchingRoute
826
+ in
827
+ ( { model | staticRoutes = Just [] }
828
+ , apiResponse
829
+ )
830
+
831
+ StaticResponses.Page contentJson ->
832
+ case model.unprocessedPages |> List.head of
833
+ Just pageAndMetadata ->
834
+ ( model
835
+ , sendSinglePageProgress site contentJson config model pageAndMetadata
836
+ )
837
+
838
+ Nothing ->
839
+ ( model
840
+ , [] |> ToJsPayload.Errors |> Effect.SendSinglePage True
841
+ )
842
+
843
+ StaticResponses.Errors errors ->
844
+ ( model
845
+ , errors |> ToJsPayload.Errors |> Effect.SendSinglePage True
846
+ )
847
+
848
+
849
+ sendSinglePageProgress :
850
+ SiteConfig siteData
851
+ -> Dict String String
852
+ -> ProgramConfig userMsg userModel route siteData pageData sharedData
853
+ -> Model route
854
+ -> ( Path, route )
855
+ -> Effect
856
+ sendSinglePageProgress site contentJson config model =
857
+ \( page, route ) ->
858
+ case model.maybeRequestJson of
859
+ RenderRequest.SinglePage includeHtml _ _ ->
860
+ let
861
+ pageFoundResult : Result BuildError (Maybe NotFoundReason)
862
+ pageFoundResult =
863
+ StaticHttpRequest.resolve ApplicationType.Browser
864
+ (if model.isDevServer then
865
+ config.handleRoute route
866
+
867
+ else
868
+ DataSource.succeed Nothing
869
+ )
870
+ model.allRawResponses
871
+ |> Result.mapError (StaticHttpRequest.toBuildError currentUrl.path)
872
+
873
+ renderedResult : Result BuildError { head : List Head.Tag, view : String, title : String }
874
+ renderedResult =
875
+ case includeHtml of
876
+ RenderRequest.OnlyJson ->
877
+ Ok
878
+ { head = []
879
+ , view = "This page was not rendered because it is a JSON-only request."
880
+ , title = "This page was not rendered because it is a JSON-only request."
881
+ }
882
+
883
+ RenderRequest.HtmlAndJson ->
884
+ Result.map2 Tuple.pair pageDataResult sharedDataResult
885
+ |> Result.map
886
+ (\( pageData, sharedData ) ->
887
+ let
888
+ pageModel : userModel
889
+ pageModel =
890
+ config.init
891
+ Pages.Flags.PreRenderFlags
892
+ sharedData
893
+ pageData
894
+ Nothing
895
+ (Just
896
+ { path =
897
+ { path = currentPage.path
898
+ , query = Nothing
899
+ , fragment = Nothing
900
+ }
901
+ , metadata = currentPage.route
902
+ , pageUrl = Nothing
903
+ }
904
+ )
905
+ |> Tuple.first
906
+
907
+ viewValue : { title : String, body : Html userMsg }
908
+ viewValue =
909
+ (config.view currentPage Nothing sharedData pageData |> .view) pageModel
910
+ in
911
+ { head = config.view currentPage Nothing sharedData pageData |> .head
912
+ , view = viewValue.body |> HtmlPrinter.htmlToString
913
+ , title = viewValue.title
914
+ }
915
+ )
916
+
917
+ currentUrl : Url.Url
918
+ currentUrl =
919
+ { protocol = Url.Https
920
+ , host = site.canonicalUrl
921
+ , port_ = Nothing
922
+ , path = page |> Path.toRelative
923
+ , query = Nothing
924
+ , fragment = Nothing
925
+ }
926
+
927
+ currentPage : { path : Path, route : route }
928
+ currentPage =
929
+ { path = page, route = config.urlToRoute currentUrl }
930
+
931
+ pageDataResult : Result BuildError pageData
932
+ pageDataResult =
933
+ StaticHttpRequest.resolve ApplicationType.Browser
934
+ (config.data (config.urlToRoute currentUrl))
935
+ (contentJson |> Dict.map (\_ v -> Just v))
936
+ |> Result.mapError (StaticHttpRequest.toBuildError currentUrl.path)
937
+
938
+ sharedDataResult : Result BuildError sharedData
939
+ sharedDataResult =
940
+ StaticHttpRequest.resolve ApplicationType.Browser
941
+ config.sharedData
942
+ (contentJson |> Dict.map (\_ v -> Just v))
943
+ |> Result.mapError (StaticHttpRequest.toBuildError currentUrl.path)
944
+
945
+ siteDataResult : Result BuildError siteData
946
+ siteDataResult =
947
+ StaticHttpRequest.resolve ApplicationType.Cli
948
+ site.data
949
+ (contentJson |> Dict.map (\_ v -> Just v))
950
+ |> Result.mapError (StaticHttpRequest.toBuildError "Site.elm")
951
+ in
952
+ case Result.map3 (\a b c -> ( a, b, c )) pageFoundResult renderedResult siteDataResult of
953
+ Ok ( maybeNotFoundReason, rendered, siteData ) ->
954
+ case maybeNotFoundReason of
955
+ Nothing ->
956
+ { route = page |> Path.toRelative
957
+ , contentJson = contentJson
958
+ , html = rendered.view
959
+ , errors = []
960
+ , head = rendered.head ++ site.head siteData
961
+ , title = rendered.title
962
+ , staticHttpCache = model.allRawResponses |> Dict.Extra.filterMap (\_ v -> v)
963
+ , is404 = False
964
+ }
965
+ |> ToJsPayload.PageProgress
966
+ |> Effect.SendSinglePage True
967
+
968
+ Just notFoundReason ->
969
+ render404Page config model page notFoundReason
970
+
971
+ Err error ->
972
+ [ error ]
973
+ |> ToJsPayload.Errors
974
+ |> Effect.SendSinglePage True
975
+
976
+
977
+ render404Page :
978
+ ProgramConfig userMsg userModel route siteData pageData sharedData
979
+ -> Model route
980
+ -> Path
981
+ -> NotFoundReason
982
+ -> Effect
983
+ render404Page config model path notFoundReason =
984
+ let
985
+ notFoundDocument : { title : String, body : Html msg }
986
+ notFoundDocument =
987
+ { path = path
988
+ , reason = notFoundReason
989
+ }
990
+ |> Pages.Internal.NotFoundReason.document config.pathPatterns
991
+ in
992
+ { route = Path.toAbsolute path
993
+ , contentJson =
994
+ Dict.fromList
995
+ [ ( "notFoundReason"
996
+ , Json.Encode.encode 0
997
+ (Codec.encoder Pages.Internal.NotFoundReason.codec
998
+ { path = path
999
+ , reason = notFoundReason
1000
+ }
1001
+ )
1002
+ )
1003
+ , ( "path", Path.toAbsolute path )
1004
+ ]
1005
+
1006
+ -- TODO include the needed info for content.json?
1007
+ , html = HtmlPrinter.htmlToString notFoundDocument.body
1008
+ , errors = []
1009
+ , head = []
1010
+ , title = notFoundDocument.title
1011
+ , staticHttpCache = model.allRawResponses |> Dict.Extra.filterMap (\_ v -> v)
1012
+ , is404 = True
1013
+ }
1014
+ |> ToJsPayload.PageProgress
1015
+ |> Effect.SendSinglePage True