@danielsitek/eslint-stats 0.1.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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +118 -0
  3. package/dist/formatters/by-error-and-warning-stacked.d.ts +4 -0
  4. package/dist/formatters/by-error-and-warning-stacked.d.ts.map +1 -0
  5. package/dist/formatters/by-error-and-warning-stacked.js +8 -0
  6. package/dist/formatters/by-error-and-warning-stacked.js.map +1 -0
  7. package/dist/formatters/by-error-and-warning.d.ts +4 -0
  8. package/dist/formatters/by-error-and-warning.d.ts.map +1 -0
  9. package/dist/formatters/by-error-and-warning.js +8 -0
  10. package/dist/formatters/by-error-and-warning.js.map +1 -0
  11. package/dist/formatters/by-error.d.ts +4 -0
  12. package/dist/formatters/by-error.d.ts.map +1 -0
  13. package/dist/formatters/by-error.js +8 -0
  14. package/dist/formatters/by-error.js.map +1 -0
  15. package/dist/formatters/by-folder.d.ts +4 -0
  16. package/dist/formatters/by-folder.d.ts.map +1 -0
  17. package/dist/formatters/by-folder.js +8 -0
  18. package/dist/formatters/by-folder.js.map +1 -0
  19. package/dist/formatters/by-warning.d.ts +4 -0
  20. package/dist/formatters/by-warning.d.ts.map +1 -0
  21. package/dist/formatters/by-warning.js +8 -0
  22. package/dist/formatters/by-warning.js.map +1 -0
  23. package/dist/index.d.ts +14 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +17 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/types/types.d.ts +15 -0
  28. package/dist/types/types.d.ts.map +1 -0
  29. package/dist/types/types.js +2 -0
  30. package/dist/types/types.js.map +1 -0
  31. package/dist/utils/bar.d.ts +2 -0
  32. package/dist/utils/bar.d.ts.map +1 -0
  33. package/dist/utils/bar.js +6 -0
  34. package/dist/utils/bar.js.map +1 -0
  35. package/dist/utils/chart.d.ts +5 -0
  36. package/dist/utils/chart.d.ts.map +1 -0
  37. package/dist/utils/chart.js +98 -0
  38. package/dist/utils/chart.js.map +1 -0
  39. package/dist/utils/colors.d.ts +10 -0
  40. package/dist/utils/colors.d.ts.map +1 -0
  41. package/dist/utils/colors.js +11 -0
  42. package/dist/utils/colors.js.map +1 -0
  43. package/dist/utils/severities.d.ts +4 -0
  44. package/dist/utils/severities.d.ts.map +1 -0
  45. package/dist/utils/severities.js +8 -0
  46. package/dist/utils/severities.js.map +1 -0
  47. package/dist/utils/stats.d.ts +4 -0
  48. package/dist/utils/stats.d.ts.map +1 -0
  49. package/dist/utils/stats.js +48 -0
  50. package/dist/utils/stats.js.map +1 -0
  51. package/package.json +105 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daniel Sitek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,118 @@
1
+ ![Build Status](https://github.com/danielsitek/eslint-stats/actions/workflows/dev.yml/badge.svg?branch=main)
2
+ [![Codacy Badge](https://app.codacy.com/project/badge/Grade/6c466a724da04212b8471eda7c6adf16)](https://app.codacy.com/gh/danielsitek/eslint-stats/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
3
+ [![Codacy Badge](https://app.codacy.com/project/badge/Coverage/6c466a724da04212b8471eda7c6adf16)](https://app.codacy.com/gh/danielsitek/eslint-stats/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
4
+ [![Maintainability](https://qlty.sh/gh/danielsitek/projects/eslint-stats/maintainability.svg)](https://qlty.sh/gh/danielsitek/projects/eslint-stats)
5
+
6
+ # Statistic Reporter for ESLint
7
+
8
+ Modern TypeScript formatters for ESLint with aggregated error and warning statistics. Analyzes files by error frequency rather than location, making it easier to prioritize fixes when introducing ESLint to existing projects.
9
+
10
+ ![screenshot](https://raw.githubusercontent.com/danielsitek/eslint-stats/master/screenshot.png)
11
+
12
+ ## Features
13
+
14
+ - Multiple aggregation views (by error, warning, folder)
15
+ - Color-coded output with visual graphs
16
+ - ESLint 8 and 9 compatible
17
+ - Full TypeScript support with type definitions
18
+ - Zero runtime dependencies
19
+ - Modern Node.js (20+)
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install --save-dev @danielsitek/eslint-stats
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ### With ESLint CLI
30
+
31
+ ```bash
32
+ # Using specific formatters
33
+ eslint src/ -f ./node_modules/@danielsitek/eslint-stats/dist/formatters/by-error.js
34
+ eslint src/ -f ./node_modules/@danielsitek/eslint-stats/dist/formatters/by-error-and-warning.js
35
+ eslint src/ -f ./node_modules/@danielsitek/eslint-stats/dist/formatters/by-folder.js
36
+ ```
37
+
38
+ ### Programmatic Usage
39
+
40
+ ```typescript
41
+ import {
42
+ byError,
43
+ byWarning,
44
+ byErrorAndWarning,
45
+ } from "@danielsitek/eslint-stats";
46
+ import { ESLint } from "eslint";
47
+
48
+ const eslint = new ESLint({
49
+ // your config
50
+ });
51
+
52
+ const results = await eslint.lintFiles(["src/**/*.ts"]);
53
+ const formatter = await eslint.loadFormatter(byError);
54
+
55
+ console.log(formatter.format(results));
56
+ ```
57
+
58
+ ## Available Formatters
59
+
60
+ ### by-error
61
+
62
+ Displays aggregated error statistics without file separation. Only shows rules with errors; warnings are not displayed.
63
+
64
+ ### by-warning
65
+
66
+ Displays aggregated warning statistics without file separation. Only shows rules with warnings; errors are not displayed.
67
+
68
+ ### by-error-and-warning
69
+
70
+ Displays aggregated statistics for both errors and warnings without file separation. Errors are shown in red, warnings in yellow.
71
+
72
+ ### by-error-and-warning-stacked
73
+
74
+ Similar to by-error-and-warning but displays errors and warnings stacked together when a rule has both severities across different files.
75
+
76
+ ### by-folder
77
+
78
+ Displays aggregated statistics grouped by folder. Errors are shown in red, warnings in yellow.
79
+
80
+ ## Demo
81
+
82
+ The package includes demo scripts for testing formatters:
83
+
84
+ ```bash
85
+ npm run demo:error
86
+ npm run demo:warning
87
+ npm run demo:both
88
+ npm run demo:stacked
89
+ npm run demo:folder
90
+ ```
91
+
92
+ ## Requirements
93
+
94
+ - Node.js >= 20.0.0
95
+ - ESLint >= 8.0.0
96
+
97
+ ## Migration from `ganimomer/eslint-stats` v1.x
98
+
99
+ If you're upgrading from the original `eslint-stats` package:
100
+
101
+ 1. Update package name:
102
+
103
+ ```bash
104
+ npm uninstall eslint-stats
105
+ npm install --save-dev @danielsitek/eslint-stats
106
+ ```
107
+
108
+ 2. Update formatter paths in your ESLint configuration or CLI commands to use the new scoped package name.
109
+
110
+ 3. For programmatic usage, update imports to use the scoped package name.
111
+
112
+ ## Credits
113
+
114
+ Modernized fork of [eslint-stats](https://github.com/ganimomer/eslint-stats) by [Omer Ganim](https://github.com/ganimomer).
115
+
116
+ ## License
117
+
118
+ MIT
@@ -0,0 +1,4 @@
1
+ import type { LintResult } from "../types/types.js";
2
+ export declare const byErrorAndWarningStacked: (results: LintResult[]) => string;
3
+ export default byErrorAndWarningStacked;
4
+ //# sourceMappingURL=by-error-and-warning-stacked.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"by-error-and-warning-stacked.d.ts","sourceRoot":"","sources":["../../src/formatters/by-error-and-warning-stacked.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD,eAAO,MAAM,wBAAwB,GAAI,SAAS,UAAU,EAAE,KAAG,MAGhE,CAAC;AAEF,eAAe,wBAAwB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { byRule } from "../utils/stats.js";
2
+ import { getStackedOutput } from "../utils/chart.js";
3
+ export const byErrorAndWarningStacked = (results) => {
4
+ const obj = byRule(results);
5
+ return getStackedOutput(obj, process.stdout.columns || 80);
6
+ };
7
+ export default byErrorAndWarningStacked;
8
+ //# sourceMappingURL=by-error-and-warning-stacked.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"by-error-and-warning-stacked.js","sourceRoot":"","sources":["../../src/formatters/by-error-and-warning-stacked.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,OAAqB,EAAU,EAAE;IACxE,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5B,OAAO,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;AAC7D,CAAC,CAAC;AAEF,eAAe,wBAAwB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintResult } from "../types/types.js";
2
+ export declare const byErrorAndWarning: (results: LintResult[]) => string;
3
+ export default byErrorAndWarning;
4
+ //# sourceMappingURL=by-error-and-warning.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"by-error-and-warning.d.ts","sourceRoot":"","sources":["../../src/formatters/by-error-and-warning.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD,eAAO,MAAM,iBAAiB,GAAI,SAAS,UAAU,EAAE,KAAG,MAGzD,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { byRule } from "../utils/stats.js";
2
+ import { getObjectOutput } from "../utils/chart.js";
3
+ export const byErrorAndWarning = (results) => {
4
+ const obj = byRule(results);
5
+ return getObjectOutput(obj, process.stdout.columns || 80);
6
+ };
7
+ export default byErrorAndWarning;
8
+ //# sourceMappingURL=by-error-and-warning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"by-error-and-warning.js","sourceRoot":"","sources":["../../src/formatters/by-error-and-warning.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAqB,EAAU,EAAE;IACjE,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5B,OAAO,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;AAC5D,CAAC,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintResult } from "../types/types.js";
2
+ export declare const byError: (results: LintResult[]) => string;
3
+ export default byError;
4
+ //# sourceMappingURL=by-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"by-error.d.ts","sourceRoot":"","sources":["../../src/formatters/by-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD,eAAO,MAAM,OAAO,GAAI,SAAS,UAAU,EAAE,KAAG,MAG/C,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { byRule } from "../utils/stats.js";
2
+ import { getObjectOutput } from "../utils/chart.js";
3
+ export const byError = (results) => {
4
+ const errorObj = byRule(results, 2);
5
+ return getObjectOutput(errorObj, process.stdout.columns || 80);
6
+ };
7
+ export default byError;
8
+ //# sourceMappingURL=by-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"by-error.js","sourceRoot":"","sources":["../../src/formatters/by-error.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAAqB,EAAU,EAAE;IACvD,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpC,OAAO,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;AACjE,CAAC,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintResult } from "../types/types.js";
2
+ export declare const byFolder: (results: LintResult[]) => string;
3
+ export default byFolder;
4
+ //# sourceMappingURL=by-folder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"by-folder.d.ts","sourceRoot":"","sources":["../../src/formatters/by-folder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD,eAAO,MAAM,QAAQ,GAAI,SAAS,UAAU,EAAE,KAAG,MAGhD,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { byFolderAndRule } from "../utils/stats.js";
2
+ import { getOutputByFolder } from "../utils/chart.js";
3
+ export const byFolder = (results) => {
4
+ const obj = byFolderAndRule(results);
5
+ return getOutputByFolder(obj, process.stdout.columns || 80);
6
+ };
7
+ export default byFolder;
8
+ //# sourceMappingURL=by-folder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"by-folder.js","sourceRoot":"","sources":["../../src/formatters/by-folder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAqB,EAAU,EAAE;IACxD,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;AAC9D,CAAC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintResult } from "../types/types.js";
2
+ export declare const byWarning: (results: LintResult[]) => string;
3
+ export default byWarning;
4
+ //# sourceMappingURL=by-warning.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"by-warning.d.ts","sourceRoot":"","sources":["../../src/formatters/by-warning.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD,eAAO,MAAM,SAAS,GAAI,SAAS,UAAU,EAAE,KAAG,MAGjD,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { byRule } from "../utils/stats.js";
2
+ import { getObjectOutput } from "../utils/chart.js";
3
+ export const byWarning = (results) => {
4
+ const warningObj = byRule(results, 1);
5
+ return getObjectOutput(warningObj, process.stdout.columns || 80);
6
+ };
7
+ export default byWarning;
8
+ //# sourceMappingURL=by-warning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"by-warning.js","sourceRoot":"","sources":["../../src/formatters/by-warning.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAqB,EAAU,EAAE;IACzD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACtC,OAAO,eAAe,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;AACnE,CAAC,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,14 @@
1
+ export declare const byError: string;
2
+ export declare const byWarning: string;
3
+ export declare const byErrorAndWarning: string;
4
+ export declare const byErrorAndWarningStacked: string;
5
+ export declare const byFolder: string;
6
+ declare const _default: {
7
+ byError: string;
8
+ byWarning: string;
9
+ byErrorAndWarning: string;
10
+ byErrorAndWarningStacked: string;
11
+ byFolder: string;
12
+ };
13
+ export default _default;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,OAAO,QAA+B,CAAC;AACpD,eAAO,MAAM,SAAS,QAAiC,CAAC;AACxD,eAAO,MAAM,iBAAiB,QAA2C,CAAC;AAC1E,eAAO,MAAM,wBAAwB,QAEpC,CAAC;AACF,eAAO,MAAM,QAAQ,QAAgC,CAAC;;;;;;;;AAEtD,wBAME"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ import { dirname, join } from "node:path";
2
+ const getFormatterPath = (formatter) => {
3
+ return join(dirname(new URL(import.meta.url).pathname), "formatters", `${formatter}.js`);
4
+ };
5
+ export const byError = getFormatterPath("by-error");
6
+ export const byWarning = getFormatterPath("by-warning");
7
+ export const byErrorAndWarning = getFormatterPath("by-error-and-warning");
8
+ export const byErrorAndWarningStacked = getFormatterPath("by-error-and-warning-stacked");
9
+ export const byFolder = getFormatterPath("by-folder");
10
+ export default {
11
+ byError,
12
+ byWarning,
13
+ byErrorAndWarning,
14
+ byErrorAndWarningStacked,
15
+ byFolder,
16
+ };
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,gBAAgB,GAAG,CAAC,SAAiB,EAAU,EAAE;IAErD,OAAO,IAAI,CACT,OAAO,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,EAC1C,YAAY,EACZ,GAAG,SAAS,KAAK,CAClB,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,SAAS,GAAG,gBAAgB,CAAC,YAAY,CAAC,CAAC;AACxD,MAAM,CAAC,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;AAC1E,MAAM,CAAC,MAAM,wBAAwB,GAAG,gBAAgB,CACtD,8BAA8B,CAC/B,CAAC;AACF,MAAM,CAAC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;AAEtD,eAAe;IACb,OAAO;IACP,SAAS;IACT,iBAAiB;IACjB,wBAAwB;IACxB,QAAQ;CACT,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { ESLint, Linter } from "eslint";
2
+ export type LintResult = ESLint.LintResult;
3
+ export type LintMessage = Linter.LintMessage;
4
+ export type Formatter = ESLint.Formatter["format"];
5
+ export interface SeverityStats {
6
+ Error?: number;
7
+ Warning?: number;
8
+ }
9
+ export type RuleStats = Record<string, SeverityStats>;
10
+ export type FolderStats = Record<string, RuleStats>;
11
+ export type SeverityLevel = 0 | 1 | 2;
12
+ export interface SeverityMap {
13
+ names: Record<number, "Warning" | "Error">;
14
+ }
15
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE7C,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AAC3C,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;AAC7C,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEpD,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEtC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC;CAC5C"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export declare const getString: (length: number, color: "red" | "yellow") => string;
2
+ //# sourceMappingURL=bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bar.d.ts","sourceRoot":"","sources":["../../src/utils/bar.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,EAAE,OAAO,KAAK,GAAG,QAAQ,KAAG,MAInE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { bgRed, bgYellow } from "./colors.js";
2
+ export const getString = (length, color) => {
3
+ const colorFn = color === "red" ? bgRed : bgYellow;
4
+ return colorFn(" ".repeat(length));
5
+ };
6
+ //# sourceMappingURL=bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bar.js","sourceRoot":"","sources":["../../src/utils/bar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAAc,EAAE,KAAuB,EAAU,EAAE;IAC3E,MAAM,OAAO,GAAG,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEnD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AACrC,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { RuleStats, FolderStats } from "../types/types.js";
2
+ export declare function getObjectOutput(stats: RuleStats, maxWidth: number): string;
3
+ export declare function getStackedOutput(stats: RuleStats, maxWidth: number): string;
4
+ export declare function getOutputByFolder(stats: FolderStats, maxWidth: number): string;
5
+ //# sourceMappingURL=chart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart.d.ts","sourceRoot":"","sources":["../../src/utils/chart.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAiB,MAAM,mBAAmB,CAAC;AAiC/E,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAyC1E;AAQD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAmE3E;AAOD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,MAAM,GACf,MAAM,CAUR"}
@@ -0,0 +1,98 @@
1
+ import { magenta, underline } from "./colors.js";
2
+ import { getString } from "./bar.js";
3
+ const barColors = {
4
+ Error: "red",
5
+ Warning: "yellow",
6
+ };
7
+ const allSeverities = ["Error", "Warning"];
8
+ function getMaxRuleLength(stats) {
9
+ return Math.max(...Object.keys(stats).map((key) => key.length));
10
+ }
11
+ function getStringLength(num) {
12
+ return String(num).length;
13
+ }
14
+ const getBarRatio = (usedColumns, maxResult, maxWidth) => {
15
+ const maxBarLength = maxWidth - usedColumns;
16
+ return maxResult <= maxBarLength ? 1 : maxBarLength / maxResult;
17
+ };
18
+ const sortByKey = (obj) => {
19
+ return Object.entries(obj)
20
+ .sort(([a], [b]) => a.localeCompare(b))
21
+ .map(([, value]) => value);
22
+ };
23
+ export function getObjectOutput(stats, maxWidth) {
24
+ const maxRuleLength = getMaxRuleLength(stats);
25
+ const maxResult = Math.max(...Object.values(stats).flatMap((ruleStats) => [
26
+ ruleStats.Error ?? 0,
27
+ ruleStats.Warning ?? 0,
28
+ ]));
29
+ const maxResultLength = String(maxResult).length;
30
+ const barRatio = getBarRatio(maxRuleLength + maxResultLength + 3, maxResult, maxWidth);
31
+ const getRuleOutput = (ruleStats, ruleName) => {
32
+ const ruleCell = `${ruleName}: `.padEnd(maxRuleLength + 2);
33
+ return Object.entries(ruleStats)
34
+ .map(([severity, count]) => {
35
+ const countCell = magenta(String(count).padStart(maxResultLength));
36
+ const barCell = getString(Math.floor(barRatio * count), barColors[severity]);
37
+ return `${ruleCell}${countCell}|${barCell}`;
38
+ })
39
+ .join("\n");
40
+ };
41
+ const mappedStats = Object.fromEntries(Object.entries(stats).map(([ruleName, ruleStats]) => [
42
+ ruleName,
43
+ getRuleOutput(ruleStats, ruleName),
44
+ ]));
45
+ return `${sortByKey(mappedStats).join("\n")}\n`;
46
+ }
47
+ function isAnyRuleStacked(stats) {
48
+ return Object.values(stats).some((ruleData) => Object.keys(ruleData).length > 1);
49
+ }
50
+ export function getStackedOutput(stats, maxWidth) {
51
+ if (!isAnyRuleStacked(stats)) {
52
+ return getObjectOutput(stats, maxWidth);
53
+ }
54
+ const normalizedStats = Object.fromEntries(Object.entries(stats).map(([key, value]) => [
55
+ key,
56
+ { Error: 0, Warning: 0, ...value },
57
+ ]));
58
+ const maxRuleLength = getMaxRuleLength(normalizedStats);
59
+ const maxResults = {};
60
+ for (const severity of allSeverities) {
61
+ maxResults[severity] = Math.max(...Object.values(stats).map((s) => {
62
+ const val = severity === "Error" ? s.Error : s.Warning;
63
+ return val ?? 0;
64
+ }));
65
+ }
66
+ const maxResultLengths = Object.fromEntries(Object.entries(maxResults).map(([key, value]) => [
67
+ key,
68
+ getStringLength(value),
69
+ ]));
70
+ const maxRuleSum = Math.max(...Object.values(normalizedStats).map((x) => x.Error + x.Warning));
71
+ const barRatio = getBarRatio(maxRuleLength +
72
+ Object.values(maxResultLengths).reduce((a, b) => a + b, 0) +
73
+ 4, maxRuleSum, maxWidth);
74
+ const getStackedBar = (ruleStats) => {
75
+ return (getString(Math.floor(barRatio * ruleStats.Error), barColors.Error) +
76
+ getString(Math.floor(barRatio * ruleStats.Warning), barColors.Warning));
77
+ };
78
+ return `${Object.entries(normalizedStats)
79
+ .map(([ruleId, ruleStats]) => {
80
+ const ruleCell = `${ruleId}: `.padEnd(maxRuleLength + 2);
81
+ const errorLength = maxResultLengths.Error ?? 0;
82
+ const warningLength = maxResultLengths.Warning ?? 0;
83
+ const errorCountCell = String(ruleStats.Error).padStart(errorLength);
84
+ const warningCountCell = String(ruleStats.Warning).padStart(warningLength);
85
+ const countCell = magenta(`${errorCountCell},${warningCountCell}`);
86
+ const barCell = getStackedBar(ruleStats);
87
+ return `${ruleCell}${countCell}|${barCell}`;
88
+ })
89
+ .join("\n")}\n`;
90
+ }
91
+ const getFolderOutput = (maxWidth) => (folderStats, folderName) => `${underline(`${folderName}:`)}\n${getObjectOutput(folderStats, maxWidth)}`;
92
+ export function getOutputByFolder(stats, maxWidth) {
93
+ const filteredStats = Object.fromEntries(Object.entries(stats).filter(([, value]) => Object.keys(value).length > 0));
94
+ return Object.entries(filteredStats)
95
+ .map(([folderName, folderStats]) => getFolderOutput(maxWidth)(folderStats, folderName))
96
+ .join("");
97
+ }
98
+ //# sourceMappingURL=chart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart.js","sourceRoot":"","sources":["../../src/utils/chart.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ type Color = "red" | "yellow" | "magenta" | "underline" | "bgRed" | "bgYellow";
2
+ export declare const color: (text: string, style: Color) => string;
3
+ export declare const red: (text: string) => string;
4
+ export declare const yellow: (text: string) => string;
5
+ export declare const magenta: (text: string) => string;
6
+ export declare const underline: (text: string) => string;
7
+ export declare const bgRed: (text: string) => string;
8
+ export declare const bgYellow: (text: string) => string;
9
+ export {};
10
+ //# sourceMappingURL=colors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/utils/colors.ts"],"names":[],"mappings":"AAOA,KAAK,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,UAAU,CAAC;AAE/E,eAAO,MAAM,KAAK,GAAI,MAAM,MAAM,EAAE,OAAO,KAAK,KAAG,MAElD,CAAC;AAEF,eAAO,MAAM,GAAG,GAAI,MAAM,MAAM,KAAG,MAA4B,CAAC;AAEhE,eAAO,MAAM,MAAM,GAAI,MAAM,MAAM,KAAG,MAA+B,CAAC;AAEtE,eAAO,MAAM,OAAO,GAAI,MAAM,MAAM,KAAG,MAAgC,CAAC;AAExE,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,MAAkC,CAAC;AAE5E,eAAO,MAAM,KAAK,GAAI,MAAM,MAAM,KAAG,MAA8B,CAAC;AAEpE,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,KAAG,MAAiC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { styleText } from "node:util";
2
+ export const color = (text, style) => {
3
+ return styleText(style, text);
4
+ };
5
+ export const red = (text) => color(text, "red");
6
+ export const yellow = (text) => color(text, "yellow");
7
+ export const magenta = (text) => color(text, "magenta");
8
+ export const underline = (text) => color(text, "underline");
9
+ export const bgRed = (text) => color(text, "bgRed");
10
+ export const bgYellow = (text) => color(text, "bgYellow");
11
+ //# sourceMappingURL=colors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/utils/colors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAStC,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,KAAY,EAAU,EAAE;IAC1D,OAAO,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAEhE,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAEtE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AAExE,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AAE5E,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAEpE,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { SeverityLevel, SeverityMap } from "../types/types.js";
2
+ export declare const names: SeverityMap["names"];
3
+ export declare const normalize: (severity?: SeverityLevel) => SeverityLevel[];
4
+ //# sourceMappingURL=severities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"severities.d.ts","sourceRoot":"","sources":["../../src/utils/severities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEpE,eAAO,MAAM,KAAK,EAAE,WAAW,CAAC,OAAO,CAGtC,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,WAAW,aAAa,KAAG,aAAa,EAEjE,CAAC"}
@@ -0,0 +1,8 @@
1
+ export const names = {
2
+ 1: "Warning",
3
+ 2: "Error",
4
+ };
5
+ export const normalize = (severity) => {
6
+ return severity ? [severity] : [1, 2];
7
+ };
8
+ //# sourceMappingURL=severities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"severities.js","sourceRoot":"","sources":["../../src/utils/severities.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,KAAK,GAAyB;IACzC,CAAC,EAAE,SAAS;IACZ,CAAC,EAAE,OAAO;CACX,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,QAAwB,EAAmB,EAAE;IACrE,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACxC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintResult, RuleStats, FolderStats, SeverityLevel } from "../types/types.js";
2
+ export declare function byRule(results: LintResult[], severity?: SeverityLevel): RuleStats;
3
+ export declare function byFolderAndRule(results: LintResult[], severity?: SeverityLevel): FolderStats;
4
+ //# sourceMappingURL=stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/utils/stats.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EAEV,SAAS,EACT,WAAW,EACX,aAAa,EAEd,MAAM,mBAAmB,CAAC;AA2D3B,wBAAgB,MAAM,CACpB,OAAO,EAAE,UAAU,EAAE,EACrB,QAAQ,CAAC,EAAE,aAAa,GACvB,SAAS,CAaX;AAQD,wBAAgB,eAAe,CAC7B,OAAO,EAAE,UAAU,EAAE,EACrB,QAAQ,CAAC,EAAE,aAAa,GACvB,WAAW,CAIb"}
@@ -0,0 +1,48 @@
1
+ import path from "node:path";
2
+ import { names } from "./severities.js";
3
+ const countBy = (array, iterate) => {
4
+ return array.reduce((result, item) => {
5
+ const key = String(iterate(item));
6
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
7
+ return result;
8
+ }
9
+ result[key] = (result[key] ?? 0) + 1;
10
+ return result;
11
+ }, {});
12
+ };
13
+ const groupBy = (array, iterate) => {
14
+ return array.reduce((result, item) => {
15
+ const key = String(iterate(item));
16
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
17
+ return result;
18
+ }
19
+ if (!Array.isArray(result[key])) {
20
+ result[key] = [];
21
+ }
22
+ result[key].push(item);
23
+ return result;
24
+ }, {});
25
+ };
26
+ const mapValues = (obj, iterate) => {
27
+ return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, iterate(value)]));
28
+ };
29
+ const getStatsForRule = (ruleMessages) => {
30
+ return countBy(ruleMessages, (message) => names[message.severity]);
31
+ };
32
+ export function byRule(results, severity) {
33
+ const allMessages = results.flatMap((result) => result.messages);
34
+ const messagesInSeverities = severity
35
+ ? allMessages.filter((message) => message.severity === severity)
36
+ : allMessages;
37
+ const messagesByRuleId = groupBy(messagesInSeverities, (message) => message.ruleId ?? "unknown");
38
+ return mapValues(messagesByRuleId, getStatsForRule);
39
+ }
40
+ const getDirName = (result) => {
41
+ const dirname = path.dirname(result.filePath);
42
+ return dirname === "." ? "Base Folder" : dirname;
43
+ };
44
+ export function byFolderAndRule(results, severity) {
45
+ const byDirName = groupBy(results, getDirName);
46
+ return mapValues(byDirName, (messages) => byRule(messages, severity));
47
+ }
48
+ //# sourceMappingURL=stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/utils/stats.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,105 @@
1
+ {
2
+ "name": "@danielsitek/eslint-stats",
3
+ "version": "0.1.0",
4
+ "description": "Modern TypeScript formatters for ESLint with aggregated error/warning statistics and visual graphs - Zero dependencies",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./by-error": {
14
+ "types": "./dist/formatters/by-error.d.ts",
15
+ "import": "./dist/formatters/by-error.js"
16
+ },
17
+ "./by-warning": {
18
+ "types": "./dist/formatters/by-warning.d.ts",
19
+ "import": "./dist/formatters/by-warning.js"
20
+ },
21
+ "./by-error-and-warning": {
22
+ "types": "./dist/formatters/by-error-and-warning.d.ts",
23
+ "import": "./dist/formatters/by-error-and-warning.js"
24
+ },
25
+ "./by-error-and-warning-stacked": {
26
+ "types": "./dist/formatters/by-error-and-warning-stacked.d.ts",
27
+ "import": "./dist/formatters/by-error-and-warning-stacked.js"
28
+ },
29
+ "./by-folder": {
30
+ "types": "./dist/formatters/by-folder.d.ts",
31
+ "import": "./dist/formatters/by-folder.js"
32
+ }
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "LICENSE"
38
+ ],
39
+ "keywords": [
40
+ "eslint",
41
+ "formatter",
42
+ "statistics",
43
+ "stats",
44
+ "aggregated",
45
+ "visualization",
46
+ "typescript",
47
+ "zero-dependencies",
48
+ "eslint9"
49
+ ],
50
+ "scripts": {
51
+ "build": "tsc -p tsconfig.build.json",
52
+ "clean": "rm -rf dist",
53
+ "prebuild": "npm run clean",
54
+ "typecheck": "tsc --noEmit",
55
+ "lint": "eslint .",
56
+ "format": "prettier --write .",
57
+ "format:check": "prettier --check .",
58
+ "test": "tsx --test test/**/*.test.ts",
59
+ "test:watch": "tsx --test --watch test/**/*.test.ts",
60
+ "test:coverage": "tsx --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info --test test/**/*.test.ts",
61
+ "prepublishOnly": "npm run build && npm test",
62
+ "demo:error": "eslint .demo/test.js -f ./dist/formatters/by-error.js -c .demo/eslint.config.mjs",
63
+ "demo:warning": "eslint .demo/test.js -f ./dist/formatters/by-warning.js -c .demo/eslint.config.mjs",
64
+ "demo:both": "eslint .demo/test.js -f ./dist/formatters/by-error-and-warning.js -c .demo/eslint.config.mjs",
65
+ "demo:stacked": "eslint .demo/test.js -f ./dist/formatters/by-error-and-warning-stacked.js -c .demo/eslint.config.mjs",
66
+ "demo:folder": "eslint .demo/test.js -f ./dist/formatters/by-folder.js -c .demo/eslint.config.mjs"
67
+ },
68
+ "repository": {
69
+ "type": "git",
70
+ "url": "git+https://github.com/danielsitek/eslint-stats.git"
71
+ },
72
+ "bugs": {
73
+ "url": "https://github.com/danielsitek/eslint-stats/issues"
74
+ },
75
+ "homepage": "https://github.com/danielsitek/eslint-stats#readme",
76
+ "author": {
77
+ "name": "Daniel Sitek",
78
+ "email": "me@danielsitek.com",
79
+ "url": "https://github.com/danielsitek"
80
+ },
81
+ "contributors": [
82
+ {
83
+ "name": "Omer Ganim",
84
+ "email": "ganimomer@gmail.com",
85
+ "url": "http://github.com/ganimomer"
86
+ }
87
+ ],
88
+ "engines": {
89
+ "node": ">=20.0.0"
90
+ },
91
+ "peerDependencies": {
92
+ "eslint": ">=8.0.0"
93
+ },
94
+ "license": "MIT",
95
+ "devDependencies": {
96
+ "@types/node": "^25.0.10",
97
+ "@typescript-eslint/eslint-plugin": "^8.53.1",
98
+ "@typescript-eslint/parser": "^8.53.1",
99
+ "eslint": "^9.39.2",
100
+ "eslint-config-prettier": "^10.1.8",
101
+ "prettier": "^3.8.1",
102
+ "tsx": "^4.21.0",
103
+ "typescript": "^5.9.3"
104
+ }
105
+ }