import { promises , existsSync as fsExists , statSync } from "fs" ; import * as path from "path" ; import { JsonLdDocumentLintResult , JsonLdDocumentProcessingResultType , JsonLdDocumentProcessingResult , lint as jsonldLint , process as processDocument , JsonLdDocumentSyntaxError } from "jsonld-lint" ; export const exists = ( fileOrDirectoryPath ) : boolean => { return fsExists ( fileOrDirectoryPath ) ; } ; export const isDirectory = ( fileOrDirectoryPath ) : boolean => { const result = statSync ( fileOrDirectoryPath ) ; return result . isDirectory ( ) ; } ; export const processJsonLd = async ( file ) : Promise < boolean > => { try { if ( ! exists ( file ) ) { throw new Error ( "File does not exist" ) ; } if ( isDirectory ( file ) ) { throw new Error ( "Supplied path is a directory, expected a file" ) ; } return await processFile ( file ) ; } catch ( ex ) { console . error ( "ERROR:" , JSON . stringify ( ex , null , 2 ) , ex ) ; process . exit ( 1 ) ; } } ; export const lint = async ( fileOrDirectoryPath , recursiveFileSearch , fileExtensionFilter ) : Promise < boolean > => { try { console . log ( "JSON-LD Linter" ) ; if ( ! exists ( fileOrDirectoryPath ) ) { throw new Error ( "File or directory does not exist" ) ; } if ( fileExtensionFilter . charAt ( 0 ) !== "." ) { throw new Error ( "File extension must begin with `.`" ) ; } if ( isDirectory ( fileOrDirectoryPath ) ) { return await lintDirectory ( fileOrDirectoryPath , fileExtensionFilter , recursiveFileSearch ) ; } else { if ( recursiveFileSearch ) { console . log ( "WARN: ignoring recursive option, not valid when linting file" ) ; } return await lintFile ( fileOrDirectoryPath ) ; } } catch ( ex ) { console . error ( "ERROR:" , ex . message ) ; process . exit ( 1 ) ; } } ; export const lintDirectory = async ( directory , filter , recursive ) : Promise < boolean > => { const directoryPath = path . join ( process . env . PWD as string , directory ) ; console . log ( `Linting directory: ${ directoryPath } with file filter ${ filter } ${ recursive ? `recursively` : `` }` ) ; const matchedFiles = await fileSearch ( directory , filter , recursive ) ; if ( matchedFiles . length === 0 ) { console . log ( `No files found for linting` ) ; return true ; } let result = false ; for ( let i = 0 ; i < matchedFiles . length ; i ++ ) { result = ( await lintFile ( matchedFiles [ i ] ) ) || result ; } return result ; } ; export const processFile = async ( file ) : Promise < boolean > => { const filePath = path . join ( process . env . PWD as string , file ) ; const fileContents = ( await promises . readFile ( filePath ) ) . toString ( ) ; const results = await processDocument ( fileContents ) ; console . log ( JSON . stringify ( results , null , 2 ) ) ; return false ; } ; export const lintFile = async ( file ) : Promise < boolean > => { const filePath = path . join ( process . env . PWD as string , file ) ; const fileContents = ( await promises . readFile ( filePath ) ) . toString ( ) ; const results = await jsonldLint ( fileContents ) ; if ( results . length > 0 ) { formatResults ( filePath , results ) ; return true ; } else { console . log ( `SUCCESS: ${ filePath }` ) ; } return false ; } ; const formatResults = ( filePath , results ) => { results . filter ( item => item . type === JsonLdDocumentProcessingResultType . JsonLdSyntaxError ) . forEach ( result => { formatJsonSyntaxError ( filePath , result as JsonLdDocumentSyntaxError ) ; } ) ; results . filter ( item => item . type === JsonLdDocumentProcessingResultType . JsonLdLintingResult ) . forEach ( result => { formatLintResult ( filePath , result as JsonLdDocumentLintResult ) ; } ) ; } ; const formatLintResult = ( filePath , result ) => { console . log ( `ERROR: ${ filePath } - ${ result . message }` ) ; } ; const formatJsonSyntaxError = ( filePath , result ) => { console . log ( `SYNTAX ERROR: ${ filePath } - ${ result . message }` ) ; } ; const fileSearch = async ( startPath , filter , recursive , matchedFiles = [ ] ) : Promise < string [ ] > => { let files = await promises . readdir ( startPath ) ; for ( let i = 0 ; i < files . length ; i ++ ) { let filename = path . join ( startPath , files [ i ] ) ; let stat = await promises . lstat ( filename ) ; if ( stat . isDirectory ( ) && recursive ) { const results = await fileSearch ( filename , filter , recursive , matchedFiles ) ; results . forEach ( item => { if ( ! matchedFiles . includes ( item ) ) { matchedFiles . push ( item ) ; } } ) ; } else if ( filename . indexOf ( filter ) >= 0 && ! matchedFiles . includes ( filename ) ) { matchedFiles . push ( filename ) ; } } return matchedFiles ; } ;