main.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // The main coordination file of JokeAPI
  2. // This file starts all necessary modules like the joke parser, the JokeAPI Documentation page injection and the HTTP listener, etc.
  3. "use strict";
  4. const jsl = require("svjsl");
  5. const fs = require("fs-extra");
  6. const promiseAllSequential = require("promise-all-sequential");
  7. require("dotenv").config();
  8. const env = require("./env");
  9. const debug = require("./verboseLogging");
  10. const parseJokes = require("./parseJokes");
  11. const httpServer = require("./httpServer");
  12. const lists = require("./lists");
  13. const docs = require("./docs");
  14. const analytics = require("./analytics");
  15. const logRequest = require("./logRequest");
  16. const auth = require("./auth");
  17. const languages = require("./languages");
  18. const translate = require("./translate");
  19. const meter = require("./meter");
  20. const settings = require("../settings");
  21. const col = jsl.colors.fg;
  22. process.debuggerActive = jsl.inDebugger();
  23. const noDbg = process.debuggerActive || false;
  24. settings.init.exitSignals.forEach(sig => {
  25. process.on(sig, () => softExit(0));
  26. });
  27. //#MARKER init all
  28. const initAll = () => {
  29. env.init();
  30. let initTimestamp = new Date().getTime();
  31. console.log(`Initializing ${settings.info.name}...\n`);
  32. process.jokeapi = {};
  33. initializeDirs();
  34. let initPromises = [];
  35. let initStages = [
  36. {
  37. name: "Initializing languages",
  38. fn: languages.init
  39. },
  40. {
  41. name: "Initializing translations",
  42. fn: translate.init
  43. },
  44. {
  45. name: "Initializing joke parser",
  46. fn: parseJokes.init
  47. },
  48. {
  49. name: "Initializing lists",
  50. fn: lists.init
  51. },
  52. {
  53. name: "Initializing documentation",
  54. fn: docs.init
  55. },
  56. {
  57. name: "Initializing authorization module",
  58. fn: auth.init
  59. },
  60. {
  61. name: "Initializing HTTP server",
  62. fn: httpServer.init
  63. },
  64. {
  65. name: "Initializing analytics module",
  66. fn: analytics.init
  67. },
  68. {
  69. name: "Initializing pm2 meter",
  70. fn: meter.init
  71. }
  72. ];
  73. let pb;
  74. if(!noDbg && !settings.debug.progressBarDisabled)
  75. pb = new jsl.ProgressBar(initStages.length, initStages[0].name);
  76. initStages.forEach(stage => {
  77. initPromises.push(stage.fn);
  78. });
  79. debug("Init", `Sequentially initializing all ${initStages.length} modules...`);
  80. promiseAllSequential(initPromises).then((res) => {
  81. jsl.unused(res);
  82. if(!jsl.isEmpty(pb))
  83. pb.next("Done.");
  84. debug("Init", `Done initializing all ${initStages.length} modules. Printing init message...`);
  85. logRequest.initMsg(initTimestamp);
  86. }).catch(err => {
  87. initError("initializing", err);
  88. });
  89. };
  90. //#MARKER other
  91. /**
  92. * This function gets called when JokeAPI encounters an error while initializing.
  93. * Because the initialization phase is such a delicate and important process, JokeAPI shuts down if an error is encountered.
  94. * @param {String} action
  95. * @param {Error} err
  96. */
  97. const initError = (action, err) => {
  98. let errMsg = err.stack || err || "(No error message provided)";
  99. console.log(`\n\n\n${col.red}JokeAPI encountered an error while ${action}:\n${errMsg}\n\n${jsl.colors.rst}`);
  100. process.exit(1);
  101. }
  102. /**
  103. * Makes sure all directories exist and creates them if they don't
  104. */
  105. const initializeDirs = () => {
  106. try
  107. {
  108. settings.init.initDirs.forEach(dir => {
  109. if(!fs.existsSync(dir))
  110. {
  111. debug("InitDirs", `Dir "${dir}" doesn't exist, creating it...`);
  112. fs.mkdirSync(dir);
  113. }
  114. });
  115. }
  116. catch(err)
  117. {
  118. initError("initializing default directories", err);
  119. }
  120. }
  121. /**
  122. * Ends all open connections and then shuts down the process with the specified exit code
  123. * @param {Number} [code=0] Exit code - defaults to 0
  124. */
  125. const softExit = code => {
  126. if(typeof code != "number" || code < 0)
  127. code = 0;
  128. analytics.endSqlConnection().then(() => process.exit(code)).catch(() => process.exit(code));
  129. }
  130. module.exports = { softExit };
  131. initAll();