// IMPORTANT: // Madge needs the Graphviz software to generate the SVG graphs. // // On Windows, download it here: https://graphviz.gitlab.io/download/, then add the path to the "bin" folder to your PATH variable or specify the path to the bin folder in the "madgeOptions" object below. // On Linux, run "sudo apt-get install graphviz" // On Mac, run "brew install graphviz || port install graphviz" // // To add files to be included in the graphing process, add them to the "otherFiles" array below (path is relative to project root). // Before running this script by using "node dev/madge", make sure all dev dependencies are installed by running the command "npm i --save-dev" const madgeOptions = { // graphVizPath: "C:/Users/fes/Desktop/Graphviz/bin" // set to null to use the path inside the PATH environment variable graphVizPath: null }; const otherFiles = [ "./JokeAPI.js" ]; const madge = require("madge"); const fs = require("fs-extra"); const settings = require("../../settings"); var fileList = []; var firstIframePos = {url: "./madge/JokeAPI.html", name: "./JokeAPI"}; let isWindows = process.platform == "win32"; if(isWindows && !process.env.PATH.toLowerCase().includes("graphviz") && madgeOptions.graphVizPath == null) { console.log("\x1b[31m\x1b[1m\nMadge needs the GraphViz software to generate the SVG graphs. Please download it (https://graphviz.gitlab.io/download/) and add it to your PATH environment variable.\nAlso make sure the path to it contains the word \"Graphviz\"\x1b[0m"); process.exit(1); } const generateForOther = () => { let iterCount = 0; return new Promise((resolve, reject) => { otherFiles.forEach(file => { if(!file.endsWith(".js")) { iterCount++; return; } let filename = file.replace(/\.js/g, ""); try { madge(`${file}`, madgeOptions) .then((res) => res.svg()) .then((output) => { iterCount++; fs.writeFileSync(`./dev/madge/${filename}.html`, output.toString()); if(iterCount == otherFiles.length) resolve(); }); fileList.push(`
  • ${filename}.js
  • `); } catch(err) { reject(err); } }); }); } const generateForSrc = () => { let iterCount = 0; let srcFiles = fs.readdirSync("./src"); return new Promise((resolve, reject) => { srcFiles.forEach(file => { if(!file.endsWith(".js")) { iterCount++; return; } let filename = file.replace(/\.js/g, ""); try { madge(`./src/${file}`, madgeOptions) .then((res) => res.svg()) .then((output) => { iterCount++; fs.writeFileSync(`./dev/madge/src-${filename}.html`, output.toString()); if(iterCount == srcFiles.length) resolve(); }); fileList.push(`
  • src/${filename}.js
  • `); } catch(err) { reject(err); } }); }); } const generateForEndpoints = () => { let iterCount = 0; let endpointFiles = fs.readdirSync("./endpoints"); return new Promise((resolve, reject) => { endpointFiles.forEach(file => { if(!file.endsWith(".js")) { iterCount++; return; } let filename = file.replace(/\.js/g, ""); try { madge(`./endpoints/${file}`, madgeOptions) .then((res) => res.svg()) .then((output) => { iterCount++; fs.writeFileSync(`./dev/madge/endpoints-${filename}.html`, output.toString()); if(iterCount == endpointFiles.length) resolve(); }); fileList.push(`
  • endpoints/${filename}.js
  • `); } catch(err) { reject(err); } }); }); } const generateForTools = () => { let iterCount = 0; let toolFiles = fs.readdirSync("./tools"); return new Promise((resolve, reject) => { toolFiles.forEach(file => { if(!file.endsWith(".js")) { iterCount++; return; } let filename = file.replace(/\.js/g, ""); try { madge(`./tools/${file}`, madgeOptions) .then((res) => res.svg()) .then((output) => { iterCount++; fs.writeFileSync(`./dev/madge/tools-${filename}.html`, output.toString()); if(iterCount == toolFiles.length) resolve(); }); fileList.push(`
  • tools/${filename}.js
  • `); } catch(err) { reject(err); } }); }); } const generateForClasses = () => { let iterCount = 0; let classesFiles = fs.readdirSync("./src/classes"); return new Promise((resolve, reject) => { classesFiles.forEach(file => { if(!file.endsWith(".js")) { iterCount++; return; } let filename = file.replace(/\.js/g, ""); try { madge(`./src/classes/${file}`, madgeOptions) .then((res) => res.svg()) .then((output) => { iterCount++; fs.writeFileSync(`./dev/madge/classes-${filename}.html`, output.toString()); if(iterCount == classesFiles.length) resolve(); }); fileList.push(`
  • classes/${filename}.js
  • `); } catch(err) { reject(err); } }); }); } const generateForTests = () => { let iterCount = 0; let testsFiles = fs.readdirSync("./tests"); return new Promise((resolve, reject) => { testsFiles.forEach(file => { if(!file.endsWith(".js") || file == "template.js") { iterCount++; return; } let filename = file.replace(/\.js/g, ""); try { madge(`./tests/${file}`, madgeOptions) .then((res) => res.svg()) .then((output) => { iterCount++; fs.writeFileSync(`./dev/madge/tests-${filename}.html`, output.toString()); if(iterCount == testsFiles.length) resolve(); }); fileList.push(`
  • tests/${filename}.js
  • `); } catch(err) { reject(err); } }); }); } const writeIndex = () => { let index = getIndex(); fs.writeFileSync("./dev/dependency-graph.html", index); console.log(`\n\n\x1b[32m\x1b[1mSuccessfully generated dependency graphs for ${fileList.length} files.\n\x1b[0m`); process.exit(0); } const getIndex = () => `\ ${settings.info.name} Dependency Graph


    Blue has dependencies.
    Green has no dependencies.
    Red has circular dependencies.

    `; async function exec() { try { if(!fs.existsSync("./dev/madge")) fs.mkdirSync("./dev/madge"); await generateForOther(); process.stdout.write("."); await generateForSrc(); process.stdout.write("."); await generateForEndpoints(); process.stdout.write("."); await generateForTools(); process.stdout.write("."); await generateForClasses(); process.stdout.write("."); await generateForTests(); process.stdout.write("."); writeIndex(); process.stdout.write(".\n"); } catch(err) { console.log(`\n\n\x1b[31m\x1b[1mError while generating dependency graphs:\n\x1b[0m${err}\n`); process.exit(1); } } exec();