Skip to content

Instantly share code, notes, and snippets.

@Qvatra
Created December 8, 2014 13:56
Show Gist options
  • Save Qvatra/db825eae720c70c0c88a to your computer and use it in GitHub Desktop.
Save Qvatra/db825eae720c70c0c88a to your computer and use it in GitHub Desktop.
ionic development: build.js
var fs = require('fs');
var path = require('path');
var exec = require('child_process').exec;
var archiver = require('archiver'); //npm install archiver
var prompt = require('prompt'); //npm install prompt
var appVersion;
var androidStoreVersion;
var device;
var mode;
var dest;
function info() {
console.log('usage: >node build <android/ios> <release/debug>');
process.exit(0);
}
function verifyArg(arg) {
if (arg === 'ios' || arg === 'android') {
device = (arg === 'ios') ? 'ios' : 'android';
dest = (device === 'ios') ? '../iosBuild' : '../androidBuild';
} else if (arg === 'release' || arg === 'debug') {
mode = (arg === 'release') ? 'release' : 'debug';
} else {
info();
}
}
function fatalError(err){
console.error('fatal Error: ' + err);
process.exit(1);
}
function setAndroidStoreVersion(callback) {
prompt.get(['storeVersion'], function (err, result) {
if (!result.storeVersion) {
setAndroidStoreVersion();
} else {
androidStoreVersion = result.storeVersion;
callback();
}
});
}
function setAppVersion(callback) {
prompt.get(['appVersion'], function (err, result) {
if (!result.appVersion) {
setAppVersion(callback);
} else {
appVersion = result.appVersion;
if (device === 'ios') {
callback();
} else {
setAndroidStoreVersion(callback);
}
}
});
}
function makeZip(from, to, zipName, callback){
var zipArchive = archiver('zip');
var zipOutput = fs.createWriteStream(to+'/'+zipName);
zipOutput.on('close', function() {
console.log('zipping done: ', to+'/'+zipName);
callback();
});
zipArchive.pipe(zipOutput);
zipArchive.bulk([{ src: [ '**/*' ], cwd: from, expand: true }]);
zipArchive.finalize(function(err, bytes) {
if(err) fatalError(err);
console.log('done:', base, bytes);
});
}
function createPathSync(dirPath, mode, fullPath){ //usage: createPathSync('a/b/c/d', [mode]);
if (typeof fullPath == 'undefined') fullPath = dirPath; //initialization
try{//try to make dir
fs.mkdirSync(dirPath, mode);
//if succeeded go recursive or finish
if (!fs.existsSync(fullPath)) createPathSync(fullPath, mode, fullPath);
} catch(err) {
createPathSync(path.dirname(dirPath), mode, fullPath);
}
}
function copyFileSync( source, target ) {
var targetFile = target;
if ( fs.existsSync( target ) ) {
if ( fs.lstatSync( target ).isDirectory() ) {
targetFile = path.join( target, path.basename( source ) );
}
}
fs.createReadStream( source ).pipe( fs.createWriteStream( targetFile ) );
}
function copyFolderRecursiveSync( source, target ) {
var files = [];
if ( !fs.existsSync( target ) ) { //assure that target path exists
createPathSync(target);
}
if ( fs.lstatSync( source ).isDirectory() ) {
files = fs.readdirSync( source );
files.forEach( function ( file, index ) {
var curSource = path.join( source, file );
var curTarget = path.join( target, file );
if ( fs.lstatSync( curSource ).isDirectory() ) {
copyFolderRecursiveSync( curSource, curTarget );
} else {
copyFileSync( curSource, curTarget );
}
} );
}
}
function deleteFolderRecursiveSync(path) {
if( fs.existsSync(path) ) {
fs.readdirSync(path).forEach(function(file,index){
var curPath = path + "/" + file;
if(fs.lstatSync(curPath).isDirectory()) {
deleteFolderRecursiveSync(curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
};
//patching config.xml to change index.html to bootstrapper.html
function patchConfigXml(){
fs.readFile(dest + '/config.xml', 'utf8', function (err, data) {
if (err) fatalError(err);;
data = data.replace('index.html', 'bootstrapper.html');
data = data.replace(/ version="....."/g, ' version="' + appVersion + '"');
if (device === 'android'){
data = data.replace(/ android-versionName="....."/g, ' android-versionName="' + appVersion + '"');
var start = data.indexOf('android-versionCode="') + 21;
var end = data.indexOf('"', start);
data = data.substring(0, start) + androidStoreVersion + data.substr(end);
}
fs.writeFile(dest + '/config.xml', data, function (err) {
if(err) {
fatalError(err);
} else {
console.log("successfully patched!");
}
});
});
}
function changeDir(target) {
try {
var dir0 = process.cwd();
process.chdir(target);
console.log('change directory: ' + dir0 + ' --> ' + process.cwd());
} catch (err) {
fatalError(err);
}
}
function shellExec(cmd, callback){
console.log(cmd + ' executing...');
exec(cmd, function(err, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (err !== null) {
fatalError(err);
} else {
typeof callback === 'function' && callback();
}
});
}
function start() {
//clear
deleteFolderRecursiveSync(dest);
console.log(dest + ' was cleared');
//some files/folders
copyFolderRecursiveSync('bootstrapper', dest + '/www');
console.log('bootstrapper copied to ' + dest + '/www');
copyFolderRecursiveSync('config', dest + '/config');
console.log('config folder copied to ' + dest + '/config');
copyFolderRecursiveSync('hooks', dest + '/hooks');
console.log('hooks folder copied to ' + dest + '/hooks');
copyFileSync('config.xml', dest + '/config.xml');
console.log('config.xml copied to ' + dest + '/config.xml');
patchConfigXml();
if (device === 'android') {
//handling android cordova.zip
var cordovaDest = dest + '/cordovaZip';
copyFolderRecursiveSync('platforms/android/assets/www/plugins', cordovaDest + '/plugins');
console.log('plugins copied to cordovaZip');
copyFileSync('platforms/android/assets/www/cordova.js', cordovaDest + '/cordova.js');
console.log('cordova.js copied to cordovaZip');
copyFileSync('platforms/android/assets/www/cordova_plugins.js', cordovaDest + '/cordova_plugins.js');
console.log('cordova_plugins.js copied to cordovaZip');
} else if (device === 'ios') { //check the path
//handling ios cordova.zip
var cordovaDest = dest + '/cordovaZip';
copyFolderRecursiveSync('platforms/ios/assets/www/plugins', cordovaDest + '/plugins');
console.log('plugins copied to cordovaZip');
copyFileSync('platforms/ios/assets/www/cordova.js', cordovaDest + '/cordova.js');
console.log('cordova.js copied to cordovaZip');
copyFileSync('platforms/ios/assets/www/cordova_plugins.js', cordovaDest + '/cordova_plugins.js');
console.log('cordova_plugins.js copied to cordovaZip');
}
//handling content.zip
var contentDest = dest + '/contentZip';
createPathSync(contentDest);
console.log(contentDest + ' created');
copyFileSync('www/content/contentInfo.json', contentDest + '/contentInfo.json');
console.log('contentInfo.json copied to contentZip');
copyFileSync('www/content/search_stoplist.txt', contentDest + '/search_stoplist.txt');
console.log('search_stoplist.txt copied to contentZip');
//handling www.zip
var wwwDest = dest + '/wwwZip/www';
if (mode === 'release') {
createPathSync(wwwDest + '/js');
copyFileSync('www/js/tslib.js', wwwDest + '/js');
console.log('tslib.js copied to wwwZip/js');
copyFileSync('www/index-min.html', wwwDest + '/index.html');
console.log('index.html copied to wwwZip');
createPathSync(wwwDest + '/template/directives/bookviewer');
copyFileSync('www/template/directives/bookviewer/bookviewer-min.html', wwwDest + '/template/directives/bookviewer/bookviewer.html');
console.log('bookviewer.html copied to /template/directives/bookviewer');
copyFolderRecursiveSync('www/views/min', wwwDest + '/views');
console.log('views copied to wwwZip');
} else {
copyFolderRecursiveSync('www/js', wwwDest + '/js');
console.log('js copied to wwwZip');
copyFileSync('www/index.html', wwwDest + '/index.html');
console.log('index.html copied to wwwZip');
copyFolderRecursiveSync('www/template', wwwDest + '/template');
console.log('template copied to wwwZip');
copyFolderRecursiveSync('www/views', wwwDest + '/views');
console.log('views copied to wwwZip');
}
copyFolderRecursiveSync('www/images', wwwDest + '/images');
console.log('images copied to wwwZip');
copyFolderRecursiveSync('www/fonts', wwwDest + '/fonts');
console.log('fonts copied to wwwZip');
copyFolderRecursiveSync('www/css', wwwDest + '/css');
console.log('css copied to wwwZip');
copyFileSync('www/404.html', wwwDest + '/404.html');
console.log('404.html copied to wwwZip');
copyFileSync('www/favicon.ico', wwwDest + '/favicon.ico');
console.log('favicon.ico copied to wwwZip');
copyFileSync('www/robots.txt', wwwDest + '/robots.txt');
console.log('robots.txt copied to wwwZip');
copyFileSync('www/touch-icon-ipad.png', wwwDest + '/touch-icon-ipad.png');
console.log('touch-icon-ipad.png copied to wwwZip');
copyFileSync('www/touch-icon-ipad-retina.png', wwwDest + '/touch-icon-ipad-retina.png');
console.log('touch-icon-ipad-retina.png copied to wwwZip');
copyFileSync('www/touch-icon-iphone.png', wwwDest + '/touch-icon-iphone.png');
console.log('touch-icon-iphone.png copied to wwwZip');
copyFileSync('www/touch-icon-iphone-retina.png', wwwDest + '/touch-icon-iphone-retina.png');
console.log('touch-icon-iphone-retina.png copied to wwwZip');
//copy lib files to wwwDest
var lib = wwwDest + '/lib';
createPathSync(lib + '/jQuery/dist');
copyFileSync('www/lib/jQuery/dist/jquery.min.js', lib + '/jQuery/dist/jquery.min.js');
console.log('jquery.min.js copied');
createPathSync(lib + '/raygun4js/dist');
copyFileSync('www/lib/raygun4js/dist/raygun.min.js', lib + '/raygun4js/dist/raygun.min.js');
console.log('raygun.min.js copied');
createPathSync(lib + '/handlebars');
copyFileSync('www/lib/handlebars/handlebars.min.js', lib + '/handlebars/handlebars.min.js');
console.log('handlebars.min.js copied');
createPathSync(lib + '/lazy.js');
copyFileSync('www/lib/lazy.js/lazy.js', lib + '/lazy.js/lazy.js');
console.log('lazy.js copied');
createPathSync(lib + '/angular');
copyFileSync('www/lib/angular/angular.min.js', lib + '/angular/angular.min.js');
console.log('angular.min.js copied');
createPathSync(lib + '/angular-animate');
copyFileSync('www/lib/angular-animate/angular-animate.min.js', lib + '/angular-animate/angular-animate.min.js');
console.log('angular-animate.min.js copied');
createPathSync(lib + '/angular-sanitize');
copyFileSync('www/lib/angular-sanitize/angular-sanitize.min.js', lib + '/angular-sanitize/angular-sanitize.min.js');
console.log('angular-sanitize.min.js copied');
createPathSync(lib + '/angular-ui-router/release');
copyFileSync('www/lib/angular-ui-router/release/angular-ui-router.min.js', lib + '/angular-ui-router/release/angular-ui-router.min.js');
console.log('angular-ui-router.min.js copied');
createPathSync(lib + '/collide');
copyFileSync('www/lib/collide/collide.js', lib + '/collide/collide.js');
console.log('collide.js copied');
createPathSync(lib + '/ionic/release/js');
copyFileSync('www/lib/ionic/release/js/ionic.min.js', lib + '/ionic/release/js/ionic.min.js');
copyFileSync('www/lib/ionic/release/js/ionic-angular.min.js', lib + '/ionic/release/js/ionic-angular.min.js');
console.log('ionic.min.js and ionic-angular.min.js copied');
createPathSync(lib + '/lunr.js');
copyFileSync('www/lib/lunr.js/lunr.min.js', lib + '/lunr.js/lunr.min.js');
console.log('lunr.min.js copied');
makeZip(dest + '/cordovaZip', dest + '/www', 'cordova.zip', function () {
makeZip(dest + '/contentZip', dest + '/www', 'content.zip', function () {
makeZip(dest + '/wwwZip', dest + '/www', 'www.zip', function () {
deleteFolderRecursiveSync(dest + '/wwwZip');
console.log('wwwZip removed');
//done with copying; exec commands here
if (device === 'android') {
shellCommandsAndroid();
} else if (device === 'ios') {
shellCommandsIOS();
}
});
deleteFolderRecursiveSync(dest + '/contentZip');
console.log('contentZip removed');
});
deleteFolderRecursiveSync(dest + '/cordovaZip');
console.log('cordovaZip removed');
});
}
function shellCommandsAndroid(){
changeDir(dest);
shellExec('cordova restore plugins --experimental', function(){
shellExec('cordova platform add android', function () {
//shellExec('cordova run android');
shellExec('cordova build --release android', function () {
shellExec('jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore config/android/elseviernextens.keystore platforms/android/ant-build/CordovaApp-release-unsigned.apk -storepass nextens elseviernextens', function () {
shellExec('zipalign -v 4 platforms/android/ant-build/CordovaApp-release-unsigned.apk nextens.apk');
});
});
});
});
}
function shellCommandsIOS(){
changeDir(dest);
shellExec('cordova restore plugins --experimental', function () {
shellExec('cordova platform add ios', function () {
//shellExec('cordova run ios');
shellExec('cordova build --release ios', function () {
//to do
});
});
});
}
///------------------------------------------------------------------------------------------------------------------
///---plain----------------------------------------------------------------------------------------------------------
///------------------------------------------------------------------------------------------------------------------
if (process.argv.length === 4) {
verifyArg(process.argv[2]);
verifyArg(process.argv[3]);
} else {
info();
}
setAppVersion(function () {
shellExec('gulp ' + mode, function () {
start();
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment