elm-pages 3.0.0-beta.1 → 3.0.0-beta.12

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 (103) hide show
  1. package/README.md +10 -1
  2. package/codegen/elm-pages-codegen.js +803 -284
  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 +1326 -121
  11. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +15368 -13272
  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 +1 -1
  14. package/generator/dead-code-review/elm.json +6 -5
  15. package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +141 -17
  16. package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +218 -0
  17. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  18. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  19. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  20. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
  21. package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1326 -121
  22. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +14574 -12631
  23. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  24. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +1 -1
  25. package/generator/review/elm.json +6 -6
  26. package/generator/src/SharedTemplate.elm +1 -1
  27. package/generator/src/build.js +81 -51
  28. package/generator/src/cli.js +120 -42
  29. package/generator/src/codegen.js +11 -10
  30. package/generator/src/compatibility-key.js +1 -0
  31. package/generator/src/config.js +41 -0
  32. package/generator/src/dev-server.js +36 -56
  33. package/generator/src/elm-codegen.js +3 -0
  34. package/generator/src/generate-template-module-connector.js +0 -28
  35. package/generator/src/pre-render-html.js +31 -17
  36. package/generator/src/render-worker.js +1 -1
  37. package/generator/src/render.js +224 -37
  38. package/generator/src/request-cache.js +1 -0
  39. package/generator/src/rewrite-elm-json.js +3 -3
  40. package/generator/src/seo-renderer.js +11 -4
  41. package/generator/src/vite-utils.js +78 -0
  42. package/generator/template/app/Api.elm +1 -1
  43. package/generator/template/app/Site.elm +6 -1
  44. package/package.json +12 -13
  45. package/src/ApiRoute.elm +146 -11
  46. package/src/DataSource/Env.elm +27 -3
  47. package/src/DataSource/File.elm +1 -1
  48. package/src/DataSource/Internal/Request.elm +0 -5
  49. package/src/DataSource.elm +50 -53
  50. package/src/Form/Field.elm +1 -1
  51. package/src/Form.elm +33 -33
  52. package/src/Head/Seo.elm +16 -27
  53. package/src/Head.elm +237 -7
  54. package/src/HtmlPrinter.elm +7 -3
  55. package/src/MultiDict.elm +49 -0
  56. package/src/Pages/Generate.elm +548 -103
  57. package/src/Pages/GeneratorProgramConfig.elm +15 -0
  58. package/src/Pages/Internal/NotFoundReason.elm +3 -2
  59. package/src/Pages/Internal/Platform/Cli.elm +91 -27
  60. package/src/Pages/Internal/Platform/Cli.elm.bak +1276 -0
  61. package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
  62. package/src/Pages/Internal/Platform/GeneratorApplication.elm +455 -0
  63. package/src/Pages/Internal/Platform.elm +34 -27
  64. package/src/Pages/Manifest.elm +24 -0
  65. package/src/Pages/ProgramConfig.elm +6 -3
  66. package/src/Pages/Script.elm +100 -0
  67. package/src/PairingHeap.elm +137 -0
  68. package/src/Parser/Extra/String.elm +33 -0
  69. package/src/Parser/Extra.elm +69 -0
  70. package/src/ProgramTest/ComplexQuery.elm +360 -0
  71. package/src/ProgramTest/EffectSimulation.elm +122 -0
  72. package/src/ProgramTest/Failure.elm +367 -0
  73. package/src/ProgramTest/HtmlHighlighter.elm +116 -0
  74. package/src/ProgramTest/HtmlParserHacks.elm +58 -0
  75. package/src/ProgramTest/HtmlRenderer.elm +73 -0
  76. package/src/ProgramTest/Program.elm +30 -0
  77. package/src/ProgramTest/StringLines.elm +26 -0
  78. package/src/ProgramTest/TestHtmlHacks.elm +132 -0
  79. package/src/ProgramTest/TestHtmlParser.elm +201 -0
  80. package/src/ProgramTest.elm +2339 -0
  81. package/src/Query/Extra.elm +55 -0
  82. package/src/Result/Extra.elm +21 -0
  83. package/src/Server/Request.elm +2 -2
  84. package/src/Server/Session.elm +149 -83
  85. package/src/Server/SetCookie.elm +89 -31
  86. package/src/SimulatedEffect/Cmd.elm +69 -0
  87. package/src/SimulatedEffect/Http.elm +330 -0
  88. package/src/SimulatedEffect/Navigation.elm +69 -0
  89. package/src/SimulatedEffect/Ports.elm +62 -0
  90. package/src/SimulatedEffect/Process.elm +24 -0
  91. package/src/SimulatedEffect/Sub.elm +48 -0
  92. package/src/SimulatedEffect/Task.elm +252 -0
  93. package/src/SimulatedEffect/Time.elm +25 -0
  94. package/src/SimulatedEffect.elm +42 -0
  95. package/src/String/Extra.elm +6 -0
  96. package/src/Test/Http.elm +145 -0
  97. package/src/TestResult.elm +35 -0
  98. package/src/TestState.elm +305 -0
  99. package/src/Url/Extra.elm +100 -0
  100. package/src/Vendored/Diff.elm +321 -0
  101. package/src/Vendored/Failure.elm +217 -0
  102. package/src/Vendored/FormatMonochrome.elm +44 -0
  103. package/src/Vendored/Highlightable.elm +53 -0
@@ -0,0 +1,78 @@
1
+ /** This code is from https://github.com/sveltejs/kit/blob/3b457f67d4d7c59fc63bb3f600a490e4dacc2e62/packages/kit/src/exports/vite/utils.js */
2
+
3
+ /**
4
+ * @param {...import('vite').UserConfig} configs
5
+ * @returns {import('vite').UserConfig}
6
+ */
7
+ function merge_vite_configs(...configs) {
8
+ return deep_merge(
9
+ ...configs.map((config) => ({
10
+ ...config,
11
+ resolve: {
12
+ ...config.resolve,
13
+ alias: normalize_alias(config.resolve?.alias || {}),
14
+ },
15
+ }))
16
+ );
17
+ }
18
+
19
+ /**
20
+ * Takes zero or more objects and returns a new object that has all the values
21
+ * deeply merged together. None of the original objects will be mutated at any
22
+ * level, and the returned object will have no references to the original
23
+ * objects at any depth. If there's a conflict the last one wins, except for
24
+ * arrays which will be combined.
25
+ * @param {...Object} objects
26
+ * @returns {Record<string, any>} the merged object
27
+ */
28
+ function deep_merge(...objects) {
29
+ const result = {};
30
+ /** @type {string[]} */
31
+ objects.forEach((o) => merge_into(result, o));
32
+ return result;
33
+ }
34
+
35
+ /**
36
+ * normalize kit.vite.resolve.alias as an array
37
+ * @param {import('vite').AliasOptions} o
38
+ * @returns {import('vite').Alias[]}
39
+ */
40
+ function normalize_alias(o) {
41
+ if (Array.isArray(o)) return o;
42
+ return Object.entries(o).map(([find, replacement]) => ({
43
+ find,
44
+ replacement,
45
+ }));
46
+ }
47
+
48
+ /**
49
+ * Merges b into a, recursively, mutating a.
50
+ * @param {Record<string, any>} a
51
+ * @param {Record<string, any>} b
52
+ */
53
+ function merge_into(a, b) {
54
+ /**
55
+ * Checks for "plain old Javascript object", typically made as an object
56
+ * literal. Excludes Arrays and built-in types like Buffer.
57
+ * @param {any} x
58
+ */
59
+ const is_plain_object = (x) =>
60
+ typeof x === "object" && x.constructor === Object;
61
+
62
+ for (const prop in b) {
63
+ if (is_plain_object(b[prop])) {
64
+ if (!is_plain_object(a[prop])) {
65
+ a[prop] = {};
66
+ }
67
+ merge_into(a[prop], b[prop]);
68
+ } else if (Array.isArray(b[prop])) {
69
+ if (!Array.isArray(a[prop])) {
70
+ a[prop] = [];
71
+ }
72
+ a[prop].push(...b[prop]);
73
+ } else {
74
+ a[prop] = b[prop];
75
+ }
76
+ }
77
+ }
78
+ module.exports = { merge_vite_configs };
@@ -9,7 +9,7 @@ import Route exposing (Route)
9
9
 
10
10
  routes :
11
11
  DataSource (List Route)
12
- -> (Html Never -> String)
12
+ -> (Maybe { indent : Int, newLines : Bool } -> Html Never -> String)
13
13
  -> List (ApiRoute ApiRoute.Response)
14
14
  routes getStaticRoutes htmlToString =
15
15
  []
@@ -14,6 +14,11 @@ config =
14
14
 
15
15
  head : DataSource (List Head.Tag)
16
16
  head =
17
- [ Head.sitemapLink "/sitemap.xml"
17
+ [ Head.metaName "viewport" (Head.raw "width=device-width,initial-scale=1")
18
+ , Head.metaName "mobile-web-app-capable" (Head.raw "yes")
19
+ , Head.metaName "theme-color" (Head.raw "#ffffff")
20
+ , Head.metaName "apple-mobile-web-app-capable" (Head.raw "yes")
21
+ , Head.metaName "apple-mobile-web-app-status-bar-style" (Head.raw "black-translucent")
22
+ , Head.sitemapLink "/sitemap.xml"
18
23
  ]
19
24
  |> DataSource.succeed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "elm-pages",
3
- "version": "3.0.0-beta.1",
3
+ "version": "3.0.0-beta.12",
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.",
@@ -10,7 +10,6 @@
10
10
  "test": "./test.sh",
11
11
  "test:snapshot": "(cd examples/escaping && npm install && npm test) && (cd examples/base-path && npm install && npm test)",
12
12
  "cypress": "npm start & cypress run",
13
- "prepare": "npm run build:generator",
14
13
  "build:generator": "elm-codegen install && (cd codegen && lamdera make Generate.elm --output elm-pages-codegen.js)",
15
14
  "review": "elm-review"
16
15
  },
@@ -27,14 +26,14 @@
27
26
  "dependencies": {
28
27
  "busboy": "^1.0.0",
29
28
  "chokidar": "^3.5.3",
30
- "commander": "^9.4.0",
29
+ "commander": "9.4.1",
31
30
  "connect": "^3.7.0",
32
31
  "cookie-signature": "^1.1.0",
33
32
  "cross-spawn": "7.0.3",
34
33
  "devcert": "^1.2.2",
35
34
  "elm-doc-preview": "^5.0.5",
36
35
  "elm-hot": "^1.1.6",
37
- "esbuild": "^0.15.5",
36
+ "esbuild": "^0.15.14",
38
37
  "fs-extra": "^10.1.0",
39
38
  "globby": "11.0.4",
40
39
  "gray-matter": "^4.0.3",
@@ -45,26 +44,26 @@
45
44
  "node-fetch": "^2.6.7",
46
45
  "object-hash": "^2.2.0",
47
46
  "serve-static": "^1.15.0",
48
- "terser": "^5.14.2",
49
- "vite": "^3.0.9",
47
+ "terser": "^5.15.1",
48
+ "vite": "^3.2.4",
50
49
  "which": "^2.0.2"
51
50
  },
52
51
  "devDependencies": {
53
52
  "@types/cross-spawn": "^6.0.2",
54
53
  "@types/fs-extra": "^9.0.13",
55
54
  "@types/micromatch": "^4.0.2",
56
- "@types/node": "12.20.12",
55
+ "@types/node": "^18.11.9",
57
56
  "@types/serve-static": "^1.15.0",
58
- "cypress": "^10.6.0",
57
+ "cypress": "^11.1.0",
59
58
  "elm-codegen": "^0.2.0",
60
- "elm-optimize-level-2": "^0.1.5",
61
- "elm-review": "^2.7.4",
62
- "elm-test": "^0.19.1-revision9",
63
- "elm-tooling": "^1.8.0",
59
+ "elm-optimize-level-2": "^0.3.5",
60
+ "elm-review": "^2.8.2",
61
+ "elm-test": "^0.19.1-revision10",
62
+ "elm-tooling": "^1.10.0",
64
63
  "elm-verify-examples": "^5.2.0",
65
64
  "elmi-to-json": "^1.2.0",
66
65
  "mocha": "^10.0.0",
67
- "typescript": "^4.7.4"
66
+ "typescript": "^4.9.3"
68
67
  },
69
68
  "files": [
70
69
  "generator/src/",
package/src/ApiRoute.elm CHANGED
@@ -1,8 +1,9 @@
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
8
  , toJson, getBuildTimeRoutes, getGlobalHeadTagsDataSource
8
9
  )
@@ -11,22 +12,153 @@ module ApiRoute exposing
11
12
  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
13
  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.
13
14
 
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.
15
+ 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
16
+ use cases they support.
16
17
 
17
- @docs ApiRoute, ApiRouteBuilder, Response
18
18
 
19
- @docs capture, literal, slash, succeed
19
+ ## Pre-Rendering
20
20
 
21
+ A pre-rendered ApiRoute is just a generated file. For example:
21
22
 
22
- ## Pre-Rendering
23
+ - [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))
24
+ - [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))
25
+ - A redirect file for a hosting provider like Netlify
26
+
27
+ 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!
28
+ The beauty is that you have a way to 1) pull in type-safe data using DataSource's, and 2) write those files, and all in pure Elm!
23
29
 
24
30
  @docs single, preRender
25
31
 
26
32
 
27
33
  ## Server Rendering
28
34
 
29
- @docs preRenderWithFallback, serverRender
35
+ 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.
36
+ 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
37
+ than upfront at build-time. That means you can hit your database and serve up always-up-to-date data.
38
+
39
+ 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,
40
+ a server-rendered ApiRoute accesses the incoming HTTP request through a [Server.Request.Parser](Server-Request). Consider the use cases that this opens up:
41
+
42
+ - 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.
43
+ - Serve up user-specific content, either through a cookie or other means of authentication
44
+ - 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)).
45
+ - 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.
46
+
47
+ @docs serverRender
48
+
49
+ 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.
50
+ 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).
51
+ 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
52
+ 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)
53
+ that asset will be served up if that URL was already served up by the server.
54
+
55
+ @docs preRenderWithFallback
56
+
57
+
58
+ ## Defining ApiRoute's
59
+
60
+ You define your ApiRoute's in `app/Api.elm`. Here's a simple example:
61
+
62
+ module Api exposing (routes)
63
+
64
+ import ApiRoute
65
+ import DataSource exposing (DataSource)
66
+ import Server.Request
67
+
68
+ routes :
69
+ DataSource (List Route)
70
+ -> (Maybe { indent : Int, newLines : Bool } -> Html Never -> String)
71
+ -> List (ApiRoute.ApiRoute ApiRoute.Response)
72
+ routes getStaticRoutes htmlToString =
73
+ [ preRenderedExample
74
+ , requestPrinterExample
75
+ ]
76
+
77
+ {-| Generates the following files when you
78
+ run `elm-pages build`:
79
+
80
+ - `dist/users/1.json`
81
+ - `dist/users/2.json`
82
+ - `dist/users/3.json`
83
+
84
+ When you host it, these static assets will
85
+ be served at `/users/1.json`, etc.
86
+
87
+ -}
88
+ preRenderedExample : ApiRoute.ApiRoute ApiRoute.Response
89
+ preRenderedExample =
90
+ ApiRoute.succeed
91
+ (\userId ->
92
+ DataSource.succeed
93
+ (Json.Encode.object
94
+ [ ( "id", Json.Encode.string userId )
95
+ , ( "name", "Data for user " ++ userId |> Json.Encode.string )
96
+ ]
97
+ |> Json.Encode.encode 2
98
+ )
99
+ )
100
+ |> ApiRoute.literal "users"
101
+ |> ApiRoute.slash
102
+ |> ApiRoute.capture
103
+ |> ApiRoute.literal ".json"
104
+ |> ApiRoute.preRender
105
+ (\route ->
106
+ DataSource.succeed
107
+ [ route "1"
108
+ , route "2"
109
+ , route "3"
110
+ ]
111
+ )
112
+
113
+ {-| This returns a JSON response that prints information about the incoming
114
+ HTTP request. In practice you'd want to do something useful with that data,
115
+ and use more of the high-level helpers from the Server.Request API.
116
+ -}
117
+ requestPrinterExample : ApiRoute ApiRoute.Response
118
+ requestPrinterExample =
119
+ ApiRoute.succeed
120
+ (Server.Request.map4
121
+ (\rawBody method cookies queryParams ->
122
+ Encode.object
123
+ [ ( "rawBody"
124
+ , rawBody
125
+ |> Maybe.map Encode.string
126
+ |> Maybe.withDefault Encode.null
127
+ )
128
+ , ( "method"
129
+ , method
130
+ |> Server.Request.methodToString
131
+ |> Encode.string
132
+ )
133
+ , ( "cookies"
134
+ , cookies
135
+ |> Encode.dict
136
+ identity
137
+ Encode.string
138
+ )
139
+ , ( "queryParams"
140
+ , queryParams
141
+ |> Encode.dict
142
+ identity
143
+ (Encode.list Encode.string)
144
+ )
145
+ ]
146
+ |> Response.json
147
+ |> DataSource.succeed
148
+ )
149
+ Server.Request.rawBody
150
+ Server.Request.method
151
+ Server.Request.allCookies
152
+ Server.Request.queryParams
153
+ )
154
+ |> ApiRoute.literal "api"
155
+ |> ApiRoute.slash
156
+ |> ApiRoute.literal "request-test"
157
+ |> ApiRoute.serverRender
158
+
159
+ @docs ApiRoute, ApiRouteBuilder, Response
160
+
161
+ @docs capture, literal, slash, succeed
30
162
 
31
163
 
32
164
  ## Including Head Tags
@@ -57,7 +189,9 @@ type alias ApiRoute response =
57
189
  Internal.ApiRoute.ApiRoute response
58
190
 
59
191
 
60
- {-| -}
192
+ {-| Same as [`preRender`](#preRender), but for an ApiRoute that has no dynamic segments. This is just a bit simpler because
193
+ since there are no dynamic segments, you don't need to provide a DataSource with the list of dynamic segments to pre-render because there is only a single possible route.
194
+ -}
61
195
  single : ApiRouteBuilder (DataSource String) (List String) -> ApiRoute Response
62
196
  single handler =
63
197
  handler
@@ -238,7 +372,8 @@ toJson ((ApiRoute { kind }) as apiRoute) =
238
372
  ]
239
373
 
240
374
 
241
- {-| -}
375
+ {-| A literal String segment of a route.
376
+ -}
242
377
  literal : String -> ApiRouteBuilder a constructor -> ApiRouteBuilder a constructor
243
378
  literal segment (ApiRouteBuilder patterns pattern handler toString constructor) =
244
379
  ApiRouteBuilder
@@ -1,6 +1,28 @@
1
1
  module DataSource.Env exposing (get, expect)
2
2
 
3
- {-|
3
+ {-| Because DataSource's in `elm-pages` never run in the browser (see [the DataSource docs](DataSource)), you can access environment variables securely. As long as the environment variable isn't sent
4
+ down into the final `Data` value, it won't end up in the client!
5
+
6
+ import DataSource exposing (DataSource)
7
+ import DataSource.Env
8
+
9
+ type alias EnvVariables =
10
+ { sendGridKey : String
11
+ , siteUrl : String
12
+ }
13
+
14
+ sendEmail : Email -> DataSource ()
15
+ sendEmail email =
16
+ DataSource.map2 EnvVariables
17
+ (DataSource.Env.expect "SEND_GRID_KEY")
18
+ (DataSource.Env.get "BASE_URL"
19
+ |> DataSource.map (Maybe.withDefault "http://localhost:1234")
20
+ )
21
+ |> DataSource.andThen (sendEmailDataSource email)
22
+
23
+ sendEmailDataSource : Email -> EnvVariables -> DataSource ()
24
+ sendEmailDataSource email envVariables =
25
+ Debug.todo "Not defined here"
4
26
 
5
27
  @docs get, expect
6
28
 
@@ -13,7 +35,8 @@ import Json.Decode as Decode
13
35
  import Json.Encode as Encode
14
36
 
15
37
 
16
- {-| -}
38
+ {-| Get an environment variable, or Nothing if there is no environment variable matching that name.
39
+ -}
17
40
  get : String -> DataSource (Maybe String)
18
41
  get envVariableName =
19
42
  DataSource.Internal.Request.request
@@ -25,7 +48,8 @@ get envVariableName =
25
48
  }
26
49
 
27
50
 
28
- {-| -}
51
+ {-| Get an environment variable, or a DataSource failure if there is no environment variable matching that name.
52
+ -}
29
53
  expect : String -> DataSource String
30
54
  expect envVariableName =
31
55
  envVariableName
@@ -171,7 +171,7 @@ just the metadata.
171
171
  (Decode.field "tags" (Decode.list Decode.string))
172
172
 
173
173
  If you wanted to use this to get this metadata for all blog posts in a folder, you could use
174
- the [`DataSource`](DataSource) API along with [`DataSource.Glob`](DataSource.Glob).
174
+ the [`DataSource`](DataSource) API along with [`DataSource.Glob`](DataSource-Glob).
175
175
 
176
176
  import DataSource exposing (DataSource)
177
177
  import DataSource.File as File
@@ -1,10 +1,5 @@
1
1
  module DataSource.Internal.Request exposing (request)
2
2
 
3
- {-| Build a `DataSource.Http` request (analogous to [Http.request](https://package.elm-lang.org/packages/elm/http/latest/Http#request)).
4
- This function takes in all the details to build a `DataSource.Http` request, but you can build your own simplified helper functions
5
- with this as a low-level detail, or you can use functions like [DataSource.Http.get](#get).
6
- -}
7
-
8
3
  import DataSource exposing (DataSource)
9
4
  import DataSource.Http exposing (Body, Expect)
10
5