@web/browser-logs
Version:
Capture browser logs for logging in NodeJS
121 lines • 5.38 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseStackTrace = void 0;
const errorStacks = __importStar(require("errorstacks"));
const path_1 = __importDefault(require("path"));
// regexp to match a stack track that is only a full address
const REGEXP_ADDRESS = /^(http(s)?:\/\/.*)(:\d+)(:\d+)$/;
const FILTERED_STACKS = [
'@web/test-runner',
'@web/dev-runner',
'__web-test-runner__',
'__web-dev-server__',
];
const validString = (str) => typeof str === 'string' && str !== '';
const validNumber = (nr) => typeof nr === 'number' && nr !== -1;
function filterStackFrames(frames) {
const withoutNative = frames.filter(f => f.type !== 'native');
const withoutInternal = withoutNative.filter(f => !FILTERED_STACKS.some(p => f.fileName.includes(p)));
return withoutInternal.length > 0 ? withoutInternal : withoutNative;
}
async function mapLocation(url, loc, mapBrowserUrl, mapStackLocation) {
const browserUrl = `${url.pathname}${url.search}${url.hash}`;
const filePath = mapBrowserUrl(url);
return mapStackLocation({
filePath,
browserUrl,
line: loc.line,
column: loc.column,
});
}
function parseUrl(url) {
try {
return new URL(url, 'http://www.example.org/');
}
catch (_a) {
return undefined;
}
}
async function formatLocation(loc, cwd, mapBrowserUrl, mapStackLocation) {
const url = parseUrl(loc.fileName);
let mappedLocation;
if (url) {
mappedLocation = await mapLocation(url, loc, mapBrowserUrl, mapStackLocation);
}
else {
// we could not create a browser URL from the stack location, so we don't try to map it
mappedLocation = { browserUrl: '', filePath: loc.fileName, line: loc.line, column: loc.column };
}
const relativeFileName = path_1.default.relative(cwd, mappedLocation.filePath);
return Object.assign(Object.assign({}, mappedLocation), { filePath: relativeFileName });
}
async function formatFrame(f, cwd, mapBrowserUrl, mapStackLocation) {
if (validString(f.fileName) && validNumber(f.line) && validNumber(f.column)) {
const location = `${f.fileName}:${f.line}:${f.column}`;
if (validString(f.name)) {
return ` at ${f.name} (${location})`;
}
return ` at ${location}`;
}
const trimmedRaw = f.raw.trim();
const matchFullAddress = trimmedRaw.match(REGEXP_ADDRESS);
if (matchFullAddress) {
// frame is only a full browser path (ex. http://localhost:8000/foo/bar.js:1:2)
const [, fileName, , line, column] = matchFullAddress;
const mappedLocation = await formatLocation({ fileName, line: Number(line), column: Number(column) }, cwd, mapBrowserUrl, mapStackLocation);
return ` at ${mappedLocation.filePath}:${mappedLocation.line}:${mappedLocation.column}`;
}
// fallback to raw
return ` ${trimmedRaw}`;
}
async function parseStackTrace(errorMsg, rawStack, options = {}) {
if (rawStack === '' || (rawStack.split('\n').length === 1 && rawStack.includes(errorMsg))) {
// there is no track trace, or it's only an error message
return undefined;
}
const defaultCwd = process.cwd();
const { browserRootDir = defaultCwd, cwd = defaultCwd, mapStackLocation = l => l, mapBrowserUrl = p => path_1.default.join(browserRootDir, p.pathname.split('/').join(path_1.default.sep)), } = options;
const allFrames = errorStacks.parseStackTrace(rawStack);
const frames = filterStackFrames(allFrames);
if (frames.length === 0) {
return undefined;
}
for (const frame of frames) {
if (validString(frame.fileName) && validNumber(frame.line) && validNumber(frame.column)) {
const l = await formatLocation(frame, cwd, mapBrowserUrl, mapStackLocation);
frame.fileName = l.filePath;
frame.line = l.line;
frame.column = l.column;
}
}
const formattedFrames = await Promise.all(frames.map(f => formatFrame(f, browserRootDir, mapBrowserUrl, mapStackLocation)));
return formattedFrames.join('\n');
}
exports.parseStackTrace = parseStackTrace;
//# sourceMappingURL=parseStackTrace.js.map