import * as fs from "fs-extra" ; import * as path from "path" ; import { formatWithPrettier } from "../../maintenance/src/prettier" ; const apiRegex = /^@API\(CommandClasses(?:\.|\[)(.+?)(?:\])?\)/m ; const classNameRegex = /class ([^\s]+) extends (\w+)?CCAPI/ ; const ccDir = path . join ( __dirname , ".." , "src/lib/commandclass" ) ; const apiFile = path . join ( ccDir , "API.ts" ) ; const startTokenType = "export type CCToName<CC extends CommandClasses> =" ; const endTokenType = "never;" ; const startTokenInterface = "\t// AUTO GENERATION BELOW" ; const endTokenInterface = "}" ; process . on ( "unhandledRejection" , ( r ) => { throw r ; } ) ; export async function generateCCAPIInterface ( ) { const ccFiles = ( await fs . readdir ( ccDir ) ) . filter ( ( file ) => file . endsWith ( ".ts" ) && ! file . endsWith ( "test.ts" ) ) ; const CCsWithAPI = [ ] ; for ( const ccFile of ccFiles ) { const fileContent = await fs . readFile ( path . join ( ccDir , ccFile ) , "utf8" ) ; const apiMatch = apiRegex . exec ( fileContent ) ; const classMatch = classNameRegex . exec ( fileContent ) ; if ( apiMatch && classMatch ) { CCsWithAPI . push ( { file : ccFile . replace ( /\.ts$/ , "" ) , name : apiMatch [ 1 ] , className : classMatch [ 1 ] } ) ; } } console . log ( `Found ${ CCsWithAPI . length } API classes...` ) ; const originalApiFileContent = await fs . readFile ( apiFile , "utf8" ) ; let apiFileContent = originalApiFileContent ; let startTokenEnd = apiFileContent . indexOf ( startTokenInterface ) + startTokenInterface . length ; let endTokenStart = apiFileContent . indexOf ( endTokenInterface , startTokenEnd ) ; apiFileContent = apiFileContent . substr ( 0 , startTokenEnd ) + "\n" + CCsWithAPI . map ( ( { name , className , file } ) => `\t${ name }: import("./${ file }").${ className };` ) . join ( "\n" ) + "\n" + apiFileContent . substr ( endTokenStart ) ; startTokenEnd = apiFileContent . indexOf ( startTokenType ) + startTokenType . length ; endTokenStart = apiFileContent . indexOf ( endTokenType , startTokenEnd ) ; apiFileContent = apiFileContent . substr ( 0 , startTokenEnd ) + "\n" + CCsWithAPI . map ( ( { name } ) => { if ( ! name . startsWith ( `"` ) ) name = `"${ name }"` ; return `\t[CC] extends [(typeof CommandClasses[${ name }])] ? ${ name } : ` ; } ) . join ( "\n" ) + "\n" + apiFileContent . substr ( endTokenStart ) ; apiFileContent = formatWithPrettier ( apiFile , apiFileContent ) ; if ( apiFileContent !== originalApiFileContent ) { console . log ( "API interface changed" ) ; await fs . writeFile ( apiFile , apiFileContent , "utf8" ) ; } } if ( require . main === module ) void generateCCAPIInterface ( ) ;