No Description
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.

emulatorLogger.js 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.EmulatorLogger = exports.Verbosity = void 0;
  4. const clc = require("colorette");
  5. const utils = require("../utils");
  6. const logger_1 = require("../logger");
  7. const types_1 = require("./types");
  8. const utils_1 = require("../utils");
  9. const TYPE_VERBOSITY = {
  10. DEBUG: 0,
  11. INFO: 1,
  12. BULLET: 1,
  13. SUCCESS: 1,
  14. USER: 2,
  15. WARN: 2,
  16. WARN_ONCE: 2,
  17. ERROR: 2,
  18. };
  19. var Verbosity;
  20. (function (Verbosity) {
  21. Verbosity[Verbosity["DEBUG"] = 0] = "DEBUG";
  22. Verbosity[Verbosity["INFO"] = 1] = "INFO";
  23. Verbosity[Verbosity["QUIET"] = 2] = "QUIET";
  24. })(Verbosity = exports.Verbosity || (exports.Verbosity = {}));
  25. class EmulatorLogger {
  26. constructor(name, data = {}) {
  27. this.name = name;
  28. this.data = data;
  29. }
  30. static forEmulator(emulator) {
  31. return new EmulatorLogger(emulator, {
  32. metadata: {
  33. emulator: {
  34. name: emulator,
  35. },
  36. },
  37. });
  38. }
  39. static forFunction(functionName, extensionLogInfo) {
  40. return new EmulatorLogger(types_1.Emulators.FUNCTIONS, {
  41. metadata: {
  42. emulator: {
  43. name: types_1.Emulators.FUNCTIONS,
  44. },
  45. function: {
  46. name: functionName,
  47. },
  48. extension: extensionLogInfo,
  49. },
  50. });
  51. }
  52. static forExtension(extensionLogInfo) {
  53. return new EmulatorLogger(types_1.Emulators.EXTENSIONS, {
  54. metadata: {
  55. emulator: {
  56. name: types_1.Emulators.EXTENSIONS,
  57. },
  58. extension: extensionLogInfo,
  59. },
  60. });
  61. }
  62. log(type, text, data) {
  63. if (!data) {
  64. data = this.data;
  65. }
  66. if (EmulatorLogger.shouldSupress(type)) {
  67. logger_1.logger.debug(`${type}: ${text}`);
  68. return;
  69. }
  70. const mergedData = Object.assign(Object.assign({}, data), { metadata: Object.assign(Object.assign({}, data.metadata), { message: text }) });
  71. switch (type) {
  72. case "DEBUG":
  73. logger_1.logger.debug(text, mergedData);
  74. break;
  75. case "INFO":
  76. logger_1.logger.info(text, mergedData);
  77. break;
  78. case "USER":
  79. logger_1.logger.info(text, mergedData);
  80. break;
  81. case "BULLET":
  82. utils.logBullet(text, "info", mergedData);
  83. break;
  84. case "WARN":
  85. utils.logWarning(text, "warn", mergedData);
  86. break;
  87. case "WARN_ONCE":
  88. if (!EmulatorLogger.warnOnceCache.has(text)) {
  89. utils.logWarning(text, "warn", mergedData);
  90. EmulatorLogger.warnOnceCache.add(text);
  91. }
  92. break;
  93. case "SUCCESS":
  94. utils.logSuccess(text, "info", mergedData);
  95. break;
  96. case "ERROR":
  97. utils.logBullet(text, "error", mergedData);
  98. break;
  99. }
  100. }
  101. handleRuntimeLog(log, ignore = []) {
  102. if (ignore.includes(log.level)) {
  103. return;
  104. }
  105. switch (log.level) {
  106. case "SYSTEM":
  107. this.handleSystemLog(log);
  108. break;
  109. case "USER":
  110. this.log("USER", `${clc.blackBright("> ")} ${log.text}`, Object.assign({ user: (0, utils_1.tryParse)(log.text) }, this.data));
  111. break;
  112. case "DEBUG":
  113. if (log.data && Object.keys(log.data).length > 0) {
  114. this.log("DEBUG", `[${log.type}] ${log.text} ${JSON.stringify(log.data)}`);
  115. }
  116. else {
  117. this.log("DEBUG", `[${log.type}] ${log.text}`);
  118. }
  119. break;
  120. case "INFO":
  121. this.logLabeled("BULLET", "functions", log.text);
  122. break;
  123. case "WARN":
  124. this.logLabeled("WARN", "functions", log.text);
  125. break;
  126. case "WARN_ONCE":
  127. this.logLabeled("WARN_ONCE", "functions", log.text);
  128. break;
  129. case "FATAL":
  130. this.logLabeled("WARN", "functions", log.text);
  131. break;
  132. default:
  133. this.log("INFO", `${log.level}: ${log.text}`);
  134. break;
  135. }
  136. }
  137. handleSystemLog(systemLog) {
  138. switch (systemLog.type) {
  139. case "runtime-status":
  140. if (systemLog.text === "killed") {
  141. this.log("WARN", `Your function was killed because it raised an unhandled error.`);
  142. }
  143. break;
  144. case "googleapis-network-access":
  145. this.log("WARN", `Google API requested!\n - URL: "${systemLog.data.href}"\n - Be careful, this may be a production service.`);
  146. break;
  147. case "unidentified-network-access":
  148. this.log("WARN", `External network resource requested!\n - URL: "${systemLog.data.href}"\n - Be careful, this may be a production service.`);
  149. break;
  150. case "functions-config-missing-value":
  151. 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`);
  152. break;
  153. case "non-default-admin-app-used":
  154. this.log("WARN", `Non-default "firebase-admin" instance created!\n ` +
  155. `- This instance will *not* be mocked and will access production resources.`);
  156. break;
  157. case "missing-module":
  158. 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.`);
  159. break;
  160. case "uninstalled-module":
  161. 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. \
  162. You probably need to run "npm install" in your functions directory.`);
  163. break;
  164. case "out-of-date-module":
  165. 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. \
  166. You can probably fix this by running "npm install ${systemLog.data.name}@latest" in your functions directory.`);
  167. break;
  168. case "missing-package-json":
  169. this.log("WARN", `The Cloud Functions directory you specified does not have a "package.json" file, so we can't load it.`);
  170. break;
  171. case "function-code-resolution-failed":
  172. this.log("WARN", systemLog.data.error);
  173. const helper = ["We were unable to load your functions code. (see above)"];
  174. if (systemLog.data.isPotentially.wrong_directory) {
  175. helper.push(` - There is no "package.json" file in your functions directory.`);
  176. }
  177. if (systemLog.data.isPotentially.typescript) {
  178. helper.push(" - It appears your code is written in Typescript, which must be compiled before emulation.");
  179. }
  180. if (systemLog.data.isPotentially.uncompiled) {
  181. helper.push(` - You may be able to run "npm run build" in your functions directory to resolve this.`);
  182. }
  183. utils.logWarning(helper.join("\n"), "warn", this.data);
  184. break;
  185. case "function-runtimeconfig-json-invalid":
  186. this.log("WARN", "Found .runtimeconfig.json but the JSON format is invalid.");
  187. break;
  188. default:
  189. }
  190. }
  191. logLabeled(type, labelOrText, text) {
  192. let label = labelOrText;
  193. if (text === undefined) {
  194. text = label;
  195. label = this.name;
  196. }
  197. if (EmulatorLogger.shouldSupress(type)) {
  198. logger_1.logger.debug(`[${label}] ${text}`);
  199. return;
  200. }
  201. const mergedData = Object.assign(Object.assign({}, this.data), { metadata: Object.assign(Object.assign({}, this.data.metadata), { message: text }) });
  202. switch (type) {
  203. case "DEBUG":
  204. logger_1.logger.debug(`[${label}] ${text}`);
  205. break;
  206. case "BULLET":
  207. utils.logLabeledBullet(label, text, "info", mergedData);
  208. break;
  209. case "SUCCESS":
  210. utils.logLabeledSuccess(label, text, "info", mergedData);
  211. break;
  212. case "WARN":
  213. utils.logLabeledWarning(label, text, "warn", mergedData);
  214. break;
  215. case "WARN_ONCE":
  216. if (!EmulatorLogger.warnOnceCache.has(text)) {
  217. utils.logLabeledWarning(label, text, "warn", mergedData);
  218. EmulatorLogger.warnOnceCache.add(text);
  219. }
  220. break;
  221. case "ERROR":
  222. utils.logLabeledError(label, text, "error", mergedData);
  223. break;
  224. }
  225. }
  226. static shouldSupress(type) {
  227. const typeVerbosity = TYPE_VERBOSITY[type];
  228. return EmulatorLogger.verbosity > typeVerbosity;
  229. }
  230. }
  231. exports.EmulatorLogger = EmulatorLogger;
  232. EmulatorLogger.verbosity = Verbosity.DEBUG;
  233. EmulatorLogger.warnOnceCache = new Set();