storage.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. const fs = require('fs-extra')
  2. const path = require('path')
  3. const tar = require('tar-fs')
  4. const zlib = require('zlib')
  5. const stream = require('stream')
  6. const Promise = require('bluebird')
  7. const pipeline = Promise.promisify(stream.pipeline)
  8. const pageHelper = require('../../../helpers/page.js')
  9. const moment = require('moment')
  10. /* global WIKI */
  11. /**
  12. * Get file extension based on content type
  13. */
  14. const getFileExtension = (contentType) => {
  15. switch (contentType) {
  16. case 'markdown':
  17. return 'md'
  18. case 'html':
  19. return 'html'
  20. default:
  21. return 'txt'
  22. }
  23. }
  24. module.exports = {
  25. async activated() {
  26. // not used
  27. },
  28. async deactivated() {
  29. // not used
  30. },
  31. async init() {
  32. WIKI.logger.info('(STORAGE/DISK) Initializing...')
  33. await fs.ensureDir(this.config.path)
  34. WIKI.logger.info('(STORAGE/DISK) Initialization completed.')
  35. },
  36. async sync({ manual } = { manual: false }) {
  37. if (this.config.createDailyBackups || manual) {
  38. const dirPath = path.join(this.config.path, manual ? '_manual' : '_daily')
  39. await fs.ensureDir(dirPath)
  40. const dateFilename = moment().format(manual ? 'YYYYMMDD-HHmmss' : 'DD')
  41. WIKI.logger.info(`(STORAGE/DISK) Creating backup archive...`)
  42. await pipeline(
  43. tar.pack(this.config.path, {
  44. ignore: (filePath) => {
  45. return filePath.indexOf('_daily') >= 0 || filePath.indexOf('_manual') >= 0
  46. }
  47. }),
  48. zlib.createGzip(),
  49. fs.createWriteStream(path.join(dirPath, `wiki-${dateFilename}.tar.gz`))
  50. )
  51. WIKI.logger.info('(STORAGE/DISK) Backup archive created successfully.')
  52. }
  53. },
  54. async created(page) {
  55. WIKI.logger.info(`(STORAGE/DISK) Creating file ${page.path}...`)
  56. let fileName = `${page.path}.${getFileExtension(page.contentType)}`
  57. if (WIKI.config.lang.namespacing && WIKI.config.lang.code !== page.localeCode) {
  58. fileName = `${page.localeCode}/${fileName}`
  59. }
  60. const filePath = path.join(this.config.path, fileName)
  61. await fs.outputFile(filePath, page.injectMetadata(), 'utf8')
  62. },
  63. async updated(page) {
  64. WIKI.logger.info(`(STORAGE/DISK) Updating file ${page.path}...`)
  65. let fileName = `${page.path}.${getFileExtension(page.contentType)}`
  66. if (WIKI.config.lang.namespacing && WIKI.config.lang.code !== page.localeCode) {
  67. fileName = `${page.localeCode}/${fileName}`
  68. }
  69. const filePath = path.join(this.config.path, fileName)
  70. await fs.outputFile(filePath, page.injectMetadata(), 'utf8')
  71. },
  72. async deleted(page) {
  73. WIKI.logger.info(`(STORAGE/DISK) Deleting file ${page.path}...`)
  74. let fileName = `${page.path}.${getFileExtension(page.contentType)}`
  75. if (WIKI.config.lang.namespacing && WIKI.config.lang.code !== page.localeCode) {
  76. fileName = `${page.localeCode}/${fileName}`
  77. }
  78. const filePath = path.join(this.config.path, fileName)
  79. await fs.unlink(filePath)
  80. },
  81. async renamed(page) {
  82. WIKI.logger.info(`(STORAGE/DISK) Renaming file ${page.sourcePath} to ${page.destinationPath}...`)
  83. let sourceFilePath = `${page.sourcePath}.${getFileExtension(page.contentType)}`
  84. let destinationFilePath = `${page.destinationPath}.${getFileExtension(page.contentType)}`
  85. if (WIKI.config.lang.namespacing && WIKI.config.lang.code !== page.localeCode) {
  86. sourceFilePath = `${page.localeCode}/${sourceFilePath}`
  87. destinationFilePath = `${page.localeCode}/${destinationFilePath}`
  88. }
  89. await fs.move(path.join(this.config.path, sourceFilePath), path.join(this.config.path, destinationFilePath), { overwrite: true })
  90. },
  91. /**
  92. * HANDLERS
  93. */
  94. async dump() {
  95. WIKI.logger.info(`(STORAGE/DISK) Dumping all content to disk...`)
  96. await pipeline(
  97. WIKI.models.knex.column('path', 'localeCode', 'title', 'description', 'contentType', 'content', 'isPublished', 'updatedAt').select().from('pages').where({
  98. isPrivate: false
  99. }).stream(),
  100. new stream.Transform({
  101. objectMode: true,
  102. transform: async (page, enc, cb) => {
  103. let fileName = `${page.path}.${getFileExtension(page.contentType)}`
  104. if (WIKI.config.lang.namespacing && WIKI.config.lang.code !== page.localeCode) {
  105. fileName = `${page.localeCode}/${fileName}`
  106. }
  107. WIKI.logger.info(`(STORAGE/DISK) Dumping ${fileName}...`)
  108. const filePath = path.join(this.config.path, fileName)
  109. await fs.outputFile(filePath, pageHelper.injectPageMetadata(page), 'utf8')
  110. cb()
  111. }
  112. })
  113. )
  114. WIKI.logger.info('(STORAGE/DISK) All content was dumped to disk successfully.')
  115. },
  116. async backup() {
  117. return this.sync({ manual: true })
  118. }
  119. }