elm-pages 3.0.0-beta.3 → 3.0.0-beta.31

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 (129) hide show
  1. package/README.md +10 -1
  2. package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2864 -2589
  3. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
  4. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
  5. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
  6. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  7. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  8. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  9. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -1
  10. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1447 -342
  11. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +16458 -13724
  12. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  13. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
  14. package/generator/dead-code-review/elm.json +9 -7
  15. package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +59 -10
  16. package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +52 -36
  17. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
  18. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
  19. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
  20. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
  21. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  22. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  23. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  24. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
  25. package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1447 -342
  26. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +24542 -21748
  27. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  28. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
  29. package/generator/review/elm.json +10 -10
  30. package/generator/src/RouteBuilder.elm +113 -107
  31. package/generator/src/SharedTemplate.elm +3 -2
  32. package/generator/src/SiteConfig.elm +3 -2
  33. package/generator/src/basepath-middleware.js +3 -3
  34. package/generator/src/build.js +125 -88
  35. package/generator/src/cli.js +273 -88
  36. package/generator/src/codegen.js +29 -27
  37. package/generator/src/compatibility-key.js +3 -0
  38. package/generator/src/compile-elm.js +43 -26
  39. package/generator/src/config.js +39 -0
  40. package/generator/src/copy-dir.js +2 -2
  41. package/generator/src/dev-server.js +150 -133
  42. package/generator/src/dir-helpers.js +9 -26
  43. package/generator/src/elm-codegen.js +5 -4
  44. package/generator/src/elm-file-constants.js +2 -3
  45. package/generator/src/error-formatter.js +12 -11
  46. package/generator/src/file-helpers.js +3 -4
  47. package/generator/src/generate-template-module-connector.js +23 -22
  48. package/generator/src/init.js +9 -8
  49. package/generator/src/pre-render-html.js +39 -28
  50. package/generator/src/render-test.js +109 -0
  51. package/generator/src/render-worker.js +25 -28
  52. package/generator/src/render.js +320 -142
  53. package/generator/src/request-cache.js +252 -163
  54. package/generator/src/resolve-elm-module.js +63 -0
  55. package/generator/src/rewrite-client-elm-json.js +6 -5
  56. package/generator/src/rewrite-elm-json-help.js +56 -0
  57. package/generator/src/rewrite-elm-json.js +17 -7
  58. package/generator/src/route-codegen-helpers.js +16 -31
  59. package/generator/src/seo-renderer.js +12 -7
  60. package/generator/src/vite-utils.js +77 -0
  61. package/generator/static-code/hmr.js +79 -13
  62. package/generator/template/app/Api.elm +6 -5
  63. package/generator/template/app/Effect.elm +123 -0
  64. package/generator/template/app/ErrorPage.elm +37 -6
  65. package/generator/template/app/Route/Index.elm +17 -10
  66. package/generator/template/app/Shared.elm +24 -47
  67. package/generator/template/app/Site.elm +19 -6
  68. package/generator/template/app/View.elm +1 -8
  69. package/generator/template/elm-tooling.json +0 -3
  70. package/generator/template/elm.json +32 -24
  71. package/generator/template/package.json +10 -4
  72. package/package.json +29 -27
  73. package/src/ApiRoute.elm +199 -61
  74. package/src/BackendTask/Custom.elm +325 -0
  75. package/src/BackendTask/Env.elm +90 -0
  76. package/src/{DataSource → BackendTask}/File.elm +128 -43
  77. package/src/{DataSource → BackendTask}/Glob.elm +136 -125
  78. package/src/BackendTask/Http.elm +673 -0
  79. package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
  80. package/src/BackendTask/Internal/Request.elm +28 -0
  81. package/src/BackendTask/Random.elm +79 -0
  82. package/src/BackendTask/Time.elm +47 -0
  83. package/src/BackendTask.elm +537 -0
  84. package/src/FatalError.elm +89 -0
  85. package/src/Form/Field.elm +21 -9
  86. package/src/Form/FieldView.elm +94 -14
  87. package/src/Form.elm +275 -400
  88. package/src/Head.elm +237 -7
  89. package/src/HtmlPrinter.elm +7 -3
  90. package/src/Internal/ApiRoute.elm +7 -5
  91. package/src/PageServerResponse.elm +6 -1
  92. package/src/Pages/FormState.elm +6 -5
  93. package/src/Pages/GeneratorProgramConfig.elm +15 -0
  94. package/src/Pages/Internal/FatalError.elm +5 -0
  95. package/src/Pages/Internal/Form.elm +21 -1
  96. package/src/Pages/{Msg.elm → Internal/Msg.elm} +26 -16
  97. package/src/Pages/Internal/Platform/Cli.elm +598 -763
  98. package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
  99. package/src/Pages/Internal/Platform/Effect.elm +1 -2
  100. package/src/Pages/Internal/Platform/GeneratorApplication.elm +373 -0
  101. package/src/Pages/Internal/Platform/StaticResponses.elm +73 -270
  102. package/src/Pages/Internal/Platform/ToJsPayload.elm +4 -7
  103. package/src/Pages/Internal/Platform.elm +216 -102
  104. package/src/Pages/Internal/Script.elm +17 -0
  105. package/src/Pages/Internal/StaticHttpBody.elm +35 -1
  106. package/src/Pages/Manifest.elm +29 -4
  107. package/src/Pages/PageUrl.elm +23 -9
  108. package/src/Pages/ProgramConfig.elm +14 -10
  109. package/src/Pages/Script.elm +109 -0
  110. package/src/Pages/SiteConfig.elm +3 -2
  111. package/src/Pages/StaticHttp/Request.elm +2 -2
  112. package/src/Pages/StaticHttpRequest.elm +23 -98
  113. package/src/PagesMsg.elm +92 -0
  114. package/src/Path.elm +16 -19
  115. package/src/QueryParams.elm +21 -172
  116. package/src/RequestsAndPending.elm +8 -19
  117. package/src/Result/Extra.elm +26 -0
  118. package/src/Scaffold/Form.elm +560 -0
  119. package/src/Scaffold/Route.elm +1388 -0
  120. package/src/Server/Request.elm +43 -37
  121. package/src/Server/Session.elm +62 -42
  122. package/src/Server/SetCookie.elm +12 -4
  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/Pages/Generate.elm +0 -800
@@ -1,67 +1,220 @@
1
1
  // @ts-check
2
2
 
3
- const path = require("path");
4
- const mm = require("micromatch");
5
- const matter = require("gray-matter");
6
- const globby = require("globby");
7
- const fsPromises = require("fs").promises;
8
- const preRenderHtml = require("./pre-render-html.js");
9
- const { lookupOrPerform } = require("./request-cache.js");
10
- const kleur = require("kleur");
11
- const cookie = require("cookie-signature");
12
- kleur.enabled = true;
3
+ import * as path from "node:path";
4
+ import { default as mm } from "micromatch";
5
+ import { default as matter } from "gray-matter";
6
+ import * as globby from "globby";
7
+ import * as fsPromises from "node:fs/promises";
8
+ import * as preRenderHtml from "./pre-render-html.js";
9
+ import { lookupOrPerform } from "./request-cache.js";
10
+ import * as kleur from "kleur/colors";
11
+ import * as cookie from "cookie-signature";
12
+ import { compatibilityKey } from "./compatibility-key.js";
13
+ import * as fs from "node:fs";
14
+ import * as crypto from "node:crypto";
15
+ import { restoreColorSafe } from "./error-formatter.js";
13
16
 
14
17
  process.on("unhandledRejection", (error) => {
15
18
  console.error(error);
16
19
  });
17
20
  let foundErrors;
18
- let pendingDataSourceResponses;
19
- let pendingDataSourceCount;
20
21
 
21
- module.exports =
22
- /**
23
- *
24
- * @param {string} basePath
25
- * @param {Object} elmModule
26
- * @param {string} path
27
- * @param {{ method: string; hostname: string; query: Record<string, string | undefined>; headers: Record<string, string>; host: string; pathname: string; port: number | null; protocol: string; rawUrl: string; }} request
28
- * @param {(pattern: string) => void} addDataSourceWatcher
29
- * @param {boolean} hasFsAccess
30
- * @returns
31
- */
32
- async function run(
22
+ /**
23
+ *
24
+ * @param {string} basePath
25
+ * @param {Object} elmModule
26
+ * @param {string} path
27
+ * @param {{ method: string; hostname: string; query: Record<string, string | undefined>; headers: Record<string, string>; host: string; pathname: string; port: number | null; protocol: string; rawUrl: string; }} request
28
+ * @param {(pattern: string) => void} addBackendTaskWatcher
29
+ * @param {boolean} hasFsAccess
30
+ * @returns
31
+ */
32
+ export async function render(
33
+ portsFile,
34
+ basePath,
35
+ elmModule,
36
+ mode,
37
+ path,
38
+ request,
39
+ addBackendTaskWatcher,
40
+ hasFsAccess
41
+ ) {
42
+ // const { fs, resetInMemoryFs } = require("./request-cache-fs.js")(hasFsAccess);
43
+ // resetInMemoryFs();
44
+ foundErrors = false;
45
+ // since init/update are never called in pre-renders, and BackendTask.Http is called using pure NodeJS HTTP fetching
46
+ // we can provide a fake HTTP instead of xhr2 (which is otherwise needed for Elm HTTP requests from Node)
47
+ global.XMLHttpRequest = {};
48
+ const result = await runElmApp(
33
49
  portsFile,
34
50
  basePath,
35
51
  elmModule,
36
52
  mode,
37
53
  path,
38
54
  request,
39
- addDataSourceWatcher,
55
+ addBackendTaskWatcher,
40
56
  hasFsAccess
41
- ) {
42
- const { fs, resetInMemoryFs } = require("./request-cache-fs.js")(
43
- hasFsAccess
44
- );
45
- resetInMemoryFs();
46
- foundErrors = false;
47
- pendingDataSourceResponses = [];
48
- pendingDataSourceCount = 0;
49
- // since init/update are never called in pre-renders, and DataSource.Http is called using pure NodeJS HTTP fetching
50
- // we can provide a fake HTTP instead of xhr2 (which is otherwise needed for Elm HTTP requests from Node)
51
- XMLHttpRequest = {};
52
- const result = await runElmApp(
57
+ );
58
+ return result;
59
+ }
60
+
61
+ /**
62
+ * @param {Object} elmModule
63
+ * @returns
64
+ * @param {string[]} cliOptions
65
+ * @param {any} portsFile
66
+ * @param {string} scriptModuleName
67
+ */
68
+ export async function runGenerator(
69
+ cliOptions,
70
+ portsFile,
71
+ elmModule,
72
+ scriptModuleName
73
+ ) {
74
+ global.isRunningGenerator = true;
75
+ // const { fs, resetInMemoryFs } = require("./request-cache-fs.js")(true);
76
+ // resetInMemoryFs();
77
+ foundErrors = false;
78
+ // since init/update are never called in pre-renders, and BackendTask.Http is called using pure NodeJS HTTP fetching
79
+ // we can provide a fake HTTP instead of xhr2 (which is otherwise needed for Elm HTTP requests from Node)
80
+ global.XMLHttpRequest = {};
81
+ try {
82
+ const result = await runGeneratorAppHelp(
83
+ cliOptions,
53
84
  portsFile,
54
- basePath,
85
+ "",
55
86
  elmModule,
56
- mode,
57
- path,
58
- request,
59
- addDataSourceWatcher,
60
- fs,
61
- hasFsAccess
87
+ scriptModuleName,
88
+ "production",
89
+ "",
90
+ true
62
91
  );
63
92
  return result;
64
- };
93
+ } catch (error) {
94
+ console.log(restoreColorSafe(error));
95
+ }
96
+ }
97
+ /**
98
+ * @param {string} basePath
99
+ * @param {Object} elmModule
100
+ * @param {string} pagePath
101
+ * @param {string} mode
102
+ * @returns {Promise<({is404: boolean;} & ({kind: 'json';contentJson: string;} | {kind: 'html';htmlString: string;} | {kind: 'api-response';body: string;}))>}
103
+ * @param {string[]} cliOptions
104
+ * @param {any} portsFile
105
+ * @param {typeof import("fs") | import("memfs").IFs} fs
106
+ * @param {boolean} hasFsAccess
107
+ * @param {string} scriptModuleName
108
+ */
109
+ function runGeneratorAppHelp(
110
+ cliOptions,
111
+ portsFile,
112
+ basePath,
113
+ elmModule,
114
+ scriptModuleName,
115
+ mode,
116
+ pagePath,
117
+ hasFsAccess
118
+ ) {
119
+ const isDevServer = mode !== "build";
120
+ let patternsToWatch = new Set();
121
+ let app = null;
122
+ let killApp;
123
+ return new Promise((resolve, reject) => {
124
+ const isBytes = pagePath.match(/content\.dat\/?$/);
125
+
126
+ app = elmModule.Elm.Main.init({
127
+ flags: {
128
+ compatibilityKey,
129
+ argv: ["", `elm-pages run ${scriptModuleName}`, ...cliOptions],
130
+ versionMessage: "1.2.3",
131
+ },
132
+ });
133
+
134
+ killApp = () => {
135
+ app.ports.toJsPort.unsubscribe(portHandler);
136
+ app.die();
137
+ app = null;
138
+ // delete require.cache[require.resolve(compiledElmPath)];
139
+ };
140
+
141
+ async function portHandler(/** @type { FromElm } */ newThing) {
142
+ let fromElm;
143
+ let contentDatPayload;
144
+
145
+ fromElm = newThing;
146
+ if (fromElm.command === "log") {
147
+ console.log(fromElm.value);
148
+ } else if (fromElm.tag === "ApiResponse") {
149
+ // Finished successfully
150
+ process.exit(0);
151
+ } else if (fromElm.tag === "PageProgress") {
152
+ const args = fromElm.args[0];
153
+
154
+ if (isBytes) {
155
+ resolve({
156
+ kind: "bytes",
157
+ is404: false,
158
+ contentJson: JSON.stringify({
159
+ staticData: args.contentJson,
160
+ is404: false,
161
+ }),
162
+ statusCode: args.statusCode,
163
+ headers: args.headers,
164
+ contentDatPayload,
165
+ });
166
+ } else {
167
+ resolve(
168
+ outputString(basePath, fromElm, isDevServer, contentDatPayload)
169
+ );
170
+ }
171
+ } else if (fromElm.tag === "DoHttp") {
172
+ app.ports.gotBatchSub.send(
173
+ Object.fromEntries(
174
+ await Promise.all(
175
+ fromElm.args[0].map(([requestHash, requestToPerform]) => {
176
+ if (
177
+ requestToPerform.url !== "elm-pages-internal://port" &&
178
+ requestToPerform.url.startsWith("elm-pages-internal://")
179
+ ) {
180
+ return runInternalJob(
181
+ requestHash,
182
+ app,
183
+ mode,
184
+ requestToPerform,
185
+ hasFsAccess,
186
+ patternsToWatch
187
+ );
188
+ } else {
189
+ return runHttpJob(
190
+ requestHash,
191
+ portsFile,
192
+ app,
193
+ mode,
194
+ requestToPerform,
195
+ hasFsAccess,
196
+ requestToPerform
197
+ );
198
+ }
199
+ })
200
+ )
201
+ )
202
+ );
203
+ } else if (fromElm.tag === "Errors") {
204
+ foundErrors = true;
205
+ reject(fromElm.args[0].errorsJson);
206
+ } else {
207
+ console.log(fromElm);
208
+ }
209
+ }
210
+ app.ports.toJsPort.subscribe(portHandler);
211
+ }).finally(() => {
212
+ try {
213
+ killApp();
214
+ killApp = null;
215
+ } catch (error) {}
216
+ });
217
+ }
65
218
 
66
219
  /**
67
220
  * @param {string} basePath
@@ -69,7 +222,7 @@ module.exports =
69
222
  * @param {string} pagePath
70
223
  * @param {string} mode
71
224
  * @param {{ method: string; hostname: string; query: string; headers: Object; host: string; pathname: string; port: string; protocol: string; rawUrl: string; }} request
72
- * @param {(pattern: string) => void} addDataSourceWatcher
225
+ * @param {(pattern: string) => void} addBackendTaskWatcher
73
226
  * @returns {Promise<({is404: boolean} & ( { kind: 'json'; contentJson: string} | { kind: 'html'; htmlString: string } | { kind: 'api-response'; body: string; }) )>}
74
227
  */
75
228
  function runElmApp(
@@ -79,8 +232,7 @@ function runElmApp(
79
232
  mode,
80
233
  pagePath,
81
234
  request,
82
- addDataSourceWatcher,
83
- fs,
235
+ addBackendTaskWatcher,
84
236
  hasFsAccess
85
237
  ) {
86
238
  const isDevServer = mode !== "build";
@@ -94,10 +246,10 @@ function runElmApp(
94
246
  .replace(/content\.dat\/?$/, "");
95
247
 
96
248
  const modifiedRequest = { ...request, path: route };
97
- // console.log("StaticHttp cache keys", Object.keys(global.staticHttpCache));
98
249
  app = elmModule.Elm.Main.init({
99
250
  flags: {
100
251
  mode,
252
+ compatibilityKey,
101
253
  request: {
102
254
  payload: modifiedRequest,
103
255
  kind: "single-page",
@@ -127,9 +279,6 @@ function runElmApp(
127
279
  console.log(fromElm.value);
128
280
  } else if (fromElm.tag === "ApiResponse") {
129
281
  const args = fromElm.args[0];
130
- if (mode === "build") {
131
- global.staticHttpCache = args.staticHttpCache;
132
- }
133
282
 
134
283
  resolve({
135
284
  kind: "api-response",
@@ -139,10 +288,6 @@ function runElmApp(
139
288
  });
140
289
  } else if (fromElm.tag === "PageProgress") {
141
290
  const args = fromElm.args[0];
142
- if (mode === "build") {
143
- global.staticHttpCache = args.staticHttpCache;
144
- }
145
-
146
291
  if (isBytes) {
147
292
  resolve({
148
293
  kind: "bytes",
@@ -161,30 +306,37 @@ function runElmApp(
161
306
  );
162
307
  }
163
308
  } else if (fromElm.tag === "DoHttp") {
164
- const requestToPerform = fromElm.args[0];
165
- if (
166
- requestToPerform.url !== "elm-pages-internal://port" &&
167
- requestToPerform.url.startsWith("elm-pages-internal://")
168
- ) {
169
- runInternalJob(
170
- app,
171
- mode,
172
- requestToPerform,
173
- fs,
174
- hasFsAccess,
175
- patternsToWatch
176
- );
177
- } else {
178
- runHttpJob(
179
- portsFile,
180
- app,
181
- mode,
182
- requestToPerform,
183
- fs,
184
- hasFsAccess,
185
- fromElm.args[1]
186
- );
187
- }
309
+ app.ports.gotBatchSub.send(
310
+ Object.fromEntries(
311
+ await Promise.all(
312
+ fromElm.args[0].map(([requestHash, requestToPerform]) => {
313
+ if (
314
+ requestToPerform.url !== "elm-pages-internal://port" &&
315
+ requestToPerform.url.startsWith("elm-pages-internal://")
316
+ ) {
317
+ return runInternalJob(
318
+ requestHash,
319
+ app,
320
+ mode,
321
+ requestToPerform,
322
+ hasFsAccess,
323
+ patternsToWatch
324
+ );
325
+ } else {
326
+ return runHttpJob(
327
+ requestHash,
328
+ portsFile,
329
+ app,
330
+ mode,
331
+ requestToPerform,
332
+ hasFsAccess,
333
+ requestToPerform
334
+ );
335
+ }
336
+ })
337
+ )
338
+ )
339
+ );
188
340
  } else if (fromElm.tag === "Errors") {
189
341
  foundErrors = true;
190
342
  reject(fromElm.args[0].errorsJson);
@@ -195,7 +347,7 @@ function runElmApp(
195
347
  app.ports.toJsPort.subscribe(portHandler);
196
348
  app.ports.sendPageData.subscribe(portHandler);
197
349
  }).finally(() => {
198
- addDataSourceWatcher(patternsToWatch);
350
+ addBackendTaskWatcher(patternsToWatch);
199
351
  try {
200
352
  killApp();
201
353
  killApp = null;
@@ -244,17 +396,16 @@ async function outputString(
244
396
  /** @typedef { { head: any[]; errors: any[]; contentJson: any[]; html: string; route: string; title: string; } } Arg */
245
397
 
246
398
  async function runHttpJob(
399
+ requestHash,
247
400
  portsFile,
248
401
  app,
249
402
  mode,
250
403
  requestToPerform,
251
- fs,
252
404
  hasFsAccess,
253
405
  useCache
254
406
  ) {
255
- pendingDataSourceCount += 1;
256
407
  try {
257
- const responseFilePath = await lookupOrPerform(
408
+ const lookupResponse = await lookupOrPerform(
258
409
  portsFile,
259
410
  mode,
260
411
  requestToPerform,
@@ -262,17 +413,31 @@ async function runHttpJob(
262
413
  useCache
263
414
  );
264
415
 
265
- pendingDataSourceResponses.push({
266
- request: requestToPerform,
267
- response: JSON.parse(
268
- (await fs.promises.readFile(responseFilePath, "utf8")).toString()
269
- ),
270
- });
416
+ if (lookupResponse.kind === "cache-response-path") {
417
+ const responseFilePath = lookupResponse.value;
418
+ return [
419
+ requestHash,
420
+ {
421
+ request: requestToPerform,
422
+ response: JSON.parse(
423
+ (await fs.promises.readFile(responseFilePath, "utf8")).toString()
424
+ ),
425
+ },
426
+ ];
427
+ } else if (lookupResponse.kind === "response-json") {
428
+ return [
429
+ requestHash,
430
+ {
431
+ request: requestToPerform,
432
+ response: lookupResponse.value,
433
+ },
434
+ ];
435
+ } else {
436
+ throw `Unexpected kind ${lookupResponse}`;
437
+ }
271
438
  } catch (error) {
272
- sendError(app, error);
273
- } finally {
274
- pendingDataSourceCount -= 1;
275
- flushIfDone(app);
439
+ console.log("@@@ERROR", error);
440
+ // sendError(app, error);
276
441
  }
277
442
  }
278
443
 
@@ -290,46 +455,54 @@ function jsonResponse(request, json) {
290
455
  }
291
456
 
292
457
  async function runInternalJob(
458
+ requestHash,
293
459
  app,
294
460
  mode,
295
461
  requestToPerform,
296
- fs,
297
462
  hasFsAccess,
298
463
  patternsToWatch
299
464
  ) {
300
465
  try {
301
- pendingDataSourceCount += 1;
302
-
303
- if (requestToPerform.url === "elm-pages-internal://read-file") {
304
- pendingDataSourceResponses.push(
305
- await readFileJobNew(requestToPerform, patternsToWatch)
306
- );
466
+ if (requestToPerform.url === "elm-pages-internal://log") {
467
+ return [requestHash, await runLogJob(requestToPerform)];
468
+ } else if (requestToPerform.url === "elm-pages-internal://read-file") {
469
+ return [
470
+ requestHash,
471
+ await readFileJobNew(requestToPerform, patternsToWatch),
472
+ ];
307
473
  } else if (requestToPerform.url === "elm-pages-internal://glob") {
308
- pendingDataSourceResponses.push(
309
- await runGlobNew(requestToPerform, patternsToWatch)
310
- );
474
+ return [requestHash, await runGlobNew(requestToPerform, patternsToWatch)];
475
+ } else if (requestToPerform.url === "elm-pages-internal://randomSeed") {
476
+ return [
477
+ requestHash,
478
+ jsonResponse(
479
+ requestToPerform,
480
+ crypto.getRandomValues(new Uint32Array(1))[0]
481
+ ),
482
+ ];
483
+ } else if (requestToPerform.url === "elm-pages-internal://now") {
484
+ return [requestHash, jsonResponse(requestToPerform, Date.now())];
311
485
  } else if (requestToPerform.url === "elm-pages-internal://env") {
312
- pendingDataSourceResponses.push(
313
- await runEnvJob(requestToPerform, patternsToWatch)
314
- );
486
+ return [requestHash, await runEnvJob(requestToPerform, patternsToWatch)];
315
487
  } else if (requestToPerform.url === "elm-pages-internal://encrypt") {
316
- pendingDataSourceResponses.push(
317
- await runEncryptJob(requestToPerform, patternsToWatch)
318
- );
488
+ return [
489
+ requestHash,
490
+ await runEncryptJob(requestToPerform, patternsToWatch),
491
+ ];
319
492
  } else if (requestToPerform.url === "elm-pages-internal://decrypt") {
320
- pendingDataSourceResponses.push(
321
- await runDecryptJob(requestToPerform, patternsToWatch)
322
- );
493
+ return [
494
+ requestHash,
495
+ await runDecryptJob(requestToPerform, patternsToWatch),
496
+ ];
497
+ } else if (requestToPerform.url === "elm-pages-internal://write-file") {
498
+ return [requestHash, await runWriteFileJob(requestToPerform)];
323
499
  } else {
324
- throw `Unexpected internal DataSource request format: ${kleur.yellow(
500
+ throw `Unexpected internal BackendTask request format: ${kleur.yellow(
325
501
  JSON.stringify(2, null, requestToPerform)
326
502
  )}`;
327
503
  }
328
504
  } catch (error) {
329
505
  sendError(app, error);
330
- } finally {
331
- pendingDataSourceCount -= 1;
332
- flushIfDone(app);
333
506
  }
334
507
  }
335
508
 
@@ -344,6 +517,7 @@ async function readFileJobNew(req, patternsToWatch) {
344
517
  path.join(process.env.LAMBDA_TASK_ROOT || process.cwd(), filePath)
345
518
  )
346
519
  ).toString();
520
+ // TODO does this throw an error if there is invalid frontmatter?
347
521
  const parsedFile = matter(fileContents);
348
522
 
349
523
  return jsonResponse(req, {
@@ -352,10 +526,24 @@ async function readFileJobNew(req, patternsToWatch) {
352
526
  rawFile: fileContents,
353
527
  });
354
528
  } catch (error) {
529
+ return jsonResponse(req, {
530
+ errorCode: error.code,
531
+ });
532
+ }
533
+ }
534
+ async function runWriteFileJob(req) {
535
+ const data = req.body.args[0];
536
+ try {
537
+ const fullPathToWrite = path.join(process.cwd(), data.path);
538
+ await fsPromises.mkdir(path.dirname(fullPathToWrite), { recursive: true });
539
+ await fsPromises.writeFile(fullPathToWrite, data.body);
540
+ return jsonResponse(req, null);
541
+ } catch (error) {
542
+ console.trace(error);
355
543
  throw {
356
- title: "DataSource.File Error",
357
- message: `A DataSource.File read failed because I couldn't find this file: ${kleur.yellow(
358
- filePath
544
+ title: "BackendTask Error",
545
+ message: `BackendTask.Generator.writeFile failed for file path: ${kleur.yellow(
546
+ data.path
359
547
  )}\n${kleur.red(error.toString())}`,
360
548
  };
361
549
  }
@@ -364,7 +552,7 @@ async function readFileJobNew(req, patternsToWatch) {
364
552
  async function runGlobNew(req, patternsToWatch) {
365
553
  try {
366
554
  const { pattern, options } = req.body.args[0];
367
- const matchedPaths = await globby(pattern, options);
555
+ const matchedPaths = await globby.globby(pattern, options);
368
556
  patternsToWatch.add(pattern);
369
557
 
370
558
  return jsonResponse(
@@ -382,6 +570,15 @@ async function runGlobNew(req, patternsToWatch) {
382
570
  }
383
571
  }
384
572
 
573
+ async function runLogJob(req) {
574
+ try {
575
+ console.log(req.body.args[0].message);
576
+ return jsonResponse(req, null);
577
+ } catch (e) {
578
+ console.log(`Error performing env '${JSON.stringify(req.body)}'`);
579
+ throw e;
580
+ }
581
+ }
385
582
  async function runEnvJob(req, patternsToWatch) {
386
583
  try {
387
584
  const expectedEnv = req.body.args[0];
@@ -402,7 +599,7 @@ async function runEncryptJob(req, patternsToWatch) {
402
599
  );
403
600
  } catch (e) {
404
601
  throw {
405
- title: "DataSource Encrypt Error",
602
+ title: "BackendTask Encrypt Error",
406
603
  message:
407
604
  e.toString() + e.stack + "\n\n" + JSON.stringify(rawRequest, null, 2),
408
605
  };
@@ -419,32 +616,13 @@ async function runDecryptJob(req, patternsToWatch) {
419
616
  return jsonResponse(req, JSON.parse(signed || "null"));
420
617
  } catch (e) {
421
618
  throw {
422
- title: "DataSource Decrypt Error",
619
+ title: "BackendTask Decrypt Error",
423
620
  message:
424
621
  e.toString() + e.stack + "\n\n" + JSON.stringify(rawRequest, null, 2),
425
622
  };
426
623
  }
427
624
  }
428
625
 
429
- function flushIfDone(app) {
430
- if (foundErrors) {
431
- pendingDataSourceResponses = [];
432
- } else if (pendingDataSourceCount === 0) {
433
- // console.log(
434
- // `Flushing ${pendingDataSourceResponses.length} items in ${timeUntilThreshold}ms`
435
- // );
436
-
437
- flushQueue(app);
438
- }
439
- }
440
-
441
- function flushQueue(app) {
442
- const temp = pendingDataSourceResponses;
443
- pendingDataSourceResponses = [];
444
- // console.log("@@@ FLUSHING", temp.length);
445
- app.ports.gotBatchSub.send(temp);
446
- }
447
-
448
626
  /**
449
627
  * @param {{ ports: { fromJsPort: { send: (arg0: { tag: string; data: any; }) => void; }; }; }} app
450
628
  * @param {{ message: string; title: string; }} error