UNPKG

evectr.api

Version:

The official eVectr� API.

459 lines (413 loc) 14.7 kB
'use strict'; // ---------------------------------------------------------------------------------------------- // Handle Configurations ------------------------------------------------------------------------ // Requires --------------------------------------------------------------------------------- /** * @type {('development'|'production')} */ process.env.NODE_ENV = 'development'; function isDev() { return process.env.NODE_ENV == 'development'; } function isPro() { return process.env.NODE_ENV == 'production'; } // Requires --------------------------------------------------------------------------------- const os = require('os'); const fs = require('fs'); const path = require('path'); const exec = require('child_process').exec; const gulp = require('gulp'); let Assign, nodemon, babel, cssmin, rename, less, source, browserify, watchify, map, redis; // Variables -------------------------------------------------------------------------------- const JSNS = (obj) => (JSON.stringify(obj, null, ' ')); const LOG = console.log; const SERIES = gulp.series; const PARALLEL = gulp.parallel; const WATCH = (name, source, tasks) => { return (done) => { gulp.watch(source, PARALLEL(...tasks)) .on( 'change', (e) => { LOG(`${name} Change |`, e); }) .on( 'error', (e) => { LOG(`${name} Error |`, e); }) .on( 'nomatch', (e) => { LOG(`${name} NoMatch |`, e); }); done(); }; }; let crashes = null, args = process.argv.slice(2), C = 0, verb = (args.slice(-1)[0]||'')=='--verbose'; // Configs ---------------------------------------------------------------------------------- const cfgfld = './config'; const pubFld = './public'; const brwFld = './main/browser'; const brwexs = !!fs.existsSync(brwFld); const libFld = `${brwFld}/lib`; const opsys = { linux: 'nix', darwin: 'nix', win32: 'win' }[os.platform()]; const frwk = { folders: [ `./node_modules/dffrnt.*` ], options: { cwd: `./` }, location: `./framework` }; const spce = { folder: `${libFld}/spaces/lib`, options: { cwd: `./` }, location: `./spaces` }; const conf = { files: [ `./node_modules/dffrnt.confs/lib/*.cfg.js` ], options: { cwd: `./` }, location: cfgfld }; const browReq = [ 'harmony-reflect', 'object-assign', 'immutable', // 'immutablediff', // 'password-generator', 'classnames', 'socket.io-client', 'reflux', 'react', 'react-dom', 'react-stripe-elements', ]; const browExl = [ './lib/iso', // '../../spaces', ]; const brow = { options: { cache: {}, packageCache: {}, fullPaths: false, debug: isDev(), }, bundles: [ { source: 'vendor.js', require: browReq, }, { source: 'engine.js', entries: [ `${brwFld}/main.js` ], external: browReq.concat(browExl), exclude: [ // `${libFld}/src/renders/lib/iso.jsx`, // `${libFld}/spaces/lib/*.js`, ], }, ], mini: { uglify: { global: true, mangle: isPro(), compress: { sequences: true, dead_code: true, unused: true, conditionals: true, booleans: true, if_return: true, join_vars: true, warnings: isDev() && verb, // passes: 5, } } }, location: `${pubFld}/js`, }; const jsx = { task: 'brow-jsx', source: `${brwFld}/src/**/*.jsx`, watch: `${brwFld}/lib/**/*.jsx`, location: libFld, presets: ['react','env'] }; const es6 = { task: 'brow-es6', source: `${brwFld}/src/es6/*.js`, watch: `${brwFld}/lib/es6/*.js`, location: jsx.location, presets: jsx.presets }; const style = { css: { src: [ `${pubFld}/css/*.css`, `!${pubFld}/css/*.min.css` ] }, less: { src: `${pubFld}/less/*.less` }, min: { showLog: true, compatibility: 'ie8', keepSpecialComments: 0, roundingPrecision: -1 }, location: `${pubFld}/css` }; const redfl = { cwd: '../REDIS', cmd: 'redis-server', cfg: 'redis.conf' }; const rds = { nix: { proc: redfl.cmd, conf: redfl.cfg, kill: `ps -ef|grep ${redfl.cmd.replace(/^r/,'[r]')}|awk '{print $2}'|xargs kill -9`, }, win: { proc: path.join('win',`${redfl.cmd}.exe`), conf: path.join(redfl.cfg), kill: `for /f "tokens=2" %i in ('tasklist ^| find "${redfl.cmd}.exe"') do (taskkill /PID %i /F)`, } }[opsys]; function Ready() { try { Assign = require('object-assign'); nodemon = require('gulp-nodemon'); babel = require('gulp-babel'); cssmin = require('gulp-cssmin'); rename = require("gulp-rename"); less = require('gulp-less'); source = require('vinyl-source-stream'); browserify = require('browserify'); watchify = require('watchify'); map = require('map-stream'); redis = require('redis'); } catch (e) { console.log('\n[ ERROR ]:', e, '\n'); }; }; Ready(); // ---------------------------------------------------------------------------------------------- // Handle Bundle Gulp --------------------------------------------------------------------------- // Configs ---------------------------------------------------------------------------------- // Initialize Framework Directory; if necessary gulp.task( 'framework', (end) => { let loc = frwk.location, fld, len = 0, cnt = []; // ------------------------------------------------------------------------------ function Count(path) { return fs.readdirSync(path).filter(f=>!!!f.match(/^\./)).length;; } function Traverse(file, location, end, level = 1) { level++; let len = 0, idx = 0, cnt = [], TAB = new Array(level).join(' '), { path: full, basename: dir } = file, lnk = `${location}/${dir}`; len = Count(full); gulp.src(`${full}/*`, { nosort: true }) .pipe(map((item, done) => { let fini=()=>(cnt.push(0),done(null,item),cnt.length==len&&end()), { path: pth, basename: base } = item, stat = fs.statSync(pth), absl = `${lnk}/${base}`, exst = fs.existsSync(absl); idx++; // --- if (stat.isDirectory()) { LOG(`${TAB}+ (${idx}/${len}) ${dir}/${base}/`); !exst && fs.mkdirSync(absl); Traverse(item, lnk, fini, level); } else if (!exst) { LOG(`${TAB}- (${idx}/${len}) ${dir}/${base}`); LOG(`fs.symlinkSync('${pth}', '${absl}');`) fs.symlinkSync(pth, absl); // gulp.src(pth).pipe(gulp.symlink(full)); fini(); } else fini(); })); }; // ------------------------------------------------------------------------------ if (!fs.existsSync(loc)) fs.mkdirSync(loc), LOG(`Created Framework Directory.`); // ------------------------------------------------------------------------------ gulp.src(frwk.folders, frwk.options) .pipe(map((file, done) => ( cnt.push(0),setTimeout( ()=>done(null,file),500) ))) .pipe(map((file, done) => { let fini=()=>(cnt.shift(),done(null,file),cnt.length==0&&end()), nme = file.basename, full = `${loc}/${nme}`, exst = fs.existsSync(full), lnkd = exst?fs.lstatSync(full).isSymbolicLink():false, floc = path.resolve(loc); // ---------------------------------------------------------------- LOG(`Linking Module, [${nme}/], to ${loc} ...`); lnkd && fs.unlinkSync(full); exst || fs.mkdirSync(full); Traverse(file, floc, fini); })); }); // Initialize Spaces Directory; if necessary gulp.task( 'spaces', (done) => { if (!!!brwexs) { done(); return; } let loc = spce.location, pth = spce.folder; if (!fs.existsSync(loc)) { gulp.src(pth).pipe(gulp.symlink(loc)); LOG(`Created Spaces Directory.`); }; done(); }); // Initialize Configs; if necessary gulp.task( 'config', (done) => { let max = 0, fld = conf.location; if (!fs.existsSync(fld)) fs.mkdirSync(fld), LOG(`Created Config Directory.`); gulp.src(conf.files, conf.options) .pipe(map((file, done) => { let len = file.basename.length; max = (len>max?len:max); done(null, file); })) .pipe(map((file, done) => { let nme = file.basename; if (!fs.existsSync(`${fld}/${nme}`)) { LOG(`Copied default, [${nme.padStart(max)}], to ${fld} ...`); gulp.src(file.path).pipe(gulp.dest(fld)); }; done(null, file); })); done(); }); gulp.task( 'init', SERIES('framework','config','spaces')); // Install NPM Packages gulp.task( 'npm', (done) => { exec('npm install', (err, stdo, stde) => { if (!!err) LOG(`NPM.ERR: ${JSNS(err)}`); else LOG(stdo||stde); Ready(); done(); }); }); // Install Bower Components gulp.task( 'bower', (done) => { if (!!!brwexs) { done(); return; } exec('bower --allow-root install', (err, stdo, stde) => { if (!!err) LOG(`Bower.ERR: ${JSNS(err)}`); else LOG(stdo||stde); done(); }); }); gulp.task('setup', SERIES('npm','bower','init')); // Convert ---------------------------------------------------------------------------------- // ES6 to ES5 Conversion/Watch gulp.task('es6-make', (done) => { gulp.src(es6.source) .on( 'end', (e) => { done(); }) .on('error', (e) => { LOG('>>> ERROR', e); this.emit('end'); }) .pipe( babel({ presets: es6.presets, /* compact: true, */ comments: false })) .pipe(gulp.dest(es6.location)); }); gulp.task('es6-watch', WATCH( 'ES6', es6.source, ['es6-make'])); gulp.task('es6', PARALLEL('es6-make','es6-watch')); // JSX to JS Conversion/Watch gulp.task('jsx-make', (done) => { gulp.src(jsx.source) .on( 'end', (e) => { done(); }) .on('error', (e) => { LOG('>>> ERROR', e); this.emit('end'); }) .pipe( babel({ presets: jsx.presets, /* compact: true, */ comments: false })) .pipe(gulp.dest(jsx.location)); }); gulp.task('jsx-watch', WATCH( 'JSX', jsx.source, ['jsx-make'])); gulp.task('jsx', PARALLEL('jsx-make','jsx-watch')); // Browserify Concatenation gulp.task('brow-make', (done) => { function getBundle(entry) { let BUND = new browserify(Assign({}, { entries: entry.entries, }, brow.options)), SMAP = `${entry.source}.map`, PMAP = `${pubFld}/js/${SMAP}`, MINI = Assign({}, isDev() ? { map: PMAP.slice(1), output: PMAP, } : {},{ compressPath: p => (path.relative(`${__dirname}/..`, p)) }, brow.mini); function doBundle(ids = []) { // console.log(ids) LOG(`BUNDLE: ${entry.source} to ${brow.location} ...`); // if (fs.existsSync(PMAP)) { fs.unlinkSync(PMAP); console.log('FILE DELETED'); } BUND.bundle() .pipe(source(entry.source)) // .pipe( babel({ presets: ['env'], compact: false })) .pipe(gulp.dest(brow.location)); return BUND; }; if (!!entry.require ) BUND.require( entry.require ); if (!!entry.external) BUND.external(entry.external); if (!!entry.exclude ) BUND.exclude( entry.exclude ); BUND.on('update', doBundle) .plugin('minifyify', MINI) .plugin('watchify', { delay: 100, ignoreWatch: ['**/node_modules/**'] }) .on('log', msg => { LOG(`BUNDLE.SIZE: ${msg}`); BUND.emit('end'); }) .on('end', ( ) => { done(); }) if (verb) BUND .on('file', (f,i)=>{ C++; LOG(`BUNDLE.FILE ${i} | ${C}: ${f}`); }) .on('transform', (_tr,file) => { LOG(`BUNDLE.TRANSFORM: ${file}`); }) doBundle(); }; brow.bundles.map(getBundle); }); // gulp.task('brow-watch', WATCH('BROW', [es6.watch,jsx.watch], ['brow-make'])); // gulp.task('bundle', SERIES('es6', 'jsx', 'brow-make', 'brow-watch')); gulp.task('bundle', SERIES('es6', 'jsx', 'brow-make')); // LESS to CSS Conversion/Watch gulp.task('css-make', (done) => { gulp.src(style.less.src) .pipe(less()) .pipe(gulp.dest(style.location)); done(); }); gulp.task('css-minify', (done) => { gulp.src(style.css.src) // .pipe(sourcemaps.init({ debug: true })) .pipe(cssmin(style.min)) .pipe(rename({ suffix: '.min' })) // .pipe(sourcemaps.write({ debug: true })) .pipe(gulp.dest(style.location)); done(); }); gulp.task('css-conv', SERIES('css-make','css-minify')); gulp.task('css-watch', WATCH('LESS', style.css.src, ['css-conv'])); gulp.task('css', SERIES('css-conv','css-watch')); gulp.task('convert', PARALLEL('bundle', 'css')); // System ----------------------------------------------------------------------------------- // REDIS Server Init gulp.task('redis', (done) => { let RED = redis.createClient(); RED.on('error', (err) => { switch (err.code) { // If it failed due to REDIS not running case 'ECONNREFUSED': exec([`cd ${redfl.cwd} &&`,rds.proc,rds.conf].join(' '), { cwd: path.normalize(redfl.cwd) }, (err, stdo, stde) => { if (!!err) LOG(`REDIS.ERR: ${JSNS(err)}`); else LOG(`REDIS.STD: ${JSNS({OUT:stdo,ERR:stde})}`); }); // Not an issue, just need to know if it's UP case 'NOAUTH': done(); break; // Otherwise, log output; halt execution default: LOG(JSNS(err)); } }); RED.on('ready', () => { LOG('REDIS is running'); done(); }); }); // Daemonized Startup gulp.task('demon', (done) => { let nmon = nodemon({ execMap: { js: 'node --harmony', tasks: ['demon'], }}) .on('crash', () => { try { LOG('Crashed ~ !!'); if ((new Date() - crashes) > 5000) { nmon.emit('restart', 1); } } catch (e) { LOG(e); } }) .on('restart', () => { LOG('Restarted ~ !!'); }); crashes = new Date(); nmon; done(); }); gulp.task( 'system', SERIES('redis', 'demon')); // StartUp ---------------------------------------------------------------------------------- switch (true) { case !!!brwexs: gulp.task('main', SERIES('init','system')); break;; default: gulp.task('main', SERIES('init','convert','system')); break;; } gulp.task('default', SERIES('main')); // ----------------------------------------------------------------------------------------------