elm-pages 3.0.0-beta.8 → 3.0.0

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 (164) hide show
  1. package/README.md +11 -2
  2. package/adapter/netlify.js +207 -0
  3. package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2730 -2938
  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 +1527 -422
  12. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +16840 -13653
  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 +2 -2
  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 +1527 -422
  27. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25118 -21832
  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 +2 -2
  30. package/generator/review/elm.json +10 -10
  31. package/generator/src/RouteBuilder.elm +93 -128
  32. package/generator/src/SharedTemplate.elm +8 -7
  33. package/generator/src/SiteConfig.elm +3 -2
  34. package/generator/src/basepath-middleware.js +3 -3
  35. package/generator/src/build.js +147 -63
  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 +2 -4
  41. package/generator/src/copy-dir.js +2 -2
  42. package/generator/src/dev-server.js +159 -92
  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 +10 -13
  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 +1 -2
  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 +3 -2
  65. package/generator/template/app/Effect.elm +155 -0
  66. package/generator/template/app/ErrorPage.elm +49 -6
  67. package/generator/template/app/Route/Blog/Slug_.elm +86 -0
  68. package/generator/template/app/Route/Greet.elm +107 -0
  69. package/generator/template/app/Route/Hello.elm +119 -0
  70. package/generator/template/app/Route/Index.elm +26 -25
  71. package/generator/template/app/Shared.elm +38 -39
  72. package/generator/template/app/Site.elm +4 -7
  73. package/generator/template/app/View.elm +9 -8
  74. package/generator/template/codegen/elm.codegen.json +18 -0
  75. package/generator/template/custom-backend-task.ts +3 -0
  76. package/generator/template/elm-pages.config.mjs +13 -0
  77. package/generator/template/elm-tooling.json +0 -3
  78. package/generator/template/elm.json +25 -20
  79. package/generator/template/index.ts +1 -2
  80. package/generator/template/netlify.toml +4 -1
  81. package/generator/template/package.json +10 -4
  82. package/generator/template/script/.elm-pages/compiled-ports/custom-backend-task.mjs +7 -0
  83. package/generator/template/script/custom-backend-task.ts +3 -0
  84. package/generator/template/script/elm.json +61 -0
  85. package/generator/template/script/src/AddRoute.elm +312 -0
  86. package/generator/template/script/src/Stars.elm +42 -0
  87. package/package.json +30 -27
  88. package/src/ApiRoute.elm +249 -85
  89. package/src/BackendTask/Custom.elm +325 -0
  90. package/src/BackendTask/Env.elm +90 -0
  91. package/src/{DataSource → BackendTask}/File.elm +171 -56
  92. package/src/{DataSource → BackendTask}/Glob.elm +136 -125
  93. package/src/BackendTask/Http.elm +679 -0
  94. package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
  95. package/src/BackendTask/Internal/Request.elm +69 -0
  96. package/src/BackendTask/Random.elm +79 -0
  97. package/src/BackendTask/Time.elm +47 -0
  98. package/src/BackendTask.elm +531 -0
  99. package/src/FatalError.elm +90 -0
  100. package/src/FormData.elm +21 -18
  101. package/src/Head/Seo.elm +4 -4
  102. package/src/Head.elm +237 -7
  103. package/src/Internal/ApiRoute.elm +7 -5
  104. package/src/Internal/Request.elm +84 -4
  105. package/src/PageServerResponse.elm +6 -1
  106. package/src/Pages/ConcurrentSubmission.elm +127 -0
  107. package/src/Pages/Form.elm +340 -0
  108. package/src/Pages/FormData.elm +19 -0
  109. package/src/Pages/GeneratorProgramConfig.elm +15 -0
  110. package/src/Pages/Internal/FatalError.elm +5 -0
  111. package/src/Pages/Internal/Msg.elm +93 -0
  112. package/src/Pages/Internal/NotFoundReason.elm +4 -4
  113. package/src/Pages/Internal/Platform/Cli.elm +629 -767
  114. package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
  115. package/src/Pages/Internal/Platform/Effect.elm +1 -2
  116. package/src/Pages/Internal/Platform/GeneratorApplication.elm +379 -0
  117. package/src/Pages/Internal/Platform/StaticResponses.elm +65 -276
  118. package/src/Pages/Internal/Platform/ToJsPayload.elm +6 -9
  119. package/src/Pages/Internal/Platform.elm +330 -203
  120. package/src/Pages/Internal/ResponseSketch.elm +2 -2
  121. package/src/Pages/Internal/Script.elm +17 -0
  122. package/src/Pages/Internal/StaticHttpBody.elm +35 -1
  123. package/src/Pages/Manifest.elm +52 -11
  124. package/src/Pages/Navigation.elm +85 -0
  125. package/src/Pages/PageUrl.elm +26 -12
  126. package/src/Pages/ProgramConfig.elm +32 -22
  127. package/src/Pages/Script.elm +166 -0
  128. package/src/Pages/SiteConfig.elm +3 -2
  129. package/src/Pages/StaticHttp/Request.elm +2 -2
  130. package/src/Pages/StaticHttpRequest.elm +23 -99
  131. package/src/Pages/Url.elm +3 -3
  132. package/src/PagesMsg.elm +88 -0
  133. package/src/QueryParams.elm +21 -172
  134. package/src/RenderRequest.elm +7 -7
  135. package/src/RequestsAndPending.elm +37 -20
  136. package/src/Result/Extra.elm +26 -0
  137. package/src/Scaffold/Form.elm +569 -0
  138. package/src/Scaffold/Route.elm +1431 -0
  139. package/src/Server/Request.elm +476 -1001
  140. package/src/Server/Response.elm +130 -36
  141. package/src/Server/Session.elm +181 -111
  142. package/src/Server/SetCookie.elm +80 -32
  143. package/src/Stub.elm +53 -0
  144. package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
  145. package/src/{Path.elm → UrlPath.elm} +33 -36
  146. package/generator/template/public/images/icon-png.png +0 -0
  147. package/src/DataSource/Env.elm +0 -38
  148. package/src/DataSource/Http.elm +0 -446
  149. package/src/DataSource/Internal/Request.elm +0 -20
  150. package/src/DataSource/Port.elm +0 -90
  151. package/src/DataSource.elm +0 -538
  152. package/src/Form/Field.elm +0 -717
  153. package/src/Form/FieldStatus.elm +0 -36
  154. package/src/Form/FieldView.elm +0 -417
  155. package/src/Form/FormData.elm +0 -22
  156. package/src/Form/Validation.elm +0 -391
  157. package/src/Form/Value.elm +0 -118
  158. package/src/Form.elm +0 -1683
  159. package/src/FormDecoder.elm +0 -102
  160. package/src/Pages/FormState.elm +0 -256
  161. package/src/Pages/Generate.elm +0 -1151
  162. package/src/Pages/Internal/Form.elm +0 -17
  163. package/src/Pages/Msg.elm +0 -79
  164. package/src/Pages/Transition.elm +0 -70
package/src/ApiRoute.elm CHANGED
@@ -1,32 +1,166 @@
1
1
  module ApiRoute exposing
2
- ( ApiRoute, ApiRouteBuilder, Response
2
+ ( single, preRender
3
+ , serverRender
4
+ , preRenderWithFallback
5
+ , ApiRoute, ApiRouteBuilder, Response
3
6
  , capture, literal, slash, succeed
4
- , single, preRender
5
- , preRenderWithFallback, serverRender
6
7
  , withGlobalHeadTags
7
- , toJson, getBuildTimeRoutes, getGlobalHeadTagsDataSource
8
+ , toJson, getBuildTimeRoutes, getGlobalHeadTagsBackendTask
8
9
  )
9
10
 
10
- {-| ApiRoute's are defined in `src/Api.elm` and are a way to generate files, like RSS feeds, sitemaps, or any text-based file that you output with an Elm function! You get access
11
- to a DataSource so you can pull in HTTP data, etc. Because ApiRoutes don't hydrate into Elm apps (like pages in elm-pages do), you can pull in as much data as you want in
12
- the DataSource for your ApiRoutes, and it won't effect the payload size. Instead, the size of an ApiRoute is just the content you output for that route.
11
+ {-| ApiRoute's are defined in `src/Api.elm` and are a way to generate files either statically pre-rendered at build-time (like RSS feeds, sitemaps, or any text-based file that you output with an Elm function),
12
+ or server-rendered at runtime (like a JSON API endpoint, or an RSS feed that gives you fresh data without rebuilding your site).
13
13
 
14
- In a future release, ApiRoutes may be able to run at request-time in a serverless function, allowing you to use pure Elm code to create dynamic APIs, and even pulling in data from
15
- DataSources dynamically.
14
+ Your ApiRoute's get access to a [`BackendTask`](BackendTask) so you can pull in HTTP data, etc. Because ApiRoutes don't hydrate into Elm apps (like pages in elm-pages do), you can pull in as much data as you want in
15
+ the BackendTask for your ApiRoutes and it won't effect the payload size. Instead, the size of an ApiRoute is just the content you output for that route.
16
16
 
17
- @docs ApiRoute, ApiRouteBuilder, Response
18
-
19
- @docs capture, literal, slash, succeed
17
+ Similar to your elm-pages Route Modules, ApiRoute's can be either server-rendered or pre-rendered. Let's compare the differences between pre-rendered and server-rendered ApiRoutes, and the different
18
+ use cases they support.
20
19
 
21
20
 
22
21
  ## Pre-Rendering
23
22
 
23
+ A pre-rendered ApiRoute is just a generated file. For example:
24
+
25
+ - [An RSS feed](https://github.com/dillonkearns/elm-pages/blob/131f7b750cdefb2ba7a34a06be06dfbfafc79a86/examples/docs/app/Api.elm#L77-L84) ([Output file](https://elm-pages.com/blog/feed.xml))
26
+ - [A calendar feed in the ical format](https://github.com/dillonkearns/incrementalelm.com/blob/d4934d899d06232dc66dcf9f4b5eccc74bbc60d3/src/Api.elm#L51-L60) ([Output file](https://incrementalelm.com/live.ics))
27
+ - A redirect file for a hosting provider like Netlify
28
+
29
+ You could even generate a JavaScript file, an Elm file, or any file with a String body! It's really just a way to generate files, which are typically used to serve files to a user or Browser, but you execute them, copy them, etc. The only limit is your imagination!
30
+ The beauty is that you have a way to 1) pull in type-safe data using BackendTask's, and 2) write those files, and all in pure Elm!
31
+
24
32
  @docs single, preRender
25
33
 
26
34
 
27
35
  ## Server Rendering
28
36
 
29
- @docs preRenderWithFallback, serverRender
37
+ You could use server-rendered ApiRoutes to do a lot of similar things, the main difference being that it will be served up through a URL and generated on-demand when that URL is requested.
38
+ So for example, for an RSS feed or ical calendar feed like in the pre-rendered examples, you could build the same routes, but you would be pulling in the list of posts or calendar events on-demand rather
39
+ than upfront at build-time. That means you can hit your database and serve up always-up-to-date data.
40
+
41
+ Not only that, but your server-rendered ApiRoutes have access to the incoming HTTP request payload just like your server-rendered Route Modules do. Just as with server-rendered Route Modules,
42
+ a server-rendered ApiRoute accesses the incoming HTTP request through a [Server.Request.Parser](Server-Request). Consider the use cases that this opens up:
43
+
44
+ - Serve up protected assets. For example, gated content, like a paid subscriber feed for a podcast that checks authentication information in a query parameter to authenticate that a user has an active paid subscription before serving up the Pro RSS feed.
45
+ - Serve up user-specific content, either through a cookie or other means of authentication
46
+ - Look at the [accepted content-type in the request headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) and use that to choose a response format, like XML or JSON ([full example](https://github.com/dillonkearns/elm-pages/blob/131f7b750cdefb2ba7a34a06be06dfbfafc79a86/examples/end-to-end/app/Api.elm#L76-L107)).
47
+ - Look at the [accepted language in the request headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language) and use that to choose a language for the response data.
48
+
49
+ @docs serverRender
50
+
51
+ You can also do a hybrid approach using `preRenderWithFallback`. This allows you to pre-render a set of routes at build-time, but build additional routes that weren't rendered at build-time on the fly on the server.
52
+ Conceptually, this is just a delayed version of a pre-rendered route. Because of that, you _do not_ have access to the incoming HTTP request (no `Server.Request.Parser` like in server-rendered ApiRoute's).
53
+ The strategy used to build these routes will differ depending on your hosting provider and the elm-pages adapter you have setup, but generally ApiRoute's that use `preRenderWithFallback` will be cached on the server
54
+ so within a certain time interval (or in the case of [Netlify's DPR](https://www.netlify.com/blog/2021/04/14/distributed-persistent-rendering-a-new-jamstack-approach-for-faster-builds/), until a new build is done)
55
+ that asset will be served up if that URL was already served up by the server.
56
+
57
+ @docs preRenderWithFallback
58
+
59
+
60
+ ## Defining ApiRoute's
61
+
62
+ You define your ApiRoute's in `app/Api.elm`. Here's a simple example:
63
+
64
+ module Api exposing (routes)
65
+
66
+ import ApiRoute
67
+ import BackendTask exposing (BackendTask)
68
+ import Server.Request
69
+
70
+ routes :
71
+ BackendTask (List Route)
72
+ -> (Maybe { indent : Int, newLines : Bool } -> Html Never -> String)
73
+ -> List (ApiRoute.ApiRoute ApiRoute.Response)
74
+ routes getStaticRoutes htmlToString =
75
+ [ preRenderedExample
76
+ , requestPrinterExample
77
+ ]
78
+
79
+ {-| Generates the following files when you
80
+ run `elm-pages build`:
81
+
82
+ - `dist/users/1.json`
83
+ - `dist/users/2.json`
84
+ - `dist/users/3.json`
85
+
86
+ When you host it, these static assets will
87
+ be served at `/users/1.json`, etc.
88
+
89
+ -}
90
+ preRenderedExample : ApiRoute.ApiRoute ApiRoute.Response
91
+ preRenderedExample =
92
+ ApiRoute.succeed
93
+ (\userId ->
94
+ BackendTask.succeed
95
+ (Json.Encode.object
96
+ [ ( "id", Json.Encode.string userId )
97
+ , ( "name", "Data for user " ++ userId |> Json.Encode.string )
98
+ ]
99
+ |> Json.Encode.encode 2
100
+ )
101
+ )
102
+ |> ApiRoute.literal "users"
103
+ |> ApiRoute.slash
104
+ |> ApiRoute.capture
105
+ |> ApiRoute.literal ".json"
106
+ |> ApiRoute.preRender
107
+ (\route ->
108
+ BackendTask.succeed
109
+ [ route "1"
110
+ , route "2"
111
+ , route "3"
112
+ ]
113
+ )
114
+
115
+ {-| This returns a JSON response that prints information about the incoming
116
+ HTTP request. In practice you'd want to do something useful with that data,
117
+ and use more of the high-level helpers from the Server.Request API.
118
+ -}
119
+ requestPrinterExample : ApiRoute ApiRoute.Response
120
+ requestPrinterExample =
121
+ ApiRoute.succeed
122
+ (Server.Request.map4
123
+ (\rawBody method cookies queryParams ->
124
+ Encode.object
125
+ [ ( "rawBody"
126
+ , rawBody
127
+ |> Maybe.map Encode.string
128
+ |> Maybe.withDefault Encode.null
129
+ )
130
+ , ( "method"
131
+ , method
132
+ |> Server.Request.methodToString
133
+ |> Encode.string
134
+ )
135
+ , ( "cookies"
136
+ , cookies
137
+ |> Encode.dict
138
+ identity
139
+ Encode.string
140
+ )
141
+ , ( "queryParams"
142
+ , queryParams
143
+ |> Encode.dict
144
+ identity
145
+ (Encode.list Encode.string)
146
+ )
147
+ ]
148
+ |> Response.json
149
+ |> BackendTask.succeed
150
+ )
151
+ Server.Request.rawBody
152
+ Server.Request.method
153
+ Server.Request.allCookies
154
+ Server.Request.queryParams
155
+ )
156
+ |> ApiRoute.literal "api"
157
+ |> ApiRoute.slash
158
+ |> ApiRoute.literal "request-test"
159
+ |> ApiRoute.serverRender
160
+
161
+ @docs ApiRoute, ApiRouteBuilder, Response
162
+
163
+ @docs capture, literal, slash, succeed
30
164
 
31
165
 
32
166
  ## Including Head Tags
@@ -36,15 +170,15 @@ DataSources dynamically.
36
170
 
37
171
  ## Internals
38
172
 
39
- @docs toJson, getBuildTimeRoutes, getGlobalHeadTagsDataSource
173
+ @docs toJson, getBuildTimeRoutes, getGlobalHeadTagsBackendTask
40
174
 
41
175
  -}
42
176
 
43
- import DataSource exposing (DataSource)
44
- import DataSource.Http
177
+ import BackendTask exposing (BackendTask)
178
+ import FatalError exposing (FatalError)
45
179
  import Head
46
180
  import Internal.ApiRoute exposing (ApiRoute(..), ApiRouteBuilder(..))
47
- import Json.Decode as Decode
181
+ import Internal.Request
48
182
  import Json.Encode
49
183
  import Pattern
50
184
  import Regex
@@ -57,52 +191,34 @@ type alias ApiRoute response =
57
191
  Internal.ApiRoute.ApiRoute response
58
192
 
59
193
 
60
- {-| -}
61
- single : ApiRouteBuilder (DataSource String) (List String) -> ApiRoute Response
194
+ {-| Same as [`preRender`](#preRender), but for an ApiRoute that has no dynamic segments. This is just a bit simpler because
195
+ since there are no dynamic segments, you don't need to provide a BackendTask with the list of dynamic segments to pre-render because there is only a single possible route.
196
+ -}
197
+ single : ApiRouteBuilder (BackendTask FatalError String) (List String) -> ApiRoute Response
62
198
  single handler =
63
199
  handler
64
- |> preRender (\constructor -> DataSource.succeed [ constructor ])
200
+ |> preRender (\constructor -> BackendTask.succeed [ constructor ])
65
201
 
66
202
 
67
203
  {-| -}
68
- serverRender : ApiRouteBuilder (Server.Request.Parser (DataSource (Server.Response.Response Never Never))) constructor -> ApiRoute Response
204
+ serverRender : ApiRouteBuilder (Server.Request.Request -> BackendTask FatalError (Server.Response.Response Never Never)) constructor -> ApiRoute Response
69
205
  serverRender ((ApiRouteBuilder patterns pattern _ _ _) as fullHandler) =
70
206
  ApiRoute
71
207
  { regex = Regex.fromString ("^" ++ pattern ++ "$") |> Maybe.withDefault Regex.never
72
208
  , matchesToResponse =
73
- \path ->
209
+ \serverRequest path ->
74
210
  Internal.ApiRoute.tryMatch path fullHandler
75
211
  |> Maybe.map
76
- (\toDataSource ->
77
- DataSource.Http.get
78
- "$$elm-pages$$headers"
79
- (toDataSource |> Server.Request.getDecoder |> Decode.map Just)
80
- |> DataSource.andThen
81
- (\rendered ->
82
- case rendered of
83
- Just (Ok okRendered) ->
84
- okRendered
85
-
86
- Just (Err errors) ->
87
- errors
88
- |> Server.Request.errorsToString
89
- |> Server.Response.plainText
90
- |> Server.Response.withStatusCode 400
91
- |> DataSource.succeed
92
-
93
- Nothing ->
94
- Server.Response.plainText "No matching request handler"
95
- |> Server.Response.withStatusCode 400
96
- |> DataSource.succeed
97
- )
212
+ (\toBackendTask ->
213
+ toBackendTask (Internal.Request.toRequest serverRequest)
98
214
  )
99
- |> Maybe.map (DataSource.map (Server.Response.toJson >> Just))
215
+ |> Maybe.map (BackendTask.map (Server.Response.toJson >> Just))
100
216
  |> Maybe.withDefault
101
- (DataSource.succeed Nothing)
102
- , buildTimeRoutes = DataSource.succeed []
217
+ (BackendTask.succeed Nothing)
218
+ , buildTimeRoutes = BackendTask.succeed []
103
219
  , handleRoute =
104
220
  \path ->
105
- DataSource.succeed
221
+ BackendTask.succeed
106
222
  (case Internal.ApiRoute.tryMatch path fullHandler of
107
223
  Just _ ->
108
224
  True
@@ -117,26 +233,26 @@ serverRender ((ApiRouteBuilder patterns pattern _ _ _) as fullHandler) =
117
233
 
118
234
 
119
235
  {-| -}
120
- preRenderWithFallback : (constructor -> DataSource (List (List String))) -> ApiRouteBuilder (DataSource (Server.Response.Response Never Never)) constructor -> ApiRoute Response
236
+ preRenderWithFallback : (constructor -> BackendTask FatalError (List (List String))) -> ApiRouteBuilder (BackendTask FatalError (Server.Response.Response Never Never)) constructor -> ApiRoute Response
121
237
  preRenderWithFallback buildUrls ((ApiRouteBuilder patterns pattern _ toString constructor) as fullHandler) =
122
238
  let
123
- buildTimeRoutes__ : DataSource (List String)
239
+ buildTimeRoutes__ : BackendTask FatalError (List String)
124
240
  buildTimeRoutes__ =
125
241
  buildUrls (constructor [])
126
- |> DataSource.map (List.map toString)
242
+ |> BackendTask.map (List.map toString)
127
243
  in
128
244
  ApiRoute
129
245
  { regex = Regex.fromString ("^" ++ pattern ++ "$") |> Maybe.withDefault Regex.never
130
246
  , matchesToResponse =
131
- \path ->
247
+ \_ path ->
132
248
  Internal.ApiRoute.tryMatch path fullHandler
133
- |> Maybe.map (DataSource.map (Server.Response.toJson >> Just))
249
+ |> Maybe.map (BackendTask.map (Server.Response.toJson >> Just))
134
250
  |> Maybe.withDefault
135
- (DataSource.succeed Nothing)
251
+ (BackendTask.succeed Nothing)
136
252
  , buildTimeRoutes = buildTimeRoutes__
137
253
  , handleRoute =
138
254
  \path ->
139
- DataSource.succeed
255
+ BackendTask.succeed
140
256
  (case Internal.ApiRoute.tryMatch path fullHandler of
141
257
  Just _ ->
142
258
  True
@@ -158,43 +274,90 @@ encodeStaticFileBody fileBody =
158
274
  ]
159
275
 
160
276
 
161
- {-| -}
162
- preRender : (constructor -> DataSource (List (List String))) -> ApiRouteBuilder (DataSource String) constructor -> ApiRoute Response
277
+ {-| Pre-render files for a given route pattern statically at build-time. If you only need to serve a single file, you can use [`single`](#single) instead.
278
+
279
+ import ApiRoute
280
+ import BackendTask
281
+ import BackendTask.Http
282
+ import Json.Decode as Decode
283
+ import Json.Encode as Encode
284
+
285
+ starsApi : ApiRoute ApiRoute.Response
286
+ starsApi =
287
+ ApiRoute.succeed
288
+ (\user repoName ->
289
+ BackendTask.Http.getJson
290
+ ("https://api.github.com/repos/" ++ user ++ "/" ++ repoName)
291
+ (Decode.field "stargazers_count" Decode.int)
292
+ |> BackendTask.allowFatal
293
+ |> BackendTask.map
294
+ (\stars ->
295
+ Encode.object
296
+ [ ( "repo", Encode.string repoName )
297
+ , ( "stars", Encode.int stars )
298
+ ]
299
+ |> Encode.encode 2
300
+ )
301
+ )
302
+ |> ApiRoute.literal "repo"
303
+ |> ApiRoute.slash
304
+ |> ApiRoute.capture
305
+ |> ApiRoute.slash
306
+ |> ApiRoute.capture
307
+ |> ApiRoute.slash
308
+ |> ApiRoute.literal ".json"
309
+ |> ApiRoute.preRender
310
+ (\route ->
311
+ BackendTask.succeed
312
+ [ route "dillonkearns" "elm-graphql"
313
+ , route "dillonkearns" "elm-pages"
314
+ ]
315
+ )
316
+
317
+ You can view these files in the dev server at <http://localhost:1234/repo/dillonkearns/elm-graphql.json>, and when you run `elm-pages build` this will result in the following files being generated:
318
+
319
+ - `dist/repo/dillonkearns/elm-graphql.json`
320
+ - `dist/repo/dillonkearns/elm-pages.json`
321
+
322
+ Note: `dist` is the output folder for `elm-pages build`, so this will be accessible in your hosted site at `/repo/dillonkearns/elm-graphql.json` and `/repo/dillonkearns/elm-pages.json`.
323
+
324
+ -}
325
+ preRender : (constructor -> BackendTask FatalError (List (List String))) -> ApiRouteBuilder (BackendTask FatalError String) constructor -> ApiRoute Response
163
326
  preRender buildUrls ((ApiRouteBuilder patterns pattern _ toString constructor) as fullHandler) =
164
327
  let
165
- buildTimeRoutes__ : DataSource (List String)
328
+ buildTimeRoutes__ : BackendTask FatalError (List String)
166
329
  buildTimeRoutes__ =
167
330
  buildUrls (constructor [])
168
- |> DataSource.map (List.map toString)
331
+ |> BackendTask.map (List.map toString)
169
332
 
170
- preBuiltMatches : DataSource (List (List String))
333
+ preBuiltMatches : BackendTask FatalError (List (List String))
171
334
  preBuiltMatches =
172
335
  buildUrls (constructor [])
173
336
  in
174
337
  ApiRoute
175
338
  { regex = Regex.fromString ("^" ++ pattern ++ "$") |> Maybe.withDefault Regex.never
176
339
  , matchesToResponse =
177
- \path ->
340
+ \_ path ->
178
341
  let
179
342
  matches : List String
180
343
  matches =
181
344
  Internal.ApiRoute.pathToMatches path fullHandler
182
345
 
183
- routeFound : DataSource Bool
346
+ routeFound : BackendTask FatalError Bool
184
347
  routeFound =
185
348
  preBuiltMatches
186
- |> DataSource.map (List.member matches)
349
+ |> BackendTask.map (List.member matches)
187
350
  in
188
351
  routeFound
189
- |> DataSource.andThen
352
+ |> BackendTask.andThen
190
353
  (\found ->
191
354
  if found then
192
355
  Internal.ApiRoute.tryMatch path fullHandler
193
- |> Maybe.map (DataSource.map (encodeStaticFileBody >> Just))
194
- |> Maybe.withDefault (DataSource.succeed Nothing)
356
+ |> Maybe.map (BackendTask.map (encodeStaticFileBody >> Just))
357
+ |> Maybe.withDefault (BackendTask.succeed Nothing)
195
358
 
196
359
  else
197
- DataSource.succeed Nothing
360
+ BackendTask.succeed Nothing
198
361
  )
199
362
  , buildTimeRoutes = buildTimeRoutes__
200
363
  , handleRoute =
@@ -205,24 +368,27 @@ preRender buildUrls ((ApiRouteBuilder patterns pattern _ toString constructor) a
205
368
  Internal.ApiRoute.pathToMatches path fullHandler
206
369
  in
207
370
  preBuiltMatches
208
- |> DataSource.map (List.member matches)
371
+ |> BackendTask.map (List.member matches)
209
372
  , pattern = patterns
210
373
  , kind = "prerender"
211
374
  , globalHeadTags = Nothing
212
375
  }
213
376
 
214
377
 
215
- {-| -}
378
+ {-| The intermediary value while building an ApiRoute definition.
379
+ -}
216
380
  type alias ApiRouteBuilder a constructor =
217
381
  Internal.ApiRoute.ApiRouteBuilder a constructor
218
382
 
219
383
 
220
- {-| -}
384
+ {-| The final value from defining an ApiRoute.
385
+ -}
221
386
  type alias Response =
222
387
  Json.Encode.Value
223
388
 
224
389
 
225
- {-| -}
390
+ {-| Starts the definition of a route with any captured segments.
391
+ -}
226
392
  succeed : a -> ApiRouteBuilder a (List String)
227
393
  succeed a =
228
394
  ApiRouteBuilder Pattern.empty "" (\_ -> a) (\_ -> "") (\list -> list)
@@ -238,7 +404,8 @@ toJson ((ApiRoute { kind }) as apiRoute) =
238
404
  ]
239
405
 
240
406
 
241
- {-| -}
407
+ {-| A literal String segment of a route.
408
+ -}
242
409
  literal : String -> ApiRouteBuilder a constructor -> ApiRouteBuilder a constructor
243
410
  literal segment (ApiRouteBuilder patterns pattern handler toString constructor) =
244
411
  ApiRouteBuilder
@@ -249,13 +416,15 @@ literal segment (ApiRouteBuilder patterns pattern handler toString constructor)
249
416
  constructor
250
417
 
251
418
 
252
- {-| -}
419
+ {-| A path separator within the route.
420
+ -}
253
421
  slash : ApiRouteBuilder a constructor -> ApiRouteBuilder a constructor
254
422
  slash (ApiRouteBuilder patterns pattern handler toString constructor) =
255
423
  ApiRouteBuilder (patterns |> Pattern.addSlash) (pattern ++ "/") handler (\arg -> toString arg ++ "/") constructor
256
424
 
257
425
 
258
- {-| -}
426
+ {-| Captures a dynamic segment from the route.
427
+ -}
259
428
  capture :
260
429
  ApiRouteBuilder (String -> a) constructor
261
430
  -> ApiRouteBuilder a (String -> constructor)
@@ -287,25 +456,20 @@ capture (ApiRouteBuilder patterns pattern previousHandler toString constructor)
287
456
 
288
457
  {-| For internal use by generated code. Not so useful in user-land.
289
458
  -}
290
- getBuildTimeRoutes : ApiRoute response -> DataSource (List String)
459
+ getBuildTimeRoutes : ApiRoute response -> BackendTask FatalError (List String)
291
460
  getBuildTimeRoutes (ApiRoute handler) =
292
461
  handler.buildTimeRoutes
293
462
 
294
463
 
295
464
  {-| Include head tags on every page's HTML.
296
465
  -}
297
- withGlobalHeadTags : DataSource (List Head.Tag) -> ApiRoute response -> ApiRoute response
466
+ withGlobalHeadTags : BackendTask FatalError (List Head.Tag) -> ApiRoute response -> ApiRoute response
298
467
  withGlobalHeadTags globalHeadTags (ApiRoute handler) =
299
468
  ApiRoute { handler | globalHeadTags = Just globalHeadTags }
300
469
 
301
470
 
302
- {-| -}
303
- getGlobalHeadTagsDataSource : ApiRoute response -> Maybe (DataSource (List Head.Tag))
304
- getGlobalHeadTagsDataSource (ApiRoute handler) =
471
+ {-| For internal use.
472
+ -}
473
+ getGlobalHeadTagsBackendTask : ApiRoute response -> Maybe (BackendTask FatalError (List Head.Tag))
474
+ getGlobalHeadTagsBackendTask (ApiRoute handler) =
305
475
  handler.globalHeadTags
306
-
307
-
308
-
309
- --captureRest : ApiRouteBuilder (List String -> a) b -> ApiRouteBuilder a b
310
- --captureRest previousHandler =
311
- -- Debug.todo ""