From 787cc6bd1fb3b155d5bb91b3cc7ff11f258fde6e Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 30 Sep 2025 20:12:58 +0200 Subject: [PATCH] refactor: replace `module-alias` dependency with internal alias resolver (#3893) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - removes the external unmaintained `module-alias` dependency -> reducing complexity and risk - introduces a small internal alias mechanism for `logger` and `node_helper` - preserves backward compatibility for existing 3rd‑party modules - should simplify a future ESM migration of MagicMirror I'm confident that it shouldn't cause any problems, but we could also consider including it in the release after next. What do you think? This PR is inspired by PR #2934 - so thanks to @thesebas! :bow: :smiley: --- CHANGELOG.md | 2 ++ jest.config.js | 10 +++++++--- js/alias-resolver.js | 31 +++++++++++++++++++++++++++++++ js/app.js | 4 ++-- js/check_config.js | 5 ++++- js/utils.js | 5 +---- modules/default/calendar/debug.js | 4 ++-- package-lock.json | 7 ------- package.json | 5 ----- 9 files changed, 49 insertions(+), 24 deletions(-) create mode 100644 js/alias-resolver.js diff --git a/CHANGELOG.md b/CHANGELOG.md index a6d9fef7..1164cb1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ planned for 2026-01-01 ### Changed +- [core] refactor: replace `module-alias` dependency with internal alias resolver (#3893) + ### Fixed ### Updated diff --git a/jest.config.js b/jest.config.js index cc65330f..ee51664f 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,3 +1,7 @@ +const aliasMapper = { + logger: "/js/logger.js" +}; + const config = { verbose: true, testTimeout: 20000, @@ -6,21 +10,21 @@ const config = { { displayName: "unit", globalSetup: "/tests/unit/helpers/global-setup.js", - moduleNameMapper: { - logger: "/js/logger.js" - }, + moduleNameMapper: aliasMapper, testMatch: ["**/tests/unit/**/*.[jt]s?(x)"], testPathIgnorePatterns: ["/tests/unit/mocks", "/tests/unit/helpers"] }, { displayName: "electron", testMatch: ["**/tests/electron/**/*.[jt]s?(x)"], + moduleNameMapper: aliasMapper, testPathIgnorePatterns: ["/tests/electron/helpers"] }, { displayName: "e2e", testMatch: ["**/tests/e2e/**/*.[jt]s?(x)"], modulePaths: ["/js/"], + moduleNameMapper: aliasMapper, testPathIgnorePatterns: ["/tests/e2e/helpers", "/tests/e2e/mocks"] } ], diff --git a/js/alias-resolver.js b/js/alias-resolver.js new file mode 100644 index 00000000..9af170a2 --- /dev/null +++ b/js/alias-resolver.js @@ -0,0 +1,31 @@ +// Internal alias mapping for default and 3rd party modules. +// Provides short require identifiers: "logger" and "node_helper". +// For a future ESM migration, replace this with a public export/import surface. + +const path = require("node:path"); +const Module = require("module"); + +const root = path.join(__dirname, ".."); + +// Keep this list minimal; do not add new aliases without architectural review. +const ALIASES = { + logger: "js/logger.js", + node_helper: "js/node_helper.js" +}; + +// Resolve to absolute paths now. +const resolved = Object.fromEntries( + Object.entries(ALIASES).map(([k, rel]) => [k, path.join(root, rel)]) +); + +// Prevent multiple patching if this file is required more than once. +if (!Module._mmAliasPatched) { + const origResolveFilename = Module._resolveFilename; + Module._resolveFilename = function (request, parent, isMain, options) { + if (Object.prototype.hasOwnProperty.call(resolved, request)) { + return resolved[request]; + } + return origResolveFilename.call(this, request, parent, isMain, options); + }; + Module._mmAliasPatched = true; // non-enumerable marker would be overkill here +} diff --git a/js/app.js b/js/app.js index c0677c71..5e5d3aee 100644 --- a/js/app.js +++ b/js/app.js @@ -1,5 +1,5 @@ -// Alias modules mentioned in package.js under _moduleAliases. -require("module-alias/register"); +// Load lightweight internal alias resolver +require("./alias-resolver"); const fs = require("node:fs"); const path = require("node:path"); diff --git a/js/check_config.js b/js/check_config.js index 628c3747..14fda3c5 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -1,12 +1,15 @@ +// Ensure internal require aliases (e.g., "logger") resolve when this file is run as a standalone script +require("./alias-resolver"); + const path = require("node:path"); const fs = require("node:fs"); const { styleText } = require("node:util"); const Ajv = require("ajv"); const globals = require("globals"); const { Linter } = require("eslint"); +const Log = require("logger"); const rootPath = path.resolve(`${__dirname}/../`); -const Log = require(`${rootPath}/js/logger.js`); const Utils = require(`${rootPath}/js/utils.js`); const linter = new Linter({ configType: "flat" }); diff --git a/js/utils.js b/js/utils.js index d20d6cf6..24705e05 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,10 +1,7 @@ -const path = require("node:path"); - -const rootPath = path.resolve(`${__dirname}/../`); -const Log = require(`${rootPath}/js/logger.js`); const os = require("node:os"); const fs = require("node:fs"); const si = require("systeminformation"); +const Log = require("logger"); const modulePositions = []; // will get list from index.html const regionRegEx = /"region ([^"]*)/i; diff --git a/modules/default/calendar/debug.js b/modules/default/calendar/debug.js index 3acfc311..92b15062 100644 --- a/modules/default/calendar/debug.js +++ b/modules/default/calendar/debug.js @@ -3,8 +3,8 @@ * use this script with `node debug.js` to test the fetcher without the need * of starting the MagicMirror² core. Adjust the values below to your desire. */ -// Alias modules mentioned in package.js under _moduleAliases. -require("module-alias/register"); +// Load internal alias resolver +require("../../../js/alias-resolver"); const Log = require("logger"); const CalendarFetcher = require("./calendarfetcher"); diff --git a/package-lock.json b/package-lock.json index c1ab0062..9a303b09 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,6 @@ "helmet": "^8.1.0", "html-to-text": "^9.0.5", "iconv-lite": "^0.7.0", - "module-alias": "^2.2.3", "moment": "^2.30.1", "moment-timezone": "^0.6.0", "node-ical": "^0.21.0", @@ -10448,12 +10447,6 @@ "node": ">=10" } }, - "node_modules/module-alias": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.3.tgz", - "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==", - "license": "MIT" - }, "node_modules/module-details-from-path": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", diff --git a/package.json b/package.json index 704767f3..125975b9 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,6 @@ "helmet": "^8.1.0", "html-to-text": "^9.0.5", "iconv-lite": "^0.7.0", - "module-alias": "^2.2.3", "moment": "^2.30.1", "moment-timezone": "^0.6.0", "node-ical": "^0.21.0", @@ -121,9 +120,5 @@ }, "engines": { "node": ">=22.18.0" - }, - "_moduleAliases": { - "node_helper": "js/node_helper.js", - "logger": "js/logger.js" } }