elm-pages 3.0.0-beta.4 → 3.0.0-beta.40

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 (140) hide show
  1. package/README.md +10 -1
  2. package/adapter/netlify.js +207 -0
  3. package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2678 -2725
  4. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
  5. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
  6. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
  7. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  8. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  9. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  10. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -1
  11. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1447 -342
  12. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +17004 -13817
  13. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  14. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
  15. package/generator/dead-code-review/elm.json +9 -7
  16. package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +59 -10
  17. package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +52 -36
  18. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
  19. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
  20. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
  21. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
  22. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  23. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  24. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  25. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
  26. package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1447 -342
  27. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25025 -21739
  28. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  29. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
  30. package/generator/review/elm.json +10 -10
  31. package/generator/src/RouteBuilder.elm +115 -109
  32. package/generator/src/SharedTemplate.elm +3 -2
  33. package/generator/src/SiteConfig.elm +3 -2
  34. package/generator/src/basepath-middleware.js +3 -3
  35. package/generator/src/build.js +209 -92
  36. package/generator/src/cli.js +292 -88
  37. package/generator/src/codegen.js +29 -27
  38. package/generator/src/compatibility-key.js +3 -0
  39. package/generator/src/compile-elm.js +43 -26
  40. package/generator/src/config.js +39 -0
  41. package/generator/src/copy-dir.js +2 -2
  42. package/generator/src/dev-server.js +176 -138
  43. package/generator/src/dir-helpers.js +9 -26
  44. package/generator/src/elm-codegen.js +5 -4
  45. package/generator/src/elm-file-constants.js +2 -3
  46. package/generator/src/error-formatter.js +12 -11
  47. package/generator/src/file-helpers.js +3 -4
  48. package/generator/src/generate-template-module-connector.js +23 -23
  49. package/generator/src/init.js +9 -8
  50. package/generator/src/pre-render-html.js +39 -28
  51. package/generator/src/render-test.js +109 -0
  52. package/generator/src/render-worker.js +25 -28
  53. package/generator/src/render.js +321 -142
  54. package/generator/src/request-cache.js +265 -162
  55. package/generator/src/resolve-elm-module.js +64 -0
  56. package/generator/src/rewrite-client-elm-json.js +6 -5
  57. package/generator/src/rewrite-elm-json-help.js +56 -0
  58. package/generator/src/rewrite-elm-json.js +17 -7
  59. package/generator/src/route-codegen-helpers.js +16 -31
  60. package/generator/src/seo-renderer.js +12 -7
  61. package/generator/src/vite-utils.js +77 -0
  62. package/generator/static-code/elm-pages.js +10 -0
  63. package/generator/static-code/hmr.js +79 -13
  64. package/generator/template/app/Api.elm +6 -5
  65. package/generator/template/app/Effect.elm +123 -0
  66. package/generator/template/app/ErrorPage.elm +37 -6
  67. package/generator/template/app/Route/Index.elm +17 -10
  68. package/generator/template/app/Shared.elm +24 -47
  69. package/generator/template/app/Site.elm +19 -6
  70. package/generator/template/app/View.elm +1 -8
  71. package/generator/template/elm-tooling.json +0 -3
  72. package/generator/template/elm.json +32 -24
  73. package/generator/template/package.json +10 -4
  74. package/package.json +30 -27
  75. package/src/ApiRoute.elm +199 -61
  76. package/src/BackendTask/Custom.elm +325 -0
  77. package/src/BackendTask/Env.elm +90 -0
  78. package/src/{DataSource → BackendTask}/File.elm +171 -56
  79. package/src/{DataSource → BackendTask}/Glob.elm +136 -125
  80. package/src/BackendTask/Http.elm +679 -0
  81. package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
  82. package/src/BackendTask/Internal/Request.elm +69 -0
  83. package/src/BackendTask/Random.elm +79 -0
  84. package/src/BackendTask/Time.elm +47 -0
  85. package/src/BackendTask.elm +537 -0
  86. package/src/FatalError.elm +90 -0
  87. package/src/Head.elm +237 -7
  88. package/src/HtmlPrinter.elm +7 -3
  89. package/src/Internal/ApiRoute.elm +7 -5
  90. package/src/PageServerResponse.elm +6 -1
  91. package/src/Pages/Form.elm +229 -0
  92. package/src/Pages/GeneratorProgramConfig.elm +15 -0
  93. package/src/Pages/Internal/FatalError.elm +5 -0
  94. package/src/Pages/Internal/Msg.elm +93 -0
  95. package/src/Pages/Internal/Platform/Cli.elm +612 -763
  96. package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
  97. package/src/Pages/Internal/Platform/Effect.elm +1 -2
  98. package/src/Pages/Internal/Platform/GeneratorApplication.elm +379 -0
  99. package/src/Pages/Internal/Platform/StaticResponses.elm +65 -276
  100. package/src/Pages/Internal/Platform/ToJsPayload.elm +6 -9
  101. package/src/Pages/Internal/Platform.elm +327 -194
  102. package/src/Pages/Internal/Script.elm +17 -0
  103. package/src/Pages/Internal/StaticHttpBody.elm +35 -1
  104. package/src/Pages/Manifest.elm +29 -4
  105. package/src/Pages/PageUrl.elm +23 -9
  106. package/src/Pages/ProgramConfig.elm +26 -15
  107. package/src/Pages/Script.elm +109 -0
  108. package/src/Pages/SiteConfig.elm +3 -2
  109. package/src/Pages/StaticHttp/Request.elm +2 -2
  110. package/src/Pages/StaticHttpRequest.elm +23 -99
  111. package/src/Pages/Transition.elm +12 -3
  112. package/src/PagesMsg.elm +82 -0
  113. package/src/Path.elm +16 -19
  114. package/src/QueryParams.elm +21 -172
  115. package/src/RequestsAndPending.elm +37 -20
  116. package/src/Result/Extra.elm +26 -0
  117. package/src/Scaffold/Form.elm +546 -0
  118. package/src/Scaffold/Route.elm +1402 -0
  119. package/src/Server/Request.elm +73 -72
  120. package/src/Server/Session.elm +62 -42
  121. package/src/Server/SetCookie.elm +12 -4
  122. package/src/Stub.elm +53 -0
  123. package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
  124. package/src/DataSource/Env.elm +0 -38
  125. package/src/DataSource/Http.elm +0 -446
  126. package/src/DataSource/Internal/Request.elm +0 -20
  127. package/src/DataSource/Port.elm +0 -90
  128. package/src/DataSource.elm +0 -538
  129. package/src/Form/Field.elm +0 -717
  130. package/src/Form/FieldStatus.elm +0 -36
  131. package/src/Form/FieldView.elm +0 -417
  132. package/src/Form/FormData.elm +0 -22
  133. package/src/Form/Validation.elm +0 -391
  134. package/src/Form/Value.elm +0 -118
  135. package/src/Form.elm +0 -1683
  136. package/src/FormDecoder.elm +0 -102
  137. package/src/Pages/FormState.elm +0 -256
  138. package/src/Pages/Generate.elm +0 -800
  139. package/src/Pages/Internal/Form.elm +0 -17
  140. package/src/Pages/Msg.elm +0 -79
@@ -1,21 +1,25 @@
1
- const fs = require("./dir-helpers.js");
2
- const fsPromises = require("fs").promises;
3
-
4
- const { runElmReview } = require("./compile-elm.js");
5
- const { restoreColorSafe } = require("./error-formatter");
6
- const path = require("path");
7
- const spawnCallback = require("cross-spawn").spawn;
8
- const codegen = require("./codegen.js");
9
- const terser = require("terser");
10
- const os = require("os");
11
- const { Worker, SHARE_ENV } = require("worker_threads");
12
- const { ensureDirSync } = require("./file-helpers.js");
13
- const { generateClientFolder } = require("./codegen.js");
14
- const which = require("which");
15
- const { build } = require("vite");
16
- const preRenderHtml = require("./pre-render-html.js");
17
- const esbuild = require("esbuild");
18
- const { createHash } = require("crypto");
1
+ import * as fs from "./dir-helpers.js";
2
+ import * as fsPromises from "fs/promises";
3
+ import { runElmReview } from "./compile-elm.js";
4
+ import { restoreColorSafe } from "./error-formatter.js";
5
+ import * as path from "path";
6
+ import { spawn as spawnCallback } from "cross-spawn";
7
+ import * as codegen from "./codegen.js";
8
+ import * as terser from "terser";
9
+ import * as os from "os";
10
+ import { Worker, SHARE_ENV } from "worker_threads";
11
+ import { ensureDirSync } from "./file-helpers.js";
12
+ import { generateClientFolder } from "./codegen.js";
13
+ import { default as which } from "which";
14
+ import { build } from "vite";
15
+ import * as preRenderHtml from "./pre-render-html.js";
16
+ import * as esbuild from "esbuild";
17
+ import { createHash } from "crypto";
18
+ import { merge_vite_configs } from "./vite-utils.js";
19
+ import { resolveConfig } from "./config.js";
20
+ import * as globby from "globby";
21
+ import { fileURLToPath } from "url";
22
+ import { copyFile } from "fs/promises";
19
23
 
20
24
  let pool = [];
21
25
  let pagesReady;
@@ -28,7 +32,6 @@ let pagesReadyCalled = false;
28
32
  let activeWorkers = 0;
29
33
  let buildError = false;
30
34
 
31
- const DIR_PATH = process.cwd();
32
35
  const OUTPUT_FILE_NAME = "elm.js";
33
36
 
34
37
  process.on("unhandledRejection", (error) => {
@@ -36,11 +39,9 @@ process.on("unhandledRejection", (error) => {
36
39
  process.exitCode = 1;
37
40
  });
38
41
 
39
- const ELM_FILE_PATH = path.join(
40
- DIR_PATH,
41
- "./elm-stuff/elm-pages",
42
- OUTPUT_FILE_NAME
43
- );
42
+ function ELM_FILE_PATH() {
43
+ return path.join(process.cwd(), "./elm-stuff/elm-pages", OUTPUT_FILE_NAME);
44
+ }
44
45
 
45
46
  async function ensureRequiredDirs() {
46
47
  ensureDirSync(`dist`);
@@ -65,50 +66,54 @@ async function ensureRequiredExecutables() {
65
66
  }
66
67
  }
67
68
 
68
- async function run(options) {
69
+ export async function run(options) {
70
+ const __filename = fileURLToPath(import.meta.url);
71
+ const __dirname = path.dirname(__filename);
72
+ console.warn = function (...messages) {
73
+ // This is a temporary hack to avoid this warning. elm-pages manages compiling the Elm code without Vite's involvement, so it is external to Vite.
74
+ // There is a pending issue to allow having external scripts in Vite, once this issue is fixed we can remove this hack:
75
+ // https://github.com/vitejs/vite/issues/3533
76
+ if (!messages[0]?.startsWith(`<script src="/elm.js">`)) {
77
+ console.info(...messages);
78
+ }
79
+ };
69
80
  try {
70
81
  await ensureRequiredDirs();
71
82
  await ensureRequiredExecutables();
72
- // since init/update are never called in pre-renders, and DataSource.Http is called using pure NodeJS HTTP fetching
83
+ // since init/update are never called in pre-renders, and BackendTask.Http is called using pure NodeJS HTTP fetching
73
84
  // we can provide a fake HTTP instead of xhr2 (which is otherwise needed for Elm HTTP requests from Node)
74
85
 
75
86
  const generateCode = codegen.generate(options.base);
76
87
 
77
88
  await generateCode;
89
+
90
+ const config = await resolveConfig();
78
91
  await fsPromises.writeFile(
79
92
  "elm-stuff/elm-pages/index.html",
80
- preRenderHtml.templateHtml()
93
+ preRenderHtml.templateHtml(false, config.headTagsTemplate)
81
94
  );
82
-
83
- const config = await import(
84
- path.join(process.cwd(), "elm-pages.config.mjs")
85
- )
86
- .then(async (elmPagesConfig) => {
87
- return elmPagesConfig.default || {};
88
- })
89
- .catch((error) => {
90
- console.warn(
91
- "No `elm-pages.config.mjs` file found. Using default config."
92
- );
93
- return {};
94
- });
95
- const viteConfig = config.vite || {};
96
-
97
- const buildComplete = build({
98
- configFile: false,
99
- root: process.cwd(),
100
- base: options.base,
101
- ssr: false,
102
-
103
- build: {
104
- manifest: true,
105
- outDir: "dist",
106
- rollupOptions: {
107
- input: "elm-stuff/elm-pages/index.html",
95
+ const viteConfig = merge_vite_configs(
96
+ {
97
+ configFile: false,
98
+ root: process.cwd(),
99
+ base: options.base,
100
+ ssr: false,
101
+
102
+ build: {
103
+ manifest: true,
104
+ outDir: "dist",
105
+ rollupOptions: {
106
+ input: "elm-stuff/elm-pages/index.html",
107
+ },
108
+ },
109
+ optimizeDeps: {
110
+ include: [],
108
111
  },
109
112
  },
110
- ...viteConfig,
111
- });
113
+ config.vite || {}
114
+ );
115
+
116
+ const buildComplete = build(viteConfig);
112
117
  const compileClientDone = compileElm(options);
113
118
  await buildComplete;
114
119
  await compileClientDone;
@@ -119,57 +124,144 @@ async function run(options) {
119
124
  withoutExtension
120
125
  );
121
126
  const assetManifestPath = path.join(process.cwd(), "dist/manifest.json");
122
- const manifest = require(assetManifestPath);
127
+ const manifest = JSON.parse(
128
+ await fsPromises.readFile(assetManifestPath, { encoding: "utf-8" })
129
+ );
123
130
  const indexTemplate = await fsPromises.readFile(
124
131
  "dist/elm-stuff/elm-pages/index.html",
125
132
  "utf-8"
126
133
  );
127
- const preloads = `<link rel="modulepreload" href="/${manifest["elm-stuff/elm-pages/index.html"]["file"]}" />`;
134
+ const preloadFiles = [
135
+ `elm.${browserElmHash}.js`,
136
+ ...Object.entries(manifest).map((entry) => entry[1].file),
137
+ ].map((file) => path.join(options.base, file));
138
+ const userProcessedPreloads = preloadFiles.flatMap((file) => {
139
+ const userPreloadForFile = config.preloadTagForFile(file);
140
+ if (userPreloadForFile === true) {
141
+ return [defaultPreloadForFile(file)];
142
+ } else if (userPreloadForFile === false) {
143
+ return [];
144
+ } else if (typeof userPreloadForFile === "string") {
145
+ return [userPreloadForFile];
146
+ } else {
147
+ throw `I expected preloadTagForFile in elm-pages.config.mjs to return a string or boolean, but instead it returned: ${userPreloadForFile}`;
148
+ }
149
+ });
128
150
 
129
151
  const processedIndexTemplate = indexTemplate
130
- .replace("<!-- PLACEHOLDER_PRELOADS -->", preloads)
152
+ .replace("<!-- PLACEHOLDER_PRELOADS -->", userProcessedPreloads.join(""))
131
153
  .replace(
132
154
  '<script defer src="/elm.js" type="text/javascript"></script>',
133
155
  `<script defer src="/elm.${browserElmHash}.js" type="text/javascript"></script>`
134
156
  );
135
157
  await fsPromises.writeFile("dist/template.html", processedIndexTemplate);
136
158
  await fsPromises.unlink(assetManifestPath);
137
-
138
- const portDataSourceCompiled = esbuild
159
+ const portBackendTaskCompiled = esbuild
139
160
  .build({
140
- entryPoints: ["./port-data-source"],
161
+ entryPoints: ["./custom-backend-task"],
141
162
  platform: "node",
142
- outfile: ".elm-pages/compiled-ports/port-data-source.js",
163
+ outfile: ".elm-pages/compiled-ports/custom-backend-task.mjs",
143
164
  assetNames: "[name]-[hash]",
144
165
  chunkNames: "chunks/[name]-[hash]",
145
166
  outExtension: { ".js": ".js" },
146
167
  metafile: true,
147
168
  bundle: true,
148
- watch: false,
149
- logLevel: "error",
169
+ format: "esm",
170
+ packages: "external",
171
+ logLevel: "silent",
150
172
  })
151
173
  .then((result) => {
152
- global.portsFilePath = Object.keys(result.metafile.outputs)[0];
174
+ try {
175
+ global.portsFilePath = Object.keys(result.metafile.outputs)[0];
176
+ } catch (e) {}
153
177
  })
154
178
  .catch((error) => {
155
- if (
156
- error.errors.length === 1 &&
157
- error.errors[0].text.includes(
158
- `Could not resolve "./port-data-source"`
159
- )
160
- ) {
161
- console.warn("No port-data-source file found.");
162
- } else {
163
- console.error("Failed to load port-data-source file", error);
179
+ const portBackendTaskFileFound =
180
+ globby.globbySync("./custom-backend-task.*").length > 0;
181
+ if (portBackendTaskFileFound) {
182
+ // don't present error if there are no files matching custom-backend-task
183
+ // if there are files matching custom-backend-task, warn the user in case something went wrong loading it
184
+ console.error("Failed to start custom-backend-task watcher", error);
164
185
  }
165
186
  });
166
- // TODO extract common code for compiling ports file?
167
187
 
168
- XMLHttpRequest = {};
188
+ global.XMLHttpRequest = {};
169
189
  const compileCli = compileCliApp(options);
170
190
  try {
171
191
  await compileCli;
172
192
  await compileClientDone;
193
+ await portBackendTaskCompiled;
194
+ const inlineRenderCode = `
195
+ import * as renderer from "./render.js";
196
+ import * as elmModule from "${path.resolve("./elm-stuff/elm-pages/elm.cjs")}";
197
+ import * as url from 'url';
198
+ ${
199
+ global.portsFilePath
200
+ ? `import * as customBackendTask from "${path.resolve(
201
+ global.portsFilePath
202
+ )}";`
203
+ : `const customBackendTask = {};`
204
+ }
205
+
206
+ import * as preRenderHtml from "./pre-render-html.js";
207
+ const basePath = \`${options.base || "/"}\`;
208
+ const htmlTemplate = ${JSON.stringify(processedIndexTemplate)};
209
+ const mode = "build";
210
+ const addWatcher = () => {};
211
+
212
+ export async function render(request) {
213
+ const requestTime = new Date();
214
+ const response = await renderer.render(
215
+ customBackendTask,
216
+ basePath,
217
+ elmModule.default,
218
+ mode,
219
+ (new url.URL(request.rawUrl)).pathname,
220
+ request,
221
+ addWatcher,
222
+ false
223
+ );
224
+ console.dir(response);
225
+ if (response.kind === "bytes") {
226
+ return {
227
+ body: response.contentDatPayload.buffer,
228
+ statusCode: response.statusCode,
229
+ kind: response.kind,
230
+ headers: response.headers,
231
+ }
232
+ } else if (response.kind === "api-response") {
233
+ // isBase64Encoded
234
+ return {
235
+ body: response.body.body,
236
+ statusCode: response.statusCode,
237
+ kind: response.kind,
238
+ headers: response.headers,
239
+ isBase64Encoded: response.body.isBase64Encoded,
240
+ }
241
+ } else {
242
+ return {
243
+ body: preRenderHtml.replaceTemplate(htmlTemplate, response.htmlString),
244
+ statusCode: response.statusCode,
245
+ kind: response.kind,
246
+ headers: response.headers,
247
+ }
248
+ }
249
+ }
250
+ `;
251
+ await esbuild.build({
252
+ format: "esm",
253
+ platform: "node",
254
+ stdin: { contents: inlineRenderCode, resolveDir: __dirname },
255
+ bundle: true,
256
+ // TODO do I need to make the outfile joined with the current working directory?
257
+
258
+ outfile: ".elm-pages/compiled/render.mjs",
259
+ // external: ["node:*", ...options.external],
260
+ packages: "external",
261
+ minify: true,
262
+ // absWorkingDir: projectDirectory,
263
+ // banner: { js: `#!/usr/bin/env node\n\n${ESM_REQUIRE_SHIM}` },
264
+ });
173
265
  } catch (cliError) {
174
266
  // TODO make sure not to print duplicate error output if cleaner review output is printed
175
267
  console.error(cliError);
@@ -184,7 +276,7 @@ async function run(options) {
184
276
  }
185
277
  process.exit(1);
186
278
  }
187
- await portDataSourceCompiled;
279
+ await portBackendTaskCompiled;
188
280
  const cliDone = runCli(options);
189
281
  await cliDone;
190
282
 
@@ -202,8 +294,9 @@ async function run(options) {
202
294
  processedIndexTemplate
203
295
  );
204
296
  } catch (error) {
297
+ console.trace(error);
205
298
  if (error) {
206
- console.error(error);
299
+ console.error(restoreColorSafe(error));
207
300
  }
208
301
  buildError = true;
209
302
  process.exitCode = 1;
@@ -215,6 +308,8 @@ async function run(options) {
215
308
  */
216
309
  function initWorker(basePath, whenDone) {
217
310
  return new Promise((resolve, reject) => {
311
+ const __filename = fileURLToPath(import.meta.url);
312
+ const __dirname = path.dirname(__filename);
218
313
  activeWorkers += 1;
219
314
  let newWorker = {
220
315
  worker: new Worker(path.join(__dirname, "./render-worker.js"), {
@@ -343,7 +438,7 @@ async function fingerprintElmAsset(fullOutputPath, withoutExtension) {
343
438
  return fileHash;
344
439
  }
345
440
 
346
- function elmOptimizeLevel2(outputPath, cwd) {
441
+ export function elmOptimizeLevel2(outputPath, cwd) {
347
442
  return new Promise((resolve, reject) => {
348
443
  const optimizedOutputPath = outputPath + ".opt";
349
444
  const subprocess = spawnCallback(
@@ -364,7 +459,7 @@ function elmOptimizeLevel2(outputPath, cwd) {
364
459
 
365
460
  subprocess.on("close", async (code) => {
366
461
  if (code === 0) {
367
- await fs.copyFile(optimizedOutputPath, outputPath);
462
+ await copyFile(optimizedOutputPath, outputPath);
368
463
  resolve();
369
464
  } else {
370
465
  if (!buildError) {
@@ -403,7 +498,7 @@ async function spawnElmMake(mode, options, elmEntrypointPath, outputPath, cwd) {
403
498
  "function appendSubmitter (myFormData, event) { event.submitter && event.submitter.name && event.submitter.name.length > 0 ? myFormData.append(event.submitter.name, event.submitter.value) : myFormData; return myFormData }; return " +
404
499
  (options.debug
405
500
  ? "_Json_wrap(Array.from(appendSubmitter(new FormData(_Json_unwrap(event).target), _Json_unwrap(event))))"
406
- : "Array.from(new FormData(event.target))")
501
+ : "[...(appendSubmitter(new FormData(event.target), event))]")
407
502
  )
408
503
  );
409
504
  }
@@ -433,8 +528,9 @@ function modeToOptions(mode) {
433
528
  */
434
529
  function runElmMake(mode, options, elmEntrypointPath, outputPath, cwd) {
435
530
  return new Promise(async (resolve, reject) => {
531
+ const executableName = options.executableName || "lamdera";
436
532
  const subprocess = spawnCallback(
437
- `lamdera`,
533
+ executableName,
438
534
  [
439
535
  "make",
440
536
  elmEntrypointPath,
@@ -491,7 +587,7 @@ function runElmMake(mode, options, elmEntrypointPath, outputPath, cwd) {
491
587
  /**
492
588
  * @param {string} filePath
493
589
  */
494
- async function runTerser(filePath) {
590
+ export async function runTerser(filePath) {
495
591
  console.log("Running terser");
496
592
  const minifiedElm = await terser.minify(
497
593
  (await fsPromises.readFile(filePath)).toString(),
@@ -534,7 +630,7 @@ async function runTerser(filePath) {
534
630
  }
535
631
  }
536
632
 
537
- async function compileCliApp(options) {
633
+ export async function compileCliApp(options) {
538
634
  await spawnElmMake(
539
635
  // TODO should be --optimize, but there seems to be an issue with the html to JSON with --optimize
540
636
  options.debug ? "debug" : "optimize",
@@ -544,7 +640,7 @@ async function compileCliApp(options) {
544
640
  path.join(process.cwd(), "elm-stuff/elm-pages")
545
641
  );
546
642
 
547
- const elmFileContent = await fsPromises.readFile(ELM_FILE_PATH, "utf-8");
643
+ const elmFileContent = await fsPromises.readFile(ELM_FILE_PATH(), "utf-8");
548
644
  // Source: https://github.com/elm-explorations/test/blob/d5eb84809de0f8bbf50303efd26889092c800609/src/Elm/Kernel/HtmlAsJson.js
549
645
  const forceThunksSource = ` _HtmlAsJson_toJson(x)
550
646
  }
@@ -590,7 +686,7 @@ function _HtmlAsJson_toJson(html) {
590
686
  `;
591
687
 
592
688
  await fsPromises.writeFile(
593
- ELM_FILE_PATH,
689
+ ELM_FILE_PATH().replace(/\.js$/, ".cjs"),
594
690
  elmFileContent
595
691
  .replace(
596
692
  /return \$elm\$json\$Json\$Encode\$string\(.REPLACE_ME_WITH_JSON_STRINGIFY.\)/g,
@@ -605,19 +701,17 @@ function _HtmlAsJson_toJson(html) {
605
701
  async function runAdapter(adaptFn, processedIndexTemplate) {
606
702
  try {
607
703
  await adaptFn({
608
- renderFunctionFilePath: "./elm-stuff/elm-pages/elm.js",
704
+ renderFunctionFilePath: "./.elm-pages/compiled/render.mjs",
609
705
  routePatterns: JSON.parse(
610
706
  await fsPromises.readFile("./dist/route-patterns.json", "utf-8")
611
707
  ),
612
708
  apiRoutePatterns: JSON.parse(
613
709
  await fsPromises.readFile("./dist/api-patterns.json", "utf-8")
614
710
  ),
615
- portsFilePath: "./.elm-pages/compiled-ports/port-data-source.js",
616
- htmlTemplate: processedIndexTemplate,
617
711
  });
618
712
  console.log("Success - Adapter script complete");
619
713
  } catch (error) {
620
- console.error("ERROR - Adapter script failed");
714
+ console.trace("ERROR - Adapter script failed", error);
621
715
  try {
622
716
  console.error(JSON.stringify(error));
623
717
  } catch (parsingError) {
@@ -627,6 +721,31 @@ async function runAdapter(adaptFn, processedIndexTemplate) {
627
721
  }
628
722
  }
629
723
 
724
+ // Source: https://github.com/vitejs/vite/blob/c53ffec3465d2d28d08d29ca61313469e03f5dd6/playground/ssr-vue/src/entry-server.js#L50-L68
725
+ /**
726
+ * @param {string} file
727
+ */
728
+ function defaultPreloadForFile(file) {
729
+ if (file.endsWith(".js")) {
730
+ return `<link rel="modulepreload" crossorigin href="${file}">`;
731
+ } else if (file.endsWith(".css")) {
732
+ return `<link rel="preload" href="${file}" as="style">`;
733
+ } else if (file.endsWith(".woff")) {
734
+ return ` <link rel="preload" href="${file}" as="font" type="font/woff" crossorigin>`;
735
+ } else if (file.endsWith(".woff2")) {
736
+ return ` <link rel="preload" href="${file}" as="font" type="font/woff2" crossorigin>`;
737
+ } else if (file.endsWith(".gif")) {
738
+ return ` <link rel="preload" href="${file}" as="image" type="image/gif">`;
739
+ } else if (file.endsWith(".jpg") || file.endsWith(".jpeg")) {
740
+ return ` <link rel="preload" href="${file}" as="image" type="image/jpeg">`;
741
+ } else if (file.endsWith(".png")) {
742
+ return ` <link rel="preload" href="${file}" as="image" type="image/png">`;
743
+ } else {
744
+ // TODO
745
+ return "";
746
+ }
747
+ }
748
+
630
749
  /** @typedef { { route : string; contentJson : string; head : SeoTag[]; html: string; body: string; } } FromElm */
631
750
  /** @typedef {HeadTag | JsonLdTag} SeoTag */
632
751
  /** @typedef {{ name: string; attributes: string[][]; type: 'head' }} HeadTag */
@@ -641,5 +760,3 @@ async function runAdapter(adaptFn, processedIndexTemplate) {
641
760
  * @param {string} contentJsonString
642
761
  * @returns {string}
643
762
  */
644
-
645
- module.exports = { run };