firebase-tools
Version:
Command-Line Interface for Firebase
199 lines (198 loc) • 6.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.logger = exports.vsceLogEmitter = void 0;
exports.resolveLogTarget = resolveLogTarget;
exports.findAvailableLogFile = findAvailableLogFile;
exports.tryStringify = tryStringify;
exports.useFileLogger = useFileLogger;
exports.useConsoleLoggers = useConsoleLoggers;
const winston = require("winston");
const events_1 = require("events");
const path = require("path");
const os = require("os");
const fs = require("fs");
const triple_beam_1 = require("triple-beam");
const util_1 = require("util");
const vsCodeUtils_1 = require("./vsCodeUtils");
exports.vsceLogEmitter = new events_1.EventEmitter();
function expandErrors(logger) {
const oldLogFunc = logger.log.bind(logger);
const newLogFunc = function (levelOrEntry, message, ...meta) {
if (message && message instanceof Error) {
message = message.stack || message.message;
return oldLogFunc(levelOrEntry, message, ...meta);
}
return oldLogFunc(levelOrEntry, message, ...meta);
};
logger.log = newLogFunc;
return logger;
}
function annotateDebugLines(logger) {
const debug = logger.debug.bind(logger);
const newDebug = function (message, ...meta) {
if (typeof message === "string") {
message = `[${new Date().toISOString()}] ${message || ""}`;
}
return debug(message, ...meta);
};
logger.debug = newDebug;
return logger;
}
function maybeUseVSCodeLogger(logger) {
if (!(0, vsCodeUtils_1.isVSCodeExtension)()) {
return logger;
}
const oldLogFunc = logger.log.bind(logger);
const vsceLogger = function (levelOrEntry, message, ...meta) {
if (message) {
exports.vsceLogEmitter.emit("log", { level: levelOrEntry, message });
}
else {
exports.vsceLogEmitter.emit("log", levelOrEntry);
}
return oldLogFunc(levelOrEntry, message, ...meta);
};
logger.log = vsceLogger;
return logger;
}
function resolveLogTarget(customPath) {
const debugPath = customPath ?? process.env.FIREBASE_DEBUG_PATH;
if (!debugPath || !debugPath.trim()) {
return {
baseDir: process.cwd(),
baseName: "firebase-debug",
ext: ".log",
};
}
let trimmed = debugPath.trim();
if (trimmed === "~" || trimmed.startsWith("~/") || trimmed.startsWith("~\\")) {
trimmed = path.join(os.homedir(), trimmed.slice(1));
}
const resolvedPath = path.resolve(process.cwd(), trimmed);
if (fs.existsSync(resolvedPath)) {
let isDir = false;
try {
isDir = fs.statSync(resolvedPath).isDirectory();
}
catch {
}
if (isDir) {
return {
baseDir: resolvedPath,
baseName: "firebase-debug",
ext: ".log",
};
}
const ext = path.extname(resolvedPath);
return {
baseDir: path.dirname(resolvedPath),
baseName: path.basename(resolvedPath, ext),
ext,
};
}
if (trimmed.endsWith(path.sep) || trimmed.endsWith("/") || trimmed.endsWith("\\")) {
return {
baseDir: resolvedPath,
baseName: "firebase-debug",
ext: ".log",
};
}
const ext = path.extname(resolvedPath);
if (ext) {
return {
baseDir: path.dirname(resolvedPath),
baseName: path.basename(resolvedPath, ext),
ext,
};
}
return {
baseDir: resolvedPath,
baseName: "firebase-debug",
ext: ".log",
};
}
function findAvailableLogFile(customPath) {
const { baseDir, baseName, ext } = resolveLogTarget(customPath);
if (!fs.existsSync(baseDir)) {
try {
fs.mkdirSync(baseDir, { recursive: true });
}
catch {
}
}
const candidates = [`${baseName}${ext}`];
for (let i = 1; i < 10; i++) {
candidates.push(`${baseName}.${i}${ext}`);
}
for (const c of candidates) {
const logFilename = path.join(baseDir, c);
try {
const fd = fs.openSync(logFilename, "r+");
fs.closeSync(fd);
return logFilename;
}
catch (err) {
if (typeof err === "object" &&
err !== null &&
"code" in err &&
err.code === "ENOENT") {
try {
fs.accessSync(baseDir, fs.constants.W_OK);
return logFilename;
}
catch {
}
}
}
}
throw new Error(`Unable to obtain permissions for ${baseName}${ext}`);
}
function tryStringify(value) {
if (typeof value === "string") {
return value;
}
try {
return JSON.stringify(value);
}
catch {
return value;
}
}
const rawLogger = winston.createLogger();
rawLogger.add(new winston.transports.Console({
silent: true,
consoleWarnLevels: ["debug", "warn"],
}));
rawLogger.exitOnError = false;
exports.logger = maybeUseVSCodeLogger(annotateDebugLines(expandErrors(rawLogger)));
function useFileLogger(logFile) {
const logFileName = findAvailableLogFile(logFile);
exports.logger.add(new winston.transports.File({
level: "debug",
filename: logFileName,
format: winston.format.printf((info) => {
const segments = [info.message, ...(info[triple_beam_1.SPLAT] || [])].map(tryStringify);
return `[${info.level}] ${(0, util_1.stripVTControlCharacters)(segments.join(" "))}`;
}),
}));
return logFileName;
}
function useConsoleLoggers() {
if (process.env.DEBUG) {
exports.logger.add(new winston.transports.Console({
level: "debug",
format: winston.format.printf((info) => {
const segments = [info.message, ...(info[triple_beam_1.SPLAT] || [])].map(tryStringify);
return `${(0, util_1.stripVTControlCharacters)(segments.join(" "))}`;
}),
}));
}
else if (process.env.IS_FIREBASE_CLI) {
exports.logger.add(new winston.transports.Console({
level: "info",
format: winston.format.printf((info) => [info.message, ...(info[triple_beam_1.SPLAT] || [])]
.filter((chunk) => typeof chunk === "string")
.join(" ")),
}));
}
}