import * as fs from 'fs' ; import cloneDeep from 'lodash/cloneDeep' ; import path from 'path' ; import { DockerConfig , NetworksConfig , NetworksUserConfig , ProjectPathsConfig , ProjectPathsUserConfig , RedspotConfig , RedspotNetworkConfig , RedspotUserConfig } from '../../../types' ; import { fromEntries } from '../../util/lang' ; import { defaultDefaultNetwork , defaultDockerOptions , defaultInkConfig , defaultLocalhostNetworkParams , defaultMochaOptions , defaultSolangConfig } from './default-config' ; param userConfigPath param userConfig returns export function resolveConfig ( userConfigPath , userConfig ) { userConfig = cloneDeep ( userConfig ) ; return { ... userConfig , defaultNetwork : userConfig . defaultNetwork ?? defaultDefaultNetwork , paths : resolveProjectPaths ( userConfigPath , userConfig . paths ) , networks : resolveNetworksConfig ( userConfig . networks ) , mocha : resolveMochaConfig ( userConfig ) , contract : resolveContractConfig ( userConfig ) , docker : resolveDockerOptions ( userConfig ) } ; } function resolveNetworksConfig ( networksConfig = { } ) { const otherNetworks = fromEntries ( Object . entries ( networksConfig ) . filter ( ( [ _ , config ] ) => config !== undefined ) . map ( ( [ name , config ] ) => [ name , { ... cloneDeep ( defaultLocalhostNetworkParams ) , ... config } ] ) ) ; return { ... otherNetworks } ; } function resolveMochaConfig ( userConfig ) { return { ... cloneDeep ( defaultMochaOptions ) , ... userConfig . mocha } ; } function resolveDockerOptions ( userConfig ) { return { ... cloneDeep ( defaultDockerOptions ) , ... userConfig . docker } ; } function resolveContractConfig ( userConfig ) { const _defaultInkConfig = cloneDeep ( defaultInkConfig ) ; const _defaultSolangConfig = cloneDeep ( defaultSolangConfig ) ; const result = { ... userConfig . contract , ink : { ... _defaultInkConfig , ... userConfig . contract ?. ink } } ; if ( userConfig . contract . solang ) { result . solang = { ... _defaultSolangConfig , ... userConfig . contract . solang } ; } return result ; } /**
 * This function resolves the ProjectPathsConfig object from the user-provided config
 * and its path. The logic of this is not obvious and should well be document.
 * The good thing is that most users will never use this.
 *
 * Explanation:
 *    - paths.configFile is not overridable
 *    - If a path is absolute it is used "as is".
 *    - If the root path is relative, it's resolved from paths.configFile's dir.
 *    - If any other path is relative, it's resolved from paths.root.
 *    - Plugin-defined paths are not resolved, but encouraged to follow the same pattern.
 */ export function resolveProjectPaths ( userConfigPath , userPaths = { } ) { const configFile = fs . realpathSync ( userConfigPath ) ; const configDir = path . dirname ( configFile ) ; const root = resolvePathFrom ( configDir , '' , userPaths . root ) ; return { ... userPaths , root , configFile , cache : resolvePathFrom ( root , '.cache' , userPaths . cache ) , artifacts : resolvePathFrom ( root , 'artifacts' , userPaths . artifacts ) , tests : resolvePathFrom ( root , 'tests' , userPaths . tests ) } ; } function resolvePathFrom ( from , defaultPath , relativeOrAbsolutePath = defaultPath ) { if ( path . isAbsolute ( relativeOrAbsolutePath ) ) { return relativeOrAbsolutePath ; } return path . join ( from , relativeOrAbsolutePath ) ; }