Initial code test
This commit is contained in:
commit
d4fae15f5c
1696 files changed
+271223
No files matched your search
+98
@@ -0,0 +1,98 @@
|
||||
'use strict'
|
||||
|
||||
function _resolveEscapeSequences (value) {
|
||||
return value.replace(/\\\$/g, '$')
|
||||
}
|
||||
|
||||
function expandValue (value, processEnv, runningParsed) {
|
||||
const env = { ...runningParsed, ...processEnv } // process.env wins
|
||||
|
||||
const regex = /(?<!\\)\${([^{}]+)}|(?<!\\)\$([A-Za-z_][A-Za-z0-9_]*)/g
|
||||
|
||||
let result = value
|
||||
let match
|
||||
const seen = new Set() // self-referential checker
|
||||
|
||||
while ((match = regex.exec(result)) !== null) {
|
||||
seen.add(result)
|
||||
|
||||
const [template, bracedExpression, unbracedExpression] = match
|
||||
const expression = bracedExpression || unbracedExpression
|
||||
|
||||
// match the operators `:+`, `+`, `:-`, and `-`
|
||||
const opRegex = /(:\+|\+|:-|-)/
|
||||
// find first match
|
||||
const opMatch = expression.match(opRegex)
|
||||
const splitter = opMatch ? opMatch[0] : null
|
||||
|
||||
const r = expression.split(splitter)
|
||||
|
||||
let defaultValue
|
||||
let value
|
||||
|
||||
const key = r.shift()
|
||||
|
||||
if ([':+', '+'].includes(splitter)) {
|
||||
defaultValue = env[key] ? r.join(splitter) : ''
|
||||
value = null
|
||||
} else {
|
||||
defaultValue = r.join(splitter)
|
||||
value = env[key]
|
||||
}
|
||||
|
||||
if (value) {
|
||||
// self-referential check
|
||||
if (seen.has(value)) {
|
||||
result = result.replace(template, defaultValue)
|
||||
} else {
|
||||
result = result.replace(template, value)
|
||||
}
|
||||
} else {
|
||||
result = result.replace(template, defaultValue)
|
||||
}
|
||||
|
||||
// if the result equaled what was in process.env and runningParsed then stop expanding
|
||||
if (result === runningParsed[key]) {
|
||||
break
|
||||
}
|
||||
|
||||
regex.lastIndex = 0 // reset regex search position to re-evaluate after each replacement
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
function expand (options) {
|
||||
// for use with progressive expansion
|
||||
const runningParsed = {}
|
||||
|
||||
let processEnv = process.env
|
||||
if (options && options.processEnv != null) {
|
||||
processEnv = options.processEnv
|
||||
}
|
||||
|
||||
// dotenv.config() ran before this so the assumption is process.env has already been set
|
||||
for (const key in options.parsed) {
|
||||
let value = options.parsed[key]
|
||||
|
||||
// short-circuit scenario: process.env was already set prior to the file value
|
||||
if (processEnv[key] && processEnv[key] !== value) {
|
||||
value = processEnv[key]
|
||||
} else {
|
||||
value = expandValue(value, processEnv, runningParsed)
|
||||
}
|
||||
|
||||
options.parsed[key] = _resolveEscapeSequences(value)
|
||||
|
||||
// for use with progressive expansion
|
||||
runningParsed[key] = _resolveEscapeSequences(value)
|
||||
}
|
||||
|
||||
for (const processKey in options.parsed) {
|
||||
processEnv[processKey] = options.parsed[processKey]
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
module.exports.expand = expand
|
||||
Reference in new issue
Block a user