import LogLevel from "./levels"; import { FieldsObject } from "./logger"; import { getStackTrace } from "./stack"; /** * A log hook is a function which is called with the log object, the log level, and the message * just before the log is written to the output. * * The logObject is the full JSON object which will be emitted, however for convenience the * level and message are also passed in. * * A hook is allowed to modify the log object as required. */ export type LogHook = ( logObject: FieldsObject, level: LogLevel, msg: string, ) => void; export function WithCaller(dropFrames = 0): LogHook { const encoreDevPkgDir = encorePackagesPath(); return (logObject: FieldsObject) => { for (const frame of getStackTrace(dropFrames + 1)) { if (frame.file.startsWith(encoreDevPkgDir)) { continue; } else if ( frame.file.indexOf("/.encore/build/") !== -1 || frame.file.indexOf("/gen_encore.app/") !== -1 ) { // Ignore generated code continue; } logObject.caller = `${frame.file}:${frame.line}`; break; } }; } /** * Returns the path to the @encore.dev folder (or "packages" folder if running within the workspace) */ function encorePackagesPath(): string { const trace = getStackTrace(); if (trace.length === 0) { throw new Error("unable to determine log package"); } const components = trace[0].file.split("/"); const fileName = components.pop()!; const last = () => components[components.length - 1]; // Get the directory if (last() !== "internal") { // If we're compiled bundled output, the file extension will be .mjs or .js // so let's just return the path to the bundle if (fileName.endsWith(".mjs") || fileName.endsWith(".js")) { components.pop(); return components.join("/") + "/"; } throw new Error("unable to determine log package"); } // Drop the "internal" folder components.pop(); // Drop the "log" folder components.pop(); // Drop the dist folder, if this is the compiled js output if (last() === "dist") { components.pop(); } // Drop the "internal-runtime" folder. if (last() === "internal-runtime") { components.pop(); } const suffix = last(); if ( suffix !== "encore.dev" && suffix !== "@encore.dev" && suffix !== "packages" ) { throw new Error("unable to determine encore.dev folder path"); } return components.join("/") + "/"; }