UNPKG

@edenjs/cli

Version:

Web Application Framework built on Express.js, Redis and RiotJS

268 lines (231 loc) 7.26 kB
// Require dependencies const gulp = require('gulp'); const through = require('through2'); const deepMerge = require('deepmerge'); // Require local dependencies const parser = require('lib/utilities/parser'); /** * Create Controllers Task class * * @task controllers */ class ControllersTask { /** * Construct Controllers Task class * * @param {Loader} runner */ constructor(runner) { // Set private variables this._runner = runner; // Bind public methods this.run = this.run.bind(this); this.watch = this.watch.bind(this); } /** * Run assets task * * @return {Promise} */ run() { // Set config let config = {}; // Get all routes return gulp.src(this._runner.files('controllers/**/*.js')) .pipe(through.obj((chunk, enc, cb) => { // parse file config = deepMerge(config, this.parse(parser.file(chunk.path))); // Run callback cb(null, chunk); })) .on('end', () => { // Loop types in config for (const type of Object.keys(config)) { // Write config file this._runner.write(type, config[type]); } // Restart server this._runner.restart(); }); } /** * Watch task * * @return {string[]} */ watch() { // Return files return [ 'controllers/**/*.js', 'helpers/**/*.js', ]; } /** * parse file * * @param {Object} file * * @return {Object} */ parse(file) { // get mount const mount = file.tags.mount ? file.tags.mount[0].value : ''; const cluster = file.tags.cluster ? file.tags.cluster.map(c => c.value) : null; const priority = file.tags.priority ? parseInt(file.tags.priority[0].value, 10) : null; // skip custom methods const skip = ['call', 'param', 'return', 'returns', 'method', 'route', 'priority', 'acl', 'fail', 'upload']; const single = ['view', 'title', 'layout', 'cache', 'icon', 'menu', 'parent']; // set classes const classes = [Object.assign({}, file, { cluster, priority, methods : undefined, })]; // extract routes const menus = []; const calls = []; const hooks = []; const routes = []; const events = []; const endpoints = []; // forEach file.methods.forEach((method) => { // combine tags const combinedTags = deepMerge(file.tags || {}, method.tags); // parse endpoints [...(method.tags.endpoint || [])].forEach((tag) => { // Comply with max-length of 100 (TravicCI) const methodPriority = method.tags.priority; // create route const endpoint = Object.assign({ fn : method.method, all : !!method.tags.all, file : file.file, endpoint : (tag.value || '').trim(), priority : methodPriority ? parseInt(methodPriority[0].value, 10) : priority, }, parser.acl(combinedTags)); // push endpoint endpoints.push(endpoint); }); // parse events [...(method.tags.on || [])].forEach((tag) => { // Comply with max-length of 100 (TravicCI) const methodPriority = method.tags.priority; // create route const e = Object.assign({ fn : method.method, all : !!method.tags.all, file : file.file, event : (tag.value || '').trim(), priority : methodPriority ? parseInt(methodPriority[0].value, 10) : priority, }, parser.acl(combinedTags)); // push endpoint events.push(e); }); // parse endpoints ['pre', 'post'].forEach((type) => { // pre/post [...(method.tags[type] || [])].forEach((tag) => { // Comply with max-length of 100 (TravicCI) const methodPriority = method.tags.priority; // create route const hook = Object.assign({ type, fn : method.method, file : file.file, hook : (tag.value || '').trim(), priority : methodPriority ? parseInt(methodPriority[0].value, 10) : priority, }, parser.acl(combinedTags)); // push hook hooks.push(hook); }); }); // create route [...(method.tags.route || []), ...(method.tags.call || [])].forEach((tag) => { // Comply with max-length of 100 (TravicCI) const methodPriority = method.tags.priority; // create route const route = Object.assign({ fn : method.method, file : file.file, path : tag.tag === 'route' ? (mount + tag.value).split('//').join('/') : (tag.value || '').trim(), method : tag.tag === 'route' ? (tag.type || 'get').toLowerCase() : null, priority : methodPriority ? parseInt(methodPriority[0].value, 10) : priority, }, parser.acl(combinedTags), tag.tag === 'route' ? { upload : parser.upload(method.tags), } : {}); // check path if (route.path !== '/') route.path = route.path.replace(/\/$/, ''); // loop boolean elements Object.keys(method.tags).filter(key => !skip.includes(key)).forEach((key) => { // check key let routeTag = method.tags[key].map((val) => { // check type if (!val.type) { // return value return val.value === 'true' || val.value.trim() === '' ? true : val.value; } // return value return { type : val.type, value : val.value === 'true' || val.value.trim() === '' ? true : val.value, }; }); // set to first element of array if (single.includes(key)) [routeTag] = routeTag; // set to key route[key] = routeTag; }); // delete priority Object.keys(route).forEach((key) => { // delete key if (route[key] === null) delete route[key]; }); // push route if (tag.tag === 'route') { // push route routes.push(route); } else { // push call calls.push(route); } // create menu (method.tags.menu || []).forEach((menu) => { // set menu menus.push(Object.assign({ acl : route.acl, type : menu.type, icon : route.icon, route : route.path, title : menu.value, parent : route.parent, priority : route.priority, })); }); }); }); // return parsed stuff return { calls, routes, classes, menus : menus.reduce((accum, menu) => { // set menu if (!accum[menu.type]) accum[menu.type] = []; // push menu accum[menu.type].push(menu); // return accum return accum; }, {}), 'controller.hooks' : hooks, 'controller.events' : events, 'controller.endpoints' : endpoints, }; } } /** * Export Controllers Task class * * @type {ControllersTask} */ module.exports = ControllersTask;