elm-pages 2.1.11 → 3.0.0-beta.1

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 (161) hide show
  1. package/codegen/elm-pages-codegen.js +38507 -0
  2. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
  3. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
  4. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmi +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/Reporter.elmi +0 -0
  7. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
  8. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
  9. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
  10. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  11. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  12. package/generator/{template/public/style.css → dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock} +0 -0
  13. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  14. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -0
  15. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +6795 -0
  16. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25651 -0
  17. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +110 -0
  18. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +187 -0
  19. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/package.json +1 -0
  20. package/generator/dead-code-review/elm-stuff/tests-0.19.1/src/Reporter.elm +26 -0
  21. package/generator/dead-code-review/elm-stuff/tests-0.19.1/src/Runner.elm +62 -0
  22. package/generator/dead-code-review/elm.json +35 -0
  23. package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +181 -0
  24. package/generator/dead-code-review/src/ReviewConfig.elm +9 -0
  25. package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +455 -0
  26. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
  27. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
  28. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
  29. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
  30. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmi +0 -0
  31. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolationsTest.elmo +0 -0
  32. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmi +0 -0
  33. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Reporter.elmo +0 -0
  34. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmi +0 -0
  35. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Runner.elmo +0 -0
  36. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  37. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  38. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/lock +0 -0
  39. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  40. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -0
  41. package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +6795 -0
  42. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +27617 -0
  43. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +110 -0
  44. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +187 -0
  45. package/generator/review/elm-stuff/tests-0.19.1/js/package.json +1 -0
  46. package/generator/review/elm-stuff/tests-0.19.1/src/Reporter.elm +26 -0
  47. package/generator/review/elm-stuff/tests-0.19.1/src/Runner.elm +62 -0
  48. package/generator/review/elm.json +13 -4
  49. package/{src → generator/review/src}/Pages/Review/NoContractViolations.elm +148 -148
  50. package/generator/review/tests/Pages/Review/NoContractViolationsTest.elm +331 -0
  51. package/generator/src/RouteBuilder.elm +420 -0
  52. package/generator/src/SharedTemplate.elm +4 -5
  53. package/generator/src/SiteConfig.elm +3 -9
  54. package/generator/src/build.js +308 -95
  55. package/generator/src/cli.js +103 -8
  56. package/generator/src/codegen.js +192 -35
  57. package/generator/src/compile-elm.js +183 -31
  58. package/generator/src/dev-server.js +353 -96
  59. package/generator/src/elm-application.json +3 -1
  60. package/generator/src/elm-codegen.js +34 -0
  61. package/generator/src/elm-file-constants.js +2 -0
  62. package/generator/src/error-formatter.js +20 -1
  63. package/generator/src/generate-template-module-connector.js +125 -927
  64. package/generator/src/hello.ts +5 -0
  65. package/generator/src/pre-render-html.js +58 -104
  66. package/generator/src/render-worker.js +27 -13
  67. package/generator/src/render.js +252 -197
  68. package/generator/src/request-cache-fs.js +18 -0
  69. package/generator/src/request-cache.js +128 -56
  70. package/generator/src/rewrite-client-elm-json.js +49 -0
  71. package/generator/src/route-codegen-helpers.js +62 -1
  72. package/generator/static-code/dev-style.css +22 -0
  73. package/generator/static-code/elm-pages.js +43 -39
  74. package/generator/static-code/hmr.js +98 -88
  75. package/generator/template/app/Api.elm +25 -0
  76. package/generator/template/app/ErrorPage.elm +38 -0
  77. package/generator/template/app/Route/Index.elm +87 -0
  78. package/generator/template/{src → app}/Shared.elm +34 -13
  79. package/generator/template/app/Site.elm +19 -0
  80. package/generator/template/{src → app}/View.elm +0 -0
  81. package/generator/template/elm-pages.config.mjs +5 -0
  82. package/generator/template/elm.json +1 -0
  83. package/generator/template/{public/index.js → index.ts} +7 -3
  84. package/generator/template/package.json +4 -4
  85. package/generator/template/public/favicon.ico +0 -0
  86. package/generator/template/public/images/icon-png.png +0 -0
  87. package/generator/template/src/.gitkeep +0 -0
  88. package/generator/template/style.css +4 -0
  89. package/package.json +33 -23
  90. package/src/ApiRoute.elm +176 -43
  91. package/src/BuildError.elm +10 -1
  92. package/src/CookieParser.elm +84 -0
  93. package/src/DataSource/Env.elm +38 -0
  94. package/src/DataSource/File.elm +27 -16
  95. package/src/DataSource/Glob.elm +126 -80
  96. package/src/DataSource/Http.elm +283 -304
  97. package/src/DataSource/Internal/Glob.elm +5 -21
  98. package/src/DataSource/Internal/Request.elm +25 -0
  99. package/src/DataSource/Port.elm +17 -14
  100. package/src/DataSource.elm +55 -318
  101. package/src/Form/Field.elm +717 -0
  102. package/src/Form/FieldStatus.elm +36 -0
  103. package/src/Form/FieldView.elm +417 -0
  104. package/src/Form/FormData.elm +22 -0
  105. package/src/Form/Validation.elm +391 -0
  106. package/src/Form/Value.elm +118 -0
  107. package/src/Form.elm +1683 -0
  108. package/src/FormData.elm +58 -0
  109. package/src/FormDecoder.elm +102 -0
  110. package/src/Head/Seo.elm +12 -4
  111. package/src/Head.elm +12 -2
  112. package/src/HtmlPrinter.elm +1 -1
  113. package/src/Internal/ApiRoute.elm +17 -4
  114. package/src/Internal/Request.elm +7 -0
  115. package/src/PageServerResponse.elm +68 -0
  116. package/src/Pages/ContentCache.elm +1 -229
  117. package/src/Pages/Fetcher.elm +58 -0
  118. package/src/Pages/FormState.elm +256 -0
  119. package/src/Pages/Generate.elm +800 -0
  120. package/src/Pages/Internal/Form.elm +17 -0
  121. package/src/Pages/Internal/NotFoundReason.elm +3 -55
  122. package/src/Pages/Internal/Platform/Cli.elm +777 -579
  123. package/src/Pages/Internal/Platform/Effect.elm +5 -5
  124. package/src/Pages/Internal/Platform/StaticResponses.elm +178 -394
  125. package/src/Pages/Internal/Platform/ToJsPayload.elm +24 -23
  126. package/src/Pages/Internal/Platform.elm +1244 -504
  127. package/src/Pages/Internal/ResponseSketch.elm +19 -0
  128. package/src/Pages/Internal/RoutePattern.elm +596 -45
  129. package/src/Pages/Manifest.elm +26 -0
  130. package/src/Pages/Msg.elm +79 -0
  131. package/src/Pages/ProgramConfig.elm +67 -14
  132. package/src/Pages/SiteConfig.elm +3 -6
  133. package/src/Pages/StaticHttp/Request.elm +4 -2
  134. package/src/Pages/StaticHttpRequest.elm +50 -215
  135. package/src/Pages/Transition.elm +70 -0
  136. package/src/Path.elm +1 -0
  137. package/src/Pattern.elm +98 -0
  138. package/src/RenderRequest.elm +2 -2
  139. package/src/RequestsAndPending.elm +111 -9
  140. package/src/Server/Request.elm +1253 -0
  141. package/src/Server/Response.elm +292 -0
  142. package/src/Server/Session.elm +316 -0
  143. package/src/Server/SetCookie.elm +169 -0
  144. package/src/TerminalText.elm +1 -1
  145. package/src/Test/Html/Internal/ElmHtml/Markdown.elm +0 -1
  146. package/src/Test/Html/Internal/ElmHtml/ToString.elm +1 -1
  147. package/generator/src/Page.elm +0 -359
  148. package/generator/src/codegen-template-module.js +0 -183
  149. package/generator/src/elm-pages-js-minified.js +0 -1
  150. package/generator/template/src/Api.elm +0 -14
  151. package/generator/template/src/Page/Index.elm +0 -69
  152. package/generator/template/src/Site.elm +0 -41
  153. package/src/DataSource/ServerRequest.elm +0 -60
  154. package/src/Internal/OptimizedDecoder.elm +0 -18
  155. package/src/KeepOrDiscard.elm +0 -6
  156. package/src/OptimizedDecoder/Pipeline.elm +0 -335
  157. package/src/OptimizedDecoder.elm +0 -818
  158. package/src/Pages/Internal/ApplicationType.elm +0 -6
  159. package/src/Pages/Secrets.elm +0 -83
  160. package/src/Secrets.elm +0 -111
  161. package/src/SecretsDict.elm +0 -45
@@ -2,14 +2,17 @@ const globby = require("globby");
2
2
  const path = require("path");
3
3
  const mm = require("micromatch");
4
4
  const routeHelpers = require("./route-codegen-helpers");
5
+ const { runElmCodegenInstall } = require("./elm-codegen");
6
+ const { compileCliApp } = require("./compile-elm");
7
+ const { restoreColorSafe } = require("./error-formatter");
5
8
 
6
9
  /**
7
10
  * @param {string} basePath
8
11
  * @param {'browser' | 'cli'} phase
9
12
  */
10
- function generateTemplateModuleConnector(basePath, phase) {
11
- const templates = globby.sync(["src/Page/**/*.elm"], {}).map((file) => {
12
- const captures = mm.capture("src/Page/**/*.elm", file);
13
+ async function generateTemplateModuleConnector(basePath, phase) {
14
+ const templates = globby.sync(["app/Route/**/*.elm"], {}).map((file) => {
15
+ const captures = mm.capture("app/Route/**/*.elm", file);
13
16
  if (captures) {
14
17
  return path.join(captures[0], captures[1]).split(path.sep);
15
18
  } else {
@@ -19,7 +22,7 @@ function generateTemplateModuleConnector(basePath, phase) {
19
22
  if (templates.length <= 0) {
20
23
  throw {
21
24
  path: "",
22
- name: "TemplateModulesBeta",
25
+ name: "Main",
23
26
  problems: [
24
27
  {
25
28
  title: "Could not generate entrypoint",
@@ -36,803 +39,76 @@ function generateTemplateModuleConnector(basePath, phase) {
36
39
  ],
37
40
  };
38
41
  }
42
+ let elmCodegenFiles = null;
43
+ try {
44
+ elmCodegenFiles = await runElmCodegenCli(
45
+ sortTemplates(templates),
46
+ basePath,
47
+ phase
48
+ );
49
+ } catch (error) {
50
+ console.log(restoreColorSafe(error));
51
+ throw error;
52
+ }
53
+ const routesModule = elmCodegenFiles[0].contents;
54
+ const newMain = elmCodegenFiles[1].contents;
39
55
 
40
56
  return {
41
- mainModule: `port module TemplateModulesBeta exposing (..)
42
-
43
- import Api
44
- import ApiRoute
45
- import Browser.Navigation
46
- import Route exposing (Route)
47
- import View
48
- import Json.Decode
49
- import Json.Encode
50
- import Pages.Flags
51
- import ${
52
- phase === "browser"
53
- ? "Pages.Internal.Platform"
54
- : "Pages.Internal.Platform.Cli"
55
- }
56
- import Pages.Manifest as Manifest
57
- import Shared
58
- import Site
59
- import Head
60
- import Html exposing (Html)
61
- import Pages.Internal.NotFoundReason
62
- import Pages.PageUrl exposing (PageUrl)
63
- import Path exposing (Path)
64
- import Pages.Internal.RoutePattern
65
- import Url
66
- import DataSource exposing (DataSource)
67
- import QueryParams
68
-
69
- ${templates.map((name) => `import Page.${name.join(".")}`).join("\n")}
70
-
71
-
72
- type alias Model =
73
- { global : Shared.Model
74
- , page : PageModel
75
- , current :
76
- Maybe
77
- { path :
78
- { path : Path
79
- , query : Maybe String
80
- , fragment : Maybe String
81
- }
82
- , metadata : Maybe Route
83
- , pageUrl : Maybe PageUrl
84
- }
85
- }
86
-
87
-
88
- type PageModel
89
- = ${templates
90
- .map(
91
- (name) =>
92
- `Model${pathNormalizedName(name)} Page.${moduleName(name)}.Model\n`
93
- )
94
- .join(" | ")}
95
- | NotFound
96
-
97
-
98
-
99
-
100
- type Msg
101
- = MsgGlobal Shared.Msg
102
- | OnPageChange
103
- { protocol : Url.Protocol
104
- , host : String
105
- , port_ : Maybe Int
106
- , path : Path
107
- , query : Maybe String
108
- , fragment : Maybe String
109
- , metadata : Maybe Route
110
- }
111
- | ${templates
112
- .map(
113
- (name) =>
114
- `Msg${pathNormalizedName(name)} Page.${moduleName(name)}.Msg\n`
115
- )
116
- .join(" | ")}
117
-
118
-
119
- type PageData
120
- = Data404NotFoundPage____
121
- | ${templates
122
- .map(
123
- (name) =>
124
- `Data${pathNormalizedName(name)} Page.${moduleName(name)}.Data\n`
125
- )
126
- .join(" | ")}
127
-
128
-
57
+ mainModule: newMain,
58
+ routesModule,
59
+ fetcherModules: templates.map((name) => {
60
+ return [name, fetcherModule(name)];
61
+ }),
62
+ };
63
+ }
129
64
 
130
- view :
131
- { path : Path
132
- , route : Maybe Route
65
+ async function runElmCodegenCli(templates, basePath, phase) {
66
+ // await runElmCodegenInstall();
67
+ // try {
68
+ // await compileCliApp(
69
+ // // { debug: true },
70
+ // {},
71
+ // `Generate.elm`,
72
+ // path.join(process.cwd(), "elm-stuff/elm-pages-codegen.js"),
73
+ // path.join(__dirname, "../../codegen"),
74
+
75
+ // path.join(process.cwd(), "elm-stuff/elm-pages-codegen.js")
76
+ // );
77
+ // } catch (error) {
78
+ // console.log(restoreColorSafe(error));
79
+ // process.exit(1);
80
+ // // throw error;
81
+ // }
82
+
83
+ const filePath = path.join(__dirname, `../../codegen/elm-pages-codegen.js`);
84
+
85
+ // TODO use uncached require here to prevent stale code from running
86
+
87
+ const promise = new Promise((resolve, reject) => {
88
+ const elmPagesCodegen = require(filePath).Elm.Generate;
89
+ // path.join(
90
+ // process.cwd(),
91
+ // "./elm-stuff/elm-pages-codegen.js")
92
+
93
+ const app = elmPagesCodegen.init({
94
+ flags: { templates: templates, basePath, phase },
95
+ });
96
+ if (app.ports.onSuccessSend) {
97
+ app.ports.onSuccessSend.subscribe(resolve);
133
98
  }
134
- -> Maybe PageUrl
135
- -> Shared.Data
136
- -> PageData
137
- ->
138
- { view : Model -> { title : String, body : Html Msg }
139
- , head : List Head.Tag
140
- }
141
- view page maybePageUrl globalData pageData =
142
- case ( page.route, pageData ) of
143
- ${templates
144
- .map(
145
- (name) =>
146
- `( Just ${
147
- emptyRouteParams(name)
148
- ? `Route.${routeHelpers.routeVariant(name)}`
149
- : `(Route.${routeHelpers.routeVariant(name)} s)`
150
- }, Data${routeHelpers.routeVariant(name)} data ) ->
151
- { view =
152
- \\model ->
153
- case model.page of
154
- Model${pathNormalizedName(name)} subModel ->
155
- Page.${moduleName(name)}.page.view
156
- maybePageUrl
157
- model.global
158
- subModel
159
- { data = data
160
- , sharedData = globalData
161
- , routeParams = ${
162
- emptyRouteParams(name) ? "{}" : "s"
163
- }
164
- , path = page.path
165
- }
166
- |> View.map Msg${pathNormalizedName(name)}
167
- |> Shared.template.view globalData page model.global MsgGlobal
168
-
169
- _ ->
170
- { title = "Model mismatch", body = Html.text <| "Model mismatch" }
171
- , head = ${
172
- phase === "browser"
173
- ? "[]"
174
- : `Page.${moduleName(name)}.page.head
175
- { data = data
176
- , sharedData = globalData
177
- , routeParams = ${emptyRouteParams(name) ? "{}" : "s"}
178
- , path = page.path
179
- }
180
- `
181
- }
182
- }
183
- `
184
- )
185
- .join("\n\n ")}
186
- _ ->
187
- { head = []
188
- , view =
189
- \\_ ->
190
- { title = "Page not found"
191
- , body =
192
- Html.div []
193
- [ Html.text "This page could not be found."
194
- ]
195
- }
196
-
197
- }
198
-
199
-
200
-
201
- init :
202
- Maybe Shared.Model
203
- -> Pages.Flags.Flags
204
- -> Shared.Data
205
- -> PageData
206
- -> Maybe Browser.Navigation.Key
207
- ->
208
- Maybe
209
- { path :
210
- { path : Path
211
- , query : Maybe String
212
- , fragment : Maybe String
213
- }
214
- , metadata : Maybe Route
215
- , pageUrl : Maybe PageUrl
216
- }
217
- -> ( Model, Cmd Msg )
218
- init currentGlobalModel userFlags sharedData pageData navigationKey maybePagePath =
219
- let
220
- ( sharedModel, globalCmd ) =
221
- currentGlobalModel |> Maybe.map (\\m -> ( m, Cmd.none )) |> Maybe.withDefault (Shared.template.init navigationKey userFlags maybePagePath)
222
-
223
- ( templateModel, templateCmd ) =
224
- case ( ( Maybe.map2 Tuple.pair (maybePagePath |> Maybe.andThen .metadata) (maybePagePath |> Maybe.map .path) ), pageData ) of
225
- ${templates
226
- .map(
227
- (name) => `( Just ( ${
228
- emptyRouteParams(name)
229
- ? `Route.${routeHelpers.routeVariant(name)}`
230
- : `(Route.${routeHelpers.routeVariant(
231
- name
232
- )} routeParams)`
233
- }, justPath ), Data${pathNormalizedName(
234
- name
235
- )} thisPageData ) ->
236
- Page.${moduleName(name)}.page.init
237
- (Maybe.andThen .pageUrl maybePagePath)
238
- sharedModel
239
- { data = thisPageData
240
- , sharedData = sharedData
241
- , routeParams = ${
242
- emptyRouteParams(name) ? "{}" : "routeParams"
243
- }
244
- , path = justPath.path
245
- }
246
- |> Tuple.mapBoth Model${pathNormalizedName(
247
- name
248
- )} (Cmd.map Msg${pathNormalizedName(name)})
249
- `
250
- )
251
- .join("\n ")}
252
- _ ->
253
- ( NotFound, Cmd.none )
254
- in
255
- ( { global = sharedModel
256
- , page = templateModel
257
- , current = maybePagePath
258
- }
259
- , Cmd.batch
260
- [ templateCmd
261
- , globalCmd |> Cmd.map MsgGlobal
262
- ]
263
- )
264
-
265
-
266
-
267
- update : Shared.Data -> PageData -> Maybe Browser.Navigation.Key -> Msg -> Model -> ( Model, Cmd Msg )
268
- update sharedData pageData navigationKey msg model =
269
- case msg of
270
- MsgGlobal msg_ ->
271
- let
272
- ( sharedModel, globalCmd ) =
273
- Shared.template.update msg_ model.global
274
- in
275
- ( { model | global = sharedModel }
276
- , globalCmd |> Cmd.map MsgGlobal
277
- )
278
-
279
- OnPageChange record ->
280
- (init (Just model.global) Pages.Flags.PreRenderFlags sharedData pageData navigationKey <|
281
- Just
282
- { path =
283
- { path = record.path
284
- , query = record.query
285
- , fragment = record.fragment
286
- }
287
- , metadata = record.metadata
288
- , pageUrl =
289
- Just
290
- { protocol = record.protocol
291
- , host = record.host
292
- , port_ = record.port_
293
- , path = record.path
294
- , query = record.query |> Maybe.map QueryParams.fromString
295
- , fragment = record.fragment
296
- }
297
- }
298
- )
299
- |> (\\( updatedModel, cmd ) ->
300
- case Shared.template.onPageChange of
301
- Nothing ->
302
- ( updatedModel, cmd )
303
-
304
- Just thingy ->
305
- let
306
- ( updatedGlobalModel, globalCmd ) =
307
- Shared.template.update
308
- (thingy
309
- { path = record.path
310
- , query = record.query
311
- , fragment = record.fragment
312
- }
313
- )
314
- model.global
315
- in
316
- ( { updatedModel
317
- | global = updatedGlobalModel
318
- }
319
- , Cmd.batch [ cmd, Cmd.map MsgGlobal globalCmd ]
320
- )
321
- )
322
-
323
-
324
- ${templates
325
- .map(
326
- (name) => `
327
- Msg${pathNormalizedName(name)} msg_ ->
328
- let
329
- ( updatedPageModel, pageCmd, ( newGlobalModel, newGlobalCmd ) ) =
330
- case ( model.page, pageData, Maybe.map3 (\\a b c -> ( a, b, c )) (model.current |> Maybe.andThen .metadata) (model.current |> Maybe.andThen .pageUrl) (model.current |> Maybe.map .path) ) of
331
- ( Model${pathNormalizedName(
332
- name
333
- )} pageModel, Data${pathNormalizedName(
334
- name
335
- )} thisPageData, Just ( ${routeHelpers.destructureRoute(
336
- name,
337
- "routeParams"
338
- )}, pageUrl, justPage ) ) ->
339
- Page.${moduleName(name)}.page.update
340
- pageUrl
341
- { data = thisPageData
342
- , sharedData = sharedData
343
- , routeParams = ${routeHelpers.referenceRouteParams(
344
- name,
345
- "routeParams"
346
- )}
347
- , path = justPage.path
348
- }
349
- navigationKey
350
- msg_
351
- pageModel
352
- model.global
353
- |> mapBoth Model${pathNormalizedName(
354
- name
355
- )} (Cmd.map Msg${pathNormalizedName(name)})
356
- |> (\\( a, b, c ) ->
357
- case c of
358
- Just sharedMsg ->
359
- ( a, b, Shared.template.update sharedMsg model.global )
360
-
361
- Nothing ->
362
- ( a, b, ( model.global, Cmd.none ) )
363
- )
364
-
365
- _ ->
366
- ( model.page, Cmd.none, ( model.global, Cmd.none ) )
367
- in
368
- ( { model | page = updatedPageModel, global = newGlobalModel }
369
- , Cmd.batch [ pageCmd, newGlobalCmd |> Cmd.map MsgGlobal ]
370
- )
371
- `
372
- )
373
- .join("\n ")}
374
-
375
-
376
- type alias SiteConfig =
377
- { canonicalUrl : String
378
- , manifest : Manifest.Config
99
+ if (app.ports.onInfoSend) {
100
+ app.ports.onInfoSend.subscribe((info) => console.log(info));
379
101
  }
380
-
381
- templateSubscriptions : Maybe Route -> Path -> Model -> Sub Msg
382
- templateSubscriptions route path model =
383
- case ( model.page, route ) of
384
- ${templates
385
- .map(
386
- (name) => `
387
- ( Model${pathNormalizedName(
388
- name
389
- )} templateModel, Just ${routeHelpers.destructureRoute(
390
- name,
391
- "routeParams"
392
- )} ) ->
393
- Page.${moduleName(name)}.page.subscriptions
394
- Nothing -- TODO wire through value
395
- ${routeHelpers.referenceRouteParams(name, "routeParams")}
396
- path
397
- templateModel
398
- model.global
399
- |> Sub.map Msg${pathNormalizedName(name)}
400
- `
401
- )
402
- .join("\n ")}
403
-
404
-
405
- _ ->
406
- Sub.none
407
-
408
-
409
- main : ${
410
- phase === "browser"
411
- ? "Pages.Internal.Platform.Program Model Msg PageData Shared.Data"
412
- : "Pages.Internal.Platform.Cli.Program (Maybe Route)"
102
+ if (app.ports.onFailureSend) {
103
+ app.ports.onFailureSend.subscribe(reject);
413
104
  }
414
- main =
415
- ${
416
- phase === "browser"
417
- ? "Pages.Internal.Platform.application"
418
- : "Pages.Internal.Platform.Cli.cliApplication"
419
- }
420
- { init = init Nothing
421
- , urlToRoute = Route.urlToRoute
422
- , routeToPath = \\route -> route |> Maybe.map Route.routeToPath |> Maybe.withDefault []
423
- , site = ${phase === "browser" ? `Nothing` : `Just Site.config`}
424
- , getStaticRoutes = ${
425
- phase === "browser"
426
- ? `DataSource.succeed []`
427
- : `getStaticRoutes |> DataSource.map (List.map Just)`
428
- }
429
- , handleRoute = handleRoute
430
- , view = view
431
- , update = update
432
- , subscriptions =
433
- \\route path model ->
434
- Sub.batch
435
- [ Shared.template.subscriptions path model.global |> Sub.map MsgGlobal
436
- , templateSubscriptions route path model
437
- ]
438
- , onPageChange = OnPageChange
439
- , toJsPort = toJsPort
440
- , fromJsPort = fromJsPort identity
441
- , data = dataForRoute
442
- , sharedData = Shared.template.data
443
- , apiRoutes = ${
444
- phase === "browser"
445
- ? `\\_ -> []`
446
- : `\\htmlToString -> pathsToGenerateHandler :: routePatterns :: manifestHandler :: Api.routes getStaticRoutes htmlToString`
447
- }
448
- , pathPatterns = routePatterns3
449
- , basePath = [ ${basePath
450
- .split("/")
451
- .filter((segment) => segment !== "")
452
- .map((segment) => `"${segment}"`)
453
- .join(", ")} ]
454
- }
455
-
456
- dataForRoute : Maybe Route -> DataSource PageData
457
- dataForRoute route =
458
- case route of
459
- Nothing ->
460
- DataSource.succeed Data404NotFoundPage____
461
- ${templates
462
- .map(
463
- (name) =>
464
- `Just ${
465
- emptyRouteParams(name)
466
- ? `Route.${routeHelpers.routeVariant(name)}`
467
- : `(Route.${routeHelpers.routeVariant(name)} routeParams)`
468
- } ->\n Page.${name.join(
469
- "."
470
- )}.page.data ${routeHelpers.referenceRouteParams(
471
- name,
472
- "routeParams"
473
- )} |> DataSource.map Data${routeHelpers.routeVariant(name)}`
474
- )
475
- .join("\n ")}
476
-
477
- handleRoute : Maybe Route -> DataSource (Maybe Pages.Internal.NotFoundReason.NotFoundReason)
478
- handleRoute maybeRoute =
479
- case maybeRoute of
480
- Nothing ->
481
- DataSource.succeed Nothing
482
-
483
- ${templates
484
- .map(
485
- (name) =>
486
- `Just (Route.${routeHelpers.routeVariant(name)}${
487
- routeHelpers.parseRouteParams(name).length === 0
488
- ? ""
489
- : " routeParams"
490
- }) ->\n Page.${name.join(
491
- "."
492
- )}.page.handleRoute { moduleName = [ ${name
493
- .map((part) => `"${part}"`)
494
- .join(", ")} ], routePattern = ${routeHelpers.toElmPathPattern(
495
- name
496
- )} } (\\param -> [ ${routeHelpers
497
- .parseRouteParams(name)
498
- .map(
499
- (param) =>
500
- `( "${param.name}", ${paramAsElmString(param)} param.${
501
- param.name
502
- } )`
503
- )
504
- .join(", ")} ]) ${routeHelpers.referenceRouteParams(
505
- name,
506
- "routeParams"
507
- )}`
508
- )
509
- .join("\n ")}
510
-
511
-
512
- stringToString : String -> String
513
- stringToString string =
514
- "\\"" ++ string ++ "\\""
515
-
516
-
517
- nonEmptyToString : ( String, List String ) -> String
518
- nonEmptyToString ( first, rest ) =
519
- "( "
520
- ++ stringToString first
521
- ++ ", [ "
522
- ++ (rest
523
- |> List.map stringToString
524
- |> String.join ", "
525
- )
526
- ++ " ] )"
527
-
528
-
529
- listToString : List String -> String
530
- listToString strings =
531
- "[ "
532
- ++ (strings
533
- |> List.map stringToString
534
- |> String.join ", "
535
- )
536
- ++ " ]"
537
-
538
-
539
- maybeToString : Maybe String -> String
540
- maybeToString maybeString =
541
- case maybeString of
542
- Just string ->
543
- "Just " ++ stringToString string
544
-
545
- Nothing ->
546
- "Nothing"
547
-
548
-
549
-
550
-
551
- routePatterns : ApiRoute.ApiRoute ApiRoute.Response
552
- routePatterns =
553
- ApiRoute.succeed
554
- (Json.Encode.list
555
- (\\{ kind, pathPattern } ->
556
- Json.Encode.object
557
- [ ( "kind", Json.Encode.string kind )
558
- , ( "pathPattern", Json.Encode.string pathPattern )
559
- ]
560
- )
561
- [ ${sortTemplates(templates)
562
- .map((name) => {
563
- return `{ kind = Page.${moduleName(
564
- name
565
- )}.page.kind, pathPattern = "${routeHelpers.toPathPattern(
566
- name
567
- )}" }`;
568
- })
569
- .join("\n , ")}
570
-
571
- ]
572
- |> (\\json -> DataSource.succeed { body = Json.Encode.encode 0 json })
573
- )
574
- |> ApiRoute.literal "route-patterns.json"
575
- |> ApiRoute.single
576
-
577
-
578
- routePatterns2 : List String
579
- routePatterns2 =
580
- [ ${sortTemplates(templates)
581
- .map((name) => {
582
- return `"${routeHelpers.toPathPattern(name)}"`;
583
- })
584
- .join("\n , ")}
585
- ]
586
-
587
-
588
- routePatterns3 : List Pages.Internal.RoutePattern.RoutePattern
589
- routePatterns3 =
590
- [ ${sortTemplates(templates)
591
- .map((name) => {
592
- return `${routeHelpers.toElmPathPattern(name)}`;
593
- })
594
- .join("\n , ")}
595
- ]
596
-
597
- getStaticRoutes : DataSource (List Route)
598
- getStaticRoutes =
599
- DataSource.combine
600
- [ ${templates
601
- .map((name) => {
602
- return `Page.${moduleName(
603
- name
604
- )}.page.staticRoutes |> DataSource.map (List.map ${
605
- emptyRouteParams(name)
606
- ? `(\\_ -> Route.${pathNormalizedName(name)}))`
607
- : `Route.${pathNormalizedName(name)})`
608
- }`;
609
- })
610
- .join("\n , ")}
611
- ]
612
- |> DataSource.map List.concat
613
-
614
-
615
- pathsToGenerateHandler : ApiRoute.ApiRoute ApiRoute.Response
616
- pathsToGenerateHandler =
617
- ApiRoute.succeed
618
- (DataSource.map2
619
- (\\pageRoutes apiRoutes ->
620
- { body =
621
- (pageRoutes ++ (apiRoutes |> List.map (\\api -> "/" ++ api)))
622
- |> Json.Encode.list Json.Encode.string
623
- |> Json.Encode.encode 0
624
- }
625
- )
626
- (DataSource.map
627
- (List.map
628
- (\\route ->
629
- route
630
- |> Route.toPath
631
- |> Path.toAbsolute
632
- )
633
- )
634
- getStaticRoutes
635
- )
636
- ((manifestHandler :: Api.routes getStaticRoutes (\\_ -> ""))
637
- |> List.map ApiRoute.getBuildTimeRoutes
638
- |> DataSource.combine
639
- |> DataSource.map List.concat
640
- )
641
- )
642
- |> ApiRoute.literal "all-paths.json"
643
- |> ApiRoute.single
644
-
645
-
646
- manifestHandler : ApiRoute.ApiRoute ApiRoute.Response
647
- manifestHandler =
648
- ApiRoute.succeed
649
- (Site.config
650
- |> .data
651
- |> DataSource.map
652
- (\\data ->
653
- Site.config.manifest data
654
- |> manifestToFile (Site.config.canonicalUrl)
655
- )
656
- )
657
- |> ApiRoute.literal "manifest.json"
658
- |> ApiRoute.single
659
-
660
-
661
- manifestToFile : String -> Manifest.Config -> { body : String }
662
- manifestToFile resolvedCanonicalUrl manifestConfig =
663
- manifestConfig
664
- |> Manifest.toJson resolvedCanonicalUrl
665
- |> (\\manifestJsonValue ->
666
- { body = Json.Encode.encode 0 manifestJsonValue
667
- }
668
- )
669
-
670
-
671
- port toJsPort : Json.Encode.Value -> Cmd msg
672
-
673
- port fromJsPort : (Json.Decode.Value -> msg) -> Sub msg
674
-
675
-
676
- mapBoth : (a -> b) -> (c -> d) -> ( a, c, e ) -> ( b, d, e )
677
- mapBoth fnA fnB ( a, b, c ) =
678
- ( fnA a, fnB b, c )
679
- `,
680
- routesModule: `module Route exposing (Route(..), link, matchers, routeToPath, toLink, urlToRoute, toPath)
681
-
682
- {-|
683
-
684
- @docs Route, link, matchers, routeToPath, toLink, urlToRoute, toPath
685
-
686
- -}
687
-
688
-
689
- import Html exposing (Attribute, Html)
690
- import Html.Attributes as Attr
691
- import Path exposing (Path)
692
- import Pages.Internal.Router
693
-
694
-
695
- {-| -}
696
- type Route
697
- = ${templates.map(routeHelpers.routeVariantDefinition).join("\n | ")}
698
-
699
-
700
- {-| -}
701
- urlToRoute : { url | path : String } -> Maybe Route
702
- urlToRoute url =
703
- url.path
704
- |> withoutBaseUrl
705
- |> Pages.Internal.Router.firstMatch matchers
706
-
707
-
708
- baseUrl : String
709
- baseUrl =
710
- "${basePath}"
711
-
712
-
713
- baseUrlAsPath : List String
714
- baseUrlAsPath =
715
- baseUrl
716
- |> String.split "/"
717
- |> List.filter (not << String.isEmpty)
718
-
719
-
720
- withoutBaseUrl path =
721
- if (path |> String.startsWith baseUrl) then
722
- String.dropLeft (String.length baseUrl) path
723
- else
724
- path
725
-
726
- {-| -}
727
- matchers : List (Pages.Internal.Router.Matcher Route)
728
- matchers =
729
- [ ${sortTemplates(templates)
730
- .map(
731
- (name) => `{ pattern = "^${routeRegex(name).pattern}$"
732
- , toRoute = ${routeRegex(name).toRoute}
733
- }\n`
734
- )
735
- .join(" , ")}
736
- ]
737
-
738
-
739
- {-| -}
740
- routeToPath : Route -> List String
741
- routeToPath route =
742
- case route of
743
- ${templates
744
- .map(
745
- (name) =>
746
- `${routeHelpers.routeVariant(name)}${
747
- routeHelpers.parseRouteParams(name).length === 0
748
- ? ""
749
- : ` params`
750
- } ->\n List.concat [ ${routeHelpers
751
- .parseRouteParamsWithStatic(name)
752
- .map((param) => {
753
- switch (param.kind) {
754
- case "static": {
755
- return param.name === "Index"
756
- ? `[]`
757
- : `[ "${camelToKebab(param.name)}" ]`;
758
- }
759
- case "optional": {
760
- return `Pages.Internal.Router.maybeToList params.${param.name}`;
761
- }
762
- case "required-splat": {
763
- return `Pages.Internal.Router.nonEmptyToList params.${param.name}`;
764
- }
765
- case "dynamic": {
766
- return `[ params.${param.name} ]`;
767
- }
768
- case "optional-splat": {
769
- return `params.${param.name}`;
770
- }
771
- }
772
- })} ]`
773
- )
774
- .join("\n ")}
775
-
776
- {-| -}
777
- toPath : Route -> Path
778
- toPath route =
779
- (baseUrlAsPath ++ (route |> routeToPath)) |> String.join "/" |> Path.fromString
780
-
781
-
782
- {-| -}
783
- toString : Route -> String
784
- toString route =
785
- route |> toPath |> Path.toAbsolute
786
-
787
-
788
- {-| -}
789
- toLink : (List (Attribute msg) -> tag) -> Route -> tag
790
- toLink toAnchorTag route =
791
- toAnchorTag
792
- [ route |> toString |> Attr.href
793
- , Attr.attribute "elm-pages:prefetch" ""
794
- ]
795
-
105
+ });
106
+ const filesToGenerate = await promise;
107
+ console.dir(filesToGenerate.map((file) => file.path));
796
108
 
797
- {-| -}
798
- link : Route -> List (Attribute msg) -> List (Html msg) -> Html msg
799
- link route attributes children =
800
- toLink
801
- (\\anchorAttrs ->
802
- Html.a
803
- (anchorAttrs ++ attributes)
804
- children
805
- )
806
- route
807
- `,
808
- };
109
+ return filesToGenerate;
809
110
  }
810
111
 
811
- function emptyRouteParams(name) {
812
- return routeHelpers.parseRouteParams(name).length === 0;
813
- }
814
-
815
- /**
816
- * @param {string} segment
817
- * @returns {'static' | 'dynamic' | 'optional' | 'index' | 'required-splat' | 'optional-splat'}
818
- */
819
- function segmentKind(segment) {
820
- if (segment === "Index") {
821
- return "index";
822
- }
823
- const routeParamMatch = segment.match(/([A-Z][A-Za-z0-9]*)(_?_?)$/);
824
- const segmentKind = (routeParamMatch && routeParamMatch[2]) || "";
825
- const isSplat = routeParamMatch && routeParamMatch[1] === "SPLAT";
826
- if (segmentKind === "") {
827
- return "static";
828
- } else if (segmentKind === "_") {
829
- return isSplat ? "required-splat" : "dynamic";
830
- } else if (segmentKind === "__") {
831
- return isSplat ? "optional-splat" : "optional";
832
- } else {
833
- throw "Unhandled segmentKind";
834
- }
835
- }
836
112
 
837
113
  /**
838
114
  *
@@ -899,122 +175,80 @@ function sortScore(name) {
899
175
  );
900
176
  }
901
177
 
902
- /**
903
- * @param {string[]} name
904
- */
905
- function routeRegex(name) {
906
- const parsedParams = routeHelpers.parseRouteParams(name);
907
- const includesOptional = parsedParams.some(
908
- (param) => param.kind === "optional"
909
- );
910
- const params = routeHelpers.routeParams(name);
911
- const parserCode = name
912
- .flatMap((section) => {
913
- const routeParamMatch = section.match(/([A-Z][A-Za-z0-9]*)(_?_?)$/);
914
- const maybeParam = routeParamMatch && routeParamMatch[1];
915
- switch (segmentKind(section)) {
178
+
179
+
180
+ function fetcherModule(name) {
181
+ let moduleName = name.join(".");
182
+ // TODO need to account for splat routes/etc.
183
+ let modulePath = name.join("/");
184
+ let fetcherPath = routeHelpers
185
+ .parseRouteParamsWithStatic(name)
186
+ .map((param) => {
187
+ switch (param.kind) {
916
188
  case "static": {
917
- return [`\\\\/` + camelToKebab(section)];
918
- }
919
- case "index": {
920
- return [`\\\\/`];
189
+ return param.name === "Index"
190
+ ? `[]`
191
+ : `[ "${camelToKebab(param.name)}" ]`;
921
192
  }
922
- case "dynamic": {
923
- return [`\\\\/(?:([^/]+))`];
193
+ case "optional": {
194
+ return `Pages.Internal.Router.maybeToList params.${param.name}`;
924
195
  }
925
196
  case "required-splat": {
926
- return [`\\\\/(.*)`];
197
+ return `Pages.Internal.Router.nonEmptyToList params.${param.name}`;
927
198
  }
928
- case "optional-splat": {
929
- return [`(.*)`];
199
+ case "dynamic": {
200
+ return `[ params.${param.name} ]`;
930
201
  }
931
- case "optional": {
932
- return [`(?:\\\\/([^/]+))?`];
202
+ case "optional-splat": {
203
+ return `params.${param.name}`;
933
204
  }
934
205
  }
935
206
  })
936
- .join("");
207
+ .join(", ");
937
208
 
938
- const toRoute = `\\matches ->
939
- case matches of
940
- [ ${parsedParams
941
- .flatMap((parsedParam) => {
942
- switch (parsedParam.kind) {
943
- case "optional": {
944
- return parsedParam.name;
945
- }
946
- case "dynamic": {
947
- return `Just ${parsedParam.name}`;
948
- }
949
- case "required-splat": {
950
- return `Just splat`;
951
- }
952
- case "optional-splat": {
953
- return `splat`;
954
- }
955
- }
956
- })
957
- .join(", ")} ] ->
958
- Just ${
959
- parsedParams.length === 0
960
- ? pathNormalizedName(name)
961
- : `( ${pathNormalizedName(name)} { ${parsedParams.map(
962
- (param) => {
963
- return `${param.name} = ${prefixThing(param)}${
964
- param.name
965
- }`;
966
- }
967
- )} } )`
968
- }
969
- _ ->
970
- Nothing
209
+ return `module Fetcher.${moduleName} exposing (submit)
971
210
 
972
- `;
211
+ {-| -}
973
212
 
974
- return { pattern: parserCode, toRoute };
975
- }
213
+ import Bytes exposing (Bytes)
214
+ import Bytes.Decode
215
+ import FormDecoder
216
+ import Http
217
+ import Pages.Fetcher
218
+ import Route.${moduleName}
976
219
 
977
- function prefixThing(param) {
978
- switch (param.kind) {
979
- case "optional-splat": {
980
- return "Pages.Internal.Router.fromOptionalSplat ";
981
- }
982
- case "required-splat": {
983
- return "Pages.Internal.Router.toNonEmpty ";
984
- }
985
- default: {
986
- return "";
220
+
221
+ submit :
222
+ (Result Http.Error Route.${moduleName}.ActionData -> msg)
223
+ ->
224
+ { fields : List ( String, String )
225
+ , headers : List ( String, String )
226
+ }
227
+ -> Pages.Fetcher.Fetcher msg
228
+ submit toMsg options =
229
+ { decoder =
230
+ \\bytesResult ->
231
+ bytesResult
232
+ |> Result.andThen
233
+ (\\okBytes ->
234
+ okBytes
235
+ |> Bytes.Decode.decode Route.${moduleName}.w3_decode_ActionData
236
+ |> Result.fromMaybe (Http.BadBody "Couldn't decode bytes.")
237
+ )
238
+ |> toMsg
239
+ , fields = options.fields
240
+ , headers = ("elm-pages-action-only", "true") :: options.headers
241
+ , url = ${
242
+ fetcherPath === ""
243
+ ? 'Just "/content.dat"'
244
+ : `[ ${fetcherPath}, [ "content.dat" ] ] |> List.concat |> String.join "/" |> Just`
245
+ }
987
246
  }
988
- }
247
+ |> Pages.Fetcher.Fetcher
248
+ `;
989
249
  }
990
250
 
991
- /**
992
- * @param {string[]} name
993
- */
994
- function routePathList(name) {
995
- return withoutTrailingIndex(name)
996
- .map((section) => {
997
- const routeParamMatch = section.match(/([A-Z][A-Za-z0-9]*)_$/);
998
- const maybeParam = routeParamMatch && routeParamMatch[1];
999
- if (maybeParam) {
1000
- return `params.${maybeParam.toLowerCase()}`;
1001
- } else {
1002
- return `"${camelToKebab(section)}"`;
1003
- }
1004
- })
1005
- .join(", ");
1006
- }
1007
251
 
1008
- /**
1009
- * @param {string[]} name
1010
- */
1011
- function withoutTrailingIndex(name) {
1012
- if (name[name.length - 1] === "Index") {
1013
- return name.slice(0, -1);
1014
- } else {
1015
- return name;
1016
- }
1017
- }
1018
252
  /**
1019
253
  * Convert Strings from camelCase to kebab-case
1020
254
  * @param {string} input
@@ -1023,42 +257,6 @@ function withoutTrailingIndex(name) {
1023
257
  function camelToKebab(input) {
1024
258
  return input.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
1025
259
  }
1026
- /**
1027
- * @param {string[]} name
1028
- */
1029
- function isParameterizedRoute(name) {
1030
- return name.some((section) => section.includes("_"));
1031
- }
1032
-
1033
- /**
1034
- * @param {string[]} name
1035
- */
1036
- function pathNormalizedName(name) {
1037
- return name.join("__");
1038
- }
1039
260
 
1040
- /**
1041
- * @param {string[]} name
1042
- */
1043
- function moduleName(name) {
1044
- return name.join(".");
1045
- }
1046
-
1047
- function paramAsElmString(param) {
1048
- switch (param.kind) {
1049
- case "dynamic": {
1050
- return "stringToString";
1051
- }
1052
- case "optional": {
1053
- return "maybeToString";
1054
- }
1055
- case "required-splat": {
1056
- return "nonEmptyToString";
1057
- }
1058
- case "optional-splat": {
1059
- return "listToString";
1060
- }
1061
- }
1062
- }
1063
261
 
1064
262
  module.exports = { generateTemplateModuleConnector, sortTemplates };