From 147016278a5b411eea49d4b84461b4c96cefe1d2 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Mon, 4 Mar 2024 21:29:53 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Auto-rebuild=20script=20done,=20wit?= =?UTF-8?q?h=20debounce=20and=20term=20logging?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- services/watch-for-changes.js | 90 +++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 20 deletions(-) diff --git a/services/watch-for-changes.js b/services/watch-for-changes.js index 51b2c8f9..a66000b2 100644 --- a/services/watch-for-changes.js +++ b/services/watch-for-changes.js @@ -1,28 +1,78 @@ const fs = require('fs'); const { exec } = require('child_process'); const path = require('path'); +const crypto = require('crypto'); -const configFile = path.resolve(__dirname, './public/conf.yml'); +// Default location of config file in container +const configFileName = '../public/conf.yml'; +// Real path of config file in container +const configFilePath = path.resolve(__dirname, configFileName); +// Amount of time to ignore file after change detected +const debounceTimeMs = 2000; + +// Store current timeout let timeout = null; +// Store last hash of file +let lastHash = null; -console.log(`Watching for file changes on ${configFile}`); +/** + * Calculate hash of file, used for de-bounce mechanism to + * prevent successive updates if file content not changed + */ +const hashFileContent = (filePath) => { + const content = fs.readFileSync(filePath, 'utf8'); + return crypto.createHash('sha256').update(content).digest('hex'); +}; -fs.watch(configFile, (eventType, filename) => { - if (filename && eventType === 'change') { - console.log(`${filename} file Changed, preparing to build...`); - // Clear the existing timeout, if there is one - if (timeout) clearTimeout(timeout); - // Set a new timeout - timeout = setTimeout(() => { - console.log('Running build...'); - exec('yarn build', (error, stdout, stderr) => { - if (error) { - console.error(`exec error: ${error}`); - return; - } - console.log(`stdout: ${stdout}`); - console.error(`stderr: ${stderr}`); - }); - }, 1000); // Adjust the debounce time as necessary, here it's 1000 milliseconds (1 second) +/** + * Just logs a given message to terminal so user knows what's happening + */ +const logInfo = (message, msgLevel = 'OUTPUT') => { + const RESET = '\x1b[0m'; + let logLevels = {}; + switch (msgLevel) { + case 'ERROR': logLevels = { col: '\x1b[31m', func: console.error }; break; + case 'WARNING': logLevels = { col: '\x1b[33m', func: console.warn }; break; + case 'INFO': logLevels = { col: '\x1b[36m', func: console.info }; break; + case 'SUCCESS': logLevels = { col: '\x1b[32m', func: console.log }; break; + default: logLevels = { col: RESET, func: console.log }; } -}); + logLevels.func(`${logLevels.col}\x1b[1m[${msgLevel}]${RESET} ${logLevels.col}${message}${RESET}\n`); +}; + +// Log initial message to user +logInfo(`When '${configFileName}' is updated, a rebuild will be triggered.\n`); + +/** + * Code to be executed when a watch event is triggered + * Will check correctly expected file and time frame, + * then ensure the hash is different from last hash, + * and then trigger -rebuild of frontend with yarn build + * outputting the stdrout and stderr to user's terminal + */ +const watchAction = (eventType, filename) => { + if (filename && eventType === 'change') { + if (timeout) clearTimeout(timeout); + timeout = setTimeout(() => { + const currentHash = hashFileContent(configFilePath); + if (currentHash !== lastHash) { + lastHash = currentHash; + logInfo(`${filename} file Changed, running build...`); + exec('yarn build', (error, stdout, stderr) => { + if (error) { + logInfo(error, 'ERROR'); + return; + } + logInfo(stdout); + logInfo(stderr, 'WARNING'); + logInfo('Build completed successfully.\n', 'SUCCESS'); + }); + } else { + logInfo(`${filename} file Detected change, but content is the same. Skipping....`, 'WARNING'); + } + }, debounceTimeMs); + } +}; + +// Watch given config path, with the watch action function +fs.watch(configFilePath, watchAction);