elm-pages 2.1.11 → 3.0.0-beta.1

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 (161) hide show
  1. package/codegen/elm-pages-codegen.js +38507 -0
  2. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
  3. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
  4. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmi +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/Reporter.elmi +0 -0
  7. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
  8. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
  9. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
  10. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  11. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  12. package/generator/{template/public/style.css → dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock} +0 -0
  13. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  14. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -0
  15. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +6795 -0
  16. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25651 -0
  17. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +110 -0
  18. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +187 -0
  19. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/package.json +1 -0
  20. package/generator/dead-code-review/elm-stuff/tests-0.19.1/src/Reporter.elm +26 -0
  21. package/generator/dead-code-review/elm-stuff/tests-0.19.1/src/Runner.elm +62 -0
  22. package/generator/dead-code-review/elm.json +35 -0
  23. package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +181 -0
  24. package/generator/dead-code-review/src/ReviewConfig.elm +9 -0
  25. package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +455 -0
  26. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
  27. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
  28. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
  29. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
  30. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmi +0 -0
  31. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmo +0 -0
  32. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmi +0 -0
  33. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
  34. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
  35. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
  36. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  37. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  38. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock +0 -0
  39. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  40. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -0
  41. package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +6795 -0
  42. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +27617 -0
  43. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +110 -0
  44. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +187 -0
  45. package/generator/review/elm-stuff/tests-0.19.1/js/package.json +1 -0
  46. package/generator/review/elm-stuff/tests-0.19.1/src/Reporter.elm +26 -0
  47. package/generator/review/elm-stuff/tests-0.19.1/src/Runner.elm +62 -0
  48. package/generator/review/elm.json +13 -4
  49. package/{src → generator/review/src}/Pages/Review/NoContractViolations.elm +148 -148
  50. package/generator/review/tests/Pages/Review/NoContractViolationsTest.elm +331 -0
  51. package/generator/src/RouteBuilder.elm +420 -0
  52. package/generator/src/SharedTemplate.elm +4 -5
  53. package/generator/src/SiteConfig.elm +3 -9
  54. package/generator/src/build.js +308 -95
  55. package/generator/src/cli.js +103 -8
  56. package/generator/src/codegen.js +192 -35
  57. package/generator/src/compile-elm.js +183 -31
  58. package/generator/src/dev-server.js +353 -96
  59. package/generator/src/elm-application.json +3 -1
  60. package/generator/src/elm-codegen.js +34 -0
  61. package/generator/src/elm-file-constants.js +2 -0
  62. package/generator/src/error-formatter.js +20 -1
  63. package/generator/src/generate-template-module-connector.js +125 -927
  64. package/generator/src/hello.ts +5 -0
  65. package/generator/src/pre-render-html.js +58 -104
  66. package/generator/src/render-worker.js +27 -13
  67. package/generator/src/render.js +252 -197
  68. package/generator/src/request-cache-fs.js +18 -0
  69. package/generator/src/request-cache.js +128 -56
  70. package/generator/src/rewrite-client-elm-json.js +49 -0
  71. package/generator/src/route-codegen-helpers.js +62 -1
  72. package/generator/static-code/dev-style.css +22 -0
  73. package/generator/static-code/elm-pages.js +43 -39
  74. package/generator/static-code/hmr.js +98 -88
  75. package/generator/template/app/Api.elm +25 -0
  76. package/generator/template/app/ErrorPage.elm +38 -0
  77. package/generator/template/app/Route/Index.elm +87 -0
  78. package/generator/template/{src → app}/Shared.elm +34 -13
  79. package/generator/template/app/Site.elm +19 -0
  80. package/generator/template/{src → app}/View.elm +0 -0
  81. package/generator/template/elm-pages.config.mjs +5 -0
  82. package/generator/template/elm.json +1 -0
  83. package/generator/template/{public/index.js → index.ts} +7 -3
  84. package/generator/template/package.json +4 -4
  85. package/generator/template/public/favicon.ico +0 -0
  86. package/generator/template/public/images/icon-png.png +0 -0
  87. package/generator/template/src/.gitkeep +0 -0
  88. package/generator/template/style.css +4 -0
  89. package/package.json +33 -23
  90. package/src/ApiRoute.elm +176 -43
  91. package/src/BuildError.elm +10 -1
  92. package/src/CookieParser.elm +84 -0
  93. package/src/DataSource/Env.elm +38 -0
  94. package/src/DataSource/File.elm +27 -16
  95. package/src/DataSource/Glob.elm +126 -80
  96. package/src/DataSource/Http.elm +283 -304
  97. package/src/DataSource/Internal/Glob.elm +5 -21
  98. package/src/DataSource/Internal/Request.elm +25 -0
  99. package/src/DataSource/Port.elm +17 -14
  100. package/src/DataSource.elm +55 -318
  101. package/src/Form/Field.elm +717 -0
  102. package/src/Form/FieldStatus.elm +36 -0
  103. package/src/Form/FieldView.elm +417 -0
  104. package/src/Form/FormData.elm +22 -0
  105. package/src/Form/Validation.elm +391 -0
  106. package/src/Form/Value.elm +118 -0
  107. package/src/Form.elm +1683 -0
  108. package/src/FormData.elm +58 -0
  109. package/src/FormDecoder.elm +102 -0
  110. package/src/Head/Seo.elm +12 -4
  111. package/src/Head.elm +12 -2
  112. package/src/HtmlPrinter.elm +1 -1
  113. package/src/Internal/ApiRoute.elm +17 -4
  114. package/src/Internal/Request.elm +7 -0
  115. package/src/PageServerResponse.elm +68 -0
  116. package/src/Pages/ContentCache.elm +1 -229
  117. package/src/Pages/Fetcher.elm +58 -0
  118. package/src/Pages/FormState.elm +256 -0
  119. package/src/Pages/Generate.elm +800 -0
  120. package/src/Pages/Internal/Form.elm +17 -0
  121. package/src/Pages/Internal/NotFoundReason.elm +3 -55
  122. package/src/Pages/Internal/Platform/Cli.elm +777 -579
  123. package/src/Pages/Internal/Platform/Effect.elm +5 -5
  124. package/src/Pages/Internal/Platform/StaticResponses.elm +178 -394
  125. package/src/Pages/Internal/Platform/ToJsPayload.elm +24 -23
  126. package/src/Pages/Internal/Platform.elm +1244 -504
  127. package/src/Pages/Internal/ResponseSketch.elm +19 -0
  128. package/src/Pages/Internal/RoutePattern.elm +596 -45
  129. package/src/Pages/Manifest.elm +26 -0
  130. package/src/Pages/Msg.elm +79 -0
  131. package/src/Pages/ProgramConfig.elm +67 -14
  132. package/src/Pages/SiteConfig.elm +3 -6
  133. package/src/Pages/StaticHttp/Request.elm +4 -2
  134. package/src/Pages/StaticHttpRequest.elm +50 -215
  135. package/src/Pages/Transition.elm +70 -0
  136. package/src/Path.elm +1 -0
  137. package/src/Pattern.elm +98 -0
  138. package/src/RenderRequest.elm +2 -2
  139. package/src/RequestsAndPending.elm +111 -9
  140. package/src/Server/Request.elm +1253 -0
  141. package/src/Server/Response.elm +292 -0
  142. package/src/Server/Session.elm +316 -0
  143. package/src/Server/SetCookie.elm +169 -0
  144. package/src/TerminalText.elm +1 -1
  145. package/src/Test/Html/Internal/ElmHtml/Markdown.elm +0 -1
  146. package/src/Test/Html/Internal/ElmHtml/ToString.elm +1 -1
  147. package/generator/src/Page.elm +0 -359
  148. package/generator/src/codegen-template-module.js +0 -183
  149. package/generator/src/elm-pages-js-minified.js +0 -1
  150. package/generator/template/src/Api.elm +0 -14
  151. package/generator/template/src/Page/Index.elm +0 -69
  152. package/generator/template/src/Site.elm +0 -41
  153. package/src/DataSource/ServerRequest.elm +0 -60
  154. package/src/Internal/OptimizedDecoder.elm +0 -18
  155. package/src/KeepOrDiscard.elm +0 -6
  156. package/src/OptimizedDecoder/Pipeline.elm +0 -335
  157. package/src/OptimizedDecoder.elm +0 -818
  158. package/src/Pages/Internal/ApplicationType.elm +0 -6
  159. package/src/Pages/Secrets.elm +0 -83
  160. package/src/Secrets.elm +0 -111
  161. package/src/SecretsDict.elm +0 -45
@@ -8,37 +8,37 @@ module Pages.Internal.Platform.Cli exposing (Flags, Model, Msg(..), Program, cli
8
8
 
9
9
  import ApiRoute
10
10
  import BuildError exposing (BuildError)
11
+ import Bytes exposing (Bytes)
12
+ import Bytes.Encode
11
13
  import Codec
12
14
  import DataSource exposing (DataSource)
13
- import DataSource.Http exposing (RequestDetails)
14
- import Dict exposing (Dict)
15
- import Dict.Extra
15
+ import Dict
16
16
  import Head
17
17
  import Html exposing (Html)
18
18
  import HtmlPrinter
19
- import Http
20
19
  import Internal.ApiRoute exposing (ApiRoute(..))
21
20
  import Json.Decode as Decode
22
21
  import Json.Encode
23
- import Pages.ContentCache as ContentCache exposing (ContentCache)
22
+ import PageServerResponse exposing (PageServerResponse)
24
23
  import Pages.Flags
25
24
  import Pages.Http
26
- import Pages.Internal.ApplicationType as ApplicationType
27
- import Pages.Internal.NotFoundReason exposing (NotFoundReason)
25
+ import Pages.Internal.NotFoundReason as NotFoundReason exposing (NotFoundReason)
28
26
  import Pages.Internal.Platform.Effect as Effect exposing (Effect)
29
27
  import Pages.Internal.Platform.StaticResponses as StaticResponses exposing (StaticResponses)
30
28
  import Pages.Internal.Platform.ToJsPayload as ToJsPayload
29
+ import Pages.Internal.ResponseSketch as ResponseSketch
31
30
  import Pages.Internal.StaticHttpBody as StaticHttpBody
31
+ import Pages.Msg
32
32
  import Pages.ProgramConfig exposing (ProgramConfig)
33
33
  import Pages.SiteConfig exposing (SiteConfig)
34
34
  import Pages.StaticHttp.Request
35
35
  import Pages.StaticHttpRequest as StaticHttpRequest
36
36
  import Path exposing (Path)
37
37
  import RenderRequest exposing (RenderRequest)
38
- import SecretsDict exposing (SecretsDict)
38
+ import RequestsAndPending exposing (RequestsAndPending)
39
39
  import Task
40
40
  import TerminalText as Terminal
41
- import Url
41
+ import Url exposing (Url)
42
42
 
43
43
 
44
44
  {-| -}
@@ -49,12 +49,9 @@ type alias Flags =
49
49
  {-| -}
50
50
  type alias Model route =
51
51
  { staticResponses : StaticResponses
52
- , secrets : SecretsDict
53
52
  , errors : List BuildError
54
- , allRawResponses : Dict String (Maybe String)
55
- , pendingRequests : List { masked : RequestDetails, unmasked : RequestDetails }
53
+ , allRawResponses : RequestsAndPending
56
54
  , unprocessedPages : List ( Path, route )
57
- , staticRoutes : Maybe (List ( Path, route ))
58
55
  , maybeRequestJson : RenderRequest route
59
56
  , isDevServer : Bool
60
57
  }
@@ -64,12 +61,11 @@ type alias Model route =
64
61
  type Msg
65
62
  = GotDataBatch
66
63
  (List
67
- { request : { masked : RequestDetails, unmasked : RequestDetails }
68
- , response : String
64
+ { request : Pages.StaticHttp.Request.Request
65
+ , response : RequestsAndPending.Response
69
66
  }
70
67
  )
71
68
  | GotBuildError BuildError
72
- | Continue
73
69
 
74
70
 
75
71
  {-| -}
@@ -79,19 +75,15 @@ type alias Program route =
79
75
 
80
76
  {-| -}
81
77
  cliApplication :
82
- ProgramConfig userMsg userModel (Maybe route) siteData pageData sharedData
78
+ ProgramConfig userMsg userModel (Maybe route) pageData actionData sharedData effect mappedMsg errorPage
83
79
  -> Program (Maybe route)
84
80
  cliApplication config =
85
81
  let
86
- contentCache : ContentCache
87
- contentCache =
88
- ContentCache.init Nothing
89
-
90
- site : SiteConfig siteData
82
+ site : SiteConfig
91
83
  site =
92
84
  getSiteConfig config
93
85
 
94
- getSiteConfig : ProgramConfig userMsg userModel (Maybe route) siteData pageData sharedData -> SiteConfig siteData
86
+ getSiteConfig : ProgramConfig userMsg userModel (Maybe route) pageData actionData sharedData effect mappedMsg errorPage -> SiteConfig
95
87
  getSiteConfig fullConfig =
96
88
  case fullConfig.site of
97
89
  Just mySite ->
@@ -109,108 +101,130 @@ cliApplication config =
109
101
  Decode.decodeValue (RenderRequest.decoder config) flags
110
102
  |> Result.withDefault RenderRequest.default
111
103
  in
112
- init site renderRequest contentCache config flags
113
- |> Tuple.mapSecond (perform site renderRequest config config.toJsPort)
104
+ init site renderRequest config flags
105
+ |> Tuple.mapSecond (perform site renderRequest config)
114
106
  , update =
115
107
  \msg model ->
116
- update site contentCache config msg model
117
- |> Tuple.mapSecond (perform site model.maybeRequestJson config config.toJsPort)
108
+ update site config msg model
109
+ |> Tuple.mapSecond (perform site model.maybeRequestJson config)
118
110
  , subscriptions =
119
111
  \_ ->
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
112
+ Sub.batch
113
+ [ config.fromJsPort
114
+ |> Sub.map
115
+ (\jsonValue ->
116
+ let
117
+ decoder : Decode.Decoder Msg
118
+ decoder =
119
+ Decode.field "tag" Decode.string
120
+ |> Decode.andThen
121
+ (\tag ->
122
+ case tag of
123
+ "BuildError" ->
124
+ Decode.field "data"
150
125
  (Decode.map2
151
- (\requests response ->
152
- { request =
153
- { masked = requests.masked
154
- , unmasked = requests.unmasked
155
- }
156
- , response = response
126
+ (\message title ->
127
+ { title = title
128
+ , message = message
129
+ , fatal = True
130
+ , path = "" -- TODO wire in current path here
157
131
  }
158
132
  )
159
- (Decode.field "request" requestDecoder)
160
- (Decode.field "response" Decode.string)
133
+ (Decode.field "message" Decode.string |> Decode.map Terminal.fromAnsiString)
134
+ (Decode.field "title" Decode.string)
161
135
  )
162
- )
163
- |> Decode.map GotDataBatch
164
-
165
- _ ->
166
- Decode.fail "Unhandled msg"
136
+ |> Decode.map GotBuildError
137
+
138
+ _ ->
139
+ Decode.fail "Unhandled msg"
140
+ )
141
+ in
142
+ Decode.decodeValue decoder jsonValue
143
+ |> Result.mapError
144
+ (\error ->
145
+ ("From location 1: "
146
+ ++ (error
147
+ |> Decode.errorToString
148
+ )
167
149
  )
168
- in
169
- Decode.decodeValue decoder jsonValue
170
- |> Result.mapError Decode.errorToString
171
- |> Result.withDefault Continue
172
- )
150
+ |> BuildError.internal
151
+ |> GotBuildError
152
+ )
153
+ |> mergeResult
154
+ )
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
+ )
172
+ ]
173
173
  }
174
174
 
175
175
 
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
+ mergeResult : Result a a -> a
185
+ mergeResult r =
186
+ case r of
187
+ Ok rr ->
188
+ rr
189
+
190
+ Err rr ->
191
+ rr
192
+
193
+
176
194
  {-| -}
177
- requestDecoder : Decode.Decoder { masked : Pages.StaticHttp.Request.Request, unmasked : Pages.StaticHttp.Request.Request }
195
+ requestDecoder : Decode.Decoder Pages.StaticHttp.Request.Request
178
196
  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
- )
197
+ Pages.StaticHttp.Request.codec
184
198
  |> Codec.decoder
185
199
 
186
200
 
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
- )
201
+ flatten : SiteConfig -> RenderRequest route -> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage -> List Effect -> Cmd Msg
202
+ flatten site renderRequest config list =
203
+ Cmd.batch (flattenHelp [] site renderRequest config list)
194
204
 
195
205
 
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
- )
206
+ flattenHelp : List (Cmd Msg) -> SiteConfig -> RenderRequest route -> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage -> List Effect -> List (Cmd Msg)
207
+ flattenHelp soFar site renderRequest config list =
208
+ case list of
209
+ first :: rest ->
210
+ flattenHelp
211
+ (perform site renderRequest config first :: soFar)
212
+ site
213
+ renderRequest
214
+ config
215
+ rest
216
+
217
+ [] ->
218
+ soFar
203
219
 
204
220
 
205
221
  perform :
206
- SiteConfig siteData
222
+ SiteConfig
207
223
  -> RenderRequest route
208
- -> ProgramConfig userMsg userModel route siteData pageData sharedData
209
- -> (Codec.Value -> Cmd Never)
224
+ -> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
210
225
  -> Effect
211
226
  -> Cmd Msg
212
- perform site renderRequest config toJsPort effect =
213
- -- elm-review: known-unoptimized-recursion
227
+ perform site renderRequest config effect =
214
228
  let
215
229
  canonicalSiteUrl : String
216
230
  canonicalSiteUrl =
@@ -221,21 +235,19 @@ perform site renderRequest config toJsPort effect =
221
235
  Cmd.none
222
236
 
223
237
  Effect.Batch list ->
224
- list
225
- |> List.map (perform site renderRequest config toJsPort)
226
- |> Cmd.batch
238
+ flatten site renderRequest config list
227
239
 
228
- Effect.FetchHttp ({ unmasked, masked } as requests) ->
240
+ Effect.FetchHttp unmasked ->
229
241
  if unmasked.url == "$$elm-pages$$headers" then
230
242
  case
231
243
  renderRequest
232
244
  |> RenderRequest.maybeRequestPayload
233
- |> Maybe.map (Json.Encode.encode 0)
245
+ |> Maybe.map (\json -> RequestsAndPending.Response Nothing (RequestsAndPending.JsonBody json))
234
246
  |> Result.fromMaybe (Pages.Http.BadUrl "$$elm-pages$$headers is only available on server-side request (not on build).")
235
247
  of
236
248
  Ok okResponse ->
237
249
  Task.succeed
238
- [ { request = requests
250
+ [ { request = unmasked
239
251
  , response = okResponse
240
252
  }
241
253
  ]
@@ -247,8 +259,8 @@ perform site renderRequest config toJsPort effect =
247
259
  [ Terminal.text "I got an error making an HTTP request to this URL: "
248
260
 
249
261
  -- 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
262
+ , Terminal.yellow unmasked.url
263
+ , Terminal.text <| Json.Encode.encode 2 <| StaticHttpBody.encode unmasked.body
252
264
  , Terminal.text "\n\n"
253
265
  , case error of
254
266
  Pages.Http.BadStatus metadata body ->
@@ -261,7 +273,7 @@ perform site renderRequest config toJsPort effect =
261
273
 
262
274
  Pages.Http.BadUrl _ ->
263
275
  -- TODO include HTTP method, headers, and body
264
- Terminal.text <| "Invalid url: " ++ requests.masked.url
276
+ Terminal.text <| "Invalid url: " ++ unmasked.url
265
277
 
266
278
  Pages.Http.Timeout ->
267
279
  Terminal.text "Timeout"
@@ -275,35 +287,29 @@ perform site renderRequest config toJsPort effect =
275
287
  |> Task.succeed
276
288
  |> Task.perform GotBuildError
277
289
 
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
290
+ else
291
+ ToJsPayload.DoHttp unmasked unmasked.useCache
285
292
  |> Codec.encoder (ToJsPayload.successCodecNew2 canonicalSiteUrl "")
286
- |> toJsPort
293
+ |> config.toJsPort
287
294
  |> Cmd.map never
288
295
 
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
296
+ Effect.SendSinglePage info ->
297
+ let
298
+ currentPagePath : String
299
+ currentPagePath =
300
+ case info of
301
+ ToJsPayload.PageProgress toJsSuccessPayloadNew ->
302
+ toJsSuccessPayloadNew.route
299
303
 
300
- else
301
- ToJsPayload.DoHttp { masked = masked, unmasked = unmasked }
302
- |> Codec.encoder (ToJsPayload.successCodecNew2 canonicalSiteUrl "")
303
- |> toJsPort
304
- |> Cmd.map never
304
+ _ ->
305
+ ""
306
+ in
307
+ info
308
+ |> Codec.encoder (ToJsPayload.successCodecNew2 canonicalSiteUrl currentPagePath)
309
+ |> config.toJsPort
310
+ |> Cmd.map never
305
311
 
306
- Effect.SendSinglePage done info ->
312
+ Effect.SendSinglePageNew rawBytes info ->
307
313
  let
308
314
  currentPagePath : String
309
315
  currentPagePath =
@@ -314,80 +320,59 @@ perform site renderRequest config toJsPort effect =
314
320
  _ ->
315
321
  ""
316
322
  in
317
- Cmd.batch
318
- [ info
323
+ { oldThing =
324
+ info
319
325
  |> 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
- ]
326
+ , binaryPageData = rawBytes
327
+ }
328
+ |> config.sendPageData
329
+ |> Cmd.map never
329
330
 
330
331
  Effect.Continue ->
331
332
  Cmd.none
332
333
 
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
334
 
346
335
  flagsDecoder :
347
336
  Decode.Decoder
348
- { secrets : SecretsDict
349
- , staticHttpCache : Dict String (Maybe String)
337
+ { staticHttpCache : RequestsAndPending
350
338
  , isDevServer : Bool
351
339
  }
352
340
  flagsDecoder =
353
- Decode.map3
354
- (\secrets staticHttpCache isDevServer ->
355
- { secrets = secrets
356
- , staticHttpCache = staticHttpCache
341
+ Decode.map2
342
+ (\staticHttpCache isDevServer ->
343
+ { staticHttpCache = staticHttpCache
357
344
  , isDevServer = isDevServer
358
345
  }
359
346
  )
360
- (Decode.field "secrets" SecretsDict.decoder)
361
- (Decode.field "staticHttpCache"
362
- (Decode.dict
363
- (Decode.string
364
- |> Decode.map Just
365
- )
366
- )
367
- )
347
+ --(Decode.field "staticHttpCache"
348
+ -- (Decode.dict
349
+ -- (Decode.string
350
+ -- |> Decode.map Just
351
+ -- )
352
+ -- )
353
+ --)
354
+ -- TODO remove hardcoding and decode staticHttpCache here
355
+ (Decode.succeed Dict.empty)
368
356
  (Decode.field "mode" Decode.string |> Decode.map (\mode -> mode == "dev-server"))
369
357
 
370
358
 
371
359
  {-| -}
372
360
  init :
373
- SiteConfig siteData
361
+ SiteConfig
374
362
  -> RenderRequest route
375
- -> ContentCache
376
- -> ProgramConfig userMsg userModel route siteData pageData sharedData
363
+ -> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
377
364
  -> Decode.Value
378
365
  -> ( Model route, Effect )
379
- init site renderRequest contentCache config flags =
366
+ init site renderRequest config flags =
380
367
  case Decode.decodeValue flagsDecoder flags of
381
- Ok { secrets, staticHttpCache, isDevServer } ->
382
- initLegacy site renderRequest { secrets = secrets, staticHttpCache = staticHttpCache, isDevServer = isDevServer } contentCache config flags
368
+ Ok { staticHttpCache, isDevServer } ->
369
+ initLegacy site renderRequest { staticHttpCache = staticHttpCache, isDevServer = isDevServer } config
383
370
 
384
371
  Err error ->
385
372
  updateAndSendPortIfDone
386
373
  site
387
- contentCache
388
374
  config
389
- { staticResponses = StaticResponses.error
390
- , secrets = SecretsDict.masked
375
+ { staticResponses = StaticResponses.empty
391
376
  , errors =
392
377
  [ { title = "Internal Error"
393
378
  , message = [ Terminal.text <| "Failed to parse flags: " ++ Decode.errorToString error ]
@@ -396,35 +381,105 @@ init site renderRequest contentCache config flags =
396
381
  }
397
382
  ]
398
383
  , allRawResponses = Dict.empty
399
- , pendingRequests = []
400
384
  , unprocessedPages = []
401
- , staticRoutes = Just []
402
385
  , maybeRequestJson = renderRequest
403
386
  , isDevServer = False
404
387
  }
405
388
 
406
389
 
390
+ type ActionRequest
391
+ = ActionResponseRequest
392
+ | ActionOnlyRequest
393
+
394
+
395
+ isActionDecoder : Decode.Decoder (Maybe ActionRequest)
396
+ isActionDecoder =
397
+ Decode.map2 Tuple.pair
398
+ (Decode.field "method" Decode.string)
399
+ (Decode.field "headers" (Decode.dict Decode.string))
400
+ |> Decode.map
401
+ (\( method, headers ) ->
402
+ case method |> String.toUpper of
403
+ "GET" ->
404
+ Nothing
405
+
406
+ "OPTIONS" ->
407
+ Nothing
408
+
409
+ _ ->
410
+ let
411
+ actionOnly : Bool
412
+ actionOnly =
413
+ case headers |> Dict.get "elm-pages-action-only" of
414
+ Just _ ->
415
+ True
416
+
417
+ Nothing ->
418
+ False
419
+ in
420
+ Just
421
+ (if actionOnly then
422
+ ActionOnlyRequest
423
+
424
+ else
425
+ ActionResponseRequest
426
+ )
427
+ )
428
+
429
+
407
430
  initLegacy :
408
- SiteConfig siteData
431
+ SiteConfig
409
432
  -> 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
433
+ -> { staticHttpCache : RequestsAndPending, isDevServer : Bool }
434
+ -> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
414
435
  -> ( Model route, Effect )
415
- initLegacy site renderRequest { secrets, staticHttpCache, isDevServer } contentCache config flags =
436
+ initLegacy site renderRequest { staticHttpCache, isDevServer } config =
416
437
  let
417
438
  staticResponses : StaticResponses
418
439
  staticResponses =
419
440
  case renderRequest of
420
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
421
447
  case singleRequest of
422
448
  RenderRequest.Page serverRequestPayload ->
423
- StaticResponses.renderSingleRoute config
424
- serverRequestPayload
425
- (DataSource.map2 (\_ _ -> ())
426
- (config.data serverRequestPayload.frontmatter)
427
- config.sharedData
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
428
483
  )
429
484
  (if isDevServer then
430
485
  config.handleRoute serverRequestPayload.frontmatter
@@ -435,11 +490,17 @@ initLegacy site renderRequest { secrets, staticHttpCache, isDevServer } contentC
435
490
 
436
491
  RenderRequest.Api ( path, ApiRoute apiRequest ) ->
437
492
  StaticResponses.renderApiRequest
438
- (apiRequest.matchesToResponse path)
493
+ (DataSource.map2 (\_ _ -> ())
494
+ (apiRequest.matchesToResponse path)
495
+ globalHeadTags
496
+ )
439
497
 
440
- RenderRequest.NotFound path ->
498
+ RenderRequest.NotFound _ ->
441
499
  StaticResponses.renderApiRequest
442
- (DataSource.succeed [])
500
+ (DataSource.map2 (\_ _ -> ())
501
+ (DataSource.succeed [])
502
+ globalHeadTags
503
+ )
443
504
 
444
505
  unprocessedPages : List ( Path, route )
445
506
  unprocessedPages =
@@ -452,104 +513,57 @@ initLegacy site renderRequest { secrets, staticHttpCache, isDevServer } contentC
452
513
  RenderRequest.Api _ ->
453
514
  []
454
515
 
455
- RenderRequest.NotFound path ->
516
+ RenderRequest.NotFound _ ->
456
517
  []
457
518
 
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
519
  initialModel : Model route
473
520
  initialModel =
474
521
  { staticResponses = staticResponses
475
- , secrets = secrets
476
522
  , errors = []
477
523
  , allRawResponses = staticHttpCache
478
- , pendingRequests = []
479
524
  , unprocessedPages = unprocessedPages
480
- , staticRoutes = unprocessedPagesState
481
525
  , maybeRequestJson = renderRequest
482
526
  , isDevServer = isDevServer
483
527
  }
484
528
  in
485
- StaticResponses.nextStep config initialModel Nothing
529
+ StaticResponses.nextStep initialModel Nothing
486
530
  |> nextStepToEffect site
487
- contentCache
488
531
  config
489
532
  initialModel
490
533
 
491
534
 
492
535
  updateAndSendPortIfDone :
493
- SiteConfig siteData
494
- -> ContentCache
495
- -> ProgramConfig userMsg userModel route siteData pageData sharedData
536
+ SiteConfig
537
+ -> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
496
538
  -> Model route
497
539
  -> ( Model route, Effect )
498
- updateAndSendPortIfDone site contentCache config model =
540
+ updateAndSendPortIfDone site config model =
499
541
  StaticResponses.nextStep
500
- config
501
542
  model
502
543
  Nothing
503
- |> nextStepToEffect site contentCache config model
544
+ |> nextStepToEffect site config model
504
545
 
505
546
 
506
547
  {-| -}
507
548
  update :
508
- SiteConfig siteData
509
- -> ContentCache
510
- -> ProgramConfig userMsg userModel route siteData pageData sharedData
549
+ SiteConfig
550
+ -> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
511
551
  -> Msg
512
552
  -> Model route
513
553
  -> ( Model route, Effect )
514
- update site contentCache config msg model =
554
+ update site config msg model =
515
555
  case msg of
516
556
  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
557
  let
545
558
  updatedModel : Model route
546
559
  updatedModel =
547
560
  model
561
+ |> StaticResponses.batchUpdate batch
548
562
  in
549
- StaticResponses.nextStep config
563
+ StaticResponses.nextStep
550
564
  updatedModel
551
565
  Nothing
552
- |> nextStepToEffect site contentCache config updatedModel
566
+ |> nextStepToEffect site config updatedModel
553
567
 
554
568
  GotBuildError buildError ->
555
569
  let
@@ -560,51 +574,22 @@ update site contentCache config msg model =
560
574
  buildError :: model.errors
561
575
  }
562
576
  in
563
- StaticResponses.nextStep config
577
+ StaticResponses.nextStep
564
578
  updatedModel
565
579
  Nothing
566
- |> nextStepToEffect site contentCache config updatedModel
580
+ |> nextStepToEffect site config updatedModel
567
581
 
568
582
 
569
583
  nextStepToEffect :
570
- SiteConfig siteData
571
- -> ContentCache
572
- -> ProgramConfig userMsg userModel route siteData pageData sharedData
584
+ SiteConfig
585
+ -> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
573
586
  -> Model route
574
587
  -> ( StaticResponses, StaticResponses.NextStep route )
575
588
  -> ( Model route, Effect )
576
- nextStepToEffect site contentCache config model ( updatedStaticResponsesModel, nextStep ) =
589
+ nextStepToEffect site config model ( updatedStaticResponsesModel, nextStep ) =
577
590
  case nextStep of
578
591
  StaticResponses.Continue updatedAllRawResponses httpRequests maybeRoutes ->
579
592
  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
593
  updatedUnprocessedPages : List ( Path, route )
609
594
  updatedUnprocessedPages =
610
595
  case maybeRoutes of
@@ -624,25 +609,22 @@ nextStepToEffect site contentCache config model ( updatedStaticResponsesModel, n
624
609
  updatedModel =
625
610
  { model
626
611
  | allRawResponses = updatedAllRawResponses
627
- , pendingRequests = pending
628
612
  , staticResponses = updatedStaticResponsesModel
629
- , staticRoutes = updatedRoutes
630
613
  , unprocessedPages = updatedUnprocessedPages
631
614
  }
632
615
  in
633
- if List.isEmpty doNow && updatedRoutes /= model.staticRoutes then
616
+ if List.isEmpty httpRequests then
634
617
  nextStepToEffect site
635
- contentCache
636
618
  config
637
619
  updatedModel
638
- (StaticResponses.nextStep config
620
+ (StaticResponses.nextStep
639
621
  updatedModel
640
622
  Nothing
641
623
  )
642
624
 
643
625
  else
644
626
  ( updatedModel
645
- , (doNow
627
+ , (httpRequests
646
628
  |> List.map Effect.FetchHttp
647
629
  )
648
630
  |> Effect.Batch
@@ -655,7 +637,15 @@ nextStepToEffect site contentCache config model ( updatedStaticResponsesModel, n
655
637
  apiResponse : Effect
656
638
  apiResponse =
657
639
  case model.maybeRequestJson of
658
- RenderRequest.SinglePage includeHtml requestPayload value ->
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
659
649
  case requestPayload of
660
650
  RenderRequest.Api ( path, ApiRoute apiHandler ) ->
661
651
  let
@@ -663,40 +653,38 @@ nextStepToEffect site contentCache config model ( updatedStaticResponsesModel, n
663
653
  thing =
664
654
  apiHandler.matchesToResponse path
665
655
  in
666
- StaticHttpRequest.resolve ApplicationType.Cli
656
+ StaticHttpRequest.resolve
667
657
  thing
668
658
  model.allRawResponses
669
659
  |> Result.mapError (StaticHttpRequest.toBuildError "TODO - path from request")
670
660
  |> (\response ->
671
661
  case response of
672
662
  Ok (Just okResponse) ->
673
- { body = okResponse.body
674
- , staticHttpCache = model.allRawResponses |> Dict.Extra.filterMap (\_ v -> v)
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)
675
667
  , statusCode = 200
676
668
  }
677
669
  |> ToJsPayload.SendApiResponse
678
- |> Effect.SendSinglePage True
670
+ |> Effect.SendSinglePage
679
671
 
680
672
  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
673
+ render404Page config (Result.toMaybe sharedDataResult) model (Path.fromString path) NotFoundReason.NoMatchingRoute
687
674
 
688
675
  Err error ->
689
676
  [ error ]
690
677
  |> ToJsPayload.Errors
691
- |> Effect.SendSinglePage True
678
+ |> Effect.SendSinglePage
692
679
  )
693
680
 
694
681
  RenderRequest.Page payload ->
695
682
  let
696
683
  pageFoundResult : Result BuildError (Maybe NotFoundReason)
697
684
  pageFoundResult =
698
- StaticHttpRequest.resolve ApplicationType.Browser
685
+ StaticHttpRequest.resolve
699
686
  (if model.isDevServer then
687
+ -- TODO OPTIMIZATION this is redundant
700
688
  config.handleRoute payload.frontmatter
701
689
 
702
690
  else
@@ -707,309 +695,519 @@ nextStepToEffect site contentCache config model ( updatedStaticResponsesModel, n
707
695
  in
708
696
  case pageFoundResult of
709
697
  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
698
+ sendSinglePageProgress site model.allRawResponses config model payload
817
699
 
818
700
  Ok (Just notFoundReason) ->
819
- render404Page config model payload.path notFoundReason
701
+ render404Page config
702
+ --Nothing
703
+ (Result.toMaybe sharedDataResult)
704
+ model
705
+ payload.path
706
+ notFoundReason
820
707
 
821
708
  Err error ->
822
- [ error ] |> ToJsPayload.Errors |> Effect.SendSinglePage True
709
+ [ error ] |> ToJsPayload.Errors |> Effect.SendSinglePage
823
710
 
824
711
  RenderRequest.NotFound path ->
825
- render404Page config model path Pages.Internal.NotFoundReason.NoMatchingRoute
712
+ render404Page config
713
+ --Nothing
714
+ (Result.toMaybe sharedDataResult)
715
+ model
716
+ path
717
+ NotFoundReason.NoMatchingRoute
826
718
  in
827
- ( { model | staticRoutes = Just [] }
719
+ ( model
828
720
  , apiResponse
829
721
  )
830
722
 
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
723
  StaticResponses.Errors errors ->
844
724
  ( model
845
- , errors |> ToJsPayload.Errors |> Effect.SendSinglePage True
725
+ , errors |> ToJsPayload.Errors |> Effect.SendSinglePage
846
726
  )
847
727
 
848
728
 
849
729
  sendSinglePageProgress :
850
- SiteConfig siteData
851
- -> Dict String String
852
- -> ProgramConfig userMsg userModel route siteData pageData sharedData
730
+ SiteConfig
731
+ -> RequestsAndPending
732
+ -> ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
853
733
  -> Model route
854
- -> ( Path, route )
734
+ -> { path : Path, frontmatter : route }
855
735
  -> 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
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)
866
749
 
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
- }
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
882
756
 
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
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
900
828
  }
901
- , metadata = currentPage.route
902
- , pageUrl = Nothing
903
- }
904
- )
905
- |> Tuple.first
829
+ )
830
+ |> Tuple.first
831
+
832
+ viewValue : { title : String, body : 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 |> HtmlPrinter.htmlToString
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 : 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 |> HtmlPrinter.htmlToString
884
+ , title = viewValue.title
885
+ }
886
+ )
906
887
 
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
- )
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
+ }
916
897
 
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
- }
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
+ )
926
922
 
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
923
  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
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))
970
1027
 
971
- Err error ->
972
- [ error ]
973
- |> ToJsPayload.Errors
974
- |> Effect.SendSinglePage True
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
+ )
1081
+
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
975
1105
 
976
1106
 
977
1107
  render404Page :
978
- ProgramConfig userMsg userModel route siteData pageData sharedData
1108
+ ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage
1109
+ -> Maybe sharedData
979
1110
  -> Model route
980
1111
  -> Path
981
1112
  -> NotFoundReason
982
1113
  -> 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
- }
1114
+ render404Page config sharedData model path notFoundReason =
1115
+ case ( model.isDevServer, sharedData ) of
1116
+ ( False, Just justSharedData ) ->
1117
+ let
1118
+ byteEncodedPageData : Bytes
1119
+ byteEncodedPageData =
1120
+ ResponseSketch.HotUpdate
1121
+ (config.errorPageToData config.notFoundPage)
1122
+ justSharedData
1123
+ -- TODO remove shared action data
1124
+ Nothing
1125
+ |> config.encodeResponse
1126
+ |> Bytes.Encode.encode
1127
+
1128
+ pageModel : userModel
1129
+ pageModel =
1130
+ config.init
1131
+ Pages.Flags.PreRenderFlags
1132
+ justSharedData
1133
+ pageData
1134
+ Nothing
1135
+ Nothing
1136
+ |> Tuple.first
1137
+
1138
+ pageData : pageData
1139
+ pageData =
1140
+ config.errorPageToData config.notFoundPage
1141
+
1142
+ pathAndRoute : { path : Path, route : route }
1143
+ pathAndRoute =
1144
+ { path = path, route = config.notFoundRoute }
1145
+
1146
+ viewValue : { title : String, body : Html (Pages.Msg.Msg userMsg) }
1147
+ viewValue =
1148
+ (config.view Dict.empty
1149
+ Dict.empty
1150
+ Nothing
1151
+ pathAndRoute
1152
+ Nothing
1153
+ justSharedData
1154
+ pageData
1155
+ Nothing
1156
+ |> .view
1001
1157
  )
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
1158
+ pageModel
1159
+ in
1160
+ { route = Path.toAbsolute path
1161
+ , contentJson = Dict.empty
1162
+ , html = viewValue.body |> HtmlPrinter.htmlToString
1163
+ , errors = []
1164
+ , head = config.view Dict.empty Dict.empty Nothing pathAndRoute Nothing justSharedData pageData Nothing |> .head
1165
+ , title = viewValue.title
1166
+ , staticHttpCache = Dict.empty
1167
+ , is404 = True
1168
+ , statusCode = 404
1169
+ , headers = []
1170
+ }
1171
+ |> ToJsPayload.PageProgress
1172
+ |> Effect.SendSinglePageNew byteEncodedPageData
1173
+
1174
+ _ ->
1175
+ let
1176
+ byteEncodedPageData : Bytes
1177
+ byteEncodedPageData =
1178
+ ResponseSketch.NotFound { reason = notFoundReason, path = path }
1179
+ |> config.encodeResponse
1180
+ |> Bytes.Encode.encode
1181
+
1182
+ notFoundDocument : { title : String, body : Html msg }
1183
+ notFoundDocument =
1184
+ { path = path
1185
+ , reason = notFoundReason
1186
+ }
1187
+ |> NotFoundReason.document config.pathPatterns
1188
+ in
1189
+ { route = Path.toAbsolute path
1190
+ , contentJson = Dict.empty
1191
+ , html = HtmlPrinter.htmlToString notFoundDocument.body
1192
+ , errors = []
1193
+ , head = []
1194
+ , title = notFoundDocument.title
1195
+ , staticHttpCache = Dict.empty
1196
+
1197
+ -- TODO can I handle caching from the JS-side only?
1198
+ --model.allRawResponses |> Dict.Extra.filterMap (\_ v -> v)
1199
+ , is404 = True
1200
+ , statusCode = 404
1201
+ , headers = []
1202
+ }
1203
+ |> ToJsPayload.PageProgress
1204
+ |> Effect.SendSinglePageNew byteEncodedPageData
1205
+
1206
+
1207
+ urlToRoute : ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage -> Url -> route
1208
+ urlToRoute config url =
1209
+ if url.path |> String.startsWith "/____elm-pages-internal____" then
1210
+ config.notFoundRoute
1211
+
1212
+ else
1213
+ config.urlToRoute url