elm-pages 3.0.0-beta.14 → 3.0.0-beta.15

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 (65) hide show
  1. package/README.md +1 -1
  2. package/codegen/elm-pages-codegen.js +4 -7
  3. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  4. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  5. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +1 -1
  6. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  7. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  8. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +1 -1
  9. package/generator/src/compatibility-key.js +1 -1
  10. package/generator/src/error-formatter.js +7 -3
  11. package/generator/src/render.js +8 -17
  12. package/generator/src/request-cache.js +34 -4
  13. package/generator/static-code/hmr.js +16 -2
  14. package/package.json +1 -1
  15. package/src/ApiRoute.elm +1 -4
  16. package/src/BackendTask/Env.elm +10 -8
  17. package/src/BackendTask/File.elm +10 -10
  18. package/src/BackendTask/Glob.elm +2 -2
  19. package/src/BackendTask/Http.elm +49 -13
  20. package/src/BackendTask/Port.elm +50 -46
  21. package/src/BackendTask.elm +5 -5
  22. package/src/Exception.elm +70 -12
  23. package/src/Form.elm +3 -2
  24. package/src/Pages/Generate.elm +299 -102
  25. package/src/Pages/Internal/Platform/Cli.elm +17 -37
  26. package/src/Pages/Internal/Platform/CompatibilityKey.elm +1 -1
  27. package/src/Pages/Internal/Platform/GeneratorApplication.elm +17 -41
  28. package/src/Pages/Internal/Platform/StaticResponses.elm +11 -25
  29. package/src/Pages/Script.elm +2 -2
  30. package/src/Pages/StaticHttpRequest.elm +1 -23
  31. package/src/Server/Request.elm +3 -2
  32. package/src/MultiDict.elm +0 -49
  33. package/src/PairingHeap.elm +0 -137
  34. package/src/Parser/Extra/String.elm +0 -33
  35. package/src/Parser/Extra.elm +0 -69
  36. package/src/ProgramTest/ComplexQuery.elm +0 -360
  37. package/src/ProgramTest/EffectSimulation.elm +0 -122
  38. package/src/ProgramTest/Failure.elm +0 -367
  39. package/src/ProgramTest/HtmlHighlighter.elm +0 -116
  40. package/src/ProgramTest/HtmlParserHacks.elm +0 -58
  41. package/src/ProgramTest/HtmlRenderer.elm +0 -73
  42. package/src/ProgramTest/Program.elm +0 -30
  43. package/src/ProgramTest/StringLines.elm +0 -26
  44. package/src/ProgramTest/TestHtmlHacks.elm +0 -132
  45. package/src/ProgramTest/TestHtmlParser.elm +0 -201
  46. package/src/ProgramTest.elm +0 -2339
  47. package/src/Query/Extra.elm +0 -55
  48. package/src/SimulatedEffect/Cmd.elm +0 -69
  49. package/src/SimulatedEffect/Http.elm +0 -330
  50. package/src/SimulatedEffect/Navigation.elm +0 -69
  51. package/src/SimulatedEffect/Ports.elm +0 -62
  52. package/src/SimulatedEffect/Process.elm +0 -24
  53. package/src/SimulatedEffect/Sub.elm +0 -48
  54. package/src/SimulatedEffect/Task.elm +0 -252
  55. package/src/SimulatedEffect/Time.elm +0 -25
  56. package/src/SimulatedEffect.elm +0 -42
  57. package/src/String/Extra.elm +0 -6
  58. package/src/Test/Http.elm +0 -145
  59. package/src/TestResult.elm +0 -35
  60. package/src/TestState.elm +0 -305
  61. package/src/Url/Extra.elm +0 -100
  62. package/src/Vendored/Diff.elm +0 -321
  63. package/src/Vendored/Failure.elm +0 -217
  64. package/src/Vendored/FormatMonochrome.elm +0 -44
  65. package/src/Vendored/Highlightable.elm +0 -53
@@ -3,47 +3,36 @@ module BackendTask.Port exposing
3
3
  , Error(..)
4
4
  )
5
5
 
6
- {-|
7
-
8
- @docs get
9
-
10
- @docs Error
11
-
12
- -}
13
-
14
- import BackendTask
15
- import BackendTask.Http
16
- import BackendTask.Internal.Request
17
- import Exception exposing (Catchable)
18
- import Json.Decode as Decode exposing (Decoder)
19
- import Json.Encode as Encode
20
- import TerminalText
6
+ {-| 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.
21
7
 
8
+ With `BackendTask.Port`, you send and receive JSON to JavaScript running in NodeJS. As with any `BackendTask`, Port 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
9
+ lifecycle of `BackendTask`'s.
22
10
 
23
- {-| 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.
11
+ 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.
24
12
 
25
- With `BackendTask.Port`, you send and receive JSON to JavaScript running in NodeJS during build-time. This means that you can call shell scripts, or run NPM packages that are installed, or anything else you could do with NodeJS.
13
+ A `BackendTask.Port` will call an async JavaScript function with the given name from the definition in a file called `port-data-source.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.
26
14
 
27
- A `BackendTask.Port` will call an async JavaScript function with the given name. The function receives the input JSON value, and the Decoder is used to decode the return value of the async function.
15
+ @docs get
28
16
 
29
- Here is the Elm code and corresponding JavaScript definition for getting an environment variable (or a build error if it isn't found).
17
+ Here is the Elm code and corresponding JavaScript definition for getting an environment variable (or an `Exception BackendTask.Port.Error` if it isn't found). In this example,
18
+ we're using `BackendTask.throw` to let the framework treat that as an unexpected exception, but we could also handle the possible failures of the `Exception` (see [`Exception`](Exception)).
30
19
 
31
20
  import BackendTask exposing (BackendTask)
32
21
  import BackendTask.Port
33
22
  import Json.Encode
34
23
  import OptimizedDecoder as Decode
35
24
 
36
- data : BackendTask String
25
+ data : BackendTask Throwable String
37
26
  data =
38
27
  BackendTask.Port.get "environmentVariable"
39
28
  (Json.Encode.string "EDITOR")
40
29
  Decode.string
30
+ |> BackendTask.throw
41
31
 
42
32
  -- will resolve to "VIM" if you run `EDITOR=vim elm-pages dev`
43
33
 
44
34
  ```javascript
45
- const kleur = require("kleur");
46
-
35
+ // port-data-source.js
47
36
 
48
37
  module.exports =
49
38
  /**
@@ -56,32 +45,47 @@ module.exports =
56
45
  if (result) {
57
46
  return result;
58
47
  } else {
59
- throw `No environment variable called ${kleur
60
- .yellow()
61
- .underline(name)}\n\nAvailable:\n\n${Object.keys(process.env).join(
62
- "\n"
63
- )}`;
48
+ throw `No environment variable called ${name}
49
+
50
+ Available:
51
+
52
+ ${Object.keys(process.env).join("\n")}
53
+ `;
64
54
  }
65
55
  },
66
56
  }
67
57
  ```
68
58
 
69
59
 
70
- ## Error Handling
60
+ ## Performance
71
61
 
72
- `port-data-source.js`
62
+ 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` performances all `BackendTask`'s in parallel whenever possible.
63
+ So if you do `BackendTask.map2 Tuple.pair myHttpBackendTask myPortBackendTask`, 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`,
64
+ it will need to resolve them in sequence rather than in parallel, but it's still best to avoid blocking IO operations in your BackendTask Port definitions.
73
65
 
74
- Any time you throw an exception from a BackendTask.Port definition, it will result in a build error in your `elm-pages build` or dev server. In the example above, if the environment variable
75
- is not found it will result in a build failure. Notice that the NPM package `kleur` is being used in this example to add color to the output for that build error. You can use any tool you
76
- prefer to add ANSI color codes within the error string in an exception and it will show up with color output in the build output and dev server.
77
66
 
67
+ ## Error Handling
78
68
 
79
- ## Performance
69
+ There are a few different things that can go wrong when running a port-data-source. These possible errors are captured in the `BackendTask.Port.Error` type.
80
70
 
81
- 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.
71
+ @docs Error
72
+
73
+ Any time you throw a JavaScript exception from a BackendTask.Port definition, it will give you a `PortCallException`. It's usually easier to add a `try`/`catch` in your JavaScript code in `port-data-source.js`
74
+ to handle possible errors, but you can throw a JSON value and handle it in Elm in the `PortCallException` call error.
82
75
 
83
76
  -}
84
- get : String -> Encode.Value -> Decoder b -> BackendTask.BackendTask (Catchable Error) b
77
+
78
+ import BackendTask
79
+ import BackendTask.Http
80
+ import BackendTask.Internal.Request
81
+ import Exception exposing (Exception)
82
+ import Json.Decode as Decode exposing (Decoder)
83
+ import Json.Encode as Encode
84
+ import TerminalText
85
+
86
+
87
+ {-| -}
88
+ get : String -> Encode.Value -> Decoder b -> BackendTask.BackendTask (Exception Error) b
85
89
  get portName input decoder =
86
90
  BackendTask.Internal.Request.request
87
91
  { name = "port"
@@ -97,7 +101,7 @@ get portName input decoder =
97
101
  |> Decode.andThen
98
102
  (\errorKind ->
99
103
  if errorKind == "PortNotDefined" then
100
- Exception.Catchable (PortNotDefined { name = portName })
104
+ Exception.Exception (PortNotDefined { name = portName })
101
105
  { title = "Port Error"
102
106
  , body =
103
107
  [ TerminalText.text "Something went wrong in a call to BackendTask.Port.get. I expected to find a port named `"
@@ -114,7 +118,7 @@ get portName input decoder =
114
118
  |> Decode.map (Maybe.withDefault "")
115
119
  |> Decode.map
116
120
  (\incorrectPortType ->
117
- Exception.Catchable ExportIsNotFunction
121
+ Exception.Exception ExportIsNotFunction
118
122
  { title = "Port Error"
119
123
  , body =
120
124
  [ TerminalText.text "Something went wrong in a call to BackendTask.Port.get. I found an export called `"
@@ -127,7 +131,7 @@ get portName input decoder =
127
131
  )
128
132
 
129
133
  else if errorKind == "MissingPortsFile" then
130
- Exception.Catchable MissingPortsFile
134
+ Exception.Exception MissingPortsFile
131
135
  { title = "Port Error"
132
136
  , body =
133
137
  [ TerminalText.text "Something went wrong in a call to BackendTask.Port.get. I couldn't find your port-data-source file. Be sure to create a 'port-data-source.ts' or 'port-data-source.js' file."
@@ -142,7 +146,7 @@ get portName input decoder =
142
146
  |> Decode.map (Maybe.withDefault "")
143
147
  |> Decode.map
144
148
  (\errorMessage ->
145
- Exception.Catchable
149
+ Exception.Exception
146
150
  ErrorInPortsFile
147
151
  { title = "Port Error"
148
152
  , body =
@@ -154,26 +158,26 @@ get portName input decoder =
154
158
  }
155
159
  )
156
160
 
157
- else if errorKind == "PortCallError" then
161
+ else if errorKind == "PortCallException" then
158
162
  Decode.field "error" Decode.value
159
163
  |> Decode.maybe
160
164
  |> Decode.map (Maybe.withDefault Encode.null)
161
165
  |> Decode.map
162
166
  (\portCallError ->
163
- Exception.Catchable
164
- (PortCallError portCallError)
167
+ Exception.Exception
168
+ (PortCallException portCallError)
165
169
  { title = "Port Error"
166
170
  , body =
167
- [ TerminalText.text "Something went wrong in a call to BackendTask.Port.get. I couldn't import the port definitions file, because of this exception:\n\n"
171
+ [ TerminalText.text "Something went wrong in a call to BackendTask.Port.get. I was able to import the port definitions file, but when running it I encountered this exception:\n\n"
168
172
  , TerminalText.red (Encode.encode 2 portCallError)
169
- , TerminalText.text "\n\nAre there syntax errors or exceptions thrown during import?"
173
+ , TerminalText.text "\n\nYou could add a `try`/`catch` in your `port-data-source` JavaScript code to handle that error."
170
174
  ]
171
175
  |> TerminalText.toString
172
176
  }
173
177
  )
174
178
 
175
179
  else
176
- Exception.Catchable ErrorInPortsFile
180
+ Exception.Exception ErrorInPortsFile
177
181
  { title = "Port Error"
178
182
  , body =
179
183
  [ TerminalText.text "Something went wrong in a call to BackendTask.Port.get. I expected to find a port named `"
@@ -198,5 +202,5 @@ type Error
198
202
  | ErrorInPortsFile
199
203
  | MissingPortsFile
200
204
  | PortNotDefined { name : String }
201
- | PortCallError Decode.Value
205
+ | PortCallException Decode.Value
202
206
  | ExportIsNotFunction
@@ -86,7 +86,7 @@ Any place in your `elm-pages` app where the framework lets you pass in a value o
86
86
 
87
87
  -}
88
88
 
89
- import Exception exposing (Catchable(..), Throwable)
89
+ import Exception exposing (Exception(..), Throwable)
90
90
  import Json.Encode
91
91
  import Pages.StaticHttpRequest exposing (RawRequest(..))
92
92
 
@@ -524,26 +524,26 @@ map9 combineFn request1 request2 request3 request4 request5 request6 request7 re
524
524
 
525
525
 
526
526
  {-| -}
527
- catch : BackendTask (Catchable error) value -> BackendTask error value
527
+ catch : BackendTask (Exception error) value -> BackendTask error value
528
528
  catch ds =
529
529
  ds
530
530
  |> onError
531
531
  (\exception ->
532
532
  case exception of
533
- Catchable error _ ->
533
+ Exception error _ ->
534
534
  fail error
535
535
  )
536
536
 
537
537
 
538
538
  {-| -}
539
- throw : BackendTask (Catchable error) data -> BackendTask Throwable data
539
+ throw : BackendTask (Exception error) data -> BackendTask Throwable data
540
540
  throw backendTask =
541
541
  backendTask
542
542
  |> onError (Exception.throw >> fail)
543
543
 
544
544
 
545
545
  {-| -}
546
- toResult : BackendTask (Catchable error) data -> BackendTask noError (Result error data)
546
+ toResult : BackendTask (Exception error) data -> BackendTask noError (Result error data)
547
547
  toResult backendTask =
548
548
  backendTask
549
549
  |> catch
package/src/Exception.elm CHANGED
@@ -1,37 +1,95 @@
1
- module Exception exposing (Throwable, Catchable(..), fromString, fromStringWithValue, throw)
1
+ module Exception exposing (Throwable, Exception(..), fromString, fromStringWithValue, throw, unwrap)
2
2
 
3
- {-|
3
+ {-| The Elm language doesn't have the concept of exceptions or special control flow for errors. It just has
4
+ Custom Types, and by convention types like `Result` and the `Err` variant are used to represent possible failure states
5
+ and combine together different error states.
4
6
 
5
- @docs Throwable, Catchable, fromString, fromStringWithValue, throw
7
+ `elm-pages` doesn't change that, Elm still doesn't have special exception control flow at the language level. It does have
8
+ a type, which is just a regular old Elm type, called `Exception`. Why? Because this plain old Elm type does have one
9
+ special characteristic - the `elm-pages` framework knows how to turn it into an error message. This becomes interesting
10
+ because an `elm-pages` app has several places that accept a value of type `BackendTask Exception.Throwable value`.
11
+ This design lets the `elm-pages` framework do some of the work for you.
12
+
13
+ For example, if you wanted to handle possible errors to present them to the user
14
+
15
+ type alias Data =
16
+ String
17
+
18
+ data : RouteParams -> BackendTask Throwable Data
19
+ data routeParams =
20
+ BackendTask.Http.getJson "https://api.github.com/repos/dillonkearns/elm-pages"
21
+ (Decode.field "description" Decode.string)
22
+ |> BackendTask.onError
23
+ (\error ->
24
+ case Exception.unwrap error of
25
+ BackendTask.Http.BadStatus metadata string ->
26
+ if metadata.statusCode == 401 || metadata.statusCode == 403 || metadata.statusCode == 404 then
27
+ BackendTask.succeed "Either this repo doesn't exist or you don't have access to it."
28
+
29
+ else
30
+ -- we're only handling these expected error cases. In the case of an HTTP timeout,
31
+ -- we'll let the error propagate as a Throwable
32
+ BackendTask.fail error |> BackendTask.throw
33
+
34
+ _ ->
35
+ BackendTask.fail error |> BackendTask.throw
36
+ )
37
+
38
+ This can be a lot of work for all possible errors, though. If you don't expect this kind of error (it's an _exceptional_ case),
39
+ you can let the framework handle it if the error ever does unexpectedly occur.
40
+
41
+ data : RouteParams -> BackendTask Throwable Data
42
+ data routeParams =
43
+ BackendTask.Http.getJson "https://api.github.com/repos/dillonkearns/elm-pages"
44
+ (Decode.field "description" Decode.string)
45
+ |> BackendTask.throw
46
+
47
+ This is especially useful for pages generated at build-time (`RouteBuilder.preRender`) where you want the build
48
+ to fail if anything unexpected happens. With pre-rendered routes, you know that these error cases won't
49
+ be seen by users, so it's often a great idea to just let the framework handle these unexpected errors so a developer can
50
+ debug them and see what went wrong. In the example above, maybe we are only pre-rendering pages for a set of known
51
+ GitHub Repositories, so a Not Found or Unauthorized HTTP error would be unexpected and should stop the build so we can fix the
52
+ issue.
53
+
54
+ In the case of server-rendered Routes (`RouteBuilder.serverRender`), `elm-pages` will show your 500 error page
55
+ when these errors occur.
56
+
57
+ @docs Throwable, Exception, fromString, fromStringWithValue, throw, unwrap
6
58
 
7
59
  -}
8
60
 
9
61
 
10
62
  {-| -}
11
63
  type alias Throwable =
12
- Catchable ()
64
+ Exception ()
13
65
 
14
66
 
15
67
  {-| -}
16
- type Catchable error
17
- = Catchable error { title : String, body : String }
68
+ type Exception error
69
+ = Exception error { title : String, body : String }
18
70
 
19
71
 
20
72
  {-| -}
21
- fromString : String -> Catchable ()
73
+ fromString : String -> Exception ()
22
74
  fromString string =
23
75
  fromStringWithValue string ()
24
76
 
25
77
 
26
78
  {-| -}
27
- fromStringWithValue : String -> value -> Catchable value
79
+ fromStringWithValue : String -> value -> Exception value
28
80
  fromStringWithValue string value =
29
- Catchable value { title = "Custom Error", body = string }
81
+ Exception value { title = "Custom Error", body = string }
30
82
 
31
83
 
32
84
  {-| -}
33
- throw : Catchable error -> Catchable ()
85
+ throw : Exception error -> Exception ()
34
86
  throw exception =
35
87
  case exception of
36
- Catchable _ string ->
37
- Catchable () string
88
+ Exception _ string ->
89
+ Exception () string
90
+
91
+
92
+ {-| -}
93
+ unwrap : Exception error -> error
94
+ unwrap (Exception error _) =
95
+ error
package/src/Form.elm CHANGED
@@ -269,6 +269,7 @@ Totally customizable. Uses [`Form.FieldView`](Form-FieldView) to render all of t
269
269
 
270
270
  import BackendTask exposing (BackendTask)
271
271
  import Dict exposing (Dict)
272
+ import Exception exposing (Throwable)
272
273
  import Form.Field as Field exposing (Field(..))
273
274
  import Form.FieldStatus as FieldStatus exposing (FieldStatus)
274
275
  import Form.FieldView
@@ -681,7 +682,7 @@ toServerForm :
681
682
  ->
682
683
  Form
683
684
  error
684
- { combine : Validation.Validation error (BackendTask backendTaskError (Validation.Validation error combined kind constraints)) kind constraints
685
+ { combine : Validation.Validation error (BackendTask Throwable (Validation.Validation error combined kind constraints)) kind constraints
685
686
  , view : viewFn
686
687
  }
687
688
  data
@@ -694,7 +695,7 @@ toServerForm (Form a b c) =
694
695
  { result : Dict String (List error)
695
696
  , isMatchCandidate : Bool
696
697
  , combineAndView :
697
- { combine : Validation.Validation error (BackendTask backendTaskError (Validation.Validation error combined kind constraints)) kind constraints
698
+ { combine : Validation.Validation error (BackendTask Throwable (Validation.Validation error combined kind constraints)) kind constraints
698
699
  , view : viewFn
699
700
  }
700
701
  }