@lage-run/reporters 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,7 +17,7 @@ reporter.log({
17
17
  status: "running",
18
18
  duration: [0, 0],
19
19
  startTime: [0, 0],
20
- } as TargetStatusEntry,
20
+ },
21
21
  level: LogLevel.verbose,
22
22
  msg: "test message",
23
23
  timestamp: 0,
@@ -2,7 +2,7 @@ import { LogLevel, type LogStructuredData } from "@lage-run/logger";
2
2
  import chalk from "chalk";
3
3
  import type { Reporter, LogEntry } from "@lage-run/logger";
4
4
  import type { SchedulerRunSummary, TargetRun } from "@lage-run/scheduler-types";
5
- import type { TargetMessageEntry, TargetStatusEntry } from "./types/TargetLogEntry.js";
5
+ import type { TargetLogData } from "./types/TargetLogData.js";
6
6
  import type { Writable } from "stream";
7
7
  export declare const colors: {
8
8
  30: chalk.Chalk;
@@ -42,7 +42,7 @@ export declare abstract class GroupedReporter implements Reporter {
42
42
  logStream?: Writable;
43
43
  });
44
44
  log(entry: LogEntry<any>): boolean | void;
45
- protected logTargetEntry(entry: LogEntry<TargetStatusEntry | TargetMessageEntry>): boolean | void;
45
+ protected logTargetEntry(entry: LogEntry<TargetLogData>): boolean | void;
46
46
  private logTargetEntryByGroup;
47
47
  summarize(schedulerRunSummary: SchedulerRunSummary): void;
48
48
  /** Returns the opening line for a grouped target log block, including trailing newline. */
@@ -72,19 +72,15 @@ function getTaskLogPrefix(pkg, task) {
72
72
  }
73
73
  function normalize(prefixOrMessage, message) {
74
74
  if (typeof message === "string") {
75
- const prefix = prefixOrMessage;
76
75
  return {
77
- prefix,
78
- message
79
- };
80
- } else {
81
- const prefix = "";
82
- const message = prefixOrMessage;
83
- return {
84
- prefix,
76
+ prefix: prefixOrMessage,
85
77
  message
86
78
  };
87
79
  }
80
+ return {
81
+ prefix: "",
82
+ message: prefixOrMessage
83
+ };
88
84
  }
89
85
  function format(level, prefix, message) {
90
86
  return `${logLevelLabel[level]}: ${prefix} ${message}\n`;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/GroupedReporter.ts"],"sourcesContent":["import { formatDuration, hrToSeconds } from \"@lage-run/format-hrtime\";\nimport { isTargetStatusLogEntry } from \"./isTargetStatusLogEntry.js\";\nimport { LogLevel, type LogStructuredData } from \"@lage-run/logger\";\nimport chalk from \"chalk\";\nimport type { Reporter, LogEntry } from \"@lage-run/logger\";\nimport type { SchedulerRunSummary, TargetRun, TargetStatus } from \"@lage-run/scheduler-types\";\nimport type { TargetMessageEntry, TargetStatusEntry } from \"./types/TargetLogEntry.js\";\nimport type { Writable } from \"stream\";\nimport { slowestTargetRuns } from \"./slowestTargetRuns.js\";\n\nexport const colors = {\n [LogLevel.info]: chalk.white,\n [LogLevel.verbose]: chalk.gray,\n [LogLevel.warn]: chalk.white,\n [LogLevel.error]: chalk.white,\n [LogLevel.silly]: chalk.green,\n task: chalk.cyan,\n pkg: chalk.magenta,\n ok: chalk.green,\n error: chalk.red,\n warn: chalk.yellow,\n};\n\nexport const logLevelLabel = {\n [LogLevel.info]: \"INFO\",\n [LogLevel.warn]: \"WARN\",\n [LogLevel.error]: \"ERR!\",\n [LogLevel.silly]: \"SILLY\",\n [LogLevel.verbose]: \"VERB\",\n};\n\nexport function getTaskLogPrefix(pkg: string, task: string): string {\n return `${colors.pkg(pkg)} ${colors.task(task)}`;\n}\n\nfunction normalize(prefixOrMessage: string, message?: string) {\n if (typeof message === \"string\") {\n const prefix = prefixOrMessage;\n return { prefix, message };\n } else {\n const prefix = \"\";\n const message = prefixOrMessage;\n return { prefix, message };\n }\n}\n\nexport function format(level: LogLevel, prefix: string, message: string): string {\n return `${logLevelLabel[level]}: ${prefix} ${message}\\n`;\n}\n\nexport abstract class GroupedReporter implements Reporter {\n protected logStream: Writable;\n protected logEntries = new Map<string, LogEntry[]>();\n private readonly groupedEntries: Map<string, LogEntry<LogStructuredData>[]> = new Map<string, LogEntry[]>();\n\n constructor(\n protected options: {\n logLevel?: LogLevel;\n grouped?: boolean;\n /** stream for testing */\n logStream?: Writable;\n }\n ) {\n options.logLevel = options.logLevel || LogLevel.info;\n this.logStream = options.logStream || process.stdout;\n }\n\n public log(entry: LogEntry<any>): boolean | void {\n if (entry.data && entry.data.target && entry.data.target.hidden) {\n return;\n }\n\n if (entry.data && entry.data.target) {\n if (!this.logEntries.has(entry.data.target.id)) {\n this.logEntries.set(entry.data.target.id, []);\n }\n\n this.logEntries.get(entry.data.target.id)!.push(entry);\n }\n\n if (this.options.logLevel! >= entry.level) {\n if (this.options.grouped && entry.data?.target) {\n return this.logTargetEntryByGroup(entry);\n }\n\n return this.logTargetEntry(entry);\n }\n }\n\n protected logTargetEntry(entry: LogEntry<TargetStatusEntry | TargetMessageEntry>): boolean | void {\n const colorFn = colors[entry.level];\n const data = entry.data!;\n\n if (isTargetStatusLogEntry(data)) {\n const { target, hash, duration } = data;\n const { packageName, task } = target;\n\n const normalizedArgs = this.options.grouped\n ? normalize(entry.msg)\n : normalize(getTaskLogPrefix(packageName ?? \"<root>\", task), entry.msg);\n\n const pkgTask = this.options.grouped ? `${chalk.magenta(packageName)} ${chalk.cyan(task)}` : \"\";\n\n switch (data.status) {\n case \"running\":\n return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.ok(\"➔\")} start ${pkgTask}`)));\n\n case \"success\":\n return this.logStream.write(\n format(\n entry.level,\n normalizedArgs.prefix,\n colorFn(`${colors.ok(\"✓\")} done ${pkgTask} - ${formatDuration(hrToSeconds(duration!))}`)\n )\n );\n\n case \"failed\":\n return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.error(\"✖\")} fail ${pkgTask}`)));\n\n case \"skipped\":\n return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.ok(\"»\")} skip ${pkgTask} - ${hash!}`)));\n\n case \"aborted\":\n return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.warn(\"-\")} aborted ${pkgTask}`)));\n\n case \"queued\":\n return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.warn(\"…\")} queued ${pkgTask}`)));\n }\n } else if (entry?.data?.target) {\n const { target } = data;\n const { packageName, task } = target;\n const normalizedArgs = this.options.grouped\n ? normalize(entry.msg)\n : normalize(getTaskLogPrefix(packageName ?? \"<root>\", task), entry.msg);\n return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(\"| \" + normalizedArgs.message)));\n } else if (entry?.msg.trim() !== \"\") {\n return this.logStream.write(format(entry.level, \"\", entry.msg));\n }\n }\n\n private logTargetEntryByGroup(entry: LogEntry<TargetStatusEntry | TargetMessageEntry>) {\n const data = entry.data!;\n\n const target = data.target;\n const { id } = target;\n\n this.groupedEntries.set(id, this.groupedEntries.get(id) || []);\n this.groupedEntries.get(id)?.push(entry);\n\n if (isTargetStatusLogEntry(data)) {\n if (data.status === \"success\" || data.status === \"failed\" || data.status === \"skipped\" || data.status === \"aborted\") {\n const { status, duration } = data;\n this.logStream.write(this.formatGroupStart(data.target.packageName ?? \"<root>\", data.target.task, status, duration));\n\n const entries = this.groupedEntries.get(id)! as LogEntry<TargetStatusEntry>[];\n for (const targetEntry of entries) {\n this.logTargetEntry(targetEntry);\n }\n\n this.logStream.write(this.formatGroupEnd());\n }\n }\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n const { targetRuns, targetRunByStatus, duration } = schedulerRunSummary;\n const { failed, aborted, skipped, success, pending } = targetRunByStatus;\n\n const statusColorFn: { [status in TargetStatus]: chalk.Chalk } = {\n success: chalk.greenBright,\n failed: chalk.redBright,\n skipped: chalk.gray,\n running: chalk.yellow,\n pending: chalk.gray,\n aborted: chalk.red,\n queued: chalk.magenta,\n };\n\n this.writeSummaryHeader();\n\n if (targetRuns.size > 0) {\n const slowestTargets = slowestTargetRuns([...targetRuns.values()]);\n\n for (const wrappedTarget of slowestTargets) {\n const colorFn = statusColorFn[wrappedTarget.status];\n const target = wrappedTarget.target;\n\n this.logStream.write(\n format(\n LogLevel.info,\n getTaskLogPrefix(target.packageName || \"[GLOBAL]\", target.task),\n colorFn(\n `${wrappedTarget.status}${wrappedTarget.duration ? `, took ${formatDuration(hrToSeconds(wrappedTarget.duration))}` : \"\"}`\n )\n )\n );\n }\n\n this.logStream.write(\n `[Tasks Count] success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}\\n`\n );\n } else {\n this.logStream.write(\"Nothing has been run.\\n\");\n }\n\n this.writeSummaryFooter();\n\n if (failed && failed.length > 0) {\n this.writeFailures(failed, targetRuns);\n }\n\n this.logStream.write(format(LogLevel.info, \"\", `Took a total of ${formatDuration(hrToSeconds(duration))} to complete`));\n }\n\n /** Returns the opening line for a grouped target log block, including trailing newline. */\n protected abstract formatGroupStart(packageName: string, task: string, status: string, duration?: [number, number]): string;\n\n /** Returns the closing line for a grouped target log block, including trailing newline. */\n protected abstract formatGroupEnd(): string;\n\n /** Writes the summary section header. */\n protected abstract writeSummaryHeader(): void;\n\n /** Writes anything needed after the summary target list (e.g. closing a group). */\n protected abstract writeSummaryFooter(): void;\n\n /** Writes per-CI-system error annotations for all failed targets. */\n protected abstract writeFailures(failed: string[], targetRuns: Map<string, TargetRun<unknown>>): void;\n}\n"],"names":["GroupedReporter","colors","format","getTaskLogPrefix","logLevelLabel","LogLevel","info","chalk","white","verbose","gray","warn","error","silly","green","task","cyan","pkg","magenta","ok","red","yellow","normalize","prefixOrMessage","message","prefix","level","log","entry","data","target","hidden","logEntries","has","id","set","get","push","options","logLevel","grouped","logTargetEntryByGroup","logTargetEntry","colorFn","isTargetStatusLogEntry","hash","duration","packageName","normalizedArgs","msg","pkgTask","status","logStream","write","formatDuration","hrToSeconds","trim","groupedEntries","formatGroupStart","entries","targetEntry","formatGroupEnd","summarize","schedulerRunSummary","targetRuns","targetRunByStatus","failed","aborted","skipped","success","pending","statusColorFn","greenBright","redBright","running","queued","writeSummaryHeader","size","slowestTargets","slowestTargetRuns","values","wrappedTarget","length","writeSummaryFooter","writeFailures","Map","process","stdout"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/GroupedReporter.ts"],"sourcesContent":["import { formatDuration, hrToSeconds } from \"@lage-run/format-hrtime\";\nimport { isTargetStatusLogEntry } from \"./isTargetStatusLogEntry.js\";\nimport { LogLevel, type LogStructuredData } from \"@lage-run/logger\";\nimport chalk from \"chalk\";\nimport type { Reporter, LogEntry } from \"@lage-run/logger\";\nimport type { SchedulerRunSummary, TargetRun, TargetStatus } from \"@lage-run/scheduler-types\";\nimport type { TargetLogData, TargetStatusData } from \"./types/TargetLogData.js\";\nimport type { Writable } from \"stream\";\nimport { slowestTargetRuns } from \"./slowestTargetRuns.js\";\n\nexport const colors = {\n [LogLevel.info]: chalk.white,\n [LogLevel.verbose]: chalk.gray,\n [LogLevel.warn]: chalk.white,\n [LogLevel.error]: chalk.white,\n [LogLevel.silly]: chalk.green,\n task: chalk.cyan,\n pkg: chalk.magenta,\n ok: chalk.green,\n error: chalk.red,\n warn: chalk.yellow,\n};\n\nexport const logLevelLabel = {\n [LogLevel.info]: \"INFO\",\n [LogLevel.warn]: \"WARN\",\n [LogLevel.error]: \"ERR!\",\n [LogLevel.silly]: \"SILLY\",\n [LogLevel.verbose]: \"VERB\",\n};\n\nexport function getTaskLogPrefix(pkg: string, task: string): string {\n return `${colors.pkg(pkg)} ${colors.task(task)}`;\n}\n\nfunction normalize(prefixOrMessage: string, message?: string) {\n if (typeof message === \"string\") {\n return { prefix: prefixOrMessage, message };\n }\n return { prefix: \"\", message: prefixOrMessage };\n}\n\nexport function format(level: LogLevel, prefix: string, message: string): string {\n return `${logLevelLabel[level]}: ${prefix} ${message}\\n`;\n}\n\nexport abstract class GroupedReporter implements Reporter {\n protected logStream: Writable;\n protected logEntries = new Map<string, LogEntry[]>();\n private readonly groupedEntries: Map<string, LogEntry<LogStructuredData>[]> = new Map<string, LogEntry[]>();\n\n constructor(\n protected options: {\n logLevel?: LogLevel;\n grouped?: boolean;\n /** stream for testing */\n logStream?: Writable;\n }\n ) {\n options.logLevel = options.logLevel || LogLevel.info;\n this.logStream = options.logStream || process.stdout;\n }\n\n public log(entry: LogEntry<any>): boolean | void {\n if (entry.data && entry.data.target && entry.data.target.hidden) {\n return;\n }\n\n if (entry.data && entry.data.target) {\n if (!this.logEntries.has(entry.data.target.id)) {\n this.logEntries.set(entry.data.target.id, []);\n }\n\n this.logEntries.get(entry.data.target.id)!.push(entry);\n }\n\n if (this.options.logLevel! >= entry.level) {\n if (this.options.grouped && entry.data?.target) {\n return this.logTargetEntryByGroup(entry);\n }\n\n return this.logTargetEntry(entry);\n }\n }\n\n protected logTargetEntry(entry: LogEntry<TargetLogData>): boolean | void {\n const colorFn = colors[entry.level];\n const data = entry.data!;\n\n if (isTargetStatusLogEntry(data)) {\n const { target, hash, duration } = data;\n const { packageName, task } = target;\n\n const normalizedArgs = this.options.grouped\n ? normalize(entry.msg)\n : normalize(getTaskLogPrefix(packageName ?? \"<root>\", task), entry.msg);\n\n const pkgTask = this.options.grouped ? `${chalk.magenta(packageName)} ${chalk.cyan(task)}` : \"\";\n\n switch (data.status) {\n case \"running\":\n return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.ok(\"➔\")} start ${pkgTask}`)));\n\n case \"success\":\n return this.logStream.write(\n format(\n entry.level,\n normalizedArgs.prefix,\n colorFn(`${colors.ok(\"✓\")} done ${pkgTask} - ${formatDuration(hrToSeconds(duration!))}`)\n )\n );\n\n case \"failed\":\n return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.error(\"✖\")} fail ${pkgTask}`)));\n\n case \"skipped\":\n return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.ok(\"»\")} skip ${pkgTask} - ${hash!}`)));\n\n case \"aborted\":\n return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.warn(\"-\")} aborted ${pkgTask}`)));\n\n case \"queued\":\n return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(`${colors.warn(\"…\")} queued ${pkgTask}`)));\n }\n } else if (entry?.data?.target) {\n const { target } = data;\n const { packageName, task } = target;\n const normalizedArgs = this.options.grouped\n ? normalize(entry.msg)\n : normalize(getTaskLogPrefix(packageName ?? \"<root>\", task), entry.msg);\n return this.logStream.write(format(entry.level, normalizedArgs.prefix, colorFn(\"| \" + normalizedArgs.message)));\n } else if (entry?.msg.trim() !== \"\") {\n return this.logStream.write(format(entry.level, \"\", entry.msg));\n }\n }\n\n private logTargetEntryByGroup(entry: LogEntry<TargetLogData>) {\n const data = entry.data!;\n\n const target = data.target;\n const { id } = target;\n\n this.groupedEntries.set(id, this.groupedEntries.get(id) || []);\n this.groupedEntries.get(id)?.push(entry);\n\n if (isTargetStatusLogEntry(data)) {\n if (data.status === \"success\" || data.status === \"failed\" || data.status === \"skipped\" || data.status === \"aborted\") {\n const { status, duration } = data;\n this.logStream.write(this.formatGroupStart(data.target.packageName ?? \"<root>\", data.target.task, status, duration));\n\n const entries = this.groupedEntries.get(id)! as LogEntry<TargetStatusData>[];\n for (const targetEntry of entries) {\n this.logTargetEntry(targetEntry);\n }\n\n this.logStream.write(this.formatGroupEnd());\n }\n }\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n const { targetRuns, targetRunByStatus, duration } = schedulerRunSummary;\n const { failed, aborted, skipped, success, pending } = targetRunByStatus;\n\n const statusColorFn: { [status in TargetStatus]: chalk.Chalk } = {\n success: chalk.greenBright,\n failed: chalk.redBright,\n skipped: chalk.gray,\n running: chalk.yellow,\n pending: chalk.gray,\n aborted: chalk.red,\n queued: chalk.magenta,\n };\n\n this.writeSummaryHeader();\n\n if (targetRuns.size > 0) {\n const slowestTargets = slowestTargetRuns([...targetRuns.values()]);\n\n for (const wrappedTarget of slowestTargets) {\n const colorFn = statusColorFn[wrappedTarget.status];\n const target = wrappedTarget.target;\n\n this.logStream.write(\n format(\n LogLevel.info,\n getTaskLogPrefix(target.packageName || \"[GLOBAL]\", target.task),\n colorFn(\n `${wrappedTarget.status}${wrappedTarget.duration ? `, took ${formatDuration(hrToSeconds(wrappedTarget.duration))}` : \"\"}`\n )\n )\n );\n }\n\n this.logStream.write(\n `[Tasks Count] success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}\\n`\n );\n } else {\n this.logStream.write(\"Nothing has been run.\\n\");\n }\n\n this.writeSummaryFooter();\n\n if (failed && failed.length > 0) {\n this.writeFailures(failed, targetRuns);\n }\n\n this.logStream.write(format(LogLevel.info, \"\", `Took a total of ${formatDuration(hrToSeconds(duration))} to complete`));\n }\n\n /** Returns the opening line for a grouped target log block, including trailing newline. */\n protected abstract formatGroupStart(packageName: string, task: string, status: string, duration?: [number, number]): string;\n\n /** Returns the closing line for a grouped target log block, including trailing newline. */\n protected abstract formatGroupEnd(): string;\n\n /** Writes the summary section header. */\n protected abstract writeSummaryHeader(): void;\n\n /** Writes anything needed after the summary target list (e.g. closing a group). */\n protected abstract writeSummaryFooter(): void;\n\n /** Writes per-CI-system error annotations for all failed targets. */\n protected abstract writeFailures(failed: string[], targetRuns: Map<string, TargetRun<unknown>>): void;\n}\n"],"names":["GroupedReporter","colors","format","getTaskLogPrefix","logLevelLabel","LogLevel","info","chalk","white","verbose","gray","warn","error","silly","green","task","cyan","pkg","magenta","ok","red","yellow","normalize","prefixOrMessage","message","prefix","level","log","entry","data","target","hidden","logEntries","has","id","set","get","push","options","logLevel","grouped","logTargetEntryByGroup","logTargetEntry","colorFn","isTargetStatusLogEntry","hash","duration","packageName","normalizedArgs","msg","pkgTask","status","logStream","write","formatDuration","hrToSeconds","trim","groupedEntries","formatGroupStart","entries","targetEntry","formatGroupEnd","summarize","schedulerRunSummary","targetRuns","targetRunByStatus","failed","aborted","skipped","success","pending","statusColorFn","greenBright","redBright","running","queued","writeSummaryHeader","size","slowestTargets","slowestTargetRuns","values","wrappedTarget","length","writeSummaryFooter","writeFailures","Map","process","stdout"],"mappings":"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"}
@@ -1,13 +1,31 @@
1
- import type { SchedulerRunSummary } from "@lage-run/scheduler-types";
1
+ import type { SchedulerRunSummary, TargetStatus } from "@lage-run/scheduler-types";
2
2
  import type { LogLevel } from "@lage-run/logger";
3
3
  import { type LogEntry, type Reporter } from "@lage-run/logger";
4
- import type { TargetMessageEntry, TargetStatusEntry } from "./types/TargetLogEntry.js";
4
+ import type { TargetLogData } from "./types/TargetLogData.js";
5
+ interface JsonReporterTaskStats {
6
+ package: string | undefined;
7
+ task: string;
8
+ duration: string;
9
+ status: string;
10
+ }
11
+ /** Final entry logged by `JsonReporter.summarize()` */
12
+ export interface JsonReporterSummaryData {
13
+ summary: {
14
+ duration: string;
15
+ taskStats: JsonReporterTaskStats[];
16
+ } & {
17
+ [status in `${TargetStatus}Targets`]?: number;
18
+ };
19
+ }
20
+ /** `LogEntry.data` types for the `JsonReporter` */
21
+ export type JsonReporterLogData = JsonReporterSummaryData | TargetLogData;
5
22
  export declare class JsonReporter implements Reporter {
6
23
  private options;
7
24
  constructor(options: {
8
25
  logLevel: LogLevel;
9
26
  indented: boolean;
10
27
  });
11
- log(entry: LogEntry<TargetStatusEntry | TargetMessageEntry>): void;
28
+ log(entry: LogEntry<TargetLogData>): void;
12
29
  summarize(schedulerRunSummary: SchedulerRunSummary): void;
13
30
  }
31
+ export {};
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/JsonReporter.ts"],"sourcesContent":["/* eslint-disable no-console */\n\nimport { hrToSeconds } from \"@lage-run/format-hrtime\";\nimport type { SchedulerRunSummary } from \"@lage-run/scheduler-types\";\nimport type { LogLevel } from \"@lage-run/logger\";\nimport { type LogEntry, type Reporter } from \"@lage-run/logger\";\n\nimport type { TargetMessageEntry, TargetStatusEntry } from \"./types/TargetLogEntry.js\";\n\nexport class JsonReporter implements Reporter {\n constructor(private options: { logLevel: LogLevel; indented: boolean }) {}\n\n public log(entry: LogEntry<TargetStatusEntry | TargetMessageEntry>): void {\n if (entry.data && entry.data.target && entry.data.target.hidden) {\n return;\n }\n\n if (this.options.logLevel >= entry.level) {\n console.log(this.options.indented ? JSON.stringify(entry, null, 2) : JSON.stringify(entry));\n }\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n const { duration, targetRuns, targetRunByStatus } = schedulerRunSummary;\n\n const summary: Record<string, unknown> = {\n duration: hrToSeconds(duration),\n taskStats: [...targetRuns.values()].map((targetRun) => ({\n package: targetRun.target.packageName,\n task: targetRun.target.task,\n duration: hrToSeconds(targetRun.duration),\n status: targetRun.status,\n })),\n };\n\n for (const status of Object.keys(targetRunByStatus) as (keyof typeof targetRunByStatus)[]) {\n if (targetRunByStatus[status] && targetRunByStatus[status].length) {\n summary[`${status}Targets`] = targetRunByStatus[status].length;\n }\n }\n\n console.log(JSON.stringify({ summary }));\n }\n}\n"],"names":["JsonReporter","log","entry","data","target","hidden","options","logLevel","level","console","indented","JSON","stringify","summarize","schedulerRunSummary","duration","targetRuns","targetRunByStatus","summary","hrToSeconds","taskStats","values","map","targetRun","package","packageName","task","status","Object","keys","length"],"mappings":"AAAA,6BAA6B;;;;+BAShBA;;;eAAAA;;;8BAPe;;;;;;;;;;;;;;AAOrB,MAAMA;IAGJC,IAAIC,KAAuD,EAAQ;QACxE,IAAIA,MAAMC,IAAI,IAAID,MAAMC,IAAI,CAACC,MAAM,IAAIF,MAAMC,IAAI,CAACC,MAAM,CAACC,MAAM,EAAE;YAC/D;QACF;QAEA,IAAI,IAAI,CAACC,OAAO,CAACC,QAAQ,IAAIL,MAAMM,KAAK,EAAE;YACxCC,QAAQR,GAAG,CAAC,IAAI,CAACK,OAAO,CAACI,QAAQ,GAAGC,KAAKC,SAAS,CAACV,OAAO,MAAM,KAAKS,KAAKC,SAAS,CAACV;QACtF;IACF;IAEOW,UAAUC,mBAAwC,EAAQ;QAC/D,MAAM,EAAEC,QAAQ,EAAEC,UAAU,EAAEC,iBAAiB,EAAE,GAAGH;QAEpD,MAAMI,UAAmC;YACvCH,UAAUI,IAAAA,yBAAW,EAACJ;YACtBK,WAAW;mBAAIJ,WAAWK,MAAM;aAAG,CAACC,GAAG,CAAC,CAACC,YAAe,CAAA;oBACtDC,SAASD,UAAUnB,MAAM,CAACqB,WAAW;oBACrCC,MAAMH,UAAUnB,MAAM,CAACsB,IAAI;oBAC3BX,UAAUI,IAAAA,yBAAW,EAACI,UAAUR,QAAQ;oBACxCY,QAAQJ,UAAUI,MAAM;gBAC1B,CAAA;QACF;QAEA,KAAK,MAAMA,UAAUC,OAAOC,IAAI,CAACZ,mBAA0D;YACzF,IAAIA,iBAAiB,CAACU,OAAO,IAAIV,iBAAiB,CAACU,OAAO,CAACG,MAAM,EAAE;gBACjEZ,OAAO,CAAC,GAAGS,OAAO,OAAO,CAAC,CAAC,GAAGV,iBAAiB,CAACU,OAAO,CAACG,MAAM;YAChE;QACF;QAEArB,QAAQR,GAAG,CAACU,KAAKC,SAAS,CAAC;YAAEM;QAAQ;IACvC;IAhCA,YAAY,AAAQZ,OAAkD,CAAE;;aAApDA,UAAAA;IAAqD;AAiC3E"}
1
+ {"version":3,"sources":["../src/JsonReporter.ts"],"sourcesContent":["/* eslint-disable no-console */\n\nimport { hrToSeconds } from \"@lage-run/format-hrtime\";\nimport type { SchedulerRunSummary, TargetStatus } from \"@lage-run/scheduler-types\";\nimport type { LogLevel } from \"@lage-run/logger\";\nimport { type LogEntry, type Reporter } from \"@lage-run/logger\";\nimport type { TargetLogData } from \"./types/TargetLogData.js\";\n\ninterface JsonReporterTaskStats {\n package: string | undefined;\n task: string;\n duration: string;\n status: string;\n}\n\n/** Final entry logged by `JsonReporter.summarize()` */\nexport interface JsonReporterSummaryData {\n summary: {\n duration: string;\n taskStats: JsonReporterTaskStats[];\n } & {\n [status in `${TargetStatus}Targets`]?: number;\n };\n}\n\n/** `LogEntry.data` types for the `JsonReporter` */\nexport type JsonReporterLogData = JsonReporterSummaryData | TargetLogData;\n\nexport class JsonReporter implements Reporter {\n constructor(private options: { logLevel: LogLevel; indented: boolean }) {}\n\n public log(entry: LogEntry<TargetLogData>): void {\n if (entry.data && entry.data.target && entry.data.target.hidden) {\n return;\n }\n\n if (this.options.logLevel >= entry.level) {\n console.log(this.options.indented ? JSON.stringify(entry, null, 2) : JSON.stringify(entry));\n }\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n const { duration, targetRuns, targetRunByStatus } = schedulerRunSummary;\n\n const summary: JsonReporterSummaryData[\"summary\"] = {\n duration: hrToSeconds(duration),\n taskStats: [...targetRuns.values()].map((targetRun) => ({\n package: targetRun.target.packageName,\n task: targetRun.target.task,\n duration: hrToSeconds(targetRun.duration),\n status: targetRun.status,\n })),\n };\n\n for (const status of Object.keys(targetRunByStatus) as TargetStatus[]) {\n if (targetRunByStatus[status] && targetRunByStatus[status].length) {\n summary[`${status}Targets`] = targetRunByStatus[status].length;\n }\n }\n\n console.log(JSON.stringify({ summary }));\n }\n}\n"],"names":["JsonReporter","log","entry","data","target","hidden","options","logLevel","level","console","indented","JSON","stringify","summarize","schedulerRunSummary","duration","targetRuns","targetRunByStatus","summary","hrToSeconds","taskStats","values","map","targetRun","package","packageName","task","status","Object","keys","length"],"mappings":"AAAA,6BAA6B;;;;+BA4BhBA;;;eAAAA;;;8BA1Be;;;;;;;;;;;;;;AA0BrB,MAAMA;IAGJC,IAAIC,KAA8B,EAAQ;QAC/C,IAAIA,MAAMC,IAAI,IAAID,MAAMC,IAAI,CAACC,MAAM,IAAIF,MAAMC,IAAI,CAACC,MAAM,CAACC,MAAM,EAAE;YAC/D;QACF;QAEA,IAAI,IAAI,CAACC,OAAO,CAACC,QAAQ,IAAIL,MAAMM,KAAK,EAAE;YACxCC,QAAQR,GAAG,CAAC,IAAI,CAACK,OAAO,CAACI,QAAQ,GAAGC,KAAKC,SAAS,CAACV,OAAO,MAAM,KAAKS,KAAKC,SAAS,CAACV;QACtF;IACF;IAEOW,UAAUC,mBAAwC,EAAQ;QAC/D,MAAM,EAAEC,QAAQ,EAAEC,UAAU,EAAEC,iBAAiB,EAAE,GAAGH;QAEpD,MAAMI,UAA8C;YAClDH,UAAUI,IAAAA,yBAAW,EAACJ;YACtBK,WAAW;mBAAIJ,WAAWK,MAAM;aAAG,CAACC,GAAG,CAAC,CAACC,YAAe,CAAA;oBACtDC,SAASD,UAAUnB,MAAM,CAACqB,WAAW;oBACrCC,MAAMH,UAAUnB,MAAM,CAACsB,IAAI;oBAC3BX,UAAUI,IAAAA,yBAAW,EAACI,UAAUR,QAAQ;oBACxCY,QAAQJ,UAAUI,MAAM;gBAC1B,CAAA;QACF;QAEA,KAAK,MAAMA,UAAUC,OAAOC,IAAI,CAACZ,mBAAsC;YACrE,IAAIA,iBAAiB,CAACU,OAAO,IAAIV,iBAAiB,CAACU,OAAO,CAACG,MAAM,EAAE;gBACjEZ,OAAO,CAAC,GAAGS,OAAO,OAAO,CAAC,CAAC,GAAGV,iBAAiB,CAACU,OAAO,CAACG,MAAM;YAChE;QACF;QAEArB,QAAQR,GAAG,CAACU,KAAKC,SAAS,CAAC;YAAEM;QAAQ;IACvC;IAhCA,YAAY,AAAQZ,OAAkD,CAAE;;aAApDA,UAAAA;IAAqD;AAiC3E"}
@@ -80,19 +80,15 @@ function stripAnsi(message) {
80
80
  }
81
81
  function normalize(prefixOrMessage, message) {
82
82
  if (typeof message === "string") {
83
- const prefix = prefixOrMessage;
84
83
  return {
85
- prefix,
86
- message
87
- };
88
- } else {
89
- const prefix = "";
90
- const message = prefixOrMessage;
91
- return {
92
- prefix,
84
+ prefix: prefixOrMessage,
93
85
  message
94
86
  };
95
87
  }
88
+ return {
89
+ prefix: "",
90
+ message: prefixOrMessage
91
+ };
96
92
  }
97
93
  class LogReporter {
98
94
  log(entry) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/LogReporter.ts"],"sourcesContent":["import { formatDuration, hrtimeDiff, hrToSeconds } from \"@lage-run/format-hrtime\";\nimport { isTargetStatusLogEntry } from \"./isTargetStatusLogEntry.js\";\nimport { LogLevel } from \"@lage-run/logger\";\nimport ansiRegex from \"ansi-regex\";\nimport chalk from \"chalk\";\nimport type { Chalk } from \"chalk\";\nimport { gradient } from \"./gradient.js\";\nimport type { Reporter, LogEntry } from \"@lage-run/logger\";\nimport type { SchedulerRunSummary, TargetStatus } from \"@lage-run/scheduler-types\";\nimport type { TargetMessageEntry, TargetStatusEntry } from \"./types/TargetLogEntry.js\";\nimport type { Writable } from \"stream\";\nimport crypto from \"crypto\";\nimport { formatBytes } from \"./formatBytes.js\";\nimport { slowestTargetRuns } from \"./slowestTargetRuns.js\";\n\nconst colors = {\n [LogLevel.info]: chalk.white,\n [LogLevel.verbose]: chalk.gray,\n [LogLevel.warn]: chalk.white,\n [LogLevel.error]: chalk.hex(\"#FF1010\"),\n [LogLevel.silly]: chalk.green,\n task: chalk.hex(\"#00DDDD\"),\n pkg: chalk.hex(\"#FFD66B\"),\n ok: chalk.green,\n error: chalk.red,\n warn: chalk.yellow,\n};\n\n// Monokai color scheme\nconst pkgColors: Chalk[] = [\n chalk.hex(\"#e5b567\"),\n chalk.hex(\"#b4d273\"),\n chalk.hex(\"#e87d3e\"),\n chalk.hex(\"#9e86c8\"),\n chalk.hex(\"#b05279\"),\n chalk.hex(\"#6c99bb\"),\n];\n\nfunction hashStringToNumber(str: string): number {\n const hash = crypto.createHash(\"md5\");\n hash.update(str);\n const hex = hash.digest(\"hex\").substring(0, 6);\n return parseInt(hex, 16);\n}\n\nconst pkgNameToIndexInPkgColorArray = new Map<string, number>();\n\nfunction getColorForPkg(pkg: string): Chalk {\n if (!pkgNameToIndexInPkgColorArray.has(pkg)) {\n const index = hashStringToNumber(pkg) % pkgColors.length;\n pkgNameToIndexInPkgColorArray.set(pkg, index);\n }\n\n return pkgColors[pkgNameToIndexInPkgColorArray.get(pkg)!];\n}\n\nconst stripAnsiRegex = ansiRegex();\n\nfunction getTaskLogPrefix(pkg: string, task: string) {\n const pkgColor = getColorForPkg(pkg);\n return `${pkgColor(pkg)} ${colors.task(task)}`;\n}\n\nfunction stripAnsi(message: string) {\n return message.replace(stripAnsiRegex, \"\");\n}\n\nfunction normalize(prefixOrMessage: string, message?: string) {\n if (typeof message === \"string\") {\n const prefix = prefixOrMessage;\n return { prefix, message };\n } else {\n const prefix = \"\";\n const message = prefixOrMessage;\n return { prefix, message };\n }\n}\n\nexport class LogReporter implements Reporter {\n private logStream: Writable;\n private logEntries = new Map<string, LogEntry[]>();\n\n constructor(\n private options: {\n logLevel?: LogLevel;\n grouped?: boolean;\n /** stream for testing */\n logStream?: Writable;\n }\n ) {\n options.logLevel = options.logLevel || LogLevel.info;\n this.logStream = options.logStream || process.stdout;\n }\n\n public log(entry: LogEntry<any>): void {\n // if \"hidden\", do not even attempt to record or report the entry\n if (entry?.data?.target?.hidden) {\n return;\n }\n\n // save the logs for errors\n if (entry.data?.target?.id) {\n if (!this.logEntries.has(entry.data.target.id)) {\n this.logEntries.set(entry.data.target.id, []);\n }\n this.logEntries.get(entry.data.target.id)!.push(entry);\n }\n\n // if loglevel is not high enough, do not report the entry\n if (this.options.logLevel! < entry.level) {\n return;\n }\n\n // log to grouped entries\n if (this.options.grouped && entry.data?.target) {\n return this.logTargetEntryByGroup(entry);\n }\n\n // log normal target entries\n if (entry.data && entry.data.target) {\n return this.logTargetEntry(entry);\n }\n\n // log generic entries (not related to target)\n if (entry.msg) {\n return this.print(entry.msg);\n }\n }\n\n private printEntry(entry: LogEntry<any>, message: string) {\n let prefix = \"\";\n let msg = message;\n\n if (entry?.data?.target) {\n const { packageName, task } = entry.data.target;\n const normalizedArgs = normalize(getTaskLogPrefix(packageName ?? \"<root>\", task), msg);\n prefix = normalizedArgs.prefix;\n msg = normalizedArgs.message;\n }\n\n this.print(`${prefix ? prefix + \" \" : \"\"}${msg}`);\n }\n\n private print(message: string) {\n this.logStream.write(message + \"\\n\");\n }\n\n private logTargetEntry(entry: LogEntry<TargetStatusEntry | TargetMessageEntry>) {\n const colorFn = colors[entry.level];\n const data = entry.data!;\n\n if (isTargetStatusLogEntry(data)) {\n const { hash, duration } = data;\n switch (data.status) {\n case \"running\":\n return this.printEntry(entry, colorFn(`${colors.ok(\"➔\")} start`));\n\n case \"success\":\n return this.printEntry(entry, colorFn(`${colors.ok(\"✓\")} done - ${formatDuration(hrToSeconds(duration!))}`));\n\n case \"failed\":\n return this.printEntry(entry, colorFn(`${colors.error(\"✖\")} fail`));\n\n case \"skipped\":\n return this.printEntry(entry, colorFn(`${colors.ok(\"»\")} skip - ${hash!}`));\n\n case \"aborted\":\n return this.printEntry(entry, colorFn(`${colors.warn(\"-\")} aborted`));\n\n case \"queued\":\n return this.printEntry(entry, colorFn(`${colors.warn(\"…\")} queued`));\n }\n } else {\n return this.printEntry(entry, colorFn(\": \" + stripAnsi(entry.msg)));\n }\n }\n\n private logTargetEntryByGroup(entry: LogEntry<TargetStatusEntry | TargetMessageEntry>) {\n const data = entry.data!;\n\n const target = data.target;\n const { id } = target;\n\n if (\n isTargetStatusLogEntry(data) &&\n (data.status === \"success\" || data.status === \"failed\" || data.status === \"skipped\" || data.status === \"aborted\")\n ) {\n const entries = this.logEntries.get(id)! as LogEntry<TargetStatusEntry>[];\n\n for (const targetEntry of entries) {\n this.logTargetEntry(targetEntry);\n }\n\n if (entries.length > 2) {\n this.hr();\n }\n }\n }\n\n private hr(): void {\n this.print(\"┈\".repeat(80));\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n const { targetRuns, targetRunByStatus, duration } = schedulerRunSummary;\n const { failed, aborted, skipped, success, pending } = targetRunByStatus;\n\n const statusColorFn: {\n [status in TargetStatus]: chalk.Chalk;\n } = {\n success: chalk.greenBright,\n failed: chalk.redBright,\n skipped: chalk.gray,\n running: chalk.yellow,\n pending: chalk.gray,\n aborted: chalk.red,\n queued: chalk.magenta,\n };\n\n if (targetRuns.size > 0) {\n this.print(chalk.cyanBright(`\\nSummary`));\n\n this.hr();\n\n const slowestTargets = slowestTargetRuns([...targetRuns.values()]);\n\n for (const wrappedTarget of slowestTargets) {\n if (wrappedTarget.target.hidden) {\n continue;\n }\n\n const colorFn = statusColorFn[wrappedTarget.status] ?? chalk.white;\n const target = wrappedTarget.target;\n const hasDurations = !!wrappedTarget.duration && !!wrappedTarget.queueTime;\n const queueDuration: [number, number] = hasDurations ? hrtimeDiff(wrappedTarget.queueTime, wrappedTarget.startTime) : [0, 0];\n\n this.print(\n `${getTaskLogPrefix(target.packageName || \"<root>\", target.task)} ${colorFn(\n `${wrappedTarget.status === \"running\" ? \"running - incomplete\" : wrappedTarget.status}${\n hasDurations\n ? `, took ${formatDuration(hrToSeconds(wrappedTarget.duration))}, queued for ${formatDuration(hrToSeconds(queueDuration))}`\n : \"\"\n }`\n )}`\n );\n }\n\n this.print(\n `success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}, failed: ${failed.length}`\n );\n\n this.print(\n `worker restarts: ${schedulerRunSummary.workerRestarts}, max worker memory usage: ${formatBytes(\n schedulerRunSummary.maxWorkerMemoryUsage\n )}`\n );\n } else {\n this.print(\"Nothing has been run.\");\n }\n\n this.hr();\n\n if (failed && failed.length > 0) {\n for (const targetId of failed) {\n const target = targetRuns.get(targetId)?.target;\n\n if (target) {\n const { packageName, task } = target;\n const failureLogs = this.logEntries.get(targetId);\n\n this.print(`[${colors.pkg(packageName ?? \"<root>\")} ${colors.task(task)}] ${colors[LogLevel.error](\"ERROR DETECTED\")}`);\n\n if (failureLogs) {\n for (const entry of failureLogs) {\n // Log each entry separately to prevent truncation\n this.print(entry.msg);\n }\n }\n\n this.hr();\n }\n }\n }\n\n const allCacheHits = [...targetRuns.values()].filter((run) => !run.target.hidden).length === skipped.length;\n const allCacheHitText = allCacheHits ? gradient({ r: 237, g: 178, b: 77 }, \"cyan\")(`All targets skipped!`) : \"\";\n\n this.print(`Took a total of ${formatDuration(hrToSeconds(duration))} to complete. ${allCacheHitText}`);\n }\n\n public resetLogEntries(): void {\n this.logEntries.clear();\n }\n}\n"],"names":["LogReporter","colors","LogLevel","info","chalk","white","verbose","gray","warn","error","hex","silly","green","task","pkg","ok","red","yellow","pkgColors","hashStringToNumber","str","hash","crypto","createHash","update","digest","substring","parseInt","pkgNameToIndexInPkgColorArray","Map","getColorForPkg","has","index","length","set","get","stripAnsiRegex","ansiRegex","getTaskLogPrefix","pkgColor","stripAnsi","message","replace","normalize","prefixOrMessage","prefix","log","entry","data","target","hidden","id","logEntries","push","options","logLevel","level","grouped","logTargetEntryByGroup","logTargetEntry","msg","print","printEntry","packageName","normalizedArgs","logStream","write","colorFn","isTargetStatusLogEntry","duration","status","formatDuration","hrToSeconds","entries","targetEntry","hr","repeat","summarize","schedulerRunSummary","targetRuns","targetRunByStatus","failed","aborted","skipped","success","pending","statusColorFn","greenBright","redBright","running","queued","magenta","size","cyanBright","slowestTargets","slowestTargetRuns","values","wrappedTarget","hasDurations","queueTime","queueDuration","hrtimeDiff","startTime","workerRestarts","formatBytes","maxWorkerMemoryUsage","targetId","failureLogs","allCacheHits","filter","run","allCacheHitText","gradient","r","g","b","resetLogEntries","clear","process","stdout"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/LogReporter.ts"],"sourcesContent":["import { formatDuration, hrtimeDiff, hrToSeconds } from \"@lage-run/format-hrtime\";\nimport { isTargetStatusLogEntry } from \"./isTargetStatusLogEntry.js\";\nimport { LogLevel } from \"@lage-run/logger\";\nimport ansiRegex from \"ansi-regex\";\nimport chalk from \"chalk\";\nimport type { Chalk } from \"chalk\";\nimport { gradient } from \"./gradient.js\";\nimport type { Reporter, LogEntry } from \"@lage-run/logger\";\nimport type { SchedulerRunSummary, TargetStatus } from \"@lage-run/scheduler-types\";\nimport type { TargetLogData, TargetStatusData } from \"./types/TargetLogData.js\";\nimport type { Writable } from \"stream\";\nimport crypto from \"crypto\";\nimport { formatBytes } from \"./formatBytes.js\";\nimport { slowestTargetRuns } from \"./slowestTargetRuns.js\";\n\nconst colors = {\n [LogLevel.info]: chalk.white,\n [LogLevel.verbose]: chalk.gray,\n [LogLevel.warn]: chalk.white,\n [LogLevel.error]: chalk.hex(\"#FF1010\"),\n [LogLevel.silly]: chalk.green,\n task: chalk.hex(\"#00DDDD\"),\n pkg: chalk.hex(\"#FFD66B\"),\n ok: chalk.green,\n error: chalk.red,\n warn: chalk.yellow,\n};\n\n// Monokai color scheme\nconst pkgColors: Chalk[] = [\n chalk.hex(\"#e5b567\"),\n chalk.hex(\"#b4d273\"),\n chalk.hex(\"#e87d3e\"),\n chalk.hex(\"#9e86c8\"),\n chalk.hex(\"#b05279\"),\n chalk.hex(\"#6c99bb\"),\n];\n\nfunction hashStringToNumber(str: string): number {\n const hash = crypto.createHash(\"md5\");\n hash.update(str);\n const hex = hash.digest(\"hex\").substring(0, 6);\n return parseInt(hex, 16);\n}\n\nconst pkgNameToIndexInPkgColorArray = new Map<string, number>();\n\nfunction getColorForPkg(pkg: string): Chalk {\n if (!pkgNameToIndexInPkgColorArray.has(pkg)) {\n const index = hashStringToNumber(pkg) % pkgColors.length;\n pkgNameToIndexInPkgColorArray.set(pkg, index);\n }\n\n return pkgColors[pkgNameToIndexInPkgColorArray.get(pkg)!];\n}\n\nconst stripAnsiRegex = ansiRegex();\n\nfunction getTaskLogPrefix(pkg: string, task: string) {\n const pkgColor = getColorForPkg(pkg);\n return `${pkgColor(pkg)} ${colors.task(task)}`;\n}\n\nfunction stripAnsi(message: string) {\n return message.replace(stripAnsiRegex, \"\");\n}\n\nfunction normalize(prefixOrMessage: string, message?: string) {\n if (typeof message === \"string\") {\n return { prefix: prefixOrMessage, message };\n }\n return { prefix: \"\", message: prefixOrMessage };\n}\n\nexport class LogReporter implements Reporter {\n private logStream: Writable;\n private logEntries = new Map<string, LogEntry[]>();\n\n constructor(\n private options: {\n logLevel?: LogLevel;\n grouped?: boolean;\n /** stream for testing */\n logStream?: Writable;\n }\n ) {\n options.logLevel = options.logLevel || LogLevel.info;\n this.logStream = options.logStream || process.stdout;\n }\n\n public log(entry: LogEntry<any>): void {\n // if \"hidden\", do not even attempt to record or report the entry\n if (entry?.data?.target?.hidden) {\n return;\n }\n\n // save the logs for errors\n if (entry.data?.target?.id) {\n if (!this.logEntries.has(entry.data.target.id)) {\n this.logEntries.set(entry.data.target.id, []);\n }\n this.logEntries.get(entry.data.target.id)!.push(entry);\n }\n\n // if loglevel is not high enough, do not report the entry\n if (this.options.logLevel! < entry.level) {\n return;\n }\n\n // log to grouped entries\n if (this.options.grouped && entry.data?.target) {\n return this.logTargetEntryByGroup(entry);\n }\n\n // log normal target entries\n if (entry.data && entry.data.target) {\n return this.logTargetEntry(entry);\n }\n\n // log generic entries (not related to target)\n if (entry.msg) {\n return this.print(entry.msg);\n }\n }\n\n private printEntry(entry: LogEntry<any>, message: string) {\n let prefix = \"\";\n let msg = message;\n\n if (entry?.data?.target) {\n const { packageName, task } = entry.data.target;\n const normalizedArgs = normalize(getTaskLogPrefix(packageName ?? \"<root>\", task), msg);\n prefix = normalizedArgs.prefix;\n msg = normalizedArgs.message;\n }\n\n this.print(`${prefix ? prefix + \" \" : \"\"}${msg}`);\n }\n\n private print(message: string) {\n this.logStream.write(message + \"\\n\");\n }\n\n private logTargetEntry(entry: LogEntry<TargetLogData>) {\n const colorFn = colors[entry.level];\n const data = entry.data!;\n\n if (isTargetStatusLogEntry(data)) {\n const { hash, duration } = data;\n switch (data.status) {\n case \"running\":\n return this.printEntry(entry, colorFn(`${colors.ok(\"➔\")} start`));\n\n case \"success\":\n return this.printEntry(entry, colorFn(`${colors.ok(\"✓\")} done - ${formatDuration(hrToSeconds(duration!))}`));\n\n case \"failed\":\n return this.printEntry(entry, colorFn(`${colors.error(\"✖\")} fail`));\n\n case \"skipped\":\n return this.printEntry(entry, colorFn(`${colors.ok(\"»\")} skip - ${hash!}`));\n\n case \"aborted\":\n return this.printEntry(entry, colorFn(`${colors.warn(\"-\")} aborted`));\n\n case \"queued\":\n return this.printEntry(entry, colorFn(`${colors.warn(\"…\")} queued`));\n }\n } else {\n return this.printEntry(entry, colorFn(\": \" + stripAnsi(entry.msg)));\n }\n }\n\n private logTargetEntryByGroup(entry: LogEntry<TargetLogData>) {\n const data = entry.data!;\n\n const target = data.target;\n const { id } = target;\n\n if (\n isTargetStatusLogEntry(data) &&\n (data.status === \"success\" || data.status === \"failed\" || data.status === \"skipped\" || data.status === \"aborted\")\n ) {\n const entries = this.logEntries.get(id)! as LogEntry<TargetStatusData>[];\n\n for (const targetEntry of entries) {\n this.logTargetEntry(targetEntry);\n }\n\n if (entries.length > 2) {\n this.hr();\n }\n }\n }\n\n private hr(): void {\n this.print(\"┈\".repeat(80));\n }\n\n public summarize(schedulerRunSummary: SchedulerRunSummary): void {\n const { targetRuns, targetRunByStatus, duration } = schedulerRunSummary;\n const { failed, aborted, skipped, success, pending } = targetRunByStatus;\n\n const statusColorFn: {\n [status in TargetStatus]: chalk.Chalk;\n } = {\n success: chalk.greenBright,\n failed: chalk.redBright,\n skipped: chalk.gray,\n running: chalk.yellow,\n pending: chalk.gray,\n aborted: chalk.red,\n queued: chalk.magenta,\n };\n\n if (targetRuns.size > 0) {\n this.print(chalk.cyanBright(`\\nSummary`));\n\n this.hr();\n\n const slowestTargets = slowestTargetRuns([...targetRuns.values()]);\n\n for (const wrappedTarget of slowestTargets) {\n if (wrappedTarget.target.hidden) {\n continue;\n }\n\n const colorFn = statusColorFn[wrappedTarget.status] ?? chalk.white;\n const target = wrappedTarget.target;\n const hasDurations = !!wrappedTarget.duration && !!wrappedTarget.queueTime;\n const queueDuration: [number, number] = hasDurations ? hrtimeDiff(wrappedTarget.queueTime, wrappedTarget.startTime) : [0, 0];\n\n this.print(\n `${getTaskLogPrefix(target.packageName || \"<root>\", target.task)} ${colorFn(\n `${wrappedTarget.status === \"running\" ? \"running - incomplete\" : wrappedTarget.status}${\n hasDurations\n ? `, took ${formatDuration(hrToSeconds(wrappedTarget.duration))}, queued for ${formatDuration(hrToSeconds(queueDuration))}`\n : \"\"\n }`\n )}`\n );\n }\n\n this.print(\n `success: ${success.length}, skipped: ${skipped.length}, pending: ${pending.length}, aborted: ${aborted.length}, failed: ${failed.length}`\n );\n\n this.print(\n `worker restarts: ${schedulerRunSummary.workerRestarts}, max worker memory usage: ${formatBytes(\n schedulerRunSummary.maxWorkerMemoryUsage\n )}`\n );\n } else {\n this.print(\"Nothing has been run.\");\n }\n\n this.hr();\n\n if (failed && failed.length > 0) {\n for (const targetId of failed) {\n const target = targetRuns.get(targetId)?.target;\n\n if (target) {\n const { packageName, task } = target;\n const failureLogs = this.logEntries.get(targetId);\n\n this.print(`[${colors.pkg(packageName ?? \"<root>\")} ${colors.task(task)}] ${colors[LogLevel.error](\"ERROR DETECTED\")}`);\n\n if (failureLogs) {\n for (const entry of failureLogs) {\n // Log each entry separately to prevent truncation\n this.print(entry.msg);\n }\n }\n\n this.hr();\n }\n }\n }\n\n const allCacheHits = [...targetRuns.values()].filter((run) => !run.target.hidden).length === skipped.length;\n const allCacheHitText = allCacheHits ? gradient({ r: 237, g: 178, b: 77 }, \"cyan\")(`All targets skipped!`) : \"\";\n\n this.print(`Took a total of ${formatDuration(hrToSeconds(duration))} to complete. ${allCacheHitText}`);\n }\n\n public resetLogEntries(): void {\n this.logEntries.clear();\n }\n}\n"],"names":["LogReporter","colors","LogLevel","info","chalk","white","verbose","gray","warn","error","hex","silly","green","task","pkg","ok","red","yellow","pkgColors","hashStringToNumber","str","hash","crypto","createHash","update","digest","substring","parseInt","pkgNameToIndexInPkgColorArray","Map","getColorForPkg","has","index","length","set","get","stripAnsiRegex","ansiRegex","getTaskLogPrefix","pkgColor","stripAnsi","message","replace","normalize","prefixOrMessage","prefix","log","entry","data","target","hidden","id","logEntries","push","options","logLevel","level","grouped","logTargetEntryByGroup","logTargetEntry","msg","print","printEntry","packageName","normalizedArgs","logStream","write","colorFn","isTargetStatusLogEntry","duration","status","formatDuration","hrToSeconds","entries","targetEntry","hr","repeat","summarize","schedulerRunSummary","targetRuns","targetRunByStatus","failed","aborted","skipped","success","pending","statusColorFn","greenBright","redBright","running","queued","magenta","size","cyanBright","slowestTargets","slowestTargetRuns","values","wrappedTarget","hasDurations","queueTime","queueDuration","hrtimeDiff","startTime","workerRestarts","formatBytes","maxWorkerMemoryUsage","targetId","failureLogs","allCacheHits","filter","run","allCacheHitText","gradient","r","g","b","resetLogEntries","clear","process","stdout"],"mappings":";;;;+BA0EaA;;;eAAAA;;;8BA1E2C;wCACjB;wBACd;kEACH;8DACJ;0BAEO;+DAKN;6BACS;mCACM;;;;;;;;;;;;;;;;;;;AAElC,MAAMC,SAAS;IACb,CAACC,gBAAQ,CAACC,IAAI,CAAC,EAAEC,cAAK,CAACC,KAAK;IAC5B,CAACH,gBAAQ,CAACI,OAAO,CAAC,EAAEF,cAAK,CAACG,IAAI;IAC9B,CAACL,gBAAQ,CAACM,IAAI,CAAC,EAAEJ,cAAK,CAACC,KAAK;IAC5B,CAACH,gBAAQ,CAACO,KAAK,CAAC,EAAEL,cAAK,CAACM,GAAG,CAAC;IAC5B,CAACR,gBAAQ,CAACS,KAAK,CAAC,EAAEP,cAAK,CAACQ,KAAK;IAC7BC,MAAMT,cAAK,CAACM,GAAG,CAAC;IAChBI,KAAKV,cAAK,CAACM,GAAG,CAAC;IACfK,IAAIX,cAAK,CAACQ,KAAK;IACfH,OAAOL,cAAK,CAACY,GAAG;IAChBR,MAAMJ,cAAK,CAACa,MAAM;AACpB;AAEA,uBAAuB;AACvB,MAAMC,YAAqB;IACzBd,cAAK,CAACM,GAAG,CAAC;IACVN,cAAK,CAACM,GAAG,CAAC;IACVN,cAAK,CAACM,GAAG,CAAC;IACVN,cAAK,CAACM,GAAG,CAAC;IACVN,cAAK,CAACM,GAAG,CAAC;IACVN,cAAK,CAACM,GAAG,CAAC;CACX;AAED,SAASS,mBAAmBC,GAAW;IACrC,MAAMC,OAAOC,eAAM,CAACC,UAAU,CAAC;IAC/BF,KAAKG,MAAM,CAACJ;IACZ,MAAMV,MAAMW,KAAKI,MAAM,CAAC,OAAOC,SAAS,CAAC,GAAG;IAC5C,OAAOC,SAASjB,KAAK;AACvB;AAEA,MAAMkB,gCAAgC,IAAIC;AAE1C,SAASC,eAAehB,GAAW;IACjC,IAAI,CAACc,8BAA8BG,GAAG,CAACjB,MAAM;QAC3C,MAAMkB,QAAQb,mBAAmBL,OAAOI,UAAUe,MAAM;QACxDL,8BAA8BM,GAAG,CAACpB,KAAKkB;IACzC;IAEA,OAAOd,SAAS,CAACU,8BAA8BO,GAAG,CAACrB,KAAM;AAC3D;AAEA,MAAMsB,iBAAiBC,IAAAA,kBAAS;AAEhC,SAASC,iBAAiBxB,GAAW,EAAED,IAAY;IACjD,MAAM0B,WAAWT,eAAehB;IAChC,OAAO,GAAGyB,SAASzB,KAAK,CAAC,EAAEb,OAAOY,IAAI,CAACA,OAAO;AAChD;AAEA,SAAS2B,UAAUC,OAAe;IAChC,OAAOA,QAAQC,OAAO,CAACN,gBAAgB;AACzC;AAEA,SAASO,UAAUC,eAAuB,EAAEH,OAAgB;IAC1D,IAAI,OAAOA,YAAY,UAAU;QAC/B,OAAO;YAAEI,QAAQD;YAAiBH;QAAQ;IAC5C;IACA,OAAO;QAAEI,QAAQ;QAAIJ,SAASG;IAAgB;AAChD;AAEO,MAAM5C;IAgBJ8C,IAAIC,KAAoB,EAAQ;QACrC,iEAAiE;QACjE,IAAIA,OAAOC,MAAMC,QAAQC,QAAQ;YAC/B;QACF;QAEA,2BAA2B;QAC3B,IAAIH,MAAMC,IAAI,EAAEC,QAAQE,IAAI;YAC1B,IAAI,CAAC,IAAI,CAACC,UAAU,CAACrB,GAAG,CAACgB,MAAMC,IAAI,CAACC,MAAM,CAACE,EAAE,GAAG;gBAC9C,IAAI,CAACC,UAAU,CAAClB,GAAG,CAACa,MAAMC,IAAI,CAACC,MAAM,CAACE,EAAE,EAAE,EAAE;YAC9C;YACA,IAAI,CAACC,UAAU,CAACjB,GAAG,CAACY,MAAMC,IAAI,CAACC,MAAM,CAACE,EAAE,EAAGE,IAAI,CAACN;QAClD;QAEA,0DAA0D;QAC1D,IAAI,IAAI,CAACO,OAAO,CAACC,QAAQ,GAAIR,MAAMS,KAAK,EAAE;YACxC;QACF;QAEA,yBAAyB;QACzB,IAAI,IAAI,CAACF,OAAO,CAACG,OAAO,IAAIV,MAAMC,IAAI,EAAEC,QAAQ;YAC9C,OAAO,IAAI,CAACS,qBAAqB,CAACX;QACpC;QAEA,4BAA4B;QAC5B,IAAIA,MAAMC,IAAI,IAAID,MAAMC,IAAI,CAACC,MAAM,EAAE;YACnC,OAAO,IAAI,CAACU,cAAc,CAACZ;QAC7B;QAEA,8CAA8C;QAC9C,IAAIA,MAAMa,GAAG,EAAE;YACb,OAAO,IAAI,CAACC,KAAK,CAACd,MAAMa,GAAG;QAC7B;IACF;IAEQE,WAAWf,KAAoB,EAAEN,OAAe,EAAE;QACxD,IAAII,SAAS;QACb,IAAIe,MAAMnB;QAEV,IAAIM,OAAOC,MAAMC,QAAQ;YACvB,MAAM,EAAEc,WAAW,EAAElD,IAAI,EAAE,GAAGkC,MAAMC,IAAI,CAACC,MAAM;YAC/C,MAAMe,iBAAiBrB,UAAUL,iBAAiByB,eAAe,UAAUlD,OAAO+C;YAClFf,SAASmB,eAAenB,MAAM;YAC9Be,MAAMI,eAAevB,OAAO;QAC9B;QAEA,IAAI,CAACoB,KAAK,CAAC,GAAGhB,SAASA,SAAS,MAAM,KAAKe,KAAK;IAClD;IAEQC,MAAMpB,OAAe,EAAE;QAC7B,IAAI,CAACwB,SAAS,CAACC,KAAK,CAACzB,UAAU;IACjC;IAEQkB,eAAeZ,KAA8B,EAAE;QACrD,MAAMoB,UAAUlE,MAAM,CAAC8C,MAAMS,KAAK,CAAC;QACnC,MAAMR,OAAOD,MAAMC,IAAI;QAEvB,IAAIoB,IAAAA,8CAAsB,EAACpB,OAAO;YAChC,MAAM,EAAE3B,IAAI,EAAEgD,QAAQ,EAAE,GAAGrB;YAC3B,OAAQA,KAAKsB,MAAM;gBACjB,KAAK;oBACH,OAAO,IAAI,CAACR,UAAU,CAACf,OAAOoB,QAAQ,GAAGlE,OAAOc,EAAE,CAAC,KAAK,MAAM,CAAC;gBAEjE,KAAK;oBACH,OAAO,IAAI,CAAC+C,UAAU,CAACf,OAAOoB,QAAQ,GAAGlE,OAAOc,EAAE,CAAC,KAAK,QAAQ,EAAEwD,IAAAA,4BAAc,EAACC,IAAAA,yBAAW,EAACH,YAAa;gBAE5G,KAAK;oBACH,OAAO,IAAI,CAACP,UAAU,CAACf,OAAOoB,QAAQ,GAAGlE,OAAOQ,KAAK,CAAC,KAAK,KAAK,CAAC;gBAEnE,KAAK;oBACH,OAAO,IAAI,CAACqD,UAAU,CAACf,OAAOoB,QAAQ,GAAGlE,OAAOc,EAAE,CAAC,KAAK,QAAQ,EAAEM,MAAO;gBAE3E,KAAK;oBACH,OAAO,IAAI,CAACyC,UAAU,CAACf,OAAOoB,QAAQ,GAAGlE,OAAOO,IAAI,CAAC,KAAK,QAAQ,CAAC;gBAErE,KAAK;oBACH,OAAO,IAAI,CAACsD,UAAU,CAACf,OAAOoB,QAAQ,GAAGlE,OAAOO,IAAI,CAAC,KAAK,OAAO,CAAC;YACtE;QACF,OAAO;YACL,OAAO,IAAI,CAACsD,UAAU,CAACf,OAAOoB,QAAQ,QAAQ3B,UAAUO,MAAMa,GAAG;QACnE;IACF;IAEQF,sBAAsBX,KAA8B,EAAE;QAC5D,MAAMC,OAAOD,MAAMC,IAAI;QAEvB,MAAMC,SAASD,KAAKC,MAAM;QAC1B,MAAM,EAAEE,EAAE,EAAE,GAAGF;QAEf,IACEmB,IAAAA,8CAAsB,EAACpB,SACtBA,CAAAA,KAAKsB,MAAM,KAAK,aAAatB,KAAKsB,MAAM,KAAK,YAAYtB,KAAKsB,MAAM,KAAK,aAAatB,KAAKsB,MAAM,KAAK,SAAQ,GAC/G;YACA,MAAMG,UAAU,IAAI,CAACrB,UAAU,CAACjB,GAAG,CAACgB;YAEpC,KAAK,MAAMuB,eAAeD,QAAS;gBACjC,IAAI,CAACd,cAAc,CAACe;YACtB;YAEA,IAAID,QAAQxC,MAAM,GAAG,GAAG;gBACtB,IAAI,CAAC0C,EAAE;YACT;QACF;IACF;IAEQA,KAAW;QACjB,IAAI,CAACd,KAAK,CAAC,IAAIe,MAAM,CAAC;IACxB;IAEOC,UAAUC,mBAAwC,EAAQ;QAC/D,MAAM,EAAEC,UAAU,EAAEC,iBAAiB,EAAEX,QAAQ,EAAE,GAAGS;QACpD,MAAM,EAAEG,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAEC,OAAO,EAAEC,OAAO,EAAE,GAAGL;QAEvD,MAAMM,gBAEF;YACFF,SAAShF,cAAK,CAACmF,WAAW;YAC1BN,QAAQ7E,cAAK,CAACoF,SAAS;YACvBL,SAAS/E,cAAK,CAACG,IAAI;YACnBkF,SAASrF,cAAK,CAACa,MAAM;YACrBoE,SAASjF,cAAK,CAACG,IAAI;YACnB2E,SAAS9E,cAAK,CAACY,GAAG;YAClB0E,QAAQtF,cAAK,CAACuF,OAAO;QACvB;QAEA,IAAIZ,WAAWa,IAAI,GAAG,GAAG;YACvB,IAAI,CAAC/B,KAAK,CAACzD,cAAK,CAACyF,UAAU,CAAC,CAAC,SAAS,CAAC;YAEvC,IAAI,CAAClB,EAAE;YAEP,MAAMmB,iBAAiBC,IAAAA,oCAAiB,EAAC;mBAAIhB,WAAWiB,MAAM;aAAG;YAEjE,KAAK,MAAMC,iBAAiBH,eAAgB;gBAC1C,IAAIG,cAAchD,MAAM,CAACC,MAAM,EAAE;oBAC/B;gBACF;gBAEA,MAAMiB,UAAUmB,aAAa,CAACW,cAAc3B,MAAM,CAAC,IAAIlE,cAAK,CAACC,KAAK;gBAClE,MAAM4C,SAASgD,cAAchD,MAAM;gBACnC,MAAMiD,eAAe,CAAC,CAACD,cAAc5B,QAAQ,IAAI,CAAC,CAAC4B,cAAcE,SAAS;gBAC1E,MAAMC,gBAAkCF,eAAeG,IAAAA,wBAAU,EAACJ,cAAcE,SAAS,EAAEF,cAAcK,SAAS,IAAI;oBAAC;oBAAG;iBAAE;gBAE5H,IAAI,CAACzC,KAAK,CACR,GAAGvB,iBAAiBW,OAAOc,WAAW,IAAI,UAAUd,OAAOpC,IAAI,EAAE,CAAC,EAAEsD,QAClE,GAAG8B,cAAc3B,MAAM,KAAK,YAAY,yBAAyB2B,cAAc3B,MAAM,GACnF4B,eACI,CAAC,OAAO,EAAE3B,IAAAA,4BAAc,EAACC,IAAAA,yBAAW,EAACyB,cAAc5B,QAAQ,GAAG,aAAa,EAAEE,IAAAA,4BAAc,EAACC,IAAAA,yBAAW,EAAC4B,iBAAiB,GACzH,IACJ,GACD;YAEP;YAEA,IAAI,CAACvC,KAAK,CACR,CAAC,SAAS,EAAEuB,QAAQnD,MAAM,CAAC,WAAW,EAAEkD,QAAQlD,MAAM,CAAC,WAAW,EAAEoD,QAAQpD,MAAM,CAAC,WAAW,EAAEiD,QAAQjD,MAAM,CAAC,UAAU,EAAEgD,OAAOhD,MAAM,EAAE;YAG5I,IAAI,CAAC4B,KAAK,CACR,CAAC,iBAAiB,EAAEiB,oBAAoByB,cAAc,CAAC,2BAA2B,EAAEC,IAAAA,wBAAW,EAC7F1B,oBAAoB2B,oBAAoB,GACvC;QAEP,OAAO;YACL,IAAI,CAAC5C,KAAK,CAAC;QACb;QAEA,IAAI,CAACc,EAAE;QAEP,IAAIM,UAAUA,OAAOhD,MAAM,GAAG,GAAG;YAC/B,KAAK,MAAMyE,YAAYzB,OAAQ;gBAC7B,MAAMhC,SAAS8B,WAAW5C,GAAG,CAACuE,WAAWzD;gBAEzC,IAAIA,QAAQ;oBACV,MAAM,EAAEc,WAAW,EAAElD,IAAI,EAAE,GAAGoC;oBAC9B,MAAM0D,cAAc,IAAI,CAACvD,UAAU,CAACjB,GAAG,CAACuE;oBAExC,IAAI,CAAC7C,KAAK,CAAC,CAAC,CAAC,EAAE5D,OAAOa,GAAG,CAACiD,eAAe,UAAU,CAAC,EAAE9D,OAAOY,IAAI,CAACA,MAAM,EAAE,EAAEZ,MAAM,CAACC,gBAAQ,CAACO,KAAK,CAAC,CAAC,mBAAmB;oBAEtH,IAAIkG,aAAa;wBACf,KAAK,MAAM5D,SAAS4D,YAAa;4BAC/B,kDAAkD;4BAClD,IAAI,CAAC9C,KAAK,CAACd,MAAMa,GAAG;wBACtB;oBACF;oBAEA,IAAI,CAACe,EAAE;gBACT;YACF;QACF;QAEA,MAAMiC,eAAe;eAAI7B,WAAWiB,MAAM;SAAG,CAACa,MAAM,CAAC,CAACC,MAAQ,CAACA,IAAI7D,MAAM,CAACC,MAAM,EAAEjB,MAAM,KAAKkD,QAAQlD,MAAM;QAC3G,MAAM8E,kBAAkBH,eAAeI,IAAAA,kBAAQ,EAAC;YAAEC,GAAG;YAAKC,GAAG;YAAKC,GAAG;QAAG,GAAG,QAAQ,CAAC,oBAAoB,CAAC,IAAI;QAE7G,IAAI,CAACtD,KAAK,CAAC,CAAC,gBAAgB,EAAEU,IAAAA,4BAAc,EAACC,IAAAA,yBAAW,EAACH,WAAW,cAAc,EAAE0C,iBAAiB;IACvG;IAEOK,kBAAwB;QAC7B,IAAI,CAAChE,UAAU,CAACiE,KAAK;IACvB;IAlNA,YACE,AAAQ/D,OAKP,CACD;;QAVF,uBAAQW,aAAR,KAAA;QACA,uBAAQb,cAAR,KAAA;aAGUE,UAAAA;aAHFF,aAAa,IAAIvB;QAUvByB,QAAQC,QAAQ,GAAGD,QAAQC,QAAQ,IAAIrD,gBAAQ,CAACC,IAAI;QACpD,IAAI,CAAC8D,SAAS,GAAGX,QAAQW,SAAS,IAAIqD,QAAQC,MAAM;IACtD;AAyMF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/VerboseFileLogReporter.ts"],"sourcesContent":["import { formatDuration, hrToSeconds } from \"@lage-run/format-hrtime\";\nimport { isTargetStatusLogEntry } from \"./isTargetStatusLogEntry.js\";\nimport { LogLevel } from \"@lage-run/logger\";\nimport ansiRegex from \"ansi-regex\";\nimport type { Reporter, LogEntry } from \"@lage-run/logger\";\nimport type { TargetMessageEntry, TargetStatusEntry } from \"./types/TargetLogEntry.js\";\nimport { Writable } from \"stream\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport type { TargetStatus } from \"@lage-run/scheduler-types\";\n\nconst stripAnsiRegex = ansiRegex();\n\nfunction stripAnsi(message: string) {\n return message.replace(stripAnsiRegex, \"\");\n}\n\nexport class VerboseFileLogReporter implements Reporter {\n private fileStream: Writable;\n\n /**\n * @param logFile Log file path from CLI args\n * @param fileStream Stream for testing\n */\n constructor(logFile?: string, fileStream?: Writable) {\n // if logFile is falsy (not specified on cli args), this.fileStream just become a \"nowhere\" stream and this reporter effectively does nothing\n if (logFile) {\n const logFileDir = path.dirname(path.resolve(logFile));\n if (!fs.existsSync(logFileDir)) {\n fs.mkdirSync(logFileDir, { recursive: true });\n }\n }\n\n this.fileStream = fileStream ?? (logFile ? fs.createWriteStream(logFile) : new Writable({ write() {} }));\n }\n\n public cleanup(): void {\n this.fileStream.end();\n }\n\n public log(entry: LogEntry<any>): void {\n // if \"hidden\", do not even attempt to record or report the entry\n if (entry?.data?.target?.hidden) {\n return;\n }\n\n // if loglevel is not high enough, do not report the entry\n if (LogLevel.verbose < entry.level) {\n return;\n }\n\n // log normal target entries\n if (entry.data && entry.data.target) {\n return this.logTargetEntry(entry);\n }\n\n // log generic entries (not related to target)\n if (entry.msg) {\n return this.print(`${entry.msg}`);\n }\n }\n\n private printEntry(entry: LogEntry<any>, message: string) {\n let packageAndTask = \"\";\n\n if (entry?.data?.target) {\n const { packageName, task } = entry.data.target;\n const pkg = packageName ?? \"<root>\";\n\n packageAndTask = `${pkg} ${task}`.trim();\n }\n\n this.print(`${this.getEntryTargetId(entry)} ${packageAndTask} ${message}`.trim());\n }\n\n private getEntryTargetId(entry: LogEntry<any>) {\n if (entry.data?.target?.id) {\n return `[:${entry.data.target.id}:]`;\n }\n\n return \"\";\n }\n\n private print(message: string) {\n this.fileStream.write(message + \"\\n\");\n }\n\n private logTargetEntry(entry: LogEntry<TargetStatusEntry | TargetMessageEntry>) {\n const data = entry.data!;\n\n if (isTargetStatusLogEntry(data)) {\n const { hash, duration, status } = data;\n const statusMessages: Record<TargetStatus, string> = {\n running: \"➔ start\",\n success: `✓ done - ${duration && formatDuration(hrToSeconds(duration))}`,\n failed: \"✖ fail\",\n skipped: `» skip - ${hash}`,\n aborted: \"- aborted\",\n queued: \"… queued\",\n pending: \"… pending\",\n };\n\n return this.printEntry(entry, statusMessages[status]);\n } else {\n const defaultMessage = `: ${stripAnsi(entry.msg)}`;\n return this.printEntry(entry, defaultMessage);\n }\n }\n\n public summarize(): void {\n // No summary needed for VerboseFileLogReporter\n }\n}\n"],"names":["VerboseFileLogReporter","stripAnsiRegex","ansiRegex","stripAnsi","message","replace","cleanup","fileStream","end","log","entry","data","target","hidden","LogLevel","verbose","level","logTargetEntry","msg","print","printEntry","packageAndTask","packageName","task","pkg","trim","getEntryTargetId","id","write","isTargetStatusLogEntry","hash","duration","status","statusMessages","running","success","formatDuration","hrToSeconds","failed","skipped","aborted","queued","pending","defaultMessage","summarize","logFile","logFileDir","path","dirname","resolve","fs","existsSync","mkdirSync","recursive","createWriteStream","Writable"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/VerboseFileLogReporter.ts"],"sourcesContent":["import { formatDuration, hrToSeconds } from \"@lage-run/format-hrtime\";\nimport { isTargetStatusLogEntry } from \"./isTargetStatusLogEntry.js\";\nimport { LogLevel } from \"@lage-run/logger\";\nimport ansiRegex from \"ansi-regex\";\nimport type { Reporter, LogEntry } from \"@lage-run/logger\";\nimport type { TargetLogData } from \"./types/TargetLogData.js\";\nimport { Writable } from \"stream\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport type { TargetStatus } from \"@lage-run/scheduler-types\";\n\nconst stripAnsiRegex = ansiRegex();\n\nfunction stripAnsi(message: string) {\n return message.replace(stripAnsiRegex, \"\");\n}\n\nexport class VerboseFileLogReporter implements Reporter {\n private fileStream: Writable;\n\n /**\n * @param logFile Log file path from CLI args\n * @param fileStream Stream for testing\n */\n constructor(logFile?: string, fileStream?: Writable) {\n // if logFile is falsy (not specified on cli args), this.fileStream just become a \"nowhere\" stream and this reporter effectively does nothing\n if (logFile) {\n const logFileDir = path.dirname(path.resolve(logFile));\n if (!fs.existsSync(logFileDir)) {\n fs.mkdirSync(logFileDir, { recursive: true });\n }\n }\n\n this.fileStream = fileStream ?? (logFile ? fs.createWriteStream(logFile) : new Writable({ write() {} }));\n }\n\n public cleanup(): void {\n this.fileStream.end();\n }\n\n public log(entry: LogEntry<any>): void {\n // if \"hidden\", do not even attempt to record or report the entry\n if (entry?.data?.target?.hidden) {\n return;\n }\n\n // if loglevel is not high enough, do not report the entry\n if (LogLevel.verbose < entry.level) {\n return;\n }\n\n // log normal target entries\n if (entry.data && entry.data.target) {\n return this.logTargetEntry(entry);\n }\n\n // log generic entries (not related to target)\n if (entry.msg) {\n return this.print(`${entry.msg}`);\n }\n }\n\n private printEntry(entry: LogEntry<any>, message: string) {\n let packageAndTask = \"\";\n\n if (entry?.data?.target) {\n const { packageName, task } = entry.data.target;\n const pkg = packageName ?? \"<root>\";\n\n packageAndTask = `${pkg} ${task}`.trim();\n }\n\n this.print(`${this.getEntryTargetId(entry)} ${packageAndTask} ${message}`.trim());\n }\n\n private getEntryTargetId(entry: LogEntry<any>) {\n if (entry.data?.target?.id) {\n return `[:${entry.data.target.id}:]`;\n }\n\n return \"\";\n }\n\n private print(message: string) {\n this.fileStream.write(message + \"\\n\");\n }\n\n private logTargetEntry(entry: LogEntry<TargetLogData>) {\n const data = entry.data!;\n\n if (isTargetStatusLogEntry(data)) {\n const { hash, duration, status } = data;\n const statusMessages: Record<TargetStatus, string> = {\n running: \"➔ start\",\n success: `✓ done - ${duration && formatDuration(hrToSeconds(duration))}`,\n failed: \"✖ fail\",\n skipped: `» skip - ${hash}`,\n aborted: \"- aborted\",\n queued: \"… queued\",\n pending: \"… pending\",\n };\n\n return this.printEntry(entry, statusMessages[status]);\n } else {\n const defaultMessage = `: ${stripAnsi(entry.msg)}`;\n return this.printEntry(entry, defaultMessage);\n }\n }\n\n public summarize(): void {\n // No summary needed for VerboseFileLogReporter\n }\n}\n"],"names":["VerboseFileLogReporter","stripAnsiRegex","ansiRegex","stripAnsi","message","replace","cleanup","fileStream","end","log","entry","data","target","hidden","LogLevel","verbose","level","logTargetEntry","msg","print","printEntry","packageAndTask","packageName","task","pkg","trim","getEntryTargetId","id","write","isTargetStatusLogEntry","hash","duration","status","statusMessages","running","success","formatDuration","hrToSeconds","failed","skipped","aborted","queued","pending","defaultMessage","summarize","logFile","logFileDir","path","dirname","resolve","fs","existsSync","mkdirSync","recursive","createWriteStream","Writable"],"mappings":"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"}
package/lib/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  export { AdoReporter } from "./AdoReporter.js";
2
2
  export { GithubActionsReporter } from "./GithubActionsReporter.js";
3
3
  export { BasicReporter } from "./BasicReporter.js";
4
- export { JsonReporter } from "./JsonReporter.js";
4
+ export { JsonReporter, type JsonReporterLogData, type JsonReporterSummaryData } from "./JsonReporter.js";
5
5
  export { LogReporter } from "./LogReporter.js";
6
6
  export { ChromeTraceEventsReporter } from "./ChromeTraceEventsReporter.js";
7
7
  export { ProgressReporter } from "./ProgressReporter.js";
8
8
  export { VerboseFileLogReporter } from "./VerboseFileLogReporter.js";
9
- export type { TargetStatusEntry, TargetMessageEntry } from "./types/TargetLogEntry.js";
9
+ export type { TargetStatusData, TargetMessageData, TargetLogData } from "./types/TargetLogData.js";
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { AdoReporter } from \"./AdoReporter.js\";\nexport { GithubActionsReporter } from \"./GithubActionsReporter.js\";\nexport { BasicReporter } from \"./BasicReporter.js\";\nexport { JsonReporter } from \"./JsonReporter.js\";\nexport { LogReporter } from \"./LogReporter.js\";\nexport { ChromeTraceEventsReporter } from \"./ChromeTraceEventsReporter.js\";\nexport { ProgressReporter } from \"./ProgressReporter.js\";\nexport { VerboseFileLogReporter } from \"./VerboseFileLogReporter.js\";\nexport type { TargetStatusEntry, TargetMessageEntry } from \"./types/TargetLogEntry.js\";\n"],"names":["AdoReporter","BasicReporter","ChromeTraceEventsReporter","GithubActionsReporter","JsonReporter","LogReporter","ProgressReporter","VerboseFileLogReporter"],"mappings":";;;;;;;;;;;QAASA;eAAAA,wBAAW;;QAEXC;eAAAA,4BAAa;;QAGbC;eAAAA,oDAAyB;;QAJzBC;eAAAA,4CAAqB;;QAErBC;eAAAA,0BAAY;;QACZC;eAAAA,wBAAW;;QAEXC;eAAAA,kCAAgB;;QAChBC;eAAAA,8CAAsB;;;6BAPH;uCACU;+BACR;8BACD;6BACD;2CACc;kCACT;wCACM"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { AdoReporter } from \"./AdoReporter.js\";\nexport { GithubActionsReporter } from \"./GithubActionsReporter.js\";\nexport { BasicReporter } from \"./BasicReporter.js\";\nexport { JsonReporter, type JsonReporterLogData, type JsonReporterSummaryData } from \"./JsonReporter.js\";\nexport { LogReporter } from \"./LogReporter.js\";\nexport { ChromeTraceEventsReporter } from \"./ChromeTraceEventsReporter.js\";\nexport { ProgressReporter } from \"./ProgressReporter.js\";\nexport { VerboseFileLogReporter } from \"./VerboseFileLogReporter.js\";\nexport type { TargetStatusData, TargetMessageData, TargetLogData } from \"./types/TargetLogData.js\";\n"],"names":["AdoReporter","BasicReporter","ChromeTraceEventsReporter","GithubActionsReporter","JsonReporter","LogReporter","ProgressReporter","VerboseFileLogReporter"],"mappings":";;;;;;;;;;;QAASA;eAAAA,wBAAW;;QAEXC;eAAAA,4BAAa;;QAGbC;eAAAA,oDAAyB;;QAJzBC;eAAAA,4CAAqB;;QAErBC;eAAAA,0BAAY;;QACZC;eAAAA,wBAAW;;QAEXC;eAAAA,kCAAgB;;QAChBC;eAAAA,8CAAsB;;;6BAPH;uCACU;+BACR;8BACuD;6BACzD;2CACc;kCACT;wCACM"}
@@ -1,3 +1,3 @@
1
1
  import type { LogStructuredData } from "@lage-run/logger";
2
- import type { TargetStatusEntry } from "./types/TargetLogEntry.js";
3
- export declare function isTargetStatusLogEntry(data?: LogStructuredData): data is TargetStatusEntry;
2
+ import type { TargetStatusData } from "./types/TargetLogData.js";
3
+ export declare function isTargetStatusLogEntry(data?: LogStructuredData): data is TargetStatusData;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/isTargetStatusLogEntry.ts"],"sourcesContent":["import type { LogStructuredData } from \"@lage-run/logger\";\nimport type { TargetStatusEntry } from \"./types/TargetLogEntry.js\";\n\nexport function isTargetStatusLogEntry(data?: LogStructuredData): data is TargetStatusEntry {\n return data !== undefined && data.target && data.status !== undefined;\n}\n"],"names":["isTargetStatusLogEntry","data","undefined","target","status"],"mappings":";;;;+BAGgBA;;;eAAAA;;;AAAT,SAASA,uBAAuBC,IAAwB;IAC7D,OAAOA,SAASC,aAAaD,KAAKE,MAAM,IAAIF,KAAKG,MAAM,KAAKF;AAC9D"}
1
+ {"version":3,"sources":["../src/isTargetStatusLogEntry.ts"],"sourcesContent":["import type { LogStructuredData } from \"@lage-run/logger\";\nimport type { TargetStatusData } from \"./types/TargetLogData.js\";\n\nexport function isTargetStatusLogEntry(data?: LogStructuredData): data is TargetStatusData {\n return data !== undefined && data.target && data.status !== undefined;\n}\n"],"names":["isTargetStatusLogEntry","data","undefined","target","status"],"mappings":";;;;+BAGgBA;;;eAAAA;;;AAAT,SAASA,uBAAuBC,IAAwB;IAC7D,OAAOA,SAASC,aAAaD,KAAKE,MAAM,IAAIF,KAAKG,MAAM,KAAKF;AAC9D"}
@@ -0,0 +1,16 @@
1
+ import type { TargetStatus } from "@lage-run/scheduler-types";
2
+ import type { Target } from "@lage-run/target-graph";
3
+ /** `LogEntry.data` for a target status log */
4
+ export interface TargetStatusData {
5
+ target: Target;
6
+ status: TargetStatus;
7
+ duration?: [number, number];
8
+ hash?: string;
9
+ }
10
+ /** `LogEntry.data` for a target message log */
11
+ export interface TargetMessageData {
12
+ target: Target;
13
+ pid: number;
14
+ }
15
+ /** `LogEntry.data` for any target log */
16
+ export type TargetLogData = TargetStatusData | TargetMessageData;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lage-run/reporters",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "Log reporters for Lage",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,10 +18,10 @@
18
18
  "lint": "monorepo-scripts lint"
19
19
  },
20
20
  "dependencies": {
21
- "@lage-run/format-hrtime": "^0.1.8",
21
+ "@lage-run/format-hrtime": "^0.1.9",
22
22
  "@lage-run/logger": "^1.3.3",
23
- "@lage-run/scheduler-types": "^0.3.30",
24
- "@lage-run/target-graph": "^0.13.0",
23
+ "@lage-run/scheduler-types": "^0.3.31",
24
+ "@lage-run/target-graph": "^0.14.0",
25
25
  "@ms-cloudpack/task-reporter": "^0.19.0",
26
26
  "ansi-regex": "^5.0.1",
27
27
  "chalk": "^4.1.2",
@@ -1,12 +0,0 @@
1
- import type { TargetStatus } from "@lage-run/scheduler-types";
2
- import type { Target } from "@lage-run/target-graph";
3
- export interface TargetStatusEntry {
4
- target: Target;
5
- status: TargetStatus;
6
- duration?: [number, number];
7
- hash?: string;
8
- }
9
- export interface TargetMessageEntry {
10
- target: Target;
11
- pid: number;
12
- }