@herodevs/cli 2.0.0-beta.4 → 2.0.0-beta.5

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 (55) hide show
  1. package/README.md +142 -108
  2. package/dist/api/gql-operations.d.ts +2 -0
  3. package/dist/api/gql-operations.js +36 -0
  4. package/dist/api/nes.client.d.ts +12 -0
  5. package/dist/api/nes.client.js +71 -0
  6. package/dist/commands/scan/eol.d.ts +12 -12
  7. package/dist/commands/scan/eol.js +163 -104
  8. package/dist/config/constants.d.ts +8 -3
  9. package/dist/config/constants.js +18 -3
  10. package/dist/hooks/finally.d.ts +3 -0
  11. package/dist/hooks/finally.js +14 -0
  12. package/dist/hooks/prerun.js +12 -0
  13. package/dist/service/analytics.svc.d.ts +28 -0
  14. package/dist/service/analytics.svc.js +112 -0
  15. package/dist/service/{eol/cdx.svc.d.ts → cdx.svc.d.ts} +8 -16
  16. package/dist/service/{eol/cdx.svc.js → cdx.svc.js} +17 -7
  17. package/dist/service/display.svc.d.ts +22 -0
  18. package/dist/service/display.svc.js +72 -0
  19. package/dist/service/file.svc.d.ts +20 -0
  20. package/dist/service/file.svc.js +71 -0
  21. package/dist/service/log.svc.d.ts +1 -0
  22. package/dist/service/log.svc.js +9 -0
  23. package/dist/service/{eol/sbom.worker.js → sbom.worker.js} +1 -1
  24. package/package.json +22 -15
  25. package/dist/api/client.d.ts +0 -12
  26. package/dist/api/client.js +0 -43
  27. package/dist/api/nes/nes.client.d.ts +0 -24
  28. package/dist/api/nes/nes.client.js +0 -127
  29. package/dist/api/queries/nes/sbom.d.ts +0 -3
  30. package/dist/api/queries/nes/sbom.js +0 -39
  31. package/dist/api/queries/nes/telemetry.d.ts +0 -2
  32. package/dist/api/queries/nes/telemetry.js +0 -24
  33. package/dist/api/types/hd-cli.types.d.ts +0 -30
  34. package/dist/api/types/hd-cli.types.js +0 -10
  35. package/dist/api/types/nes.types.d.ts +0 -58
  36. package/dist/api/types/nes.types.js +0 -1
  37. package/dist/commands/report/committers.d.ts +0 -23
  38. package/dist/commands/report/committers.js +0 -147
  39. package/dist/commands/report/purls.d.ts +0 -15
  40. package/dist/commands/report/purls.js +0 -85
  41. package/dist/commands/scan/sbom.d.ts +0 -21
  42. package/dist/commands/scan/sbom.js +0 -164
  43. package/dist/service/committers.svc.d.ts +0 -70
  44. package/dist/service/committers.svc.js +0 -196
  45. package/dist/service/eol/eol.svc.d.ts +0 -12
  46. package/dist/service/eol/eol.svc.js +0 -25
  47. package/dist/service/error.svc.d.ts +0 -8
  48. package/dist/service/error.svc.js +0 -28
  49. package/dist/service/nes/nes.svc.d.ts +0 -5
  50. package/dist/service/nes/nes.svc.js +0 -36
  51. package/dist/service/purls.svc.d.ts +0 -23
  52. package/dist/service/purls.svc.js +0 -99
  53. package/dist/ui/shared.ui.d.ts +0 -4
  54. package/dist/ui/shared.ui.js +0 -14
  55. /package/dist/service/{eol/sbom.worker.d.ts → sbom.worker.d.ts} +0 -0
@@ -1,58 +0,0 @@
1
- /**
2
- * Input parameters for the EOL scan operation
3
- */
4
- export interface InsightsEolScanInput {
5
- scanId?: string;
6
- /** Array of package URLs in purl format to scan */
7
- components: string[];
8
- /** The type of scan being performed (e.g. 'SBOM') */
9
- type: string;
10
- page: number;
11
- totalPages: number;
12
- }
13
- export interface ScanResponse {
14
- insights: {
15
- scan: {
16
- eol: InsightsEolScanResult;
17
- };
18
- };
19
- }
20
- /**
21
- * Result of the EOL scan operation
22
- */
23
- export interface InsightsEolScanResult {
24
- scanId?: string;
25
- createdOn: string;
26
- success: boolean;
27
- message: string;
28
- components: InsightsEolScanComponent[];
29
- warnings: ScanWarning[];
30
- }
31
- /**
32
- * Information about a component's EOL status
33
- */
34
- export interface InsightsEolScanComponentInfo {
35
- isEol: boolean;
36
- isUnsafe: boolean;
37
- eolAt: Date | null;
38
- status: ComponentStatus;
39
- daysEol: number | null;
40
- vulnCount: number | null;
41
- nesAvailable?: boolean;
42
- }
43
- export interface InsightsEolScanComponent {
44
- info: InsightsEolScanComponentInfo;
45
- purl: string;
46
- remediation?: {
47
- id: string;
48
- } | null;
49
- }
50
- export interface ScanWarning {
51
- purl: string;
52
- message: string;
53
- type?: string;
54
- error?: unknown;
55
- diagnostics?: Record<string, unknown>;
56
- }
57
- export type ComponentStatus = (typeof VALID_STATUSES)[number];
58
- export declare const VALID_STATUSES: readonly ["UNKNOWN", "OK", "EOL", "EOL_UPCOMING"];
@@ -1 +0,0 @@
1
- export const VALID_STATUSES = ['UNKNOWN', 'OK', 'EOL', 'EOL_UPCOMING'];
@@ -1,23 +0,0 @@
1
- import { Command } from '@oclif/core';
2
- import { type ReportData } from '../../service/committers.svc.ts';
3
- export default class Committers extends Command {
4
- static description: string;
5
- static enableJsonFlag: boolean;
6
- static examples: string[];
7
- static flags: {
8
- months: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
9
- csv: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
- save: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
- };
12
- run(): Promise<ReportData | string>;
13
- /**
14
- * Generates structured report data
15
- * @param entries - parsed git log output for commits
16
- */
17
- private generateReportData;
18
- /**
19
- * Fetches git commit data with month and author information
20
- * @param sinceDate - Date range for git log
21
- */
22
- private fetchGitCommitData;
23
- }
@@ -1,147 +0,0 @@
1
- import { spawnSync } from 'node:child_process';
2
- import { Command, Flags } from '@oclif/core';
3
- import fs from 'node:fs';
4
- import path from 'node:path';
5
- import { filenamePrefix } from "../../config/constants.js";
6
- import { calculateOverallStats, formatAsCsv, formatAsText, groupCommitsByMonth, parseGitLogOutput, } from "../../service/committers.svc.js";
7
- import { getErrorMessage, isErrnoException } from "../../service/error.svc.js";
8
- export default class Committers extends Command {
9
- static description = 'Generate report of committers to a git repository';
10
- static enableJsonFlag = true;
11
- static examples = [
12
- '<%= config.bin %> <%= command.id %>',
13
- '<%= config.bin %> <%= command.id %> --csv -s',
14
- '<%= config.bin %> <%= command.id %> --json',
15
- '<%= config.bin %> <%= command.id %> --csv',
16
- ];
17
- static flags = {
18
- months: Flags.integer({
19
- char: 'm',
20
- description: 'The number of months of git history to review',
21
- default: 12,
22
- }),
23
- csv: Flags.boolean({
24
- char: 'c',
25
- description: 'Output in CSV format',
26
- default: false,
27
- }),
28
- save: Flags.boolean({
29
- char: 's',
30
- description: `Save the committers report as ${filenamePrefix}.committers.<output>`,
31
- default: false,
32
- }),
33
- };
34
- async run() {
35
- const { flags } = await this.parse(Committers);
36
- const { months, csv, save } = flags;
37
- const isJson = this.jsonEnabled();
38
- const sinceDate = `${months} months ago`;
39
- this.log('Starting committers report with flags: %O', flags);
40
- try {
41
- // Generate structured report data
42
- const entries = this.fetchGitCommitData(sinceDate);
43
- this.log('Fetched %d commit entries', entries.length);
44
- const reportData = this.generateReportData(entries);
45
- // Handle different output scenarios
46
- if (isJson) {
47
- // JSON mode
48
- if (save) {
49
- try {
50
- fs.writeFileSync(path.resolve(`${filenamePrefix}.committers.json`), JSON.stringify(reportData, null, 2));
51
- this.log('Report written to json');
52
- }
53
- catch (error) {
54
- this.error(`Failed to save JSON report: ${getErrorMessage(error)}`);
55
- }
56
- }
57
- return reportData;
58
- }
59
- const textOutput = formatAsText(reportData);
60
- if (csv) {
61
- // CSV mode
62
- const csvOutput = formatAsCsv(reportData);
63
- if (save) {
64
- try {
65
- fs.writeFileSync(path.resolve(`${filenamePrefix}.committers.csv`), csvOutput);
66
- this.log('Report written to csv');
67
- }
68
- catch (error) {
69
- this.error(`Failed to save CSV report: ${getErrorMessage(error)}`);
70
- }
71
- }
72
- else {
73
- this.log(textOutput);
74
- }
75
- return csvOutput;
76
- }
77
- if (save) {
78
- try {
79
- fs.writeFileSync(path.resolve(`${filenamePrefix}.committers.txt`), textOutput);
80
- this.log('Report written to txt');
81
- }
82
- catch (error) {
83
- this.error(`Failed to save txt report: ${getErrorMessage(error)}`);
84
- }
85
- }
86
- else {
87
- this.log(textOutput);
88
- }
89
- return textOutput;
90
- }
91
- catch (error) {
92
- this.error(`Failed to generate report: ${getErrorMessage(error)}`);
93
- }
94
- }
95
- /**
96
- * Generates structured report data
97
- * @param entries - parsed git log output for commits
98
- */
99
- generateReportData(entries) {
100
- if (entries.length === 0) {
101
- return { monthly: {}, overall: { total: 0 } };
102
- }
103
- const monthlyData = groupCommitsByMonth(entries);
104
- const overallStats = calculateOverallStats(entries);
105
- const grandTotal = entries.length;
106
- // Format into a structured report data object
107
- const report = {
108
- monthly: {},
109
- overall: { ...overallStats, total: grandTotal },
110
- };
111
- // Add monthly totals
112
- for (const [month, authors] of Object.entries(monthlyData)) {
113
- const monthTotal = Object.values(authors).reduce((sum, count) => sum + count, 0);
114
- report.monthly[month] = { ...authors, total: monthTotal };
115
- }
116
- return report;
117
- }
118
- /**
119
- * Fetches git commit data with month and author information
120
- * @param sinceDate - Date range for git log
121
- */
122
- fetchGitCommitData(sinceDate) {
123
- const logProcess = spawnSync('git', [
124
- 'log',
125
- '--all', // Include committers on all branches in the repo
126
- '--format="%ad|%an"', // Format: date|author
127
- '--date=format:%Y-%m', // Format date as YYYY-MM
128
- `--since="${sinceDate}"`,
129
- ], { encoding: 'utf-8' });
130
- if (logProcess.error) {
131
- if (isErrnoException(logProcess.error)) {
132
- if (logProcess.error.code === 'ENOENT') {
133
- this.error('Git command not found. Please ensure git is installed and available in your PATH.');
134
- }
135
- this.error(`Git command failed: ${getErrorMessage(logProcess.error)}`);
136
- }
137
- this.error(`Git command failed: ${getErrorMessage(logProcess.error)}`);
138
- }
139
- if (logProcess.status !== 0) {
140
- this.error(`Git command failed with status ${logProcess.status}: ${logProcess.stderr}`);
141
- }
142
- if (!logProcess.stdout) {
143
- return [];
144
- }
145
- return parseGitLogOutput(logProcess.stdout);
146
- }
147
- }
@@ -1,15 +0,0 @@
1
- import { Command } from '@oclif/core';
2
- export default class ReportPurls extends Command {
3
- static description: string;
4
- static enableJsonFlag: boolean;
5
- static examples: string[];
6
- static flags: {
7
- file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
- dir: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
- save: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
- csv: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
- };
12
- run(): Promise<{
13
- purls: string[];
14
- }>;
15
- }
@@ -1,85 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { Command, Flags, ux } from '@oclif/core';
4
- import { filenamePrefix } from "../../config/constants.js";
5
- import { getErrorMessage, isErrnoException } from "../../service/error.svc.js";
6
- import { extractPurls, getPurlOutput } from "../../service/purls.svc.js";
7
- import ScanSbom from "../scan/sbom.js";
8
- export default class ReportPurls extends Command {
9
- static description = 'Generate a list of purls from a sbom';
10
- static enableJsonFlag = true;
11
- static examples = [
12
- '<%= config.bin %> <%= command.id %> --json -s',
13
- '<%= config.bin %> <%= command.id %> --dir=./my-project',
14
- '<%= config.bin %> <%= command.id %> --file=path/to/sbom.json',
15
- '<%= config.bin %> <%= command.id %> --dir=./my-project --save',
16
- '<%= config.bin %> <%= command.id %> --save --csv',
17
- ];
18
- static flags = {
19
- file: Flags.string({
20
- char: 'f',
21
- description: 'The file path of an existing cyclonedx sbom to scan for EOL',
22
- }),
23
- dir: Flags.string({
24
- char: 'd',
25
- description: 'The directory to scan in order to create a cyclonedx sbom',
26
- }),
27
- save: Flags.boolean({
28
- char: 's',
29
- default: false,
30
- description: `Save the list of purls as ${filenamePrefix}.purls.<output>`,
31
- }),
32
- csv: Flags.boolean({
33
- char: 'c',
34
- default: false,
35
- description: 'Save output in CSV format (only applies when using --save)',
36
- }),
37
- };
38
- async run() {
39
- const { flags } = await this.parse(ReportPurls);
40
- const { dir: _dirFlag, file: _fileFlag, save, csv } = flags;
41
- try {
42
- const sbom = await ScanSbom.loadSbom(flags, this.config);
43
- const purls = await extractPurls(sbom);
44
- this.log('Extracted %d purls from SBOM', purls.length);
45
- ux.action.stop('Scan completed');
46
- // Print the purls
47
- for (const purl of purls) {
48
- this.log(purl);
49
- }
50
- // Save if requested
51
- if (save) {
52
- try {
53
- const outputFile = csv && !this.jsonEnabled() ? 'csv' : 'json';
54
- const outputPath = path.join(_dirFlag || process.cwd(), `${filenamePrefix}.purls.${outputFile}`);
55
- const purlOutput = getPurlOutput(purls, outputFile);
56
- fs.writeFileSync(outputPath, purlOutput);
57
- this.log('Purls saved to %s', outputPath);
58
- }
59
- catch (error) {
60
- if (isErrnoException(error)) {
61
- switch (error.code) {
62
- case 'EACCES':
63
- this.error('Permission denied: Cannot write to output file');
64
- break;
65
- case 'ENOSPC':
66
- this.error('No space left on device');
67
- break;
68
- case 'EISDIR':
69
- this.error('Cannot write to output file: Is a directory');
70
- break;
71
- default:
72
- this.error(`Failed to save purls: ${getErrorMessage(error)}`);
73
- }
74
- }
75
- this.error(`Failed to save purls: ${getErrorMessage(error)}`);
76
- }
77
- }
78
- // Return wrapped object with metadata
79
- return { purls };
80
- }
81
- catch (error) {
82
- this.error(`Failed to generate PURLs: ${getErrorMessage(error)}`);
83
- }
84
- }
85
- }
@@ -1,21 +0,0 @@
1
- import { Command } from '@oclif/core';
2
- import type { Sbom } from '../../service/eol/cdx.svc.ts';
3
- export default class ScanSbom extends Command {
4
- static description: string;
5
- static enableJsonFlag: boolean;
6
- static examples: string[];
7
- static flags: {
8
- file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
- dir: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
- save: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
- background: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
- };
13
- static loadSbom(flags: Record<string, string>, config: Command['config']): Promise<Sbom>;
14
- static getSbomArgs(flags: Record<string, string>): string[];
15
- getScanOptions(): {};
16
- run(): Promise<Sbom | undefined>;
17
- private _getSbomFromScan;
18
- private _getSbomInBackground;
19
- private _getSbomFromFile;
20
- private _saveSbom;
21
- }
@@ -1,164 +0,0 @@
1
- import { spawn } from 'node:child_process';
2
- import fs from 'node:fs';
3
- import { join, resolve } from 'node:path';
4
- import { Command, Flags, ux } from '@oclif/core';
5
- import { filenamePrefix } from "../../config/constants.js";
6
- import { createSbom, validateIsCycloneDxSbom } from "../../service/eol/eol.svc.js";
7
- import { getErrorMessage } from "../../service/error.svc.js";
8
- export default class ScanSbom extends Command {
9
- static description = 'Scan a SBOM for purls';
10
- static enableJsonFlag = true;
11
- static examples = [
12
- '<%= config.bin %> <%= command.id %> --dir=./my-project',
13
- '<%= config.bin %> <%= command.id %> --file=path/to/sbom.json',
14
- ];
15
- static flags = {
16
- file: Flags.string({
17
- char: 'f',
18
- description: 'The file path of an existing cyclonedx sbom to scan for EOL',
19
- }),
20
- dir: Flags.string({
21
- char: 'd',
22
- description: 'The directory to scan in order to create a cyclonedx sbom',
23
- }),
24
- save: Flags.boolean({
25
- char: 's',
26
- default: false,
27
- description: `Save the generated SBOM as ${filenamePrefix}.sbom.json in the scanned directory`,
28
- }),
29
- background: Flags.boolean({
30
- char: 'b',
31
- default: false,
32
- description: 'Run the scan in the background',
33
- }),
34
- };
35
- static async loadSbom(flags, config) {
36
- const sbomArgs = ScanSbom.getSbomArgs(flags);
37
- const sbomCommand = new ScanSbom(sbomArgs, config);
38
- const sbom = await sbomCommand.run();
39
- if (!sbom) {
40
- throw new Error('SBOM not generated');
41
- }
42
- return sbom;
43
- }
44
- static getSbomArgs(flags) {
45
- const { dir, file, background } = flags ?? {};
46
- const sbomArgs = ['--json'];
47
- if (file)
48
- sbomArgs.push('--file', file);
49
- if (dir)
50
- sbomArgs.push('--dir', dir);
51
- // if (save) sbomArgs.push('--save'); // only save if sbom command is used directly with -s flag
52
- if (background)
53
- sbomArgs.push('--background');
54
- return sbomArgs;
55
- }
56
- getScanOptions() {
57
- // intentionally provided for mocking
58
- return {};
59
- }
60
- async run() {
61
- const { flags } = await this.parse(ScanSbom);
62
- const { dir, save, file, background } = flags;
63
- // Validate that exactly one of --file or --dir is provided
64
- if (file && dir) {
65
- this.error('Cannot specify both --file and --dir flags. Please use one or the other.');
66
- }
67
- let sbom;
68
- const path = dir || process.cwd();
69
- if (file) {
70
- sbom = this._getSbomFromFile(file);
71
- ux.action.stop();
72
- }
73
- else if (background) {
74
- this._getSbomInBackground(path);
75
- this.log(`The scan is running in the background. The file will be saved at ${path}/${filenamePrefix}.sbom.json`);
76
- ux.action.stop();
77
- return;
78
- }
79
- else {
80
- sbom = await this._getSbomFromScan(path);
81
- ux.action.stop();
82
- if (save) {
83
- this._saveSbom(path, sbom);
84
- }
85
- }
86
- if (!save) {
87
- this.log(JSON.stringify(sbom, null, 2));
88
- }
89
- return sbom;
90
- }
91
- async _getSbomFromScan(_dirFlag) {
92
- const dir = resolve(_dirFlag);
93
- try {
94
- if (!fs.existsSync(dir)) {
95
- this.error(`Directory not found: ${dir}`);
96
- }
97
- const stats = fs.statSync(dir);
98
- if (!stats.isDirectory()) {
99
- this.error(`Path is not a directory: ${dir}`);
100
- }
101
- ux.action.start(`Scanning ${dir}`);
102
- const options = this.getScanOptions();
103
- const sbom = await createSbom(dir, options);
104
- if (!sbom) {
105
- this.error(`SBOM failed to generate for dir: ${dir}`);
106
- }
107
- return sbom;
108
- }
109
- catch (error) {
110
- this.error(`Failed to scan directory: ${getErrorMessage(error)}`);
111
- }
112
- }
113
- _getSbomInBackground(path) {
114
- try {
115
- const opts = this.getScanOptions();
116
- const args = [
117
- JSON.stringify({
118
- opts,
119
- path,
120
- }),
121
- ];
122
- const workerProcess = spawn('node', [join(import.meta.url, '../../service/eol/sbom.worker.js'), ...args], {
123
- stdio: 'ignore',
124
- detached: true,
125
- env: { ...process.env },
126
- });
127
- workerProcess.unref();
128
- }
129
- catch (error) {
130
- this.error(`Failed to start background scan: ${getErrorMessage(error)}`);
131
- }
132
- }
133
- _getSbomFromFile(_fileFlag) {
134
- const file = resolve(_fileFlag);
135
- try {
136
- if (!fs.existsSync(file)) {
137
- this.error(`SBOM file not found: ${file}`);
138
- }
139
- ux.action.start(`Loading sbom from ${file}`);
140
- const fileContent = fs.readFileSync(file, {
141
- encoding: 'utf8',
142
- flag: 'r',
143
- });
144
- const sbom = JSON.parse(fileContent);
145
- validateIsCycloneDxSbom(sbom);
146
- return sbom;
147
- }
148
- catch (error) {
149
- this.error(`Failed to read SBOM file: ${getErrorMessage(error)}`);
150
- }
151
- }
152
- _saveSbom(dir, sbom) {
153
- try {
154
- const outputPath = join(dir, `${filenamePrefix}.sbom.json`);
155
- fs.writeFileSync(outputPath, JSON.stringify(sbom, null, 2));
156
- if (!this.jsonEnabled()) {
157
- this.log(`SBOM saved to ${outputPath}`);
158
- }
159
- }
160
- catch (error) {
161
- this.error(`Failed to save SBOM: ${getErrorMessage(error)}`);
162
- }
163
- }
164
- }
@@ -1,70 +0,0 @@
1
- export interface CommitEntry {
2
- month: string;
3
- author: string;
4
- }
5
- export interface AuthorCommitCounts {
6
- [author: string]: number;
7
- }
8
- export interface MonthlyData {
9
- [month: string]: AuthorCommitCounts;
10
- }
11
- export interface ReportData {
12
- monthly: {
13
- [month: string]: {
14
- [author: string]: number;
15
- total: number;
16
- };
17
- };
18
- overall: {
19
- [author: string]: number;
20
- total: number;
21
- };
22
- }
23
- /**
24
- * Parses git log output into structured data
25
- * @param output - Git log command output
26
- * @returns Parsed commit entries
27
- */
28
- export declare function parseGitLogOutput(output: string): CommitEntry[];
29
- /**
30
- * Groups commit data by month
31
- * @param entries - Commit entries
32
- * @returns Object with months as keys and author commit counts as values
33
- */
34
- export declare function groupCommitsByMonth(entries: CommitEntry[]): MonthlyData;
35
- /**
36
- * Calculates overall commit statistics by author
37
- * @param entries - Commit entries
38
- * @returns Object with authors as keys and total commit counts as values
39
- */
40
- export declare function calculateOverallStats(entries: CommitEntry[]): AuthorCommitCounts;
41
- /**
42
- * Formats monthly report sections
43
- * @param monthlyData - Grouped commit data by month
44
- * @returns Formatted monthly report sections
45
- */
46
- export declare function formatMonthlyReport(monthlyData: MonthlyData): string;
47
- /**
48
- * Formats overall statistics section
49
- * @param overallStats - Overall commit counts by author
50
- * @param grandTotal - Total number of commits
51
- * @returns Formatted overall statistics section
52
- */
53
- export declare function formatOverallStats(overallStats: AuthorCommitCounts, grandTotal: number): string;
54
- /**
55
- * Formats the report data as CSV
56
- * @param data - The structured report data
57
- */
58
- export declare function formatAsCsv(data: ReportData): string;
59
- /**
60
- * Formats the report data as text
61
- * @param data - The structured report data
62
- */
63
- export declare function formatAsText(data: ReportData): string;
64
- /**
65
- * Format output based on user preference
66
- * @param output
67
- * @param reportData
68
- * @returns
69
- */
70
- export declare function formatOutputBasedOnFlag(output: string, reportData: ReportData): string;