123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- "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;
|