/** * This task builds OpenLayers with the Closure Compiler. */ var fs = require('fs'); var path = require('path'); var async = require('async'); var closure = require('closure-util'); var fse = require('fs-extra'); var nomnom = require('nomnom'); var generateExports = require('./generate-exports'); var log = closure.log; var root = path.join(__dirname, '..'); /** * Assert that a provided config object is valid. * @param {Object} config Build configuration object. * @param {function(Error)} callback Called with an error if config is invalid. */ function assertValidConfig(config, callback) { process.nextTick(function() { if (!Array.isArray(config.exports)) { callback(new Error('Config missing "exports" array')); return; } if (typeof config.compile !== 'object') { callback(new Error('Config missing "compile" object')); return; } callback(null); }); } /** * Read the build configuration file. * @param {string} configPath Path to config file. * @param {function(Error, Object)} callback Callback. */ function readConfig(configPath, callback) { fs.readFile(configPath, function(err, data) { if (err) { if (err.code === 'ENOENT') { err = new Error('Unable to find config file: ' + configPath); } callback(err); return; } var config; try { config = JSON.parse(String(data)); } catch (err2) { callback(new Error('Trouble parsing config as JSON: ' + err2.message)); return; } callback(null, config); }); } /** * Get the list of sources sorted in dependency order. * @param {function(Error, Array.)} callback Called with a list of paths * or any error. */ function getDependencies(callback) { log.info('ol', 'Parsing dependencies'); closure.getDependencies({lib: ['src/**/*.js']}, function(err, paths) { if (err) { callback(err); return; } paths.push(path.join(root, 'build', 'exports.js')); callback(null, paths); }); } /** * Run the compiler. * @param {Object} options Options for Closure Compiler. * @param {Array.} paths List of paths to source files. * @param {function(Error, string)} callback Called with the compiled output or * any error. */ function build(options, paths, callback) { log.info('ol', 'Compiling ' + paths.length + ' sources'); options.js = paths; closure.compile(options, callback); } /** * Generate a build of the library. * @param {Object} config Build configuration object. Must have an "exports" * array and a "compile" object with options for the compiler. * @param {function(Error, string)} callback Called with the compiled source * or any error. */ function main(config, callback) { async.waterfall([ assertValidConfig.bind(null, config), generateExports.bind(null, config.exports), getDependencies, build.bind(null, config.compile) ], callback); } /** * If running this module directly, read the config file and call the main * function. */ if (require.main === module) { var options = nomnom.options({ config: { position: 0, required: true, help: 'Path to JSON config file' }, output: { position: 1, required: true, help: 'Output file path' }, loglevel: { abbr: 'l', choices: ['silly', 'verbose', 'info', 'warn', 'error'], default: 'info', help: 'Log level', metavar: 'LEVEL' } }).parse(); /** * Set the log level. * @type {string} */ log.level = options.loglevel; // read the config, run the main function, and write the output file async.waterfall([ readConfig.bind(null, options.config), main, fse.outputFile.bind(fse, options.output) ], function(err) { if (err) { log.error(err.message); process.exit(1); } else { process.exit(0); } }); } /** * Export main function. */ module.exports = main;