elm-pages 2.1.11 → 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 +1 -0
  58. package/generator/template/{public/index.js → index.ts} +7 -3
  59. package/generator/template/package.json +4 -4
  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
@@ -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,74 @@ 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
-
129
-
130
- view :
131
- { path : Path
132
- , route : Maybe Route
133
- }
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 )
57
+ mainModule: newMain,
58
+ routesModule,
59
+ fetcherModules: templates.map((name) => {
60
+ return [name, fetcherModule(name)];
61
+ }),
62
+ };
63
+ }
360
64
 
361
- Nothing ->
362
- ( a, b, ( model.global, Cmd.none ) )
363
- )
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
+ }
364
82
 
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 ")}
83
+ // TODO use uncached require here to prevent stale code from running
374
84
 
85
+ const promise = new Promise((resolve, reject) => {
86
+ const elmPagesCodegen = require(path.join(
87
+ process.cwd(),
88
+ "./elm-stuff/elm-pages-codegen.js"
89
+ )).Elm.Generate;
375
90
 
376
- type alias SiteConfig =
377
- { canonicalUrl : String
378
- , manifest : Manifest.Config
91
+ const app = elmPagesCodegen.init({
92
+ flags: { templates: templates, basePath, phase },
93
+ });
94
+ if (app.ports.onSuccessSend) {
95
+ app.ports.onSuccessSend.subscribe(resolve);
379
96
  }
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)"
97
+ if (app.ports.onInfoSend) {
98
+ app.ports.onInfoSend.subscribe((info) => console.log(info));
413
99
  }
414
- main =
415
- ${
416
- phase === "browser"
417
- ? "Pages.Internal.Platform.application"
418
- : "Pages.Internal.Platform.Cli.cliApplication"
100
+ if (app.ports.onFailureSend) {
101
+ app.ports.onFailureSend.subscribe(reject);
419
102
  }
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
-
796
-
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
- };
809
- }
103
+ });
104
+ const filesToGenerate = await promise;
105
+ console.dir(filesToGenerate.map((file) => file.path));
810
106
 
811
- function emptyRouteParams(name) {
812
- return routeHelpers.parseRouteParams(name).length === 0;
107
+ return filesToGenerate;
813
108
  }
814
109
 
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
110
 
837
111
  /**
838
112
  *
@@ -899,122 +173,80 @@ function sortScore(name) {
899
173
  );
900
174
  }
901
175
 
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)) {
176
+
177
+
178
+ function fetcherModule(name) {
179
+ let moduleName = name.join(".");
180
+ // TODO need to account for splat routes/etc.
181
+ let modulePath = name.join("/");
182
+ let fetcherPath = routeHelpers
183
+ .parseRouteParamsWithStatic(name)
184
+ .map((param) => {
185
+ switch (param.kind) {
916
186
  case "static": {
917
- return [`\\\\/` + camelToKebab(section)];
918
- }
919
- case "index": {
920
- return [`\\\\/`];
187
+ return param.name === "Index"
188
+ ? `[]`
189
+ : `[ "${camelToKebab(param.name)}" ]`;
921
190
  }
922
- case "dynamic": {
923
- return [`\\\\/(?:([^/]+))`];
191
+ case "optional": {
192
+ return `Pages.Internal.Router.maybeToList params.${param.name}`;
924
193
  }
925
194
  case "required-splat": {
926
- return [`\\\\/(.*)`];
195
+ return `Pages.Internal.Router.nonEmptyToList params.${param.name}`;
927
196
  }
928
- case "optional-splat": {
929
- return [`(.*)`];
197
+ case "dynamic": {
198
+ return `[ params.${param.name} ]`;
930
199
  }
931
- case "optional": {
932
- return [`(?:\\\\/([^/]+))?`];
200
+ case "optional-splat": {
201
+ return `params.${param.name}`;
933
202
  }
934
203
  }
935
204
  })
936
- .join("");
205
+ .join(", ");
937
206
 
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
207
+ return `module Fetcher.${moduleName} exposing (submit)
971
208
 
972
- `;
209
+ {-| -}
973
210
 
974
- return { pattern: parserCode, toRoute };
975
- }
211
+ import Bytes exposing (Bytes)
212
+ import Bytes.Decode
213
+ import FormDecoder
214
+ import Http
215
+ import Pages.Fetcher
216
+ import Route.${moduleName}
976
217
 
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 "";
218
+
219
+ submit :
220
+ (Result Http.Error Route.${moduleName}.ActionData -> msg)
221
+ ->
222
+ { fields : List ( String, String )
223
+ , headers : List ( String, String )
224
+ }
225
+ -> Pages.Fetcher.Fetcher msg
226
+ submit toMsg options =
227
+ { decoder =
228
+ \\bytesResult ->
229
+ bytesResult
230
+ |> Result.andThen
231
+ (\\okBytes ->
232
+ okBytes
233
+ |> Bytes.Decode.decode Route.${moduleName}.w3_decode_ActionData
234
+ |> Result.fromMaybe (Http.BadBody "Couldn't decode bytes.")
235
+ )
236
+ |> toMsg
237
+ , fields = options.fields
238
+ , headers = ("elm-pages-action-only", "true") :: options.headers
239
+ , url = ${
240
+ fetcherPath === ""
241
+ ? 'Just "/content.dat"'
242
+ : `[ ${fetcherPath}, [ "content.dat" ] ] |> List.concat |> String.join "/" |> Just`
243
+ }
987
244
  }
988
- }
245
+ |> Pages.Fetcher.Fetcher
246
+ `;
989
247
  }
990
248
 
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
249
 
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
250
  /**
1019
251
  * Convert Strings from camelCase to kebab-case
1020
252
  * @param {string} input
@@ -1023,42 +255,6 @@ function withoutTrailingIndex(name) {
1023
255
  function camelToKebab(input) {
1024
256
  return input.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
1025
257
  }
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
258
 
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
259
 
1064
260
  module.exports = { generateTemplateModuleConnector, sortTemplates };