// libraries const fs = require("fs/promises") const path = require("path") const crypto = require("crypto") const { sourceDir } = require("./config.js") class Logger { constructor({ name, logDebug }) { this.name = name this.debug = logDebug } _log(logType, data, method) { console[method](`[${this.name}] [${logType}] ${typeof data == "string" ? data : data.toString()}`) } info(data) { this._log("info", data, "log") } warn(data) { this._log("warn", data, "error") } error(data) { this._log("error", data, "error") } debug(data) { if (this.debug) { this._log("debug", data, "error") } } } async function recursiveFileSearch(dir) { const fileList = [] for (const file of await fs.readdir(dir, { withFileTypes: true })) { let pathDir = path.resolve(dir, file.name) if (file.isFile()) { fileList.push(pathDir) } else if (file.isDirectory()) { fileList.push(...(await recursiveFileSearch(pathDir))) } else { logger.warn(`Found directory entry that is neither a file or directory (${pathDir}), ignoring!`) } } return fileList } const logger = new Logger({ name: "launcher", logDebug: process.env.DEBUG == "true" }), LINE_SEPERATOR = "-----------------------------------" if (!process.env.REPL_SLUG) { logger.error(LINE_SEPERATOR) logger.error("Repl not detected!") logger.error("") logger.error("This file is meant to be ran in a Repl") logger.error(LINE_SEPERATOR) } logger.info(LINE_SEPERATOR) logger.info("Checking if the proxy needs to be recompiled...") logger.info(LINE_SEPERATOR) fs.readFile(path.join(__dirname, ".sourcehash")) .then(data => { let oldHash = data.toString() logger.info("Found old hash, calculating hash of source files...") recursiveFileSearch(sourceDir) .then(files => { Promise.all(files.map(f => fs.readFile(f))) .then(data => { const hash = crypto.createHash("sha256") data.forEach(d => hash.update(d)) let sourceHash = hash.digest().toString() if (sourceHash === oldHash) { logger.info("Source hasn't been changed, skipping compilation...") process.exit(0) } else { logger.info("Source has been changed, recompiling...") fs.writeFile(path.join(__dirname, ".sourcehash"), sourceHash) .then(() => { process.exit(2) }) .catch(err => { logger.error(`Could not write new hash to disk!\n${err.stack}`) process.exit(1) }) } }) }) .catch(err => { logger.error(`Could not calculate file hashes for files in directory ${sourceDir}!\n${err.stack}`) process.exit(1) }) }) .catch(err => { if (err.code == "ENOENT") { logger.warn("Previous source hash not found! Assuming a clean install is being used.") logger.info("Calculating hash...") recursiveFileSearch(sourceDir) .then(files => { Promise.all(files.map(f => fs.readFile(f))) .then(data => { const hash = crypto.createHash("sha256") data.forEach(d => hash.update(d)) let sourceHash = hash.digest().toString() fs.writeFile(path.join(__dirname, ".sourcehash"), sourceHash) .then(() => { logger.info("Saved hash to disk.") process.exit(2) }) .catch(err => { logger.error(`Could not write new hash to disk!\n${err.stack}`) process.exit(1) }) }) }) .catch(err => { logger.error(`Could not calculate file hashes for files in directory ${sourceDir}!\n${err.stack}`) process.exit(1) }) } else { logger.error(`Could not read .sourcehash file in ${path.join(__dirname, ".sourcehash")} due to an unknown error! Try again with a clean repl?\n${err.stack}`) process.exit(1) } })