elm-pages 2.1.10 → 3.0.0-beta.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 (136) hide show
  1. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
  2. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
  3. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
  4. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
  5. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmi +0 -0
  6. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmo +0 -0
  7. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmi +0 -0
  8. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
  9. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
  10. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
  11. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  12. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  13. package/generator/{template/public/style.css → review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock} +0 -0
  14. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  15. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -0
  16. package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +6795 -0
  17. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +27617 -0
  18. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +110 -0
  19. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +187 -0
  20. package/generator/review/elm-stuff/tests-0.19.1/js/package.json +1 -0
  21. package/generator/review/elm-stuff/tests-0.19.1/src/Reporter.elm +26 -0
  22. package/generator/review/elm-stuff/tests-0.19.1/src/Runner.elm +62 -0
  23. package/generator/review/elm.json +13 -4
  24. package/{src → generator/review/src}/Pages/Review/NoContractViolations.elm +148 -148
  25. package/generator/review/tests/Pages/Review/NoContractViolationsTest.elm +331 -0
  26. package/generator/src/RouteBuilder.elm +420 -0
  27. package/generator/src/SharedTemplate.elm +4 -5
  28. package/generator/src/SiteConfig.elm +3 -9
  29. package/generator/src/build.js +308 -95
  30. package/generator/src/cli.js +103 -8
  31. package/generator/src/codegen.js +192 -35
  32. package/generator/src/compile-elm.js +183 -31
  33. package/generator/src/dev-server.js +353 -96
  34. package/generator/src/elm-application.json +3 -1
  35. package/generator/src/elm-codegen.js +34 -0
  36. package/generator/src/elm-file-constants.js +2 -0
  37. package/generator/src/error-formatter.js +20 -1
  38. package/generator/src/generate-template-module-connector.js +120 -924
  39. package/generator/src/hello.ts +5 -0
  40. package/generator/src/pre-render-html.js +58 -104
  41. package/generator/src/render-worker.js +27 -13
  42. package/generator/src/render.js +252 -197
  43. package/generator/src/request-cache-fs.js +18 -0
  44. package/generator/src/request-cache.js +128 -56
  45. package/generator/src/rewrite-client-elm-json.js +49 -0
  46. package/generator/src/route-codegen-helpers.js +62 -1
  47. package/generator/static-code/dev-style.css +22 -0
  48. package/generator/static-code/elm-pages.js +43 -39
  49. package/generator/static-code/hmr.js +98 -88
  50. package/generator/template/app/Api.elm +25 -0
  51. package/generator/template/app/ErrorPage.elm +38 -0
  52. package/generator/template/app/Route/Index.elm +87 -0
  53. package/generator/template/{src → app}/Shared.elm +34 -13
  54. package/generator/template/app/Site.elm +19 -0
  55. package/generator/template/{src → app}/View.elm +0 -0
  56. package/generator/template/elm-pages.config.mjs +5 -0
  57. package/generator/template/elm.json +14 -5
  58. package/generator/template/{public/index.js → index.ts} +7 -3
  59. package/generator/template/package.json +5 -5
  60. package/generator/template/public/favicon.ico +0 -0
  61. package/generator/template/public/images/icon-png.png +0 -0
  62. package/generator/template/src/.gitkeep +0 -0
  63. package/generator/template/style.css +4 -0
  64. package/package.json +30 -23
  65. package/src/ApiRoute.elm +176 -43
  66. package/src/BuildError.elm +10 -1
  67. package/src/CookieParser.elm +84 -0
  68. package/src/DataSource/Env.elm +38 -0
  69. package/src/DataSource/File.elm +27 -16
  70. package/src/DataSource/Glob.elm +126 -80
  71. package/src/DataSource/Http.elm +283 -304
  72. package/src/DataSource/Internal/Glob.elm +5 -21
  73. package/src/DataSource/Internal/Request.elm +25 -0
  74. package/src/DataSource/Port.elm +17 -14
  75. package/src/DataSource.elm +55 -318
  76. package/src/Form/Field.elm +717 -0
  77. package/src/Form/FieldStatus.elm +36 -0
  78. package/src/Form/FieldView.elm +417 -0
  79. package/src/Form/FormData.elm +22 -0
  80. package/src/Form/Validation.elm +391 -0
  81. package/src/Form/Value.elm +118 -0
  82. package/src/Form.elm +1683 -0
  83. package/src/FormData.elm +58 -0
  84. package/src/FormDecoder.elm +102 -0
  85. package/src/Head/Seo.elm +12 -4
  86. package/src/Head.elm +12 -2
  87. package/src/HtmlPrinter.elm +1 -1
  88. package/src/Internal/ApiRoute.elm +17 -4
  89. package/src/Internal/Request.elm +7 -0
  90. package/src/PageServerResponse.elm +68 -0
  91. package/src/Pages/ContentCache.elm +1 -229
  92. package/src/Pages/Fetcher.elm +58 -0
  93. package/src/Pages/FormState.elm +256 -0
  94. package/src/Pages/Generate.elm +800 -0
  95. package/src/Pages/Internal/Form.elm +17 -0
  96. package/src/Pages/Internal/NotFoundReason.elm +3 -55
  97. package/src/Pages/Internal/Platform/Cli.elm +777 -579
  98. package/src/Pages/Internal/Platform/Effect.elm +5 -5
  99. package/src/Pages/Internal/Platform/StaticResponses.elm +178 -394
  100. package/src/Pages/Internal/Platform/ToJsPayload.elm +24 -23
  101. package/src/Pages/Internal/Platform.elm +1244 -504
  102. package/src/Pages/Internal/ResponseSketch.elm +19 -0
  103. package/src/Pages/Internal/RoutePattern.elm +596 -45
  104. package/src/Pages/Manifest.elm +26 -0
  105. package/src/Pages/Msg.elm +79 -0
  106. package/src/Pages/ProgramConfig.elm +67 -14
  107. package/src/Pages/SiteConfig.elm +3 -6
  108. package/src/Pages/StaticHttp/Request.elm +4 -2
  109. package/src/Pages/StaticHttpRequest.elm +50 -215
  110. package/src/Pages/Transition.elm +70 -0
  111. package/src/Path.elm +1 -0
  112. package/src/Pattern.elm +98 -0
  113. package/src/RenderRequest.elm +2 -2
  114. package/src/RequestsAndPending.elm +111 -9
  115. package/src/Server/Request.elm +1253 -0
  116. package/src/Server/Response.elm +292 -0
  117. package/src/Server/Session.elm +316 -0
  118. package/src/Server/SetCookie.elm +169 -0
  119. package/src/TerminalText.elm +1 -1
  120. package/src/Test/Html/Internal/ElmHtml/Markdown.elm +0 -1
  121. package/src/Test/Html/Internal/ElmHtml/ToString.elm +1 -1
  122. package/generator/src/Page.elm +0 -359
  123. package/generator/src/codegen-template-module.js +0 -183
  124. package/generator/src/elm-pages-js-minified.js +0 -1
  125. package/generator/template/src/Api.elm +0 -14
  126. package/generator/template/src/Page/Index.elm +0 -69
  127. package/generator/template/src/Site.elm +0 -41
  128. package/src/DataSource/ServerRequest.elm +0 -60
  129. package/src/Internal/OptimizedDecoder.elm +0 -18
  130. package/src/KeepOrDiscard.elm +0 -6
  131. package/src/OptimizedDecoder/Pipeline.elm +0 -335
  132. package/src/OptimizedDecoder.elm +0 -818
  133. package/src/Pages/Internal/ApplicationType.elm +0 -6
  134. package/src/Pages/Secrets.elm +0 -83
  135. package/src/Secrets.elm +0 -111
  136. package/src/SecretsDict.elm +0 -45
@@ -0,0 +1,4 @@
1
+ body {
2
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
3
+ sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
4
+ }
package/package.json CHANGED
@@ -1,15 +1,16 @@
1
1
  {
2
2
  "name": "elm-pages",
3
- "version": "2.1.10",
3
+ "version": "3.0.0-beta.0",
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.",
7
7
  "main": "index.js",
8
8
  "scripts": {
9
- "start": "cd examples/end-to-end && npm start",
10
- "test": "npx elmi-to-json --version && elm-verify-examples --run-tests && elm-test && (cd generator && mocha) && (cd examples/routing && npm i && npm run build -- --debug && elm-test) && npm run test:snapshot",
11
- "test:snapshot": "(cd examples/escaping && npm install && npm test && cd ../..) && (cd examples/base-path && npm install && npm test && cd ../..)",
12
- "cypress": "npm start & cypress run --spec cypress/integration/elm-pages-dev.spec.js",
9
+ "start": "cd examples/end-to-end && npm i && npx elm-pages dev",
10
+ "test": "./test.sh",
11
+ "test:snapshot": "(cd examples/escaping && npm install && npm test) && (cd examples/base-path && npm install && npm test)",
12
+ "cypress": "npm start & cypress run",
13
+ "prepare": "elm-codegen install",
13
14
  "review": "elm-review"
14
15
  },
15
16
  "repository": "https://github.com/dillonkearns/elm-pages",
@@ -23,40 +24,46 @@
23
24
  "author": "Dillon Kearns",
24
25
  "license": "BSD-3-Clause",
25
26
  "dependencies": {
26
- "chokidar": "3.5.2",
27
- "commander": "^8.1.0",
27
+ "busboy": "^1.0.0",
28
+ "chokidar": "^3.5.3",
29
+ "commander": "^9.4.0",
28
30
  "connect": "^3.7.0",
31
+ "cookie-signature": "^1.1.0",
29
32
  "cross-spawn": "7.0.3",
30
- "devcert": "^1.2.0",
33
+ "devcert": "^1.2.2",
31
34
  "elm-doc-preview": "^5.0.5",
32
35
  "elm-hot": "^1.1.6",
33
- "fs-extra": "^10.0.0",
36
+ "esbuild": "^0.15.5",
37
+ "fs-extra": "^10.1.0",
34
38
  "globby": "11.0.4",
35
39
  "gray-matter": "^4.0.3",
36
40
  "jsesc": "^3.0.2",
37
- "kleur": "^4.1.4",
38
- "micromatch": "^4.0.4",
41
+ "kleur": "^4.1.5",
42
+ "memfs": "^3.4.7",
43
+ "micromatch": "^4.0.5",
44
+ "node-fetch": "^2.6.7",
39
45
  "object-hash": "^2.2.0",
40
- "serve-static": "^1.14.1",
41
- "terser": "^5.7.2",
42
- "undici": "^4.4.7",
46
+ "serve-static": "^1.15.0",
47
+ "terser": "^5.14.2",
48
+ "vite": "^3.0.9",
43
49
  "which": "^2.0.2"
44
50
  },
45
51
  "devDependencies": {
46
52
  "@types/cross-spawn": "^6.0.2",
47
- "@types/fs-extra": "9.0.12",
53
+ "@types/fs-extra": "^9.0.13",
48
54
  "@types/micromatch": "^4.0.2",
49
55
  "@types/node": "12.20.12",
50
- "@types/serve-static": "1.13.10",
51
- "cypress": "^8.3.0",
56
+ "@types/serve-static": "^1.15.0",
57
+ "cypress": "^10.6.0",
58
+ "elm-codegen": "^0.2.0",
52
59
  "elm-optimize-level-2": "^0.1.5",
53
- "elm-review": "^2.5.3",
54
- "elm-test": "^0.19.1-revision7",
55
- "elm-tooling": "^1.3.0",
56
- "elm-verify-examples": "^5.0.0",
60
+ "elm-review": "^2.7.4",
61
+ "elm-test": "^0.19.1-revision9",
62
+ "elm-tooling": "^1.8.0",
63
+ "elm-verify-examples": "^5.2.0",
57
64
  "elmi-to-json": "^1.2.0",
58
- "mocha": "^9.1.0",
59
- "typescript": "4.3.5"
65
+ "mocha": "^10.0.0",
66
+ "typescript": "^4.7.4"
60
67
  },
61
68
  "files": [
62
69
  "generator/src/",
package/src/ApiRoute.elm CHANGED
@@ -1,4 +1,11 @@
1
- module ApiRoute exposing (ApiRoute, ApiRouteBuilder, Response, buildTimeRoutes, capture, int, literal, single, slash, succeed, getBuildTimeRoutes)
1
+ module ApiRoute exposing
2
+ ( ApiRoute, ApiRouteBuilder, Response
3
+ , capture, literal, slash, succeed
4
+ , single, preRender
5
+ , preRenderWithFallback, serverRender
6
+ , withGlobalHeadTags
7
+ , toJson, getBuildTimeRoutes, getGlobalHeadTagsDataSource
8
+ )
2
9
 
3
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
4
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
@@ -7,13 +14,42 @@ the DataSource for your ApiRoutes, and it won't effect the payload size. Instead
7
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
8
15
  DataSources dynamically.
9
16
 
10
- @docs ApiRoute, ApiRouteBuilder, Response, buildTimeRoutes, capture, int, literal, single, slash, succeed, getBuildTimeRoutes
17
+ @docs ApiRoute, ApiRouteBuilder, Response
18
+
19
+ @docs capture, literal, slash, succeed
20
+
21
+
22
+ ## Pre-Rendering
23
+
24
+ @docs single, preRender
25
+
26
+
27
+ ## Server Rendering
28
+
29
+ @docs preRenderWithFallback, serverRender
30
+
31
+
32
+ ## Including Head Tags
33
+
34
+ @docs withGlobalHeadTags
35
+
36
+
37
+ ## Internals
38
+
39
+ @docs toJson, getBuildTimeRoutes, getGlobalHeadTagsDataSource
11
40
 
12
41
  -}
13
42
 
14
43
  import DataSource exposing (DataSource)
44
+ import DataSource.Http
45
+ import Head
15
46
  import Internal.ApiRoute exposing (ApiRoute(..), ApiRouteBuilder(..))
47
+ import Json.Decode as Decode
48
+ import Json.Encode
49
+ import Pattern
16
50
  import Regex
51
+ import Server.Request
52
+ import Server.Response
17
53
 
18
54
 
19
55
  {-| -}
@@ -22,15 +58,109 @@ type alias ApiRoute response =
22
58
 
23
59
 
24
60
  {-| -}
25
- single : ApiRouteBuilder (DataSource Response) (List String) -> ApiRoute Response
61
+ single : ApiRouteBuilder (DataSource String) (List String) -> ApiRoute Response
26
62
  single handler =
27
63
  handler
28
- |> buildTimeRoutes (\constructor -> DataSource.succeed [ constructor ])
64
+ |> preRender (\constructor -> DataSource.succeed [ constructor ])
65
+
66
+
67
+ {-| -}
68
+ serverRender : ApiRouteBuilder (Server.Request.Parser (DataSource (Server.Response.Response Never Never))) constructor -> ApiRoute Response
69
+ serverRender ((ApiRouteBuilder patterns pattern _ _ _) as fullHandler) =
70
+ ApiRoute
71
+ { regex = Regex.fromString ("^" ++ pattern ++ "$") |> Maybe.withDefault Regex.never
72
+ , matchesToResponse =
73
+ \path ->
74
+ Internal.ApiRoute.tryMatch path fullHandler
75
+ |> 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
+ )
98
+ )
99
+ |> Maybe.map (DataSource.map (Server.Response.toJson >> Just))
100
+ |> Maybe.withDefault
101
+ (DataSource.succeed Nothing)
102
+ , buildTimeRoutes = DataSource.succeed []
103
+ , handleRoute =
104
+ \path ->
105
+ DataSource.succeed
106
+ (case Internal.ApiRoute.tryMatch path fullHandler of
107
+ Just _ ->
108
+ True
109
+
110
+ Nothing ->
111
+ False
112
+ )
113
+ , pattern = patterns
114
+ , kind = "serverless"
115
+ , globalHeadTags = Nothing
116
+ }
117
+
118
+
119
+ {-| -}
120
+ preRenderWithFallback : (constructor -> DataSource (List (List String))) -> ApiRouteBuilder (DataSource (Server.Response.Response Never Never)) constructor -> ApiRoute Response
121
+ preRenderWithFallback buildUrls ((ApiRouteBuilder patterns pattern _ toString constructor) as fullHandler) =
122
+ let
123
+ buildTimeRoutes__ : DataSource (List String)
124
+ buildTimeRoutes__ =
125
+ buildUrls (constructor [])
126
+ |> DataSource.map (List.map toString)
127
+ in
128
+ ApiRoute
129
+ { regex = Regex.fromString ("^" ++ pattern ++ "$") |> Maybe.withDefault Regex.never
130
+ , matchesToResponse =
131
+ \path ->
132
+ Internal.ApiRoute.tryMatch path fullHandler
133
+ |> Maybe.map (DataSource.map (Server.Response.toJson >> Just))
134
+ |> Maybe.withDefault
135
+ (DataSource.succeed Nothing)
136
+ , buildTimeRoutes = buildTimeRoutes__
137
+ , handleRoute =
138
+ \path ->
139
+ DataSource.succeed
140
+ (case Internal.ApiRoute.tryMatch path fullHandler of
141
+ Just _ ->
142
+ True
143
+
144
+ Nothing ->
145
+ False
146
+ )
147
+ , pattern = patterns
148
+ , kind = "prerender-with-fallback"
149
+ , globalHeadTags = Nothing
150
+ }
151
+
152
+
153
+ encodeStaticFileBody : String -> Response
154
+ encodeStaticFileBody fileBody =
155
+ Json.Encode.object
156
+ [ ( "body", fileBody |> Json.Encode.string )
157
+ , ( "kind", Json.Encode.string "static-file" )
158
+ ]
29
159
 
30
160
 
31
161
  {-| -}
32
- buildTimeRoutes : (constructor -> DataSource (List (List String))) -> ApiRouteBuilder (DataSource Response) constructor -> ApiRoute Response
33
- buildTimeRoutes buildUrls ((ApiRouteBuilder pattern _ toString constructor) as fullHandler) =
162
+ preRender : (constructor -> DataSource (List (List String))) -> ApiRouteBuilder (DataSource String) constructor -> ApiRoute Response
163
+ preRender buildUrls ((ApiRouteBuilder patterns pattern _ toString constructor) as fullHandler) =
34
164
  let
35
165
  buildTimeRoutes__ : DataSource (List String)
36
166
  buildTimeRoutes__ =
@@ -60,7 +190,7 @@ buildTimeRoutes buildUrls ((ApiRouteBuilder pattern _ toString constructor) as f
60
190
  (\found ->
61
191
  if found then
62
192
  Internal.ApiRoute.tryMatch path fullHandler
63
- |> Maybe.map (DataSource.map Just)
193
+ |> Maybe.map (DataSource.map (encodeStaticFileBody >> Just))
64
194
  |> Maybe.withDefault (DataSource.succeed Nothing)
65
195
 
66
196
  else
@@ -76,6 +206,9 @@ buildTimeRoutes buildUrls ((ApiRouteBuilder pattern _ toString constructor) as f
76
206
  in
77
207
  preBuiltMatches
78
208
  |> DataSource.map (List.member matches)
209
+ , pattern = patterns
210
+ , kind = "prerender"
211
+ , globalHeadTags = Nothing
79
212
  }
80
213
 
81
214
 
@@ -86,33 +219,49 @@ type alias ApiRouteBuilder a constructor =
86
219
 
87
220
  {-| -}
88
221
  type alias Response =
89
- { body : String }
222
+ Json.Encode.Value
90
223
 
91
224
 
92
225
  {-| -}
93
226
  succeed : a -> ApiRouteBuilder a (List String)
94
227
  succeed a =
95
- ApiRouteBuilder "" (\_ -> a) (\_ -> "") (\list -> list)
228
+ ApiRouteBuilder Pattern.empty "" (\_ -> a) (\_ -> "") (\list -> list)
229
+
230
+
231
+ {-| Turn the route into a pattern in JSON format. For internal uses.
232
+ -}
233
+ toJson : ApiRoute response -> Json.Encode.Value
234
+ toJson ((ApiRoute { kind }) as apiRoute) =
235
+ Json.Encode.object
236
+ [ ( "pathPattern", apiRoute |> Internal.ApiRoute.toPattern |> Pattern.toJson )
237
+ , ( "kind", Json.Encode.string kind )
238
+ ]
96
239
 
97
240
 
98
241
  {-| -}
99
242
  literal : String -> ApiRouteBuilder a constructor -> ApiRouteBuilder a constructor
100
- literal segment (ApiRouteBuilder pattern handler toString constructor) =
101
- ApiRouteBuilder (pattern ++ segment) handler (\values -> toString values ++ segment) constructor
243
+ literal segment (ApiRouteBuilder patterns pattern handler toString constructor) =
244
+ ApiRouteBuilder
245
+ (Pattern.addLiteral segment patterns)
246
+ (pattern ++ segment)
247
+ handler
248
+ (\values -> toString values ++ segment)
249
+ constructor
102
250
 
103
251
 
104
252
  {-| -}
105
253
  slash : ApiRouteBuilder a constructor -> ApiRouteBuilder a constructor
106
- slash (ApiRouteBuilder pattern handler toString constructor) =
107
- ApiRouteBuilder (pattern ++ "/") handler (\arg -> toString arg ++ "/") constructor
254
+ slash (ApiRouteBuilder patterns pattern handler toString constructor) =
255
+ ApiRouteBuilder (patterns |> Pattern.addSlash) (pattern ++ "/") handler (\arg -> toString arg ++ "/") constructor
108
256
 
109
257
 
110
258
  {-| -}
111
259
  capture :
112
260
  ApiRouteBuilder (String -> a) constructor
113
261
  -> ApiRouteBuilder a (String -> constructor)
114
- capture (ApiRouteBuilder pattern previousHandler toString constructor) =
262
+ capture (ApiRouteBuilder patterns pattern previousHandler toString constructor) =
115
263
  ApiRouteBuilder
264
+ (patterns |> Pattern.addCapture)
116
265
  (pattern ++ "(.*)")
117
266
  (\matches ->
118
267
  case matches of
@@ -136,35 +285,6 @@ capture (ApiRouteBuilder pattern previousHandler toString constructor) =
136
285
  )
137
286
 
138
287
 
139
- {-| -}
140
- int :
141
- ApiRouteBuilder (Int -> a) constructor
142
- -> ApiRouteBuilder a (Int -> constructor)
143
- int (ApiRouteBuilder pattern previousHandler toString constructor) =
144
- ApiRouteBuilder
145
- (pattern ++ "(\\d+)")
146
- (\matches ->
147
- case matches of
148
- first :: rest ->
149
- previousHandler rest (String.toInt first |> Maybe.withDefault -1)
150
-
151
- _ ->
152
- previousHandler [] -1
153
- )
154
- (\s ->
155
- case s of
156
- first :: rest ->
157
- toString rest ++ first
158
-
159
- _ ->
160
- ""
161
- )
162
- (\matches ->
163
- \string ->
164
- constructor (String.fromInt string :: matches)
165
- )
166
-
167
-
168
288
  {-| For internal use by generated code. Not so useful in user-land.
169
289
  -}
170
290
  getBuildTimeRoutes : ApiRoute response -> DataSource (List String)
@@ -172,6 +292,19 @@ getBuildTimeRoutes (ApiRoute handler) =
172
292
  handler.buildTimeRoutes
173
293
 
174
294
 
295
+ {-| Include head tags on every page's HTML.
296
+ -}
297
+ withGlobalHeadTags : DataSource (List Head.Tag) -> ApiRoute response -> ApiRoute response
298
+ withGlobalHeadTags globalHeadTags (ApiRoute handler) =
299
+ ApiRoute { handler | globalHeadTags = Just globalHeadTags }
300
+
301
+
302
+ {-| -}
303
+ getGlobalHeadTagsDataSource : ApiRoute response -> Maybe (DataSource (List Head.Tag))
304
+ getGlobalHeadTagsDataSource (ApiRoute handler) =
305
+ handler.globalHeadTags
306
+
307
+
175
308
 
176
309
  --captureRest : ApiRouteBuilder (List String -> a) b -> ApiRouteBuilder a b
177
310
  --captureRest previousHandler =
@@ -1,4 +1,4 @@
1
- module BuildError exposing (BuildError, encode, errorToString, errorsToString)
1
+ module BuildError exposing (BuildError, encode, errorToString, errorsToString, internal)
2
2
 
3
3
  import Json.Encode as Encode
4
4
  import TerminalText as Terminal
@@ -12,6 +12,15 @@ type alias BuildError =
12
12
  }
13
13
 
14
14
 
15
+ internal : String -> { title : String, path : String, message : List Terminal.Text, fatal : Bool }
16
+ internal string =
17
+ { title = "Internal Error"
18
+ , path = ""
19
+ , message = [ Terminal.text string ]
20
+ , fatal = True
21
+ }
22
+
23
+
15
24
  errorsToString : List BuildError -> String
16
25
  errorsToString errors =
17
26
  errors
@@ -0,0 +1,84 @@
1
+ module CookieParser exposing (parse)
2
+
3
+ import Dict exposing (Dict)
4
+ import Parser exposing ((|.), (|=), Parser, Step(..))
5
+ import Url
6
+
7
+
8
+ parse : String -> Dict String String
9
+ parse input =
10
+ Parser.run parser input
11
+ |> Result.withDefault Dict.empty
12
+
13
+
14
+ parser : Parser (Dict String String)
15
+ parser =
16
+ Parser.loop [] keyValuePair
17
+ |> Parser.map Dict.fromList
18
+
19
+
20
+ keyValuePair : List ( String, String ) -> Parser (Step (List ( String, String )) (List ( String, String )))
21
+ keyValuePair revChunks =
22
+ Parser.oneOf
23
+ [ Parser.end
24
+ |> Parser.map (\_ -> Done (List.reverse revChunks))
25
+ , Parser.succeed (Loop revChunks)
26
+ |. Parser.chompIf isSpace
27
+ |. Parser.chompWhile isSpace
28
+ , Parser.succeed Tuple.pair
29
+ |= parseKey
30
+ |= Parser.oneOf
31
+ [ Parser.succeed Nothing
32
+ |. Parser.token ";"
33
+ , Parser.succeed Just
34
+ |. Parser.token "="
35
+ |= valueParser
36
+ |. Parser.oneOf
37
+ [ Parser.token ";"
38
+ , Parser.succeed ()
39
+ ]
40
+ ]
41
+ |> Parser.andThen
42
+ (\( key, maybeValue ) ->
43
+ case maybeValue of
44
+ Just value ->
45
+ Parser.succeed (Loop (( key, value ) :: revChunks))
46
+
47
+ Nothing ->
48
+ Parser.succeed (Loop revChunks)
49
+ )
50
+ ]
51
+
52
+
53
+ valueParser : Parser String
54
+ valueParser =
55
+ Parser.succeed identity
56
+ |. Parser.chompWhile isSpace
57
+ |= Parser.oneOf
58
+ [ Parser.succeed ""
59
+ |. Parser.token ";"
60
+ , Parser.succeed identity
61
+ |. Parser.token "\""
62
+ |= (Parser.chompUntil "\""
63
+ |> Parser.getChompedString
64
+ )
65
+ |. Parser.token "\""
66
+ , Parser.chompWhile (\c -> c /= ';')
67
+ |> Parser.getChompedString
68
+ ]
69
+ |> Parser.map String.trim
70
+ |> Parser.map (\value -> value |> Url.percentDecode |> Maybe.withDefault "")
71
+
72
+
73
+ parseKey : Parser String
74
+ parseKey =
75
+ Parser.succeed identity
76
+ |= (Parser.chompWhile (\c -> c /= '=' && c /= ';')
77
+ |> Parser.getChompedString
78
+ |> Parser.map String.trim
79
+ )
80
+
81
+
82
+ isSpace : Char -> Bool
83
+ isSpace c =
84
+ c == ' '
@@ -0,0 +1,38 @@
1
+ module DataSource.Env exposing (get, expect)
2
+
3
+ {-|
4
+
5
+ @docs get, expect
6
+
7
+ -}
8
+
9
+ import DataSource exposing (DataSource)
10
+ import DataSource.Http
11
+ import DataSource.Internal.Request
12
+ import Json.Decode as Decode
13
+ import Json.Encode as Encode
14
+
15
+
16
+ {-| -}
17
+ get : String -> DataSource (Maybe String)
18
+ get envVariableName =
19
+ DataSource.Internal.Request.request
20
+ { name = "env"
21
+ , body = DataSource.Http.jsonBody (Encode.string envVariableName)
22
+ , expect =
23
+ DataSource.Http.expectJson
24
+ (Decode.nullable Decode.string)
25
+ }
26
+
27
+
28
+ {-| -}
29
+ expect : String -> DataSource String
30
+ expect envVariableName =
31
+ envVariableName
32
+ |> get
33
+ |> DataSource.andThen
34
+ (\maybeValue ->
35
+ maybeValue
36
+ |> Result.fromMaybe ("DataSource.Env.expect was expecting a variable `" ++ envVariableName ++ "` but couldn't find a variable with that name.")
37
+ |> DataSource.fromResult
38
+ )
@@ -30,7 +30,7 @@ The frontmatter is in the [YAML format](https://en.wikipedia.org/wiki/YAML) here
30
30
  Hey there! This is my first post :)
31
31
  ```
32
32
 
33
- Whether it's YAML or JSON, you use an `OptimizedDecoder` to decode your frontmatter, so it feels just like using
33
+ Whether it's YAML or JSON, you use an `Decode` to decode your frontmatter, so it feels just like using
34
34
  plain old JSON in Elm.
35
35
 
36
36
  @docs bodyWithFrontmatter, bodyWithoutFrontmatter, onlyFrontmatter
@@ -44,20 +44,20 @@ plain old JSON in Elm.
44
44
 
45
45
  import DataSource exposing (DataSource)
46
46
  import DataSource.Http
47
- import OptimizedDecoder exposing (Decoder)
48
- import Secrets
47
+ import DataSource.Internal.Request
48
+ import Json.Decode as Decode exposing (Decoder)
49
49
 
50
50
 
51
51
  frontmatter : Decoder frontmatter -> Decoder frontmatter
52
52
  frontmatter frontmatterDecoder =
53
- OptimizedDecoder.field "parsedFrontmatter" frontmatterDecoder
53
+ Decode.field "parsedFrontmatter" frontmatterDecoder
54
54
 
55
55
 
56
56
  {-|
57
57
 
58
58
  import DataSource exposing (DataSource)
59
59
  import DataSource.File as File
60
- import OptimizedDecoder as Decode exposing (Decoder)
60
+ import Decode as Decode exposing (Decoder)
61
61
 
62
62
  blogPost : DataSource BlogPostMetadata
63
63
  blogPost =
@@ -93,8 +93,8 @@ It's common to parse the body with a markdown parser or other format.
93
93
 
94
94
  import DataSource exposing (DataSource)
95
95
  import DataSource.File as File
96
+ import Decode as Decode exposing (Decoder)
96
97
  import Html exposing (Html)
97
- import OptimizedDecoder as Decode exposing (Decoder)
98
98
 
99
99
  example :
100
100
  DataSource
@@ -137,7 +137,7 @@ bodyWithFrontmatter : (String -> Decoder frontmatter) -> String -> DataSource fr
137
137
  bodyWithFrontmatter frontmatterDecoder filePath =
138
138
  read filePath
139
139
  (body
140
- |> OptimizedDecoder.andThen
140
+ |> Decode.andThen
141
141
  (\bodyString ->
142
142
  frontmatter (frontmatterDecoder bodyString)
143
143
  )
@@ -151,7 +151,7 @@ just the metadata.
151
151
 
152
152
  import DataSource exposing (DataSource)
153
153
  import DataSource.File as File
154
- import OptimizedDecoder as Decode exposing (Decoder)
154
+ import Decode as Decode exposing (Decoder)
155
155
 
156
156
  blogPost : DataSource BlogPostMetadata
157
157
  blogPost =
@@ -175,7 +175,7 @@ the [`DataSource`](DataSource) API along with [`DataSource.Glob`](DataSource.Glo
175
175
 
176
176
  import DataSource exposing (DataSource)
177
177
  import DataSource.File as File
178
- import OptimizedDecoder as Decode exposing (Decoder)
178
+ import Decode as Decode exposing (Decoder)
179
179
 
180
180
  blogPostFiles : DataSource (List String)
181
181
  blogPostFiles =
@@ -237,7 +237,7 @@ This is the function you want if you are reading in a file directly. For example
237
237
  have frontmatter.
238
238
 
239
239
  There's a special function for reading in JSON files, [`jsonFile`](#jsonFile). If you're reading a JSON file then be sure to
240
- use `jsonFile` to get the benefits of the `OptimizedDecoder` here.
240
+ use `jsonFile` to get the benefits of the `Decode` here.
241
241
 
242
242
  You could read a file called `hello.txt` in your root project directory like this:
243
243
 
@@ -251,12 +251,12 @@ You could read a file called `hello.txt` in your root project directory like thi
251
251
  -}
252
252
  rawFile : String -> DataSource String
253
253
  rawFile filePath =
254
- read filePath (OptimizedDecoder.field "rawFile" OptimizedDecoder.string)
254
+ read filePath (Decode.field "rawFile" Decode.string)
255
255
 
256
256
 
257
257
  {-| Read a file as JSON.
258
258
 
259
- The OptimizedDecoder will strip off any unused JSON data.
259
+ The Decode will strip off any unused JSON data.
260
260
 
261
261
  import DataSource exposing (DataSource)
262
262
  import DataSource.File as File
@@ -273,16 +273,27 @@ The OptimizedDecoder will strip off any unused JSON data.
273
273
  -}
274
274
  jsonFile : Decoder a -> String -> DataSource a
275
275
  jsonFile jsonFileDecoder filePath =
276
- read filePath (OptimizedDecoder.field "jsonFile" jsonFileDecoder)
276
+ rawFile filePath
277
+ |> DataSource.andThen
278
+ (\jsonString ->
279
+ jsonString
280
+ |> Decode.decodeString jsonFileDecoder
281
+ |> Result.mapError Decode.errorToString
282
+ |> DataSource.fromResult
283
+ )
277
284
 
278
285
 
279
286
  {-| Gives us the file's content without stripping off frontmatter.
280
287
  -}
281
288
  body : Decoder String
282
289
  body =
283
- OptimizedDecoder.field "withoutFrontmatter" OptimizedDecoder.string
290
+ Decode.field "withoutFrontmatter" Decode.string
284
291
 
285
292
 
286
293
  read : String -> Decoder a -> DataSource a
287
- read filePath =
288
- DataSource.Http.get (Secrets.succeed <| "file://" ++ filePath)
294
+ read filePath decoder =
295
+ DataSource.Internal.Request.request
296
+ { name = "read-file"
297
+ , body = DataSource.Http.stringBody "" filePath
298
+ , expect = decoder |> DataSource.Http.expectJson
299
+ }