UNPKG

sqlpad

Version:

Web app for writing and running SQL queries and visualizing the results. Supports Postgres, MySQL, SQL Server, Crate and Vertica.

213 lines (189 loc) 6.43 kB
/* ConfigItem behaves a lot differently than other models All config item data is cached in memory. Config items are defined in a toml file Config item values come from all kinds of sources: - Environment variables - cli flags - saved cli flags - the config nedb database That last source it tricky because the nedb database depends on config values to load */ var fs = require('fs') var path = require('path') var toml = require('toml') var _ = require('lodash') var minimist = require('minimist') // various file paths for later var userHome = process.platform === 'win32' ? process.env.USERPROFILE : process.env.HOME var savedCliFilePath = path.join(userHome, '.sqlpadrc') var defaultDbPath = path.join(userHome, 'sqlpad/db') // toml config item definitions var tomlFile = fs.readFileSync( path.join(__dirname, '/../resources/config-items.toml'), { encoding: 'utf8' } ) var parsedToml = toml.parse(tomlFile) var configItemDefinitions = parsedToml.configItems // parse command line args var argv = minimist(process.argv.slice(2)) // if saved cli file exists, read it var savedCli = {} if (fs.existsSync(savedCliFilePath)) { savedCli = JSON.parse(fs.readFileSync(savedCliFilePath, { encoding: 'utf8' })) } // in-memory store of items var configItems = [] var ConfigItem = function(data) { var self = this this.interface = data.interface // env or ui this.key = data.key this.cliFlag = data.cliFlag this.envVar = data.envVar this.default = data.default this.example = data.example this.options = data.options this.sensitive = data.sensitive || false this.description = data.description this.label = data.label this.envValue = null this.cliValue = null this.savedCliValue = null this.dbValue = null this.effectiveValue = null this.effectiveValueSource = null // assign values as appropriate based on what is available // special exception. if item is dbPath set default to user home if (this.key === 'dbPath') this.default = defaultDbPath // populate env value if env var present if (this.envVar && process.env[this.envVar]) { this.envValue = process.env[this.envVar] } // populate value from saved cli file // NOTE: there could be multiple cli flags defined if (this.cliFlag && Array.isArray(this.cliFlag)) { this.cliFlag.forEach(function(flag) { if (savedCli[flag] != null) { self.savedCliValue = savedCli[flag] } }) } else if (this.cliFlag && savedCli[this.cliFlag] != null) { this.savedCliValue = savedCli[this.cliFlag] } // populate value from cli flag // NOTE: there could be multiple cli flags defined if (this.cliFlag && Array.isArray(this.cliFlag)) { this.cliFlag.forEach(function(flag) { if (argv[flag] != null) { self.cliValue = argv[flag] } }) } else if (this.cliFlag && argv[this.cliFlag] != null) { this.cliValue = argv[this.cliFlag] } // if this config item is for the database path // we should resolve it to ensure it is ready for use if (this.key === 'dbPath') { if (this.envValue) this.envValue = path.resolve(this.envValue) if (this.cliValue) this.cliValue = path.resolve(this.cliValue) if (this.savedCliValue) { this.savedCliValue = path.resolve(this.savedCliValue) } } this.computeEffectiveValue() } ConfigItem.prototype.computeEffectiveValue = function() { if (this.cliValue != null) { this.effectiveValue = this.cliValue this.effectiveValueSource = 'cli' } else if (this.savedCliValue != null) { this.effectiveValue = this.savedCliValue this.effectiveValueSource = 'saved cli' } else if (this.envValue != null) { this.effectiveValue = this.envValue this.effectiveValueSource = 'env' } else if (this.dbValue != null) { this.effectiveValue = this.dbValue this.effectiveValueSource = 'db' } else if (this.default != null) { this.effectiveValue = this.default this.effectiveValueSource = 'default' } // It is possible that some of our boolean values are stored as text // for consumption convenience, those strings should be turned to actual booleans var valueProps = [ 'default', 'savedCliValue', 'cliValue', 'envValue', 'dbValue', 'effectiveValue' ] valueProps.forEach( function(valueProp) { if (typeof this[valueProp] === 'string') { if (this[valueProp].toLowerCase() === 'true') { this[valueProp] = true } else if (this[valueProp].toLowerCase() === 'false') { this[valueProp] = false } } }.bind(this) ) } ConfigItem.prototype.setDbValue = function(value) { this.dbValue = value this.computeEffectiveValue() } // Saves a config value to the database // Here we are throwing any errors that may come up. // The only time this should be used is for saving values from the ui // and the UI is built using the Config Item toml file // If this is trying to save a value not in that file it is being misused ConfigItem.prototype.save = function(callback) { var self = this if (this.interface !== 'ui') { throw new Error( 'Config Item ' + this.key + ' must use ui interface to be saved to db' ) } // get database and save the value there var db = require('../lib/db.js') db.config.findOne({ key: this.key }).exec(function(err, doc) { if (err) return callback(err) if (doc) { doc.value = self.dbValue doc.modifiedDate = new Date() db.config.update({ _id: doc._id }, doc, {}, function(err) { callback(err, self) }) } else { var newConfigValue = { key: self.key, value: self.dbValue, createdDate: new Date(), modifiedDate: new Date() } db.config.insert(newConfigValue, function(err) { callback(err, self) }) } }) } /* Loop through config item definitions and create config items stored in memory ============================================================================== */ configItemDefinitions.forEach(function(itemDefinition) { var configItem = new ConfigItem(itemDefinition) configItems.push(configItem) }) /* Query methods ============================================================================== */ ConfigItem.findOneByKey = function(key) { return _.find(configItems, { key: key }) } ConfigItem.findAll = function() { return configItems } module.exports = ConfigItem