install.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. 'use strict'
  2. const Promise = require('bluebird')
  3. const exec = require('execa')
  4. const fs = Promise.promisifyAll(require('fs-extra'))
  5. const https = require('follow-redirects').https
  6. const path = require('path')
  7. const pm2 = Promise.promisifyAll(require('pm2'))
  8. const tar = require('tar')
  9. const zlib = require('zlib')
  10. const inquirer = require('inquirer')
  11. const colors = require('colors/safe')
  12. const _ = require('lodash')
  13. let installDir = path.resolve(__dirname, '../..')
  14. console.info(colors.yellow(
  15. ' __ __ _ _ _ _ \n' +
  16. '/ / /\\ \\ (_) | _(_) (_)___ \n' +
  17. '\\ \\/ \\/ / | |/ / | | / __| \n' +
  18. ' \\ /\\ /| | <| |_ | \\__ \\ \n' +
  19. ' \\/ \\/ |_|_|\\_\\_(_)/ |___/ \n' +
  20. ' |__/\n'))
  21. var ora = require('ora')({ text: 'Initializing...', spinner: 'dots12' }).start()
  22. ora.text = 'Looking for running instances...'
  23. pm2.connectAsync().then(() => {
  24. return pm2.describeAsync('wiki').then(() => {
  25. ora.text = 'Stopping and deleting process from pm2...'
  26. return pm2.deleteAsync('wiki')
  27. }).catch(err => { // eslint-disable-line handle-callback-err
  28. return true
  29. })
  30. }).then(() => {
  31. /**
  32. * Fetch version from npm package
  33. */
  34. return fs.readJsonAsync('package.json').then((packageObj) => {
  35. let versionGet = _.chain(packageObj.version).split('.').take(4).join('.')
  36. let remoteURL = _.replace('https://github.com/Requarks/wiki/releases/download/v{0}/wiki-js.tar.gz', '{0}', versionGet)
  37. return new Promise((resolve, reject) => {
  38. /**
  39. * Fetch tarball
  40. */
  41. ora.text = 'Looking for latest release...'
  42. https.get(remoteURL, resp => {
  43. if (resp.statusCode !== 200) {
  44. return reject(new Error('Remote file not found'))
  45. }
  46. ora.text = 'Install tarball found. Downloading...'
  47. /**
  48. * Extract tarball
  49. */
  50. resp.pipe(zlib.createGunzip())
  51. .pipe(tar.Extract({ path: installDir }))
  52. .on('error', err => reject(err))
  53. .on('end', () => {
  54. ora.text = 'Tarball extracted successfully.'
  55. resolve(true)
  56. })
  57. })
  58. })
  59. })
  60. }).then(() => {
  61. ora.text = 'Installing Wiki.js npm dependencies...'
  62. return exec.stdout('npm', ['install', '--only=production', '--no-optional'], {
  63. cwd: installDir
  64. }).then(results => {
  65. ora.text = 'Wiki.js npm dependencies installed successfully.'
  66. return true
  67. })
  68. }).then(() => {
  69. fs.accessAsync(path.join(installDir, 'config.yml')).then(() => {
  70. /**
  71. * Upgrade mode
  72. */
  73. ora.succeed('Upgrade completed.')
  74. return false
  75. }).catch(err => {
  76. /**
  77. * Install mode
  78. */
  79. if (err.code === 'ENOENT') {
  80. ora.text = 'First-time install, creating a new config.yml...'
  81. return fs.copyAsync(path.join(installDir, 'config.sample.yml'), path.join(installDir, 'config.yml')).then(() => {
  82. ora.succeed('Installation succeeded.')
  83. return true
  84. })
  85. } else {
  86. return err
  87. }
  88. }).then((isNewInstall) => {
  89. if (process.stdout.isTTY) {
  90. inquirer.prompt([{
  91. type: 'list',
  92. name: 'action',
  93. message: 'Continue with configuration wizard?',
  94. default: 'default',
  95. choices: [
  96. { name: 'Yes, run configuration wizard on port 3000 (recommended)', value: 'default', short: 'Yes' },
  97. { name: 'Yes, run configuration wizard on a custom port...', value: 'custom', short: 'Yes' },
  98. { name: 'No, I\'ll configure the config file manually', value: 'exit', short: 'No' }
  99. ]
  100. }, {
  101. type: 'input',
  102. name: 'customport',
  103. message: 'Custom port to use:',
  104. default: 3000,
  105. validate: (val) => {
  106. val = _.toNumber(val)
  107. return (_.isNumber(val) && val > 0) ? true : 'Invalid Port!'
  108. },
  109. when: (ans) => {
  110. return ans.action === 'custom'
  111. }
  112. }]).then((ans) => {
  113. switch (ans.action) {
  114. case 'default':
  115. console.info(colors.bold.cyan('> Browse to http://your-server:3000/ to configure your wiki!'))
  116. ora = require('ora')({ text: 'I\'ll wait until you\'re done ;)', color: 'yellow', spinner: 'pong' }).start()
  117. return exec.stdout('node', ['wiki', 'configure'], {
  118. cwd: installDir
  119. })
  120. case 'custom':
  121. console.info(colors.bold.cyan('> Browse to http://your-server:' + ans.customport + '/ to configure your wiki!'))
  122. ora = require('ora')({ text: 'I\'ll wait until you\'re done ;)', color: 'yellow', spinner: 'pong' }).start()
  123. return exec.stdout('node', ['wiki', 'configure', ans.customport], {
  124. cwd: installDir
  125. })
  126. default:
  127. console.info(colors.bold.cyan('> Open config.yml in your favorite editor. Then start Wiki.js using: node wiki start'))
  128. return process.exit(0)
  129. }
  130. }).then(() => {
  131. ora.succeed(colors.bold.green('Wiki.js has been configured and is now running!'))
  132. })
  133. } else {
  134. console.info('[!] Non-interactive terminal detected. You may now manually edit config.yml and start Wiki.js by running: node wiki start')
  135. }
  136. })
  137. }).catch(err => {
  138. ora.fail(err)
  139. }).finally(() => {
  140. pm2.disconnect()
  141. })