chore: update min supported node version to >=18 (#19)

Update required minimum node version to >=18 in preparation for updating other dependencies that require newer node versions.
This commit is contained in:
M. George Hansen 2024-07-15 00:01:14 -07:00
parent a13295b223
commit 999b9b54a2
Signed by: mgeorgehansen
SSH key fingerprint: SHA256:JlIGiQLPyQ2RHTH3a2oVlb20Xkh9Glr8DUF4YTXHJxM
9 changed files with 2712 additions and 1745 deletions

2
.nvmrc
View file

@ -1 +1 @@
lts/erbium 18

View file

@ -8,5 +8,4 @@ os:
node_js: node_js:
- node - node
- lts/* - lts/*
- 12 - 18
- 10

File diff suppressed because it is too large Load diff

1816
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,7 @@
"license": "MPL-2.0", "license": "MPL-2.0",
"repository": "github:websnacksjs/websnacks", "repository": "github:websnacksjs/websnacks",
"engines": { "engines": {
"node": ">=10" "node": ">=18"
}, },
"main": "dist/index.js", "main": "dist/index.js",
"types": "types.d.ts", "types": "types.d.ts",
@ -35,7 +35,7 @@
"test:e2e": "cd test && ts-node --script-mode ./run-e2e.ts" "test:e2e": "cd test && ts-node --script-mode ./run-e2e.ts"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "~10", "@types/node": "~18",
"@types/ws": "^7.4.0", "@types/ws": "^7.4.0",
"@typescript-eslint/eslint-plugin": "^4.15.2", "@typescript-eslint/eslint-plugin": "^4.15.2",
"@typescript-eslint/parser": "^4.15.2", "@typescript-eslint/parser": "^4.15.2",
@ -44,8 +44,8 @@
"eslint-plugin-prettier": "^3.3.1", "eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react": "^7.22.0", "eslint-plugin-react": "^7.22.0",
"prettier": "=2.2.1", "prettier": "=2.2.1",
"ts-node": "^9.1.1", "ts-node": "^10.9.2",
"typescript": "~4.2.2" "typescript": "~4.9.5"
}, },
"optionalDependencies": { "optionalDependencies": {
"node-watch": "^0.7.1", "node-watch": "^0.7.1",

View file

@ -34,9 +34,7 @@ const renderPagesToHtml = async ({
try { try {
compiledHtml = renderPage(pageSrc.page()); compiledHtml = renderPage(pageSrc.page());
} catch (error) { } catch (error) {
throw new Error( throw new Error(`failed to compile ${srcPath}: ${error}`);
`failed to compile ${srcPath}: ${error.stack ?? error}`,
);
} }
const relPath = path.relative(pagesDir, path.dirname(srcPath)); const relPath = path.relative(pagesDir, path.dirname(srcPath));
let baseName = path.basename(srcPath, ".tsx"); let baseName = path.basename(srcPath, ".tsx");

View file

@ -5,11 +5,11 @@
import { existsSync, promises as fs, watch } from "fs"; import { existsSync, promises as fs, watch } from "fs";
import * as http from "http"; import * as http from "http";
import * as net from "net";
import * as path from "path"; import * as path from "path";
import { renderSite } from "../../build"; import { renderSite } from "../../build";
import { Config, loadConfig } from "../../config"; import { Config, loadConfig } from "../../config";
import { isErrnoException } from "../../utils/error";
import { Command, UsageError } from "../types"; import { Command, UsageError } from "../types";
const DEFAULT_SERVER_PORT = 8080; const DEFAULT_SERVER_PORT = 8080;
@ -119,14 +119,16 @@ const guessMimeType = (ext: string): string => {
return mimeType; return mimeType;
}; };
const portFromServer = (server: Pick<net.Server, "address">): number => { const portFromServer = (
const addrInfo = server.address(); addrInfo: { port: number } | object | string | undefined | null,
if (addrInfo == null) { ): number => {
throw new Error(`server address is null (this should never happen!)`); if (
} typeof addrInfo !== "object" ||
if (typeof addrInfo === "string") { addrInfo == null ||
!("port" in addrInfo)
) {
throw new Error( throw new Error(
`server address is a string (this should never happen!)`, "server address does not have a valid port (this should never happen!)",
); );
} }
return addrInfo.port; return addrInfo.port;
@ -158,7 +160,7 @@ const startHttpServer = async (publicDir: string): Promise<http.Server> => {
} }
const mimeType = guessMimeType(reqExt); const mimeType = guessMimeType(reqExt);
if (mimeType === "text/html") { if (mimeType === "text/html") {
const port = portFromServer(req.socket); const port = portFromServer(req.socket.address());
contents = injectLiveReloadScript(contents.toString("utf8"), port); contents = injectLiveReloadScript(contents.toString("utf8"), port);
} }
res.writeHead(200, { res.writeHead(200, {
@ -176,12 +178,16 @@ const startHttpServer = async (publicDir: string): Promise<http.Server> => {
try { try {
await listen(DEFAULT_SERVER_PORT); await listen(DEFAULT_SERVER_PORT);
} catch (error) { } catch (error) {
if (error.code !== "EADDRINUSE") { if (
error instanceof Error &&
isErrnoException(error) &&
error.code !== "EADDRINUSE"
) {
throw error; throw error;
} }
await listen(); await listen();
} }
const port = portFromServer(httpServer); const port = portFromServer(httpServer.address());
console.log(`Listening at http://127.0.0.1:${port}`); console.log(`Listening at http://127.0.0.1:${port}`);
return httpServer; return httpServer;
}; };
@ -194,7 +200,11 @@ const startWebSocketServer = async (
try { try {
ws = await import("ws"); ws = await import("ws");
} catch (error) { } catch (error) {
if (error.code !== "MODULE_NOT_FOUND") { if (
error instanceof Error &&
isErrnoException(error) &&
error.code !== "MODULE_NOT_FOUND"
) {
throw error; throw error;
} }
console.warn(`'ws' module not found, live-reloading will be disabled`); console.warn(`'ws' module not found, live-reloading will be disabled`);
@ -218,7 +228,11 @@ const watchFolders = async (
nodeWatch.default(folders, { recursive: true }, listener); nodeWatch.default(folders, { recursive: true }, listener);
return; return;
} catch (error) { } catch (error) {
if (error.code !== "MODULE_NOT_FOUND") { if (
error instanceof Error &&
isErrnoException(error) &&
error.code !== "MODULE_NOT_FOUND"
) {
throw error; throw error;
} }
console.warn( console.warn(
@ -230,7 +244,7 @@ const watchFolders = async (
// triggering duplicate file events on some systems. // triggering duplicate file events on some systems.
for (const folder of folders) { for (const folder of folders) {
watch(folder, { recursive: true }, (_, fileName) => { watch(folder, { recursive: true }, (_, fileName) => {
listener("update", fileName); listener("update", fileName || undefined);
}); });
} }
}; };

View file

@ -3,11 +3,17 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
import { isErrnoException } from "./error";
const resolveModulePath = (importPath: string): string | undefined => { const resolveModulePath = (importPath: string): string | undefined => {
try { try {
return require.resolve(importPath); return require.resolve(importPath);
} catch (error) { } catch (error) {
if (error.code === "MODULE_NOT_FOUND") { if (
error instanceof Error &&
isErrnoException(error) &&
error.code === "MODULE_NOT_FOUND"
) {
return; return;
} }
throw error; throw error;

3
src/utils/error.ts Normal file
View file

@ -0,0 +1,3 @@
export const isErrnoException = (
error: Error,
): error is NodeJS.ErrnoException => "code" in error;