You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
5.3 KiB

  1. #!/usr/bin/env node
  2. // ===========================================
  3. // Wiki.js
  4. // 2.0
  5. // Licensed under AGPLv3
  6. // ===========================================
  7. const Promise = require('bluebird')
  8. const fs = Promise.promisifyAll(require('fs-extra'))
  9. const pm2 = Promise.promisifyAll(require('pm2'))
  10. const ora = require('ora')
  11. const path = require('path')
  12. const cluster = require('cluster')
  13. const _ = require('lodash')
  14. const chalk = require('chalk')
  15. const ROOTPATH = process.cwd()
  16. const init = {
  17. /**
  18. * Start in background mode
  19. */
  20. start () {
  21. let spinner = ora('Initializing...').start()
  22. return fs.emptyDirAsync(path.join(ROOTPATH, './logs')).then(() => {
  23. return pm2.connectAsync().then(() => {
  24. return pm2.startAsync({
  25. name: 'wiki',
  26. script: 'server',
  27. cwd: ROOTPATH,
  28. output: path.join(ROOTPATH, './logs/wiki-output.log'),
  29. error: path.join(ROOTPATH, './logs/wiki-error.log'),
  30. minUptime: 5000,
  31. maxRestarts: 5
  32. }).then(() => {
  33. spinner.succeed('Wiki.js has started successfully.')
  34. }).finally(() => {
  35. pm2.disconnect()
  36. })
  37. })
  38. }).catch(err => {
  39. spinner.fail(err)
  40. process.exit(1)
  41. })
  42. },
  43. /**
  44. * Stop Wiki.js process(es)
  45. */
  46. stop () {
  47. let spinner = ora('Shutting down Wiki.js...').start()
  48. return pm2.connectAsync().then(() => {
  49. return pm2.stopAsync('wiki').then(() => {
  50. spinner.succeed('Wiki.js has stopped successfully.')
  51. }).finally(() => {
  52. pm2.disconnect()
  53. })
  54. }).catch(err => {
  55. spinner.fail(err)
  56. process.exit(1)
  57. })
  58. },
  59. /**
  60. * Restart Wiki.js process(es)
  61. */
  62. restart: function () {
  63. return this.stop().delay(1000).then(() => {
  64. this.start()
  65. })
  66. },
  67. dev() {
  68. if (cluster.isMaster) {
  69. const webpack = require('webpack')
  70. const chokidar = require('chokidar')
  71. global.DEV = true
  72. global.WP_CONFIG = require('./dev/webpack/webpack.dev.js')
  73. global.WP = webpack(global.WP_CONFIG)
  74. global.WP_DEV = {
  75. devMiddleware: require('webpack-dev-middleware')(global.WP, {
  76. publicPath: global.WP_CONFIG.output.publicPath
  77. }),
  78. hotMiddleware: require('webpack-hot-middleware')(global.WP)
  79. }
  80. global.WP_DEV.devMiddleware.waitUntilValid(() => {
  81. console.info(chalk.yellow.bold('>>> Starting Wiki.js in DEVELOPER mode...'))
  82. require('./server')
  83. process.stdin.setEncoding('utf8')
  84. process.stdin.on('data', data => {
  85. if (_.trim(data) === 'rs') {
  86. console.warn(chalk.yellow.bold('--- >>>>>>>>>>>>>>>>>>>>>>>> ---'))
  87. console.warn(chalk.yellow.bold('--- Manual restart requested ---'))
  88. console.warn(chalk.yellow.bold('--- <<<<<<<<<<<<<<<<<<<<<<<< ---'))
  89. this.reload()
  90. }
  91. })
  92. const devWatcher = chokidar.watch([
  93. './server',
  94. '!./server/views/master.pug'
  95. ], {
  96. ignoreInitial: true,
  97. atomic: 400
  98. })
  99. devWatcher.on('ready', () => {
  100. devWatcher.on('all', () => {
  101. console.warn(chalk.yellow.bold('--- >>>>>>>>>>>>>>>>>>>>>>>>>>>> ---'))
  102. console.warn(chalk.yellow.bold('--- Changes detected: Restarting ---'))
  103. console.warn(chalk.yellow.bold('--- <<<<<<<<<<<<<<<<<<<<<<<<<<<< ---'))
  104. this.reload()
  105. })
  106. })
  107. })
  108. } else {
  109. require('./server')
  110. }
  111. },
  112. async reload() {
  113. console.warn(chalk.yellow('--- Stopping scheduled jobs...'))
  114. if (global.WIKI.scheduler) {
  115. global.WIKI.scheduler.stop()
  116. }
  117. console.warn(chalk.yellow('--- Closing DB connections...'))
  118. await global.WIKI.models.knex.destroy()
  119. console.warn(chalk.yellow('--- Closing Server connections...'))
  120. if (global.WIKI.server) {
  121. await new Promise((resolve, reject) => global.WIKI.server.destroy(resolve))
  122. }
  123. console.warn(chalk.yellow('--- Purging node modules cache...'))
  124. global.WIKI = {}
  125. Object.keys(require.cache).forEach(id => {
  126. if (/[/\\]server[/\\]/.test(id)) {
  127. delete require.cache[id]
  128. }
  129. })
  130. Object.keys(module.constructor._pathCache).forEach(cacheKey => {
  131. if (/[/\\]server[/\\]/.test(cacheKey)) {
  132. delete module.constructor._pathCache[cacheKey]
  133. }
  134. })
  135. console.warn(chalk.yellow('--- Unregistering process listeners...'))
  136. process.removeAllListeners('unhandledRejection')
  137. process.removeAllListeners('uncaughtException')
  138. require('./server')
  139. }
  140. }
  141. require('yargs') // eslint-disable-line no-unused-expressions
  142. .usage('Usage: node $0 <cmd> [args]')
  143. .command({
  144. command: 'start',
  145. alias: ['boot', 'init'],
  146. desc: 'Start Wiki.js process',
  147. handler: argv => {
  148. init.start()
  149. }
  150. })
  151. .command({
  152. command: 'stop',
  153. alias: ['quit', 'exit'],
  154. desc: 'Stop Wiki.js process',
  155. handler: argv => {
  156. init.stop()
  157. }
  158. })
  159. .command({
  160. command: 'restart',
  161. alias: ['reload'],
  162. desc: 'Restart Wiki.js process',
  163. handler: argv => {
  164. init.restart()
  165. }
  166. })
  167. .command({
  168. command: 'dev',
  169. desc: 'Start in Developer Mode',
  170. handler: argv => {
  171. init.dev()
  172. }
  173. })
  174. .recommendCommands()
  175. .demandCommand(1, 'You must provide one of the accepted commands above.')
  176. .help()
  177. .version()
  178. .epilogue('Read the docs at https://docs.requarks.io/wiki')
  179. .argv