From 018bcc42fbf896b39a36a3e40d744c15b768a826 Mon Sep 17 00:00:00 2001 From: SahilDahekar Date: Wed, 30 Oct 2024 12:32:49 +0530 Subject: [PATCH 1/3] Implemented logic to output diagnostics log by adding additional output flag --- src/core/parser.ts | 50 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/core/parser.ts b/src/core/parser.ts index 3bbb69c87c3..58124a6262e 100644 --- a/src/core/parser.ts +++ b/src/core/parser.ts @@ -12,6 +12,22 @@ import { red, yellow, green, cyan } from 'chalk'; import type { Diagnostic } from '@asyncapi/parser/cjs'; import type Command from './base'; import type { Specification } from './models/SpecificationFile'; +import { promises } from 'fs'; +import path from 'path'; + +const { writeFile } = promises; + +type DiagnosticsFormat = 'stylish' | 'json' | 'junit' | 'html' | 'text' | 'teamcity' | 'pretty'; + +const formatExtensions: Record = { + stylish: '.txt', + json: '.json', + junit: '.xml', + html: '.html', + text: '.txt', + teamcity: '.txt', + pretty: '.txt', +}; export type SeverityKind = 'error' | 'warn' | 'info' | 'hint'; @@ -56,6 +72,10 @@ export function validationFlags({ logDiagnostics = true }: ValidationFlagsOption options: ['error', 'warn', 'info', 'hint'] as const, default: 'error', })(), + 'output': Flags.string({ + description: 'The output file name. Omitting this flag the result will be printed in the console.', + char: 'o' + }) }; } @@ -63,6 +83,7 @@ export interface ValidateOptions { 'log-diagnostics'?: boolean; 'diagnostics-format'?: `${OutputFormat}`; 'fail-severity'?: SeverityKind; + 'output'?: string; } export async function validate(command: Command, specFile: Specification, options: ValidateOptions = {}) { @@ -86,14 +107,24 @@ function logDiagnostics(diagnostics: Diagnostic[], command: Command, specFile: S if (hasFailSeverity(diagnostics, failSeverity)) { if (logDiagnostics) { command.logToStderr(`\n${sourceString} and/or referenced documents have governance issues.`); - command.logToStderr(formatOutput(diagnostics, diagnosticsFormat, failSeverity)); + const diagnosticsOutput = formatOutput(diagnostics, diagnosticsFormat, failSeverity); + if (options.output) { + writeValidationDiagnostic(options.output, command, diagnosticsFormat, diagnosticsOutput); + } else { + command.log(diagnosticsOutput); + } } return ValidationStatus.INVALID; } if (logDiagnostics) { command.log(`\n${sourceString} is valid but has (itself and/or referenced documents) governance issues.`); - command.log(formatOutput(diagnostics, diagnosticsFormat, failSeverity)); + const diagnosticsOutput = formatOutput(diagnostics, diagnosticsFormat, failSeverity); + if (options.output) { + writeValidationDiagnostic(options.output, command, diagnosticsFormat, diagnosticsOutput); + } else { + command.log(diagnosticsOutput); + } } } else if (logDiagnostics) { command.log(`\n${sourceString} is valid! ${sourceString} and referenced documents don't have governance issues.`); @@ -145,3 +176,18 @@ function hasFailSeverity(diagnostics: Diagnostic[], failSeverity: SeverityKind) const diagnosticSeverity = getDiagnosticSeverity(failSeverity); return diagnostics.some(diagnostic => diagnostic.severity <= diagnosticSeverity); } + +async function writeValidationDiagnostic(outputPath: string, command: Command, format: DiagnosticsFormat, formatOutput: string){ + const expectedExtension = formatExtensions[format]; + const actualExtension = path.extname(outputPath); + + // Validate file extension against diagnostics format + if (expectedExtension && (actualExtension !== expectedExtension)) { + command.logToStderr(`Invalid file extension for format "${format}". Expected extension: "${expectedExtension}"`); + } else { + await writeFile(path.resolve(process.cwd(), outputPath), formatOutput, { + encoding: 'utf-8', + }).catch(err => console.log(err)); + } + +} From 89554d82ff6ab83aed04488e25a53ca7ee36c0fa Mon Sep 17 00:00:00 2001 From: SahilDahekar Date: Mon, 11 Nov 2024 19:53:08 +0530 Subject: [PATCH 2/3] Fixed linting errors and warnings --- src/core/parser.ts | 128 ++++++++++++++++++++++++++++++++------------- 1 file changed, 93 insertions(+), 35 deletions(-) diff --git a/src/core/parser.ts b/src/core/parser.ts index 58124a6262e..65c6d26e728 100644 --- a/src/core/parser.ts +++ b/src/core/parser.ts @@ -15,10 +15,14 @@ import type { Specification } from './models/SpecificationFile'; import { promises } from 'fs'; import path from 'path'; -const { writeFile } = promises; - type DiagnosticsFormat = 'stylish' | 'json' | 'junit' | 'html' | 'text' | 'teamcity' | 'pretty'; +export type SeverityKind = 'error' | 'warn' | 'info' | 'hint'; + +export { convertToOldAPI }; + +const { writeFile } = promises; + const formatExtensions: Record = { stylish: '.txt', json: '.json', @@ -29,9 +33,7 @@ const formatExtensions: Record = { pretty: '.txt', }; -export type SeverityKind = 'error' | 'warn' | 'info' | 'hint'; - -export { convertToOldAPI }; +const validFormats = ['stylish', 'json', 'junit', 'html', 'text', 'teamcity', 'pretty']; const parser = new Parser({ __unstable: { @@ -72,7 +74,7 @@ export function validationFlags({ logDiagnostics = true }: ValidationFlagsOption options: ['error', 'warn', 'info', 'hint'] as const, default: 'error', })(), - 'output': Flags.string({ + output: Flags.string({ description: 'The output file name. Omitting this flag the result will be printed in the console.', char: 'o' }) @@ -97,40 +99,92 @@ export async function parse(command: Command, specFile: Specification, options: return { document, diagnostics, status }; } -function logDiagnostics(diagnostics: Diagnostic[], command: Command, specFile: Specification, options: ValidateOptions = {}): 'valid' | 'invalid' { +// function logDiagnostics(diagnostics: Diagnostic[], command: Command, specFile: Specification, options: ValidateOptions = {}): 'valid' | 'invalid' { +// const logDiagnostics = options['log-diagnostics']; +// const failSeverity = options['fail-severity'] ?? 'error'; +// const diagnosticsFormat = options['diagnostics-format'] ?? 'stylish'; + +// const sourceString = specFile.toSourceString(); +// if (diagnostics.length) { +// if (hasFailSeverity(diagnostics, failSeverity)) { +// if (logDiagnostics) { +// command.logToStderr(`\n${sourceString} and/or referenced documents have governance issues.`); +// const diagnosticsOutput = formatOutput(diagnostics, diagnosticsFormat, failSeverity); +// if (options.output) { +// writeValidationDiagnostic(options.output, command, diagnosticsFormat, diagnosticsOutput); +// } else { +// command.log(diagnosticsOutput); +// } +// } +// return ValidationStatus.INVALID; +// } + +// if (logDiagnostics) { +// command.log(`\n${sourceString} is valid but has (itself and/or referenced documents) governance issues.`); +// const diagnosticsOutput = formatOutput(diagnostics, diagnosticsFormat, failSeverity); +// if (options.output) { +// writeValidationDiagnostic(options.output, command, diagnosticsFormat, diagnosticsOutput); +// } else { +// command.log(diagnosticsOutput); +// } +// } +// } else if (logDiagnostics) { +// command.log(`\n${sourceString} is valid! ${sourceString} and referenced documents don't have governance issues.`); +// } + +// return ValidationStatus.VALID; +// } + +function logDiagnostics( + diagnostics: Diagnostic[], + command: Command, + specFile: Specification, + options: ValidateOptions = {} +): 'valid' | 'invalid' { const logDiagnostics = options['log-diagnostics']; const failSeverity = options['fail-severity'] ?? 'error'; const diagnosticsFormat = options['diagnostics-format'] ?? 'stylish'; - const sourceString = specFile.toSourceString(); - if (diagnostics.length) { - if (hasFailSeverity(diagnostics, failSeverity)) { - if (logDiagnostics) { - command.logToStderr(`\n${sourceString} and/or referenced documents have governance issues.`); - const diagnosticsOutput = formatOutput(diagnostics, diagnosticsFormat, failSeverity); - if (options.output) { - writeValidationDiagnostic(options.output, command, diagnosticsFormat, diagnosticsOutput); - } else { - command.log(diagnosticsOutput); - } - } - return ValidationStatus.INVALID; - } - if (logDiagnostics) { - command.log(`\n${sourceString} is valid but has (itself and/or referenced documents) governance issues.`); - const diagnosticsOutput = formatOutput(diagnostics, diagnosticsFormat, failSeverity); - if (options.output) { - writeValidationDiagnostic(options.output, command, diagnosticsFormat, diagnosticsOutput); - } else { - command.log(diagnosticsOutput); - } - } - } else if (logDiagnostics) { + const hasIssues = diagnostics.length > 0; + const isFailSeverity = hasIssues && hasFailSeverity(diagnostics, failSeverity); + + if (logDiagnostics) { + logGovernanceMessage(command, sourceString, hasIssues, isFailSeverity); + outputDiagnostics(command, diagnostics, diagnosticsFormat, failSeverity, options); + } + + return isFailSeverity ? ValidationStatus.INVALID : ValidationStatus.VALID; +} + +function logGovernanceMessage( + command: Command, + sourceString: string, + hasIssues: boolean, + isFailSeverity: boolean +) { + if (!hasIssues) { command.log(`\n${sourceString} is valid! ${sourceString} and referenced documents don't have governance issues.`); + } else if (isFailSeverity) { + command.logToStderr(`\n${sourceString} and/or referenced documents have governance issues.`); + } else { + command.log(`\n${sourceString} is valid but has (itself and/or referenced documents) governance issues.`); } +} - return ValidationStatus.VALID; +function outputDiagnostics( + command: Command, + diagnostics: Diagnostic[], + diagnosticsFormat: DiagnosticsFormat, + failSeverity: SeverityKind, + options: ValidateOptions +) { + const diagnosticsOutput = formatOutput(diagnostics, diagnosticsFormat, failSeverity); + if (options.output) { + writeValidationDiagnostic(options.output, command, diagnosticsFormat, diagnosticsOutput); + } else { + command.log(diagnosticsOutput); + } } export function formatOutput(diagnostics: Diagnostic[], format: `${OutputFormat}`, failSeverity: SeverityKind) { @@ -177,8 +231,13 @@ function hasFailSeverity(diagnostics: Diagnostic[], failSeverity: SeverityKind) return diagnostics.some(diagnostic => diagnostic.severity <= diagnosticSeverity); } -async function writeValidationDiagnostic(outputPath: string, command: Command, format: DiagnosticsFormat, formatOutput: string){ - const expectedExtension = formatExtensions[format]; +async function writeValidationDiagnostic(outputPath: string, command: Command, format: DiagnosticsFormat, formatOutput: string) { + if (!validFormats.includes(format)) { + command.logToStderr(`Invalid diagnostics format: "${format}"`); + return; + } + + const expectedExtension = formatExtensions[format as keyof typeof formatExtensions]; const actualExtension = path.extname(outputPath); // Validate file extension against diagnostics format @@ -189,5 +248,4 @@ async function writeValidationDiagnostic(outputPath: string, command: Command, f encoding: 'utf-8', }).catch(err => console.log(err)); } - } From 842d098f403edf27e6c1d91f485ff5c5eb3b42ce Mon Sep 17 00:00:00 2001 From: SahilDahekar Date: Wed, 13 Nov 2024 10:56:21 +0530 Subject: [PATCH 3/3] Removed comment from parser.ts --- src/core/parser.ts | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/src/core/parser.ts b/src/core/parser.ts index 65c6d26e728..b692f174652 100644 --- a/src/core/parser.ts +++ b/src/core/parser.ts @@ -99,42 +99,6 @@ export async function parse(command: Command, specFile: Specification, options: return { document, diagnostics, status }; } -// function logDiagnostics(diagnostics: Diagnostic[], command: Command, specFile: Specification, options: ValidateOptions = {}): 'valid' | 'invalid' { -// const logDiagnostics = options['log-diagnostics']; -// const failSeverity = options['fail-severity'] ?? 'error'; -// const diagnosticsFormat = options['diagnostics-format'] ?? 'stylish'; - -// const sourceString = specFile.toSourceString(); -// if (diagnostics.length) { -// if (hasFailSeverity(diagnostics, failSeverity)) { -// if (logDiagnostics) { -// command.logToStderr(`\n${sourceString} and/or referenced documents have governance issues.`); -// const diagnosticsOutput = formatOutput(diagnostics, diagnosticsFormat, failSeverity); -// if (options.output) { -// writeValidationDiagnostic(options.output, command, diagnosticsFormat, diagnosticsOutput); -// } else { -// command.log(diagnosticsOutput); -// } -// } -// return ValidationStatus.INVALID; -// } - -// if (logDiagnostics) { -// command.log(`\n${sourceString} is valid but has (itself and/or referenced documents) governance issues.`); -// const diagnosticsOutput = formatOutput(diagnostics, diagnosticsFormat, failSeverity); -// if (options.output) { -// writeValidationDiagnostic(options.output, command, diagnosticsFormat, diagnosticsOutput); -// } else { -// command.log(diagnosticsOutput); -// } -// } -// } else if (logDiagnostics) { -// command.log(`\n${sourceString} is valid! ${sourceString} and referenced documents don't have governance issues.`); -// } - -// return ValidationStatus.VALID; -// } - function logDiagnostics( diagnostics: Diagnostic[], command: Command,