index.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. const fs = require('fs-extra');
  2. const path = require('path');
  3. const express = require('express');
  4. const http = require('http');
  5. const WebSocket = require ('ws');
  6. const utils = require('./core/utils');
  7. const ayncExit = new (require('./core/AsyncExit'))();
  8. let log;
  9. let config;
  10. let argv;
  11. let branch = '';
  12. const argvStrings = ['host', 'port', 'app-dir', 'lib-dir', 'inpx'];
  13. function showHelp(defaultConfig) {
  14. console.log(utils.versionText(config));
  15. console.log(
  16. `Usage: ${config.name} [options]
  17. Options:
  18. --help Print ${config.name} command line options
  19. --host=<ip> Set web server host, default: ${defaultConfig.server.host}
  20. --port=<port> Set web server port, default: ${defaultConfig.server.port}
  21. --app-dir=<dirpath> Set application working directory, default: <execDir>/.${config.name}
  22. --lib-dir=<dirpath> Set library directory, default: the same as ${config.name} executable's
  23. --inpx=<filepath> Set INPX collection file, default: the one that found in library dir
  24. --recreate Force recreation of the search database on start
  25. `
  26. );
  27. }
  28. async function init() {
  29. argv = require('minimist')(process.argv.slice(2), {string: argvStrings});
  30. const dataDir = argv['app-dir'];
  31. //config
  32. const configManager = new (require('./config'))();//singleton
  33. await configManager.init(dataDir);
  34. const defaultConfig = configManager.config;
  35. await configManager.load();
  36. config = configManager.config;
  37. branch = config.branch;
  38. //dirs
  39. config.tempDir = `${config.dataDir}/tmp`;
  40. config.logDir = `${config.dataDir}/log`;
  41. config.publicDir = `${config.dataDir}/public`;
  42. config.publicFilesDir = `${config.dataDir}/public-files`;
  43. config.rootPathStatic = config.server.root || '';
  44. config.bookPathStatic = `${config.rootPathStatic}/book`;
  45. config.bookDir = `${config.publicFilesDir}/book`;
  46. configManager.config = config;
  47. await fs.ensureDir(config.dataDir);
  48. await fs.ensureDir(config.bookDir);
  49. await fs.ensureDir(config.tempDir);
  50. await fs.emptyDir(config.tempDir);
  51. //logger
  52. const appLogger = new (require('./core/AppLogger'))();//singleton
  53. await appLogger.init(config);
  54. log = appLogger.log;
  55. //cli
  56. if (argv.help) {
  57. showHelp(defaultConfig);
  58. ayncExit.exit(0);
  59. } else {
  60. log(utils.versionText(config));
  61. log('Initializing');
  62. }
  63. if (argv.host) {
  64. config.server.host = argv.host;
  65. }
  66. if (argv.port) {
  67. config.server.port = argv.port;
  68. }
  69. if (!config.remoteLib) {
  70. const libDir = argv['lib-dir'];
  71. if (libDir) {
  72. if (await fs.pathExists(libDir)) {
  73. config.libDir = libDir;
  74. } else {
  75. throw new Error(`Directory "${libDir}" not exists`);
  76. }
  77. } else {
  78. config.libDir = config.execDir;
  79. }
  80. if (argv.inpx) {
  81. if (await fs.pathExists(argv.inpx)) {
  82. config.inpxFile = argv.inpx;
  83. } else {
  84. throw new Error(`File "${argv.inpx}" not found`);
  85. }
  86. } else {
  87. const inpxFiles = [];
  88. await utils.findFiles((file) => {
  89. if (path.extname(file) == '.inpx')
  90. inpxFiles.push(file);
  91. }, config.libDir, false);
  92. if (inpxFiles.length) {
  93. if (inpxFiles.length == 1) {
  94. config.inpxFile = inpxFiles[0];
  95. } else {
  96. throw new Error(`Found more than one .inpx files: \n${inpxFiles.join('\n')}`);
  97. }
  98. } else {
  99. throw new Error(`No .inpx files found here: ${config.libDir}`);
  100. }
  101. }
  102. } else {
  103. config.inpxFile = `${config.dataDir}/remote.inpx`;
  104. const RemoteLib = require('./core/RemoteLib');//singleton
  105. const remoteLib = new RemoteLib(config);
  106. await remoteLib.downloadInpxFile();
  107. }
  108. config.recreateDb = argv.recreate || false;
  109. config.inpxFilterFile = `${config.dataDir}/filter.json`;
  110. config.allowUnsafeFilter = argv['unsafe-filter'] || false;
  111. //web app
  112. if (branch !== 'development') {
  113. const createWebApp = require('./createWebApp');
  114. await createWebApp(config);
  115. }
  116. }
  117. async function main() {
  118. const log = new (require('./core/AppLogger'))().log;//singleton
  119. //server
  120. const app = express();
  121. const server = http.createServer(app);
  122. const wss = new WebSocket.Server({ server, maxPayload: config.maxPayloadSize*1024*1024 });
  123. let devModule = undefined;
  124. if (branch == 'development') {
  125. const devFileName = './dev.js'; //require ignored by pkg -50Mb executable size
  126. devModule = require(devFileName);
  127. devModule.webpackDevMiddleware(app);
  128. }
  129. if (devModule)
  130. devModule.logQueries(app);
  131. const opds = require('./core/opds');
  132. opds(app, config);
  133. const initStatic = require('./static');
  134. initStatic(app, config);
  135. const webAccess = new (require('./core/WebAccess'))(config);
  136. await webAccess.init();
  137. const { WebSocketController } = require('./controllers');
  138. new WebSocketController(wss, webAccess, config);
  139. if (devModule) {
  140. devModule.logErrors(app);
  141. } else {
  142. app.use(function(err, req, res, next) {// eslint-disable-line no-unused-vars
  143. log(LM_ERR, err.stack);
  144. res.sendStatus(500);
  145. });
  146. }
  147. server.listen(config.server.port, config.server.host, () => {
  148. config.server.ready = true;
  149. log(`Server ready`);
  150. });
  151. }
  152. (async() => {
  153. try {
  154. await init();
  155. await main();
  156. } catch (e) {
  157. const mes = (branch == 'development' ? e.stack : e.message);
  158. if (log)
  159. log(LM_FATAL, mes);
  160. else
  161. console.error(mes);
  162. ayncExit.exit(1);
  163. }
  164. })();