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