elm-pages 3.0.0-beta.3 → 3.0.0-beta.31

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 (129) hide show
  1. package/README.md +10 -1
  2. package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2864 -2589
  3. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
  4. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
  5. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
  6. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  7. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  8. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  9. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -1
  10. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1447 -342
  11. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +16458 -13724
  12. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  13. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
  14. package/generator/dead-code-review/elm.json +9 -7
  15. package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +59 -10
  16. package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +52 -36
  17. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
  18. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
  19. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
  20. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
  21. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  22. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  23. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  24. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
  25. package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1447 -342
  26. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +24542 -21748
  27. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  28. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
  29. package/generator/review/elm.json +10 -10
  30. package/generator/src/RouteBuilder.elm +113 -107
  31. package/generator/src/SharedTemplate.elm +3 -2
  32. package/generator/src/SiteConfig.elm +3 -2
  33. package/generator/src/basepath-middleware.js +3 -3
  34. package/generator/src/build.js +125 -88
  35. package/generator/src/cli.js +273 -88
  36. package/generator/src/codegen.js +29 -27
  37. package/generator/src/compatibility-key.js +3 -0
  38. package/generator/src/compile-elm.js +43 -26
  39. package/generator/src/config.js +39 -0
  40. package/generator/src/copy-dir.js +2 -2
  41. package/generator/src/dev-server.js +150 -133
  42. package/generator/src/dir-helpers.js +9 -26
  43. package/generator/src/elm-codegen.js +5 -4
  44. package/generator/src/elm-file-constants.js +2 -3
  45. package/generator/src/error-formatter.js +12 -11
  46. package/generator/src/file-helpers.js +3 -4
  47. package/generator/src/generate-template-module-connector.js +23 -22
  48. package/generator/src/init.js +9 -8
  49. package/generator/src/pre-render-html.js +39 -28
  50. package/generator/src/render-test.js +109 -0
  51. package/generator/src/render-worker.js +25 -28
  52. package/generator/src/render.js +320 -142
  53. package/generator/src/request-cache.js +252 -163
  54. package/generator/src/resolve-elm-module.js +63 -0
  55. package/generator/src/rewrite-client-elm-json.js +6 -5
  56. package/generator/src/rewrite-elm-json-help.js +56 -0
  57. package/generator/src/rewrite-elm-json.js +17 -7
  58. package/generator/src/route-codegen-helpers.js +16 -31
  59. package/generator/src/seo-renderer.js +12 -7
  60. package/generator/src/vite-utils.js +77 -0
  61. package/generator/static-code/hmr.js +79 -13
  62. package/generator/template/app/Api.elm +6 -5
  63. package/generator/template/app/Effect.elm +123 -0
  64. package/generator/template/app/ErrorPage.elm +37 -6
  65. package/generator/template/app/Route/Index.elm +17 -10
  66. package/generator/template/app/Shared.elm +24 -47
  67. package/generator/template/app/Site.elm +19 -6
  68. package/generator/template/app/View.elm +1 -8
  69. package/generator/template/elm-tooling.json +0 -3
  70. package/generator/template/elm.json +32 -24
  71. package/generator/template/package.json +10 -4
  72. package/package.json +29 -27
  73. package/src/ApiRoute.elm +199 -61
  74. package/src/BackendTask/Custom.elm +325 -0
  75. package/src/BackendTask/Env.elm +90 -0
  76. package/src/{DataSource → BackendTask}/File.elm +128 -43
  77. package/src/{DataSource → BackendTask}/Glob.elm +136 -125
  78. package/src/BackendTask/Http.elm +673 -0
  79. package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
  80. package/src/BackendTask/Internal/Request.elm +28 -0
  81. package/src/BackendTask/Random.elm +79 -0
  82. package/src/BackendTask/Time.elm +47 -0
  83. package/src/BackendTask.elm +537 -0
  84. package/src/FatalError.elm +89 -0
  85. package/src/Form/Field.elm +21 -9
  86. package/src/Form/FieldView.elm +94 -14
  87. package/src/Form.elm +275 -400
  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/FormState.elm +6 -5
  93. package/src/Pages/GeneratorProgramConfig.elm +15 -0
  94. package/src/Pages/Internal/FatalError.elm +5 -0
  95. package/src/Pages/Internal/Form.elm +21 -1
  96. package/src/Pages/{Msg.elm → Internal/Msg.elm} +26 -16
  97. package/src/Pages/Internal/Platform/Cli.elm +598 -763
  98. package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
  99. package/src/Pages/Internal/Platform/Effect.elm +1 -2
  100. package/src/Pages/Internal/Platform/GeneratorApplication.elm +373 -0
  101. package/src/Pages/Internal/Platform/StaticResponses.elm +73 -270
  102. package/src/Pages/Internal/Platform/ToJsPayload.elm +4 -7
  103. package/src/Pages/Internal/Platform.elm +216 -102
  104. package/src/Pages/Internal/Script.elm +17 -0
  105. package/src/Pages/Internal/StaticHttpBody.elm +35 -1
  106. package/src/Pages/Manifest.elm +29 -4
  107. package/src/Pages/PageUrl.elm +23 -9
  108. package/src/Pages/ProgramConfig.elm +14 -10
  109. package/src/Pages/Script.elm +109 -0
  110. package/src/Pages/SiteConfig.elm +3 -2
  111. package/src/Pages/StaticHttp/Request.elm +2 -2
  112. package/src/Pages/StaticHttpRequest.elm +23 -98
  113. package/src/PagesMsg.elm +92 -0
  114. package/src/Path.elm +16 -19
  115. package/src/QueryParams.elm +21 -172
  116. package/src/RequestsAndPending.elm +8 -19
  117. package/src/Result/Extra.elm +26 -0
  118. package/src/Scaffold/Form.elm +560 -0
  119. package/src/Scaffold/Route.elm +1388 -0
  120. package/src/Server/Request.elm +43 -37
  121. package/src/Server/Session.elm +62 -42
  122. package/src/Server/SetCookie.elm +12 -4
  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/Pages/Generate.elm +0 -800
@@ -0,0 +1,325 @@
1
+ module BackendTask.Custom exposing
2
+ ( run
3
+ , Error(..)
4
+ , timeDecoder, dateDecoder
5
+ )
6
+
7
+ {-| In a vanilla Elm application, ports let you either send or receive JSON data between your Elm application and the JavaScript context in the user's browser at runtime.
8
+
9
+ With `BackendTask.Custom`, you send and receive JSON to JavaScript running in NodeJS. As with any `BackendTask`, Custom BackendTask's are either run at build-time (for pre-rendered routes) or at request-time (for server-rendered routes). See [`BackendTask`](BackendTask) for more about the
10
+ lifecycle of `BackendTask`'s.
11
+
12
+ This means that you can call shell scripts, run NPM packages that are installed, or anything else you could do with NodeJS to perform custom side-effects, get some data, or both.
13
+
14
+ A `BackendTask.Custom` will call an async JavaScript function with the given name from the definition in a file called `custom-backend-task.js` in your project's root directory. The function receives the input JSON value, and the Decoder is used to decode the return value of the async function.
15
+
16
+ @docs run
17
+
18
+ Here is the Elm code and corresponding JavaScript definition for getting an environment variable (or an `FatalError BackendTask.Custom.Error` if it isn't found). In this example,
19
+ we're using `BackendTask.allowFatal` to let the framework treat that as an unexpected exception, but we could also handle the possible failures of the `FatalError` (see [`FatalError`](FatalError)).
20
+
21
+ import BackendTask exposing (BackendTask)
22
+ import BackendTask.Custom
23
+ import Json.Encode
24
+ import OptimizedDecoder as Decode
25
+
26
+ data : BackendTask FatalError String
27
+ data =
28
+ BackendTask.Custom.run "environmentVariable"
29
+ (Json.Encode.string "EDITOR")
30
+ Decode.string
31
+ |> BackendTask.allowFatal
32
+
33
+ -- will resolve to "VIM" if you run `EDITOR=vim elm-pages dev`
34
+
35
+ ```javascript
36
+ // custom-backend-task.js
37
+
38
+ module.exports =
39
+ /**
40
+ * @param { unknown } fromElm
41
+ * @returns { Promise<unknown> }
42
+ */
43
+ {
44
+ environmentVariable: async function (name) {
45
+ const result = process.env[name];
46
+ if (result) {
47
+ return result;
48
+ } else {
49
+ throw `No environment variable called ${name}
50
+
51
+ Available:
52
+
53
+ ${Object.keys(process.env).join("\n")}
54
+ `;
55
+ }
56
+ },
57
+ }
58
+ ```
59
+
60
+
61
+ ## Performance
62
+
63
+ As with any JavaScript or NodeJS code, avoid doing blocking IO operations. For example, avoid using `fs.readFileSync`, because blocking IO can slow down your elm-pages builds and dev server. `elm-pages` performs all `BackendTask`'s in parallel whenever possible.
64
+ So if you do `BackendTask.map2 Tuple.pair myHttpBackendTask myCustomBackendTask`, it will resolve those two in parallel. NodeJS performs best when you take advantage of its ability to do non-blocking I/O (file reads, HTTP requests, etc.). If you use `BackendTask.andThen`,
65
+ it will need to resolve them in sequence rather than in parallel, but it's still best to avoid blocking IO operations in your Custom BackendTask definitions.
66
+
67
+
68
+ ## Error Handling
69
+
70
+ There are a few different things that can go wrong when running a custom-backend-task. These possible errors are captured in the `BackendTask.Custom.Error` type.
71
+
72
+ @docs Error
73
+
74
+ Any time you throw a JavaScript exception from a BackendTask.Custom definition, it will give you a `CustomBackendTaskException`. It's usually easier to add a `try`/`catch` in your JavaScript code in `custom-backend-task.js`
75
+ to handle possible errors, but you can throw a JSON value and handle it in Elm in the `CustomBackendTaskException` call error.
76
+
77
+
78
+ ## Decoding JS Date Objects
79
+
80
+ These decoders are for use with decoding JS values of type `Date`. If you have control over the format, it may be better to
81
+ be more explicit with a [Rata Die](https://en.wikipedia.org/wiki/Rata_Die) number value or an ISO-8601 formatted date string instead.
82
+ But often JavaScript libraries and core APIs will give you JS Date objects, so this can be useful for working with those.
83
+
84
+ @docs timeDecoder, dateDecoder
85
+
86
+ -}
87
+
88
+ import BackendTask exposing (BackendTask)
89
+ import BackendTask.Http
90
+ import Date
91
+ import FatalError exposing (FatalError)
92
+ import Json.Decode as Decode exposing (Decoder)
93
+ import Json.Encode as Encode
94
+ import TerminalText
95
+ import Time
96
+
97
+
98
+ {-| -}
99
+ run :
100
+ String
101
+ -> Encode.Value
102
+ -> Decoder b
103
+ -> BackendTask { fatal : FatalError, recoverable : Error } b
104
+ run portName input decoder =
105
+ request
106
+ { body =
107
+ Encode.object
108
+ [ ( "input", input )
109
+ , ( "portName", Encode.string portName )
110
+ ]
111
+ |> BackendTask.Http.jsonBody
112
+ , expect =
113
+ Decode.field "elm-pages-internal-error" Decode.string
114
+ |> Decode.maybe
115
+ |> Decode.andThen
116
+ (\maybeInternalErrorCode ->
117
+ case maybeInternalErrorCode of
118
+ Just errorKind ->
119
+ --Decode.field "elm-pages-internal-error" Decode.string
120
+ -- |> Decode.andThen
121
+ (--\errorKind ->
122
+ if errorKind == "CustomBackendTaskNotDefined" then
123
+ FatalError.recoverable
124
+ { title = "Custom BackendTask Error"
125
+ , body =
126
+ [ TerminalText.text "Something went wrong in a call to BackendTask.Custom.run. I expected to find a port named `"
127
+ , TerminalText.yellow portName
128
+ , TerminalText.text "` but I couldn't find it. Is the function exported in your custom-backend-task file?"
129
+ ]
130
+ |> TerminalText.toString
131
+ }
132
+ (CustomBackendTaskNotDefined { name = portName })
133
+ |> Decode.succeed
134
+
135
+ else if errorKind == "ExportIsNotFunction" then
136
+ Decode.field "error" Decode.string
137
+ |> Decode.maybe
138
+ |> Decode.map (Maybe.withDefault "")
139
+ |> Decode.map
140
+ (\incorrectType ->
141
+ FatalError.recoverable
142
+ { title = "Custom BackendTask Error"
143
+ , body =
144
+ [ TerminalText.text "Something went wrong in a call to BackendTask.Custom.run. I found an export called `"
145
+ , TerminalText.yellow portName
146
+ , TerminalText.text "` but I expected its type to be function, but instead its type was: "
147
+ , TerminalText.red incorrectType
148
+ ]
149
+ |> TerminalText.toString
150
+ }
151
+ ExportIsNotFunction
152
+ )
153
+
154
+ else if errorKind == "MissingCustomBackendTaskFile" then
155
+ FatalError.recoverable
156
+ { title = "Custom BackendTask Error"
157
+ , body =
158
+ [ TerminalText.text "Something went wrong in a call to BackendTask.Custom.run. I couldn't find your custom-backend-task file. Be sure to create a 'custom-backend-task.ts' or 'custom-backend-task.js' file."
159
+ ]
160
+ |> TerminalText.toString
161
+ }
162
+ MissingCustomBackendTaskFile
163
+ |> Decode.succeed
164
+
165
+ else if errorKind == "ErrorInCustomBackendTaskFile" then
166
+ Decode.field "error" Decode.string
167
+ |> Decode.maybe
168
+ |> Decode.map (Maybe.withDefault "")
169
+ |> Decode.map
170
+ (\errorMessage ->
171
+ FatalError.recoverable
172
+ { title = "Custom BackendTask Error"
173
+ , body =
174
+ [ TerminalText.text "Something went wrong in a call to BackendTask.Custom.run. I couldn't import the port definitions file, because of this exception:\n\n"
175
+ , TerminalText.red errorMessage
176
+ , TerminalText.text "\n\nAre there syntax errors or exceptions thrown during import?"
177
+ ]
178
+ |> TerminalText.toString
179
+ }
180
+ ErrorInCustomBackendTaskFile
181
+ )
182
+
183
+ else if errorKind == "CustomBackendTaskException" then
184
+ Decode.field "error" Decode.value
185
+ |> Decode.maybe
186
+ |> Decode.map (Maybe.withDefault Encode.null)
187
+ |> Decode.map
188
+ (\portCallError ->
189
+ FatalError.recoverable
190
+ { title = "Custom BackendTask Error"
191
+ , body =
192
+ [ TerminalText.text "Something went wrong in a call to BackendTask.Custom.run. I was able to import the port definitions file, but when running it I encountered this exception:\n\n"
193
+ , TerminalText.red (Encode.encode 2 portCallError)
194
+ , TerminalText.text "\n\nYou could add a `try`/`catch` in your `custom-backend-task` JavaScript code to handle that error."
195
+ ]
196
+ |> TerminalText.toString
197
+ }
198
+ (CustomBackendTaskException portCallError)
199
+ )
200
+
201
+ else if errorKind == "NonJsonException" then
202
+ Decode.map2
203
+ (\exceptionMessage stackTrace ->
204
+ FatalError.recoverable
205
+ { title = "Custom BackendTask Error"
206
+ , body =
207
+ [ TerminalText.text "Something went wrong in a call to BackendTask.Custom.run. I was able to import the port definitions file, but when running it I encountered this exception:\n\n"
208
+ , TerminalText.red exceptionMessage
209
+ , TerminalText.text ("\n\n" ++ (stackTrace |> Maybe.withDefault "\n"))
210
+ , TerminalText.text "\n\nYou could add a `try`/`catch` in your `custom-backend-task` JavaScript code to handle that error."
211
+ ]
212
+ |> TerminalText.toString
213
+ }
214
+ (NonJsonException exceptionMessage)
215
+ )
216
+ (Decode.field "error" Decode.string)
217
+ (Decode.field "stack" (Decode.nullable Decode.string))
218
+
219
+ else
220
+ FatalError.recoverable
221
+ { title = "Custom BackendTask Error"
222
+ , body =
223
+ [ TerminalText.text "Something went wrong in a call to BackendTask.Custom.run. I expected to find a port named `"
224
+ , TerminalText.yellow portName
225
+ , TerminalText.text "`."
226
+ ]
227
+ |> TerminalText.toString
228
+ }
229
+ ErrorInCustomBackendTaskFile
230
+ |> Decode.succeed
231
+ )
232
+ |> Decode.map Err
233
+
234
+ Nothing ->
235
+ decoder |> Decode.map Ok
236
+ )
237
+ |> BackendTask.Http.expectJson
238
+ }
239
+ |> BackendTask.andThen BackendTask.fromResult
240
+
241
+
242
+ {-| -}
243
+ type Error
244
+ = Error
245
+ | ErrorInCustomBackendTaskFile
246
+ | MissingCustomBackendTaskFile
247
+ | CustomBackendTaskNotDefined { name : String }
248
+ | CustomBackendTaskException Decode.Value
249
+ | NonJsonException String
250
+ | ExportIsNotFunction
251
+ | DecodeError Decode.Error
252
+
253
+
254
+ {-| -}
255
+ timeDecoder : Decoder Time.Posix
256
+ timeDecoder =
257
+ Decode.field "__elm-pages-normalized__"
258
+ (Decode.field "kind" Decode.string
259
+ |> Decode.andThen
260
+ (\kind ->
261
+ if kind == "Date" then
262
+ Decode.field "value"
263
+ (Decode.int |> Decode.map Time.millisToPosix)
264
+
265
+ else
266
+ Decode.fail <| "I was running BackendTask.Custom.timeDecoder and expecting an elm-pages normalized Object with kind \"Date\", but got kind \"" ++ kind ++ "\"."
267
+ )
268
+ )
269
+
270
+
271
+ {-| The same as `timeDecoder`, but it converts the decoded `Time.Posix` value into a `Date` with `Date.fromPosix Time.utc`.
272
+
273
+ JavaScript `Date` objects don't distinguish between values with only a date vs. values with both a date and a time. So be sure
274
+ to use this decoder when you know the semantics represent a date with no associated time (or you're sure you don't care about the time).
275
+
276
+ -}
277
+ dateDecoder : Decoder Date.Date
278
+ dateDecoder =
279
+ Decode.field "__elm-pages-normalized__"
280
+ (Decode.field "kind" Decode.string
281
+ |> Decode.andThen
282
+ (\kind ->
283
+ if kind == "Date" then
284
+ Decode.field "value"
285
+ (Decode.int |> Decode.map (Time.millisToPosix >> Date.fromPosix Time.utc))
286
+
287
+ else
288
+ Decode.fail <| "I was running BackendTask.Custom.dateDecoder and expecting an elm-pages normalized Object with kind \"Date\", but got kind \"" ++ kind ++ "\"."
289
+ )
290
+ )
291
+
292
+
293
+ request :
294
+ { body : BackendTask.Http.Body
295
+ , expect : BackendTask.Http.Expect a
296
+ }
297
+ -> BackendTask { fatal : FatalError, recoverable : Error } a
298
+ request { body, expect } =
299
+ -- elm-review: known-unoptimized-recursion
300
+ BackendTask.Http.request
301
+ { url = "elm-pages-internal://port"
302
+ , method = "GET"
303
+ , headers = []
304
+ , body = body
305
+ , timeoutInMs = Nothing
306
+ , retries = Nothing
307
+ }
308
+ expect
309
+ |> BackendTask.onError
310
+ (\error ->
311
+ -- TODO avoid crash here, this should be handled as an internal error
312
+ --request params
313
+ case error.recoverable of
314
+ BackendTask.Http.BadBody (Just jsonError) _ ->
315
+ { recoverable = DecodeError jsonError
316
+ , fatal = error.fatal
317
+ }
318
+ |> BackendTask.fail
319
+
320
+ _ ->
321
+ { recoverable = Error
322
+ , fatal = error.fatal
323
+ }
324
+ |> BackendTask.fail
325
+ )
@@ -0,0 +1,90 @@
1
+ module BackendTask.Env exposing
2
+ ( get, expect
3
+ , Error(..)
4
+ )
5
+
6
+ {-| Because BackendTask's in `elm-pages` never run in the browser (see [the BackendTask docs](BackendTask)), you can access environment variables securely. As long as the environment variable isn't sent
7
+ down into the final `Data` value, it won't end up in the client!
8
+
9
+ import BackendTask exposing (BackendTask)
10
+ import BackendTask.Env
11
+ import FatalError exposing (FatalError)
12
+
13
+ type alias EnvVariables =
14
+ { sendGridKey : String
15
+ , siteUrl : String
16
+ }
17
+
18
+ sendEmail : Email -> BackendTask FatalError ()
19
+ sendEmail email =
20
+ BackendTask.map2 EnvVariables
21
+ (BackendTask.Env.expect "SEND_GRID_KEY" |> BackendTask.allowFatal)
22
+ (BackendTask.Env.get "BASE_URL"
23
+ |> BackendTask.map (Maybe.withDefault "http://localhost:1234")
24
+ )
25
+ |> BackendTask.andThen (sendEmailBackendTask email)
26
+
27
+ sendEmailBackendTask : Email -> EnvVariables -> BackendTask FatalError ()
28
+ sendEmailBackendTask email envVariables =
29
+ Debug.todo "Not defined here"
30
+
31
+ @docs get, expect
32
+
33
+
34
+ ## Errors
35
+
36
+ @docs Error
37
+
38
+ -}
39
+
40
+ import BackendTask exposing (BackendTask)
41
+ import BackendTask.Http
42
+ import BackendTask.Internal.Request
43
+ import FatalError exposing (FatalError)
44
+ import Json.Decode as Decode
45
+ import Json.Encode as Encode
46
+ import TerminalText
47
+
48
+
49
+ {-| -}
50
+ type Error
51
+ = MissingEnvVariable String
52
+
53
+
54
+ {-| Get an environment variable, or Nothing if there is no environment variable matching that name. This `BackendTask`
55
+ will never fail, but instead will return `Nothing` if the environment variable is missing.
56
+ -}
57
+ get : String -> BackendTask error (Maybe String)
58
+ get envVariableName =
59
+ BackendTask.Internal.Request.request
60
+ { name = "env"
61
+ , body = BackendTask.Http.jsonBody (Encode.string envVariableName)
62
+ , expect =
63
+ BackendTask.Http.expectJson
64
+ (Decode.nullable Decode.string)
65
+ }
66
+
67
+
68
+ {-| Get an environment variable, or a BackendTask FatalError if there is no environment variable matching that name.
69
+ -}
70
+ expect : String -> BackendTask { fatal : FatalError, recoverable : Error } String
71
+ expect envVariableName =
72
+ envVariableName
73
+ |> get
74
+ |> BackendTask.andThen
75
+ (\maybeValue ->
76
+ maybeValue
77
+ |> Result.fromMaybe
78
+ (FatalError.recoverable
79
+ { title = "Missing Env Variable"
80
+ , body =
81
+ [ TerminalText.text "BackendTask.Env.expect was expecting a variable `"
82
+ , TerminalText.yellow envVariableName
83
+ , TerminalText.text "` but couldn't find a variable with that name."
84
+ ]
85
+ |> TerminalText.toString
86
+ }
87
+ (MissingEnvVariable envVariableName)
88
+ )
89
+ |> BackendTask.fromResult
90
+ )