import path from 'path' ; import fs from 'fs' ; import { promisify } from 'util' ; import { EntityConfig , EntityModel } from './types' ; import { CommunOptions } from './Commun' ; import { EntityCodeHooks } from './types/EntityCodeHooks' ; let projectRootPath ; let srcRootPath ; let distRootPath ; export const ConfigManager = { getEntityPath ( entityName ) { return path . join ( srcRootPath , `entities/${ entityName }` ) ; } , getEntityConfigFilePath ( entityName ) { return path . join ( srcRootPath , `entities/${ entityName }/config.json` ) ; } , async readEnvConfig ( ) { const configFile = ( await this . _readFile ( path . join ( srcRootPath , `config/${ process . env . NODE_ENV }.json` ) ) ) . toString ( ) ; if ( ! configFile ) { throw new Error ( `Config file for environment ${ process . env . NODE_ENV } not found` ) ; } return JSON . parse ( configFile ) ; } , async getEntityConfigs < T > ( ) { const entityDirs = await this . _readdir ( path . join ( srcRootPath , 'entities' ) ) ; const entities = [ ] ; for ( const entity of entityDirs ) { entities . push ( await this . readEntityConfig < T > ( entity ) ) ; } return entities ; } , async readEntityConfig < T > ( entityName ) { const entityConfig = ( await this . _readFile ( this . getEntityConfigFilePath ( entityName ) ) ) . toString ( ) ; if ( ! entityConfig ) { throw new Error ( `Config file for entity ${ entityName } not found` ) ; } return JSON . parse ( entityConfig ) ; } , async setEntityConfig < T extends EntityModel > ( entityName , config ) { await ( this . _writeFile ( this . getEntityConfigFilePath ( entityName ) , JSON . stringify ( config , null , 2 ) ) ) ; } , async mergeEntityConfig < T extends EntityModel > ( entityName , config ) { const entityConfig = await this . readEntityConfig < T > ( entityName ) ; for ( const key of Object . keys ( config ) ) { entityConfig [ key as keyof EntityConfig < T > ] = config [ key as keyof EntityConfig < T > ] ; } await this . setEntityConfig < T > ( entityName , entityConfig ) ; return entityConfig ; } , async createEntityConfig < T extends EntityModel > ( entityName , config ) { const entityPath = this . getEntityPath ( entityName ) ; if ( ! ( await this . _exists ( entityPath ) ) ) { await this . _mkdir ( entityPath ) ; } await this . setEntityConfig ( entityName , config ) ; } , async deleteEntity ( entityName ) { const entityPath = this . getEntityPath ( entityName ) ; if ( await this . _exists ( entityPath ) ) { const files = await this . _readdir ( entityPath ) ; for ( const file of files ) { await this . _unlink ( path . join ( entityPath , file ) ) ; } await this . _rmdir ( entityPath ) ; } } , async getEntityCodeHooks ( entityName ) { const file = path . join ( distRootPath , `entities/${ entityName }/hooks.js` ) ; if ( await this . _exists ( file ) ) { return require ( file ) . default ; } return { } ; } , getPluginPath ( pluginName ) { return path . join ( srcRootPath , `plugins/${ pluginName }` ) ; } , getPluginSetupModulePath ( pluginName ) { return path . join ( distRootPath , `plugins/${ pluginName }/setup.js` ) ; } , getPluginConfigFilePath ( pluginName ) { return path . join ( this . getPluginPath ( pluginName ) , 'config.json' ) ; } , getPluginNames ( ) { return this . _readdir ( path . join ( srcRootPath , 'plugins' ) ) ; } , async runPluginSetup ( pluginName ) { const pluginSetup = this . getPluginSetupModulePath ( pluginName ) ; if ( ! pluginSetup ) { throw new Error ( `Config file for plugin ${ pluginName } not found` ) ; } return await require ( pluginSetup ) . default ( ) ; } , async readPluginConfig < T > ( pluginName ) { const pluginConfig = ( await this . _readFile ( this . getPluginConfigFilePath ( pluginName ) ) ) . toString ( ) ; if ( ! pluginConfig ) { throw new Error ( `Config file for plugin ${ pluginName } not found` ) ; } return JSON . parse ( pluginConfig ) ; } , async setPluginFile < T > ( pluginName , filePath , content ) { await this . _writeFile ( path . join ( this . getPluginPath ( pluginName ) , filePath ) , JSON . stringify ( content , null , 2 ) ) ; } , async deletePluginFile ( pluginName , filePath ) { await this . _unlink ( path . join ( this . getPluginPath ( pluginName ) , filePath ) ) ; } , setPluginConfig < T > ( pluginName , config ) { return this . setPluginFile < T > ( pluginName , 'config.json' , config ) ; } , async mergePluginConfig < T > ( pluginName , config ) { const pluginConfig = await this . readPluginConfig < T > ( pluginName ) ; for ( const key of Object . keys ( config ) ) { pluginConfig [ key as keyof T ] = config [ key as keyof T ] ! ; } await this . setPluginConfig < T > ( pluginName , pluginConfig ) ; return pluginConfig ; } , async writeGeneratedFile ( filename , content , onlyOnChanges = false ) { const generatedPath = path . join ( this . projectRootPath , '/generated' ) ; const filePath = path . join ( generatedPath , filename ) ; if ( ! ( await this . _exists ( generatedPath ) ) ) { await this . _mkdir ( generatedPath ) ; } if ( onlyOnChanges ) { const originalContent = ( await this . _readFile ( filePath ) ) . toString ( ) ; if ( originalContent === content ) { return ; } } await this . _writeFile ( path . join ( generatedPath , filename ) , content ) ; } , async getCommunOptions ( ) { const configPath = path . join ( srcRootPath , 'config' ) ; const envFiles = await this . _readdir ( configPath ) ; const options = { } ; for ( const file of envFiles ) { const envName = file . replace ( /\.json$/ , '' ) ; options [ envName ] = JSON . parse ( ( await this . _readFile ( path . join ( configPath , file ) ) ) . toString ( ) ) ; } return options ; } , async setCommunOptions ( environment , options ) { const configPath = path . join ( srcRootPath , `config/${ environment }.json` ) ; await this . _writeFile ( configPath , JSON . stringify ( options , null , 2 ) ) ; } , async getKeys ( name ) { const keysPath = path . join ( srcRootPath , '../keys' ) ; const publicKey = ( await this . _readFile ( path . join ( keysPath , `${ name }.pub` ) ) ) . toString ( ) ; const privateKey = ( await this . _readFile ( path . join ( keysPath , `${ name }.pem` ) ) ) . toString ( ) ; return { publicKey , privateKey } ; } , /**
     * Saves variables on the project's .env file
     */ async setEnvironmentVariable ( variables ) { const dotEnvPath = path . join ( projectRootPath , '.env' ) ; const dotEnvLines = [ ] ; if ( await this . _exists ( dotEnvPath ) ) { const dotEnvFile = ( await this . _readFile ( dotEnvPath ) ) . toString ( ) ; dotEnvLines . push ( ... dotEnvFile . split ( '\n' ) ) ; } for ( const [ variableName , variableValue ] of Object . entries ( variables ) ) { const newVariableLine = `${ variableName }=${ variableValue }` ; const variableLineIndex = dotEnvLines . findIndex ( line => line . trim ( ) . startsWith ( `${ variableName }=` ) ) ; if ( variableLineIndex >= 0 ) { dotEnvLines [ variableLineIndex ] = newVariableLine ; } else { dotEnvLines . push ( newVariableLine ) ; } } await this . _writeFile ( dotEnvPath , dotEnvLines . join ( '\n' ) ) ; } , setRootPath ( pathname ) { distRootPath = pathname ; srcRootPath = pathname . replace ( /\/dist$/ , '/src' ) ; projectRootPath = path . join ( pathname , '../' ) ; } , get projectRootPath ( ) { return projectRootPath ; } , _readFile : fs . promises . readFile , _writeFile : fs . promises . writeFile , _unlink : fs . promises . unlink , _exists : promisify ( fs . exists ) , _readdir : fs . promises . readdir , _mkdir : fs . promises . mkdir , _rmdir : fs . promises . rmdir , } ;