UNPKG

cqr-env

Version:

Have multiple env files that can be encrypted and included in version control

115 lines (94 loc) 2.89 kB
/* imports */ const fs = require('fs') const joi = require('joi') const JSON5 = require('json5') const path = require('path') /* lib */ const { get, set } = require('./lib/getset') /* modules */ const cryptor = require('./cryptor') function loadJs (data) { return eval(data) // eslint-disable-line no-eval } function loadJSON (data) { return JSON5.parse(data) } function loadRaw (data) { let lastKey /* skip multiline comments */ data = data.replace(/<!-- (.+?\r*\n*)+ -->/gm, '') data = data.replace(/\/\*(.+?\r*\n*)+\*\//gm, '') return data.split(/(?:\r?\n)+/).reduce(function (r, line) { /* skip singleline comments */ line = line.replace(/[ \t]*\/\/.*$/g, '') // this allows "x=1 // 2" line = line.replace(/[ \t]*#.*$/g, '') if (!line.length) return r // skip blank const match = line.match(/[ \t]*(.+?)[ \t]*=[ \t]*(.+?)$/) if (match) { const [m, key, value] = match try { r[key] = JSON.parse(value) } catch (e) { r[key] = value } lastKey = key } else { r[lastKey] += '\n' + line } return r }, {}) } function load (file, name, ext, encryptedFile, envvar) { let data if (encryptedFile && typeof envvar == 'string') { if (!envvar) throw new Error('Envvar not informed for encrypted env file') data = cryptor.decryptFile(file, envvar) } else { data = Buffer.from(fs.readFileSync(file)).toString() } switch (ext) { case '.js': data = loadJs(data); break case '.json': data = loadJSON(data); break default: data = { ...loadRaw(data) } } if (typeof envvar == 'object') { for (const key in envvar) { const path = key.split('.') if (path.shift() != name) continue set(data, path, cryptor.decrypt(get(data, path), envvar[key])) } } return data } function getKey (options) { if (options.envvar) { return { medium: 'var', value: options.envvar } } else if (options.pwfile) { return { medium: 'file', value: options.pwfile } } } function loader (gloob, options) { const env = {} for (const f of gloob) { const encryptedFile = (f.slice(-10) == '.encrypted') const ext = encryptedFile ? path.parse(f.replace('.env', '').replace('.encrypted', '')).ext : path.parse(f.replace('.env', '').replace('.exposed', '')).ext const name = (typeof options.name == 'string') ? options.name : path.basename(f).split('.')[0] if (options.name === false || ext == '') { const newEnv = load(f, name, ext, encryptedFile, options.envvar) if (joi.object().validate(newEnv).error) throw new Error('When "name" option is false, content must be an object') for (const k in newEnv) { env[k] = newEnv[k] } } else { env[name] = load(f, name, ext, encryptedFile, options.envvar) } } return env } module.exports = loader