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.
package/generator/src/cli.js
CHANGED
|
@@ -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
|
|
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
|
*/
|
|
@@ -136,9 +136,11 @@ function spawnElmMake(options, elmEntrypointPath, outputPath, cwd) {
|
|
|
136
136
|
}
|
|
137
137
|
);
|
|
138
138
|
if (await fsHelpers.fileExists(outputPath)) {
|
|
139
|
-
|
|
140
|
-
|
|
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(
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
if (initialErrorPage) {
|
|
12
|
-
handleEvent(sendContentJsonPort, { data: "content.dat" });
|
|
11
|
+
function waitFunc() {
|
|
12
|
+
return reconnectFrequencySeconds * 1000;
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
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.
|
|
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.",
|