refactor: replace module-alias dependency with internal alias resolver (#3893)

- 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! 🙇 😃
This commit is contained in:
Kristjan ESPERANTO
2025-09-30 20:12:58 +02:00
committed by GitHub
parent b1a189b238
commit 787cc6bd1f
9 changed files with 49 additions and 24 deletions

View File

@@ -15,6 +15,8 @@ planned for 2026-01-01
### Changed
- [core] refactor: replace `module-alias` dependency with internal alias resolver (#3893)
### Fixed
### Updated

View File

@@ -1,3 +1,7 @@
const aliasMapper = {
logger: "<rootDir>/js/logger.js"
};
const config = {
verbose: true,
testTimeout: 20000,
@@ -6,21 +10,21 @@ const config = {
{
displayName: "unit",
globalSetup: "<rootDir>/tests/unit/helpers/global-setup.js",
moduleNameMapper: {
logger: "<rootDir>/js/logger.js"
},
moduleNameMapper: aliasMapper,
testMatch: ["**/tests/unit/**/*.[jt]s?(x)"],
testPathIgnorePatterns: ["<rootDir>/tests/unit/mocks", "<rootDir>/tests/unit/helpers"]
},
{
displayName: "electron",
testMatch: ["**/tests/electron/**/*.[jt]s?(x)"],
moduleNameMapper: aliasMapper,
testPathIgnorePatterns: ["<rootDir>/tests/electron/helpers"]
},
{
displayName: "e2e",
testMatch: ["**/tests/e2e/**/*.[jt]s?(x)"],
modulePaths: ["<rootDir>/js/"],
moduleNameMapper: aliasMapper,
testPathIgnorePatterns: ["<rootDir>/tests/e2e/helpers", "<rootDir>/tests/e2e/mocks"]
}
],

31
js/alias-resolver.js Normal file
View File

@@ -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
}

View File

@@ -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");

View File

@@ -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" });

View File

@@ -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;

View File

@@ -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");

7
package-lock.json generated
View File

@@ -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",

View File

@@ -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"
}
}