Skip to content

Commit 16411a4

Browse files
committed
feat: sort rules before writing to stdout
Signed-off-by: Mats Johansson <extern.mats.johansson@digg.se>
1 parent 3542e5e commit 16411a4

File tree

1 file changed

+181
-150
lines changed

1 file changed

+181
-150
lines changed

src/cli-mode.ts

Lines changed: 181 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
import * as fs from "node:fs";
2-
import { join } from "path";
3-
import Parsers from "@stoplight/spectral-parsers";
4-
import { Document } from "@stoplight/spectral-core";
5-
import { importAndCreateRuleInstances } from "./util/ruleUtil.js"; // Import the helper function
1+
import * as fs from 'node:fs';
2+
import { join } from 'path';
3+
import Parsers from '@stoplight/spectral-parsers';
4+
import { Document } from '@stoplight/spectral-core';
5+
import { importAndCreateRuleInstances } from './util/ruleUtil.js'; // Import the helper function
66
import util from 'util';
7-
import {RapLPCustomSpectral} from "./util/RapLPCustomSpectral.js";
8-
import {DiagnosticReport, RapLPDiagnostic} from "./util/RapLPDiagnostic.js";
9-
import {AggregateError} from "./util/RapLPCustomErrorInfo.js";
7+
import { RapLPCustomSpectral } from './util/RapLPCustomSpectral.js';
8+
import { DiagnosticReport, RapLPDiagnostic } from './util/RapLPDiagnostic.js';
9+
import { AggregateError } from './util/RapLPCustomErrorInfo.js';
1010
import chalk from 'chalk';
11-
import { ExcelReportProcessor } from "./util/excelReportProcessor.js";
11+
import { ExcelReportProcessor } from './util/excelReportProcessor.js';
1212

1313
declare var AggregateError: {
14-
prototype: AggregateError;
15-
new(errors: any[], message?: string): AggregateError;
14+
prototype: AggregateError;
15+
new (errors: any[], message?: string): AggregateError;
1616
};
1717

1818
const writeFileAsync = util.promisify(fs.writeFile);
@@ -24,153 +24,184 @@ export type CliArgs = {
2424
logError?: string;
2525
append: boolean;
2626
logDiagnostic?: string;
27-
dex?: string
28-
}
27+
dex?: string;
28+
};
2929

3030
export async function execCLI<T extends CliArgs>(argv: T) {
31+
try {
32+
// Parse command-line arguments using yargs
33+
const apiSpecFileName = (argv.file as string) || '';
34+
const ruleCategories = argv.categories ? (argv.categories as string).split(',') : undefined;
35+
const logErrorFilePath = argv.logError as string | undefined;
36+
const logDiagnosticFilePath = argv.logDiagnostic as string | undefined;
3137
try {
32-
// Parse command-line arguments using yargs
33-
const apiSpecFileName = (argv.file as string) || "";
34-
const ruleCategories = argv.categories ? (argv.categories as string).split(",") : undefined;
35-
const logErrorFilePath = argv.logError as string | undefined;
36-
const logDiagnosticFilePath = argv.logDiagnostic as string | undefined;
37-
try {
38-
39-
// Import and create rule instances in RAP-LP
40-
const enabledRulesAndCategorys = await importAndCreateRuleInstances(ruleCategories);
41-
// Load API specification into a Document object
42-
const apiSpecDocument = new Document(
43-
fs.readFileSync(join(apiSpecFileName), "utf-8").trim(),
44-
Parsers.Yaml,
45-
apiSpecFileName
46-
);
47-
48-
try {
49-
/**
50-
* CustomSpectral
51-
*/
52-
const customSpectral = new RapLPCustomSpectral();
53-
customSpectral.setCategorys(enabledRulesAndCategorys.instanceCategoryMap);
54-
customSpectral.setRuleset(enabledRulesAndCategorys.rules);
55-
const result = await customSpectral.run(apiSpecDocument);
56-
57-
const customDiagnostic = new RapLPDiagnostic();
58-
customDiagnostic.processRuleExecutionInformation(result,enabledRulesAndCategorys.instanceCategoryMap);
59-
const diagnosticReports: DiagnosticReport[] = customDiagnostic.processDiagnosticInformation();
60-
61-
if(argv.dex != null) {
62-
const reportHandler = new ExcelReportProcessor({
63-
outputFilePath: argv.dex,
64-
});
65-
reportHandler.generateReportDocument(customDiagnostic)
38+
// Import and create rule instances in RAP-LP
39+
const enabledRulesAndCategorys = await importAndCreateRuleInstances(ruleCategories);
40+
// Load API specification into a Document object
41+
const apiSpecDocument = new Document(
42+
fs.readFileSync(join(apiSpecFileName), 'utf-8').trim(),
43+
Parsers.Yaml,
44+
apiSpecFileName,
45+
);
46+
47+
try {
48+
/**
49+
* CustomSpectral
50+
*/
51+
const customSpectral = new RapLPCustomSpectral();
52+
customSpectral.setCategorys(enabledRulesAndCategorys.instanceCategoryMap);
53+
customSpectral.setRuleset(enabledRulesAndCategorys.rules);
54+
const result = await customSpectral.run(apiSpecDocument);
55+
56+
const customDiagnostic = new RapLPDiagnostic();
57+
customDiagnostic.processRuleExecutionInformation(result, enabledRulesAndCategorys.instanceCategoryMap);
58+
const diagnosticReports: DiagnosticReport[] = customDiagnostic.processDiagnosticInformation();
59+
60+
if (argv.dex != null) {
61+
const reportHandler = new ExcelReportProcessor({
62+
outputFilePath: argv.dex,
63+
});
64+
reportHandler.generateReportDocument(customDiagnostic);
65+
}
66+
67+
/**
68+
* Chalk impl.
69+
* @param allvarlighetsgrad
70+
* @returns
71+
*/
72+
// Run Spectral on the API specification and log the result
73+
const colorizeSeverity = (allvarlighetsgrad: string) => {
74+
switch (allvarlighetsgrad) {
75+
case 'ERROR': // Error
76+
return chalk.red('Error');
77+
case 'WARNING': // Warning
78+
return chalk.yellow('Warning');
79+
case 'HINT': // Info
80+
return chalk.greenBright('Hint');
81+
default:
82+
return chalk.white('Info');
6683
}
84+
};
85+
const formatLintingResult = (result: any) => {
86+
return `allvarlighetsgrad: ${colorizeSeverity(result.allvarlighetsgrad)} \nid: ${result.id} \nkrav: ${
87+
result.krav
88+
} \nområde: ${result.omrade} \nsökväg:[${result.sokvag}] \nomfattning:${JSON.stringify(
89+
result.omfattning,
90+
null,
91+
2,
92+
)} `;
93+
};
94+
//Check specified option from yargs input
95+
96+
const currentDate = new Date(); //.toISOString(); // Get current date and time in ISO format
97+
const formattedDate = `${currentDate.getFullYear()}-${padZero(currentDate.getMonth() + 1)}-${padZero(
98+
currentDate.getDate(),
99+
)} ${padZero(currentDate.getHours())}:${padZero(currentDate.getMinutes())}:${padZero(
100+
currentDate.getSeconds(),
101+
)}`;
67102

68-
/**
69-
* Chalk impl.
70-
* @param allvarlighetsgrad
71-
* @returns
72-
*/
73-
// Run Spectral on the API specification and log the result
74-
const colorizeSeverity = (allvarlighetsgrad: string) => {
75-
switch (allvarlighetsgrad) {
76-
case 'ERROR': // Error
77-
return chalk.red('Error');
78-
case 'WARNING': // Warning
79-
return chalk.yellow('Warning');
80-
case 'HINT': // Info
81-
return chalk.greenBright('Hint');
82-
default:
83-
return chalk.white('Info');
84-
}
85-
};
86-
const formatLintingResult = (result: any) => {
87-
return `allvarlighetsgrad: ${colorizeSeverity(result.allvarlighetsgrad)} \nid: ${result.id} \nkrav: ${result.krav} \nområde: ${result.omrade} \nsökväg:[${result.sokvag}] \nomfattning:${JSON.stringify(result.omfattning,null,2)} `;
88-
};
89-
//Check specified option from yargs input
90-
91-
const currentDate = new Date() //.toISOString(); // Get current date and time in ISO format
92-
const formattedDate = `${currentDate.getFullYear()}-${padZero(currentDate.getMonth() + 1)}-${padZero(currentDate.getDate())} ${padZero(currentDate.getHours())}:${padZero(currentDate.getMinutes())}:${padZero(currentDate.getSeconds())}`;
93-
94-
function padZero(num: number): string {
95-
return num < 10 ? `0${num}` : `${num}`;
96-
}
97-
if (logDiagnosticFilePath) {
98-
let allDiagnosticReports = JSON.stringify(diagnosticReports, null, 2);
99-
let logEntry = `${formattedDate}\n${allDiagnosticReports}\n`; // Prepend datestamp to log entry
100-
let utf8EncodedContent = Buffer.from(logEntry, 'utf8');
101-
//Log to disc
102-
await writeFileAsync(logDiagnosticFilePath,utf8EncodedContent);
103-
console.log(chalk.green(`Skriver diagnostiseringsinformation från RAP-LP till ${logDiagnosticFilePath}`));
104-
}else {
105-
//STDOUT
106-
if (customDiagnostic.diagnosticInformation.executedUniqueRules!=undefined &&
107-
customDiagnostic.diagnosticInformation.executedUniqueRules.length>0) {
108-
console.log(chalk.green("<<<Verkställda och godkända regler - RAP-LP>>>\r"));
109-
console.log(chalk.whiteBright("STATUS\tOMRÅDE") + " / " +chalk.whiteBright("IDENTIFIKATIONSNUMMER")) ;
110-
customDiagnostic.diagnosticInformation.executedUniqueRules.forEach(item => {
111-
console.log(chalk.bgGreen("OK") + "\t" + item.omrade + " / " + item.id) ;
112-
});
113-
}
114-
if (customDiagnostic.diagnosticInformation.executedUniqueRulesWithError!=undefined &&
115-
customDiagnostic.diagnosticInformation.executedUniqueRulesWithError.length>0) {
116-
console.log(chalk.green("<<<Verkställda och ej godkända regler - RAP-LP>>>\r"));
117-
console.log(chalk.whiteBright("STATUS\tOMRÅDE") + " / " + chalk.whiteBright("IDENTIFIKATIONSNUMMER")) ;
118-
customDiagnostic.diagnosticInformation.executedUniqueRulesWithError.forEach(item => {
119-
console.log(chalk.bgRed("EJ OK") + "\t" + item.omrade + " / " + item.id) ;
120-
});
121-
}
122-
if (customDiagnostic.diagnosticInformation.notApplicableRules!=undefined &&
123-
customDiagnostic.diagnosticInformation.notApplicableRules.length>0) {
124-
console.log(chalk.grey("<<<Ej tillämpade regler - RAP-LP>>>\r"));
125-
console.log(chalk.whiteBright("STATUS\tOMRÅDE") + " / " + chalk.whiteBright("IDENTIFIKATIONSNUMMER")) ;
126-
customDiagnostic.diagnosticInformation.notApplicableRules.forEach(item => {
127-
console.log(chalk.bgGrey("N/A") + "\t" + item.omrade + "/" + item.id);
128-
});
129-
}
130-
}
131-
if (logErrorFilePath ) {
132-
let content = JSON.stringify(result, null, 2);
133-
let logEntry = `${formattedDate}\n${content}\n`; // Prepend datestamp to log entry
134-
let utf8EncodedContent = Buffer.from(logEntry, 'utf8');
135-
if (argv.append) {
136-
await appendFileAsync(logErrorFilePath,utf8EncodedContent);
137-
console.log(chalk.green(`Skriver inspektion/valideringsinformation från RAP-LP till ${logErrorFilePath}`));
138-
}else {
139-
//Log to disc
140-
await writeFileAsync(logErrorFilePath,utf8EncodedContent);
141-
console.log(chalk.green(`Skriver inspektion/valideringsinformation från RAP-LP till ${logErrorFilePath}`));
142-
}
143-
}else {
144-
//Verbose error logging goes here with detailed result
145-
console.log(chalk.whiteBright('\n<<Regelutfall RAP-LP>> \n'));
146-
result.forEach(item => {
147-
console.log(formatLintingResult(item));
103+
function padZero(num: number): string {
104+
return num < 10 ? `0${num}` : `${num}`;
105+
}
106+
if (logDiagnosticFilePath) {
107+
let allDiagnosticReports = JSON.stringify(diagnosticReports, null, 2);
108+
let logEntry = `${formattedDate}\n${allDiagnosticReports}\n`; // Prepend datestamp to log entry
109+
let utf8EncodedContent = Buffer.from(logEntry, 'utf8');
110+
//Log to disc
111+
await writeFileAsync(logDiagnosticFilePath, utf8EncodedContent);
112+
console.log(chalk.green(`Skriver diagnostiseringsinformation från RAP-LP till ${logDiagnosticFilePath}`));
113+
} else {
114+
//STDOUT
115+
if (
116+
customDiagnostic.diagnosticInformation.executedUniqueRules != undefined &&
117+
customDiagnostic.diagnosticInformation.executedUniqueRules.length > 0
118+
) {
119+
console.log(chalk.green('<<<Verkställda och godkända regler - RAP-LP>>>\r'));
120+
console.log(chalk.whiteBright('STATUS\tOMRÅDE') + ' / ' + chalk.whiteBright('IDENTIFIKATIONSNUMMER'));
121+
customDiagnostic.diagnosticInformation.executedUniqueRules
122+
.sort((a, b) => a.omrade.localeCompare(b.omrade, 'sv') || a.id.localeCompare(b.id, 'sv'))
123+
.forEach((item) => {
124+
console.log(chalk.bgGreen('OK') + '\t' + item.omrade + ' / ' + item.id);
125+
});
126+
}
127+
if (
128+
customDiagnostic.diagnosticInformation.executedUniqueRulesWithError != undefined &&
129+
customDiagnostic.diagnosticInformation.executedUniqueRulesWithError.length > 0
130+
) {
131+
console.log(chalk.green('<<<Verkställda och ej godkända regler - RAP-LP>>>\r'));
132+
console.log(chalk.whiteBright('STATUS\tOMRÅDE') + ' / ' + chalk.whiteBright('IDENTIFIKATIONSNUMMER'));
133+
customDiagnostic.diagnosticInformation.executedUniqueRulesWithError
134+
.sort((a, b) => a.omrade.localeCompare(b.omrade, 'sv') || a.id.localeCompare(b.id, 'sv'))
135+
.forEach((item) => {
136+
console.log(chalk.bgRed('EJ OK') + '\t' + item.omrade + ' / ' + item.id);
137+
});
138+
}
139+
if (
140+
customDiagnostic.diagnosticInformation.notApplicableRules != undefined &&
141+
customDiagnostic.diagnosticInformation.notApplicableRules.length > 0
142+
) {
143+
console.log(chalk.grey('<<<Ej tillämpade regler - RAP-LP>>>\r'));
144+
console.log(chalk.whiteBright('STATUS\tOMRÅDE') + ' / ' + chalk.whiteBright('IDENTIFIKATIONSNUMMER'));
145+
customDiagnostic.diagnosticInformation.notApplicableRules
146+
.sort((a, b) => a.omrade.localeCompare(b.omrade, 'sv') || a.id.localeCompare(b.id, 'sv'))
147+
.forEach((item) => {
148+
console.log(chalk.bgGrey('N/A') + '\t' + item.omrade + '/' + item.id);
148149
});
149-
}
150-
} catch (spectralError: any) {
151-
logErrorToFile(spectralError); // Log stack
152-
console.error(chalk.red("Ett fel uppstod vid initiering/körning av regelklasser! Undersök felloggen för RAP-LP för mer information om felet"));
153150
}
154-
} catch (initializingError: any) {
155-
logErrorToFile(initializingError);
156-
console.error(chalk.red("Ett fel uppstod vid inläsning av moduler och skapande av regelklasser! Undersök felloggen för RAP-LP för mer information om felet"));
157-
}
158-
} catch (error: any) {
159-
logErrorToFile(error);
160-
console.error(chalk.red("Ett oväntat fel uppstod! Undersök felloggen för RAP-LP för mer information om felet", error.message));
161-
}
162-
function logErrorToFile(error: any) {
163-
const errorMessage = `${new Date().toISOString()} - ${error.stack}\n`;
164-
fs.appendFileSync('rap-lp-error.log', errorMessage);
165-
if (error.errors) {
166-
const detailedMessage = `${new Date().toISOString()} - ${JSON.stringify(error.errors, null, 2)}\n`;
167-
fs.appendFileSync('rap-lp-error.log', detailedMessage);
168151
}
169-
if (error instanceof AggregateError) {
170-
error.errors.forEach((err: any, index: number) => {
171-
const causeMessage = `Cause ${index + 1}: ${err.stack || err}\n`;
172-
fs.appendFileSync('rap-lp-error.log', causeMessage);
152+
if (logErrorFilePath) {
153+
let content = JSON.stringify(result, null, 2);
154+
let logEntry = `${formattedDate}\n${content}\n`; // Prepend datestamp to log entry
155+
let utf8EncodedContent = Buffer.from(logEntry, 'utf8');
156+
if (argv.append) {
157+
await appendFileAsync(logErrorFilePath, utf8EncodedContent);
158+
console.log(chalk.green(`Skriver inspektion/valideringsinformation från RAP-LP till ${logErrorFilePath}`));
159+
} else {
160+
//Log to disc
161+
await writeFileAsync(logErrorFilePath, utf8EncodedContent);
162+
console.log(chalk.green(`Skriver inspektion/valideringsinformation från RAP-LP till ${logErrorFilePath}`));
163+
}
164+
} else {
165+
//Verbose error logging goes here with detailed result
166+
console.log(chalk.whiteBright('\n<<Regelutfall RAP-LP>> \n'));
167+
result.forEach((item) => {
168+
console.log(formatLintingResult(item));
173169
});
174170
}
171+
} catch (spectralError: any) {
172+
logErrorToFile(spectralError); // Log stack
173+
console.error(
174+
chalk.red(
175+
'Ett fel uppstod vid initiering/körning av regelklasser! Undersök felloggen för RAP-LP för mer information om felet',
176+
),
177+
);
175178
}
176-
}
179+
} catch (initializingError: any) {
180+
logErrorToFile(initializingError);
181+
console.error(
182+
chalk.red(
183+
'Ett fel uppstod vid inläsning av moduler och skapande av regelklasser! Undersök felloggen för RAP-LP för mer information om felet',
184+
),
185+
);
186+
}
187+
} catch (error: any) {
188+
logErrorToFile(error);
189+
console.error(
190+
chalk.red('Ett oväntat fel uppstod! Undersök felloggen för RAP-LP för mer information om felet', error.message),
191+
);
192+
}
193+
function logErrorToFile(error: any) {
194+
const errorMessage = `${new Date().toISOString()} - ${error.stack}\n`;
195+
fs.appendFileSync('rap-lp-error.log', errorMessage);
196+
if (error.errors) {
197+
const detailedMessage = `${new Date().toISOString()} - ${JSON.stringify(error.errors, null, 2)}\n`;
198+
fs.appendFileSync('rap-lp-error.log', detailedMessage);
199+
}
200+
if (error instanceof AggregateError) {
201+
error.errors.forEach((err: any, index: number) => {
202+
const causeMessage = `Cause ${index + 1}: ${err.stack || err}\n`;
203+
fs.appendFileSync('rap-lp-error.log', causeMessage);
204+
});
205+
}
206+
}
207+
}

0 commit comments

Comments
 (0)