elm-pages 3.0.0-beta.3 → 3.0.0-beta.31

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 (129) hide show
  1. package/README.md +10 -1
  2. package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2864 -2589
  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 +1447 -342
  11. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +16458 -13724
  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 +4 -4
  14. package/generator/dead-code-review/elm.json +9 -7
  15. package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +59 -10
  16. package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +52 -36
  17. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
  18. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
  19. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
  20. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
  21. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  22. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  23. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  24. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
  25. package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1447 -342
  26. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +24542 -21748
  27. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  28. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
  29. package/generator/review/elm.json +10 -10
  30. package/generator/src/RouteBuilder.elm +113 -107
  31. package/generator/src/SharedTemplate.elm +3 -2
  32. package/generator/src/SiteConfig.elm +3 -2
  33. package/generator/src/basepath-middleware.js +3 -3
  34. package/generator/src/build.js +125 -88
  35. package/generator/src/cli.js +273 -88
  36. package/generator/src/codegen.js +29 -27
  37. package/generator/src/compatibility-key.js +3 -0
  38. package/generator/src/compile-elm.js +43 -26
  39. package/generator/src/config.js +39 -0
  40. package/generator/src/copy-dir.js +2 -2
  41. package/generator/src/dev-server.js +150 -133
  42. package/generator/src/dir-helpers.js +9 -26
  43. package/generator/src/elm-codegen.js +5 -4
  44. package/generator/src/elm-file-constants.js +2 -3
  45. package/generator/src/error-formatter.js +12 -11
  46. package/generator/src/file-helpers.js +3 -4
  47. package/generator/src/generate-template-module-connector.js +23 -22
  48. package/generator/src/init.js +9 -8
  49. package/generator/src/pre-render-html.js +39 -28
  50. package/generator/src/render-test.js +109 -0
  51. package/generator/src/render-worker.js +25 -28
  52. package/generator/src/render.js +320 -142
  53. package/generator/src/request-cache.js +252 -163
  54. package/generator/src/resolve-elm-module.js +63 -0
  55. package/generator/src/rewrite-client-elm-json.js +6 -5
  56. package/generator/src/rewrite-elm-json-help.js +56 -0
  57. package/generator/src/rewrite-elm-json.js +17 -7
  58. package/generator/src/route-codegen-helpers.js +16 -31
  59. package/generator/src/seo-renderer.js +12 -7
  60. package/generator/src/vite-utils.js +77 -0
  61. package/generator/static-code/hmr.js +79 -13
  62. package/generator/template/app/Api.elm +6 -5
  63. package/generator/template/app/Effect.elm +123 -0
  64. package/generator/template/app/ErrorPage.elm +37 -6
  65. package/generator/template/app/Route/Index.elm +17 -10
  66. package/generator/template/app/Shared.elm +24 -47
  67. package/generator/template/app/Site.elm +19 -6
  68. package/generator/template/app/View.elm +1 -8
  69. package/generator/template/elm-tooling.json +0 -3
  70. package/generator/template/elm.json +32 -24
  71. package/generator/template/package.json +10 -4
  72. package/package.json +29 -27
  73. package/src/ApiRoute.elm +199 -61
  74. package/src/BackendTask/Custom.elm +325 -0
  75. package/src/BackendTask/Env.elm +90 -0
  76. package/src/{DataSource → BackendTask}/File.elm +128 -43
  77. package/src/{DataSource → BackendTask}/Glob.elm +136 -125
  78. package/src/BackendTask/Http.elm +673 -0
  79. package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
  80. package/src/BackendTask/Internal/Request.elm +28 -0
  81. package/src/BackendTask/Random.elm +79 -0
  82. package/src/BackendTask/Time.elm +47 -0
  83. package/src/BackendTask.elm +537 -0
  84. package/src/FatalError.elm +89 -0
  85. package/src/Form/Field.elm +21 -9
  86. package/src/Form/FieldView.elm +94 -14
  87. package/src/Form.elm +275 -400
  88. package/src/Head.elm +237 -7
  89. package/src/HtmlPrinter.elm +7 -3
  90. package/src/Internal/ApiRoute.elm +7 -5
  91. package/src/PageServerResponse.elm +6 -1
  92. package/src/Pages/FormState.elm +6 -5
  93. package/src/Pages/GeneratorProgramConfig.elm +15 -0
  94. package/src/Pages/Internal/FatalError.elm +5 -0
  95. package/src/Pages/Internal/Form.elm +21 -1
  96. package/src/Pages/{Msg.elm → Internal/Msg.elm} +26 -16
  97. package/src/Pages/Internal/Platform/Cli.elm +598 -763
  98. package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
  99. package/src/Pages/Internal/Platform/Effect.elm +1 -2
  100. package/src/Pages/Internal/Platform/GeneratorApplication.elm +373 -0
  101. package/src/Pages/Internal/Platform/StaticResponses.elm +73 -270
  102. package/src/Pages/Internal/Platform/ToJsPayload.elm +4 -7
  103. package/src/Pages/Internal/Platform.elm +216 -102
  104. package/src/Pages/Internal/Script.elm +17 -0
  105. package/src/Pages/Internal/StaticHttpBody.elm +35 -1
  106. package/src/Pages/Manifest.elm +29 -4
  107. package/src/Pages/PageUrl.elm +23 -9
  108. package/src/Pages/ProgramConfig.elm +14 -10
  109. package/src/Pages/Script.elm +109 -0
  110. package/src/Pages/SiteConfig.elm +3 -2
  111. package/src/Pages/StaticHttp/Request.elm +2 -2
  112. package/src/Pages/StaticHttpRequest.elm +23 -98
  113. package/src/PagesMsg.elm +92 -0
  114. package/src/Path.elm +16 -19
  115. package/src/QueryParams.elm +21 -172
  116. package/src/RequestsAndPending.elm +8 -19
  117. package/src/Result/Extra.elm +26 -0
  118. package/src/Scaffold/Form.elm +560 -0
  119. package/src/Scaffold/Route.elm +1388 -0
  120. package/src/Server/Request.elm +43 -37
  121. package/src/Server/Session.elm +62 -42
  122. package/src/Server/SetCookie.elm +12 -4
  123. package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
  124. package/src/DataSource/Env.elm +0 -38
  125. package/src/DataSource/Http.elm +0 -446
  126. package/src/DataSource/Internal/Request.elm +0 -20
  127. package/src/DataSource/Port.elm +0 -90
  128. package/src/DataSource.elm +0 -538
  129. package/src/Pages/Generate.elm +0 -800
@@ -31,13 +31,14 @@ import Pages.ContentCache as ContentCache
31
31
  import Pages.Fetcher
32
32
  import Pages.Flags
33
33
  import Pages.FormState
34
+ import Pages.Internal.Msg
34
35
  import Pages.Internal.NotFoundReason exposing (NotFoundReason)
35
36
  import Pages.Internal.ResponseSketch as ResponseSketch exposing (ResponseSketch)
36
37
  import Pages.Internal.String as String
37
- import Pages.Msg
38
38
  import Pages.ProgramConfig exposing (ProgramConfig)
39
39
  import Pages.StaticHttpRequest as StaticHttpRequest
40
40
  import Pages.Transition
41
+ import PagesMsg exposing (PagesMsg)
41
42
  import Path exposing (Path)
42
43
  import QueryParams
43
44
  import Task
@@ -45,11 +46,6 @@ import Time
45
46
  import Url exposing (Url)
46
47
 
47
48
 
48
- type Transition
49
- = Loading Int Path
50
- | Submitting FormData
51
-
52
-
53
49
  {-| -}
54
50
  type alias Program userModel userMsg pageData actionData sharedData errorPage =
55
51
  Platform.Program Flags (Model userModel pageData actionData sharedData) (Msg userMsg pageData actionData sharedData errorPage)
@@ -58,7 +54,7 @@ type alias Program userModel userMsg pageData actionData sharedData errorPage =
58
54
  mainView :
59
55
  ProgramConfig userMsg userModel route pageData actionData sharedData effect (Msg userMsg pageData actionData sharedData errorPage) errorPage
60
56
  -> Model userModel pageData actionData sharedData
61
- -> { title : String, body : List (Html (Pages.Msg.Msg userMsg)) }
57
+ -> { title : String, body : List (Html (PagesMsg userMsg)) }
62
58
  mainView config model =
63
59
  case model.notFound of
64
60
  Just info ->
@@ -230,7 +226,7 @@ init config flags url key =
230
226
  , host = url.host
231
227
  , port_ = url.port_
232
228
  , path = pagePath
233
- , query = url.query |> Maybe.map QueryParams.fromString
229
+ , query = url.query |> Maybe.map QueryParams.fromString |> Maybe.withDefault Dict.empty
234
230
  , fragment = url.fragment
235
231
  }
236
232
  }
@@ -274,7 +270,7 @@ init config flags url key =
274
270
  , url = url
275
271
  , currentPath = url.path
276
272
  , pageData = Err "Not found"
277
- , ariaNavigationAnnouncement = "Error" -- TODO use error page title for announcement?
273
+ , ariaNavigationAnnouncement = "Page Not Found" -- TODO use error page title for announcement?
278
274
  , userFlags = flags
279
275
  , notFound = Just info
280
276
  , transition = Nothing
@@ -313,16 +309,22 @@ init config flags url key =
313
309
  type Msg userMsg pageData actionData sharedData errorPage
314
310
  = LinkClicked Browser.UrlRequest
315
311
  | UrlChanged Url
316
- | UserMsg (Pages.Msg.Msg userMsg)
312
+ -- TODO rename to PagesMsg
313
+ | UserMsg (PagesMsg userMsg)
317
314
  | SetField { formId : String, name : String, value : String }
318
315
  | UpdateCacheAndUrlNew Bool Url (Maybe userMsg) (Result Http.Error ( Url, ResponseSketch pageData actionData sharedData ))
319
- | FetcherComplete Bool String Int (Result Http.Error ( Maybe userMsg, Maybe actionData ))
316
+ | FetcherComplete Bool String Int (Result Http.Error ( Maybe userMsg, ActionDataOrRedirect actionData ))
320
317
  | FetcherStarted String Int FormData Time.Posix
321
318
  | PageScrollComplete
322
319
  | HotReloadCompleteNew Bytes
323
320
  | ProcessFetchResponse Int (Result Http.Error ( Url, ResponseSketch pageData actionData sharedData )) (Result Http.Error ( Url, ResponseSketch pageData actionData sharedData ) -> Msg userMsg pageData actionData sharedData errorPage)
324
321
 
325
322
 
323
+ type ActionDataOrRedirect action
324
+ = ActionResponse (Maybe action)
325
+ | RedirectResponse String
326
+
327
+
326
328
  {-| -}
327
329
  type alias Model userModel pageData actionData sharedData =
328
330
  { key : Maybe Browser.Navigation.Key
@@ -414,7 +416,7 @@ update config appMsg model =
414
416
  model
415
417
 
416
418
  Nothing ->
417
- if model.url.path == url.path then
419
+ if model.url.path == url.path && model.url.query == url.query then
418
420
  ( { model
419
421
  | -- update the URL in case query params or fragment changed
420
422
  url = url
@@ -423,46 +425,57 @@ update config appMsg model =
423
425
  )
424
426
 
425
427
  else
426
- ( { model
427
- | url = url
428
- }
428
+ ( model
429
429
  , NoEffect
430
430
  )
431
431
  -- TODO is it reasonable to always re-fetch route data if you re-navigate to the current route? Might be a good
432
432
  -- parallel to the browser behavior
433
433
  |> startNewGetLoad url (UpdateCacheAndUrlNew True url Nothing)
434
434
 
435
- FetcherComplete forPageReload fetcherKey transitionId___ userMsgResult ->
435
+ FetcherComplete _ fetcherKey _ userMsgResult ->
436
436
  case userMsgResult of
437
- Ok ( userMsg, maybeFetcherDoneActionData ) ->
438
- ( { model
439
- | inFlightFetchers =
440
- model.inFlightFetchers
441
- |> Dict.update fetcherKey
442
- (Maybe.map
443
- (\( transitionId, fetcherState ) ->
444
- ( transitionId
445
- , { fetcherState
446
- | status =
447
- maybeFetcherDoneActionData
448
- |> Maybe.map Pages.Transition.FetcherReloading
449
- -- TODO remove this bad default, FetcherSubmitting is incorrect
450
- |> Maybe.withDefault Pages.Transition.FetcherSubmitting
451
- }
437
+ Ok ( userMsg, actionOrRedirect ) ->
438
+ case actionOrRedirect of
439
+ ActionResponse maybeFetcherDoneActionData ->
440
+ ( { model
441
+ | inFlightFetchers =
442
+ model.inFlightFetchers
443
+ |> Dict.update fetcherKey
444
+ (Maybe.map
445
+ (\( transitionId, fetcherState ) ->
446
+ ( transitionId
447
+ , { fetcherState
448
+ | status =
449
+ maybeFetcherDoneActionData
450
+ |> Maybe.map Pages.Transition.FetcherReloading
451
+ -- TODO remove this bad default, FetcherSubmitting is incorrect
452
+ |> Maybe.withDefault Pages.Transition.FetcherSubmitting
453
+ }
454
+ )
455
+ )
452
456
  )
453
- )
454
- )
455
- }
456
- , NoEffect
457
- )
458
- |> (case userMsg of
459
- Just justUserMsg ->
460
- performUserMsg justUserMsg config
461
-
462
- Nothing ->
463
- identity
464
- )
465
- |> startNewGetLoad (currentUrlWithPath model.url.path model) (UpdateCacheAndUrlNew False model.url Nothing)
457
+ }
458
+ , NoEffect
459
+ )
460
+ |> (case userMsg of
461
+ Just justUserMsg ->
462
+ performUserMsg justUserMsg config
463
+
464
+ Nothing ->
465
+ identity
466
+ )
467
+ |> startNewGetLoad (currentUrlWithPath model.url.path model) (UpdateCacheAndUrlNew False model.url Nothing)
468
+
469
+ RedirectResponse redirectTo ->
470
+ ( { model
471
+ | inFlightFetchers =
472
+ model.inFlightFetchers
473
+ |> Dict.remove fetcherKey
474
+ , pendingRedirect = True
475
+ }
476
+ , NoEffect
477
+ )
478
+ |> startNewGetLoad (currentUrlWithPath redirectTo model) (UpdateCacheAndUrlNew False model.url Nothing)
466
479
 
467
480
  Err _ ->
468
481
  -- TODO how to handle error?
@@ -480,11 +493,11 @@ update config appMsg model =
480
493
 
481
494
  UserMsg userMsg_ ->
482
495
  case userMsg_ of
483
- Pages.Msg.UserMsg userMsg ->
496
+ Pages.Internal.Msg.UserMsg userMsg ->
484
497
  ( model, NoEffect )
485
498
  |> performUserMsg userMsg config
486
499
 
487
- Pages.Msg.Submit fields ->
500
+ Pages.Internal.Msg.Submit fields ->
488
501
  ( { model
489
502
  | transition =
490
503
  Just
@@ -496,7 +509,7 @@ update config appMsg model =
496
509
  , Submit fields
497
510
  )
498
511
 
499
- Pages.Msg.SubmitIfValid formId fields isValid ->
512
+ Pages.Internal.Msg.SubmitIfValid formId fields isValid maybeUserMsg ->
500
513
  if isValid then
501
514
  ( { model
502
515
  -- TODO should I setSubmitAttempted here, too?
@@ -509,6 +522,13 @@ update config appMsg model =
509
522
  }
510
523
  , Submit fields
511
524
  )
525
+ |> (case maybeUserMsg of
526
+ Just justUserMsg ->
527
+ performUserMsg justUserMsg config
528
+
529
+ Nothing ->
530
+ identity
531
+ )
512
532
 
513
533
  else
514
534
  ( { model
@@ -519,7 +539,7 @@ update config appMsg model =
519
539
  , NoEffect
520
540
  )
521
541
 
522
- Pages.Msg.SubmitFetcher fetcherKey fields isValid maybeUserMsg ->
542
+ Pages.Internal.Msg.SubmitFetcher fetcherKey fields isValid maybeUserMsg ->
523
543
  if isValid then
524
544
  -- TODO should I setSubmitAttempted here, too?
525
545
  ( { model | nextTransitionKey = model.nextTransitionKey + 1 }
@@ -542,12 +562,15 @@ update config appMsg model =
542
562
  , NoEffect
543
563
  )
544
564
 
545
- Pages.Msg.FormFieldEvent value ->
565
+ Pages.Internal.Msg.FormFieldEvent value ->
546
566
  -- TODO when init is called for a new page, also need to clear out client-side `pageFormState`
547
567
  ( { model | pageFormState = Pages.FormState.update value model.pageFormState }
548
568
  , NoEffect
549
569
  )
550
570
 
571
+ Pages.Internal.Msg.NoOp ->
572
+ ( model, NoEffect )
573
+
551
574
  UpdateCacheAndUrlNew scrollToTopWhenDone urlWithoutRedirectResolution maybeUserMsg updateResult ->
552
575
  -- TODO remove all fetchers that are in the state `FetcherReloading` here -- I think that's the right logic?
553
576
  case
@@ -605,27 +628,32 @@ update config appMsg model =
605
628
  , actionData = newActionData
606
629
  }
607
630
 
608
- ( userModel, _ ) =
631
+ ( userModel, userEffect ) =
609
632
  -- TODO if urlWithoutRedirectResolution is different from the url with redirect resolution, then
610
633
  -- instead of calling update, call pushUrl (I think?)
611
634
  -- TODO include user Cmd
612
- config.update model.pageFormState
613
- (model.inFlightFetchers |> toFetcherState)
614
- (model.transition |> Maybe.map Tuple.second)
615
- newSharedData
616
- newPageData
617
- model.key
618
- (config.onPageChange
619
- { protocol = model.url.protocol
620
- , host = model.url.host
621
- , port_ = model.url.port_
622
- , path = urlPathToPath urlWithoutRedirectResolution
623
- , query = urlWithoutRedirectResolution.query
624
- , fragment = urlWithoutRedirectResolution.fragment
625
- , metadata = config.urlToRoute urlWithoutRedirectResolution
626
- }
627
- )
628
- previousPageData.userModel
635
+ if stayingOnSamePath then
636
+ ( previousPageData.userModel, NoEffect )
637
+
638
+ else
639
+ config.update model.pageFormState
640
+ (model.inFlightFetchers |> toFetcherState)
641
+ (model.transition |> Maybe.map Tuple.second)
642
+ newSharedData
643
+ newPageData
644
+ model.key
645
+ (config.onPageChange
646
+ { protocol = model.url.protocol
647
+ , host = model.url.host
648
+ , port_ = model.url.port_
649
+ , path = urlPathToPath urlWithoutRedirectResolution
650
+ , query = urlWithoutRedirectResolution.query
651
+ , fragment = urlWithoutRedirectResolution.fragment
652
+ , metadata = config.urlToRoute urlWithoutRedirectResolution
653
+ }
654
+ )
655
+ previousPageData.userModel
656
+ |> Tuple.mapSecond UserCmd
629
657
 
630
658
  updatedModel : Model userModel pageData actionData sharedData
631
659
  updatedModel =
@@ -656,10 +684,13 @@ update config appMsg model =
656
684
  , currentPath = newUrl.path
657
685
  }
658
686
  , if not stayingOnSamePath && scrollToTopWhenDone then
659
- ScrollToTop
687
+ Batch
688
+ [ ScrollToTop
689
+ , userEffect
690
+ ]
660
691
 
661
692
  else
662
- NoEffect
693
+ userEffect
663
694
  )
664
695
  |> (case maybeUserMsg of
665
696
  Just userMsg ->
@@ -679,10 +710,10 @@ update config appMsg model =
679
710
  Err _ ->
680
711
  {-
681
712
  When there is an error loading the content.dat, we are either
682
- 1) in the dev server, and should show the relevant DataSource error for the page
713
+ 1) in the dev server, and should show the relevant BackendTask error for the page
683
714
  we're navigating to. This could be done more cleanly, but it's simplest to just
684
715
  do a fresh page load and use the code path for presenting an error for a fresh page.
685
- 2) In a production app. That means we had a successful build, so there were no DataSource failures,
716
+ 2) In a production app. That means we had a successful build, so there were no BackendTask failures,
686
717
  so the app must be stale (unless it's in some unexpected state from a bug). In the future,
687
718
  it probably makes sense to include some sort of hash of the app version we are fetching, match
688
719
  it with the current version that's running, and perform this logic when we see there is a mismatch.
@@ -745,7 +776,86 @@ update config appMsg model =
745
776
  _ ->
746
777
  ( model, NoEffect )
747
778
  )
748
- |> Result.withDefault ( model, NoEffect )
779
+ |> Result.withDefault
780
+ (let
781
+ pageDataResult : Maybe (InitKind sharedData pageData actionData errorPage)
782
+ pageDataResult =
783
+ case Bytes.Decode.decode config.decodeResponse pageDataBytes of
784
+ Just (ResponseSketch.RenderPage _ _) ->
785
+ Nothing
786
+
787
+ Just (ResponseSketch.HotUpdate pageData shared actionData) ->
788
+ OkPage shared pageData actionData
789
+ |> Just
790
+
791
+ Just (ResponseSketch.NotFound notFound) ->
792
+ NotFound notFound
793
+ |> Just
794
+
795
+ _ ->
796
+ Nothing
797
+ in
798
+ case pageDataResult of
799
+ Just (OkPage sharedData pageData actionData) ->
800
+ let
801
+ urls : { currentUrl : Url, basePath : List String }
802
+ urls =
803
+ { currentUrl = model.url
804
+ , basePath = config.basePath
805
+ }
806
+
807
+ pagePath : Path
808
+ pagePath =
809
+ urlsToPagePath urls
810
+
811
+ userFlags : Pages.Flags.Flags
812
+ userFlags =
813
+ model.userFlags
814
+ |> Decode.decodeValue
815
+ (Decode.field "userFlags" Decode.value)
816
+ |> Result.withDefault Json.Encode.null
817
+ |> Pages.Flags.BrowserFlags
818
+
819
+ ( userModel, userCmd ) =
820
+ Just
821
+ { path =
822
+ { path = pagePath
823
+ , query = model.url.query
824
+ , fragment = model.url.fragment
825
+ }
826
+ , metadata = config.urlToRoute model.url
827
+ , pageUrl =
828
+ Just
829
+ { protocol = model.url.protocol
830
+ , host = model.url.host
831
+ , port_ = model.url.port_
832
+ , path = pagePath
833
+ , query = model.url.query |> Maybe.map QueryParams.fromString |> Maybe.withDefault Dict.empty
834
+ , fragment = model.url.fragment
835
+ }
836
+ }
837
+ |> config.init userFlags sharedData pageData actionData
838
+
839
+ cmd : Effect userMsg pageData actionData sharedData userEffect errorPage
840
+ cmd =
841
+ UserCmd userCmd
842
+ in
843
+ ( { model
844
+ | pageData =
845
+ Ok
846
+ { userModel = userModel
847
+ , sharedData = sharedData
848
+ , pageData = pageData
849
+ , actionData = actionData
850
+ }
851
+ , notFound = Nothing
852
+ }
853
+ , cmd
854
+ )
855
+
856
+ _ ->
857
+ ( model, NoEffect )
858
+ )
749
859
 
750
860
  FetcherStarted fetcherKey transitionId fetcherData initiatedAt ->
751
861
  ( { model
@@ -766,7 +876,7 @@ update config appMsg model =
766
876
  toFetcherState : Dict String ( Int, Pages.Transition.FetcherState actionData ) -> Dict String (Pages.Transition.FetcherState actionData)
767
877
  toFetcherState inFlightFetchers =
768
878
  inFlightFetchers
769
- |> Dict.map (\_ ( index, fetcherState ) -> fetcherState)
879
+ |> Dict.map (\_ ( _, fetcherState ) -> fetcherState)
770
880
 
771
881
 
772
882
  performUserMsg :
@@ -828,7 +938,7 @@ perform config model effect =
828
938
  |> Maybe.withDefault Cmd.none
829
939
 
830
940
  FetchPageData transitionKey maybeRequestInfo url toMsg ->
831
- fetchRouteData True transitionKey toMsg config url maybeRequestInfo
941
+ fetchRouteData transitionKey toMsg config url maybeRequestInfo
832
942
 
833
943
  Submit fields ->
834
944
  if fields.method == Get then
@@ -843,7 +953,7 @@ perform config model effect =
843
953
  -- TODO add optional path parameter to Submit variant to allow submitting to other routes
844
954
  model.url
845
955
  in
846
- fetchRouteData False -1 (UpdateCacheAndUrlNew False model.url Nothing) config urlToSubmitTo (Just fields)
956
+ fetchRouteData -1 (UpdateCacheAndUrlNew False model.url Nothing) config urlToSubmitTo (Just fields)
847
957
 
848
958
  SubmitFetcher fetcherKey transitionId formData ->
849
959
  startFetcher2 config False fetcherKey transitionId formData model
@@ -863,7 +973,7 @@ perform config model effect =
863
973
  |> config.perform
864
974
  { fetchRouteData =
865
975
  \fetchInfo ->
866
- fetchRouteData False
976
+ fetchRouteData
867
977
  -1
868
978
  (prepare fetchInfo.toMsg)
869
979
  config
@@ -873,13 +983,13 @@ perform config model effect =
873
983
  ---- TODO map the Msg with the wrapper type (like in the PR branch)
874
984
  , submit =
875
985
  \fetchInfo ->
876
- fetchRouteData False -1 (prepare fetchInfo.toMsg) config (fetchInfo.values.action |> Url.fromString |> Maybe.withDefault model.url) (Just fetchInfo.values)
986
+ fetchRouteData -1 (prepare fetchInfo.toMsg) config (fetchInfo.values.action |> Url.fromString |> Maybe.withDefault model.url) (Just fetchInfo.values)
877
987
  , runFetcher =
878
988
  \(Pages.Fetcher.Fetcher options) ->
879
989
  -- TODO need to get the fetcherId here
880
990
  -- TODO need to increment and pass in the transitionId
881
991
  startFetcher "TODO" -1 options model
882
- , fromPageMsg = Pages.Msg.UserMsg >> UserMsg
992
+ , fromPageMsg = Pages.Internal.Msg.UserMsg >> UserMsg
883
993
  , key = key
884
994
  , setField = \info -> Task.succeed (SetField info) |> Task.perform identity
885
995
  }
@@ -927,10 +1037,10 @@ startFetcher fetcherKey transitionId options model =
927
1037
  Http.expectBytesResponse (FetcherComplete False fetcherKey model.nextTransitionKey)
928
1038
  (\bytes ->
929
1039
  case bytes of
930
- Http.GoodStatus_ metadata bytesBody ->
1040
+ Http.GoodStatus_ _ bytesBody ->
931
1041
  ( options.decoder (Ok bytesBody)
932
1042
  |> Just
933
- , Nothing
1043
+ , ActionResponse Nothing
934
1044
  )
935
1045
  |> Ok
936
1046
 
@@ -943,7 +1053,7 @@ startFetcher fetcherKey transitionId options model =
943
1053
  Http.NetworkError_ ->
944
1054
  Err <| Http.NetworkError
945
1055
 
946
- Http.BadStatus_ metadata body ->
1056
+ Http.BadStatus_ metadata _ ->
947
1057
  Err <| Http.BadStatus metadata.statusCode
948
1058
  )
949
1059
  , tracker = Nothing
@@ -974,7 +1084,7 @@ startFetcher2 config fromPageReload fetcherKey transitionId formData model =
974
1084
  Cmd.batch
975
1085
  [ cancelStaleFetchers model
976
1086
  , case Dict.get fetcherKey model.inFlightFetchers of
977
- Just ( inFlightId, inFlightFetcher ) ->
1087
+ Just ( inFlightId, _ ) ->
978
1088
  Http.cancel (String.fromInt inFlightId)
979
1089
 
980
1090
  Nothing ->
@@ -985,22 +1095,26 @@ startFetcher2 config fromPageReload fetcherKey transitionId formData model =
985
1095
  Http.expectBytesResponse (FetcherComplete fromPageReload fetcherKey model.nextTransitionKey)
986
1096
  (\bytes ->
987
1097
  case bytes of
988
- Http.GoodStatus_ metadata bytesBody ->
1098
+ Http.GoodStatus_ _ bytesBody ->
989
1099
  let
990
- decodedAction : Maybe actionData
1100
+ decodedAction : ActionDataOrRedirect actionData
991
1101
  decodedAction =
992
1102
  case Bytes.Decode.decode config.decodeResponse bytesBody of
1103
+ -- @@@
1104
+ Just (ResponseSketch.Redirect redirectTo) ->
1105
+ RedirectResponse redirectTo
1106
+
993
1107
  Just (ResponseSketch.RenderPage _ maybeAction) ->
994
- maybeAction
1108
+ ActionResponse maybeAction
995
1109
 
996
- Just (ResponseSketch.HotUpdate pageData shared maybeAction) ->
997
- maybeAction
1110
+ Just (ResponseSketch.HotUpdate _ _ maybeAction) ->
1111
+ ActionResponse maybeAction
998
1112
 
999
- Just (ResponseSketch.NotFound notFound) ->
1000
- Nothing
1113
+ Just (ResponseSketch.NotFound _) ->
1114
+ ActionResponse Nothing
1001
1115
 
1002
1116
  _ ->
1003
- Nothing
1117
+ ActionResponse Nothing
1004
1118
  in
1005
1119
  -- TODO maybe have an optional way to pass the bytes through?
1006
1120
  Ok ( Nothing, decodedAction )
@@ -1014,7 +1128,7 @@ startFetcher2 config fromPageReload fetcherKey transitionId formData model =
1014
1128
  Http.NetworkError_ ->
1015
1129
  Err <| Http.NetworkError
1016
1130
 
1017
- Http.BadStatus_ metadata body ->
1131
+ Http.BadStatus_ metadata _ ->
1018
1132
  Err <| Http.BadStatus metadata.statusCode
1019
1133
  )
1020
1134
  , tracker = Just (String.fromInt transitionId)
@@ -1036,7 +1150,7 @@ cancelStaleFetchers model =
1036
1150
  model.inFlightFetchers
1037
1151
  |> Dict.toList
1038
1152
  |> List.filterMap
1039
- (\( fetcherKey, ( id, fetcher ) ) ->
1153
+ (\( _, ( id, fetcher ) ) ->
1040
1154
  case fetcher.status of
1041
1155
  Pages.Transition.FetcherReloading _ ->
1042
1156
  Http.cancel (String.fromInt id)
@@ -1104,7 +1218,7 @@ application config =
1104
1218
  [ config.subscriptions (model.url |> config.urlToRoute)
1105
1219
  (urls.currentUrl |> config.urlToRoute |> config.routeToPath |> Path.join)
1106
1220
  pageData.userModel
1107
- |> Sub.map (Pages.Msg.UserMsg >> UserMsg)
1221
+ |> Sub.map (Pages.Internal.Msg.UserMsg >> UserMsg)
1108
1222
  , config.hotReloadData
1109
1223
  |> Sub.map HotReloadCompleteNew
1110
1224
  ]
@@ -1157,14 +1271,13 @@ urlPathToPath urls =
1157
1271
 
1158
1272
 
1159
1273
  fetchRouteData :
1160
- Bool
1161
- -> Int
1274
+ Int
1162
1275
  -> (Result Http.Error ( Url, ResponseSketch pageData actionData sharedData ) -> Msg userMsg pageData actionData sharedData errorPage)
1163
1276
  -> ProgramConfig userMsg userModel route pageData actionData sharedData effect (Msg userMsg pageData actionData sharedData errorPage) errorPage
1164
1277
  -> Url
1165
1278
  -> Maybe FormData
1166
1279
  -> Cmd (Msg userMsg pageData actionData sharedData errorPage)
1167
- fetchRouteData forPageDataReload transitionKey toMsg config url details =
1280
+ fetchRouteData transitionKey toMsg config url details =
1168
1281
  {-
1169
1282
  TODO:
1170
1283
  - [X] `toMsg` needs a parameter for the callback Msg so it can pass it on if there is a Redirect response
@@ -1251,7 +1364,7 @@ fetchRouteData forPageDataReload transitionKey toMsg config url details =
1251
1364
  Http.NetworkError_ ->
1252
1365
  Err Http.NetworkError
1253
1366
 
1254
- Http.BadStatus_ metadata body ->
1367
+ Http.BadStatus_ _ body ->
1255
1368
  body
1256
1369
  |> Bytes.Decode.decode config.decodeResponse
1257
1370
  |> Result.fromMaybe "Decoding error"
@@ -1303,7 +1416,7 @@ startNewGetLoad urlToGet toMsg ( model, effect ) =
1303
1416
  cancelIfStale : Effect userMsg pageData actionData sharedData userEffect errorPage
1304
1417
  cancelIfStale =
1305
1418
  case model.transition of
1306
- Just ( transitionKey, Pages.Transition.Loading path loadingKind ) ->
1419
+ Just ( transitionKey, Pages.Transition.Loading _ _ ) ->
1307
1420
  CancelRequest transitionKey
1308
1421
 
1309
1422
  _ ->
@@ -1314,13 +1427,13 @@ startNewGetLoad urlToGet toMsg ( model, effect ) =
1314
1427
  , transition =
1315
1428
  ( model.nextTransitionKey
1316
1429
  , case model.transition of
1317
- Just ( transitionKey, Pages.Transition.LoadAfterSubmit submitData _ _ ) ->
1430
+ Just ( _, Pages.Transition.LoadAfterSubmit submitData _ _ ) ->
1318
1431
  Pages.Transition.LoadAfterSubmit
1319
1432
  submitData
1320
1433
  (urlToGet.path |> Path.fromString)
1321
1434
  Pages.Transition.Load
1322
1435
 
1323
- Just ( transitionKey, Pages.Transition.Submitting submitData ) ->
1436
+ Just ( _, Pages.Transition.Submitting submitData ) ->
1324
1437
  Pages.Transition.LoadAfterSubmit
1325
1438
  submitData
1326
1439
  (urlToGet.path |> Path.fromString)
@@ -1392,6 +1505,7 @@ loadDataAndUpdateUrl ( newPageData, newSharedData, newActionData ) maybeUserMsg
1392
1505
  , actionData = newActionData
1393
1506
  }
1394
1507
 
1508
+ -- TODO use userEffect here?
1395
1509
  ( userModel, _ ) =
1396
1510
  -- TODO if urlWithoutRedirectResolution is different from the url with redirect resolution, then
1397
1511
  -- instead of calling update, call pushUrl (I think?)
@@ -1467,10 +1581,10 @@ loadDataAndUpdateUrl ( newPageData, newSharedData, newActionData ) maybeUserMsg
1467
1581
  Err _ ->
1468
1582
  {-
1469
1583
  When there is an error loading the content.dat, we are either
1470
- 1) in the dev server, and should show the relevant DataSource error for the page
1584
+ 1) in the dev server, and should show the relevant BackendTask error for the page
1471
1585
  we're navigating to. This could be done more cleanly, but it's simplest to just
1472
1586
  do a fresh page load and use the code path for presenting an error for a fresh page.
1473
- 2) In a production app. That means we had a successful build, so there were no DataSource failures,
1587
+ 2) In a production app. That means we had a successful build, so there were no BackendTask failures,
1474
1588
  so the app must be stale (unless it's in some unexpected state from a bug). In the future,
1475
1589
  it probably makes sense to include some sort of hash of the app version we are fetching, match
1476
1590
  it with the current version that's running, and perform this logic when we see there is a mismatch.
@@ -0,0 +1,17 @@
1
+ module Pages.Internal.Script exposing (Script(..))
2
+
3
+ import BackendTask exposing (BackendTask)
4
+ import Cli.Program as Program
5
+ import FatalError exposing (FatalError)
6
+ import Html exposing (Html)
7
+
8
+
9
+ {-| -}
10
+ type Script
11
+ = Script
12
+ ((Maybe { indent : Int, newLines : Bool }
13
+ -> Html Never
14
+ -> String
15
+ )
16
+ -> Program.Config (BackendTask FatalError ())
17
+ )