GSI - Employe Self Service Mobile
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

246 lines
8.9 KiB

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadFirebaseEnvs = exports.loadUserEnvs = exports.checkForDuplicateKeys = exports.writeUserEnvs = exports.hasUserEnvs = exports.parseStrict = exports.validateKey = exports.KeyValidationError = exports.parse = void 0;
const clc = require("colorette");
const fs = require("fs");
const path = require("path");
const error_1 = require("../error");
const logger_1 = require("../logger");
const utils_1 = require("../utils");
const FUNCTIONS_EMULATOR_DOTENV = ".env.local";
const RESERVED_PREFIXES = ["X_GOOGLE_", "FIREBASE_", "EXT_"];
const RESERVED_KEYS = [
"FIREBASE_CONFIG",
"CLOUD_RUNTIME_CONFIG",
"EVENTARC_CLOUD_EVENT_SOURCE",
"ENTRY_POINT",
"GCP_PROJECT",
"GCLOUD_PROJECT",
"GOOGLE_CLOUD_PROJECT",
"FUNCTION_TRIGGER_TYPE",
"FUNCTION_NAME",
"FUNCTION_MEMORY_MB",
"FUNCTION_TIMEOUT_SEC",
"FUNCTION_IDENTITY",
"FUNCTION_REGION",
"FUNCTION_TARGET",
"FUNCTION_SIGNATURE_TYPE",
"K_SERVICE",
"K_REVISION",
"PORT",
"K_CONFIGURATION",
];
const LINE_RE = new RegExp("^" +
"\\s*" +
"([\\w./]+)" +
"\\s*=[\\f\\t\\v]*" +
"(" +
"\\s*'(?:\\\\'|[^'])*'|" +
'\\s*"(?:\\\\"|[^"])*"|' +
"[^#\\r\\n]*" +
")?" +
"\\s*" +
"(?:#[^\\n]*)?" +
"$", "gms");
const ESCAPE_SEQUENCES_TO_CHARACTERS = {
"\\n": "\n",
"\\r": "\r",
"\\t": "\t",
"\\v": "\v",
"\\\\": "\\",
"\\'": "'",
'\\"': '"',
};
const ALL_ESCAPE_SEQUENCES_RE = /\\[nrtv\\'"]/g;
const CHARACTERS_TO_ESCAPE_SEQUENCES = {
"\n": "\\n",
"\r": "\\r",
"\t": "\\t",
"\v": "\\v",
"\\": "\\\\",
"'": "\\'",
'"': '\\"',
};
const ALL_ESCAPABLE_CHARACTERS_RE = /[\n\r\t\v\\'"]/g;
function parse(data) {
const envs = {};
const errors = [];
data = data.replace(/\r\n?/, "\n");
let match;
while ((match = LINE_RE.exec(data))) {
let [, k, v] = match;
v = (v || "").trim();
let quotesMatch;
if ((quotesMatch = /^(["'])(.*)\1$/ms.exec(v)) != null) {
v = quotesMatch[2];
if (quotesMatch[1] === '"') {
v = v.replace(ALL_ESCAPE_SEQUENCES_RE, (match) => ESCAPE_SEQUENCES_TO_CHARACTERS[match]);
}
}
envs[k] = v;
}
const nonmatches = data.replace(LINE_RE, "");
for (let line of nonmatches.split(/[\r\n]+/)) {
line = line.trim();
if (line.startsWith("#")) {
continue;
}
if (line.length)
errors.push(line);
}
return { envs, errors };
}
exports.parse = parse;
class KeyValidationError extends Error {
constructor(key, message) {
super(`Failed to validate key ${key}: ${message}`);
this.key = key;
this.message = message;
}
}
exports.KeyValidationError = KeyValidationError;
function validateKey(key) {
if (RESERVED_KEYS.includes(key)) {
throw new KeyValidationError(key, `Key ${key} is reserved for internal use.`);
}
if (!/^[A-Z_][A-Z0-9_]*$/.test(key)) {
throw new KeyValidationError(key, `Key ${key} must start with an uppercase ASCII letter or underscore` +
", and then consist of uppercase ASCII letters, digits, and underscores.");
}
if (RESERVED_PREFIXES.some((prefix) => key.startsWith(prefix))) {
throw new KeyValidationError(key, `Key ${key} starts with a reserved prefix (${RESERVED_PREFIXES.join(" ")})`);
}
}
exports.validateKey = validateKey;
function parseStrict(data) {
const { envs, errors } = parse(data);
if (errors.length) {
throw new error_1.FirebaseError(`Invalid dotenv file, error on lines: ${errors.join(",")}`);
}
const validationErrors = [];
for (const key of Object.keys(envs)) {
try {
validateKey(key);
}
catch (err) {
logger_1.logger.debug(`Failed to validate key ${key}: ${err}`);
if (err instanceof KeyValidationError) {
validationErrors.push(err);
}
else {
throw err;
}
}
}
if (validationErrors.length > 0) {
throw new error_1.FirebaseError("Validation failed", { children: validationErrors });
}
return envs;
}
exports.parseStrict = parseStrict;
function findEnvfiles(functionsSource, projectId, projectAlias, isEmulator) {
const files = [".env"];
files.push(`.env.${projectId}`);
if (projectAlias) {
files.push(`.env.${projectAlias}`);
}
if (isEmulator) {
files.push(FUNCTIONS_EMULATOR_DOTENV);
}
return files
.map((f) => path.join(functionsSource, f))
.filter(fs.existsSync)
.map((p) => path.basename(p));
}
function hasUserEnvs({ functionsSource, projectId, projectAlias, isEmulator, }) {
return findEnvfiles(functionsSource, projectId, projectAlias, isEmulator).length > 0;
}
exports.hasUserEnvs = hasUserEnvs;
function writeUserEnvs(toWrite, envOpts) {
if (Object.keys(toWrite).length === 0) {
return;
}
const { functionsSource, projectId, projectAlias, isEmulator } = envOpts;
const allEnvFiles = findEnvfiles(functionsSource, projectId, projectAlias, isEmulator);
const targetEnvFile = envOpts.isEmulator
? FUNCTIONS_EMULATOR_DOTENV
: `.env.${envOpts.projectId}`;
const targetEnvFileExists = allEnvFiles.includes(targetEnvFile);
if (!targetEnvFileExists) {
fs.writeFileSync(path.join(envOpts.functionsSource, targetEnvFile), "", { flag: "wx" });
(0, utils_1.logBullet)(clc.yellow(clc.bold("functions: ")) +
`Created new local file ${targetEnvFile} to store param values. We suggest explicitly adding or excluding this file from version control.`);
}
const fullEnvs = loadUserEnvs(envOpts);
const prodEnvs = isEmulator
? loadUserEnvs(Object.assign(Object.assign({}, envOpts), { isEmulator: false }))
: loadUserEnvs(envOpts);
checkForDuplicateKeys(isEmulator || false, Object.keys(toWrite), fullEnvs, prodEnvs);
for (const k of Object.keys(toWrite)) {
validateKey(k);
}
(0, utils_1.logBullet)(clc.cyan(clc.bold("functions: ")) + `Writing new parameter values to disk: ${targetEnvFile}`);
let lines = "";
for (const k of Object.keys(toWrite)) {
lines += formatUserEnvForWrite(k, toWrite[k]);
}
fs.appendFileSync(path.join(functionsSource, targetEnvFile), lines);
}
exports.writeUserEnvs = writeUserEnvs;
function checkForDuplicateKeys(isEmulator, keys, fullEnv, envsWithoutLocal) {
for (const key of keys) {
const definedInEnv = fullEnv.hasOwnProperty(key);
if (definedInEnv) {
if (envsWithoutLocal && isEmulator && envsWithoutLocal.hasOwnProperty(key)) {
(0, utils_1.logWarning)(clc.cyan(clc.yellow("functions: ")) +
`Writing parameter ${key} to emulator-specific config .env.local. This will overwrite your existing definition only when emulating.`);
continue;
}
throw new error_1.FirebaseError(`Attempted to write param-defined key ${key} to .env files, but it was already defined.`);
}
}
}
exports.checkForDuplicateKeys = checkForDuplicateKeys;
function formatUserEnvForWrite(key, value) {
const escapedValue = value.replace(ALL_ESCAPABLE_CHARACTERS_RE, (match) => CHARACTERS_TO_ESCAPE_SEQUENCES[match]);
if (escapedValue !== value) {
return `${key}="${escapedValue}"\n`;
}
return `${key}=${escapedValue}\n`;
}
function loadUserEnvs({ functionsSource, projectId, projectAlias, isEmulator, }) {
var _a;
const envFiles = findEnvfiles(functionsSource, projectId, projectAlias, isEmulator);
if (envFiles.length === 0) {
return {};
}
if (projectAlias) {
if (envFiles.includes(`.env.${projectId}`) && envFiles.includes(`.env.${projectAlias}`)) {
throw new error_1.FirebaseError(`Can't have both dotenv files with projectId (env.${projectId}) ` +
`and projectAlias (.env.${projectAlias}) as extensions.`);
}
}
let envs = {};
for (const f of envFiles) {
try {
const data = fs.readFileSync(path.join(functionsSource, f), "utf8");
envs = Object.assign(Object.assign({}, envs), parseStrict(data));
}
catch (err) {
throw new error_1.FirebaseError(`Failed to load environment variables from ${f}.`, {
exit: 2,
children: ((_a = err.children) === null || _a === void 0 ? void 0 : _a.length) > 0 ? err.children : [err],
});
}
}
(0, utils_1.logBullet)(clc.cyan(clc.bold("functions: ")) + `Loaded environment variables from ${envFiles.join(", ")}.`);
return envs;
}
exports.loadUserEnvs = loadUserEnvs;
function loadFirebaseEnvs(firebaseConfig, projectId) {
return {
FIREBASE_CONFIG: JSON.stringify(firebaseConfig),
GCLOUD_PROJECT: projectId,
};
}
exports.loadFirebaseEnvs = loadFirebaseEnvs;