main.js 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. 'use strict'
  2. // like String.prototype.search but returns the last index
  3. function _searchLast (str, rgx) {
  4. const matches = Array.from(str.matchAll(rgx))
  5. return matches.length > 0 ? matches.slice(-1)[0].index : -1
  6. }
  7. function _interpolate (envValue, environment, config) {
  8. // find the last unescaped dollar sign in the
  9. // value so that we can evaluate it
  10. const lastUnescapedDollarSignIndex = _searchLast(envValue, /(?!(?<=\\))\$/g)
  11. // If we couldn't match any unescaped dollar sign
  12. // let's return the string as is
  13. if (lastUnescapedDollarSignIndex === -1) return envValue
  14. // This is the right-most group of variables in the string
  15. const rightMostGroup = envValue.slice(lastUnescapedDollarSignIndex)
  16. /**
  17. * This finds the inner most variable/group divided
  18. * by variable name and default value (if present)
  19. * (
  20. * (?!(?<=\\))\$ // only match dollar signs that are not escaped
  21. * {? // optional opening curly brace
  22. * ([\w]+) // match the variable name
  23. * (?::-([^}\\]*))? // match an optional default value
  24. * }? // optional closing curly brace
  25. * )
  26. */
  27. const matchGroup = /((?!(?<=\\))\${?([\w]+)(?::-([^}\\]*))?}?)/
  28. const match = rightMostGroup.match(matchGroup)
  29. if (match != null) {
  30. const [, group, variableName, defaultValue] = match
  31. return _interpolate(
  32. envValue.replace(
  33. group,
  34. environment[variableName] ||
  35. defaultValue ||
  36. config.parsed[variableName] ||
  37. ''
  38. ),
  39. environment,
  40. config
  41. )
  42. }
  43. return envValue
  44. }
  45. function _resolveEscapeSequences (value) {
  46. return value.replace(/\\\$/g, '$')
  47. }
  48. function expand (config) {
  49. // if ignoring process.env, use a blank object
  50. const environment = config.ignoreProcessEnv ? {} : process.env
  51. for (const configKey in config.parsed) {
  52. const value = Object.prototype.hasOwnProperty.call(environment, configKey)
  53. ? environment[configKey]
  54. : config.parsed[configKey]
  55. config.parsed[configKey] = _resolveEscapeSequences(
  56. _interpolate(value, environment, config)
  57. )
  58. }
  59. for (const processKey in config.parsed) {
  60. environment[processKey] = config.parsed[processKey]
  61. }
  62. return config
  63. }
  64. module.exports.expand = expand