embark/lib/pipeline/pipeline.js
Eric Mastro ab1113fc31 Fixed bug where dist folder is created before placeholder page
If dist folder did not already exist, the folder is created prior to creation of the placeholder page. Without this, the dapp files are never built.
2018-05-23 13:35:18 +10:00

261 lines
9.7 KiB
JavaScript

const fs = require('../core/fs.js');
const async = require('async');
const ProcessLauncher = require('../process/processLauncher');
const utils = require('../utils/utils.js');
const constants = require('../constants');
require("babel-preset-react");
require("babel-preset-es2015");
require("babel-preset-es2016");
require("babel-preset-es2017");
class Pipeline {
constructor(options) {
this.buildDir = options.buildDir;
this.contractsFiles = options.contractsFiles;
this.assetFiles = options.assetFiles;
this.events = options.events;
this.logger = options.logger;
this.normalizeInput = options.normalizeInput;
this.plugins = options.plugins;
this.pipelinePlugins = this.plugins.getPluginsFor('pipeline');
}
build(abi, contractsJSON, path, callback) {
let self = this;
const importsList = {};
let placeholderPage;
async.waterfall([
function createPlaceholderPage(next){
self.events.request('embark-building-placeholder', (html) => {
fs.mkdirpSync(self.buildDir); // create dist/ folder if not already exists
fs.writeFile(self.buildDir + 'index.html', html, next);
});
},
function buildTheContracts(next) {
self.buildContracts(next);
},
function buildWeb3(next) {
self.buildWeb3JS(next);
},
function createImportList(next) {
importsList["Embark/EmbarkJS"] = fs.dappPath(".embark", 'embark.js');
importsList["Embark/web3"] = fs.dappPath(".embark", 'web3_instance.js');
importsList["Embark/contracts"] = fs.dappPath(".embark/contracts", '');
self.plugins.getPluginsProperty('imports', 'imports').forEach(function (importObject) {
let [importName, importLocation] = importObject;
importsList[importName] = importLocation;
});
next();
},
function writeContracts(next) {
self.events.request('contracts:list', (contracts) => {
// ensure the .embark/contracts directory exists (create if not exists)
fs.mkdirp(fs.dappPath(".embark/contracts", ''), (err) => {
if(err) return next(err);
// Create a file .embark/contracts/index.js that requires all contract files
// Used to enable alternate import syntax:
// e.g. import {Token} from 'Embark/contracts'
// e.g. import * as Contracts from 'Embark/contracts'
let importsHelperFile = fs.createWriteStream(fs.dappPath(".embark/contracts", 'index.js'));
importsHelperFile.write('module.exports = {\n');
async.eachOf(contracts, (contract, idx, eachCb) => {
self.events.request('code-generator:contract', contract.className, (contractCode) => {
let filePath = fs.dappPath(".embark/contracts", contract.className + '.js');
importsList["Embark/contracts/" + contract.className] = filePath;
fs.writeFile(filePath, contractCode, eachCb);
// add the contract to the exports list to support alternate import syntax
importsHelperFile.write(`"${contract.className}": require('./${contract.className}').default`);
if(idx < contracts.length - 1) importsHelperFile.write(',\n'); // add a comma if we have more contracts to add
});
}, function(){
importsHelperFile.write('\n}'); // close the module.exports = {}
importsHelperFile.close(next); // close the write stream
});
});
});
},
function assetFileWrite(next) {
async.eachOf(self.assetFiles, function (files, targetFile, cb) {
async.map(files,
function (file, fileCb) {
self.logger.trace("reading " + file.filename);
// Not a JS file
if (file.filename.indexOf('.js') < 0) {
return file.content(function (fileContent) {
self.runPlugins(file, fileContent, fileCb);
});
}
// JS files
async.waterfall([
function runWebpack(next) {
const webpackProcess = new ProcessLauncher({
modulePath: utils.joinPath(__dirname, 'webpackProcess.js'),
logger: self.logger,
events: self.events,
normalizeInput: self.normalizeInput
});
webpackProcess.send({action: constants.pipeline.init, options: {}});
webpackProcess.send({action: constants.pipeline.build, file, importsList});
webpackProcess.once('result', constants.pipeline.built, (msg) => {
webpackProcess.disconnect();
return next(msg.error);
});
},
function readFile(next) {
fs.readFile('./.embark/' + file.filename, (err, data) => {
if (err) {
return next(err);
}
next(null, data.toString());
});
},
function runPluginsOnContent(fileContent, next) {
self.runPlugins(file, fileContent, next);
}
], function (err, contentFile) {
if (err) {
self.logger.error(err);
return fileCb(err);
}
fileCb(null, contentFile);
});
},
function (err, contentFiles) {
if (err) {
self.logger.error(__('errors found while generating') + ' ' + targetFile);
}
let dir = targetFile.split('/').slice(0, -1).join('/');
self.logger.trace("creating dir " + self.buildDir + dir);
fs.mkdirpSync(self.buildDir + dir);
// if it's a directory
if (targetFile.slice(-1) === '/' || targetFile.indexOf('.') === -1) {
let targetDir = targetFile;
if (targetDir.slice(-1) !== '/') {
targetDir = targetDir + '/';
}
async.each(contentFiles, function (file, mapCb) {
let filename = file.filename.replace(file.basedir + '/', '');
self.logger.info("writing file " + (self.buildDir + targetDir + filename).bold.dim);
fs.copy(file.path, self.buildDir + targetDir + filename, {overwrite: true}, mapCb);
}, cb);
return;
}
let content = contentFiles.map(function (file) {
if (file === undefined) {
return "";
}
return file.content;
}).join("\n");
self.logger.info(__("writing file") + " " + (self.buildDir + targetFile).bold.dim);
if(new RegExp(/^index.html?/i).test(targetFile)){
targetFile = targetFile.replace('index', 'index-temp');
placeholderPage = targetFile;
}
fs.writeFile(self.buildDir + targetFile, content, cb);
}
);
},
next);
},
function removePlaceholderPage(next){
let placeholderFile = self.buildDir + placeholderPage;
fs.access(self.buildDir + placeholderPage, (err) => {
if (err) return next(); // index-temp doesn't exist, do nothing
// rename index-temp.htm/l to index.htm/l, effectively replacing our placeholder page
// with the contents of the built index.html page
fs.move(placeholderFile, placeholderFile.replace('index-temp', 'index'), {overwrite: true}, next);
});
}
], callback);
}
runPlugins(file, fileContent, fileCb) {
const self = this;
if (self.pipelinePlugins.length <= 0) {
return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, basedir: file.basedir, modified: true});
}
async.eachSeries(self.pipelinePlugins,
function(plugin, pluginCB) {
if (file.options && file.options.skipPipeline) {
return pluginCB();
}
fileContent = plugin.runPipeline({targetFile: file.filename, source: fileContent});
file.modified = true;
pluginCB();
},
function (err) {
if (err) {
self.logger.error(err.message);
}
return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, basedir: file.basedir, modified: true});
}
);
}
buildContracts(cb) {
const self = this;
async.waterfall([
function makeDirectory(next) {
fs.mkdirp(fs.dappPath(self.buildDir, 'contracts'), (err, _result) => {
next(err);
});
},
function getContracts(next) {
self.events.request('contracts:list', (contracts) => {
next(null, contracts);
});
},
function writeContractsJSON(contracts, next) {
async.each(contracts, (contract, eachCb) => {
fs.writeJson(fs.dappPath(self.buildDir, 'contracts', contract.className + ".json"), contract, {spaces: 2}, eachCb);
}, () => { next(); });
}
], cb);
}
buildWeb3JS(cb) {
const self = this;
async.waterfall([
function makeDirectory(next) {
fs.mkdirp(fs.dappPath(".embark"), (err, _result) => {
next(err);
});
},
function getWeb3Code(next) {
self.events.request('code-generator:web3js', next);
},
function writeFile(code, next) {
fs.writeFile(fs.dappPath(".embark", 'web3_instance.js'), code, next);
}
], cb);
}
}
module.exports = Pipeline;