UNPKG

cleverstack-cli

Version:
296 lines (252 loc) 7.38 kB
var Promise = require('bluebird') , async = require('async') , semver = require('semver') , _ = require('lodash') , https = require('follow-redirects').https , utils = GLOBAL.lib.utils , _pkg = GLOBAL.lib.install; var _keywordRequired = [ 'cleverstack module', 'cleverstack-module', 'cleverstack seed', 'cleverstack-seed' ]; Promise.longStackTraces(); /** * Searchies <queries> within the NPM registry * * @param {String[]} queries * @return {Promise} * @api public */ var searchNPMRegistry = exports.npmRegistry = function(queries) { return new Promise(function(resolve, reject) { var repos = []; async.each( queries, function(q, next) { var search = q.split('@'); if (typeof search[1] === 'undefined') { search[1] = '*'; } _pkg.getJSON({ hostname: 'registry.npmjs.org', path: '/' + encodeURIComponent(search[0]) }) .then(function(body) { if (typeof body === 'undefined' || (body.error && body.error === 'not_found')) { return next(); } var versions = Object.keys(body.versions) , maxVersion = semver.maxSatisfying(versions, search[1]) , pkg = body.versions[maxVersion]; if (typeof pkg === 'undefined') { utils.fail('Invalid version ' + search[1] + ' for module ' + search[0], true); return next(); } if (_.intersection(pkg.keywords, _keywordRequired).length > 0) { if (typeof pkg.repository === 'object' && pkg.repository.hasOwnProperty('url')) { pkg.homepage = pkg.repository.url; } repos.push(pkg); } next(); }); }, function(err) { if (!!err) { return reject(err); } resolve(repos); }); }); }; /** * Lists all of the CleverStack-friendly * modules within the NPM registry * * @return {Promise} * @api public */ var list = exports.list = function() { return new Promise(function(resolve, reject) { _pkg .getJSON({ hostname: 'registry.npmjs.org', path: '/-/_view/byKeyword?startkey=["cleverstack"]&endkey=["cleverstack",{}]&group_level=2' }) .then(function(body) { if (typeof body !== 'object' || !body.hasOwnProperty('rows')) { return resolve([]); } var rows = body.rows.map(function(r) { return r.key[ 1 ]; }); searchNPMRegistry(rows) .then(function(response) { resolve(response); }) .catch(function (err) { reject(err); }); }); }); }; /** * Searches through the NPM registry with a * info message, if queries is empty then simply return resolves * * @param {String[]} queries * @return {Promise} * @api public */ var searchNPM = exports.npm = function(queries) { return new Promise(function(resolve, reject) { utils.info(' Searching NPM...'); lib.utils.running('Searching NPM...'); if (queries.length < 1) { list() .then(function(res) { resolve(res); }) .catch(function(err) { reject(err); }); } else { searchNPMRegistry(queries) .then(function(res) { resolve(res); }) .catch(function(err) { reject(err); }); } }); }; /** * Lists all CleverStack-friendly modules within the Bower registry * * @return {Promise} * @api private */ function listBower() { return new Promise(function(resolve) { var repos = []; utils.info(' Searching Bower...'); lib.utils.running('Searching Bower...'); _pkg.getJSON({ hostname: 'bower-component-list.herokuapp.com', path: '/keyword/cleverstack' }) .then(function(body) { if (!Array.isArray(body)) { return resolve(repos); } async.each( body, function(module, next) { _pkg.getJSON({ hostname: 'bower.herokuapp.com', path: '/packages/' + encodeURIComponent(module.name) }) .then(function(bower) { if (!bower || !bower.url) { return next(); } module.url = bower.url; repos.push(module); next(); }); }, function() { resolve(repos); }); }); }); } /** * Returns specific information from a Bower package * It will try to find if the version exists through * the packages GitHub page (this is what Bower does anyway) * * @param {String} query * @return {Promise} * @api public */ var searchBower = exports.bower = function(query) { return new Promise(function(resolve) { var pkg = query.split('@'); _pkg.getJSON({ hostname: 'bower.herokuapp.com', path: '/packages/' + encodeURIComponent(pkg[ 0 ]) }) .then(function (bower) { if (typeof bower === 'undefined') { return resolve(); } else if (typeof pkg[ 1 ] === 'undefined') { return resolve(bower); } utils.info(' Getting bower package information for ' + pkg[ 0 ] + '...'); var req = https.request({ hostname: 'github.com', path: '/' + bower.url.split('/').splice(-2).join('/').replace('.git', '') + '/tree/' + pkg[ 1 ], headers: { 'User-Agent': 'cleverstack' } }, function (res) { if (res.statusCode !== 200) { utils.fail('Couldn\'t find version ' + pkg[ 1 ] + ' for ' + pkg[ 0 ], true); return resolve(); } bower.version = pkg[ 1 ]; bower.bower = true; resolve(bower); } ); req.end(); }); }); }; /** * Aggregates searches from NPM and Bower * * @param {String[]} args * @return {Promise} * @api public */ exports.aggregate = function(args) { return new Promise(function(resolve, reject) { var all = []; utils.info(' Searching for modules...'); lib.utils.running('Searching for modules...'); all.push(searchNPM(args)); all.push(listBower()); args.forEach(function(arg) { all.push(searchBower(arg)); }); Promise .all(all) .then(function(results) { var npm = results[ 0 ].map(function (r) { r.type = 'backend'; return r; }) , keys = results[ 1 ] , repos = []; results.shift(); results.shift(); var bower = (args.length < 1 ? keys : results); if (!Array.isArray(bower)) { bower = []; } bower.filter(function(res) { return typeof res === 'object' && res.hasOwnProperty('url'); }).forEach(function(rep) { var cleverStackBower = _.find(keys, function(key) { return key.name === rep.name; }); if (cleverStackBower) { rep = _.merge(cleverStackBower, rep); rep.type = 'frontend'; repos.push(rep); } }); resolve([ npm, repos ]); }) .catch(function(err) { reject(err); }); }); };