blob: 442b8e4d1aea58c60a6f8610827c92953c513246 [file] [log] [blame]
/* eslint-disable no-useless-escape */
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
* Modification copyright 2020 The Go Authors. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------*/
'use strict';
import fs = require('fs');
function stripBOM(s: string): string {
if (s && s[0] === '\uFEFF') {
s = s.substr(1);
}
return s;
}
/**
* returns the environment variable collection created by parsing the given .env file.
*/
export function parseEnvFile(envFilePath: string, globalVars?: NodeJS.Dict<string>): { [key: string]: string } {
const env: { [key: string]: string } = {};
if (!envFilePath) {
return env;
}
if (!globalVars) {
globalVars = {};
}
try {
const buffer = stripBOM(fs.readFileSync(envFilePath, 'utf8'));
buffer.split('\n').forEach((line) => {
const r = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/);
if (r !== null) {
let value = r[2] || '';
if (value.length > 0 && value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') {
value = value.replace(/\\n/gm, '\n');
}
const v = value.replace(/(^['"]|['"]$)/g, '');
env[r[1]] = substituteEnvVars(v, env, globalVars!);
}
});
return env;
} catch (e) {
throw new Error(`Cannot load environment variables from file ${envFilePath}: ${e}`);
}
}
// matches ${var} where var is alphanumeric starting with a letter.
const SUBST_REGEX = /\${([a-zA-Z]\w*)?([^}\w].*)?}/g;
function substituteEnvVars(
value: string,
localVars: { [key: string]: string },
globalVars: NodeJS.Dict<string>
): string {
let invalid = false;
let replacement = value;
replacement = replacement.replace(SUBST_REGEX, (match, substName, bogus, offset, orig) => {
if (offset > 0 && orig[offset - 1] === '\\') {
return match;
}
if ((bogus && bogus !== '') || !substName || substName === '') {
invalid = true;
return match;
}
return localVars[substName] || globalVars[substName] || '';
});
if (!invalid && replacement !== value) {
value = replacement;
}
return value.replace(/\\\$/g, '$');
}
export function parseEnvFiles(
envFiles: string[] | string | undefined,
globalVars?: NodeJS.Dict<string>
): { [key: string]: string } {
const fileEnvs = [];
if (typeof envFiles === 'string') {
fileEnvs.push(parseEnvFile(envFiles, globalVars));
}
if (Array.isArray(envFiles)) {
envFiles.forEach((envFile) => {
fileEnvs.push(parseEnvFile(envFile, globalVars));
});
}
return Object.assign({}, ...fileEnvs);
}