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
package/README.md CHANGED
@@ -81,7 +81,7 @@ https://github.com/dillonkearns/elm-pages/projects
81
81
  You will see an error if the NPM and Elm package do not have a matching Compatibility Key. Usually it's best to upgrade to the latest version of both the Elm and NPM
82
82
  packages when you upgrade. However, in case you want to install versions that are behind the latest, the Compatibility Key is included here for reference.
83
83
 
84
- Current Compatibility Key: 4.
84
+ Current Compatibility Key: 5.
85
85
 
86
86
  ## Contributors ✨
87
87
 
@@ -26209,9 +26209,6 @@ var $author$project$Gen$Pages$Internal$Platform$Cli$annotation_ = {
26209
26209
  $author$project$Elm$Annotation$list(
26210
26210
  A3($author$project$Elm$Annotation$namedWith, _List_Nil, 'BuildError', _List_Nil))),
26211
26211
  _Utils_Tuple2(
26212
- 'allRawResponses',
26213
- A3($author$project$Elm$Annotation$namedWith, _List_Nil, 'RequestsAndPending', _List_Nil)),
26214
- _Utils_Tuple2(
26215
26212
  'maybeRequestJson',
26216
26213
  A3(
26217
26214
  $author$project$Elm$Annotation$namedWith,
@@ -27113,7 +27110,7 @@ var $author$project$Gen$BackendTask$call_ = {
27113
27110
  A3(
27114
27111
  $author$project$Elm$Annotation$namedWith,
27115
27112
  _List_Nil,
27116
- 'Catchable',
27113
+ 'Exception',
27117
27114
  _List_fromArray(
27118
27115
  [
27119
27116
  $author$project$Elm$Annotation$var('error')
@@ -28201,7 +28198,7 @@ var $author$project$Gen$BackendTask$call_ = {
28201
28198
  A3(
28202
28199
  $author$project$Elm$Annotation$namedWith,
28203
28200
  _List_Nil,
28204
- 'Catchable',
28201
+ 'Exception',
28205
28202
  _List_fromArray(
28206
28203
  [
28207
28204
  $author$project$Elm$Annotation$var('error')
@@ -28244,7 +28241,7 @@ var $author$project$Gen$BackendTask$call_ = {
28244
28241
  A3(
28245
28242
  $author$project$Elm$Annotation$namedWith,
28246
28243
  _List_Nil,
28247
- 'Catchable',
28244
+ 'Exception',
28248
28245
  _List_fromArray(
28249
28246
  [
28250
28247
  $author$project$Elm$Annotation$var('error')
@@ -33792,7 +33789,7 @@ var $author$project$Gen$ApiRoute$values_ = {
33792
33789
  'BackendTask',
33793
33790
  _List_fromArray(
33794
33791
  [
33795
- A3($author$project$Elm$Annotation$namedWith, _List_Nil, 'Never', _List_Nil),
33792
+ A3($author$project$Elm$Annotation$namedWith, _List_Nil, 'Throwable', _List_Nil),
33796
33793
  A3(
33797
33794
  $author$project$Elm$Annotation$namedWith,
33798
33795
  _List_fromArray(
@@ -75,7 +75,7 @@ console.elmlog = (str) => logs.push(str + "\n");
75
75
  const { Elm } = require("./Runner.elm.js");
76
76
 
77
77
  // Start the Elm app
78
- const flags = { initialSeed: 3386937051, fuzzRuns: 100, filter: null };
78
+ const flags = { initialSeed: 4021965449, fuzzRuns: 100, filter: null };
79
79
  const app = Elm.Runner.init({ flags: flags });
80
80
 
81
81
  // Record the timing at which we received the last "runTest" message
@@ -82,7 +82,7 @@ const verbosity = 0;
82
82
  // Create a long lived reporter worker
83
83
  const { Elm } = require("./Reporter.elm.js");
84
84
  const flags = {
85
- initialSeed: 3386937051,
85
+ initialSeed: 4021965449,
86
86
  fuzzRuns: 100,
87
87
  mode: "consoleNoColor",
88
88
  verbosity: verbosity,
@@ -75,7 +75,7 @@ console.elmlog = (str) => logs.push(str + "\n");
75
75
  const { Elm } = require("./Runner.elm.js");
76
76
 
77
77
  // Start the Elm app
78
- const flags = { initialSeed: 1238144440, fuzzRuns: 100, filter: null };
78
+ const flags = { initialSeed: 1951305281, fuzzRuns: 100, filter: null };
79
79
  const app = Elm.Runner.init({ flags: flags });
80
80
 
81
81
  // Record the timing at which we received the last "runTest" message
@@ -82,7 +82,7 @@ const verbosity = 0;
82
82
  // Create a long lived reporter worker
83
83
  const { Elm } = require("./Reporter.elm.js");
84
84
  const flags = {
85
- initialSeed: 1238144440,
85
+ initialSeed: 1951305281,
86
86
  fuzzRuns: 100,
87
87
  mode: "consoleNoColor",
88
88
  verbosity: verbosity,
@@ -1 +1 @@
1
- module.exports = { compatibilityKey: 4 };
1
+ module.exports = { compatibilityKey: 5 };
@@ -13,11 +13,12 @@ const kleur = require("kleur");
13
13
  * @param {string} rule
14
14
  * @param {string} path
15
15
  * */
16
- const parseHeader = (rule, path) =>
17
- kleur.cyan(
18
- `-- ${rule.replace("-", " ")} --------------- ${path || ""}
16
+ function parseHeader(rule, path) {
17
+ return kleur.cyan(
18
+ `-- ${(rule || "").replace("-", " ")} --------------- ${path || ""}
19
19
  `
20
20
  );
21
+ }
21
22
 
22
23
  /**
23
24
  * parseMsg :: String|Object -> String
@@ -137,7 +138,10 @@ const restoreProblem =
137
138
  parseHeader(info.rule, path),
138
139
  ...info.formatted.map(parseMsg),
139
140
  ].join("");
141
+ } else if (typeof info.message === "string") {
142
+ return info.message;
140
143
  } else {
144
+ // console.log("info.message", info.message);
141
145
  return [
142
146
  parseHeader(info.title, path),
143
147
  ...info.message.map(parseMsg),
@@ -143,22 +143,10 @@ function runGeneratorAppHelp(
143
143
  if (fromElm.command === "log") {
144
144
  console.log(fromElm.value);
145
145
  } else if (fromElm.tag === "ApiResponse") {
146
- const args = fromElm.args[0];
147
- if (mode === "build") {
148
- global.staticHttpCache = args.staticHttpCache;
149
- }
150
-
151
- resolve({
152
- kind: "api-response",
153
- is404: args.is404,
154
- statusCode: args.statusCode,
155
- body: args.body,
156
- });
146
+ // Finished successfully
147
+ process.exit(0);
157
148
  } else if (fromElm.tag === "PageProgress") {
158
149
  const args = fromElm.args[0];
159
- if (mode === "build") {
160
- global.staticHttpCache = args.staticHttpCache;
161
- }
162
150
 
163
151
  if (isBytes) {
164
152
  resolve({
@@ -653,9 +641,12 @@ function flushIfDone(app) {
653
641
  }
654
642
 
655
643
  function flushQueue(app) {
656
- app.ports.gotBatchSub.send(Object.fromEntries(pendingBackendTaskResponses));
657
- pendingBackendTaskResponses = new Map();
658
- // console.log("@@@ FLUSHING", temp.length);
644
+ // TODO - could the case where flush is called with size 0 be avoided on the Elm side?
645
+ if (pendingBackendTaskResponses.size > 0) {
646
+ // console.log("@@@ FLUSHING", pendingBackendTaskResponses.size);
647
+ app.ports.gotBatchSub.send(Object.fromEntries(pendingBackendTaskResponses));
648
+ pendingBackendTaskResponses = new Map();
649
+ }
659
650
  }
660
651
 
661
652
  /**
@@ -1,5 +1,8 @@
1
1
  const path = require("path");
2
2
  const kleur = require("kleur");
3
+ const fsPromises = require("fs/promises");
4
+
5
+ const defaultHttpCachePath = "./.elm-pages/http-cache";
3
6
 
4
7
  /** @typedef {{kind: 'cache-response-path', value: string} | {kind: 'response-json', value: JSON}} Response */
5
8
 
@@ -11,8 +14,7 @@ const kleur = require("kleur");
11
14
  * @returns {Promise<Response>}
12
15
  */
13
16
  function lookupOrPerform(portsFile, mode, rawRequest, hasFsAccess, useCache) {
14
- const fetch = require("make-fetch-happen").defaults({
15
- cachePath: "./.elm-pages/http-cache",
17
+ const makeFetchHappen = require("make-fetch-happen").defaults({
16
18
  cache: mode === "build" ? "no-cache" : "default",
17
19
  });
18
20
  return new Promise(async (resolve, reject) => {
@@ -81,7 +83,7 @@ function lookupOrPerform(portsFile, mode, rawRequest, hasFsAccess, useCache) {
81
83
  resolve({
82
84
  kind: "response-json",
83
85
  value: jsonResponse({
84
- "elm-pages-internal-error": "PortCallError",
86
+ "elm-pages-internal-error": "PortCallException",
85
87
  error: portCallError,
86
88
  }),
87
89
  });
@@ -97,7 +99,7 @@ function lookupOrPerform(portsFile, mode, rawRequest, hasFsAccess, useCache) {
97
99
  } else {
98
100
  try {
99
101
  console.time(`fetch ${request.url}`);
100
- const response = await fetch(request.url, {
102
+ const response = await safeFetch(makeFetchHappen, request.url, {
101
103
  method: request.method,
102
104
  body: request.body,
103
105
  headers: {
@@ -241,4 +243,32 @@ function jsonResponse(json) {
241
243
  return { bodyKind: "json", body: json };
242
244
  }
243
245
 
246
+ async function safeFetch(makeFetchHappen, url, options) {
247
+ const { cachePath, ...optionsWithoutCachePath } = options;
248
+ const cachePathWithDefault = cachePath || defaultHttpCachePath;
249
+ if (await canAccess(cachePathWithDefault)) {
250
+ return await makeFetchHappen(url, {
251
+ cachePath: cachePathWithDefault,
252
+ ...options,
253
+ });
254
+ } else {
255
+ return await makeFetchHappen(url, {
256
+ cache: "no-store",
257
+ ...optionsWithoutCachePath,
258
+ });
259
+ }
260
+ }
261
+
262
+ async function canAccess(filePath) {
263
+ try {
264
+ await fsPromises.access(
265
+ filePath,
266
+ fsPromises.constants.R_OK | fsPromises.constants.W_OK
267
+ );
268
+ return true;
269
+ } catch {
270
+ return false;
271
+ }
272
+ }
273
+
244
274
  module.exports = { lookupOrPerform };
@@ -224,8 +224,11 @@ function htmlSanitize(str, type) {
224
224
  );
225
225
  }
226
226
 
227
- const parseHeader = (title, path) =>
228
- `-- ${title.replace("-", " ")} --------------- ${path}`;
227
+ function parseHeader(title, path) {
228
+ return `-- ${(title || "ERROR").replace("-", " ")} --------------- ${
229
+ path || ""
230
+ }`;
231
+ }
229
232
 
230
233
  /*
231
234
  |-------------------------------------------------------------------------------
@@ -253,6 +256,14 @@ const parseConsoleErrors =
253
256
  * */
254
257
  (info) => {
255
258
  if (info.rule) {
259
+ if (info.details) {
260
+ return joinMessage(
261
+ info.details.reduce(consoleMsg, {
262
+ error: [consoleHeader(info.rule, path)],
263
+ style: [styleColor("blue")],
264
+ })
265
+ );
266
+ }
256
267
  return joinMessage(
257
268
  info.formatted.reduce(consoleMsg, {
258
269
  error: [consoleHeader(info.rule, path)],
@@ -313,6 +324,9 @@ const parseHtmlErrors = (path) => (info) => {
313
324
  if (info.rule) {
314
325
  return info.formatted.reduce(htmlMsg, htmlHeader(info.rule, path));
315
326
  } else {
327
+ if (info.details) {
328
+ return info.details.reduce(htmlMsg, htmlHeader(info.title, path));
329
+ }
316
330
  return info.message.reduce(htmlMsg, htmlHeader(info.title, path));
317
331
  }
318
332
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "elm-pages",
3
- "version": "3.0.0-beta.14",
3
+ "version": "3.0.0-beta.15",
4
4
  "homepage": "https://elm-pages.com",
5
5
  "moduleResolution": "node",
6
6
  "description": "Type-safe static sites, written in pure elm with your own custom elm-markup syntax.",
package/src/ApiRoute.elm CHANGED
@@ -199,7 +199,7 @@ single handler =
199
199
 
200
200
 
201
201
  {-| -}
202
- serverRender : ApiRouteBuilder (Server.Request.Parser (BackendTask Never (Server.Response.Response Never Never))) constructor -> ApiRoute Response
202
+ serverRender : ApiRouteBuilder (Server.Request.Parser (BackendTask Throwable (Server.Response.Response Never Never))) constructor -> ApiRoute Response
203
203
  serverRender ((ApiRouteBuilder patterns pattern _ _ _) as fullHandler) =
204
204
  ApiRoute
205
205
  { regex = Regex.fromString ("^" ++ pattern ++ "$") |> Maybe.withDefault Regex.never
@@ -225,7 +225,6 @@ serverRender ((ApiRouteBuilder patterns pattern _ _ _) as fullHandler) =
225
225
  case rendered of
226
226
  Just (Ok okRendered) ->
227
227
  okRendered
228
- |> BackendTask.onError never
229
228
 
230
229
  Just (Err errors) ->
231
230
  errors
@@ -233,13 +232,11 @@ serverRender ((ApiRouteBuilder patterns pattern _ _ _) as fullHandler) =
233
232
  |> Server.Response.plainText
234
233
  |> Server.Response.withStatusCode 400
235
234
  |> BackendTask.succeed
236
- |> BackendTask.onError never
237
235
 
238
236
  Nothing ->
239
237
  Server.Response.plainText "No matching request handler"
240
238
  |> Server.Response.withStatusCode 400
241
239
  |> BackendTask.succeed
242
- |> BackendTask.onError never
243
240
  )
244
241
  )
245
242
  |> Maybe.map (BackendTask.map (Server.Response.toJson >> Just))
@@ -8,22 +8,23 @@ down into the final `Data` value, it won't end up in the client!
8
8
 
9
9
  import BackendTask exposing (BackendTask)
10
10
  import BackendTask.Env
11
+ import Exception exposing (Throwable)
11
12
 
12
13
  type alias EnvVariables =
13
14
  { sendGridKey : String
14
15
  , siteUrl : String
15
16
  }
16
17
 
17
- sendEmail : Email -> BackendTask ()
18
+ sendEmail : Email -> BackendTask Throwable ()
18
19
  sendEmail email =
19
20
  BackendTask.map2 EnvVariables
20
- (BackendTask.Env.expect "SEND_GRID_KEY")
21
+ (BackendTask.Env.expect "SEND_GRID_KEY" |> BackendTask.throw)
21
22
  (BackendTask.Env.get "BASE_URL"
22
23
  |> BackendTask.map (Maybe.withDefault "http://localhost:1234")
23
24
  )
24
25
  |> BackendTask.andThen (sendEmailBackendTask email)
25
26
 
26
- sendEmailBackendTask : Email -> EnvVariables -> BackendTask ()
27
+ sendEmailBackendTask : Email -> EnvVariables -> BackendTask Throwable ()
27
28
  sendEmailBackendTask email envVariables =
28
29
  Debug.todo "Not defined here"
29
30
 
@@ -39,7 +40,7 @@ down into the final `Data` value, it won't end up in the client!
39
40
  import BackendTask exposing (BackendTask)
40
41
  import BackendTask.Http
41
42
  import BackendTask.Internal.Request
42
- import Exception exposing (Catchable)
43
+ import Exception exposing (Exception)
43
44
  import Json.Decode as Decode
44
45
  import Json.Encode as Encode
45
46
  import TerminalText
@@ -50,7 +51,8 @@ type Error
50
51
  = MissingEnvVariable String
51
52
 
52
53
 
53
- {-| Get an environment variable, or Nothing if there is no environment variable matching that name.
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.
54
56
  -}
55
57
  get : String -> BackendTask error (Maybe String)
56
58
  get envVariableName =
@@ -63,9 +65,9 @@ get envVariableName =
63
65
  }
64
66
 
65
67
 
66
- {-| Get an environment variable, or a BackendTask failure if there is no environment variable matching that name.
68
+ {-| Get an environment variable, or a BackendTask Exception if there is no environment variable matching that name.
67
69
  -}
68
- expect : String -> BackendTask (Catchable Error) String
70
+ expect : String -> BackendTask (Exception Error) String
69
71
  expect envVariableName =
70
72
  envVariableName
71
73
  |> get
@@ -73,7 +75,7 @@ expect envVariableName =
73
75
  (\maybeValue ->
74
76
  maybeValue
75
77
  |> Result.fromMaybe
76
- (Exception.Catchable (MissingEnvVariable envVariableName)
78
+ (Exception.Exception (MissingEnvVariable envVariableName)
77
79
  { title = "Missing Env Variable"
78
80
  , body =
79
81
  [ TerminalText.text "BackendTask.Env.expect was expecting a variable `"
@@ -51,7 +51,7 @@ plain old JSON in Elm.
51
51
  import BackendTask exposing (BackendTask)
52
52
  import BackendTask.Http
53
53
  import BackendTask.Internal.Request
54
- import Exception exposing (Catchable)
54
+ import Exception exposing (Exception)
55
55
  import Json.Decode as Decode exposing (Decoder)
56
56
  import TerminalText
57
57
 
@@ -141,7 +141,7 @@ It's common to parse the body with a markdown parser or other format.
141
141
  )
142
142
 
143
143
  -}
144
- bodyWithFrontmatter : (String -> Decoder frontmatter) -> String -> BackendTask (Catchable (FileReadError Decode.Error)) frontmatter
144
+ bodyWithFrontmatter : (String -> Decoder frontmatter) -> String -> BackendTask (Exception (FileReadError Decode.Error)) frontmatter
145
145
  bodyWithFrontmatter frontmatterDecoder filePath =
146
146
  read filePath
147
147
  (body
@@ -213,7 +213,7 @@ the [`BackendTask`](BackendTask) API along with [`BackendTask.Glob`](BackendTask
213
213
  |> BackendTask.resolve
214
214
 
215
215
  -}
216
- onlyFrontmatter : Decoder frontmatter -> String -> BackendTask (Catchable (FileReadError Decode.Error)) frontmatter
216
+ onlyFrontmatter : Decoder frontmatter -> String -> BackendTask (Exception (FileReadError Decode.Error)) frontmatter
217
217
  onlyFrontmatter frontmatterDecoder filePath =
218
218
  read filePath
219
219
  (frontmatter frontmatterDecoder)
@@ -240,7 +240,7 @@ Hey there! This is my first post :)
240
240
  Then data will yield the value `"Hey there! This is my first post :)"`.
241
241
 
242
242
  -}
243
- bodyWithoutFrontmatter : String -> BackendTask (Catchable (FileReadError decoderError)) String
243
+ bodyWithoutFrontmatter : String -> BackendTask (Exception (FileReadError decoderError)) String
244
244
  bodyWithoutFrontmatter filePath =
245
245
  read filePath
246
246
  body
@@ -264,7 +264,7 @@ You could read a file called `hello.txt` in your root project directory like thi
264
264
  File.rawFile "hello.txt"
265
265
 
266
266
  -}
267
- rawFile : String -> BackendTask (Catchable (FileReadError decoderError)) String
267
+ rawFile : String -> BackendTask (Exception (FileReadError decoderError)) String
268
268
  rawFile filePath =
269
269
  read filePath (Decode.field "rawFile" Decode.string)
270
270
 
@@ -286,7 +286,7 @@ The Decode will strip off any unused JSON data.
286
286
  "elm.json"
287
287
 
288
288
  -}
289
- jsonFile : Decoder a -> String -> BackendTask (Catchable (FileReadError Decode.Error)) a
289
+ jsonFile : Decoder a -> String -> BackendTask (Exception (FileReadError Decode.Error)) a
290
290
  jsonFile jsonFileDecoder filePath =
291
291
  rawFile filePath
292
292
  |> BackendTask.andThen
@@ -295,7 +295,7 @@ jsonFile jsonFileDecoder filePath =
295
295
  |> Decode.decodeString jsonFileDecoder
296
296
  |> Result.mapError
297
297
  (\jsonDecodeError ->
298
- Exception.Catchable (DecodingError jsonDecodeError)
298
+ Exception.Exception (DecodingError jsonDecodeError)
299
299
  { title = "JSON Decoding Error"
300
300
  , body =
301
301
  [ TerminalText.text (Decode.errorToString jsonDecodeError)
@@ -314,7 +314,7 @@ body =
314
314
  Decode.field "withoutFrontmatter" Decode.string
315
315
 
316
316
 
317
- read : String -> Decoder a -> BackendTask (Catchable (FileReadError error)) a
317
+ read : String -> Decoder a -> BackendTask (Exception (FileReadError error)) a
318
318
  read filePath decoder =
319
319
  BackendTask.Internal.Request.request
320
320
  { name = "read-file"
@@ -330,10 +330,10 @@ read filePath decoder =
330
330
  |> BackendTask.andThen BackendTask.fromResult
331
331
 
332
332
 
333
- errorDecoder : String -> Decoder (Catchable (FileReadError decoding))
333
+ errorDecoder : String -> Decoder (Exception (FileReadError decoding))
334
334
  errorDecoder filePath =
335
335
  Decode.succeed
336
- (Exception.Catchable FileDoesntExist
336
+ (Exception.Exception FileDoesntExist
337
337
  { title = "File Doesn't Exist"
338
338
  , body =
339
339
  [ TerminalText.text "Couldn't find file at path `"
@@ -229,7 +229,7 @@ import BackendTask exposing (BackendTask)
229
229
  import BackendTask.Http
230
230
  import BackendTask.Internal.Glob exposing (Glob(..))
231
231
  import BackendTask.Internal.Request
232
- import Exception exposing (Catchable, Throwable)
232
+ import Exception exposing (Exception, Throwable)
233
233
  import Json.Decode as Decode
234
234
  import Json.Encode as Encode
235
235
  import List.Extra
@@ -1054,7 +1054,7 @@ so it's ideal to make this kind of assertion rather than having fallback behavio
1054
1054
  issues (like if we had instead ignored the case where there are two or more matching blog post files).
1055
1055
 
1056
1056
  -}
1057
- expectUniqueMatch : Glob a -> BackendTask (Catchable String) a
1057
+ expectUniqueMatch : Glob a -> BackendTask (Exception String) a
1058
1058
  expectUniqueMatch glob =
1059
1059
  glob
1060
1060
  |> toBackendTask
@@ -71,7 +71,22 @@ and describe your use case!
71
71
 
72
72
  ## Caching Options
73
73
 
74
- `elm-pages` performs GET requests using a local HTTP cache by default.
74
+ `elm-pages` performs GET requests using a local HTTP cache by default. These requests are not performed using Elm's `elm/http`,
75
+ but rather are performed in NodeJS. Under the hood it uses [the NPM package `make-fetch-happen`](https://github.com/npm/make-fetch-happen).
76
+ Only GET requests made with `get`, `getJson`, or `getWithOptions` use local caching. Requests made with [`BackendTask.Http.request`](#request)
77
+ are not cached, even if the method is set to `GET`.
78
+
79
+ In dev mode, assets are cached more aggressively by default, whereas for a production build assets use a default to revalidate each cached response's freshness before using it (the `ForceRevalidate` [`CacheStrategy`](#CacheStrategy)).
80
+
81
+ The default caching behavior for GET requests is to use a local cache in `.elm-pages/http-cache`. This uses the same caching behavior
82
+ that browsers use to avoid re-downloading content when it hasn't changed. Servers can set HTTP response headers to explicitly control
83
+ this caching behavior.
84
+
85
+ - [`cache-control` HTTP response headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) let you set a length of time before considering an asset stale. This could mean that the server considers it acceptable for an asset to be somewhat outdated, or this could mean that the asset is guaranteed to be up-to-date until it is stale - those semantics are up to the server.
86
+ - `Last-Modified` and `ETag` HTTP response headers can be returned by the server allow [Conditional Requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests). Conditional Requests let us send back the `Last-Modified` timestamp or `etag` hash for assets that are in our local cache to the server to check if the asset is fresh, and skip re-downloading it if it is unchanged (or download a fresh one otherwise).
87
+
88
+ It's important to note that depending on how the server sets these HTTP response headers, we may have outdated data - either because the server explicitly allows assets to become outdated with their cache-control headers, OR because cache-control headers are not set. When these headers aren't explicitly set, [clients are allowed to cache assets for 10% of the amount of time since it was last modified](https://httpwg.org/specs/rfc7234.html#heuristic.freshness).
89
+ For production builds, the default caching will ignore both the implicit and explicit information about an asset's freshness and _always_ revalidate it before using a locally cached response.
75
90
 
76
91
  @docs getWithOptions
77
92
 
@@ -89,7 +104,7 @@ import Base64
89
104
  import Bytes exposing (Bytes)
90
105
  import Bytes.Decode
91
106
  import Dict exposing (Dict)
92
- import Exception exposing (Catchable)
107
+ import Exception exposing (Exception)
93
108
  import Json.Decode
94
109
  import Json.Encode as Encode
95
110
  import Pages.Internal.StaticHttpBody as Body
@@ -138,15 +153,16 @@ type alias Body =
138
153
  Body.Body
139
154
 
140
155
 
141
- {-| A simplified helper around [`BackendTask.Http.request`](#request), which builds up a BackendTask.Http GET request.
156
+ {-| A simplified helper around [`BackendTask.Http.get`](#get), which builds up a BackendTask.Http GET request with `expectJson`.
142
157
 
143
158
  import BackendTask
144
159
  import BackendTask.Http
160
+ import Exception exposing (Exception)
145
161
  import Json.Decode as Decode exposing (Decoder)
146
162
 
147
- getRequest : BackendTask Int
163
+ getRequest : BackendTask (Exception Error) Int
148
164
  getRequest =
149
- BackendTask.Http.get
165
+ BackendTask.Http.getJson
150
166
  "https://api.github.com/repos/dillonkearns/elm-pages"
151
167
  (Decode.field "stargazers_count" Decode.int)
152
168
 
@@ -154,7 +170,7 @@ type alias Body =
154
170
  getJson :
155
171
  String
156
172
  -> Json.Decode.Decoder a
157
- -> BackendTask (Catchable Error) a
173
+ -> BackendTask (Exception Error) a
158
174
  getJson url decoder =
159
175
  getWithOptions
160
176
  { url = url
@@ -167,11 +183,25 @@ getJson url decoder =
167
183
  }
168
184
 
169
185
 
170
- {-| -}
186
+ {-| A simplified helper around [`BackendTask.Http.getWithOptions`](#getWithOptions), which builds up a GET request with
187
+ the default retries, timeout, and HTTP caching options. If you need to configure those options or include HTTP request headers,
188
+ use the more flexible `getWithOptions`.
189
+
190
+ import BackendTask
191
+ import BackendTask.Http
192
+ import Exception exposing (Exception)
193
+
194
+ getRequest : BackendTask (Exception Error) String
195
+ getRequest =
196
+ BackendTask.Http.get
197
+ "https://api.github.com/repos/dillonkearns/elm-pages"
198
+ BackendTask.Http.expectString
199
+
200
+ -}
171
201
  get :
172
202
  String
173
203
  -> Expect a
174
- -> BackendTask (Catchable Error) a
204
+ -> BackendTask (Exception Error) a
175
205
  get url expect =
176
206
  getWithOptions
177
207
  { url = url
@@ -185,6 +215,12 @@ get url expect =
185
215
 
186
216
 
187
217
  {-| Perform a GET request, with some additional options for the HTTP request, including options for caching behavior.
218
+
219
+ - `retries` - Default is 0. Will try performing request again if set to a number greater than 0.
220
+ - `timeoutInMs` - Default is no timeout.
221
+ - `cacheStrategy` - The [caching options are passed to the NPM package `make-fetch-happen`](https://github.com/npm/make-fetch-happen#opts-cache)
222
+ - `cachePath` - override the default directory for the local HTTP cache. This can be helpful if you want more granular control to clear some HTTP caches more or less frequently than others. Or you may want to preserve the local cache for some requests in your build server, but not store the cache for other requests.
223
+
188
224
  -}
189
225
  getWithOptions :
190
226
  { url : String
@@ -195,7 +231,7 @@ getWithOptions :
195
231
  , timeoutInMs : Maybe Int
196
232
  , cachePath : Maybe String
197
233
  }
198
- -> BackendTask (Catchable Error) a
234
+ -> BackendTask (Exception Error) a
199
235
  getWithOptions request__ =
200
236
  let
201
237
  request_ : HashRequest.Request
@@ -222,7 +258,7 @@ post :
222
258
  String
223
259
  -> Body
224
260
  -> Expect a
225
- -> BackendTask (Catchable Error) a
261
+ -> BackendTask (Exception Error) a
226
262
  post url body expect =
227
263
  request
228
264
  { url = url
@@ -361,7 +397,7 @@ request :
361
397
  , timeoutInMs : Maybe Int
362
398
  }
363
399
  -> Expect a
364
- -> BackendTask (Catchable Error) a
400
+ -> BackendTask (Exception Error) a
365
401
  request request__ expect =
366
402
  let
367
403
  request_ : HashRequest.Request
@@ -439,7 +475,7 @@ with this as a low-level detail, or you can use functions like [BackendTask.Http
439
475
  requestRaw :
440
476
  HashRequest.Request
441
477
  -> Expect a
442
- -> BackendTask (Catchable Error) a
478
+ -> BackendTask (Exception Error) a
443
479
  requestRaw request__ expect =
444
480
  let
445
481
  request_ : HashRequest.Request
@@ -537,7 +573,7 @@ requestRaw request__ expect =
537
573
  |> BackendTask.fromResult
538
574
  |> BackendTask.mapError
539
575
  (\error ->
540
- Exception.Catchable error (errorToString error)
576
+ Exception.Exception error (errorToString error)
541
577
  )
542
578
  )
543
579