-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ Replace dotenv with custom implementation (#426)
* ✨ Replace dotenv with custom implementation * ✅ Remove dotenv reference
- Loading branch information
Wil Wilsman
authored
Jul 19, 2021
1 parent
2ee7898
commit 6b98230
Showing
5 changed files
with
114 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,8 +20,5 @@ | |
}, | ||
"devDependencies": { | ||
"mock-require": "^3.0.3" | ||
}, | ||
"dependencies": { | ||
"dotenv": "^10.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,76 @@ | ||
const dotenv = require('dotenv'); | ||
import fs from 'fs'; | ||
|
||
// mimic dotenv-rails file hierarchy | ||
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use | ||
export function config() { | ||
let { | ||
NODE_ENV: env, | ||
PERCY_DISABLE_DOTENV: disable | ||
} = process.env; | ||
// Heavily inspired by dotenv-rails | ||
// https://github.com/bkeepers/dotenv | ||
|
||
// matches each valid line of a dotenv file | ||
const LINE_REG = new RegExp([ | ||
// key with optional export | ||
'^\\s*(?:export\\s+)?(?<key>[\\w.]+)', | ||
// separator | ||
'(?:\\s*=\\s*?|:\\s+?)(?:', | ||
// single quoted value or | ||
'\\s*(?<squote>\')(?<sval>(?:\\\\\'|[^\'])*)\'|', | ||
// double quoted value or | ||
'\\s*(?<dquote>")(?<dval>(?:\\\\"|[^"])*)"|', | ||
// unquoted value | ||
'(?<uval>[^#\\r\\n]+))?', | ||
// optional comment | ||
'\\s*(?:#.*)?$' | ||
].join(''), 'gm'); | ||
|
||
// interpolate variable substitutions | ||
const INTERPOLATE_REG = /(.?)(\${?([a-zA-Z0-9_]+)?}?)/g; | ||
// expand newlines | ||
const EXPAND_CRLF_REG = /\\(?:(r)|n)/g; | ||
// unescape characters | ||
const UNESC_CHAR_REG = /\\([^$])/g; | ||
|
||
export function load() { | ||
// don't load dotenv files when disabled | ||
if (disable) return; | ||
if (process.env.PERCY_DISABLE_DOTENV) return; | ||
let { NODE_ENV } = process.env; | ||
|
||
// dotenv filepaths ordered by priority | ||
let paths = [ | ||
env && `.env.${env}.local`, | ||
// .env.local is not loaded in test environments | ||
env === 'test' ? null : '.env.local', | ||
env && `.env.${env}`, | ||
NODE_ENV && `.env.${NODE_ENV}.local`, | ||
NODE_ENV !== 'test' && '.env.local', | ||
NODE_ENV && `.env.${NODE_ENV}`, | ||
'.env' | ||
].filter(Boolean); | ||
]; | ||
|
||
// load each dotenv file synchronously | ||
for (let path of paths) { | ||
dotenv.config({ path }); | ||
try { | ||
let src = fs.readFileSync(path, { encoding: 'utf-8' }); | ||
|
||
// iterate over each matching line | ||
for (let { groups: match } of src.matchAll(LINE_REG)) { | ||
let value = match.sval ?? match.dval ?? match.uval ?? ''; | ||
|
||
// if double quoted, expand newlines | ||
if (match.dquote) { | ||
value = value.replace(EXPAND_CRLF_REG, (_, r) => r ? '\r' : '\n'); | ||
} | ||
|
||
// unescape characters | ||
value = value.replace(UNESC_CHAR_REG, '$1'); | ||
|
||
// if not single quoted, interpolate substitutions | ||
if (!match.squote) { | ||
value = value.replace(INTERPOLATE_REG, (_, pre, ref, key) => { | ||
if (pre === '\\') return ref; // escaped reference | ||
return pre + (process.env[key] ?? ''); | ||
}); | ||
} | ||
|
||
// set process.env if not already | ||
if (!Object.prototype.hasOwnProperty.call(process.env, match.key)) { | ||
process.env[match.key] = value; | ||
} | ||
} | ||
} catch (e) { | ||
// silent error | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
export { default } from './environment'; | ||
require('./dotenv').config(); | ||
require('./dotenv').load(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters