diff --git a/eslint.config.mjs b/eslint.config.mjs index 446af56f80..095608a25c 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -32,7 +32,7 @@ export default defineConfig([ } }, { - files: ["**/*.js", "js/app.mjs", "js/ip_access_control.mjs"], + files: ["**/*.js", "js/app.mjs", "js/ip_access_control.mjs", "js/server.mjs", "js/vendor.mjs"], languageOptions: { ecmaVersion: "latest", globals: { @@ -104,7 +104,7 @@ export default defineConfig([ } }, { - files: ["**/*.js", "js/app.mjs", "js/ip_access_control.mjs"], + files: ["**/*.js", "js/app.mjs", "js/ip_access_control.mjs", "js/server.mjs", "js/vendor.mjs"], ignores: [ "clientonly/index.js", "js/logger.js", @@ -118,7 +118,7 @@ export default defineConfig([ }, { files: ["**/*.mjs"], - ignores: ["js/app.mjs", "js/ip_access_control.mjs"], + ignores: ["js/app.mjs", "js/ip_access_control.mjs", "js/server.mjs", "js/vendor.mjs"], languageOptions: { ecmaVersion: "latest", globals: { diff --git a/js/app.mjs b/js/app.mjs index 355b767c42..730a8771a3 100644 --- a/js/app.mjs +++ b/js/app.mjs @@ -7,7 +7,7 @@ import { spawn } from "node:child_process"; import { Agent, setGlobalDispatcher } from "undici"; import packageJson from "../package.json" with { type: "json" }; import Log from "./logger.js"; -import Server from "./server.js"; +import Server from "./server.mjs"; import Utils from "./utils.js"; import serverFunctions from "#server_functions"; diff --git a/js/loader.js b/js/loader.js index 35c430196a..2d46a68a9a 100644 --- a/js/loader.js +++ b/js/loader.js @@ -1,5 +1,5 @@ import "../defaultmodules/defaultmodules.js"; -import "./vendor.js"; +import "./vendor.mjs"; /* Module state */ @@ -274,7 +274,7 @@ export const loadModules = async () => { /** * Load a file (script or stylesheet). - * Prevent double loading and search for files defined in js/vendor.js. + * Prevent double loading and search for files defined in js/vendor.mjs. * @param {string} fileName Path of the file we want to load. * @param {Module} module The module that calls the loadFile function. * @returns {Promise} resolved when the file is loaded @@ -293,7 +293,7 @@ export const loadFileForModule = (fileName, module) => { } if (globalThis.vendor[fileName] !== undefined) { - // This file is defined in js/vendor.js. + // This file is defined in js/vendor.mjs. // Load it from its location. loadedFiles.push(fileName.toLowerCase()); return loadFile(`${globalThis.vendor[fileName]}`); diff --git a/js/server.js b/js/server.mjs similarity index 91% rename from js/server.js rename to js/server.mjs index 38b0c83e08..b5b4a47f27 100644 --- a/js/server.js +++ b/js/server.mjs @@ -1,17 +1,16 @@ -const fs = require("node:fs"); -const http = require("node:http"); -const https = require("node:https"); -const path = require("node:path"); -const express = require("express"); -const helmet = require("helmet"); -const socketio = require("socket.io"); -const Log = require("logger"); - -const { ipAccessControl, socketIpAccessControl } = require("./ip_access_control.mjs"); - -const vendor = require("./vendor"); - -const { getHtml, getVersion, getEnvVars, getServerPort, cors } = require("#server_functions"); +import fs from "node:fs"; +import http from "node:http"; +import https from "node:https"; +import path from "node:path"; +import express from "express"; +import helmet from "helmet"; +import { Server as SocketServer } from "socket.io"; +import Log from "./logger.js"; +import { ipAccessControl, socketIpAccessControl } from "./ip_access_control.mjs"; +import vendor from "./vendor.mjs"; +import serverFunctions from "#server_functions"; + +const { getHtml, getVersion, getEnvVars, getServerPort, cors } = serverFunctions; /** * Server @@ -60,7 +59,7 @@ class Server { } else { this.#server = http.Server(app); } - const io = socketio(this.#server, { + const io = new SocketServer(this.#server, { allowRequest: socketIpAccessControl(config.ipWhitelist, config.trustedProxies), allowEIO3: true, pingInterval: 120000, // server → client ping every 2 mins @@ -106,7 +105,7 @@ class Server { app.use(ipAccessControl(config.ipWhitelist, config.trustedProxies)); app.use(helmet(config.httpHeaders)); - app.use("/js", express.static(__dirname)); + app.use("/js", express.static(import.meta.dirname)); const getConfigFileError = (filename) => (req, res) => { const errorText = `\n\n
\n\nCannot GET /config/${filename}\n\n`;
@@ -198,4 +197,4 @@ class Server {
}
}
-module.exports = Server;
+export default Server;
diff --git a/js/vendor.js b/js/vendor.mjs
similarity index 89%
rename from js/vendor.js
rename to js/vendor.mjs
index 0565df19b3..bcb1d68e94 100644
--- a/js/vendor.js
+++ b/js/vendor.mjs
@@ -11,6 +11,4 @@ const vendor = {
globalThis.vendor = vendor;
-if (typeof module !== "undefined") {
- module.exports = vendor;
-}
+export default vendor;
diff --git a/tests/e2e/helpers/global-setup.js b/tests/e2e/helpers/global-setup.js
index 8c2d4c158c..ce921de3e8 100644
--- a/tests/e2e/helpers/global-setup.js
+++ b/tests/e2e/helpers/global-setup.js
@@ -91,12 +91,11 @@ exports.getPage = () => {
exports.startApplication = async (configFilename) => {
vi.resetModules();
- // Clear CommonJS config and server caches; the ESM app is reused across starts.
+ // Clear CommonJS config caches; the ESM app is reused across starts.
Object.keys(require.cache).forEach((key) => {
if (
key.includes("/tests/configs/")
|| key.includes("/config/config")
- || key.includes("/js/server.js")
) {
delete require.cache[key];
}
diff --git a/tests/e2e/helpers/global-setup.mjs b/tests/e2e/helpers/global-setup.mjs
new file mode 100644
index 0000000000..c6f418ff99
--- /dev/null
+++ b/tests/e2e/helpers/global-setup.mjs
@@ -0,0 +1,6 @@
+import {createRequire} from "node:module";
+
+// Load natively: when Vitest evaluates global-setup.js itself, app.mjs would run inside Vite's module loader.
+const helpers = createRequire(import.meta.url)("./global-setup.js");
+
+export const {getPage, startApplication, stopApplication, getDocument, fixupIndex, restoreIndex} = helpers;
diff --git a/tests/e2e/vendor_spec.js b/tests/e2e/vendor_spec.js
index aca6f3f296..0c63b77f8a 100644
--- a/tests/e2e/vendor_spec.js
+++ b/tests/e2e/vendor_spec.js
@@ -1,17 +1,16 @@
-const helpers = require("./helpers/global-setup");
+import vendors from "../../js/vendor.mjs";
+import { startApplication, stopApplication } from "./helpers/global-setup.mjs";
describe("Vendors", () => {
beforeAll(async () => {
- await helpers.startApplication("tests/configs/default.js");
+ await startApplication("tests/configs/default.js");
});
afterAll(async () => {
- await helpers.stopApplication();
+ await stopApplication();
});
describe("Get list vendors", () => {
- const vendors = require(`${global.root_path}/js/vendor.js`);
-
Object.keys(vendors).forEach((vendor) => {
it(`should return 200 HTTP code for vendor "${vendor}"`, async () => {
const urlVendor = `http://localhost:8080/${vendors[vendor]}`;