import commander from 'commander' ; import fs from 'fs' ; import G from 'glob' ; import http from 'http' ; import os from 'os' ; import path from 'path' ; import { encode } from 'plantuml-encoder' ; import ts from 'typescript' ; import { tplant } from './tplant' ; const AVAILABLE_PLANTUML_EXTENSIONS = [ 'svg' , 'png' , 'txt' ] ; commander . version ( require ( '../package' ) . version ) . option ( '-i, --input <path>' , 'Define the path of the Typescript file' ) . option ( '-o, --output <path>' , 'Define the path of the output file. If not defined, it\'ll output on the STDOUT' ) . option ( '-p, --project <path>' , 'Compile a project given a valid configuration file.' + ' The argument can be a file path to a valid JSON configuration file,' + ' or a directory path to a directory containing a tsconfig.json file.' ) . option ( '-A, --associations' , 'Show associations between classes with cardinalities' ) . option ( '-I, --only-interfaces' , 'Only output interfaces' ) . option ( '-C, --only-classes' , 'Only output classes' ) . option ( '-f, --format <path>' , 'Define the format of output' ) . option ( '-T, --targetClass <className>' , 'Display class hierarchy diagram' ) . parse ( process . argv ) ; if ( ! commander . input ) { console . error ( 'Missing input file' ) ; process . exit ( 1 ) ; } G ( < string > commander . input , { } , ( err , matches ) : void => { if ( err !== null ) { throw err ; } const tsConfigFile = findTsConfigFile ( < string > commander . input , < string | undefined > commander . tsconfig ) ; const plantUMLDocument = tplant . convertToPlant ( tplant . generateDocumentation ( matches , getCompilerOptions ( tsConfigFile ) ) , { associations : < boolean > commander . associations , onlyInterfaces : < boolean > commander . onlyInterfaces , format : < string > commander . format , targetClass : < string > commander . targetClass , onlyClasses : < boolean > commander . onlyClasses } ) ; if ( commander . output === undefined ) { console . log ( plantUMLDocument ) ; return ; } const extension = path . extname ( < string > commander . output ) . replace ( /^\./gm , '' ) ; if ( AVAILABLE_PLANTUML_EXTENSIONS . includes ( extension ) ) { requestImageFile ( < string > commander . output , plantUMLDocument , extension ) ; return ; } fs . writeFileSync ( < string > commander . output , plantUMLDocument , 'utf-8' ) ; } ) ; function findTsConfigFile ( inputPath , tsConfigPath ? ) { if ( tsConfigPath !== undefined ) { const tsConfigStats = fs . statSync ( tsConfigPath ) ; if ( tsConfigStats . isFile ( ) ) { return tsConfigPath ; } if ( tsConfigStats . isDirectory ( ) ) { const tsConfigFilePath = path . resolve ( tsConfigPath , 'tsconfig.json' ) ; if ( fs . existsSync ( tsConfigFilePath ) ) { return tsConfigFilePath ; } } } const localTsConfigFile = path . resolve ( path . dirname ( inputPath ) , 'tsconfig.json' ) ; if ( fs . existsSync ( localTsConfigFile ) ) { return localTsConfigFile ; } const cwdTsConfigFile = path . resolve ( process . cwd ( ) , 'tsconfig.json' ) ; if ( fs . existsSync ( cwdTsConfigFile ) ) { return cwdTsConfigFile ; } return ; } function getCompilerOptions ( tsConfigFilePath ? ) { if ( tsConfigFilePath === undefined ) { return ts . getDefaultCompilerOptions ( ) ; } const reader = ( filePath ) : string | undefined => fs . readFileSync ( filePath , 'utf8' ) ; const configFile = ts . readConfigFile ( tsConfigFilePath , reader ) ; if ( configFile . error !== undefined && configFile . error . category === ts . DiagnosticCategory . Error ) { throw new Error ( `unable to read tsconfig.json file at: ${ tsConfigFilePath }.
             Error: ${ ts . flattenDiagnosticMessageText ( configFile . error . messageText , os . EOL ) }` ) ; } else if ( configFile . config === undefined ) { throw new Error ( `unable to read tsconfig.json file at: ${ tsConfigFilePath }.` ) ; } const convertedCompilerOptions = ts . convertCompilerOptionsFromJson ( configFile . config . compilerOptions , path . dirname ( tsConfigFilePath ) ) ; if ( convertedCompilerOptions . errors . length > 0 ) { convertedCompilerOptions . errors . forEach ( ( error ) : void => { if ( error . category === ts . DiagnosticCategory . Error ) { throw new Error ( `unable to read tsconfig.json file at: ${ tsConfigFilePath }.
                Error: ${ ts . flattenDiagnosticMessageText ( error . messageText , os . EOL ) }` ) ; } } ) ; } return convertedCompilerOptions . options ; } function requestImageFile ( output , input , extension ) { http . get ( { host : 'www.plantuml.com' , path : `/plantuml/${ extension }/${ encode ( input ) }` } , ( res ) : void => { const fileStream = fs . createWriteStream ( output ) ; res . setEncoding ( 'utf-8' ) ; res . pipe ( fileStream ) ; res . on ( 'error' , ( err ) : void => { throw err ; } ) ; } ) ; }