elm-pages 3.0.0-beta.4 → 3.0.0-beta.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/README.md +10 -1
  2. package/adapter/netlify.js +207 -0
  3. package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2828 -2933
  4. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
  5. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
  6. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
  7. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  8. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  9. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  10. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -1
  11. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1447 -342
  12. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +17004 -13817
  13. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  14. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
  15. package/generator/dead-code-review/elm.json +9 -7
  16. package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +59 -10
  17. package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +52 -36
  18. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
  19. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
  20. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
  21. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
  22. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  23. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  24. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  25. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
  26. package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1447 -342
  27. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25025 -21739
  28. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  29. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
  30. package/generator/review/elm.json +10 -10
  31. package/generator/src/RouteBuilder.elm +121 -114
  32. package/generator/src/SharedTemplate.elm +8 -7
  33. package/generator/src/SiteConfig.elm +3 -2
  34. package/generator/src/basepath-middleware.js +3 -3
  35. package/generator/src/build.js +209 -92
  36. package/generator/src/cli.js +292 -88
  37. package/generator/src/codegen.js +29 -27
  38. package/generator/src/compatibility-key.js +3 -0
  39. package/generator/src/compile-elm.js +43 -26
  40. package/generator/src/config.js +39 -0
  41. package/generator/src/copy-dir.js +2 -2
  42. package/generator/src/dev-server.js +176 -138
  43. package/generator/src/dir-helpers.js +9 -26
  44. package/generator/src/elm-codegen.js +5 -4
  45. package/generator/src/elm-file-constants.js +2 -3
  46. package/generator/src/error-formatter.js +12 -11
  47. package/generator/src/file-helpers.js +3 -4
  48. package/generator/src/generate-template-module-connector.js +23 -23
  49. package/generator/src/init.js +9 -8
  50. package/generator/src/pre-render-html.js +39 -28
  51. package/generator/src/render-test.js +109 -0
  52. package/generator/src/render-worker.js +25 -28
  53. package/generator/src/render.js +321 -142
  54. package/generator/src/request-cache.js +265 -162
  55. package/generator/src/resolve-elm-module.js +64 -0
  56. package/generator/src/rewrite-client-elm-json.js +6 -5
  57. package/generator/src/rewrite-elm-json-help.js +56 -0
  58. package/generator/src/rewrite-elm-json.js +17 -7
  59. package/generator/src/route-codegen-helpers.js +16 -31
  60. package/generator/src/seo-renderer.js +12 -7
  61. package/generator/src/vite-utils.js +77 -0
  62. package/generator/static-code/elm-pages.js +10 -0
  63. package/generator/static-code/hmr.js +79 -13
  64. package/generator/template/app/Api.elm +6 -5
  65. package/generator/template/app/Effect.elm +123 -0
  66. package/generator/template/app/ErrorPage.elm +37 -6
  67. package/generator/template/app/Route/Index.elm +17 -10
  68. package/generator/template/app/Shared.elm +24 -47
  69. package/generator/template/app/Site.elm +19 -6
  70. package/generator/template/app/View.elm +1 -8
  71. package/generator/template/elm-tooling.json +0 -3
  72. package/generator/template/elm.json +32 -24
  73. package/generator/template/package.json +10 -4
  74. package/package.json +30 -27
  75. package/src/ApiRoute.elm +199 -61
  76. package/src/BackendTask/Custom.elm +325 -0
  77. package/src/BackendTask/Env.elm +90 -0
  78. package/src/{DataSource → BackendTask}/File.elm +171 -56
  79. package/src/{DataSource → BackendTask}/Glob.elm +136 -125
  80. package/src/BackendTask/Http.elm +679 -0
  81. package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
  82. package/src/BackendTask/Internal/Request.elm +69 -0
  83. package/src/BackendTask/Random.elm +79 -0
  84. package/src/BackendTask/Time.elm +47 -0
  85. package/src/BackendTask.elm +531 -0
  86. package/src/FatalError.elm +90 -0
  87. package/src/Head/Seo.elm +4 -4
  88. package/src/Head.elm +237 -7
  89. package/src/HtmlPrinter.elm +7 -3
  90. package/src/Internal/ApiRoute.elm +7 -5
  91. package/src/PageServerResponse.elm +6 -1
  92. package/src/Pages/ConcurrentSubmission.elm +127 -0
  93. package/src/Pages/Form.elm +340 -0
  94. package/src/Pages/FormData.elm +18 -0
  95. package/src/Pages/GeneratorProgramConfig.elm +15 -0
  96. package/src/Pages/Internal/FatalError.elm +5 -0
  97. package/src/Pages/Internal/Msg.elm +93 -0
  98. package/src/Pages/Internal/NotFoundReason.elm +4 -4
  99. package/src/Pages/Internal/Platform/Cli.elm +617 -768
  100. package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
  101. package/src/Pages/Internal/Platform/Effect.elm +1 -2
  102. package/src/Pages/Internal/Platform/GeneratorApplication.elm +379 -0
  103. package/src/Pages/Internal/Platform/StaticResponses.elm +65 -276
  104. package/src/Pages/Internal/Platform/ToJsPayload.elm +6 -9
  105. package/src/Pages/Internal/Platform.elm +359 -225
  106. package/src/Pages/Internal/ResponseSketch.elm +2 -2
  107. package/src/Pages/Internal/Script.elm +17 -0
  108. package/src/Pages/Internal/StaticHttpBody.elm +35 -1
  109. package/src/Pages/Manifest.elm +52 -11
  110. package/src/Pages/Navigation.elm +87 -0
  111. package/src/Pages/PageUrl.elm +26 -12
  112. package/src/Pages/ProgramConfig.elm +35 -23
  113. package/src/Pages/Script.elm +166 -0
  114. package/src/Pages/SiteConfig.elm +3 -2
  115. package/src/Pages/StaticHttp/Request.elm +2 -2
  116. package/src/Pages/StaticHttpRequest.elm +23 -99
  117. package/src/Pages/Url.elm +3 -3
  118. package/src/PagesMsg.elm +88 -0
  119. package/src/QueryParams.elm +21 -172
  120. package/src/RenderRequest.elm +7 -7
  121. package/src/RequestsAndPending.elm +37 -20
  122. package/src/Result/Extra.elm +26 -0
  123. package/src/Scaffold/Form.elm +569 -0
  124. package/src/Scaffold/Route.elm +1411 -0
  125. package/src/Server/Request.elm +74 -72
  126. package/src/Server/Session.elm +62 -42
  127. package/src/Server/SetCookie.elm +80 -32
  128. package/src/Stub.elm +53 -0
  129. package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
  130. package/src/{Path.elm → UrlPath.elm} +33 -36
  131. package/src/DataSource/Env.elm +0 -38
  132. package/src/DataSource/Http.elm +0 -446
  133. package/src/DataSource/Internal/Request.elm +0 -20
  134. package/src/DataSource/Port.elm +0 -90
  135. package/src/DataSource.elm +0 -538
  136. package/src/Form/Field.elm +0 -717
  137. package/src/Form/FieldStatus.elm +0 -36
  138. package/src/Form/FieldView.elm +0 -417
  139. package/src/Form/FormData.elm +0 -22
  140. package/src/Form/Validation.elm +0 -391
  141. package/src/Form/Value.elm +0 -118
  142. package/src/Form.elm +0 -1683
  143. package/src/FormDecoder.elm +0 -102
  144. package/src/Pages/FormState.elm +0 -256
  145. package/src/Pages/Generate.elm +0 -800
  146. package/src/Pages/Internal/Form.elm +0 -17
  147. package/src/Pages/Msg.elm +0 -79
  148. package/src/Pages/Transition.elm +0 -70
@@ -86,17 +86,19 @@ 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 exposing (Validation)
94
+ import Form.Handler
95
+ import Form.Validation as Validation
94
96
  import FormData
95
97
  import Internal.Request
96
98
  import Json.Decode
97
99
  import Json.Encode
98
100
  import List.NonEmpty
99
- import Pages.Internal.Form exposing (Validation(..))
101
+ import Pages.Form
100
102
  import QueryParams
101
103
  import Time
102
104
  import Url
@@ -118,17 +120,17 @@ Note that this data is not available for pre-rendered pages or pre-rendered API
118
120
  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
121
  requests the page and then the pre-rendered page is served as a plain file (without running your Route Module).
120
122
 
121
- That's why `RouteBuilder.preRender` has `data : RouteParams -> DataSource Data`:
123
+ That's why `RouteBuilder.preRender` has `data : RouteParams -> BackendTask Data`:
122
124
 
123
- import DataSource exposing (DataSource)
125
+ import BackendTask exposing (BackendTask)
124
126
  import RouteBuilder exposing (StatelessRoute)
125
127
 
126
128
  type alias Data =
127
129
  {}
128
130
 
129
- data : RouteParams -> DataSource Data
131
+ data : RouteParams -> BackendTask Data
130
132
  data routeParams =
131
- DataSource.succeed Data
133
+ BackendTask.succeed Data
132
134
 
133
135
  route : StatelessRoute RouteParams Data ActionData
134
136
  route =
@@ -141,7 +143,7 @@ That's why `RouteBuilder.preRender` has `data : RouteParams -> DataSource Data`:
141
143
 
142
144
  A server-rendered Route Module _does_ have access to a user's incoming HTTP request because it runs every time the page
143
145
  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 (DataSource (Response Data))`. That means that you
146
+ `RouteBuilder.serverRender` has `data : RouteParams -> Request.Parser (BackendTask (Response Data))`. That means that you
145
147
  can use the incoming HTTP request data to choose how to respond. For example, you could check for a dark-mode preference
146
148
  cookie and render a light- or dark-themed page and render a different page.
147
149
 
@@ -151,7 +153,7 @@ That's a mouthful, so let's unpack what it means.
151
153
 
152
154
  data from the request payload using a Server Request Parser.
153
155
 
154
- import DataSource exposing (DataSource)
156
+ import BackendTask exposing (BackendTask)
155
157
  import RouteBuilder exposing (StatelessRoute)
156
158
  import Server.Request as Request exposing (Request)
157
159
  import Server.Response as Response exposing (Response)
@@ -161,11 +163,11 @@ data from the request payload using a Server Request Parser.
161
163
 
162
164
  data :
163
165
  RouteParams
164
- -> Request.Parser (DataSource (Response Data))
166
+ -> Request.Parser (BackendTask (Response Data))
165
167
  data routeParams =
166
168
  {}
167
169
  |> Server.Response.render
168
- |> DataSource.succeed
170
+ |> BackendTask.succeed
169
171
  |> Request.succeed
170
172
 
171
173
  route : StatelessRoute RouteParams Data ActionData
@@ -225,7 +227,7 @@ succeed value =
225
227
 
226
228
  {-| TODO internal only
227
229
  -}
228
- getDecoder : Parser (DataSource response) -> Json.Decode.Decoder (Result ( ValidationError, List ValidationError ) (DataSource response))
230
+ getDecoder : Parser (BackendTask error response) -> Json.Decode.Decoder (Result ( ValidationError, List ValidationError ) (BackendTask error response))
229
231
  getDecoder (Internal.Request.Parser decoder) =
230
232
  decoder
231
233
  |> Json.Decode.map
@@ -650,7 +652,6 @@ expectQueryParam name =
650
652
  maybeParamValue =
651
653
  queryString
652
654
  |> QueryParams.fromString
653
- |> QueryParams.toDict
654
655
  |> Dict.get name
655
656
  |> Maybe.andThen List.head
656
657
  in
@@ -689,7 +690,6 @@ findFirstQueryParam : String -> String -> Maybe String
689
690
  findFirstQueryParam name queryString =
690
691
  queryString
691
692
  |> QueryParams.fromString
692
- |> QueryParams.toDict
693
693
  |> Dict.get name
694
694
  |> Maybe.andThen List.head
695
695
 
@@ -704,7 +704,6 @@ queryParams =
704
704
  |> Url.fromString
705
705
  |> Maybe.andThen .query
706
706
  |> Maybe.map QueryParams.fromString
707
- |> Maybe.map QueryParams.toDict
708
707
  |> Maybe.withDefault Dict.empty
709
708
  )
710
709
 
@@ -879,94 +878,97 @@ fileField_ name =
879
878
  |> Internal.Request.Parser
880
879
 
881
880
 
881
+ runForm : Validation.Validation error parsed kind constraints -> Form.Validated error parsed
882
+ runForm validation =
883
+ Form.Handler.run []
884
+ (Form.Handler.init identity
885
+ (Form.form
886
+ { combine = validation
887
+ , view = []
888
+ }
889
+ )
890
+ )
891
+
892
+
882
893
  {-| -}
883
894
  formDataWithServerValidation :
884
- Form.ServerForms error (DataSource (Validation error combined kind constraints))
885
- -> Parser (DataSource (Result (Form.Response error) ( Form.Response error, combined )))
895
+ Pages.Form.Handler error combined
896
+ -> Parser (BackendTask FatalError (Result (Form.ServerResponse error) ( Form.ServerResponse error, combined )))
886
897
  formDataWithServerValidation formParsers =
887
898
  rawFormData
888
899
  |> andThen
889
900
  (\rawFormData_ ->
890
- let
891
- ( maybeDecoded, errors ) =
892
- Form.runOneOfServerSide
893
- rawFormData_
894
- formParsers
895
- in
896
- case ( maybeDecoded, errors |> Dict.toList |> List.filter (\( _, value ) -> value |> List.isEmpty |> not) |> List.NonEmpty.fromList ) of
897
- ( Just decoded, Nothing ) ->
901
+ case Form.Handler.run rawFormData_ formParsers of
902
+ Form.Valid decoded ->
898
903
  succeed
899
904
  (decoded
900
- |> DataSource.map
901
- (\(Validation _ _ ( maybeParsed, errors2 )) ->
902
- case ( maybeParsed, errors2 |> Dict.toList |> List.filter (\( _, value ) -> value |> List.isEmpty |> not) |> List.NonEmpty.fromList ) of
903
- ( Just decodedFinal, Nothing ) ->
905
+ |> BackendTask.map
906
+ (\clientValidated ->
907
+ case runForm clientValidated of
908
+ Form.Valid decodedFinal ->
904
909
  Ok
905
- ( Form.Response
906
- { fields = rawFormData_
907
- , errors = Dict.empty
908
- }
910
+ ( { persisted =
911
+ { fields = Just rawFormData_
912
+ , clientSideErrors = Nothing
913
+ }
914
+ , serverSideErrors = Dict.empty
915
+ }
909
916
  , decodedFinal
910
917
  )
911
918
 
912
- ( _, maybeErrors ) ->
919
+ Form.Invalid _ errors2 ->
913
920
  Err
914
- (Form.Response
915
- { fields = rawFormData_
916
- , errors =
917
- maybeErrors
918
- |> Maybe.map List.NonEmpty.toList
919
- |> Maybe.withDefault []
920
- |> Dict.fromList
921
+ { persisted =
922
+ { fields = Just rawFormData_
923
+ , clientSideErrors = Just errors2
921
924
  }
922
- )
925
+ , serverSideErrors = Dict.empty
926
+ }
923
927
  )
924
928
  )
925
929
 
926
- ( _, maybeErrors ) ->
930
+ Form.Invalid _ errors ->
927
931
  Err
928
- (Form.Response
929
- { fields = rawFormData_
930
- , errors =
931
- maybeErrors
932
- |> Maybe.map List.NonEmpty.toList
933
- |> Maybe.withDefault []
934
- |> Dict.fromList
932
+ { persisted =
933
+ { fields = Just rawFormData_
934
+ , clientSideErrors = Just errors
935
935
  }
936
- )
937
- |> DataSource.succeed
936
+ , serverSideErrors = Dict.empty
937
+ }
938
+ |> BackendTask.succeed
938
939
  |> succeed
939
940
  )
940
941
 
941
942
 
942
943
  {-| -}
943
944
  formData :
944
- Form.ServerForms error combined
945
- -> Parser (Result { fields : List ( String, String ), errors : Dict String (List error) } combined)
945
+ Form.Handler.Handler error combined
946
+ -> Parser ( Form.ServerResponse error, Form.Validated error combined )
946
947
  formData formParsers =
947
948
  rawFormData
948
949
  |> andThen
949
950
  (\rawFormData_ ->
950
- let
951
- ( maybeDecoded, errors ) =
952
- Form.runOneOfServerSide
953
- rawFormData_
954
- formParsers
955
- in
956
- case ( maybeDecoded, errors |> Dict.toList |> List.filter (\( _, value ) -> value |> List.isEmpty |> not) |> List.NonEmpty.fromList ) of
957
- ( Just decoded, Nothing ) ->
958
- Ok decoded
951
+ case Form.Handler.run rawFormData_ formParsers of
952
+ (Form.Valid _) as validated ->
953
+ ( { persisted =
954
+ { fields = Just rawFormData_
955
+ , clientSideErrors = Just Dict.empty
956
+ }
957
+ , serverSideErrors = Dict.empty
958
+ }
959
+ , validated
960
+ )
959
961
  |> succeed
960
962
 
961
- ( _, maybeErrors ) ->
962
- Err
963
- { fields = rawFormData_
964
- , errors =
965
- maybeErrors
966
- |> Maybe.map List.NonEmpty.toList
967
- |> Maybe.withDefault []
968
- |> Dict.fromList
969
- }
963
+ (Form.Invalid _ maybeErrors) as validated ->
964
+ ( { persisted =
965
+ { fields = Just rawFormData_
966
+ , clientSideErrors = Just maybeErrors
967
+ }
968
+ , serverSideErrors = Dict.empty
969
+ }
970
+ , validated
971
+ )
970
972
  |> succeed
971
973
  )
972
974
 
@@ -1,5 +1,5 @@
1
1
  module Server.Session exposing
2
- ( withSession
2
+ ( withSession, withSessionResult
3
3
  , NotLoadedReason(..)
4
4
  , Session, empty, get, insert, remove, update, withFlash
5
5
  )
@@ -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 (DataSource (Response ActionData ErrorPage))
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
- |> DataSource.map
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 : DataSource (List String)` you pass in.
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,15 +51,15 @@ 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 : DataSource (List String)` will be used to sign sessions, while the remaining String's will
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
- DataSource.map List.singleton
60
+ BackendTask.map List.singleton
61
61
  (Env.expect "SESSION_SECRET2022-09-01")
62
- , options = cookieOptions
62
+ , options = Nothing
63
63
  }
64
64
 
65
65
  Then you add a second secret
@@ -67,11 +67,11 @@ Then you add a second secret
67
67
  Session.withSession
68
68
  { name = "mysession"
69
69
  , secrets =
70
- DataSource.map2
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")
74
- , options = cookieOptions
74
+ , options = Nothing
75
75
  }
76
76
 
77
77
  The new secret (`2022-12-01`) will be used to sign all requests. This API always re-signs using the newest secret in the list
@@ -87,16 +87,16 @@ 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
- DataSource.map List.singleton
90
+ BackendTask.map List.singleton
91
91
  (Env.expect "SESSION_SECRET2022-12-01")
92
- , options = cookieOptions
92
+ , options = Nothing
93
93
  }
94
94
 
95
95
  And then a user makes a request but had a session signed with our old secret (`2022-09-01`), the session will be invalid
96
96
  (so `withSession` would parse the session for that request as `Nothing`). It's standard for cookies to have an expiration date,
97
97
  so there's nothing wrong with an old session expiring (and the browser will eventually delete old cookies), just be aware of that when rotating secrets.
98
98
 
99
- @docs withSession
99
+ @docs withSession, withSessionResult
100
100
 
101
101
  @docs NotLoadedReason
102
102
 
@@ -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 DataSource exposing (DataSource)
111
- import DataSource.Http
112
- import DataSource.Internal.Request
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,43 @@ flashPrefix =
242
242
  {-| -}
243
243
  withSession :
244
244
  { name : String
245
- , secrets : DataSource (List String)
246
- , options : SetCookie.Options
245
+ , secrets : BackendTask error (List String)
246
+ , options : Maybe SetCookie.Options
247
247
  }
248
- -> (request -> Result NotLoadedReason Session -> DataSource ( Session, Response data errorPage ))
248
+ -> (request -> Session -> BackendTask error ( Session, Response data errorPage ))
249
249
  -> Server.Request.Parser request
250
- -> Server.Request.Parser (DataSource (Response data errorPage))
250
+ -> Server.Request.Parser (BackendTask error (Response data errorPage))
251
251
  withSession config toRequest userRequest =
252
+ withSessionResult config
253
+ (\request session ->
254
+ toRequest request
255
+ (session
256
+ |> Result.withDefault empty
257
+ )
258
+ )
259
+ userRequest
260
+
261
+
262
+ {-| -}
263
+ withSessionResult :
264
+ { name : String
265
+ , secrets : BackendTask error (List String)
266
+ , options : Maybe SetCookie.Options
267
+ }
268
+ -> (request -> Result NotLoadedReason Session -> BackendTask error ( Session, Response data errorPage ))
269
+ -> Server.Request.Parser request
270
+ -> Server.Request.Parser (BackendTask error (Response data errorPage))
271
+ withSessionResult config toRequest userRequest =
252
272
  Server.Request.map2
253
273
  (\maybeSessionCookie userRequestData ->
254
274
  let
255
- unsigned : DataSource (Result NotLoadedReason Session)
275
+ unsigned : BackendTask error (Result NotLoadedReason Session)
256
276
  unsigned =
257
277
  case maybeSessionCookie of
258
278
  Just sessionCookie ->
259
279
  sessionCookie
260
280
  |> unsignCookie config
261
- |> DataSource.map
281
+ |> BackendTask.map
262
282
  (\unsignResult ->
263
283
  case unsignResult of
264
284
  Ok decoded ->
@@ -270,10 +290,10 @@ withSession config toRequest userRequest =
270
290
 
271
291
  Nothing ->
272
292
  Err NoSessionCookie
273
- |> DataSource.succeed
293
+ |> BackendTask.succeed
274
294
  in
275
295
  unsigned
276
- |> DataSource.andThen
296
+ |> BackendTask.andThen
277
297
  (encodeSessionUpdate config toRequest userRequestData)
278
298
  )
279
299
  (Server.Request.cookie config.name)
@@ -282,23 +302,23 @@ withSession config toRequest userRequest =
282
302
 
283
303
  encodeSessionUpdate :
284
304
  { name : String
285
- , secrets : DataSource (List String)
286
- , options : SetCookie.Options
305
+ , secrets : BackendTask error (List String)
306
+ , options : Maybe SetCookie.Options
287
307
  }
288
- -> (c -> d -> DataSource ( Session, Response data errorPage ))
308
+ -> (c -> d -> BackendTask error ( Session, Response data errorPage ))
289
309
  -> c
290
310
  -> d
291
- -> DataSource (Response data errorPage)
311
+ -> BackendTask error (Response data errorPage)
292
312
  encodeSessionUpdate config toRequest userRequestData sessionResult =
293
313
  sessionResult
294
314
  |> toRequest userRequestData
295
- |> DataSource.andThen
315
+ |> BackendTask.andThen
296
316
  (\( sessionUpdate, response ) ->
297
- DataSource.map
317
+ BackendTask.map
298
318
  (\encoded ->
299
319
  response
300
320
  |> Server.Response.withSetCookieHeader
301
- (SetCookie.setCookie config.name encoded config.options)
321
+ (SetCookie.setCookie config.name encoded (config.options |> Maybe.withDefault SetCookie.options))
302
322
  )
303
323
  (sign config.secrets
304
324
  (encodeNonExpiringPairs sessionUpdate)
@@ -306,11 +326,11 @@ encodeSessionUpdate config toRequest userRequestData sessionResult =
306
326
  )
307
327
 
308
328
 
309
- unsignCookie : { a | secrets : DataSource (List String) } -> String -> DataSource (Result () Session)
329
+ unsignCookie : { a | secrets : BackendTask error (List String) } -> String -> BackendTask error (Result () Session)
310
330
  unsignCookie config sessionCookie =
311
331
  sessionCookie
312
332
  |> unsign config.secrets (Json.Decode.dict Json.Decode.string)
313
- |> DataSource.map
333
+ |> BackendTask.map
314
334
  (Result.map
315
335
  (\dict ->
316
336
  dict
@@ -331,15 +351,15 @@ unsignCookie config sessionCookie =
331
351
  )
332
352
 
333
353
 
334
- sign : DataSource (List String) -> Json.Encode.Value -> DataSource String
354
+ sign : BackendTask error (List String) -> Json.Encode.Value -> BackendTask error String
335
355
  sign getSecrets input =
336
356
  getSecrets
337
- |> DataSource.andThen
357
+ |> BackendTask.andThen
338
358
  (\secrets ->
339
- DataSource.Internal.Request.request
359
+ BackendTask.Internal.Request.request
340
360
  { name = "encrypt"
341
361
  , body =
342
- DataSource.Http.jsonBody
362
+ BackendTask.Http.jsonBody
343
363
  (Json.Encode.object
344
364
  [ ( "values", input )
345
365
  , ( "secret"
@@ -353,21 +373,21 @@ sign getSecrets input =
353
373
  ]
354
374
  )
355
375
  , expect =
356
- DataSource.Http.expectJson
376
+ BackendTask.Http.expectJson
357
377
  Json.Decode.string
358
378
  }
359
379
  )
360
380
 
361
381
 
362
- unsign : DataSource (List String) -> Json.Decode.Decoder a -> String -> DataSource (Result () a)
382
+ unsign : BackendTask error (List String) -> Json.Decode.Decoder a -> String -> BackendTask error (Result () a)
363
383
  unsign getSecrets decoder input =
364
384
  getSecrets
365
- |> DataSource.andThen
385
+ |> BackendTask.andThen
366
386
  (\secrets ->
367
- DataSource.Internal.Request.request
387
+ BackendTask.Internal.Request.request
368
388
  { name = "decrypt"
369
389
  , body =
370
- DataSource.Http.jsonBody
390
+ BackendTask.Http.jsonBody
371
391
  (Json.Encode.object
372
392
  [ ( "input", Json.Encode.string input )
373
393
  , ( "secrets", Json.Encode.list Json.Encode.string secrets )
@@ -377,6 +397,6 @@ unsign getSecrets decoder input =
377
397
  decoder
378
398
  |> Json.Decode.nullable
379
399
  |> Json.Decode.map (Result.fromMaybe ())
380
- |> DataSource.Http.expectJson
400
+ |> BackendTask.Http.expectJson
381
401
  }
382
402
  )