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