mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-27 03:39:55 +00:00
Cleanup more callback things (#3051)
Looks quite stable on my computers, so maybe we give it a try? --------- Co-authored-by: veeck <michael@veeck.de>
This commit is contained in:
parent
b5b61246e6
commit
1b2785cc56
@ -37,10 +37,7 @@ _This release is scheduled to be released on 2023-04-01._
|
||||
- Update dates in Calendar widgets every minute
|
||||
- Cleanup jest coverage for patches
|
||||
- Update `stylelint` dependencies, switch to `stylelint-config-standard` and handle `stylelint` issues
|
||||
- Convert load callbacks to async/await
|
||||
- Convert module start to async/await
|
||||
- Convert translator callbacks to async/await
|
||||
- Convert app-start/-stop callbacks to async/awaits
|
||||
- Convert lots of callbacks to async/await
|
||||
|
||||
### Fixed
|
||||
|
||||
|
89
js/app.js
89
js/app.js
@ -152,9 +152,8 @@ function App() {
|
||||
* Loads a specific module.
|
||||
*
|
||||
* @param {string} module The name of the module (including subpath).
|
||||
* @param {Function} callback Function to be called after loading
|
||||
*/
|
||||
function loadModule(module, callback) {
|
||||
function loadModule(module) {
|
||||
const elements = module.split("/");
|
||||
const moduleName = elements[elements.length - 1];
|
||||
let moduleFolder = `${__dirname}/../modules/${module}`;
|
||||
@ -199,39 +198,37 @@ function App() {
|
||||
m.setPath(path.resolve(moduleFolder));
|
||||
nodeHelpers.push(m);
|
||||
|
||||
m.loaded(callback);
|
||||
} else {
|
||||
callback();
|
||||
m.loaded();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all modules.
|
||||
*
|
||||
* @param {Module[]} modules All modules to be loaded
|
||||
* @param {Function} callback Function to be called after loading
|
||||
* @param {string[]} modules All modules to be loaded
|
||||
*/
|
||||
function loadModules(modules, callback) {
|
||||
Log.log("Loading module helpers ...");
|
||||
async function loadModules(modules) {
|
||||
return new Promise((resolve) => {
|
||||
Log.log("Loading module helpers ...");
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function loadNextModule() {
|
||||
if (modules.length > 0) {
|
||||
const nextModule = modules[0];
|
||||
loadModule(nextModule, function () {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function loadNextModule() {
|
||||
if (modules.length > 0) {
|
||||
const nextModule = modules[0];
|
||||
loadModule(nextModule);
|
||||
modules = modules.slice(1);
|
||||
loadNextModule();
|
||||
});
|
||||
} else {
|
||||
// All modules are loaded
|
||||
Log.log("All module helpers loaded.");
|
||||
callback();
|
||||
} else {
|
||||
// All modules are loaded
|
||||
Log.log("All module helpers loaded.");
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loadNextModule();
|
||||
loadNextModule();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -272,43 +269,41 @@ function App() {
|
||||
Log.setLogLevel(config.logLevel);
|
||||
|
||||
let modules = [];
|
||||
|
||||
for (const module of config.modules) {
|
||||
if (!modules.includes(module.module) && !module.disabled) {
|
||||
modules.push(module.module);
|
||||
}
|
||||
}
|
||||
await loadModules(modules);
|
||||
|
||||
loadModules(modules, async function () {
|
||||
httpServer = new Server(config);
|
||||
const { app, io } = await httpServer.open();
|
||||
Log.log("Server started ...");
|
||||
httpServer = new Server(config);
|
||||
const { app, io } = await httpServer.open();
|
||||
Log.log("Server started ...");
|
||||
|
||||
const nodePromises = [];
|
||||
for (let nodeHelper of nodeHelpers) {
|
||||
nodeHelper.setExpressApp(app);
|
||||
nodeHelper.setSocketIO(io);
|
||||
const nodePromises = [];
|
||||
for (let nodeHelper of nodeHelpers) {
|
||||
nodeHelper.setExpressApp(app);
|
||||
nodeHelper.setSocketIO(io);
|
||||
|
||||
try {
|
||||
nodePromises.push(nodeHelper.start());
|
||||
} catch (error) {
|
||||
Log.error(`Error when starting node_helper for module ${nodeHelper.name}:`);
|
||||
Log.error(error);
|
||||
}
|
||||
try {
|
||||
nodePromises.push(nodeHelper.start());
|
||||
} catch (error) {
|
||||
Log.error(`Error when starting node_helper for module ${nodeHelper.name}:`);
|
||||
Log.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
const results = await Promise.allSettled(nodePromises);
|
||||
const results = await Promise.allSettled(nodePromises);
|
||||
|
||||
// Log errors that happened during async node_helper startup
|
||||
results.forEach((result) => {
|
||||
if (result.status === "rejected") {
|
||||
Log.error(result.reason);
|
||||
}
|
||||
});
|
||||
|
||||
Log.log("Sockets connected & modules started ...");
|
||||
// Log errors that happened during async node_helper startup
|
||||
results.forEach((result) => {
|
||||
if (result.status === "rejected") {
|
||||
Log.error(result.reason);
|
||||
}
|
||||
});
|
||||
|
||||
Log.log("Sockets connected & modules started ...");
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
|
141
js/loader.js
141
js/loader.js
@ -16,37 +16,9 @@ const Loader = (function () {
|
||||
/* Private Methods */
|
||||
|
||||
/**
|
||||
* Loops thru all modules and requests load for every module.
|
||||
* Loops through all modules and requests start for every module.
|
||||
*/
|
||||
const loadModules = function () {
|
||||
let moduleData = getModuleData();
|
||||
|
||||
const loadNextModule = function () {
|
||||
if (moduleData.length > 0) {
|
||||
const nextModule = moduleData[0];
|
||||
loadModule(nextModule, function () {
|
||||
moduleData = moduleData.slice(1);
|
||||
loadNextModule();
|
||||
});
|
||||
} else {
|
||||
// All modules loaded. Load custom.css
|
||||
// This is done after all the modules so we can
|
||||
// overwrite all the defined styles.
|
||||
|
||||
loadFile(config.customCss).then(() => {
|
||||
// custom.css loaded. Start all modules.
|
||||
startModules();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
loadNextModule();
|
||||
};
|
||||
|
||||
/**
|
||||
* Loops thru all modules and requests start for every module.
|
||||
*/
|
||||
const startModules = function () {
|
||||
const startModules = async function () {
|
||||
const modulePromises = [];
|
||||
for (const module of moduleObjects) {
|
||||
try {
|
||||
@ -57,25 +29,25 @@ const Loader = (function () {
|
||||
}
|
||||
}
|
||||
|
||||
Promise.allSettled(modulePromises).then((results) => {
|
||||
// Log errors that happened during async node_helper startup
|
||||
results.forEach((result) => {
|
||||
if (result.status === "rejected") {
|
||||
Log.error(result.reason);
|
||||
}
|
||||
});
|
||||
const results = await Promise.allSettled(modulePromises);
|
||||
|
||||
// Notify core of loaded modules.
|
||||
MM.modulesStarted(moduleObjects);
|
||||
|
||||
// Starting modules also hides any modules that have requested to be initially hidden
|
||||
for (const thisModule of moduleObjects) {
|
||||
if (thisModule.data.hiddenOnStartup) {
|
||||
Log.info("Initially hiding " + thisModule.name);
|
||||
thisModule.hide();
|
||||
}
|
||||
// Log errors that happened during async node_helper startup
|
||||
results.forEach((result) => {
|
||||
if (result.status === "rejected") {
|
||||
Log.error(result.reason);
|
||||
}
|
||||
});
|
||||
|
||||
// Notify core of loaded modules.
|
||||
MM.modulesStarted(moduleObjects);
|
||||
|
||||
// Starting modules also hides any modules that have requested to be initially hidden
|
||||
for (const thisModule of moduleObjects) {
|
||||
if (thisModule.data.hiddenOnStartup) {
|
||||
Log.info("Initially hiding " + thisModule.name);
|
||||
thisModule.hide();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -130,32 +102,30 @@ const Loader = (function () {
|
||||
};
|
||||
|
||||
/**
|
||||
* Load modules via ajax request and create module objects.s
|
||||
* Load modules via ajax request and create module objects.
|
||||
*
|
||||
* @param {object} module Information about the module we want to load.
|
||||
* @param {Function} callback Function called when done.
|
||||
* @returns {Promise<void>} resolved when module is loaded
|
||||
*/
|
||||
const loadModule = function (module, callback) {
|
||||
const loadModule = async function (module) {
|
||||
const url = module.path + module.file;
|
||||
|
||||
const afterLoad = function () {
|
||||
/**
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const afterLoad = async function () {
|
||||
const moduleObject = Module.create(module.name);
|
||||
if (moduleObject) {
|
||||
bootstrapModule(module, moduleObject, function () {
|
||||
callback();
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
await bootstrapModule(module, moduleObject);
|
||||
}
|
||||
};
|
||||
|
||||
if (loadedModuleFiles.indexOf(url) !== -1) {
|
||||
afterLoad();
|
||||
await afterLoad();
|
||||
} else {
|
||||
loadFile(url).then(() => {
|
||||
loadedModuleFiles.push(url);
|
||||
afterLoad();
|
||||
});
|
||||
await loadFile(url);
|
||||
loadedModuleFiles.push(url);
|
||||
await afterLoad();
|
||||
}
|
||||
};
|
||||
|
||||
@ -164,24 +134,21 @@ const Loader = (function () {
|
||||
*
|
||||
* @param {object} module Information about the module we want to load.
|
||||
* @param {Module} mObj Modules instance.
|
||||
* @param {Function} callback Function called when done.
|
||||
*/
|
||||
const bootstrapModule = function (module, mObj, callback) {
|
||||
const bootstrapModule = async function (module, mObj) {
|
||||
Log.info("Bootstrapping module: " + module.name);
|
||||
|
||||
mObj.setData(module);
|
||||
|
||||
mObj.loadScripts().then(() => {
|
||||
Log.log("Scripts loaded for: " + module.name);
|
||||
mObj.loadStyles().then(() => {
|
||||
Log.log("Styles loaded for: " + module.name);
|
||||
mObj.loadTranslations().then(() => {
|
||||
Log.log("Translations loaded for: " + module.name);
|
||||
moduleObjects.push(mObj);
|
||||
callback();
|
||||
});
|
||||
});
|
||||
});
|
||||
await mObj.loadScripts();
|
||||
Log.log("Scripts loaded for: " + module.name);
|
||||
|
||||
await mObj.loadStyles();
|
||||
Log.log("Styles loaded for: " + module.name);
|
||||
|
||||
await mObj.loadTranslations();
|
||||
Log.log("Translations loaded for: " + module.name);
|
||||
|
||||
moduleObjects.push(mObj);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -235,8 +202,28 @@ const Loader = (function () {
|
||||
/**
|
||||
* Load all modules as defined in the config.
|
||||
*/
|
||||
loadModules: function () {
|
||||
loadModules();
|
||||
loadModules: async function () {
|
||||
let moduleData = getModuleData();
|
||||
|
||||
/**
|
||||
* @returns {Promise<void>} when all modules are loaded
|
||||
*/
|
||||
const loadNextModule = async function () {
|
||||
if (moduleData.length > 0) {
|
||||
const nextModule = moduleData[0];
|
||||
await loadModule(nextModule);
|
||||
moduleData = moduleData.slice(1);
|
||||
await loadNextModule();
|
||||
} else {
|
||||
// All modules loaded. Load custom.css
|
||||
// This is done after all the modules so we can
|
||||
// overwrite all the defined styles.
|
||||
await loadFile(config.customCss);
|
||||
// custom.css loaded. Start all modules.
|
||||
await startModules();
|
||||
}
|
||||
};
|
||||
await loadNextModule();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -250,7 +237,7 @@ const Loader = (function () {
|
||||
loadFileForModule: async function (fileName, module) {
|
||||
if (loadedFiles.indexOf(fileName.toLowerCase()) !== -1) {
|
||||
Log.log("File already loaded: " + fileName);
|
||||
return Promise.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileName.indexOf("http://") === 0 || fileName.indexOf("https://") === 0 || fileName.indexOf("/") !== -1) {
|
||||
|
@ -479,13 +479,14 @@ const MM = (function () {
|
||||
/**
|
||||
* Main init method.
|
||||
*/
|
||||
init: function () {
|
||||
init: async function () {
|
||||
Log.info("Initializing MagicMirror².");
|
||||
loadConfig();
|
||||
|
||||
Log.setLogLevel(config.logLevel);
|
||||
|
||||
Translator.loadCoreTranslations(config.language).then(() => Loader.loadModules());
|
||||
await Translator.loadCoreTranslations(config.language);
|
||||
await Loader.loadModules();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,7 @@ const Module = Class.extend({
|
||||
// visibility when hiding and showing module.
|
||||
lockStrings: [],
|
||||
|
||||
// Storage of the nunjuck Environment,
|
||||
// Storage of the nunjucks Environment,
|
||||
// This should not be referenced directly.
|
||||
// Use the nunjucksEnvironment() to get it.
|
||||
_nunjucksEnvironment: null,
|
||||
@ -302,7 +302,7 @@ const Module = Class.extend({
|
||||
/**
|
||||
* Load all translations.
|
||||
*/
|
||||
async loadTranslations() {
|
||||
loadTranslations: async function () {
|
||||
const translations = this.getTranslations() || {};
|
||||
const language = config.language.toLowerCase();
|
||||
|
||||
|
@ -13,9 +13,8 @@ const NodeHelper = Class.extend({
|
||||
Log.log("Initializing new module helper ...");
|
||||
},
|
||||
|
||||
loaded(callback) {
|
||||
loaded() {
|
||||
Log.log(`Module helper loaded: ${this.name}`);
|
||||
callback();
|
||||
},
|
||||
|
||||
start() {
|
||||
|
@ -9,6 +9,9 @@ const path = require("path");
|
||||
const ipfilter = require("express-ipfilter").IpFilter;
|
||||
const fs = require("fs");
|
||||
const helmet = require("helmet");
|
||||
const socketio = require("socket.io");
|
||||
const http = require("http");
|
||||
const https = require("https");
|
||||
|
||||
const Log = require("logger");
|
||||
const Utils = require("./utils.js");
|
||||
@ -38,11 +41,11 @@ function Server(config) {
|
||||
key: fs.readFileSync(config.httpsPrivateKey),
|
||||
cert: fs.readFileSync(config.httpsCertificate)
|
||||
};
|
||||
server = require("https").Server(options, app);
|
||||
server = https.Server(options, app);
|
||||
} else {
|
||||
server = require("http").Server(app);
|
||||
server = http.Server(app);
|
||||
}
|
||||
const io = require("socket.io")(server, {
|
||||
const io = socketio(server, {
|
||||
cors: {
|
||||
origin: /.*$/,
|
||||
credentials: true
|
||||
|
2191
package-lock.json
generated
2191
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@ -51,31 +51,31 @@
|
||||
"devDependencies": {
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-jest": "^27.2.1",
|
||||
"eslint-plugin-jsdoc": "^39.8.0",
|
||||
"eslint-plugin-jsdoc": "^40.0.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"husky": "^8.0.3",
|
||||
"jest": "^29.4.2",
|
||||
"jest": "^29.4.3",
|
||||
"jsdom": "^21.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"playwright": "^1.30.0",
|
||||
"playwright": "^1.31.1",
|
||||
"prettier": "^2.8.4",
|
||||
"pretty-quick": "^3.1.3",
|
||||
"sinon": "^15.0.1",
|
||||
"stylelint": "^15.1.0",
|
||||
"stylelint": "^15.2.0",
|
||||
"stylelint-config-standard": "^30.0.1",
|
||||
"stylelint-prettier": "^2.0.0",
|
||||
"stylelint-prettier": "^3.0.0",
|
||||
"suncalc": "^1.9.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"electron": "^22.2.0"
|
||||
"electron": "^22.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"colors": "^1.4.0",
|
||||
"console-stamp": "^3.1.0",
|
||||
"console-stamp": "^3.1.1",
|
||||
"digest-fetch": "^2.0.1",
|
||||
"envsub": "^4.1.0",
|
||||
"eslint": "^8.33.0",
|
||||
"eslint": "^8.35.0",
|
||||
"express": "^4.18.2",
|
||||
"express-ipfilter": "^1.3.1",
|
||||
"feedme": "^2.0.2",
|
||||
@ -86,7 +86,7 @@
|
||||
"moment": "^2.29.4",
|
||||
"node-fetch": "^2.6.9",
|
||||
"node-ical": "^0.15.3",
|
||||
"socket.io": "^4.6.0"
|
||||
"socket.io": "^4.6.1"
|
||||
},
|
||||
"_moduleAliases": {
|
||||
"node_helper": "js/node_helper.js",
|
||||
|
@ -13,7 +13,7 @@ describe("Electron app environment", () => {
|
||||
it("should open browserwindow", async () => {
|
||||
const module = await helpers.getElement("#module_0_helloworld");
|
||||
expect(await module.textContent()).toContain("Test Display Header");
|
||||
expect(await global.electronApp.windows().length).toBe(1);
|
||||
expect(global.electronApp.windows().length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
|
18
vendor/package-lock.json
generated
vendored
18
vendor/package-lock.json
generated
vendored
@ -9,7 +9,7 @@
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.3.0",
|
||||
"moment": "^2.29.4",
|
||||
"moment-timezone": "^0.5.40",
|
||||
"moment-timezone": "^0.5.41",
|
||||
"nunjucks": "^3.2.3",
|
||||
"suncalc": "^1.9.0",
|
||||
"weathericons": "^2.1.0"
|
||||
@ -51,11 +51,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/moment-timezone": {
|
||||
"version": "0.5.40",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.40.tgz",
|
||||
"integrity": "sha512-tWfmNkRYmBkPJz5mr9GVDn9vRlVZOTe6yqY92rFxiOdWXbjaR0+9LwQnZGGuNR63X456NqmEkbskte8tWL5ePg==",
|
||||
"version": "0.5.41",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.41.tgz",
|
||||
"integrity": "sha512-e0jGNZDOHfBXJGz8vR/sIMXvBIGJJcqFjmlg9lmE+5KX1U7/RZNMswfD8nKnNCnQdKTIj50IaRKwl1fvMLyyRg==",
|
||||
"dependencies": {
|
||||
"moment": ">= 2.9.0"
|
||||
"moment": "^2.29.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
@ -123,11 +123,11 @@
|
||||
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
|
||||
},
|
||||
"moment-timezone": {
|
||||
"version": "0.5.40",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.40.tgz",
|
||||
"integrity": "sha512-tWfmNkRYmBkPJz5mr9GVDn9vRlVZOTe6yqY92rFxiOdWXbjaR0+9LwQnZGGuNR63X456NqmEkbskte8tWL5ePg==",
|
||||
"version": "0.5.41",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.41.tgz",
|
||||
"integrity": "sha512-e0jGNZDOHfBXJGz8vR/sIMXvBIGJJcqFjmlg9lmE+5KX1U7/RZNMswfD8nKnNCnQdKTIj50IaRKwl1fvMLyyRg==",
|
||||
"requires": {
|
||||
"moment": ">= 2.9.0"
|
||||
"moment": "^2.29.4"
|
||||
}
|
||||
},
|
||||
"nunjucks": {
|
||||
|
2
vendor/package.json
vendored
2
vendor/package.json
vendored
@ -12,7 +12,7 @@
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.3.0",
|
||||
"moment": "^2.29.4",
|
||||
"moment-timezone": "^0.5.40",
|
||||
"moment-timezone": "^0.5.41",
|
||||
"nunjucks": "^3.2.3",
|
||||
"suncalc": "^1.9.0",
|
||||
"weathericons": "^2.1.0"
|
||||
|
Loading…
x
Reference in New Issue
Block a user