forked from jhuckaby/Cronicle
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 2368814
Showing
114 changed files
with
22,756 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.gitignore | ||
/node_modules | ||
/work | ||
/logs | ||
/queue | ||
/data | ||
/conf |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,317 @@ | ||
#!/usr/bin/env node | ||
|
||
// Build Tools Module -- included by build.js. | ||
// Copies, symlinks and compresses files into the right locations. | ||
// Can also compact & bundle JS/CSS together for distribution. | ||
// Copyright (c) 2015 Joseph Huckaby, MIT License. | ||
|
||
var path = require('path'); | ||
var fs = require('fs'); | ||
var zlib = require('zlib'); | ||
var util = require('util'); | ||
var os = require('os'); | ||
var cp = require('child_process'); | ||
|
||
var mkdirp = require('mkdirp'); | ||
var async = require('async'); | ||
var glob = require('glob'); | ||
var UglifyJS = require("uglify-js"); | ||
var Tools = require('pixl-tools'); | ||
|
||
var symlinkFile = exports.symlinkFile = function symlinkFile( old_file, new_file, callback ) { | ||
// create symlink to file | ||
// Note: 'new_file' is the object that will be created on the filesystem | ||
// 'old_file' should already exist, and is the file being pointed to | ||
if (new_file.match(/\/$/)) new_file += path.basename(old_file); | ||
console.log( "Symlink: " + old_file + " --> " + new_file ); | ||
|
||
try { fs.unlinkSync( new_file ); } | ||
catch (e) {;} | ||
|
||
if (!fs.existsSync( path.dirname(new_file) )) { | ||
mkdirp.sync( path.dirname(new_file) ); | ||
} | ||
|
||
// fs.symlink takes a STRING (not a file path per se) as the old (existing) file, | ||
// and it needs to be relative from new_file. So we need to resolve some things. | ||
var sym_new = path.resolve( new_file ); | ||
var sym_old = path.relative( path.dirname(sym_new), path.resolve(old_file) ); | ||
|
||
fs.symlink( sym_old, sym_new, callback ); | ||
}; | ||
|
||
var copyFile = exports.copyFile = function copyFile( old_file, new_file, callback ) { | ||
// copy file | ||
if (new_file.match(/\/$/)) new_file += path.basename(old_file); | ||
console.log( "Copy: " + old_file + " --> " + new_file ); | ||
|
||
try { fs.unlinkSync( new_file ); } | ||
catch (e) {;} | ||
|
||
if (!fs.existsSync( path.dirname(new_file) )) { | ||
mkdirp.sync( path.dirname(new_file) ); | ||
} | ||
|
||
var inp = fs.createReadStream(old_file); | ||
var outp = fs.createWriteStream(new_file); | ||
inp.on('end', callback ); | ||
inp.pipe( outp ); | ||
}; | ||
|
||
var copyFiles = exports.copyFiles = function copyFiles( src_spec, dest_dir, callback ) { | ||
// copy multiple files to destination directory using filesystem globbing | ||
dest_dir = dest_dir.replace(/\/$/, ''); | ||
|
||
glob(src_spec, {}, function (err, files) { | ||
// got files | ||
if (files && files.length) { | ||
async.eachSeries( files, function(src_file, callback) { | ||
// foreach file | ||
copyFile( src_file, dest_dir + '/', callback ); | ||
}, callback ); | ||
} // got files | ||
else { | ||
callback( err || new Error("No files found matching: " + src_spec) ); | ||
} | ||
} ); | ||
}; | ||
|
||
var compressFile = exports.compressFile = function compressFile( src_file, gz_file, callback ) { | ||
// gzip compress file | ||
console.log( "Compress: " + src_file + " --> " + gz_file ); | ||
|
||
if (fs.existsSync(gz_file)) { | ||
fs.unlinkSync( gz_file ); | ||
} | ||
|
||
var gzip = zlib.createGzip(); | ||
var inp = fs.createReadStream( src_file ); | ||
var outp = fs.createWriteStream( gz_file ); | ||
inp.on('end', callback ); | ||
inp.pipe(gzip).pipe(outp); | ||
}; | ||
|
||
var copyCompress = exports.copyCompress = function copyCompress( old_file, new_file, callback ) { | ||
// copy file and create gzip version as well | ||
if (new_file.match(/\/$/)) new_file += path.basename(old_file); | ||
|
||
copyFile( old_file, new_file, function(err) { | ||
if (err) return callback(err); | ||
|
||
// Make a compressed copy, so node-static will serve it up to browsers | ||
compressFile( old_file, new_file + '.gz', callback ); | ||
} ); | ||
}; | ||
|
||
var symlinkCompress = exports.symlinkCompress = function symlinkCompress( old_file, new_file, callback ) { | ||
// symlink file and create gzip version as well | ||
if (new_file.match(/\/$/)) new_file += path.basename(old_file); | ||
|
||
symlinkFile( old_file, new_file, function(err) { | ||
if (err) return callback(err); | ||
|
||
// Make a compressed copy, so node-static will serve it up to browsers | ||
compressFile( old_file, new_file + '.gz', callback ); | ||
} ); | ||
}; | ||
|
||
var deleteFile = exports.deleteFile = function deleteFile( file, callback ) { | ||
// delete file | ||
console.log( "Delete: " + file ); | ||
|
||
if (fs.existsSync(file)) { | ||
fs.unlink( file, callback ); | ||
} | ||
else callback(); | ||
}; | ||
|
||
var deleteFiles = exports.deleteFiles = function deleteFiles( spec, callback ) { | ||
// delete multiple files using filesystem globbing | ||
glob(spec, {}, function (err, files) { | ||
// got files | ||
if (files && files.length) { | ||
async.eachSeries( files, function(file, callback) { | ||
// foreach file | ||
deleteFile( file, callback ); | ||
}, callback ); | ||
} // got files | ||
else { | ||
callback( err ); | ||
} | ||
} ); | ||
}; | ||
|
||
var chmodFiles = exports.chmodFiles = function chmodFiles( mode, spec, callback ) { | ||
// chmod multiple files to specified mode using filesystem globbing | ||
glob(spec, {}, function (err, files) { | ||
// got files | ||
if (files && files.length) { | ||
async.eachSeries( files, function(file, callback) { | ||
// foreach file | ||
fs.chmod( file, mode, callback ); | ||
}, callback ); | ||
} // got files | ||
else { | ||
callback( err || new Error("No files found matching: " + spec) ); | ||
} | ||
} ); | ||
}; | ||
|
||
var copyDir = exports.copyDir = function copyDir( src_dir, dest_dir, exclusive, callback ) { | ||
// recursively copy dir and contents, optionally with exclusive mode | ||
// symlinks are followed, and the target is copied instead | ||
var src_spec = src_dir + '/*'; | ||
|
||
// exclusive means skip if dest exists (do not replace) | ||
if (exclusive && fs.existsSync(dest_dir)) return callback(); | ||
|
||
mkdirp.sync( dest_dir ); | ||
|
||
glob(src_spec, {}, function (err, files) { | ||
// got files | ||
if (files && files.length) { | ||
async.eachSeries( files, function(src_file, callback) { | ||
// foreach file | ||
var stats = fs.statSync(src_file); | ||
|
||
if (stats.isFile()) { | ||
copyFile( src_file, dest_dir + '/', callback ); | ||
} | ||
else if (stats.isDirectory()) { | ||
copyDir( src_file, dest_dir + '/' + path.basename(src_file), exclusive, callback ); | ||
} | ||
}, callback ); | ||
} // got files | ||
else { | ||
callback( err ); | ||
} | ||
} ); | ||
}; | ||
|
||
var bundleCompress = exports.bundleCompress = function bundleCompress( args, callback ) { | ||
// compress bundle of files | ||
var html_file = args.html_file; | ||
var html_dir = path.dirname( html_file ); | ||
|
||
if (!fs.existsSync( path.dirname(args.dest_bundle) )) { | ||
mkdirp.sync( path.dirname(args.dest_bundle) ); | ||
} | ||
|
||
var raw_html = fs.readFileSync( html_file, 'utf8' ); | ||
var regexp = new RegExp( "\\<\\!\\-\\-\\s+BUILD\\:\\s*"+args.match_key+"_START\\s*\\-\\-\\>([^]+)\\<\\!\\-\\-\\s*BUILD\\:\\s+"+args.match_key+"_END\\s*\\-\\-\\>" ); | ||
|
||
if (raw_html.match(regexp)) { | ||
var files_raw = RegExp.$1; | ||
var files = []; | ||
|
||
files_raw.replace( /\b(src|href)\=[\"\']([^\"\']+)[\"\']/ig, function(m_all, m_g1, m_g2) { | ||
files.push( path.join(html_dir, m_g2) ); | ||
} ); | ||
|
||
if (files.length) { | ||
console.log("Bundling files: ", files); | ||
var raw_output = ''; | ||
|
||
// optionally add file header | ||
if (args.header) { | ||
raw_output += args.header.trim() + "\n"; | ||
} | ||
|
||
if (args.uglify) { | ||
console.log("Running UglifyJS..."); | ||
var result = UglifyJS.minify( files ); | ||
if (!result || !result.code) return callback( new Error("Failed to bundle script: Uglify failure") ); | ||
raw_output += result.code; | ||
} | ||
else { | ||
for (var idx = 0, len = files.length; idx < len; idx++) { | ||
var file = files[idx]; | ||
raw_output += fs.readFileSync( file, 'utf8' ) + "\n"; | ||
} | ||
} | ||
|
||
// optionally strip source map links | ||
// /*# sourceMappingURL=materialdesignicons.min.css.map */ | ||
if (args.strip_source_maps) { | ||
raw_output = raw_output.replace(/sourceMappingURL\=\S+/g, ""); | ||
} | ||
|
||
// write out our bundle | ||
console.log(" --> " + args.dest_bundle); | ||
fs.writeFileSync(args.dest_bundle, raw_output); | ||
|
||
// swap a ref link into a copy of the HTML | ||
console.log(" --> " + html_file ); | ||
raw_html = raw_html.replace( regexp, args.dest_bundle_tag ); | ||
fs.writeFileSync(html_file, raw_html); | ||
|
||
// now make a compressed version of the bundle | ||
compressFile( args.dest_bundle, args.dest_bundle + '.gz', function(err) { | ||
if (err) return callback(err); | ||
|
||
// and compress the final HTML as well | ||
compressFile( html_file, html_file + '.gz', callback ); | ||
}); | ||
|
||
} // found files | ||
else { | ||
callback( new Error("Could not locate any file references: " + args.src_html + ": " + args.match_key) ); | ||
} | ||
} | ||
else { | ||
callback( new Error("Could not locate match in HTML source: " + args.src_html + ": " + args.match_key) ); | ||
} | ||
}; | ||
|
||
var generateSecretKey = exports.generateSecretKey = function generateSecretKey( args, callback ) { | ||
// generate random secret key for a specified JSON config file | ||
// use regular expression to preserve natural file format | ||
var file = args.file; | ||
var key = args.key; | ||
var regex = new RegExp('(\\"'+Tools.escapeRegExp(key)+'\\"\\s*\\:\\s*\\")(.*?)(\\")'); | ||
var secret_key = Tools.generateUniqueID(32); | ||
|
||
fs.readFile(file, 'utf8', function(err, text) { | ||
if (err) return callback(err); | ||
if (!text.match(regex)) return callback( new Error("Could not locate key to replace: " + file + ": " + key) ); | ||
|
||
text = text.replace(regex, '$1' + secret_key + '$3'); | ||
fs.writeFile( file, text, callback ); | ||
}); | ||
}; | ||
|
||
var addToServerStartup = exports.addToServerStartup = function addToServerStartup( args, callback ) { | ||
// add service to init.d | ||
// (RedHat and Ubuntu only -- do nothing on OS X) | ||
var src_file = args.src_file; | ||
var dest_dir = args.dest_dir; | ||
var service_name = args.service_name; | ||
var dest_file = dest_dir + '/' + service_name; | ||
|
||
// shell command that activates service on redhat or ubuntu | ||
var cmd = 'chkconfig '+service_name+' on || update-rc.d '+service_name+' defaults'; | ||
|
||
// skip on os x, and if init dir is missing | ||
if (os.platform() == 'darwin') return callback(); | ||
if (!fs.existsSync(dest_dir)) return callback( new Error("Cannot locate init.d directory: " + dest_dir) ); | ||
if (process.getuid() != 0) return callback( new Error("Must be root to add services to server startup system.") ); | ||
|
||
// copy file into place | ||
copyFile( src_file, dest_file, function(err) { | ||
if (err) return callback(err); | ||
|
||
// must be executable | ||
fs.chmod( dest_file, "775", function(err) { | ||
if (err) return callback(err); | ||
|
||
// exec shell command | ||
cp.exec( cmd, callback ); | ||
} ); | ||
} ); | ||
}; | ||
|
||
var printMessage = exports.printMessage = function printMessage( args, callback ) { | ||
// output a message to the console | ||
// use process.stdout.write because console.log has been redirected to a file. | ||
process.stdout.write( "\n" + args.lines.join("\n") + "\n\n" ); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#!/usr/bin/env node | ||
|
||
// Simple Node Project Builder | ||
// Copies, symlinks and compresses files into the right locations. | ||
// Can also compact & bundle JS/CSS together for distribution. | ||
// Copyright (c) 2015 Joseph Huckaby, MIT License. | ||
|
||
var fs = require('fs'); | ||
var path = require('path'); | ||
var util = require('util'); | ||
var async = require('async'); | ||
var mkdirp = require('mkdirp'); | ||
|
||
var BuildTools = require('./build-tools.js'); | ||
var setup = require('../sample_conf/setup.json'); | ||
|
||
var mode = 'dist'; | ||
if (process.argv.length > 2) mode = process.argv[2]; | ||
|
||
var steps = setup.build.common || []; | ||
if (setup.build[mode]) { | ||
steps = steps.concat( setup.build[mode] ); | ||
} | ||
|
||
// chdir to the proper server root dir | ||
process.chdir( path.dirname( __dirname ) ); | ||
|
||
// make sure we have a logs dir | ||
mkdirp.sync( 'logs' ); | ||
fs.chmodSync( 'logs', "755" ); | ||
|
||
// log to file instead of console | ||
console.log = function(msg, data) { | ||
if (data) msg += ' ' + JSON.stringify(data); | ||
fs.appendFile( 'logs/build.log', msg + "\n" ); | ||
}; | ||
|
||
console.log("\nBuilding project ("+mode+")...\n"); | ||
|
||
async.eachSeries( steps, function(step, callback) { | ||
// foreach step | ||
|
||
// util.isArray is DEPRECATED??? Nooooooooode! | ||
var isArray = Array.isArray || util.isArray; | ||
|
||
if (isArray(step)) { | ||
// [ "symlinkFile", "node_modules/pixl-webapp/js", "htdocs/js/common" ], | ||
var func = step.shift(); | ||
console.log( func + ": " + JSON.stringify(step)); | ||
step.push( callback ); | ||
BuildTools[func].apply( null, step ); | ||
} | ||
else { | ||
// { "action": "bundleCompress", ... } | ||
var func = step.action; | ||
delete step.action; | ||
console.log( func + ": " + JSON.stringify(step)); | ||
BuildTools[func].apply( null, [step, callback] ); | ||
} | ||
}, | ||
function(err) { | ||
// done with iteration, check for error | ||
if (err) { | ||
console.error("\nBuild Error: " + err + "\n"); | ||
} | ||
else { | ||
console.log("\nBuild complete.\n"); | ||
} | ||
} ); | ||
|
||
// End |
Oops, something went wrong.