diff --git a/client/css/style.css b/client/css/style.css index b478b93a..bf760016 100644 --- a/client/css/style.css +++ b/client/css/style.css @@ -1932,12 +1932,14 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */ content: "\f253"; /* https://fontawesome.com/icons/hourglass-end?style=solid */ } -#version-checker.new-version { +#version-checker.new-version, +#version-checker.new-packages { color: #8a6d3b; background-color: #fcf8e3; } -#version-checker.new-version::before { +#version-checker.new-version::before, +#version-checker.new-packages::before { content: "\f164"; /* https://fontawesome.com/icons/thumbs-up?style=solid */ } diff --git a/client/js/socket-events/changelog.js b/client/js/socket-events/changelog.js index cf48878c..f78053d1 100644 --- a/client/js/socket-events/changelog.js +++ b/client/js/socket-events/changelog.js @@ -29,6 +29,8 @@ socket.on("changelog", function(data) { if (data.latest) { status = "new-version"; + } else if (data.packages) { + status = "new-packages"; } else if (data.current.changelog) { status = "up-to-date"; } else { diff --git a/client/views/version_checker.tpl b/client/views/version_checker.tpl index 8b75d09f..fc1e8eee 100644 --- a/client/views/version_checker.tpl +++ b/client/views/version_checker.tpl @@ -12,6 +12,12 @@ Read more on GitHub
+{{else equal status "new-packages"}} +
+ The Lounge is up to date, but there are out of date packages
+
+ Run thelounge upgrade
on the server to upgrade packages.
+
The Lounge is up to date! diff --git a/src/command-line/index.js b/src/command-line/index.js index c8a835fd..d91abcc2 100644 --- a/src/command-line/index.js +++ b/src/command-line/index.js @@ -60,6 +60,7 @@ if (!Helper.config.public && !Helper.config.ldap.enable) { require("./install"); require("./uninstall"); require("./upgrade"); +require("./outdated"); // `parse` expects to be passed `process.argv`, but we need to remove to give it // a version of `argv` that does not contain options already parsed by diff --git a/src/command-line/outdated.js b/src/command-line/outdated.js new file mode 100644 index 00000000..72c561d4 --- /dev/null +++ b/src/command-line/outdated.js @@ -0,0 +1,27 @@ +"use strict"; + +const program = require("commander"); +const Utils = require("./utils"); +const packageManager = require("../plugins/packages"); +const log = require("../log"); + +program + .command("outdated") + .description("Check for any outdated packages") + .on("--help", Utils.extraHelp) + .action(async () => { + log.info("Checking for outdated packages"); + + await packageManager + .outdated(0) + .then((outdated) => { + if (outdated) { + log.info("There are outdated packages"); + } else { + log.info("No outdated packages"); + } + }) + .catch(() => { + log.error("Error finding outdated packages."); + }); + }); diff --git a/src/plugins/packages/index.js b/src/plugins/packages/index.js index 1c5b4f64..01d37436 100644 --- a/src/plugins/packages/index.js +++ b/src/plugins/packages/index.js @@ -7,13 +7,22 @@ const Helper = require("../../helper"); const themes = require("./themes"); const packageMap = new Map(); const inputs = require("../inputs"); +const fs = require("fs"); +const Utils = require("../../command-line/utils"); const stylesheets = []; +const TIME_TO_LIVE = 15 * 60 * 1000; // 15 minutes, in milliseconds + +const cache = { + outdated: undefined, +}; + module.exports = { getStylesheets, getPackage, loadPackages, + outdated, }; const packageApis = function(packageName) { @@ -99,3 +108,46 @@ function loadPackages() { ); } } + +async function outdated(cacheTimeout = TIME_TO_LIVE) { + if (cache.outdated !== undefined) { + return cache.outdated; + } + + // Get paths to the location of packages directory + const packagesPath = Helper.getPackagesPath(); + const packagesConfig = path.join(packagesPath, "package.json"); + const argsList = [ + "outdated", + "--latest", + "--json", + "--production", + "--ignore-scripts", + "--non-interactive", + "--cwd", + packagesPath, + ]; + + // Check if the configuration file exists + if (!fs.existsSync(packagesConfig)) { + log.warn("There are no packages installed."); + return false; + } + + // If we get an error from calling outdated and the code isn't 0, then there are no outdated packages + await Utils.executeYarnCommand(...argsList) + .then(() => updateOutdated(false)) + .catch((code) => updateOutdated(code !== 0)); + + if (cacheTimeout > 0) { + setTimeout(() => { + delete cache.outdated; + }, cacheTimeout); + } + + return cache.outdated; +} + +function updateOutdated(outdatedPackages) { + cache.outdated = outdatedPackages; +} diff --git a/src/server.js b/src/server.js index 9f436c62..498bf38c 100644 --- a/src/server.js +++ b/src/server.js @@ -454,9 +454,13 @@ function initializeClient(socket, client, token, lastMessage) { } }); - socket.on("changelog", async () => { - const data = await changelog.fetch(); - socket.emit("changelog", data); + socket.on("changelog", () => { + Promise.all([changelog.fetch(), packages.outdated()]).then( + ([changelogData, packageUpdate]) => { + changelogData.packages = packageUpdate; + socket.emit("changelog", changelogData); + } + ); }); socket.on("msg:preview:toggle", (data) => {