import { createHash } from "crypto" ; import * as fs from "fs-extra" ; import * as path from "path" ; import { DeviceModelManager , ModelType } from "../deviceModel/deviceModelManager" ; import { DigitalTwinConstants } from "../intelliSense/digitalTwinConstants" ; import { ModelFileInfo } from "../modelRepository/modelRepositoryManager" ; import { Constants } from "./constants" ; import { PnPModelTypeInvalidError } from "../../../../common/Error/PnPErrors/PnPModelTypeInvalidError" ; /**
 * Common utility
 */ export class Utility { param templatePath param filePath param replacement static async createFileFromTemplate ( templatePath , filePath , replacement ) { const template = await fs . readFile ( templatePath , Constants . UTF8 ) ; const content = Utility . replaceAll ( template , replacement ) ; const jsonContent = JSON . parse ( content ) ; await fs . writeJson ( filePath , jsonContent , { spaces : Constants . JSON_SPACE , encoding : Constants . UTF8 } ) ; } param str param replacement static replaceAll ( str , replacement ) { const keys = Array . from ( replacement . keys ( ) ) ; const pattern = new RegExp ( keys . join ( "|" ) , "g" ) ; return str . replace ( pattern , matched => { const value = replacement . get ( matched ) ; return value || matched ; } ) ; } param name param type param folder static async validateModelName ( name , type , folder ) { if ( ! name || name . trim ( ) === Constants . EMPTY_STRING ) { return `Name ${ Constants . NOT_EMPTY_MSG }` ; } if ( ! Constants . MODEL_NAME_REGEX . test ( name ) ) { return `Name can only contain ${ Constants . MODEL_NAME_REGEX_DESCRIPTION }` ; } const filename = DeviceModelManager . generateModelFileName ( name , type ) ; if ( await fs . pathExists ( path . join ( folder , filename ) ) ) { return `${ type } ${ name } already exists in folder ${ folder }` ; } return undefined ; } param name param placeholder static validateNotEmpty ( name , placeholder ) { if ( ! name || name . trim ( ) === Constants . EMPTY_STRING ) { return `${ placeholder } ${ Constants . NOT_EMPTY_MSG }` ; } return undefined ; } param url static enforceHttps ( url ) { return Constants . URL_PROTOCAL_REGEX . test ( url ) ? url . replace ( Constants . URL_PROTOCAL_REGEX , Constants . HTTPS_PROTOCAL ) : Constants . HTTPS_PROTOCAL + url ; } param folder param modelId param content static async createModelFile ( folder , modelId , content ) { const type = DeviceModelManager . convertToModelType ( content [ DigitalTwinConstants . TYPE ] ) ; if ( ! type ) { throw new PnPModelTypeInvalidError ( "create model file" , type ) ; } const replacement = new Map < string , string > ( ) ; replacement . set ( ":" , "_" ) ; const modelName = Utility . replaceAll ( modelId , replacement ) ; let candidate = DeviceModelManager . generateModelFileName ( modelName , type ) ; let counter = 0 ; while ( true ) { if ( ! ( await fs . pathExists ( path . join ( folder , candidate ) ) ) ) { break ; } counter ++ ; candidate = DeviceModelManager . generateModelFileName ( `${ modelName }_${ counter }` , type ) ; } await fs . writeJson ( path . join ( folder , candidate ) , content , { spaces : Constants . JSON_SPACE , encoding : Constants . UTF8 } ) ; } param filePath static async getModelFileInfo ( filePath ) { const content = await Utility . getJsonContent ( filePath ) ; const modelId = content [ DigitalTwinConstants . ID ] ; const context = content [ DigitalTwinConstants . CONTEXT ] ; const modelType = DeviceModelManager . convertToModelType ( content [ DigitalTwinConstants . TYPE ] ) ; if ( modelId && context && modelType ) { return { id : modelId , type : modelType , filePath } ; } return undefined ; } param filePath static async getJsonContent ( filePath ) { return fs . readJson ( filePath , { encoding : Constants . UTF8 } ) ; } param payload static hash ( payload ) { return createHash ( Constants . SHA256 ) . update ( payload ) . digest ( Constants . HEX ) ; } private constructor ( ) { } }