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

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 (140) 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} +2678 -2725
  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 +115 -109
  32. package/generator/src/SharedTemplate.elm +3 -2
  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 +537 -0
  86. package/src/FatalError.elm +90 -0
  87. package/src/Head.elm +237 -7
  88. package/src/HtmlPrinter.elm +7 -3
  89. package/src/Internal/ApiRoute.elm +7 -5
  90. package/src/PageServerResponse.elm +6 -1
  91. package/src/Pages/Form.elm +229 -0
  92. package/src/Pages/GeneratorProgramConfig.elm +15 -0
  93. package/src/Pages/Internal/FatalError.elm +5 -0
  94. package/src/Pages/Internal/Msg.elm +93 -0
  95. package/src/Pages/Internal/Platform/Cli.elm +612 -763
  96. package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
  97. package/src/Pages/Internal/Platform/Effect.elm +1 -2
  98. package/src/Pages/Internal/Platform/GeneratorApplication.elm +379 -0
  99. package/src/Pages/Internal/Platform/StaticResponses.elm +65 -276
  100. package/src/Pages/Internal/Platform/ToJsPayload.elm +6 -9
  101. package/src/Pages/Internal/Platform.elm +327 -194
  102. package/src/Pages/Internal/Script.elm +17 -0
  103. package/src/Pages/Internal/StaticHttpBody.elm +35 -1
  104. package/src/Pages/Manifest.elm +29 -4
  105. package/src/Pages/PageUrl.elm +23 -9
  106. package/src/Pages/ProgramConfig.elm +26 -15
  107. package/src/Pages/Script.elm +109 -0
  108. package/src/Pages/SiteConfig.elm +3 -2
  109. package/src/Pages/StaticHttp/Request.elm +2 -2
  110. package/src/Pages/StaticHttpRequest.elm +23 -99
  111. package/src/Pages/Transition.elm +12 -3
  112. package/src/PagesMsg.elm +82 -0
  113. package/src/Path.elm +16 -19
  114. package/src/QueryParams.elm +21 -172
  115. package/src/RequestsAndPending.elm +37 -20
  116. package/src/Result/Extra.elm +26 -0
  117. package/src/Scaffold/Form.elm +546 -0
  118. package/src/Scaffold/Route.elm +1402 -0
  119. package/src/Server/Request.elm +73 -72
  120. package/src/Server/Session.elm +62 -42
  121. package/src/Server/SetCookie.elm +12 -4
  122. package/src/Stub.elm +53 -0
  123. package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
  124. package/src/DataSource/Env.elm +0 -38
  125. package/src/DataSource/Http.elm +0 -446
  126. package/src/DataSource/Internal/Request.elm +0 -20
  127. package/src/DataSource/Port.elm +0 -90
  128. package/src/DataSource.elm +0 -538
  129. package/src/Form/Field.elm +0 -717
  130. package/src/Form/FieldStatus.elm +0 -36
  131. package/src/Form/FieldView.elm +0 -417
  132. package/src/Form/FormData.elm +0 -22
  133. package/src/Form/Validation.elm +0 -391
  134. package/src/Form/Value.elm +0 -118
  135. package/src/Form.elm +0 -1683
  136. package/src/FormDecoder.elm +0 -102
  137. package/src/Pages/FormState.elm +0 -256
  138. package/src/Pages/Generate.elm +0 -800
  139. package/src/Pages/Internal/Form.elm +0 -17
  140. package/src/Pages/Msg.elm +0 -79
@@ -86,17 +86,18 @@ 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(..))
100
101
  import QueryParams
101
102
  import Time
102
103
  import Url
@@ -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 -> DataSource Data`:
122
+ That's why `RouteBuilder.preRender` has `data : RouteParams -> BackendTask Data`:
122
123
 
123
- import DataSource exposing (DataSource)
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 -> DataSource Data
130
+ data : RouteParams -> BackendTask Data
130
131
  data routeParams =
131
- DataSource.succeed Data
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 (DataSource (Response Data))`. That means that you
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 DataSource exposing (DataSource)
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 (DataSource (Response Data))
165
+ -> Request.Parser (BackendTask (Response Data))
165
166
  data routeParams =
166
167
  {}
167
168
  |> Server.Response.render
168
- |> DataSource.succeed
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 (DataSource response) -> Json.Decode.Decoder (Result ( ValidationError, List ValidationError ) (DataSource response))
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
 
@@ -879,94 +877,97 @@ fileField_ name =
879
877
  |> Internal.Request.Parser
880
878
 
881
879
 
880
+ runForm : Validation.Validation error parsed kind constraints -> Form.Validated error parsed
881
+ runForm validation =
882
+ Form.Handler.run []
883
+ (Form.Handler.init identity
884
+ (Form.form
885
+ { combine = validation
886
+ , view = []
887
+ }
888
+ )
889
+ )
890
+
891
+
882
892
  {-| -}
883
893
  formDataWithServerValidation :
884
- Form.ServerForms error (DataSource (Validation error combined kind constraints))
885
- -> Parser (DataSource (Result (Form.Response error) ( Form.Response error, combined )))
894
+ Form.Handler.Handler error (BackendTask FatalError (Validation.Validation error combined kind constraints))
895
+ -> Parser (BackendTask FatalError (Result (Form.ServerResponse error) ( Form.ServerResponse error, combined )))
886
896
  formDataWithServerValidation formParsers =
887
897
  rawFormData
888
898
  |> andThen
889
899
  (\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 ) ->
900
+ case Form.Handler.run rawFormData_ formParsers of
901
+ Form.Valid decoded ->
898
902
  succeed
899
903
  (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 ) ->
904
+ |> BackendTask.map
905
+ (\clientValidated ->
906
+ case runForm clientValidated of
907
+ Form.Valid decodedFinal ->
904
908
  Ok
905
- ( Form.Response
906
- { fields = rawFormData_
907
- , errors = Dict.empty
908
- }
909
+ ( { persisted =
910
+ { fields = Just rawFormData_
911
+ , clientSideErrors = Nothing
912
+ }
913
+ , serverSideErrors = Dict.empty
914
+ }
909
915
  , decodedFinal
910
916
  )
911
917
 
912
- ( _, maybeErrors ) ->
918
+ Form.Invalid _ errors2 ->
913
919
  Err
914
- (Form.Response
915
- { fields = rawFormData_
916
- , errors =
917
- maybeErrors
918
- |> Maybe.map List.NonEmpty.toList
919
- |> Maybe.withDefault []
920
- |> Dict.fromList
920
+ { persisted =
921
+ { fields = Just rawFormData_
922
+ , clientSideErrors = Just errors2
921
923
  }
922
- )
924
+ , serverSideErrors = Dict.empty
925
+ }
923
926
  )
924
927
  )
925
928
 
926
- ( _, maybeErrors ) ->
929
+ Form.Invalid _ errors ->
927
930
  Err
928
- (Form.Response
929
- { fields = rawFormData_
930
- , errors =
931
- maybeErrors
932
- |> Maybe.map List.NonEmpty.toList
933
- |> Maybe.withDefault []
934
- |> Dict.fromList
931
+ { persisted =
932
+ { fields = Just rawFormData_
933
+ , clientSideErrors = Just errors
935
934
  }
936
- )
937
- |> DataSource.succeed
935
+ , serverSideErrors = Dict.empty
936
+ }
937
+ |> BackendTask.succeed
938
938
  |> succeed
939
939
  )
940
940
 
941
941
 
942
942
  {-| -}
943
943
  formData :
944
- Form.ServerForms error combined
945
- -> Parser (Result { fields : List ( String, String ), errors : Dict String (List error) } combined)
944
+ Form.Handler.Handler error combined
945
+ -> Parser ( Form.ServerResponse error, Form.Validated error combined )
946
946
  formData formParsers =
947
947
  rawFormData
948
948
  |> andThen
949
949
  (\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
950
+ case Form.Handler.run rawFormData_ formParsers of
951
+ (Form.Valid _) as validated ->
952
+ ( { persisted =
953
+ { fields = Just rawFormData_
954
+ , clientSideErrors = Just Dict.empty
955
+ }
956
+ , serverSideErrors = Dict.empty
957
+ }
958
+ , validated
959
+ )
959
960
  |> succeed
960
961
 
961
- ( _, maybeErrors ) ->
962
- Err
963
- { fields = rawFormData_
964
- , errors =
965
- maybeErrors
966
- |> Maybe.map List.NonEmpty.toList
967
- |> Maybe.withDefault []
968
- |> Dict.fromList
969
- }
962
+ (Form.Invalid _ maybeErrors) as validated ->
963
+ ( { persisted =
964
+ { fields = Just rawFormData_
965
+ , clientSideErrors = Just maybeErrors
966
+ }
967
+ , serverSideErrors = Dict.empty
968
+ }
969
+ , validated
970
+ )
970
971
  |> succeed
971
972
  )
972
973
 
@@ -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.initOptions))
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
  )
@@ -2,7 +2,7 @@ module Server.SetCookie exposing
2
2
  ( SetCookie
3
3
  , SameSite(..)
4
4
  , Options, initOptions
5
- , withImmediateExpiration, makeVisibleToJavaScript, nonSecure, setCookie, withDomain, withExpiration, withMaxAge, withPath, withSameSite
5
+ , withImmediateExpiration, makeVisibleToJavaScript, nonSecure, setCookie, withDomain, withExpiration, withMaxAge, withPath, withoutPath, withSameSite
6
6
  , toString
7
7
  )
8
8
 
@@ -29,7 +29,7 @@ You can learn more about the basics of cookies in the Web Platform in these help
29
29
 
30
30
  @docs Options, initOptions
31
31
 
32
- @docs withImmediateExpiration, makeVisibleToJavaScript, nonSecure, setCookie, withDomain, withExpiration, withMaxAge, withPath, withSameSite
32
+ @docs withImmediateExpiration, makeVisibleToJavaScript, nonSecure, setCookie, withDomain, withExpiration, withMaxAge, withPath, withoutPath, withSameSite
33
33
 
34
34
 
35
35
  ## Internal
@@ -143,7 +143,7 @@ initOptions =
143
143
  { expiration = Nothing
144
144
  , visibleToJavaScript = False
145
145
  , maxAge = Nothing
146
- , path = Nothing
146
+ , path = Just "/"
147
147
  , domain = Nothing
148
148
  , secure = True
149
149
  , sameSite = Nothing
@@ -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 `DataSource` (which is resolved server-side before it ever reaches the browser).
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
@@ -200,6 +200,14 @@ withPath path builder =
200
200
  }
201
201
 
202
202
 
203
+ {-| -}
204
+ withoutPath : Options -> Options
205
+ withoutPath builder =
206
+ { builder
207
+ | path = Nothing
208
+ }
209
+
210
+
203
211
  {-| -}
204
212
  withDomain : String -> Options -> Options
205
213
  withDomain domain builder =
package/src/Stub.elm ADDED
@@ -0,0 +1,53 @@
1
+ module Stub exposing (Id, Model, Task(..), map2, nextId)
2
+
3
+ import Json.Decode as Decode
4
+ import Set exposing (Set)
5
+
6
+
7
+ type alias Id =
8
+ Int
9
+
10
+
11
+ type alias Model =
12
+ { nextId : Id
13
+ , sentIds : Set Id
14
+ }
15
+
16
+
17
+
18
+ --task : Task error value
19
+ --task =
20
+ -- Pending
21
+ -- (\id -> id)
22
+ -- (\value model -> ( model, Done (Ok value) ))
23
+
24
+
25
+ type Task error value
26
+ = Pending (Id -> Id) (Decode.Value -> Model -> ( Model, Task error value ))
27
+
28
+
29
+ map2 : (value1 -> value2 -> combined) -> Task error value1 -> Task error value2 -> Task error combined
30
+ map2 mapFn task1 task2 =
31
+ case ( task1, task2 ) of
32
+ ( Pending toId1 _, Pending toId2 _ ) ->
33
+ Pending
34
+ (\id ->
35
+ max (toId1 id) (toId2 id)
36
+ |> nextId
37
+ )
38
+ (\_ _ ->
39
+ Debug.todo ""
40
+ )
41
+
42
+ _ ->
43
+ Debug.todo ""
44
+
45
+
46
+ nextId : Int -> Int
47
+ nextId id =
48
+ id + 1
49
+
50
+
51
+
52
+ --(Task toId1 resolve1)
53
+ --(Task toId2 resolve2)
@@ -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.map (\( k, v ) -> k ++ "=" ++ (String.toLower <| boolToString v))
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