UNPKG

appc-cli-titanium

Version:
192 lines (166 loc) 5.13 kB
/** * This code is closed source and Confidential and Proprietary to * Appcelerator, Inc. All Rights Reserved. This code MUST not be * modified, copied or otherwise redistributed without express * written permission of Appcelerator. This file is licensed as * part of the Appcelerator Platform and governed under the terms * of the Appcelerator license agreement. */ var appc, fs = require('fs-extra'), path = require('path'), _ = require('lodash'), async = require('async'), tar = require('tar'); module.exports = { name: 'titanium-components-publish', type: 'timodule', execute: publish, find: findComponent, when: function (opts) { var isModule = false; [ 'android', 'iphone', 'mobileweb' ].forEach(function (platform) { isModule |= fs.existsSync(path.join(opts.projectDir || process.cwd(), platform, 'timodule.xml')); }); return isModule; }, passthru: true }; function findComponent(appc, opts, pluginExports) { var components = []; // search for component keywords in a directory function search(dir) { var pkgFile = path.join(dir, 'appc.json'); if (fs.existsSync(pkgFile)) { try { var pkg = JSON.parse(fs.readFileSync(pkgFile, 'utf8')); if (!pkg.type) { return; } if (/^(timodule|widget|template|theme)$/.test(pkg.type)) { appc.log.debug('found publishable component ' + pkg.name + ' at ' + dir); var rel = path.relative(process.cwd(), dir); components.push({ name: pkg.type + '/' + pkg.name + '@' + pkg.version + ' ' + appc.chalk.dim.gray('[' + (/^[/.\\]/.test(rel) ? '' : './') + rel + ']'), value: { name: pkg.name, type: pkg.type, version: pkg.version, dir: dir, plugin: module.exports } }); return; } } catch (e) { appc.log.trace('Failed to parse appc.json: ' + e.message); return; } return; } } // search directories for publishable components var searchDir = opts.projectDir || process.cwd(); appc.log.trace('searching for publishable components in ' + searchDir); search(searchDir); return components; } function publish(_appc, args, opts, callback) { appc = _appc; opts = _.clone(opts || {}); var component = opts.component, pkgFile = path.join(component.dir, 'appc.json'); appc.log.trace('loading for publish ' + appc.chalk.yellow(pkgFile)); try { opts.pkg = JSON.parse(fs.readFileSync(pkgFile, 'utf8')); } catch (e) { return callback(new Error('unable to parse appc.json\n' + e.toString())); } opts.publishDir = component.dir; async.waterfall([ // feed opts into waterfall function (cb) { return cb(null, opts); }, // package the module, via npm pack packModule, // sha1 the dist sha1Dist, // upload packaged module to registry uploadModule ], function (err, result) { if (opts.packFile) { try { fs.unlinkSync(opts.packFile); } catch (e) { // do nothing } } return callback(err, result); }); } function packModule(opts, callback) { appc.log.info('Packaging ' + opts.pkg.name); appc.spinner.start(); opts.packFile = path.join(opts.publishDir, opts.pkg.name + '-' + opts.pkg.version + '.tgz'); const tarOpt = { file: opts.packFile, cwd: path.dirname(opts.publishDir), portable: true, gzip: true }; tar.create(tarOpt, [ path.basename(opts.publishDir) ], function (err) { appc.spinner.stop(); if (err) { return callback(err); } return callback(null, opts); }); } function sha1Dist(opts, callback) { appc.log.info('Encoding ' + opts.pkg.name); var hash = require('crypto').createHash('sha1'); hash.setEncoding('hex'); var fd = fs.createReadStream(opts.packFile); fd.on('end', function () { hash.end(); opts.shasum = hash.read(); callback(null, opts); }); fd.pipe(hash); } function uploadModule(opts, callback) { appc.spinner.start(); // add the shasum to the package.json opts.pkg._shasum = opts.shasum; // attempt to find a suitable README and bring it in like npm publish does var readmeNames = [ 'README.md', 'README', 'README.txt' ]; for (var c = 0; c < readmeNames.length; c++) { var readme = path.join(opts.publishDir, readmeNames[c]); if (fs.existsSync(readme)) { opts.pkg.readme = fs.readFileSync(readme).toString(); opts.pkg.readmeFilename = readmeNames[c]; break; } } // get the TYPE if there's one and this is a appc-cli-plugin if (opts.pkg && opts.pkg.keywords && opts.pkg.keywords.indexOf('appc-cli-plugin') !== -1) { var appcfn = path.join(opts.publishDir, 'appc.js'); if (fs.existsSync(appcfn)) { try { var m = require(appcfn); // eslint-disable-line security/detect-non-literal-require opts.subtype = m.TYPE; } catch (E) { appc.log.debug('Error attempting to determine appc-cli-plugin TYPE by loading', appcfn, '. Error: ', E); } } } var appcFile = path.join(opts.publishDir, 'appc.json'); appc.publish.validateAppC(appcFile, opts.pkg, opts.session, function (err, appcJSON, saveappcJSON, savePKG) { if (err) { appc.spinner.stop(); return callback(err); } opts.appcJSON = appcJSON; appc.publish.uploadModule(opts, callback); }); }