config.mjs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import { defaultsDeep, get, isPlainObject } from 'lodash-es'
  2. import chalk from 'chalk'
  3. import cfgHelper from '../helpers/config.mjs'
  4. import regexData from '../app/regex.mjs'
  5. import fs from 'node:fs/promises'
  6. import path from 'node:path'
  7. import yaml from 'js-yaml'
  8. export default {
  9. /**
  10. * Load root config from disk
  11. */
  12. async init(silent = false) {
  13. const confPaths = {
  14. config: path.join(WIKI.ROOTPATH, 'config.yml'),
  15. data: path.join(WIKI.SERVERPATH, 'app/data.yml')
  16. }
  17. if (process.env.dockerdev) {
  18. confPaths.config = path.join(WIKI.ROOTPATH, `dev/containers/config.yml`)
  19. }
  20. if (process.env.CONFIG_FILE) {
  21. confPaths.config = path.resolve(WIKI.ROOTPATH, process.env.CONFIG_FILE)
  22. }
  23. if (!silent) {
  24. process.stdout.write(chalk.blue(`Loading configuration from ${confPaths.config}... `))
  25. }
  26. let appconfig = {}
  27. let appdata = {}
  28. try {
  29. appconfig = yaml.load(
  30. cfgHelper.parseConfigValue(
  31. await fs.readFile(confPaths.config, 'utf8')
  32. )
  33. )
  34. appdata = yaml.load(await fs.readFile(confPaths.data, 'utf8'))
  35. appdata.regex = regexData
  36. if (!silent) {
  37. console.info(chalk.green.bold(`OK`))
  38. }
  39. } catch (err) {
  40. console.error(chalk.red.bold(`FAILED`))
  41. console.error(err.message)
  42. console.error(chalk.red.bold(`>>> Unable to read configuration file! Did you create the config.yml file?`))
  43. process.exit(1)
  44. }
  45. // Merge with defaults
  46. appconfig = defaultsDeep(appconfig, appdata.defaults.config)
  47. // Override port
  48. if (appconfig.port < 1 || process.env.HEROKU) {
  49. appconfig.port = process.env.PORT || 80
  50. }
  51. if (process.env.WIKI_PORT) {
  52. appconfig.port = process.env.WIKI_PORT || 80
  53. }
  54. // Load package info
  55. const packageInfo = JSON.parse(await fs.readFile(path.join(WIKI.SERVERPATH, 'package.json'), 'utf-8'))
  56. // Load DB Password from Docker Secret File
  57. if (process.env.DB_PASS_FILE) {
  58. if (!silent) {
  59. console.info(chalk.blue(`DB_PASS_FILE is defined. Will use secret from file.`))
  60. }
  61. try {
  62. appconfig.db.pass = await fs.readFile(process.env.DB_PASS_FILE, 'utf8').trim()
  63. } catch (err) {
  64. console.error(chalk.red.bold(`>>> Failed to read Docker Secret File using path defined in DB_PASS_FILE env variable!`))
  65. console.error(err.message)
  66. process.exit(1)
  67. }
  68. }
  69. WIKI.config = appconfig
  70. WIKI.data = appdata
  71. WIKI.version = packageInfo.version
  72. WIKI.releaseDate = packageInfo.releaseDate
  73. WIKI.devMode = (packageInfo.dev === true)
  74. },
  75. /**
  76. * Load config from DB
  77. */
  78. async loadFromDb() {
  79. const conf = await WIKI.db.settings.getConfig()
  80. if (conf) {
  81. WIKI.config = defaultsDeep(conf, WIKI.config)
  82. } else {
  83. WIKI.logger.warn('Missing DB Configuration!')
  84. process.exit(1)
  85. }
  86. },
  87. /**
  88. * Save config to DB
  89. *
  90. * @param {Array} keys Array of keys to save
  91. * @returns Promise
  92. */
  93. async saveToDb(keys, propagate = true) {
  94. try {
  95. for (const key of keys) {
  96. let value = get(WIKI.config, key, null)
  97. if (!isPlainObject(value)) {
  98. value = { v: value }
  99. }
  100. let affectedRows = await WIKI.db.settings.query().patch({ value }).where('key', key)
  101. if (affectedRows === 0 && value) {
  102. await WIKI.db.settings.query().insert({ key, value })
  103. }
  104. }
  105. if (propagate) {
  106. WIKI.events.outbound.emit('reloadConfig')
  107. }
  108. } catch (err) {
  109. WIKI.logger.error(`Failed to save configuration to DB: ${err.message}`)
  110. return false
  111. }
  112. return true
  113. },
  114. /**
  115. * Apply Dev Flags
  116. */
  117. async applyFlags() {
  118. WIKI.db.knex.client.config.debug = WIKI.config.flags.sqlLog
  119. },
  120. /**
  121. * Subscribe to HA propagation events
  122. */
  123. subscribeToEvents() {
  124. WIKI.events.inbound.on('reloadConfig', async () => {
  125. await WIKI.configSvc.loadFromDb()
  126. await WIKI.configSvc.applyFlags()
  127. })
  128. }
  129. }