UNPKG

@qbyco/tjs-cli

Version:

TrafaletJS CLI Tool

570 lines (445 loc) 15.8 kB
const fs = require("fs"); const path = require("path"); const mkdirp = require('mkdirp'); const gulp = require('gulp'); const gulpweb = require('gulp-webserver'); const rename = require('gulp-rename'); const insert = require('gulp-insert'); const concat = require('gulp-concat'); const uglify = require('gulp-uglify'); const babel = require('gulp-babel'); const pump = require('pump'); const del = require('del'); const es2015 = require('babel-preset-es2015'); const CLICommand = require("../../lib/cli/Command/CLICommand"); const Stub = require("../../lib/stub/stub"); /** * @module tasks/commands/App */ class App extends CLICommand { /** * @constructor * @param lib */ constructor(lib) { super("app"); this.lib = lib; this.options = { path: this.lib.cwd, tjsVersion: 'latest', tjsPath: './vendor', appPath: './app', uiPath: './interface', statePath: './state', storagePath: './storage' }; this.paused = false; this.configPath = path.join(this.lib.cwd, 'trafaletjs.json'); this.lib.events.on('app:finishCommand', (params) => { if(this.paused) { this.finishCommand.apply(this, params); } else { console.log(this.lib.chalk.green(' - Setup complete!')); console.log(this.lib.chalk.yellow('Please open trafaletjs.json and update appPath and uiPath\n')); } }); } /** * @method createAction * @param {String} name * @param {Object} options */ createAction(name, options) { console.log(this.lib.chalk.white('\nTrafaletJS CLI ----------------\n')); this.paused = true; if ("object" === typeof name) { throw new Error("Name must be supplied"); } // Override properties Object.assign(this.options, options); console.log(this.lib.chalk.green(' - Testing app environment')); this.setAppName(name); this.setHomePath(path.join(this.options.path, this.getAppName())); if(fs.existsSync(this.getHomePath())) { console.log(this.lib.chalk.red.bold(' - A directory with the name ' + name + ' already exist. Process closed')); process.exit(); } // Create directory structure console.log(this.lib.chalk.green(' - Setup directory structure')); this.createDirectoryStructure(); // Create JSON config file console.log(this.lib.chalk.green(' - Setup config file')); this.createJSONConfig(); // Get latest TJS distribution console.log(this.lib.chalk.green(' - Downloading Trafalet JS distribution')); this.getLatestTJS(); } /** * @method createAction * @description Set current application as tjs app root * @param {String} name * @param {Object} options */ initAction (name, options) { if ("object" === typeof name) { throw new Error("Name must be supplied"); } // Override properties Object.assign(this.options, options); console.log(this.lib.chalk.green(' - Setup app environment')); this.setAppName(name); this.setHomePath(path.join(this.options.path, './')); // Create JSON config file console.log(this.lib.chalk.green(' - Setup config file')); this.createJSONConfig(true); // Get latest TJS distribution console.log(this.lib.chalk.green(' - Downloading Trafalet JS distribution')); this.getLatestTJS(); } /** * @method buildAction * @param {Object} options */ buildAction (options) { console.log(this.lib.chalk.white('\nTrafaletJS CLI ----------------\n')); if(!fs.existsSync(this.configPath)) { console.log(this.lib.chalk.red('Config file trafaletjs,json not found in path: ' + this.lib.cwd)); return false; } let config = require (this.configPath), version = config.version, distPath = path.join(this.lib.cwd, './dist'), compress = false, fileName = '', build = 'dev-build'; if(undefined !== options['version']) { version = options['version']; } if(undefined !== options['path']) { distPath = path.join(options['path']); } if(undefined !== options['compress']) { compress = true; } const dist = { es6: config.name + '-' + version + '.es6.js', es5: config.name + '-' + version + '.es5.js', dist: config.name + '-' + version + '.dist.js', dev: config.name + '-' + version + '.dev-build.js' }; if(!fs.existsSync(distPath)) { mkdirp.sync(distPath); } gulp.task('es6', () => { return gulp.src([ path.join(this.lib.cwd, 'app.js'), path.join(this.lib.cwd, './' + config.statePath + '/**/*.*'), path.join(this.lib.cwd, './' + config.storagePath + '/**/*.*'), path.join(this.lib.cwd, './' + config.appPath + '/**/*.*'), path.join(this.lib.cwd, 'boot.js') ]) .pipe(concat(dist.es6)) .pipe(insert.prepend('/** DIST:' + config.name + '-' + version + '**/\n\n')) .pipe(gulp.dest(distPath)); }); gulp.task('es5', ['es6'], () => { return gulp.src(path.join(distPath, dist.es6)) .pipe(babel({ presets: [es2015] })) .pipe(concat(dist.es5)) .pipe(gulp.dest(distPath)); }); gulp.task('dev-build', ['es5'], () => { return gulp .src(path.join(distPath, dist.es5)) .pipe(rename(dist.dev)) .pipe(gulp.dest(distPath)); }); gulp.task('dist', ['es5'], () => { return gulp.src(path.join(distPath, dist.es5)) .pipe(uglify()) .pipe(rename(dist.dist)) .pipe(gulp.dest(distPath)) }); if(compress) { console.log(this.lib.chalk.green(' - Build stable version: ' + version)); fileName = dist.dist; gulp.task ('clean', ['dist'], () => { fs.unlinkSync(path.join(distPath, dist.es6)); fs.unlinkSync(path.join(distPath, dist.es5)); }); } else { console.log(this.lib.chalk.green(' - Build dev version: ' + version)); fileName = dist.dev; gulp.task ('clean', ['dev-build'], () => { fs.unlinkSync(path.join(distPath, dist.es6)); fs.unlinkSync(path.join(distPath, dist.es5)); }); } gulp.start.apply(gulp, ['clean']); if(version !== config.version) { console.log(this.lib.chalk.green(' - Update app version: ' + config.version + '->' + version)); config.version = version; fs.writeFileSync(this.configPath, JSON.stringify(config, null, ' ')); } console.log(this.lib.chalk.green(' - Build complete!')); console.log(this.lib.chalk.yellow(' Append [' + fileName + '] to your index file to test it out')); } /** * @method watchAction * @param options */ watchAction (options) { console.log(this.lib.chalk.white('\nTrafaletJS CLI ----------------\n')); if(!fs.existsSync(this.configPath)) { console.log(this.lib.chalk.red('Config file trafaletjs,json not found in path: ' + this.lib.cwd)); return false; } let port = 9999; let host = 'localhost'; if(undefined !== options['port']) { port = parseInt(options['port']); } if(undefined !== options['host']) { host = options['host']; } gulp.task('web', () => { console.log(this.lib.chalk.cyan(' TrafaletJS watch started')); gulp .src(this.lib.cwd) .pipe(gulpweb({ livereload: true, directoryListing: false, open: false, host: host, port: port })); }); gulp.start.apply(gulp, ['web']); } /** * @method getHomePath * @returns {String|*} */ getHomePath() { return this.homePath; } /** * @method setHomePath * @param {String} path */ setHomePath(path) { this.homePath = path; } /** * @method getAppName * @returns {String|*} */ getAppName () { return this.appName; } /** * @method setAppName * @param {String} name */ setAppName (name) { this.appName = name; } /** * @method finishCommand */ finishCommand () { // Create Hello World App if(true === this.options.withBoilerplate) { console.log(this.lib.chalk.green(' - Setup boilerplate application')); this.copyHelloWorldStructure(); } else { this.copySimpleStructure(); console.log(this.lib.chalk.yellow(' - Skip boilerplate application')); } console.log(this.lib.chalk.green(' - Setup index.html')); // Create index.html this.createIndexPage(); console.log(this.lib.chalk.green(' - Setup complete!\n')); } /** * @method createDirectoryEvenIfExists * @param {String} path * @returns {App} */ createDirectoryEvenIfExists(path) { if(!fs.existsSync(path)) { fs.mkdirSync(path); } return this; } /** * @method createJSONConfig * @param empty * @return {App} */ createJSONConfig (empty = false) { let jsonTemplate = new Stub('app/tjs.json'), output = 'trafaletjs.json'; jsonTemplate.parse('name', this.getAppName()); if(empty) { this.createJSONForExistingProject(jsonTemplate); } else { this.createJSONForNewProject(jsonTemplate); } const tmpCfgJSON = JSON.parse(jsonTemplate.getStubContent()); // Update project paths Object.assign(this.options, { appPath: tmpCfgJSON.appPath, uiPath: tmpCfgJSON.uiPath, statePath: tmpCfgJSON.statePath, storagePath: tmpCfgJSON.storagePath, rootPath: this.getHomePath() }); fs.writeFileSync(path.join(this.getHomePath(), output), jsonTemplate.getStubContent()); return this; } /** * @method getLatestTJS * @description Download trafaletjs */ getLatestTJS () { this.lib.events.emit('manager:install', [ this.options.tjsVersion, { path: this.options.tjsPath, cwd: this.getHomePath() } ]); } copySimpleStructure () { const appConfigStub = new Stub('components/app.js'); const bootConfigStub = new Stub('components/boot.js'); appConfigStub.parse('name', this.getAppName().capitalizeFirstLetter()); appConfigStub.parse('uiPath', this.options.uiPath); bootConfigStub.parse('name', this.getAppName().capitalizeFirstLetter()); // Copy app and boot files fs.writeFileSync(path.join(this.options.rootPath, 'boot.js'), bootConfigStub.getStubContent()); fs.writeFileSync(path.join(this.options.rootPath, 'app.js'), appConfigStub.getStubContent()); return this; } /** * @method copyHelloWorldStructure * @description Create an app boilerplate using helloworld structure * @return {App} */ copyHelloWorldStructure () { let appPath = path.join(this.options.rootPath, this.options.appPath), uiPath = path.join(this.options.rootPath, this.options.uiPath); const appConfigStub = new Stub('components/app.js'); const bootConfigStub = new Stub('components/boot.js'); const logicStub = new Stub('app/logic-sample.js'); appConfigStub.parse('name', this.getAppName().capitalizeFirstLetter()); appConfigStub.parse('uiPath', this.options.uiPath); bootConfigStub.parse('name', this.getAppName().capitalizeFirstLetter()); logicStub.parse('name', this.getAppName().capitalizeFirstLetter()); // Copy logic file fs.writeFileSync(path.join(appPath, 'app.js'), logicStub.getStubContent()); // Copy module files mkdirp.sync(path.join(uiPath, 'helloworld/components')); // Copy module sources fs.createReadStream(path.join(__dirname, '../../resources/samples/module.js')).pipe(fs.createWriteStream(path.join(uiPath, 'helloworld', 'module.js'))); fs.createReadStream(path.join(__dirname, '../../resources/samples/module.html')).pipe(fs.createWriteStream(path.join(uiPath, 'helloworld','module.html'))); fs.createReadStream(path.join(__dirname, '../../resources/samples/component.js')).pipe(fs.createWriteStream(path.join(uiPath, 'helloworld/components', 'HelloWorld.js'))); // Copy app and boot files fs.writeFileSync(path.join(this.options.rootPath, 'boot.js'), bootConfigStub.getStubContent()); fs.writeFileSync(path.join(this.options.rootPath, 'app.js'), appConfigStub.getStubContent()); return this; } /** * @method createIndexPage * @return {App} */ createIndexPage () { let indexTemplate = new Stub('app/index.html'), config = require(path.join(this.options.rootPath, 'trafaletjs')); indexTemplate.parse('name', config.name); indexTemplate.parse('tjs-path', path.join(this.options.tjsPath, 'trafaletjs-' + config.tjs.version + '.js')); indexTemplate.parse('app-path', 'app.js'); indexTemplate.parse('boot-path','boot.js'); indexTemplate.parse('default-entry-path', path.join(this.options.appPath, 'app.js')); fs.writeFileSync(path.join(this.getHomePath(), 'index.html'), indexTemplate.getStubContent()); return this; } /** * @method createJSONForNewProject * @param {Stub} jsonTemplate */ createJSONForNewProject (jsonTemplate) { jsonTemplate.parse('description', ""); jsonTemplate.parse('appPath', this.options.appPath); jsonTemplate.parse('uiPath', this.options.uiPath); jsonTemplate.parse('statePath', this.options.statePath); jsonTemplate.parse('storagePath', this.options.storagePath); jsonTemplate.parse('tjs-version', ""); jsonTemplate.parse('tjs-path', ""); } /** * @method createJSONForExistingProject * @param {Stub} jsonTemplate */ createJSONForExistingProject (jsonTemplate) { jsonTemplate.parse('description', ""); jsonTemplate.parse('appPath', ""); jsonTemplate.parse('uiPath', ""); jsonTemplate.parse('statePath', ""); jsonTemplate.parse('storagePath', ""); jsonTemplate.parse('tjs-version', ""); jsonTemplate.parse('tjs-path', ""); } /** * @method createDirectoryStructure */ createDirectoryStructure() { this.createDirectoryEvenIfExists(this.getHomePath()); let dirs = require("../../resources/stubs/app/directories.json"); dirs.forEach((directory) => { if('app' === directory || 'ui' === directory || 'state' === directory || 'storage' === directory) { if (this.options[directory + 'Path']) { this.createDirectoryEvenIfExists(path.join(this.getHomePath(), this.options[directory + 'Path'])); } else { this.createDirectoryEvenIfExists(path.join(this.getHomePath(), directory)); } } else { this.createDirectoryEvenIfExists(path.join(this.getHomePath(), directory)); } }); //State folder sub-dirs if (this.options['statePath']) { mkdirp.sync(path.join(this.getHomePath(), this.options['statePath'], 'contracts')); mkdirp.sync(path.join(this.getHomePath(), this.options['statePath'], 'definitions')); } else { mkdirp.sync(path.join(this.getHomePath(), 'state/contracts')); mkdirp.sync(path.join(this.getHomePath(), 'state/definitions')); } } /** * @method help * @returns {Map} */ help () { const help = new Map(); help.set("create [name] [--path, --appPath, --uiPath, --statePath, --storagePath, --tjsVersion, --withBoilerplate]", "Create a new application"); help.set("init [name] [--path, --tjsVersion, --appPath, --uiPath]", "Init an app on current location"); help.set("watch [--port, --host]", "App server watcher"); help.set("build [--path, --version, --compress]", "Build app for production"); return help; } } module.exports = { init: function (lib) { lib.cli.getRepository().addCommand(new App(lib)); }, run: function (lib) { } };