elm-pages 3.0.0-beta.3 → 3.0.0-beta.30
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 +10 -1
- package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2864 -2589
- 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.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/o.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -1
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1327 -122
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +15295 -13271
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
- package/generator/dead-code-review/elm.json +8 -6
- package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +59 -10
- package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +52 -36
- 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/o.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
- package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1327 -122
- package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +14621 -12637
- package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
- package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
- package/generator/review/elm.json +8 -8
- package/generator/src/RouteBuilder.elm +113 -107
- package/generator/src/SharedTemplate.elm +3 -2
- package/generator/src/SiteConfig.elm +3 -2
- package/generator/src/basepath-middleware.js +3 -3
- package/generator/src/build.js +123 -87
- package/generator/src/cli.js +256 -77
- package/generator/src/codegen.js +29 -27
- package/generator/src/compatibility-key.js +3 -0
- package/generator/src/compile-elm.js +25 -25
- package/generator/src/config.js +39 -0
- package/generator/src/copy-dir.js +2 -2
- package/generator/src/dev-server.js +150 -133
- package/generator/src/dir-helpers.js +9 -26
- package/generator/src/elm-codegen.js +5 -4
- package/generator/src/elm-file-constants.js +2 -3
- package/generator/src/error-formatter.js +12 -11
- package/generator/src/file-helpers.js +3 -4
- package/generator/src/generate-template-module-connector.js +23 -22
- package/generator/src/init.js +9 -8
- package/generator/src/pre-render-html.js +39 -28
- package/generator/src/render-test.js +109 -0
- package/generator/src/render-worker.js +25 -28
- package/generator/src/render.js +322 -142
- package/generator/src/request-cache.js +252 -163
- package/generator/src/rewrite-client-elm-json.js +5 -5
- package/generator/src/rewrite-elm-json.js +7 -7
- package/generator/src/route-codegen-helpers.js +16 -31
- package/generator/src/seo-renderer.js +12 -7
- package/generator/src/vite-utils.js +77 -0
- package/generator/static-code/hmr.js +79 -13
- package/generator/template/app/Api.elm +6 -5
- package/generator/template/app/Effect.elm +123 -0
- package/generator/template/app/ErrorPage.elm +37 -6
- package/generator/template/app/Route/Index.elm +17 -10
- package/generator/template/app/Shared.elm +24 -47
- package/generator/template/app/Site.elm +19 -6
- package/generator/template/app/View.elm +1 -8
- package/generator/template/elm-tooling.json +0 -3
- package/generator/template/elm.json +34 -25
- package/generator/template/package.json +10 -4
- package/package.json +23 -22
- package/src/ApiRoute.elm +199 -61
- package/src/BackendTask/Custom.elm +325 -0
- package/src/BackendTask/Env.elm +90 -0
- package/src/{DataSource → BackendTask}/File.elm +128 -43
- package/src/{DataSource → BackendTask}/Glob.elm +136 -125
- package/src/BackendTask/Http.elm +673 -0
- package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
- package/src/BackendTask/Internal/Request.elm +28 -0
- package/src/BackendTask/Random.elm +79 -0
- package/src/BackendTask/Time.elm +47 -0
- package/src/BackendTask.elm +537 -0
- package/src/FatalError.elm +89 -0
- package/src/Form/Field.elm +21 -9
- package/src/Form/FieldView.elm +94 -14
- package/src/Form.elm +275 -400
- package/src/Head.elm +237 -7
- package/src/HtmlPrinter.elm +7 -3
- package/src/Internal/ApiRoute.elm +7 -5
- package/src/PageServerResponse.elm +6 -1
- package/src/Pages/FormState.elm +6 -5
- package/src/Pages/GeneratorProgramConfig.elm +15 -0
- package/src/Pages/Internal/FatalError.elm +5 -0
- package/src/Pages/Internal/Form.elm +21 -1
- package/src/Pages/{Msg.elm → Internal/Msg.elm} +26 -16
- package/src/Pages/Internal/Platform/Cli.elm +507 -763
- package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
- package/src/Pages/Internal/Platform/Effect.elm +1 -2
- package/src/Pages/Internal/Platform/GeneratorApplication.elm +373 -0
- package/src/Pages/Internal/Platform/StaticResponses.elm +73 -270
- package/src/Pages/Internal/Platform/ToJsPayload.elm +4 -7
- package/src/Pages/Internal/Platform.elm +215 -102
- package/src/Pages/Internal/Script.elm +17 -0
- package/src/Pages/Internal/StaticHttpBody.elm +35 -1
- package/src/Pages/Manifest.elm +29 -4
- package/src/Pages/PageUrl.elm +23 -9
- package/src/Pages/ProgramConfig.elm +14 -10
- package/src/Pages/Script.elm +109 -0
- package/src/Pages/SiteConfig.elm +3 -2
- package/src/Pages/StaticHttp/Request.elm +2 -2
- package/src/Pages/StaticHttpRequest.elm +23 -98
- package/src/PagesMsg.elm +92 -0
- package/src/Path.elm +16 -19
- package/src/QueryParams.elm +21 -172
- package/src/RequestsAndPending.elm +8 -19
- package/src/Result/Extra.elm +26 -0
- package/src/Scaffold/Form.elm +484 -0
- package/src/Scaffold/Route.elm +1376 -0
- package/src/Server/Request.elm +43 -37
- package/src/Server/Session.elm +34 -34
- package/src/Server/SetCookie.elm +1 -1
- package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
- package/src/DataSource/Env.elm +0 -38
- package/src/DataSource/Http.elm +0 -446
- package/src/DataSource/Internal/Request.elm +0 -20
- package/src/DataSource/Port.elm +0 -90
- package/src/DataSource.elm +0 -538
- package/src/Pages/Generate.elm +0 -800
package/src/Server/Request.elm
CHANGED
|
@@ -86,11 +86,12 @@ module Server.Request exposing
|
|
|
86
86
|
|
|
87
87
|
-}
|
|
88
88
|
|
|
89
|
+
import BackendTask exposing (BackendTask)
|
|
89
90
|
import CookieParser
|
|
90
|
-
import DataSource exposing (DataSource)
|
|
91
91
|
import Dict exposing (Dict)
|
|
92
|
+
import FatalError exposing (FatalError)
|
|
92
93
|
import Form
|
|
93
|
-
import Form.Validation
|
|
94
|
+
import Form.Validation as Validation
|
|
94
95
|
import FormData
|
|
95
96
|
import Internal.Request
|
|
96
97
|
import Json.Decode
|
|
@@ -118,17 +119,17 @@ Note that this data is not available for pre-rendered pages or pre-rendered API
|
|
|
118
119
|
This is because when a page is pre-rendered, there _is_ no incoming HTTP request to respond to, it is rendered before a user
|
|
119
120
|
requests the page and then the pre-rendered page is served as a plain file (without running your Route Module).
|
|
120
121
|
|
|
121
|
-
That's why `RouteBuilder.preRender` has `data : RouteParams ->
|
|
122
|
+
That's why `RouteBuilder.preRender` has `data : RouteParams -> BackendTask Data`:
|
|
122
123
|
|
|
123
|
-
import
|
|
124
|
+
import BackendTask exposing (BackendTask)
|
|
124
125
|
import RouteBuilder exposing (StatelessRoute)
|
|
125
126
|
|
|
126
127
|
type alias Data =
|
|
127
128
|
{}
|
|
128
129
|
|
|
129
|
-
data : RouteParams ->
|
|
130
|
+
data : RouteParams -> BackendTask Data
|
|
130
131
|
data routeParams =
|
|
131
|
-
|
|
132
|
+
BackendTask.succeed Data
|
|
132
133
|
|
|
133
134
|
route : StatelessRoute RouteParams Data ActionData
|
|
134
135
|
route =
|
|
@@ -141,7 +142,7 @@ That's why `RouteBuilder.preRender` has `data : RouteParams -> DataSource Data`:
|
|
|
141
142
|
|
|
142
143
|
A server-rendered Route Module _does_ have access to a user's incoming HTTP request because it runs every time the page
|
|
143
144
|
is loaded. That's why `data` is a `Request.Parser` in server-rendered Route Modules. Since you have an incoming HTTP request for server-rendered routes,
|
|
144
|
-
`RouteBuilder.serverRender` has `data : RouteParams -> Request.Parser (
|
|
145
|
+
`RouteBuilder.serverRender` has `data : RouteParams -> Request.Parser (BackendTask (Response Data))`. That means that you
|
|
145
146
|
can use the incoming HTTP request data to choose how to respond. For example, you could check for a dark-mode preference
|
|
146
147
|
cookie and render a light- or dark-themed page and render a different page.
|
|
147
148
|
|
|
@@ -151,7 +152,7 @@ That's a mouthful, so let's unpack what it means.
|
|
|
151
152
|
|
|
152
153
|
data from the request payload using a Server Request Parser.
|
|
153
154
|
|
|
154
|
-
import
|
|
155
|
+
import BackendTask exposing (BackendTask)
|
|
155
156
|
import RouteBuilder exposing (StatelessRoute)
|
|
156
157
|
import Server.Request as Request exposing (Request)
|
|
157
158
|
import Server.Response as Response exposing (Response)
|
|
@@ -161,11 +162,11 @@ data from the request payload using a Server Request Parser.
|
|
|
161
162
|
|
|
162
163
|
data :
|
|
163
164
|
RouteParams
|
|
164
|
-
-> Request.Parser (
|
|
165
|
+
-> Request.Parser (BackendTask (Response Data))
|
|
165
166
|
data routeParams =
|
|
166
167
|
{}
|
|
167
168
|
|> Server.Response.render
|
|
168
|
-
|>
|
|
169
|
+
|> BackendTask.succeed
|
|
169
170
|
|> Request.succeed
|
|
170
171
|
|
|
171
172
|
route : StatelessRoute RouteParams Data ActionData
|
|
@@ -225,7 +226,7 @@ succeed value =
|
|
|
225
226
|
|
|
226
227
|
{-| TODO internal only
|
|
227
228
|
-}
|
|
228
|
-
getDecoder : Parser (
|
|
229
|
+
getDecoder : Parser (BackendTask error response) -> Json.Decode.Decoder (Result ( ValidationError, List ValidationError ) (BackendTask error response))
|
|
229
230
|
getDecoder (Internal.Request.Parser decoder) =
|
|
230
231
|
decoder
|
|
231
232
|
|> Json.Decode.map
|
|
@@ -650,7 +651,6 @@ expectQueryParam name =
|
|
|
650
651
|
maybeParamValue =
|
|
651
652
|
queryString
|
|
652
653
|
|> QueryParams.fromString
|
|
653
|
-
|> QueryParams.toDict
|
|
654
654
|
|> Dict.get name
|
|
655
655
|
|> Maybe.andThen List.head
|
|
656
656
|
in
|
|
@@ -689,7 +689,6 @@ findFirstQueryParam : String -> String -> Maybe String
|
|
|
689
689
|
findFirstQueryParam name queryString =
|
|
690
690
|
queryString
|
|
691
691
|
|> QueryParams.fromString
|
|
692
|
-
|> QueryParams.toDict
|
|
693
692
|
|> Dict.get name
|
|
694
693
|
|> Maybe.andThen List.head
|
|
695
694
|
|
|
@@ -704,7 +703,6 @@ queryParams =
|
|
|
704
703
|
|> Url.fromString
|
|
705
704
|
|> Maybe.andThen .query
|
|
706
705
|
|> Maybe.map QueryParams.fromString
|
|
707
|
-
|> Maybe.map QueryParams.toDict
|
|
708
706
|
|> Maybe.withDefault Dict.empty
|
|
709
707
|
)
|
|
710
708
|
|
|
@@ -881,8 +879,8 @@ fileField_ name =
|
|
|
881
879
|
|
|
882
880
|
{-| -}
|
|
883
881
|
formDataWithServerValidation :
|
|
884
|
-
Form.ServerForms error (
|
|
885
|
-
-> Parser (
|
|
882
|
+
Form.ServerForms error (BackendTask FatalError (Validation.Validation error combined kind constraints))
|
|
883
|
+
-> Parser (BackendTask FatalError (Result (Form.Response error) ( Form.Response error, combined )))
|
|
886
884
|
formDataWithServerValidation formParsers =
|
|
887
885
|
rawFormData
|
|
888
886
|
|> andThen
|
|
@@ -897,27 +895,25 @@ formDataWithServerValidation formParsers =
|
|
|
897
895
|
( Just decoded, Nothing ) ->
|
|
898
896
|
succeed
|
|
899
897
|
(decoded
|
|
900
|
-
|>
|
|
898
|
+
|> BackendTask.map
|
|
901
899
|
(\(Validation _ _ ( maybeParsed, errors2 )) ->
|
|
902
900
|
case ( maybeParsed, errors2 |> Dict.toList |> List.filter (\( _, value ) -> value |> List.isEmpty |> not) |> List.NonEmpty.fromList ) of
|
|
903
901
|
( Just decodedFinal, Nothing ) ->
|
|
904
902
|
Ok
|
|
905
|
-
( Form.Response
|
|
903
|
+
( Pages.Internal.Form.Response
|
|
906
904
|
{ fields = rawFormData_
|
|
907
905
|
, errors = Dict.empty
|
|
906
|
+
, clientErrors = Dict.empty
|
|
908
907
|
}
|
|
909
908
|
, decodedFinal
|
|
910
909
|
)
|
|
911
910
|
|
|
912
|
-
|
|
911
|
+
_ ->
|
|
913
912
|
Err
|
|
914
|
-
(Form.Response
|
|
913
|
+
(Pages.Internal.Form.Response
|
|
915
914
|
{ fields = rawFormData_
|
|
916
|
-
, errors =
|
|
917
|
-
|
|
918
|
-
|> Maybe.map List.NonEmpty.toList
|
|
919
|
-
|> Maybe.withDefault []
|
|
920
|
-
|> Dict.fromList
|
|
915
|
+
, errors = errors2
|
|
916
|
+
, clientErrors = errors
|
|
921
917
|
}
|
|
922
918
|
)
|
|
923
919
|
)
|
|
@@ -925,16 +921,17 @@ formDataWithServerValidation formParsers =
|
|
|
925
921
|
|
|
926
922
|
( _, maybeErrors ) ->
|
|
927
923
|
Err
|
|
928
|
-
(Form.Response
|
|
924
|
+
(Pages.Internal.Form.Response
|
|
929
925
|
{ fields = rawFormData_
|
|
930
926
|
, errors =
|
|
931
927
|
maybeErrors
|
|
932
928
|
|> Maybe.map List.NonEmpty.toList
|
|
933
929
|
|> Maybe.withDefault []
|
|
934
930
|
|> Dict.fromList
|
|
931
|
+
, clientErrors = Dict.empty
|
|
935
932
|
}
|
|
936
933
|
)
|
|
937
|
-
|>
|
|
934
|
+
|> BackendTask.succeed
|
|
938
935
|
|> succeed
|
|
939
936
|
)
|
|
940
937
|
|
|
@@ -942,7 +939,7 @@ formDataWithServerValidation formParsers =
|
|
|
942
939
|
{-| -}
|
|
943
940
|
formData :
|
|
944
941
|
Form.ServerForms error combined
|
|
945
|
-
-> Parser (Result { fields : List ( String, String ), errors : Dict String (List error) } combined)
|
|
942
|
+
-> Parser ( Form.Response error, Result { fields : List ( String, String ), errors : Dict String (List error), clientErrors : Dict String (List error) } combined )
|
|
946
943
|
formData formParsers =
|
|
947
944
|
rawFormData
|
|
948
945
|
|> andThen
|
|
@@ -955,18 +952,27 @@ formData formParsers =
|
|
|
955
952
|
in
|
|
956
953
|
case ( maybeDecoded, errors |> Dict.toList |> List.filter (\( _, value ) -> value |> List.isEmpty |> not) |> List.NonEmpty.fromList ) of
|
|
957
954
|
( Just decoded, Nothing ) ->
|
|
958
|
-
|
|
955
|
+
( Pages.Internal.Form.Response { fields = [], errors = Dict.empty, clientErrors = Dict.empty }
|
|
956
|
+
, Ok decoded
|
|
957
|
+
)
|
|
959
958
|
|> succeed
|
|
960
959
|
|
|
961
960
|
( _, maybeErrors ) ->
|
|
962
|
-
|
|
963
|
-
{ fields
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
961
|
+
let
|
|
962
|
+
record : { fields : List ( String, String ), errors : Dict String (List error), clientErrors : Dict String (List error) }
|
|
963
|
+
record =
|
|
964
|
+
{ fields = rawFormData_
|
|
965
|
+
, errors = Dict.empty
|
|
966
|
+
, clientErrors =
|
|
967
|
+
maybeErrors
|
|
968
|
+
|> Maybe.map List.NonEmpty.toList
|
|
969
|
+
|> Maybe.withDefault []
|
|
970
|
+
|> Dict.fromList
|
|
971
|
+
}
|
|
972
|
+
in
|
|
973
|
+
( Pages.Internal.Form.Response record
|
|
974
|
+
, Err record
|
|
975
|
+
)
|
|
970
976
|
|> succeed
|
|
971
977
|
)
|
|
972
978
|
|
package/src/Server/Session.elm
CHANGED
|
@@ -13,13 +13,13 @@ to choose which requests to respond to and how to extract structured data from t
|
|
|
13
13
|
Using these functions, you can store and read session data in cookies to maintain state between requests.
|
|
14
14
|
For example, TODO:
|
|
15
15
|
|
|
16
|
-
action : RouteParams -> Request.Parser (
|
|
16
|
+
action : RouteParams -> Request.Parser (BackendTask (Response ActionData ErrorPage))
|
|
17
17
|
action routeParams =
|
|
18
18
|
MySession.withSession
|
|
19
19
|
(Request.formDataWithServerValidation (form |> Form.initCombinedServer identity))
|
|
20
20
|
(\nameResultData session ->
|
|
21
21
|
nameResultData
|
|
22
|
-
|>
|
|
22
|
+
|> BackendTask.map
|
|
23
23
|
(\nameResult ->
|
|
24
24
|
case nameResult of
|
|
25
25
|
Err errors ->
|
|
@@ -42,7 +42,7 @@ For example, TODO:
|
|
|
42
42
|
)
|
|
43
43
|
)
|
|
44
44
|
|
|
45
|
-
The elm-pages framework will manage signing these cookies using the `secrets :
|
|
45
|
+
The elm-pages framework will manage signing these cookies using the `secrets : BackendTask (List String)` you pass in.
|
|
46
46
|
That means that the values you set in your session will be directly visible to anyone who has access to the cookie
|
|
47
47
|
(so don't directly store sensitive data in your session). Since the session cookie is signed using the secret you provide,
|
|
48
48
|
the cookie will be invalidated if it is tampered with because it won't match when elm-pages verifies that it has been
|
|
@@ -51,13 +51,13 @@ signed with your secrets. Of course you need to provide secure secrets and treat
|
|
|
51
51
|
|
|
52
52
|
### Rotating Secrets
|
|
53
53
|
|
|
54
|
-
The first String in `secrets :
|
|
54
|
+
The first String in `secrets : BackendTask (List String)` will be used to sign sessions, while the remaining String's will
|
|
55
55
|
still be used to attempt to "unsign" the cookies. So if you have a single secret:
|
|
56
56
|
|
|
57
57
|
Session.withSession
|
|
58
58
|
{ name = "mysession"
|
|
59
59
|
, secrets =
|
|
60
|
-
|
|
60
|
+
BackendTask.map List.singleton
|
|
61
61
|
(Env.expect "SESSION_SECRET2022-09-01")
|
|
62
62
|
, options = cookieOptions
|
|
63
63
|
}
|
|
@@ -67,7 +67,7 @@ Then you add a second secret
|
|
|
67
67
|
Session.withSession
|
|
68
68
|
{ name = "mysession"
|
|
69
69
|
, secrets =
|
|
70
|
-
|
|
70
|
+
BackendTask.map2
|
|
71
71
|
(\newSecret oldSecret -> [ newSecret, oldSecret ])
|
|
72
72
|
(Env.expect "SESSION_SECRET2022-12-01")
|
|
73
73
|
(Env.expect "SESSION_SECRET2022-09-01")
|
|
@@ -87,7 +87,7 @@ it will invalidate all cookies signed with that. For example, if we remove our o
|
|
|
87
87
|
Session.withSession
|
|
88
88
|
{ name = "mysession"
|
|
89
89
|
, secrets =
|
|
90
|
-
|
|
90
|
+
BackendTask.map List.singleton
|
|
91
91
|
(Env.expect "SESSION_SECRET2022-12-01")
|
|
92
92
|
, options = cookieOptions
|
|
93
93
|
}
|
|
@@ -107,9 +107,9 @@ so there's nothing wrong with an old session expiring (and the browser will even
|
|
|
107
107
|
|
|
108
108
|
-}
|
|
109
109
|
|
|
110
|
-
import
|
|
111
|
-
import
|
|
112
|
-
import
|
|
110
|
+
import BackendTask exposing (BackendTask)
|
|
111
|
+
import BackendTask.Http
|
|
112
|
+
import BackendTask.Internal.Request
|
|
113
113
|
import Dict exposing (Dict)
|
|
114
114
|
import Json.Decode
|
|
115
115
|
import Json.Encode
|
|
@@ -242,23 +242,23 @@ flashPrefix =
|
|
|
242
242
|
{-| -}
|
|
243
243
|
withSession :
|
|
244
244
|
{ name : String
|
|
245
|
-
, secrets :
|
|
245
|
+
, secrets : BackendTask error (List String)
|
|
246
246
|
, options : SetCookie.Options
|
|
247
247
|
}
|
|
248
|
-
-> (request -> Result NotLoadedReason Session ->
|
|
248
|
+
-> (request -> Result NotLoadedReason Session -> BackendTask error ( Session, Response data errorPage ))
|
|
249
249
|
-> Server.Request.Parser request
|
|
250
|
-
-> Server.Request.Parser (
|
|
250
|
+
-> Server.Request.Parser (BackendTask error (Response data errorPage))
|
|
251
251
|
withSession config toRequest userRequest =
|
|
252
252
|
Server.Request.map2
|
|
253
253
|
(\maybeSessionCookie userRequestData ->
|
|
254
254
|
let
|
|
255
|
-
unsigned :
|
|
255
|
+
unsigned : BackendTask error (Result NotLoadedReason Session)
|
|
256
256
|
unsigned =
|
|
257
257
|
case maybeSessionCookie of
|
|
258
258
|
Just sessionCookie ->
|
|
259
259
|
sessionCookie
|
|
260
260
|
|> unsignCookie config
|
|
261
|
-
|>
|
|
261
|
+
|> BackendTask.map
|
|
262
262
|
(\unsignResult ->
|
|
263
263
|
case unsignResult of
|
|
264
264
|
Ok decoded ->
|
|
@@ -270,10 +270,10 @@ withSession config toRequest userRequest =
|
|
|
270
270
|
|
|
271
271
|
Nothing ->
|
|
272
272
|
Err NoSessionCookie
|
|
273
|
-
|>
|
|
273
|
+
|> BackendTask.succeed
|
|
274
274
|
in
|
|
275
275
|
unsigned
|
|
276
|
-
|>
|
|
276
|
+
|> BackendTask.andThen
|
|
277
277
|
(encodeSessionUpdate config toRequest userRequestData)
|
|
278
278
|
)
|
|
279
279
|
(Server.Request.cookie config.name)
|
|
@@ -282,19 +282,19 @@ withSession config toRequest userRequest =
|
|
|
282
282
|
|
|
283
283
|
encodeSessionUpdate :
|
|
284
284
|
{ name : String
|
|
285
|
-
, secrets :
|
|
285
|
+
, secrets : BackendTask error (List String)
|
|
286
286
|
, options : SetCookie.Options
|
|
287
287
|
}
|
|
288
|
-
-> (c -> d ->
|
|
288
|
+
-> (c -> d -> BackendTask error ( Session, Response data errorPage ))
|
|
289
289
|
-> c
|
|
290
290
|
-> d
|
|
291
|
-
->
|
|
291
|
+
-> BackendTask error (Response data errorPage)
|
|
292
292
|
encodeSessionUpdate config toRequest userRequestData sessionResult =
|
|
293
293
|
sessionResult
|
|
294
294
|
|> toRequest userRequestData
|
|
295
|
-
|>
|
|
295
|
+
|> BackendTask.andThen
|
|
296
296
|
(\( sessionUpdate, response ) ->
|
|
297
|
-
|
|
297
|
+
BackendTask.map
|
|
298
298
|
(\encoded ->
|
|
299
299
|
response
|
|
300
300
|
|> Server.Response.withSetCookieHeader
|
|
@@ -306,11 +306,11 @@ encodeSessionUpdate config toRequest userRequestData sessionResult =
|
|
|
306
306
|
)
|
|
307
307
|
|
|
308
308
|
|
|
309
|
-
unsignCookie : { a | secrets :
|
|
309
|
+
unsignCookie : { a | secrets : BackendTask error (List String) } -> String -> BackendTask error (Result () Session)
|
|
310
310
|
unsignCookie config sessionCookie =
|
|
311
311
|
sessionCookie
|
|
312
312
|
|> unsign config.secrets (Json.Decode.dict Json.Decode.string)
|
|
313
|
-
|>
|
|
313
|
+
|> BackendTask.map
|
|
314
314
|
(Result.map
|
|
315
315
|
(\dict ->
|
|
316
316
|
dict
|
|
@@ -331,15 +331,15 @@ unsignCookie config sessionCookie =
|
|
|
331
331
|
)
|
|
332
332
|
|
|
333
333
|
|
|
334
|
-
sign :
|
|
334
|
+
sign : BackendTask error (List String) -> Json.Encode.Value -> BackendTask error String
|
|
335
335
|
sign getSecrets input =
|
|
336
336
|
getSecrets
|
|
337
|
-
|>
|
|
337
|
+
|> BackendTask.andThen
|
|
338
338
|
(\secrets ->
|
|
339
|
-
|
|
339
|
+
BackendTask.Internal.Request.request
|
|
340
340
|
{ name = "encrypt"
|
|
341
341
|
, body =
|
|
342
|
-
|
|
342
|
+
BackendTask.Http.jsonBody
|
|
343
343
|
(Json.Encode.object
|
|
344
344
|
[ ( "values", input )
|
|
345
345
|
, ( "secret"
|
|
@@ -353,21 +353,21 @@ sign getSecrets input =
|
|
|
353
353
|
]
|
|
354
354
|
)
|
|
355
355
|
, expect =
|
|
356
|
-
|
|
356
|
+
BackendTask.Http.expectJson
|
|
357
357
|
Json.Decode.string
|
|
358
358
|
}
|
|
359
359
|
)
|
|
360
360
|
|
|
361
361
|
|
|
362
|
-
unsign :
|
|
362
|
+
unsign : BackendTask error (List String) -> Json.Decode.Decoder a -> String -> BackendTask error (Result () a)
|
|
363
363
|
unsign getSecrets decoder input =
|
|
364
364
|
getSecrets
|
|
365
|
-
|>
|
|
365
|
+
|> BackendTask.andThen
|
|
366
366
|
(\secrets ->
|
|
367
|
-
|
|
367
|
+
BackendTask.Internal.Request.request
|
|
368
368
|
{ name = "decrypt"
|
|
369
369
|
, body =
|
|
370
|
-
|
|
370
|
+
BackendTask.Http.jsonBody
|
|
371
371
|
(Json.Encode.object
|
|
372
372
|
[ ( "input", Json.Encode.string input )
|
|
373
373
|
, ( "secrets", Json.Encode.list Json.Encode.string secrets )
|
|
@@ -377,6 +377,6 @@ unsign getSecrets decoder input =
|
|
|
377
377
|
decoder
|
|
378
378
|
|> Json.Decode.nullable
|
|
379
379
|
|> Json.Decode.map (Result.fromMaybe ())
|
|
380
|
-
|>
|
|
380
|
+
|> BackendTask.Http.expectJson
|
|
381
381
|
}
|
|
382
382
|
)
|
package/src/Server/SetCookie.elm
CHANGED
|
@@ -174,7 +174,7 @@ dynamically). In this API you opt into exposing a cookie you set to JavaScript t
|
|
|
174
174
|
|
|
175
175
|
In general if you can accomplish your goal using HttpOnly cookies (i.e. not using `makeVisibleToJavaScript`) then
|
|
176
176
|
it's a good practice. With server-rendered `elm-pages` applications you can often manage your session state by pulling
|
|
177
|
-
in session data from cookies in a `
|
|
177
|
+
in session data from cookies in a `BackendTask` (which is resolved server-side before it ever reaches the browser).
|
|
178
178
|
|
|
179
179
|
-}
|
|
180
180
|
makeVisibleToJavaScript : Options -> Options
|
|
@@ -130,17 +130,16 @@ nodeRecordToString options { tag, children, facts } =
|
|
|
130
130
|
|> String.join " "
|
|
131
131
|
|> Just
|
|
132
132
|
|
|
133
|
-
boolToString b =
|
|
134
|
-
case b of
|
|
135
|
-
True ->
|
|
136
|
-
"True"
|
|
137
|
-
|
|
138
|
-
False ->
|
|
139
|
-
"False"
|
|
140
|
-
|
|
141
133
|
boolAttributes =
|
|
142
134
|
Dict.toList facts.boolAttributes
|
|
143
|
-
|> List.
|
|
135
|
+
|> List.filterMap
|
|
136
|
+
(\( k, v ) ->
|
|
137
|
+
if v then
|
|
138
|
+
Just k
|
|
139
|
+
|
|
140
|
+
else
|
|
141
|
+
Nothing
|
|
142
|
+
)
|
|
144
143
|
|> String.join " "
|
|
145
144
|
|> Just
|
|
146
145
|
in
|
package/src/DataSource/Env.elm
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
module DataSource.Env exposing (get, expect)
|
|
2
|
-
|
|
3
|
-
{-|
|
|
4
|
-
|
|
5
|
-
@docs get, expect
|
|
6
|
-
|
|
7
|
-
-}
|
|
8
|
-
|
|
9
|
-
import DataSource exposing (DataSource)
|
|
10
|
-
import DataSource.Http
|
|
11
|
-
import DataSource.Internal.Request
|
|
12
|
-
import Json.Decode as Decode
|
|
13
|
-
import Json.Encode as Encode
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
{-| -}
|
|
17
|
-
get : String -> DataSource (Maybe String)
|
|
18
|
-
get envVariableName =
|
|
19
|
-
DataSource.Internal.Request.request
|
|
20
|
-
{ name = "env"
|
|
21
|
-
, body = DataSource.Http.jsonBody (Encode.string envVariableName)
|
|
22
|
-
, expect =
|
|
23
|
-
DataSource.Http.expectJson
|
|
24
|
-
(Decode.nullable Decode.string)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
{-| -}
|
|
29
|
-
expect : String -> DataSource String
|
|
30
|
-
expect envVariableName =
|
|
31
|
-
envVariableName
|
|
32
|
-
|> get
|
|
33
|
-
|> DataSource.andThen
|
|
34
|
-
(\maybeValue ->
|
|
35
|
-
maybeValue
|
|
36
|
-
|> Result.fromMaybe ("DataSource.Env.expect was expecting a variable `" ++ envVariableName ++ "` but couldn't find a variable with that name.")
|
|
37
|
-
|> DataSource.fromResult
|
|
38
|
-
)
|