@ts-for-gir/reporter 4.0.0-beta.26

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.
@@ -0,0 +1,566 @@
1
+ /**
2
+ * Console Reporter - A concrete implementation of ReporterBase
3
+ * that provides console logging and comprehensive problem tracking
4
+ */
5
+
6
+ import { writeFile } from "node:fs/promises";
7
+ import { blue, gray, green, red, yellow, yellowBright } from "colorette";
8
+ import { REPORTER_VERSION } from "./constants.ts";
9
+ import { analyzeError, analyzeWarning } from "./message-analyzer.ts";
10
+ import { ReporterBase } from "./reporter-base.ts";
11
+ import type { GenerationReport, ProblemEntry, ReporterConfig, ReportStatistics } from "./types/index.ts";
12
+ import { ProblemCategory, ProblemSeverity } from "./types/index.ts";
13
+
14
+ /**
15
+ * Console Reporter implementation with full logging capabilities
16
+ */
17
+ export class ConsoleReporter extends ReporterBase {
18
+ constructor(config: ReporterConfig);
19
+ constructor(verbose: boolean, moduleName: string, reporterEnabled?: boolean, outputPath?: string);
20
+ constructor(
21
+ configOrVerbose: ReporterConfig | boolean,
22
+ moduleName?: string,
23
+ reporterEnabled = false,
24
+ outputPath?: string,
25
+ ) {
26
+ let config: ReporterConfig;
27
+ if (typeof configOrVerbose === "boolean") {
28
+ // Legacy Logger constructor compatibility
29
+ config = {
30
+ enabled: reporterEnabled,
31
+ verbose: configOrVerbose,
32
+ moduleName: moduleName || "Unknown",
33
+ outputPath,
34
+ };
35
+ } else {
36
+ config = configOrVerbose;
37
+ }
38
+ super(config);
39
+ }
40
+
41
+ // === Logger compatibility methods ===
42
+
43
+ public log(...args: unknown[]): void {
44
+ if (!this.config.verbose) {
45
+ return;
46
+ }
47
+ console.log(...args);
48
+ }
49
+
50
+ public dir(...args: unknown[]): void {
51
+ if (!this.config.verbose) {
52
+ return;
53
+ }
54
+ args.forEach((arg) => {
55
+ console.dir(arg);
56
+ });
57
+ }
58
+
59
+ public info(txt: string, ...args: unknown[]): void {
60
+ if (!this.config.verbose) {
61
+ return;
62
+ }
63
+ console.info(blue(txt), ...args);
64
+ }
65
+
66
+ public warn(txt: string, ...args: unknown[]): void {
67
+ // Analyze message for specific problem types
68
+ if (this.config.enabled) {
69
+ const analyzed = analyzeWarning(txt, args);
70
+ if (analyzed) {
71
+ this.addProblem(
72
+ analyzed.severity,
73
+ analyzed.category,
74
+ txt,
75
+ analyzed.details,
76
+ analyzed.typeName,
77
+ analyzed.namespace || this.config.moduleName,
78
+ analyzed.metadata,
79
+ );
80
+ }
81
+ }
82
+
83
+ if (!this.config.verbose) {
84
+ return;
85
+ }
86
+ const formattedTxt = this.prependInfo(txt, "WARN:");
87
+ console.warn(yellow(formattedTxt), ...args);
88
+ }
89
+
90
+ public debug(txt: string, ...args: unknown[]): void {
91
+ if (!this.config.verbose) {
92
+ return;
93
+ }
94
+ const formattedTxt = this.prependInfo(txt, "DEBUG:");
95
+ console.debug(yellowBright(formattedTxt), ...args);
96
+ }
97
+
98
+ public error(txt: string, ...args: unknown[]): void {
99
+ // Analyze message for specific problem types
100
+ if (this.config.enabled) {
101
+ const analyzed = analyzeError(txt, args);
102
+ if (analyzed) {
103
+ this.addProblem(
104
+ analyzed.severity,
105
+ analyzed.category,
106
+ txt,
107
+ analyzed.details,
108
+ analyzed.typeName,
109
+ analyzed.namespace || this.config.moduleName,
110
+ analyzed.metadata,
111
+ );
112
+ }
113
+ }
114
+
115
+ const formattedTxt = this.prependInfo(txt, "ERROR:");
116
+ this.danger(formattedTxt, ...args);
117
+ }
118
+
119
+ public success(txt: string, ...args: unknown[]): void {
120
+ if (!this.config.verbose) {
121
+ return;
122
+ }
123
+ this.log(green(txt), ...args);
124
+ }
125
+
126
+ public danger(txt: string, ...args: unknown[]): void {
127
+ console.error(red(txt), ...args);
128
+ }
129
+
130
+ public muted(txt: string, ...args: unknown[]): void {
131
+ this.log(gray(txt), ...args);
132
+ }
133
+
134
+ public white(txt: string, ...args: unknown[]): void {
135
+ this.log(txt, ...args);
136
+ }
137
+
138
+ public yellow(txt: string, ...args: unknown[]): void {
139
+ this.log(yellow(txt), ...args);
140
+ }
141
+
142
+ public gray(txt: string, ...args: unknown[]): void {
143
+ this.log(gray(txt), ...args);
144
+ }
145
+
146
+ // === Problem-specific reporting methods ===
147
+
148
+ public reportTypeResolutionError(typeName: string, namespace: string, message: string, details?: string): void {
149
+ this.addProblem(ProblemSeverity.ERROR, ProblemCategory.TYPE_RESOLUTION, message, details, typeName, namespace, {
150
+ namespace,
151
+ typeName,
152
+ });
153
+
154
+ if (this.config.verbose) {
155
+ const txt = this.prependInfo(message, "ERROR:");
156
+ console.error(red(txt));
157
+ }
158
+ }
159
+
160
+ public reportTypeResolutionWarning(typeName: string, namespace: string, message: string, details?: string): void {
161
+ this.addProblem(ProblemSeverity.WARNING, ProblemCategory.TYPE_RESOLUTION, message, details, typeName, namespace, {
162
+ namespace,
163
+ typeName,
164
+ });
165
+
166
+ if (this.config.verbose) {
167
+ const txt = this.prependInfo(message, "WARN:");
168
+ console.warn(yellow(txt));
169
+ }
170
+ }
171
+
172
+ public reportParsingFailure(itemName: string, itemType: string, namespace: string, error: Error | string): void {
173
+ const message = `Failed to parse ${itemType}: ${itemName}`;
174
+ const details = error instanceof Error ? error.message : error;
175
+
176
+ this.addProblem(ProblemSeverity.ERROR, ProblemCategory.PARSING_FAILURE, message, details, itemName, namespace, {
177
+ itemType,
178
+ namespace,
179
+ error: details,
180
+ });
181
+
182
+ if (this.config.verbose) {
183
+ const txt = this.prependInfo(message, "ERROR:");
184
+ console.error(red(txt), details);
185
+ }
186
+ }
187
+
188
+ public reportGenerationFailure(namespace: string, error: Error | string, context?: string): void {
189
+ const message = `Failed to generate ${context || "namespace"}: ${namespace}`;
190
+ const details = error instanceof Error ? error.message : error;
191
+
192
+ this.addProblem(ProblemSeverity.ERROR, ProblemCategory.GENERATION_FAILURE, message, details, undefined, namespace, {
193
+ namespace,
194
+ context,
195
+ error: details,
196
+ });
197
+
198
+ if (this.config.verbose) {
199
+ const txt = this.prependInfo(message, "ERROR:");
200
+ console.error(red(txt), details);
201
+ }
202
+ }
203
+
204
+ public reportTypeConflict(conflictType: string, elementName: string, namespace: string, details?: string): void {
205
+ const message = `Type conflict (${conflictType}): ${elementName}`;
206
+
207
+ this.addProblem(ProblemSeverity.WARNING, ProblemCategory.TYPE_CONFLICT, message, details, elementName, namespace, {
208
+ conflictType,
209
+ namespace,
210
+ });
211
+
212
+ if (this.config.verbose) {
213
+ const txt = this.prependInfo(message, "WARN:");
214
+ console.warn(yellow(txt), details || "");
215
+ }
216
+ }
217
+
218
+ public reportDependencyIssue(dependencyName: string, issue: string, details?: string): void {
219
+ const message = `Dependency issue: ${dependencyName} - ${issue}`;
220
+
221
+ this.addProblem(
222
+ ProblemSeverity.WARNING,
223
+ ProblemCategory.DEPENDENCY_ISSUE,
224
+ message,
225
+ details,
226
+ dependencyName,
227
+ this.config.moduleName,
228
+ { dependencyName, issue },
229
+ );
230
+
231
+ if (this.config.verbose) {
232
+ this.warn(message, details);
233
+ }
234
+ }
235
+
236
+ // === Report generation methods ===
237
+
238
+ private generateStatistics(): ReportStatistics {
239
+ const bySeverity = Object.values(ProblemSeverity).reduce(
240
+ (acc, severity) => {
241
+ acc[severity] = 0;
242
+ return acc;
243
+ },
244
+ {} as Record<ProblemSeverity, number>,
245
+ );
246
+
247
+ const byCategory = Object.values(ProblemCategory).reduce(
248
+ (acc, category) => {
249
+ acc[category] = 0;
250
+ return acc;
251
+ },
252
+ {} as Record<ProblemCategory, number>,
253
+ );
254
+
255
+ const byModule: Record<string, number> = {};
256
+
257
+ // Type-specific tracking
258
+ const unresolvedTypes: Record<string, { count: number; namespaces: Set<string> }> = {};
259
+ const typeConflicts: Record<string, { count: number; examples: Set<string> }> = {};
260
+ const namespaceProblems: Record<string, { count: number; types: Set<string> }> = {};
261
+
262
+ for (const problem of this.problems) {
263
+ bySeverity[problem.severity]++;
264
+ byCategory[problem.category]++;
265
+ byModule[problem.module] = (byModule[problem.module] || 0) + 1;
266
+
267
+ // Track type resolution problems
268
+ if (problem.category === ProblemCategory.TYPE_RESOLUTION && problem.typeName) {
269
+ if (!unresolvedTypes[problem.typeName]) {
270
+ unresolvedTypes[problem.typeName] = { count: 0, namespaces: new Set() };
271
+ }
272
+ unresolvedTypes[problem.typeName].count++;
273
+ if (problem.location) {
274
+ unresolvedTypes[problem.typeName].namespaces.add(problem.location);
275
+ }
276
+
277
+ // Track namespace problems
278
+ if (problem.location) {
279
+ if (!namespaceProblems[problem.location]) {
280
+ namespaceProblems[problem.location] = { count: 0, types: new Set() };
281
+ }
282
+ namespaceProblems[problem.location].count++;
283
+ namespaceProblems[problem.location].types.add(problem.typeName);
284
+ }
285
+ }
286
+
287
+ // Track type conflicts
288
+ if (problem.category === ProblemCategory.TYPE_CONFLICT && problem.metadata?.conflictType) {
289
+ const conflictType = problem.metadata.conflictType as string;
290
+ if (!typeConflicts[conflictType]) {
291
+ typeConflicts[conflictType] = { count: 0, examples: new Set() };
292
+ }
293
+ typeConflicts[conflictType].count++;
294
+ if (problem.typeName) {
295
+ typeConflicts[conflictType].examples.add(problem.typeName);
296
+ }
297
+ }
298
+ }
299
+
300
+ // Convert to arrays and sort
301
+ const commonUnresolvedTypes = Object.entries(unresolvedTypes)
302
+ .map(([type, data]) => ({
303
+ type,
304
+ count: data.count,
305
+ namespaces: Array.from(data.namespaces),
306
+ }))
307
+ .sort((a, b) => b.count - a.count)
308
+ .slice(0, 20);
309
+
310
+ const commonTypeConflicts = Object.entries(typeConflicts)
311
+ .map(([conflictType, data]) => ({
312
+ conflictType,
313
+ count: data.count,
314
+ examples: Array.from(data.examples).slice(0, 5),
315
+ }))
316
+ .sort((a, b) => b.count - a.count);
317
+
318
+ const problematicNamespaces = Object.entries(namespaceProblems)
319
+ .map(([namespace, data]) => ({
320
+ namespace,
321
+ problems: data.count,
322
+ types: Array.from(data.types).slice(0, 10),
323
+ }))
324
+ .sort((a, b) => b.problems - a.problems)
325
+ .slice(0, 10);
326
+
327
+ const mostProblematicModules = Object.entries(byModule)
328
+ .sort(([, a], [, b]) => b - a)
329
+ .slice(0, 10)
330
+ .map(([module, count]) => ({ module, count }));
331
+
332
+ const endTime = new Date();
333
+ const durationMs = endTime.getTime() - this.startTime.getTime();
334
+
335
+ return {
336
+ bySeverity,
337
+ byCategory,
338
+ byModule,
339
+ totalProblems: this.problems.length,
340
+ mostProblematicModules,
341
+ typeStatistics: {
342
+ commonUnresolvedTypes,
343
+ commonTypeConflicts,
344
+ problematicNamespaces,
345
+ },
346
+ startTime: this.startTime,
347
+ endTime,
348
+ durationMs,
349
+ };
350
+ }
351
+
352
+ private generateSummary(statistics: ReportStatistics): GenerationReport["summary"] {
353
+ const { bySeverity, byCategory, totalProblems } = statistics;
354
+
355
+ let status: "success" | "partial" | "failed" = "success";
356
+ if (bySeverity[ProblemSeverity.CRITICAL] > 0 || bySeverity[ProblemSeverity.ERROR] > 10) {
357
+ status = "failed";
358
+ } else if (bySeverity[ProblemSeverity.ERROR] > 0 || bySeverity[ProblemSeverity.WARNING] > 20) {
359
+ status = "partial";
360
+ }
361
+
362
+ const keyIssues: string[] = [];
363
+ const recommendations: string[] = [];
364
+
365
+ // Analyze key issues
366
+ if (byCategory[ProblemCategory.TYPE_RESOLUTION] > 0) {
367
+ keyIssues.push(`${byCategory[ProblemCategory.TYPE_RESOLUTION]} type resolution issues detected`);
368
+ recommendations.push("Review GIR files for missing or incorrect type definitions");
369
+ }
370
+
371
+ if (byCategory[ProblemCategory.PARSING_FAILURE] > 0) {
372
+ keyIssues.push(`${byCategory[ProblemCategory.PARSING_FAILURE]} parsing failures occurred`);
373
+ recommendations.push("Check GIR file syntax and ensure proper introspection data");
374
+ }
375
+
376
+ if (byCategory[ProblemCategory.GENERATION_FAILURE] > 0) {
377
+ keyIssues.push(`${byCategory[ProblemCategory.GENERATION_FAILURE]} generation failures encountered`);
378
+ recommendations.push("Review template configuration and output settings");
379
+ }
380
+
381
+ if (byCategory[ProblemCategory.TYPE_CONFLICT] > 5) {
382
+ keyIssues.push(`High number of type conflicts (${byCategory[ProblemCategory.TYPE_CONFLICT]})`);
383
+ recommendations.push("Consider using ignore patterns or updating GIR files to resolve conflicts");
384
+ }
385
+
386
+ if (keyIssues.length === 0 && totalProblems > 0) {
387
+ keyIssues.push(`${totalProblems} minor issues detected`);
388
+ }
389
+
390
+ if (recommendations.length === 0 && totalProblems > 0) {
391
+ recommendations.push("Review detailed problem list for specific improvement opportunities");
392
+ }
393
+
394
+ return {
395
+ status,
396
+ keyIssues,
397
+ recommendations,
398
+ };
399
+ }
400
+
401
+ public generateReport(): GenerationReport {
402
+ const statistics = this.generateStatistics();
403
+ const summary = this.generateSummary(statistics);
404
+
405
+ const problemsByCategory = Object.values(ProblemCategory).reduce(
406
+ (acc, category) => {
407
+ acc[category] = [];
408
+ return acc;
409
+ },
410
+ {} as Record<ProblemCategory, ProblemEntry[]>,
411
+ );
412
+
413
+ for (const problem of this.problems) {
414
+ problemsByCategory[problem.category].push(problem);
415
+ }
416
+
417
+ return {
418
+ metadata: {
419
+ version: REPORTER_VERSION,
420
+ generatedAt: new Date(),
421
+ },
422
+ statistics,
423
+ problems: [...this.problems],
424
+ problemsByCategory,
425
+ summary,
426
+ };
427
+ }
428
+
429
+ public async saveReport(outputPath?: string): Promise<void> {
430
+ if (!this.config.enabled) {
431
+ return;
432
+ }
433
+
434
+ const report = this.generateReport();
435
+ const filePath = outputPath || this.config.outputPath || "ts-for-gir-report.json";
436
+
437
+ try {
438
+ await writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
439
+ if (this.config.verbose) {
440
+ this.success(`Report saved to: ${filePath}`);
441
+ }
442
+ } catch (error) {
443
+ this.danger(`Failed to save report to ${filePath}: ${error}`);
444
+ }
445
+ }
446
+
447
+ public printSummary(): void {
448
+ if (!this.config.enabled) {
449
+ return;
450
+ }
451
+
452
+ const report = this.generateReport();
453
+ const { statistics, summary } = report;
454
+
455
+ console.log(`\n${"=".repeat(50)}`);
456
+ console.log("📊 GENERATION REPORT SUMMARY");
457
+ console.log("=".repeat(50));
458
+
459
+ // Status
460
+ const statusColor = summary.status === "success" ? green : summary.status === "partial" ? yellow : red;
461
+ console.log(`Status: ${statusColor(summary.status.toUpperCase())}`);
462
+
463
+ // Statistics
464
+ console.log(`\n📈 Statistics:`);
465
+ console.log(` Total Problems: ${statistics.totalProblems}`);
466
+ console.log(` Duration: ${Math.round((statistics.durationMs || 0) / 1000)}s`);
467
+
468
+ if (statistics.totalProblems > 0) {
469
+ console.log(`\n🔍 By Severity:`);
470
+ for (const [severity, count] of Object.entries(statistics.bySeverity)) {
471
+ if (count > 0) {
472
+ const color = severity === "error" || severity === "critical" ? red : severity === "warning" ? yellow : blue;
473
+ console.log(` ${color(severity)}: ${count}`);
474
+ }
475
+ }
476
+
477
+ console.log(`\n📂 By Category:`);
478
+ for (const [category, count] of Object.entries(statistics.byCategory)) {
479
+ if (count > 0) {
480
+ console.log(` ${category.replace(/_/g, " ")}: ${count}`);
481
+ }
482
+ }
483
+
484
+ // Type-specific statistics
485
+ if (statistics.typeStatistics.commonUnresolvedTypes.length > 0) {
486
+ console.log(`\n❌ Most Common Unresolved Types:`);
487
+ statistics.typeStatistics.commonUnresolvedTypes.slice(0, 10).forEach(({ type, count, namespaces }) => {
488
+ console.log(` ${red(type)}: ${count} occurrences in ${namespaces.length} namespace(s)`);
489
+ if (namespaces.length <= 3) {
490
+ console.log(` └─ ${gray(namespaces.join(", "))}`);
491
+ }
492
+ });
493
+ }
494
+
495
+ if (statistics.typeStatistics.commonTypeConflicts.length > 0) {
496
+ console.log(`\n⚔️ Type Conflicts:`);
497
+ statistics.typeStatistics.commonTypeConflicts.forEach(({ conflictType, count, examples }) => {
498
+ console.log(` ${yellow(conflictType)}: ${count} conflicts`);
499
+ if (examples.length > 0) {
500
+ console.log(` └─ Examples: ${gray(examples.join(", "))}`);
501
+ }
502
+ });
503
+ }
504
+
505
+ if (statistics.typeStatistics.problematicNamespaces.length > 0) {
506
+ console.log(`\n🚨 Most Problematic Namespaces:`);
507
+ statistics.typeStatistics.problematicNamespaces.slice(0, 5).forEach(({ namespace, problems, types }) => {
508
+ console.log(` ${namespace}: ${problems} problems`);
509
+ if (types.length > 0) {
510
+ const typeList = types.slice(0, 5).join(", ");
511
+ const moreTypes = types.length > 5 ? ` and ${types.length - 5} more` : "";
512
+ console.log(` └─ Types: ${gray(typeList + moreTypes)}`);
513
+ }
514
+ });
515
+ }
516
+
517
+ if (statistics.mostProblematicModules.length > 0) {
518
+ console.log(`\n📦 Most Problematic Modules:`);
519
+ statistics.mostProblematicModules.slice(0, 5).forEach(({ module, count }) => {
520
+ console.log(` ${module}: ${count} issues`);
521
+ });
522
+ }
523
+ }
524
+
525
+ // Key Issues
526
+ if (summary.keyIssues.length > 0) {
527
+ console.log(`\n⚠️ Key Issues:`);
528
+ summary.keyIssues.forEach((issue) => console.log(` • ${issue}`));
529
+ }
530
+
531
+ // Recommendations
532
+ if (summary.recommendations.length > 0) {
533
+ console.log(`\n💡 Recommendations:`);
534
+ summary.recommendations.forEach((rec) => console.log(` • ${rec}`));
535
+ }
536
+
537
+ console.log(`${"=".repeat(50)}\n`);
538
+ }
539
+
540
+ // === Private helper methods ===
541
+
542
+ private static prepend(txt: string, prepend: string): string {
543
+ if (typeof txt === "string") {
544
+ txt = `${prepend}${txt}`;
545
+ }
546
+ return txt;
547
+ }
548
+
549
+ private prependInfo(txt: string, logLevel?: "WARN:" | "ERROR:" | "INFO:" | "DEBUG:"): string {
550
+ if (logLevel || this.config.moduleName.length > 0) {
551
+ txt = ConsoleReporter.prepend(txt, " ");
552
+ }
553
+ if (logLevel) {
554
+ if (this.config.moduleName.length > 0) {
555
+ txt = ConsoleReporter.prepend(txt, ` ${logLevel}`);
556
+ } else {
557
+ txt = ConsoleReporter.prepend(txt, logLevel);
558
+ }
559
+ }
560
+ if (this.config.moduleName.length > 0) {
561
+ txt = ConsoleReporter.prepend(txt, `[${this.config.moduleName}]`);
562
+ }
563
+
564
+ return txt;
565
+ }
566
+ }
@@ -0,0 +1,69 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import { dirname, join } from "node:path";
4
+
5
+ const require = createRequire(import.meta.url);
6
+
7
+ /**
8
+ * Package information interface for workspace root package.json
9
+ * All packages in the workspace share the same version from the root
10
+ */
11
+ interface WorkspacePackage {
12
+ version: string;
13
+ name: string;
14
+ description: string;
15
+ }
16
+
17
+ /**
18
+ * Resolves the workspace root package.json path
19
+ * Uses require.resolve to find the correct path regardless of execution context
20
+ */
21
+ function resolveWorkspacePackageJson(): string {
22
+ try {
23
+ // Try to resolve from the workspace root by going up from this package
24
+ // @ts-for-gir/reporter -> ts-for-gir root
25
+ return require.resolve("../../../package.json");
26
+ } catch {
27
+ // Fallback: try to resolve from current package's package.json location
28
+ try {
29
+ const currentPackageJson = require.resolve("@ts-for-gir/reporter/package.json");
30
+ return join(dirname(dirname(currentPackageJson)), "package.json");
31
+ } catch {
32
+ throw new Error("Unable to resolve workspace package.json path");
33
+ }
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Reads and parses the workspace package.json file
39
+ * Contains version and metadata shared across all workspace packages
40
+ */
41
+ function readWorkspacePackage(): WorkspacePackage {
42
+ try {
43
+ const packagePath = resolveWorkspacePackageJson();
44
+ const content = readFileSync(packagePath, "utf-8");
45
+ return JSON.parse(content) as WorkspacePackage;
46
+ } catch (error) {
47
+ const message = error instanceof Error ? error.message : "Unknown error";
48
+ throw new Error(`Failed to read workspace package.json: ${message}`);
49
+ }
50
+ }
51
+
52
+ // Read package information once at module load
53
+ const WORKSPACE_PACKAGE = readWorkspacePackage();
54
+
55
+ /**
56
+ * The current version of ts-for-gir
57
+ * Shared across all workspace packages from the root package.json
58
+ */
59
+ export const REPORTER_VERSION = WORKSPACE_PACKAGE.version;
60
+
61
+ /**
62
+ * The name of the workspace project
63
+ */
64
+ export const PACKAGE_NAME = WORKSPACE_PACKAGE.name;
65
+
66
+ /**
67
+ * The description of the workspace project
68
+ */
69
+ export const PACKAGE_DESCRIPTION = WORKSPACE_PACKAGE.description;
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ // Backwards compatibility export - alias ConsoleReporter as Reporter
2
+ export { ConsoleReporter, ConsoleReporter as Reporter } from "./console-reporter.ts";
3
+ export type { AnalyzedMessage } from "./message-analyzer.ts";
4
+ export { analyzeError, analyzeWarning } from "./message-analyzer.ts";
5
+ export { ReporterBase } from "./reporter-base.ts";
6
+ export { ReporterService } from "./reporter-service.ts";
7
+ export * from "./types/index.ts";