diff --git a/lib/compiler.js b/lib/compiler.js index 7a7cb0c4e..3fc39dea3 100644 --- a/lib/compiler.js +++ b/lib/compiler.js @@ -9,6 +9,7 @@ var Compiler = function() { Compiler.prototype.compile_solidity = function(contractFiles) { var input = {}; + // TODO: need to match only the .sol files for (var i = 0; i < contractFiles.length; i++){ // TODO: this depends on the config var filename = contractFiles[i].filename.replace('app/contracts/',''); diff --git a/lib/config.js b/lib/config.js index bc06abfb3..7e3e2b682 100644 --- a/lib/config.js +++ b/lib/config.js @@ -2,6 +2,7 @@ var fs = require('fs'); var grunt = require('grunt'); var merge = require('merge'); var path = require('path'); +var Plugins = require('./plugins.js'); // TODO: add wrapper for fs so it can also work in the browser // can work with both read and save @@ -15,6 +16,7 @@ var Config = function(options) { this.contractsFiles = []; this.configDir = options.configDir || 'config/'; this.chainsFile = options.chainsFile || './chains.json'; + this.logger = options.logger; }; Config.prototype.loadConfigFiles = function(options) { @@ -22,8 +24,13 @@ Config.prototype.loadConfigFiles = function(options) { this.loadPipelineConfigFile(); this.loadBlockchainConfigFile(); + + this.plugins = new Plugins({plugins: this.embarkConfig.plugins, logger: this.logger}); + this.plugins.loadPlugins(); + this.loadContractsConfigFile(); this.loadChainTrackerFile(); + this.loadPluginContractFiles(); }; Config.prototype.reloadConfig = function() { @@ -39,11 +46,25 @@ Config.prototype.loadBlockchainConfigFile = function() { }; Config.prototype.loadContractsConfigFile = function() { + + var configObject = {}; + + var configPlugins = this.plugins.getPluginsFor('contractsConfig'); + if (configPlugins.length > 0) { + configPlugins.forEach(function(plugin) { + plugin.contractsConfigs.forEach(function(pluginConfig) { + configObject = merge.recursive(configObject, pluginConfig); + }); + }); + } + var contractsConfig = JSON.parse(fs.readFileSync(this.configDir + "contracts.json")); - var defaultContractsConfig = contractsConfig['default']; - var envContractsConfig = contractsConfig[this.env]; + configObject = merge.recursive(configObject, contractsConfig); + var defaultContractsConfig = configObject['default']; + var envContractsConfig = configObject[this.env]; var mergedConfig = merge.recursive(defaultContractsConfig, envContractsConfig); + console.log(JSON.stringify(mergedConfig)); this.contractsConfig = mergedConfig; }; @@ -82,18 +103,33 @@ Config.prototype.loadFiles = function(files) { return file.indexOf('.') >= 0; }).filter(function(file) { if (file === 'embark.js') { - readFiles.push({filename: 'web3.js', content: fs.readFileSync(path.join(__dirname, "/../js/web3.js")).toString()}); - readFiles.push({filename: 'ipfs.js', content: fs.readFileSync(path.join(__dirname, "/../js/ipfs.js")).toString()}); + readFiles.push({filename: 'web3.js', content: fs.readFileSync(path.join(__dirname, "/../js/web3.js")).toString(), path: path.join(__dirname, "/../js/web3.js")}); + readFiles.push({filename: 'ipfs.js', content: fs.readFileSync(path.join(__dirname, "/../js/ipfs.js")).toString(), path: path.join(__dirname, "/../js/ipfs.js")}); // TODO: remove duplicated files if funcitonality is the same for storage and orbit - readFiles.push({filename: 'ipfs-api.js', content: fs.readFileSync(path.join(__dirname, "/../js/ipfs-api.min.js")).toString()}); - readFiles.push({filename: 'orbit.js', content: fs.readFileSync(path.join(__dirname, "/../js/orbit.min.js")).toString()}); - readFiles.push({filename: 'embark.js', content: fs.readFileSync(path.join(__dirname, "/../js/build/embark.bundle.js")).toString()}); + readFiles.push({filename: 'ipfs-api.js', content: fs.readFileSync(path.join(__dirname, "/../js/ipfs-api.min.js")).toString(), path: path.join(__dirname, "/../js/ipfs-api.min.js")}); + readFiles.push({filename: 'orbit.js', content: fs.readFileSync(path.join(__dirname, "/../js/orbit.min.js")).toString(), path: path.join(__dirname, "/../js/orbit.min.js")}); + readFiles.push({filename: 'embark.js', content: fs.readFileSync(path.join(__dirname, "/../js/build/embark.bundle.js")).toString(), path: path.join(__dirname, "/../js/build/embark.bundle.js")}); + readFiles.push({filename: 'embark-plugins.js', content: "", path: ""}); } else { - readFiles.push({filename: file, content: fs.readFileSync(file).toString()}); + readFiles.push({filename: file, content: fs.readFileSync(file).toString(), path: file}); } }); return readFiles; }; +Config.prototype.loadPluginContractFiles = function() { + var self = this; + + var contractsPlugins = this.plugins.getPluginsFor('contractFiles'); + if (contractsPlugins.length > 0) { + contractsPlugins.forEach(function(plugin) { + plugin.contractsFiles.forEach(function(file) { + var filename = file.replace('./',''); + self.contractsFiles.push({filename: filename, content: plugin.loadPluginFile(file), path: plugin.pathToFile(file)}); + }); + }); + } +}; + module.exports = Config; diff --git a/lib/contracts.js b/lib/contracts.js index 76ba7d74c..339732576 100644 --- a/lib/contracts.js +++ b/lib/contracts.js @@ -8,7 +8,11 @@ var adjustGas = function(contract) { var maxGas, adjustedGas; if (contract.gas === 'auto') { if (contract.deploy) { - maxGas = Math.max(contract.gasEstimates.creation[0], contract.gasEstimates.creation[1], 500000); + if (contract.gasEstimates.creation !== undefined) { + maxGas = Math.max(contract.gasEstimates.creation[0], contract.gasEstimates.creation[1], 500000); + } else { + maxGas = 500000; + } } else { maxGas = 500000; } diff --git a/lib/index.js b/lib/index.js index 238cbe38f..b15404983 100644 --- a/lib/index.js +++ b/lib/index.js @@ -25,7 +25,6 @@ var ServicesMonitor = require('./services.js'); var Console = require('./console.js'); var IPFS = require('./ipfs.js'); var Swarm = require('./swarm.js'); -var Plugins = require('./plugins.js'); var Embark = { @@ -42,11 +41,12 @@ var Embark = { }, initConfig: function(env, options) { - this.config = new Config({env: env}); - this.config.loadConfigFiles(options); this.logger = new Logger({logLevel: 'debug'}); - this.plugins = new Plugins({plugins: this.config.embarkConfig.plugins, logger: this.logger}); - this.plugins.loadPlugins(); + + this.config = new Config({env: env, logger: this.logger}); + this.config.loadConfigFiles(options); + this.plugins = this.config.plugins; + }, redeploy: function(env) { diff --git a/lib/pipeline.js b/lib/pipeline.js index a5a4fc910..8fa40d933 100644 --- a/lib/pipeline.js +++ b/lib/pipeline.js @@ -23,13 +23,61 @@ Pipeline.prototype.build = function(abi) { if (file.filename === 'embark.js') { return file.content + "\n" + abi; + } else if (file.filename === 'embark-plugins.js') { + + var filesFromPlugins = []; + + var filePlugins = self.plugins.getPluginsFor('pipelineFiles'); + + if (filePlugins.length > 0) { + filePlugins.forEach(function(plugin) { + try { + var fileObjects = plugin.runFilePipeline(); + for (var i=0; i < fileObjects.length; i++) { + var fileObject = fileObjects[i]; + console.debug(JSON.stringify(fileObject)); + filesFromPlugins.push(fileObject); + } + } + catch(err) { + self.logger.error(err.message); + } + }); + } + + var fileContents = filesFromPlugins.map(function(file) { + if (pipelinePlugins.length > 0) { + pipelinePlugins.forEach(function(plugin) { + console.log(plugin.name + ": trying " + file.filename); + try { + if (file.options && file.options.skipPipeline) { + console.log("skipping"); + return; + } + file.content = plugin.runPipeline({targetFile: file.filename, source: file.content}); + } + catch(err) { + self.logger.error(err.message); + } + }); + } + return file.content; + }); + + return fileContents.join('\n'); + } else if (['web3.js', 'ipfs.js', 'ipfs-api.js', 'orbit.js'].indexOf(file.filename) >= 0) { return file.content; } else { if (pipelinePlugins.length > 0) { pipelinePlugins.forEach(function(plugin) { - file.content = plugin.runPipeline({targetFile: file.filename, source: file.content}); + try { + file.content = plugin.runPipeline({targetFile: file.filename, source: file.content}); + } + catch(err) { + self.logger.error(err.message); + } }); } diff --git a/lib/plugin.js b/lib/plugin.js index 21ba340f9..ba7b25f57 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -1,15 +1,21 @@ /*jshint esversion: 6, loopfunc: true */ var grunt = require('grunt'); +var fs = require('fs'); +var path = require('path'); // TODO: pass other params like blockchainConfig, contract files, etc.. var Plugin = function(options) { this.name = options.name; this.pluginModule = options.pluginModule; + this.pluginPath = options.pluginPath; this.pluginConfig = options.pluginConfig; this.clientWeb3Providers = []; this.contractsGenerators = []; this.pipeline = []; + this.pipelineFiles = []; this.console = []; + this.contractsConfigs = []; + this.contractsFiles = []; this.pluginTypes = []; this.logger = options.logger; }; @@ -19,6 +25,14 @@ Plugin.prototype.loadPlugin = function() { (this.pluginModule.call(this, this)); }; +Plugin.prototype.loadPluginFile = function(filename) { + return fs.readFileSync(this.pathToFile(filename)).toString(); +}; + +Plugin.prototype.pathToFile = function(filename) { + return path.join(this.pluginPath, filename); +}; + Plugin.prototype.interceptLogs = function(context) { var self = this; context.console = console; @@ -37,6 +51,7 @@ Plugin.prototype.interceptLogs = function(context) { self.logger.info(self.name + " > " + txt); }; context.console.debug = function(txt) { + // TODO: ue JSON.stringify self.logger.debug(self.name + " > " + txt); }; context.console.trace = function(txt) { @@ -61,6 +76,16 @@ Plugin.prototype.registerPipeline = function(matcthingFiles, cb) { this.pluginTypes.push('pipeline'); }; +Plugin.prototype.addFileToPipeline = function(file, options) { + this.pipelineFiles.push({file: file, options: options}); + this.pluginTypes.push('pipelineFiles'); +}; + +Plugin.prototype.addContractFile = function(file) { + this.contractsFiles.push(file); + this.pluginTypes.push('contractFiles'); +}; + Plugin.prototype.registerConsoleCommand = function(cb) { this.console.push(cb); this.pluginTypes.push('console'); @@ -82,12 +107,30 @@ Plugin.prototype.generateContracts = function(args) { }).join("\n"); }; +Plugin.prototype.registerContractConfiguration = function(config) { + this.contractsConfigs.push(config); + this.pluginTypes.push('contractsConfig'); +}; + Plugin.prototype.runCommands = function(cmd, options) { return this.console.map(function(cb) { return cb.call(this, cmd, options); }).join("\n"); }; +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.options = file.options; + + return obj; + }); +}; + Plugin.prototype.runPipeline = function(args) { // TODO: should iterate the pipeliens var pipeline = this.pipeline[0]; diff --git a/lib/plugins.js b/lib/plugins.js index c41ae24d4..f4f29b587 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -25,9 +25,10 @@ Plugins.prototype.listPlugins = function() { }; Plugins.prototype.loadPlugin = function(pluginName, pluginConfig) { - var plugin = require(path.join(process.env.PWD, 'node_modules', pluginName)); + var pluginPath = path.join(process.env.PWD, 'node_modules', pluginName); + var plugin = require(pluginPath); - var pluginWrapper = new Plugin({name: pluginName, pluginModule: plugin, pluginConfig: pluginConfig, logger: this.logger}); + var pluginWrapper = new Plugin({name: pluginName, pluginModule: plugin, pluginConfig: pluginConfig, logger: this.logger, pluginPath: pluginPath}); pluginWrapper.loadPlugin(); this.plugins.push(pluginWrapper); };