elm-pages 3.0.0-beta.21 → 3.0.0-beta.22

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.
@@ -12,7 +12,7 @@ import * as renderer from "./render.js";
12
12
  import { globbySync } from "globby";
13
13
  import * as esbuild from "esbuild";
14
14
  import { rewriteElmJson } from "./rewrite-elm-json.js";
15
- import { ensureDirSync, deleteIfExists } from "./file-helpers.js";
15
+ import { ensureDirSync } from "./file-helpers.js";
16
16
  import * as url from "url";
17
17
 
18
18
  import * as commander from "commander";
@@ -43,9 +43,6 @@ async function main() {
43
43
  )
44
44
  .description("run a full site build")
45
45
  .action(async (options) => {
46
- if (!options.keepCache) {
47
- clearHttpAndPortCache();
48
- }
49
46
  options.base = normalizeUrl(options.base);
50
47
  await build.run(options);
51
48
  });
@@ -76,9 +73,6 @@ async function main() {
76
73
  .option("--base <basePath>", "serve site under a base path", "/")
77
74
  .option("--https", "uses a https server")
78
75
  .action(async (options) => {
79
- if (!options.keepCache) {
80
- clearHttpAndPortCache();
81
- }
82
76
  options.base = normalizeUrl(options.base);
83
77
  await dev.start(options);
84
78
  });
@@ -334,25 +328,6 @@ function safeSubscribe(program, portName, subscribeFunction) {
334
328
  program.ports[portName].subscribe(subscribeFunction);
335
329
  }
336
330
 
337
- function clearHttpAndPortCache() {
338
- const directory = ".elm-pages/http-response-cache";
339
- if (fs.existsSync(directory)) {
340
- fs.readdir(directory, (err, files) => {
341
- if (err) {
342
- throw err;
343
- }
344
-
345
- for (const file of files) {
346
- fs.unlink(path.join(directory, file), (err) => {
347
- if (err) {
348
- throw err;
349
- }
350
- });
351
- }
352
- });
353
- }
354
- }
355
-
356
331
  /**
357
332
  * @param {string} rawPagePath
358
333
  */
@@ -1,3 +1,3 @@
1
1
  export const compatibilityKey = 7;
2
2
 
3
- export const packageVersion = "3.0.0-beta.21";
3
+ export const packageVersion = "3.0.0-beta.22";
@@ -136,9 +136,11 @@ function spawnElmMake(options, elmEntrypointPath, outputPath, cwd) {
136
136
  }
137
137
  );
138
138
  if (await fsHelpers.fileExists(outputPath)) {
139
- await fsPromises.unlink(outputPath, {
140
- force: true /* ignore errors if file doesn't exist */,
141
- });
139
+ try {
140
+ await fsPromises.unlink(outputPath, {
141
+ force: true /* ignore errors if file doesn't exist */,
142
+ });
143
+ } catch (e) {}
142
144
  }
143
145
  let commandOutput = "";
144
146
 
@@ -39,6 +39,40 @@ export async function start(options) {
39
39
  let threadReadyQueue = [];
40
40
  let pool = [];
41
41
 
42
+ function invalidatePool() {
43
+ pool.forEach((thread) => {
44
+ if (thread.used) {
45
+ thread.stale = true;
46
+ }
47
+ });
48
+ restartIdleWorkersIfStale();
49
+ }
50
+
51
+ function restartIdleWorkersIfStale() {
52
+ pool.forEach((thread) => {
53
+ if (thread.stale && thread.ready) {
54
+ reinitThread(thread);
55
+ }
56
+ });
57
+ }
58
+
59
+ function reinitThread(thisThread) {
60
+ thisThread.worker && thisThread.worker.terminate();
61
+ // TODO remove event listeners to avoid memory leak?
62
+ // thread.worker.removeAllListeners("message");
63
+ // thread.worker.removeAllListeners("error");
64
+ thisThread.ready = false;
65
+ thisThread.stale = false;
66
+ thisThread.used = false;
67
+ thisThread.worker = new Worker(path.join(__dirname, "./render-worker.js"), {
68
+ env: SHARE_ENV,
69
+ workerData: { basePath: options.base },
70
+ });
71
+ thisThread.worker.once("online", () => {
72
+ thisThread.ready = true;
73
+ });
74
+ }
75
+
42
76
  ensureDirSync(path.join(process.cwd(), ".elm-pages", "http-response-cache"));
43
77
  const cpuCount = os.cpus().length;
44
78
 
@@ -232,32 +266,13 @@ export async function start(options) {
232
266
  if (pathThatChanged === "elm.json") {
233
267
  watchElmSourceDirs(false);
234
268
  } else if (pathThatChanged.endsWith(".elm")) {
269
+ invalidatePool();
235
270
  if (elmMakeRunning) {
236
271
  } else {
237
272
  let codegenError = null;
238
273
  if (needToRerunCodegen(eventName, pathThatChanged)) {
239
274
  try {
240
275
  await codegen.generate(options.base);
241
- clientElmMakeProcess = compileElmForBrowser(options);
242
- pendingCliCompile = compileCliApp(
243
- options,
244
- ".elm-pages/Main.elm",
245
- path.join(process.cwd(), "elm-stuff/elm-pages/", "elm.js"),
246
- // "elm.js",
247
- "elm-stuff/elm-pages/",
248
- path.join("elm-stuff/elm-pages/", "elm.js")
249
- );
250
-
251
- Promise.all([clientElmMakeProcess, pendingCliCompile])
252
- .then(() => {
253
- elmMakeRunning = false;
254
- })
255
- .catch(() => {
256
- elmMakeRunning = false;
257
- });
258
- clients.forEach((client) => {
259
- client.response.write(`data: elm.js\n\n`);
260
- });
261
276
  } catch (error) {
262
277
  codegenError = error;
263
278
  }
@@ -275,10 +290,7 @@ export async function start(options) {
275
290
  pendingCliCompile = compileCliApp(
276
291
  options,
277
292
  ".elm-pages/Main.elm",
278
-
279
293
  path.join(process.cwd(), "elm-stuff/elm-pages/", "elm.js"),
280
-
281
- // "elm.js",
282
294
  "elm-stuff/elm-pages/",
283
295
  path.join("elm-stuff/elm-pages/", "elm.js")
284
296
  );
@@ -361,6 +373,8 @@ export async function start(options) {
361
373
  };
362
374
 
363
375
  readyThread.ready = false;
376
+ await pendingCliCompile;
377
+ readyThread.used = true;
364
378
  readyThread.worker.postMessage({
365
379
  mode: "dev-server",
366
380
  pathname,
@@ -607,6 +621,7 @@ export async function start(options) {
607
621
  }
608
622
 
609
623
  function runPendingWork() {
624
+ restartIdleWorkersIfStale();
610
625
  const readyThreads = pool.filter((thread) => thread.ready);
611
626
  readyThreads.forEach((readyThread) => {
612
627
  const startTask = threadReadyQueue.shift();
@@ -631,6 +646,7 @@ export async function start(options) {
631
646
  workerData: { basePath },
632
647
  }),
633
648
  ready: false,
649
+ used: false,
634
650
  };
635
651
  newWorker.worker.once("online", () => {
636
652
  newWorker.ready = true;
@@ -2,7 +2,6 @@ import * as renderer from "../../generator/src/render.js";
2
2
  import * as path from "node:path";
3
3
  import * as fs from "./dir-helpers.js";
4
4
  import { readFileSync, writeFileSync } from "node:fs";
5
- import { stat } from "fs/promises";
6
5
  import { parentPort, threadId, workerData } from "node:worker_threads";
7
6
  import * as url from "node:url";
8
7
 
@@ -48,13 +47,10 @@ async function requireElm(mode) {
48
47
  process.cwd(),
49
48
  "elm-stuff/elm-pages/elm.cjs"
50
49
  );
51
- let elmImportPath = compiledElmPath;
52
50
  let pathAsUrl = url.pathToFileURL(compiledElmPath);
53
- const changedTime = (await stat(compiledElmPath)).mtimeMs;
54
- pathAsUrl.searchParams.append("changed", `${changedTime}`);
55
51
  const warnOriginal = console.warn;
56
52
  console.warn = function () {};
57
- const Elm = (await import(elmImportPath)).default;
53
+ const Elm = (await import(pathAsUrl.toString())).default;
58
54
  console.warn = warnOriginal;
59
55
  return Elm;
60
56
  }
@@ -5,15 +5,69 @@ var eventSource = null;
5
5
  let updateAppContentJson = new Promise((resolve, reject) => resolve(() => {}));
6
6
 
7
7
  function connect(sendContentJsonPort, initialErrorPage) {
8
+ let reconnectFrequencySeconds = 1;
9
+ // reconnect logic based on: https://stackoverflow.com/a/61148682/383983
8
10
  // Listen for the server to tell us that an HMR update is available
9
- eventSource = new EventSource("/stream");
10
- window.reloadOnOk = initialErrorPage;
11
- if (initialErrorPage) {
12
- handleEvent(sendContentJsonPort, { data: "content.dat" });
11
+ function waitFunc() {
12
+ return reconnectFrequencySeconds * 1000;
13
13
  }
14
- eventSource.onmessage = async function (evt) {
15
- handleEvent(sendContentJsonPort, evt);
16
- };
14
+ function tryToSetupFunc() {
15
+ setupEventSource();
16
+ reconnectFrequencySeconds *= 2;
17
+ if (reconnectFrequencySeconds >= 8) {
18
+ reconnectFrequencySeconds = 8;
19
+ }
20
+ }
21
+ function reconnectFunc() {
22
+ console.log(
23
+ `Attempting dev server reconnect in ${reconnectFrequencySeconds}...`
24
+ );
25
+ setTimeout(tryToSetupFunc, waitFunc());
26
+ }
27
+ function setupEventSource() {
28
+ eventSource = new EventSource("/stream");
29
+ window.reloadOnOk = initialErrorPage;
30
+
31
+ try {
32
+ if (initialErrorPage) {
33
+ handleEvent(sendContentJsonPort, { data: "content.dat" });
34
+ }
35
+ } catch (e) {}
36
+ eventSource.onopen = async function () {
37
+ hideError();
38
+ reconnectFrequencySeconds = 1;
39
+ };
40
+ eventSource.onerror = async function (evt) {
41
+ eventSource && eventSource.close();
42
+ reconnectFunc();
43
+
44
+ showReconnectBanner();
45
+ };
46
+ eventSource.onmessage = async function (evt) {
47
+ handleEvent(sendContentJsonPort, evt);
48
+ };
49
+ }
50
+
51
+ setupEventSource();
52
+ }
53
+
54
+ function showReconnectBanner() {
55
+ showError({
56
+ type: "compile-errors",
57
+ errors: [
58
+ {
59
+ path: "",
60
+ name: "",
61
+ problems: [
62
+ {
63
+ title: "",
64
+ // region: "",
65
+ message: ["Dev server is disconnected..."],
66
+ },
67
+ ],
68
+ },
69
+ ],
70
+ });
17
71
  }
18
72
 
19
73
  async function handleEvent(sendContentJsonPort, evt) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "elm-pages",
3
3
  "type": "module",
4
- "version": "3.0.0-beta.21",
4
+ "version": "3.0.0-beta.22",
5
5
  "homepage": "https://elm-pages.com",
6
6
  "moduleResolution": "node",
7
7
  "description": "Type-safe static sites, written in pure elm with your own custom elm-markup syntax.",