fix rebase issues

This commit is contained in:
Iuri Matias 2019-11-12 12:05:31 -05:00
parent 208ac98909
commit f2716833d8
5 changed files with 10 additions and 1034 deletions

View File

@ -86,6 +86,8 @@ export class Config {
dappPath = dappPath;
debugLog: any;
constructor(options) {
this.env = options.env || 'default';
this.webServerConfig = options.webServerConfig;
@ -93,6 +95,7 @@ export class Config {
this.chainsFile = options.chainsFile;
this.plugins = options.plugins;
this.logger = options.logger;
this.debugLog = options.debugLog;
this.package = options.package;
this.events = options.events;
this.context = options.context || [constants.contexts.any];
@ -174,6 +177,7 @@ export class Config {
logger: this.logger,
interceptLogs,
events: this.events,
debugLog: this.debugLog,
config: this,
context: this.context,
env: this.env,

View File

@ -100,6 +100,10 @@ export class Plugin {
logger: Logger;
logId: any:
debugLog: any:
constructor(options) {
this.name = options.name;
this.isInternal = options.isInternal;
@ -112,6 +116,8 @@ export class Plugin {
this.logger = this._loggerObject; // Might get changed if we do intercept
this.events = options.events;
this.config = options.config;
this.logId = options.logId;
this.debugLog = options.debugLog;
this.plugins = options.plugins;
this.env = options.env;
this.currentContext = options.context;

View File

@ -25,9 +25,6 @@ class EmbarkController {
}
initConfig(env, options) {
let Events = require('../lib/core/events.js');
let Config = require('../lib/core/config.js');
this.events = new Events();
this.logger = new Logger({logLevel: Logger.logLevels.debug, events: this.events, context: this.context});

View File

@ -1,726 +0,0 @@
const fs = require('./fs.js');
const Plugins = require('./plugins.js');
const utils = require('../utils/utils.js');
const path = require('path');
const deepEqual = require('deep-equal');
const web3 = require('web3');
const constants = require('embark-core/constants');
import { __ } from 'embark-i18n';
import {
buildUrlFromConfig,
canonicalHost,
dappPath,
defaultHost,
File,
Types,
recursiveMerge,
AddressUtils,
unitRegex,
getWeiBalanceFromString,
prepareContractsConfig,
getExternalContractUrl
} from 'embark-utils';
const cloneDeep = require('lodash.clonedeep');
const { replaceZeroAddressShorthand } = AddressUtils;
import {getBlockchainDefaults, getContractDefaults} from './configDefaults';
const DEFAULT_CONFIG_PATH = 'config/';
const PACKAGE = require('../../../package.json');
const embark5ChangesUrl = 'https://embark.status.im/docs/migrating_from_3.x.html#Updating-to-v5';
var Config = function(options) {
this.env = options.env || 'default';
this.blockchainConfig = {};
this.contractsConfig = {};
this.pipelineConfig = {};
this.namesystemConfig = {};
this.communicationConfig = {};
this.webServerConfig = options.webServerConfig;
this.chainTracker = {};
this.assetFiles = {};
this.contractsFiles = [];
this.configDir = options.configDir || DEFAULT_CONFIG_PATH;
this.chainsFile = options.chainsFile || './chains.json';
this.plugins = options.plugins;
this.logger = options.logger;
this.debugLog = options.debugLog;
this.package = PACKAGE;
this.events = options.events;
this.embarkConfig = {};
this.context = options.context || [constants.contexts.any];
this.version = options.version;
this.shownNoAccountConfigMsg = false; // flag to ensure "no account config" message is only displayed once to the user
this.corsParts = [];
this.providerUrl = null;
this.registerEvents();
};
Config.prototype.setConfig = function(configName, newConfig, cb) {
this[configName] = newConfig;
cb();
};
Config.prototype.registerEvents = function() {
this.events.setCommandHandler("config:cors:add", (url) => {
this.corsParts.push(url);
this._updateBlockchainCors();
});
this.events.setCommandHandler("config:contractsConfig", (cb) => {
cb(null, this.contractsConfig);
});
this.events.setCommandHandler("config:storageConfig", (cb) => {
cb(null, this.storageConfig);
});
this.events.setCommandHandler("config:contractsConfig:set", this.setConfig.bind(this, 'contractsConfig'));
this.events.setCommandHandler("config:blockchainConfig:set", this.setConfig.bind(this, 'blockchainConfig'));
this.events.setCommandHandler("config:storageConfig:set", this.setConfig.bind(this, 'storageConfig'));
this.events.setCommandHandler("config:namesystemConfig:set", this.setConfig.bind(this, 'namesystemConfig'));
this.events.setCommandHandler("config:communicationConfig:set", this.setConfig.bind(this, 'communicationConfig'));
this.events.setCommandHandler("config:contractsFiles", (cb) => {
cb(null, this.contractsFiles);
});
// TODO: refactor this so reading the file can be done with a normal resolver or something that takes advantage of the plugin api
this.events.setCommandHandler("config:contractsFiles:add", (filename, resolver) => {
resolver = resolver || function(callback) {
callback(fs.readFileSync(filename).toString());
};
this.contractsFiles.push(new File({path: filename, originalPath: filename, type: Types.custom, resolver}));
});
this.events.setCommandHandler("config:contractsFiles:reset", (cb) => {
this.contractsFiles.forEach((file) => {
if(file.path.includes(".embark")) {
fs.removeSync(file.path);
}
this.contractsFiles = this.contractsFiles.filter((contractFile) => contractFile.path !== file.path);
});
cb();
});
this.events.on('file-remove', (fileType, removedPath) => {
if(fileType !== 'contract') return;
const normalizedPath = path.normalize(removedPath);
this.contractsFiles = this.contractsFiles.filter(file => path.normalize(file.path) !== normalizedPath);
});
};
// TODO remove this at some point as it is now in plugin
Config.prototype.dappPath = dappPath;
Config.prototype.loadConfigFiles = function(options) {
var interceptLogs = options.interceptLogs;
if (options.interceptLogs === undefined) {
interceptLogs = true;
}
if (!fs.existsSync(options.embarkConfig)){
this.logger.error(__('Cannot find file %s Please ensure you are running this command inside the Dapp folder', options.embarkConfig));
process.exit(1);
}
this.embarkConfig = fs.readJSONSync(options.embarkConfig);
this.embarkConfig.plugins = this.embarkConfig.plugins || {};
this.plugins = new Plugins({
plugins: this.embarkConfig.plugins,
logger: this.logger,
debugLog: this.debugLog,
interceptLogs: interceptLogs,
events: this.events,
config: this,
context: this.context,
env: this.env,
version: this.version
});
this.plugins.loadPlugins();
this.loadEmbarkConfigFile();
this.loadBlockchainConfigFile();
this.loadStorageConfigFile();
this.loadContractFiles();
this.loadCommunicationConfigFile();
this.loadNameSystemConfigFile();
this.loadPipelineConfigFile();
this.loadAssetFiles();
this.loadContractsConfigFile();
this.loadExternalContractsFiles();
this.loadWebServerConfigFile();
this.loadPluginContractFiles();
this._updateBlockchainCors();
};
Config.prototype.reloadConfig = function() {
this.loadEmbarkConfigFile();
this.loadBlockchainConfigFile();
this.loadStorageConfigFile();
this.loadContractFiles();
this.loadCommunicationConfigFile();
this.loadNameSystemConfigFile();
this.loadPipelineConfigFile();
this.loadAssetFiles();
this.loadContractsConfigFile();
this.loadExternalContractsFiles();
this._updateBlockchainCors();
};
Config.prototype.loadContractFiles = function() {
const loadedContractFiles = this.loadFiles(this.embarkConfig.contracts);
// `this.contractsFiles` could've been mutated at runtime using
// either `config:contractsFiles:add` event or through calls to
// `loadExternalContractsFiles()`, so we have to make sure we preserve
// those added files before we reset `this.contractsFiles`.
//
// We do that by determining the difference between `loadedContractFiles` and the ones
// already in memory in `this.contractsFiles`.
const addedContractFiles = this.contractsFiles.filter(existingFile => !loadedContractFiles.some(file => file.originalPath === existingFile.originalPath));
this.contractsFiles = loadedContractFiles.concat(addedContractFiles);
};
Config.prototype._updateBlockchainCors = function(){
let blockchainConfig = this.blockchainConfig;
let storageConfig = this.storageConfig;
let webServerConfig = this.webServerConfig;
let corsParts = cloneDeep(this.corsParts);
if (blockchainConfig.isDev) {
corsParts.push('*');
}
if(webServerConfig && webServerConfig.host) {
corsParts.push(buildUrlFromConfig(webServerConfig));
}
if(storageConfig && storageConfig.enabled) {
// if getUrl is specified in the config, that needs to be included in cors
// instead of the concatenated protocol://host:port
if(storageConfig.upload.getUrl) {
// remove /ipfs or /bzz: from getUrl if it's there
let getUrlParts = storageConfig.upload.getUrl.split('/');
getUrlParts = getUrlParts.slice(0, 3);
let host = canonicalHost(getUrlParts[2].split(':')[0]);
let port = getUrlParts[2].split(':')[1];
getUrlParts[2] = port ? [host, port].join(':') : host;
corsParts.push(getUrlParts.join('/'));
}
// use our modified getUrl or in case it wasn't specified, use a built url
else{
corsParts.push(buildUrlFromConfig(storageConfig.upload));
}
}
// Add cors for the proxy and whisper
corsParts.push(constants.embarkResourceOrigin);
corsParts = Array.from(new Set(corsParts));
this.corsParts = corsParts;
let cors = corsParts.join(',');
if (blockchainConfig.rpcCorsDomain === 'auto') {
blockchainConfig.rpcCorsDomain = cors;
} else if (typeof blockchainConfig.rpcCorsDomain === 'object') {
let tempCors = blockchainConfig.rpcCorsDomain.auto ? corsParts : [];
tempCors = tempCors.concat(blockchainConfig.rpcCorsDomain.additionalCors || []);
blockchainConfig.rpcCorsDomain = tempCors.join(',');
}
if (blockchainConfig.wsOrigins === 'auto') {
blockchainConfig.wsOrigins = cors;
} else if (typeof blockchainConfig.wsOrigins === 'object') {
let tempCors = blockchainConfig.wsOrigins.auto ? corsParts : [];
tempCors = tempCors.concat(blockchainConfig.wsOrigins.additionalCors || []);
blockchainConfig.wsOrigins = tempCors.join(',');
}
};
Config.prototype._loadConfigFile = function (configFilePath, defaultConfig, enabledByDefault) {
if (!configFilePath) {
const configToReturn = defaultConfig['default'] || {};
configToReturn.enabled = enabledByDefault || false;
return configToReturn;
}
configFilePath = configFilePath.replace('.json','').replace('.js', '');
let config;
if (fs.existsSync(configFilePath + '.js')) {
delete require.cache[configFilePath + '.js'];
config = require(configFilePath + '.js');
} else if (fs.existsSync(configFilePath + '.json')) {
config = fs.readJSONSync(configFilePath + '.json');
} else {
this.logger.warn(__("no config file found at %s using default config", configFilePath));
return defaultConfig['default'] || {};
}
return config;
};
Config.prototype._doMergeConfig = function(config, defaultConfig, env) {
let configObject = recursiveMerge(defaultConfig, config);
if (env) {
if (env === 'test' && !configObject[env]) {
// Disabled all configs in tests as they are opt in
return Object.assign({}, defaultConfig.default, {enabled: false});
}
return recursiveMerge(configObject.default || {}, configObject[env]);
} else if (env !== false) {
this.logger.info(__("No environment called %s found. Using defaults.", env));
}
return configObject;
};
Config.prototype._loadAndMergeConfig = function(configFilePath, defaultConfig, env, enabledByDefault) {
const config = this._loadConfigFile(configFilePath, defaultConfig, enabledByDefault);
return this._doMergeConfig(config, defaultConfig, env, enabledByDefault);
};
Config.prototype._getFileOrObject = function(object, filePath, property) {
if (typeof object === 'object') {
return object[property] ? dappPath(object[property]) : object[property];
}
return dappPath(object, filePath);
};
/*eslint complexity: ["error", 30]*/
Config.prototype.loadBlockchainConfigFile = function() {
const blockchainDefaults = getBlockchainDefaults(this.env);
const configFilePath = this._getFileOrObject(this.configDir, 'blockchain', 'blockchain');
const userConfig = this._loadConfigFile(configFilePath, blockchainDefaults, true);
const envConfig = userConfig[this.env];
if (envConfig) {
if (envConfig.ethereumClientName || envConfig.hasOwnProperty('isDev') || envConfig.hasOwnProperty('mineWhenNeeded')) {
this.logger.error(__('The blockchain config has changed quite a bit in Embark 5\nPlease visit %s to know what has to be changed', embark5ChangesUrl.underline));
process.exit(1);
}
if (envConfig.clientConfig) {
Object.assign(envConfig, envConfig.clientConfig);
delete envConfig.clientConfig;
}
switch (envConfig.miningMode) {
case 'dev': envConfig.isDev = true; break;
case 'auto': envConfig.isDev = false; envConfig.mineWhenNeeded = true; break;
case 'always': envConfig.isDev = false; envConfig.mineWhenNeeded = false; envConfig.mine = true; break;
case 'off': envConfig.isDev = false; envConfig.mineWhenNeeded = false; envConfig.mine = false; break;
default: envConfig.isDev = false;
}
if (envConfig.cors) {
const autoIndex = envConfig.cors.indexOf('auto');
envConfig.rpcCorsDomain = {};
envConfig.wsOrigins = {};
if (autoIndex > -1) {
envConfig.rpcCorsDomain.auto = true;
envConfig.wsOrigins.auto = true;
envConfig.cors.splice(autoIndex, 1);
} else {
envConfig.rpcCorsDomain.auto = false;
envConfig.wsOrigins.auto = false;
}
envConfig.rpcCorsDomain.additionalCors = envConfig.cors;
envConfig.wsOrigins.additionalCors = envConfig.cors;
delete envConfig.cors;
}
userConfig[this.env] = envConfig;
}
this.blockchainConfig = this._doMergeConfig(userConfig, blockchainDefaults, this.env);
if (!configFilePath) {
this.blockchainConfig.default = true;
}
if (this.blockchainConfig.targetGasLimit && this.blockchainConfig.targetGasLimit.toString().match(unitRegex)) {
this.blockchainConfig.targetGasLimit = getWeiBalanceFromString(this.blockchainConfig.targetGasLimit, web3);
}
if (this.blockchainConfig.gasPrice && this.blockchainConfig.gasPrice.toString().match(unitRegex)) {
this.blockchainConfig.gasPrice = getWeiBalanceFromString(this.blockchainConfig.gasPrice, web3);
}
if (this.blockchainConfig.accounts) {
this.blockchainConfig.accounts.forEach(acc => {
if (acc.balance && acc.balance.toString().match(unitRegex)) {
acc.balance = getWeiBalanceFromString(acc.balance, web3);
}
});
}
if (!this.blockchainConfig.endpoint) {
const urlConfig = (this.blockchainConfig.wsHost) ? {
host: this.blockchainConfig.wsHost,
port: this.blockchainConfig.wsPort,
type: 'ws'
} : {
host: this.blockchainConfig.rpcHost,
port: this.blockchainConfig.rpcPort,
type: 'rpc'
};
this.blockchainConfig.endpoint = buildUrlFromConfig(urlConfig);
this.blockchainConfig.isAutoEndpoint = true;
}
if (
!this.shownNoAccountConfigMsg &&
(/rinkeby|testnet|livenet/).test(this.blockchainConfig.networkType) &&
!(this.blockchainConfig.accounts && this.blockchainConfig.accounts.find(acc => acc.password)) &&
!this.blockchainConfig.isDev &&
this.env !== 'development' && this.env !== 'test') {
this.logger.warn((
'\n=== ' + __('Cannot unlock account - account config missing').bold + ' ===\n' +
__('Geth is configured to sync to a testnet/livenet and needs to unlock an account ' +
'to allow your dApp to interact with geth, however, the address and password must ' +
'be specified in your blockchain config. Please update your blockchain config with ' +
'a valid address and password: \n') +
` - config/blockchain.js > ${this.env} > account\n\n`.italic +
__('Please also make sure the keystore file for the account is located at: ') +
'\n - Mac: ' + `~/Library/Ethereum/${this.env}/keystore`.italic +
'\n - Linux: ' + `~/.ethereum/${this.env}/keystore`.italic +
'\n - Windows: ' + `%APPDATA%\\Ethereum\\${this.env}\\keystore`.italic) +
__('\n\nAlternatively, you could change ' +
`config/blockchain.js > ${this.env} > networkType`.italic +
__(' to ') +
'"custom"\n'.italic).yellow
);
this.shownNoAccountConfigMsg = true;
}
const accountDocsMessage = __('For more info, check the docs: %s', 'https://embark.status.im/docs/blockchain_accounts_configuration.html'.underline);
if (this.blockchainConfig.account) {
this.logger.error(__('The `account` config for the blockchain was removed. Please use `accounts` instead.'));
this.logger.error(accountDocsMessage);
process.exit(1);
}
if (this.blockchainConfig.simulatorMnemonic) {
this.logger.error(__('The `simulatorMnemonic` config for the blockchain was removed. Please use `accounts` instead.'));
this.logger.error(accountDocsMessage);
process.exit(1);
}
this.events.emit('config:load:blockchain', this.blockchainConfig);
};
Config.prototype.loadContractsConfigFile = function() {
let configObject = getContractDefaults(this.embarkConfig.versions);
const contractsConfigs = this.plugins.getPluginsProperty('contractsConfig', 'contractsConfigs');
contractsConfigs.forEach(function(pluginConfig) {
configObject = recursiveMerge(configObject, pluginConfig);
});
let configFilePath = this._getFileOrObject(this.configDir, 'contracts', 'contracts');
let newContractsConfig = this._loadAndMergeConfig(configFilePath, configObject, this.env);
if (newContractsConfig.contracts) {
this.logger.error(__('`contracts` has been renamed `deploy` in contracts config\nFor more information: %s', embark5ChangesUrl.underline));
process.exit(1);
}
if (newContractsConfig.deployment) {
this.logger.error(__('`deployment` has been removed from contracts config and is now part of blockchain config\nFor more information: %s', embark5ChangesUrl.underline));
process.exit(1);
}
if (newContractsConfig.gas.match(unitRegex)) {
newContractsConfig.gas = getWeiBalanceFromString(newContractsConfig.gas, web3);
}
newContractsConfig = prepareContractsConfig(newContractsConfig);
const afterDeploy = newContractsConfig.afterDeploy;
if (Array.isArray(afterDeploy)) {
newContractsConfig.afterDeploy = afterDeploy.map(replaceZeroAddressShorthand);
}
if (!deepEqual(newContractsConfig, this.contractsConfig)) {
this.contractsConfig = newContractsConfig;
}
this.events.emit('config:load:contracts', this.contractsConfig);
};
Config.prototype.loadExternalContractsFiles = function() {
let contracts = this.contractsConfig.contracts;
let storageConfig = this.storageConfig;
if (storageConfig && storageConfig.upload && storageConfig.upload.getUrl) {
this.providerUrl = storageConfig.upload.getUrl;
}
for (let contractName in contracts) {
let contract = contracts[contractName];
if (!contract.file) {
continue;
}
let externalContractFile = null;
if (contract.file.startsWith('http') || contract.file.startsWith('git') || contract.file.startsWith('ipfs') || contract.file.startsWith('bzz')) {
const fileObj = getExternalContractUrl(contract.file, this.providerUrl);
if (!fileObj) {
return this.logger.error(__("HTTP contract file not found") + ": " + contract.file);
}
externalContractFile = new File({ path: fileObj.filePath, originalPath: fileObj.filePath, type: Types.http, basedir: '', externalUrl: fileObj.url, storageConfig });
} else if (fs.existsSync(contract.file)) {
externalContractFile = new File({ path: contract.file, originalPath: contract.file, type: Types.dappFile, basedir: '', storageConfig });
} else if (fs.existsSync(path.join('./node_modules/', contract.file))) {
const completePath = path.join('./node_modules/', contract.file);
externalContractFile = new File({ path: completePath, originalPath: completePath, type: Types.dappFile, basedir: '', storageConfig });
}
if (externalContractFile) {
const index = this.contractsFiles.findIndex(contractFile => contractFile.originalPath === externalContractFile.originalPath);
// It's important that we only add `externalContractFile` if it doesn't exist already
// within `contractsFiles`, otherwise we keep adding duplicates in subsequent
// compilation routines creating a memory leak.
if (index > -1) {
this.contractsFiles[index] = externalContractFile;
} else {
this.contractsFiles.push(externalContractFile);
}
} else {
this.logger.error(__("contract file not found") + ": " + contract.file);
}
}
};
Config.prototype.loadStorageConfigFile = function() {
var versions = recursiveMerge({"ipfs-api": "17.2.4"}, this.embarkConfig.versions || {});
var configObject = {
"default": {
"versions": versions,
"enabled": true,
"available_providers": ["ipfs", "swarm"],
"ipfs_bin": "ipfs",
"upload": {
"provider": "ipfs",
"protocol": "http",
"host" : defaultHost,
"port": 5001,
"getUrl": "http://localhost:8080/ipfs/"
},
"dappConnection": [{"provider": "ipfs", "host": "localhost", "port": 5001, "getUrl": "http://localhost:8080/ipfs/"}]
}
};
let configFilePath = this._getFileOrObject(this.configDir, 'storage', 'storage');
this.storageConfig = this._loadAndMergeConfig(configFilePath, configObject, this.env);
this.events.emit('config:load:storage', this.storageConfig);
};
Config.prototype.loadNameSystemConfigFile = function() {
// todo: spec out names for registration in the file itself for a dev chain
var configObject = {
"default": {
"enabled": false
}
};
let configFilePath = this._getFileOrObject(this.configDir, 'namesystem', 'namesystem');
this.namesystemConfig = this._loadAndMergeConfig(configFilePath, configObject, this.env);
};
Config.prototype.loadCommunicationConfigFile = function() {
var configObject = {
"default": {
"enabled": true,
"provider": "whisper",
"available_providers": ["whisper"],
"connection": {
"host": defaultHost,
"port": 8557,
"type": "ws"
}
}
};
let configFilePath = this._getFileOrObject(this.configDir, 'communication', 'communication');
this.communicationConfig = this._loadAndMergeConfig(configFilePath, configObject, this.env);
this.events.emit('config:load:communication', this.communicationConfig);
};
Config.prototype.loadWebServerConfigFile = function() {
var configObject = {
"enabled": true,
"host": defaultHost,
"openBrowser": true,
"port": 8000,
"enableCatchAll": true,
"protocol": "http"
};
let configFilePath = this._getFileOrObject(this.configDir, 'webserver', 'webserver');
let webServerConfig = this._loadAndMergeConfig(configFilePath, configObject, false);
if (webServerConfig.https){
try {
webServerConfig.certOptions = {
key: fs.readFileSync(webServerConfig.key),
cert: fs.readFileSync(webServerConfig.cert)
};
webServerConfig.protocol = 'https';
} catch (e) {
this.logger.error(e.message);
this.logger.warn('Invalid path for key/cert in config/webserver.js. Using http instead.');
webServerConfig.certOptions = {};
webServerConfig.protocol = 'http';
}
}
if (configFilePath === false) {
this.webServerConfig = {enabled: false};
return;
}
if (this.webServerConfig) {
// cli flags to `embark run` should override configFile and defaults (configObject)
this.webServerConfig = recursiveMerge(webServerConfig, this.webServerConfig);
} else {
this.webServerConfig = webServerConfig;
}
if (!this.pipelineConfig.enabled) {
this.webServerConfig.enabled = false;
}
this.events.emit('config:load:webserver', this.webServerConfig);
};
Config.prototype.loadEmbarkConfigFile = function() {
var configObject = {
options: {
solc: {
"optimize": true,
"optimize-runs": 200
}
},
"generationDir": "embarkArtifacts"
};
this.embarkConfig = recursiveMerge(configObject, this.embarkConfig);
const contracts = this.embarkConfig.contracts;
// determine contract 'root' directories
this.contractDirectories = contracts.map((dir) => {
return dir.split("**")[0];
}).map((dir) => {
return dir.split("*.")[0];
});
this.contractDirectories.push(constants.httpContractsDirectory);
this.buildDir = this.embarkConfig.buildDir;
this.configDir = this.embarkConfig.config;
};
Config.prototype.loadPipelineConfigFile = function() {
const defaultPipelineConfig = {
typescript: false,
enabled: true
};
let pipelineConfigPath = this._getFileOrObject(this.configDir, 'pipeline', 'pipeline');
// Embark applications in "simple" mode that aren't aware of `pipeline.js` configuration capabilities
// won't have a pipeline config path so we need to perform this safety check here, otherwise the
// next expression is going to throw.
if (pipelineConfigPath !== undefined) {
// At this point, `pipelineConfigPath` could be either `config/pipeline` or a filepath including its extension.
// We need to make sure that we always have an extension.
pipelineConfigPath = `${dappPath(pipelineConfigPath)}${path.extname(pipelineConfigPath) === '.js' ? '' : '.js'}`;
}
let pipelineConfig = defaultPipelineConfig;
if (pipelineConfigPath && fs.existsSync(pipelineConfigPath)) {
delete require.cache[pipelineConfigPath];
pipelineConfig = recursiveMerge(
recursiveMerge(true, pipelineConfig),
require(pipelineConfigPath)
);
}
this.pipelineConfig = pipelineConfig;
this.events.emit('config:load:pipeline', this.pipelineConfig);
};
Config.prototype.loadAssetFiles = function () {
if(!this.embarkConfig.app) return;
Object.keys(this.embarkConfig.app).forEach(targetFile => {
this.assetFiles[targetFile] = this.loadFiles(this.embarkConfig.app[targetFile]);
});
};
function findMatchingExpression(filename, filesExpressions) {
for (let fileExpression of filesExpressions) {
var matchingFiles = utils.filesMatchingPattern(fileExpression);
for (let matchFile of matchingFiles) {
if (matchFile === filename) {
return path.dirname(fileExpression).replace(/\*/g, '');
}
}
}
return path.dirname(filename);
}
Config.prototype.loadFiles = function(files) {
var self = this;
var originalFiles = utils.filesMatchingPattern(files);
var readFiles = [];
let storageConfig = self.storageConfig;
originalFiles.filter(function(file) {
return (file[0] === '$' || file.indexOf('.') >= 0);
}).filter(function(file) {
let basedir = findMatchingExpression(file, files);
readFiles.push(new File({path: file, originalPath: file, type: Types.dappFile, basedir: basedir, storageConfig: storageConfig}));
});
var filesFromPlugins = [];
var filePlugins = self.plugins.getPluginsFor('pipelineFiles');
filePlugins.forEach(function(plugin) {
try {
var fileObjects = plugin.runFilePipeline();
for (var i=0; i < fileObjects.length; i++) {
var fileObject = fileObjects[i];
filesFromPlugins.push(fileObject);
}
}
catch(err) {
self.logger.error(err.message);
}
});
filesFromPlugins.filter(function(file) {
if ((file.intendedPath && utils.fileMatchesPattern(files, file.intendedPath)) || utils.fileMatchesPattern(files, file.file)) {
readFiles.push(file);
}
});
return readFiles;
};
// NOTE: this doesn't work for internal modules
Config.prototype.loadPluginContractFiles = function() {
var self = this;
let storageConfig = self.storageConfig;
var contractsPlugins = this.plugins.getPluginsFor('contractFiles');
contractsPlugins.forEach(function(plugin) {
plugin.contractsFiles.forEach(function(file) {
var filename = file.replace('./','');
self.contractsFiles.push(new File({ path: filename, originalPath: path.join(plugin.pluginPath, filename), pluginPath: plugin.pluginPath, type: Types.custom, storageConfig,
resolver: function(callback) {
callback(plugin.loadPluginFile(file));
}
}));
});
});
};
module.exports = Config;

View File

@ -1,305 +0,0 @@
const utils = require('../utils/utils.js');
import { __ } from 'embark-i18n';
import { dappPath, embarkPath, isEs6Module, joinPath } from 'embark-utils';
const constants = require('embark-core/constants');
const fs = require('fs-extra');
const deepEqual = require('deep-equal');
// TODO: pass other params like blockchainConfig, contract files, etc..
var Plugin = function(options) {
this.name = options.name;
this.isInternal = options.isInternal;
this.pluginModule = options.pluginModule;
this.pluginPath = options.pluginPath;
this.pluginConfig = options.pluginConfig;
this.shouldInterceptLogs = options.interceptLogs;
this.clientWeb3Providers = [];
this.beforeDeploy = [];
this.contractsGenerators = [];
this.generateCustomContractCode = null;
this.testContractFactory = null;
this.pipeline = [];
this.pipelineFiles = [];
this.console = [];
this.contractsConfigs = [];
this.contractsFiles = [];
this.compilers = [];
this.serviceChecks = [];
this.dappGenerators = [];
this.pluginTypes = [];
this.uploadCmds = [];
this.apiCalls = [];
this.imports = [];
this.embarkjs_code = [];
this.generated_code = [];
this.embarkjs_init_code = {};
this.embarkjs_init_console_code = {};
this.fs = fs;
this.afterContractsDeployActions = [];
this.onDeployActions = [];
this.eventActions = {};
this._loggerObject = options.logger;
this.logger = this._loggerObject; // Might get changed if we do intercept
this.events = options.events;
this.config = options.config;
this.plugins = options.plugins;
this.env = options.env;
this.loaded = false;
this.currentContext = options.context;
this.acceptedContext = options.pluginConfig.context || [constants.contexts.any];
this.version = options.version;
this.constants = constants;
this.logId = options.logId;
this.debugLog = options.debugLog;
if (!Array.isArray(this.currentContext)) {
this.currentContext = [this.currentContext];
}
if (!Array.isArray(this.acceptedContext)) {
this.acceptedContext = [this.acceptedContext];
}
};
Plugin.prototype.dappPath = dappPath;
Plugin.prototype.embarkPath = embarkPath;
Plugin.prototype._log = function(type) {
this._loggerObject[type](this.name + ':', ...[].slice.call(arguments, 1));
};
Plugin.prototype.setUpLogger = function () {
this.logger = {
log: this._log.bind(this, 'log'),
warn: this._log.bind(this, 'warn'),
error: this._log.bind(this, 'error'),
info: this._log.bind(this, 'info'),
debug: this._log.bind(this, 'debug'),
trace: this._log.bind(this, 'trace'),
dir: this._log.bind(this, 'dir')
};
};
Plugin.prototype.isContextValid = function() {
if (this.currentContext.includes(constants.contexts.any) || this.acceptedContext.includes(constants.contexts.any)) {
return true;
}
return this.acceptedContext.some(context => {
return this.currentContext.includes(context);
});
};
Plugin.prototype.hasContext = function(context) {
return this.currentContext.includes(context);
};
Plugin.prototype.loadPlugin = function() {
if (!this.isContextValid()) {
this.logger.warn(__('Plugin {{name}} can only be loaded in the context of "{{contexts}}"', {name: this.name, contexts: this.acceptedContext.join(', ')}));
return false;
}
this.loaded = true;
if (this.shouldInterceptLogs) {
this.setUpLogger();
}
if (isEs6Module(this.pluginModule)) {
if (this.pluginModule.default) {
this.pluginModule = this.pluginModule.default;
}
return new this.pluginModule(this);
}
this.pluginModule.call(this, this);
};
Plugin.prototype.loadInternalPlugin = function() {
if (isEs6Module(this.pluginModule)) {
if (this.pluginModule.default) {
this.pluginModule = this.pluginModule.default;
}
}
return new this.pluginModule(this, this.pluginConfig); /*eslint no-new: "off"*/
};
Plugin.prototype.loadPluginFile = function(filename) {
return fs.readFileSync(this.pathToFile(filename)).toString();
};
Plugin.prototype.pathToFile = function(filename) {
if (!this.pluginPath) {
throw new Error('pluginPath not defined for plugin: ' + this.name);
}
return joinPath(this.pluginPath, filename);
};
// TODO: add deploy provider
Plugin.prototype.registerClientWeb3Provider = function(cb) {
this.clientWeb3Providers.push(cb);
this.addPluginType('clientWeb3Provider');
};
Plugin.prototype.registerContractsGeneration = function(cb) {
this.contractsGenerators.push(cb);
this.addPluginType('contractGeneration');
};
Plugin.prototype.registerCustomContractGenerator = function (cb) {
this.generateCustomContractCode = cb;
this.addPluginType('customContractGeneration');
};
Plugin.prototype.registerTestContractFactory = function(cb) {
this.testContractFactory = cb;
this.addPluginType('testContractFactory');
};
Plugin.prototype.registerPipeline = function(matcthingFiles, cb) {
// TODO: generate error for more than one pipeline per plugin
this.pipeline.push({matcthingFiles: matcthingFiles, cb: cb});
this.addPluginType('pipeline');
};
Plugin.prototype.registerDappGenerator = function(framework, cb){
this.dappGenerators.push({framework: framework, cb: cb});
this.pluginTypes.push('dappGenerator');
};
Plugin.prototype.registerCustomType = function(type){
this.pluginTypes.push(type);
};
Plugin.prototype.addFileToPipeline = function(file, intendedPath, options) {
this.pipelineFiles.push({file: file, intendedPath: intendedPath, options: options});
this.addPluginType('pipelineFiles');
};
Plugin.prototype.addContractFile = function(file) {
if (this.isInternal) {
throw new Error("this API cannot work for internal modules. please use an event command instead: config:contractsFiles:add");
}
this.contractsFiles.push(file);
this.addPluginType('contractFiles');
};
Plugin.prototype.registerConsoleCommand = function(optionsOrCb) {
if (typeof optionsOrCb === 'function') {
this.logger.warn(__('Registering console commands with function syntax is deprecated and will likely be removed in future versions of Embark'));
this.logger.info(__('You can find the new API documentation here: %s', 'https://embark.status.im/docs/plugin_reference.html#registerConsoleCommand-options'.underline));
}
this.console.push(optionsOrCb);
this.addPluginType('console');
};
// TODO: this only works for services done on startup
Plugin.prototype.registerServiceCheck = function(checkName, checkFn, time) {
this.serviceChecks.push({checkName: checkName, checkFn: checkFn, time: time});
this.addPluginType('serviceChecks');
};
Plugin.prototype.has = function(pluginType) {
return this.pluginTypes.indexOf(pluginType) >= 0;
};
Plugin.prototype.addPluginType = function(pluginType) {
this.pluginTypes.push(pluginType);
this.pluginTypes = Array.from(new Set(this.pluginTypes));
};
Plugin.prototype.generateProvider = function(args) {
return this.clientWeb3Providers.map(function(cb) {
return cb.call(this, args);
}).join("\n");
};
Plugin.prototype.generateContracts = function(args) {
return this.contractsGenerators.map(function(cb) {
return cb.call(this, args);
}).join("\n");
};
Plugin.prototype.registerContractConfiguration = function(config) {
this.contractsConfigs.push(config);
this.addPluginType('contractsConfig');
};
Plugin.prototype.registerCompiler = function(extension, cb) {
this.compilers.push({extension: extension, cb: cb});
this.addPluginType('compilers');
};
Plugin.prototype.registerUploadCommand = function(cmd, cb) {
this.uploadCmds.push({cmd: cmd, cb: cb});
this.addPluginType('uploadCmds');
};
Plugin.prototype.addCodeToEmbarkJS = function(code) {
this.addPluginType('embarkjsCode');
// TODO: what is this/why
if (!this.embarkjs_code.some((existingCode) => deepEqual(existingCode, code))) {
this.embarkjs_code.push(code);
}
};
Plugin.prototype.addGeneratedCode = function(codeCb) {
this.addPluginType('generatedCode');
this.generated_code.push(codeCb);
};
Plugin.prototype.addProviderInit = function(providerType, code, initCondition) {
this.embarkjs_init_code[providerType] = this.embarkjs_init_code[providerType] || [];
this.embarkjs_init_code[providerType].push([code, initCondition]);
this.addPluginType('initCode');
};
Plugin.prototype.addConsoleProviderInit = function(providerType, code, initCondition) {
this.embarkjs_init_console_code[providerType] = this.embarkjs_init_console_code[providerType] || [];
this.addPluginType('initConsoleCode');
const toAdd = [code, initCondition];
if (!this.embarkjs_init_console_code[providerType].some((initConsoleCode) => deepEqual(initConsoleCode, toAdd))) {
this.embarkjs_init_console_code[providerType].push(toAdd);
}
};
Plugin.prototype.registerImportFile = function(importName, importLocation) {
this.imports.push([importName, importLocation]);
this.addPluginType('imports');
};
Plugin.prototype.registerActionForEvent = function(eventName, cb) {
if (!this.eventActions[eventName]) {
this.eventActions[eventName] = [];
}
this.eventActions[eventName].push(cb);
this.addPluginType('eventActions');
};
Plugin.prototype.registerAPICall = function(method, endpoint, cb) {
this.apiCalls.push({method, endpoint, cb});
this.addPluginType('apiCalls');
this.events.emit('plugins:register:api', {method, endpoint, cb});
};
Plugin.prototype.runFilePipeline = function() {
var self = this;
return this.pipelineFiles.map(function(file) {
var obj = {};
obj.filename = file.file.replace('./','');
obj.content = self.loadPluginFile(file.file).toString();
obj.intendedPath = file.intendedPath;
obj.options = file.options;
obj.path = self.pathToFile(obj.filename);
return obj;
});
};
Plugin.prototype.runPipeline = function(args) {
// TODO: should iterate the pipelines
var pipeline = this.pipeline[0];
var shouldRunPipeline = utils.fileMatchesPattern(pipeline.matcthingFiles, args.targetFile);
if (shouldRunPipeline) {
return pipeline.cb.call(this, args);
}
return args.source;
};
module.exports = Plugin;