diff --git a/src/commands/dev/exec.js b/src/commands/dev/exec.js index cc33754a01f..80434a7cf64 100644 --- a/src/commands/dev/exec.js +++ b/src/commands/dev/exec.js @@ -1,4 +1,6 @@ +const path = require('path') const execa = require('execa') +const chalk = require('chalk') const Command = require('../../utils/command') const { // NETLIFYDEV, @@ -6,6 +8,7 @@ const { // NETLIFYDEVWARN, NETLIFYDEVERR } = require('../../utils/logo') +const { getEnvSettings } = require('../../utils/env') class ExecCommand extends Command { async run() { @@ -20,6 +23,16 @@ class ExecCommand extends Command { `${NETLIFYDEVERR} No Site ID detected. You probably forgot to run \`netlify link\` or \`netlify init\`. ` ) } + + const envSettings = await getEnvSettings(site.root) + if (envSettings.file) { + console.log( + `${NETLIFYDEVLOG} Overriding the following env variables with ${chalk.blue(path.relative(site.root, envSettings.file))} file:`, + chalk.yellow(Object.keys(envSettings.vars)) + ) + Object.entries(envSettings.vars).forEach(([key, val]) => (process.env[key] = val)) + } + execa(this.argv[0], this.argv.slice(1), { env: process.env, stdio: 'inherit' @@ -37,7 +50,7 @@ ExecCommand.description = `Exec command Runs a command within the netlify dev environment, e.g. with env variables from any installed addons ` -ExecCommand.examples = ['$ netlify exec npm run bootstrap'] +ExecCommand.examples = ['$ netlify dev:exec npm run bootstrap'] ExecCommand.strict = false ExecCommand.parse = false diff --git a/src/commands/dev/index.js b/src/commands/dev/index.js index e731ab8daab..ec0b2e9f808 100644 --- a/src/commands/dev/index.js +++ b/src/commands/dev/index.js @@ -22,16 +22,14 @@ const Command = require('../../utils/command') const chalk = require('chalk') const jwtDecode = require('jwt-decode') const open = require('open') -const dotenv = require('dotenv') const { NETLIFYDEV, NETLIFYDEVLOG, NETLIFYDEVWARN, NETLIFYDEVERR } = require('../../utils/logo') const boxen = require('boxen') const { createTunnel, connectTunnel } = require('../../utils/live-tunnel') const { createRewriter } = require('../../utils/rules-proxy') const { onChanges } = require('../../utils/rules-proxy') const { parseHeadersFile, objectForPath } = require('../../utils/headers') -const { getEnvFile } = require('../../utils/env') +const { getEnvSettings } = require('../../utils/env') -const readFile = util.promisify(fs.readFile) const stat = util.promisify(fs.stat) function isInternal(url) { @@ -411,14 +409,13 @@ class DevCommand extends Command { process.env.NETLIFY_DEV = 'true' // Override env variables with .env file - const envFile = await getEnvFile(site.root) - if (envFile) { - const vars = dotenv.parse(await readFile(envFile)) || {} + const envSettings = await getEnvSettings(site.root) + if (envSettings.file) { console.log( - `${NETLIFYDEVLOG} Overriding the following env variables with ${chalk.blue(path.relative(site.root, envFile))} file:`, - chalk.yellow(Object.keys(vars)) + `${NETLIFYDEVLOG} Overriding the following env variables with ${chalk.blue(path.relative(site.root, envSettings.file))} file:`, + chalk.yellow(Object.keys(envSettings.vars)) ) - Object.entries(vars).forEach(([key, val]) => (process.env[key] = val)) + Object.entries(envSettings.vars).forEach(([key, val]) => (process.env[key] = val)) } let settings = await serverSettings(devConfig, flags, site.root, this.log) diff --git a/src/function-builder-detectors/netlify-lambda.js b/src/function-builder-detectors/netlify-lambda.js index 066603ea6cd..f685a5944f3 100644 --- a/src/function-builder-detectors/netlify-lambda.js +++ b/src/function-builder-detectors/netlify-lambda.js @@ -1,10 +1,6 @@ -const { existsSync, readFileSync, readFile: readFileAsync } = require('fs') -const util = require('util') +const { existsSync, readFileSync } = require('fs') const execa = require('execa') -const dotenv = require('dotenv') -const { getEnvFile } = require('../utils/env') - -const readFile = util.promisify(readFileAsync) +const { getEnvSettings } = require('../utils/env') module.exports = async function(projectDir) { if (!existsSync('package.json')) { @@ -31,9 +27,9 @@ module.exports = async function(projectDir) { } let envConfig = {} - const envFile = await getEnvFile(projectDir) - if (envFile) { - envConfig = dotenv.parse(await readFile(envFile)) + const envSettings = await getEnvSettings(projectDir) + if (envSettings.file) { + envConfig = envSettings.vars } if (settings.npmScript) { diff --git a/src/utils/env.js b/src/utils/env.js index e71ef1f34f7..4f543b034ac 100644 --- a/src/utils/env.js +++ b/src/utils/env.js @@ -1,25 +1,31 @@ const path = require('path') const fs = require('fs') const { promisify } = require('util') +const dotenv = require('dotenv') const fileStat = promisify(fs.stat) +const readFile = promisify(fs.readFile) -async function getEnvFile(projectDir) { +async function getEnvSettings(projectDir) { const envDevelopmentFile = path.resolve(projectDir, '.env.development') const envFile = path.resolve(projectDir, '.env') + const settings = {} + try { - if ((await fileStat(envDevelopmentFile)).isFile()) return envDevelopmentFile + if ((await fileStat(envFile)).isFile()) settings.file = envFile } catch (err) { // nothing } try { - if ((await fileStat(envFile)).isFile()) return envFile + if ((await fileStat(envDevelopmentFile)).isFile()) settings.file = envDevelopmentFile } catch (err) { // nothing } - return undefined + if (settings.file) settings.vars = dotenv.parse(await readFile(settings.file)) || {} + + return settings } -module.exports.getEnvFile = getEnvFile +module.exports.getEnvSettings = getEnvSettings diff --git a/src/utils/env.test.js b/src/utils/env.test.js index 5ec6995defb..2e8dcf64fdb 100644 --- a/src/utils/env.test.js +++ b/src/utils/env.test.js @@ -1,22 +1,31 @@ const test = require('ava') const path = require('path') -const { getEnvFile } = require('./env') +const { getEnvSettings } = require('./env') const contextSite = path.join(__dirname, '..', '..', 'tests', 'context-site') const dummySite = path.join(__dirname, '..', '..', 'tests', 'dummy-site') const craSite = path.join(__dirname, '..', '..', 'tests', 'site-cra') test('no .env files', async t => { - const f = await getEnvFile(contextSite) - t.is(f, undefined) + const vars = await getEnvSettings(contextSite) + t.deepEqual(vars, {}) }) test('.env.development file', async t => { - const f = await getEnvFile(dummySite) - t.is(f, path.resolve(dummySite, '.env.development')) + const vars = await getEnvSettings(dummySite) + t.deepEqual(vars, { + file: path.resolve(dummySite, '.env.development'), + vars: { + EASY_VAR: 'true', + DUMMY_VAR: 'false', + }, + }) }) test('.env file', async t => { - const f = await getEnvFile(craSite) - t.is(f, path.resolve(craSite, '.env')) + const vars = await getEnvSettings(craSite) + t.deepEqual(vars, { + file: path.resolve(craSite, '.env'), + vars: {}, + }) }) diff --git a/tests/dummy-site/.env b/tests/dummy-site/.env deleted file mode 100644 index e69de29bb2d..00000000000