firebase-tools
Version:
Command-Line Interface for Firebase
241 lines (240 loc) • 10.2 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.EmulatorLogger = exports.Verbosity = void 0;
const clc = require("colorette");
const utils = require("../utils");
const logger_1 = require("../logger");
const types_1 = require("./types");
const utils_1 = require("../utils");
const TYPE_VERBOSITY = {
DEBUG: 0,
INFO: 1,
BULLET: 1,
SUCCESS: 1,
USER: 2,
WARN: 2,
WARN_ONCE: 2,
ERROR: 2,
};
var Verbosity;
(function (Verbosity) {
Verbosity[Verbosity["DEBUG"] = 0] = "DEBUG";
Verbosity[Verbosity["INFO"] = 1] = "INFO";
Verbosity[Verbosity["QUIET"] = 2] = "QUIET";
Verbosity[Verbosity["SILENT"] = 3] = "SILENT";
})(Verbosity = exports.Verbosity || (exports.Verbosity = {}));
class EmulatorLogger {
constructor(name, data = {}) {
this.name = name;
this.data = data;
}
static setVerbosity(verbosity) {
EmulatorLogger.verbosity = verbosity;
}
static forEmulator(emulator) {
return new EmulatorLogger(emulator, {
metadata: {
emulator: {
name: emulator,
},
},
});
}
static forFunction(functionName, extensionLogInfo) {
return new EmulatorLogger(types_1.Emulators.FUNCTIONS, {
metadata: {
emulator: {
name: types_1.Emulators.FUNCTIONS,
},
function: {
name: functionName,
},
extension: extensionLogInfo,
},
});
}
static forExtension(extensionLogInfo) {
return new EmulatorLogger(types_1.Emulators.EXTENSIONS, {
metadata: {
emulator: {
name: types_1.Emulators.EXTENSIONS,
},
extension: extensionLogInfo,
},
});
}
log(type, text, data) {
if (!data) {
data = this.data;
}
if (EmulatorLogger.shouldSupress(type)) {
logger_1.logger.debug(`${type}: ${text}`);
return;
}
const mergedData = Object.assign(Object.assign({}, data), { metadata: Object.assign(Object.assign({}, data.metadata), { message: text }) });
switch (type) {
case "DEBUG":
logger_1.logger.debug(text, mergedData);
break;
case "INFO":
logger_1.logger.info(text, mergedData);
break;
case "USER":
logger_1.logger.info(text, mergedData);
break;
case "BULLET":
utils.logBullet(text, "info", mergedData);
break;
case "WARN":
utils.logWarning(text, "warn", mergedData);
break;
case "WARN_ONCE":
if (!EmulatorLogger.warnOnceCache.has(text)) {
utils.logWarning(text, "warn", mergedData);
EmulatorLogger.warnOnceCache.add(text);
}
break;
case "SUCCESS":
utils.logSuccess(text, "info", mergedData);
break;
case "ERROR":
utils.logBullet(text, "error", mergedData);
break;
}
}
handleRuntimeLog(log, ignore = []) {
if (ignore.includes(log.level)) {
return;
}
switch (log.level) {
case "SYSTEM":
this.handleSystemLog(log);
break;
case "USER":
this.log("USER", `${clc.blackBright("> ")} ${log.text}`, Object.assign({ user: (0, utils_1.tryParse)(log.text) }, this.data));
break;
case "DEBUG":
if (log.data && Object.keys(log.data).length > 0) {
this.log("DEBUG", `[${log.type}] ${log.text} ${JSON.stringify(log.data)}`);
}
else {
this.log("DEBUG", `[${log.type}] ${log.text}`);
}
break;
case "INFO":
this.logLabeled("BULLET", "functions", log.text);
break;
case "WARN":
this.logLabeled("WARN", "functions", log.text);
break;
case "WARN_ONCE":
this.logLabeled("WARN_ONCE", "functions", log.text);
break;
case "FATAL":
this.logLabeled("WARN", "functions", log.text);
break;
default:
this.log("INFO", `${log.level}: ${log.text}`);
break;
}
}
handleSystemLog(systemLog) {
switch (systemLog.type) {
case "runtime-status":
if (systemLog.text === "killed") {
this.log("WARN", `Your function was killed because it raised an unhandled error.`);
}
break;
case "googleapis-network-access":
this.log("WARN", `Google API requested!\n - URL: "${systemLog.data.href}"\n - Be careful, this may be a production service.`);
break;
case "unidentified-network-access":
this.log("WARN", `External network resource requested!\n - URL: "${systemLog.data.href}"\n - Be careful, this may be a production service.`);
break;
case "functions-config-missing-value":
this.log("WARN_ONCE", `It looks like you're trying to access functions.config().${systemLog.data.key} but there is no value there. You can learn more about setting up config here: https://firebase.google.com/docs/functions/local-emulator`);
break;
case "non-default-admin-app-used":
this.log("WARN", `Non-default "firebase-admin" instance created!\n ` +
`- This instance will *not* be mocked and will access production resources.`);
break;
case "missing-module":
this.log("WARN", `The Cloud Functions emulator requires the module "${systemLog.data.name}" to be installed as a ${systemLog.data.isDev ? "development dependency" : "dependency"}. To fix this, run "npm install ${systemLog.data.isDev ? "--save-dev" : "--save"} ${systemLog.data.name}" in your functions directory.`);
break;
case "uninstalled-module":
this.log("WARN", `The Cloud Functions emulator requires the module "${systemLog.data.name}" to be installed. This package is in your package.json, but it's not available. \
You probably need to run "npm install" in your functions directory.`);
break;
case "out-of-date-module":
this.log("WARN", `The Cloud Functions emulator requires the module "${systemLog.data.name}" to be version >${systemLog.data.minVersion} so your version is too old. \
You can probably fix this by running "npm install ${systemLog.data.name}@latest" in your functions directory.`);
break;
case "missing-package-json":
this.log("WARN", `The Cloud Functions directory you specified does not have a "package.json" file, so we can't load it.`);
break;
case "function-code-resolution-failed":
this.log("WARN", systemLog.data.error);
const helper = ["We were unable to load your functions code. (see above)"];
if (systemLog.data.isPotentially.wrong_directory) {
helper.push(` - There is no "package.json" file in your functions directory.`);
}
if (systemLog.data.isPotentially.typescript) {
helper.push(" - It appears your code is written in Typescript, which must be compiled before emulation.");
}
if (systemLog.data.isPotentially.uncompiled) {
helper.push(` - You may be able to run "npm run build" in your functions directory to resolve this.`);
}
utils.logWarning(helper.join("\n"), "warn", this.data);
break;
case "function-runtimeconfig-json-invalid":
this.log("WARN", "Found .runtimeconfig.json but the JSON format is invalid.");
break;
default:
}
}
logLabeled(type, labelOrText, text) {
let label = labelOrText;
if (text === undefined) {
text = label;
label = this.name;
}
if (EmulatorLogger.shouldSupress(type)) {
logger_1.logger.debug(`[${label}] ${text}`);
return;
}
const mergedData = Object.assign(Object.assign({}, this.data), { metadata: Object.assign(Object.assign({}, this.data.metadata), { message: text }) });
switch (type) {
case "DEBUG":
logger_1.logger.debug(`[${label}] ${text}`);
break;
case "BULLET":
utils.logLabeledBullet(label, text, "info", mergedData);
break;
case "INFO":
utils.logLabeledBullet(label, text, "info", mergedData);
break;
case "SUCCESS":
utils.logLabeledSuccess(label, text, "info", mergedData);
break;
case "WARN":
utils.logLabeledWarning(label, text, "warn", mergedData);
break;
case "WARN_ONCE":
if (!EmulatorLogger.warnOnceCache.has(text)) {
utils.logLabeledWarning(label, text, "warn", mergedData);
EmulatorLogger.warnOnceCache.add(text);
}
break;
case "ERROR":
utils.logLabeledError(label, text, "error", mergedData);
break;
}
}
static shouldSupress(type) {
const typeVerbosity = TYPE_VERBOSITY[type];
return EmulatorLogger.verbosity > typeVerbosity;
}
}
exports.EmulatorLogger = EmulatorLogger;
EmulatorLogger.verbosity = Verbosity.DEBUG;
EmulatorLogger.warnOnceCache = new Set();
;