UNPKG

@hkvstore/taco-cli

Version:

taco-cli is a command-line interface for rapid Apache Cordova development (forked from Microsoft taco-cli)

196 lines (194 loc) 10.8 kB
// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for details. /// <reference path="../../../typings/node.d.ts" /> /// <reference path="../../../typings/tacoUtils.d.ts" /> /// <reference path="../../../typings/Q.d.ts" /> /// <reference path="../../../typings/nopt.d.ts" /> "use strict"; var fs = require("fs"); var os = require("os"); var path = require("path"); var Q = require("q"); var resources = require("../../resources/resourceManager"); var TacoErrorCodes = require("../tacoErrorCodes"); var errorHelper = require("../tacoErrorHelper"); var Settings = require("./settings"); var tacoUtils = require("taco-utils"); var CordovaHelper = tacoUtils.CordovaHelper; var logger = tacoUtils.Logger; /* * A static class which is responsible for dealing with cordova platform determination */ var PlatformHelper = (function () { function PlatformHelper() { } /* * Given the command line options, determine which platforms we should operate on. * For example, "--local foo" specifies the local platform foo. * "--remote bar" specifies the remote platform bar * "--local" specifies all local platforms, but if there is nothing in /platforms then this is an error * "--remote" specifies all remote platforms, but if there are no remote platforms configured then this is an error * "foo" should build remotely if there is a remote configuration, otherwise it should build locally * "" means all platforms in the following order: * - If a platform has a remote configuration, then perform a remote build * - If a platform exists in /platforms and does not have a remote configuration, then perform a local build */ PlatformHelper.determinePlatform = function (options) { return Q.all([ CordovaHelper.getSupportedPlatforms(), PlatformHelper.determinePlatformsFromOptions(options) ]).spread(function (supportedPlatforms, platforms) { var filteredPlatforms = platforms.filter(function (platform) { var supported = !supportedPlatforms || platform.platform in supportedPlatforms || platform.location === PlatformHelper.BuildLocationType.Remote; if (!supported) { logger.logWarning(resources.getString("CommandUnsupportedPlatformIgnored", platform.platform)); } return supported; }); if (filteredPlatforms.length > 0) { return filteredPlatforms; } else { throw errorHelper.get(TacoErrorCodes.ErrorNoPlatformsFound); } }); }; PlatformHelper.determineSpecificPlatformsFromOptions = function (options, settings) { var platforms = PlatformHelper.parseRequestedPlatforms(options); // one or more specific platforms are specified. Determine whether they should be built locally, remotely, or local falling back to remote return platforms.map(function (platform) { var buildLocation; if (options.options["remote"]) { buildLocation = PlatformHelper.BuildLocationType.Remote; } else if (options.options["local"]) { buildLocation = PlatformHelper.BuildLocationType.Local; } else { // we build remotely if either remote server is setup for the given platform or if the target platform cannot be built locally buildLocation = (platform in (settings.remotePlatforms || {})) || !PlatformHelper.canBuildLocally(platform) ? PlatformHelper.BuildLocationType.Remote : PlatformHelper.BuildLocationType.Local; } return { location: buildLocation, platform: platform }; }); }; /** * Parse the command line options to extract any platforms that are mentioned. * Platforms are any non-flag arguments before a lone -- * * e.g. taco build ios --device ==> 'ios' * taco build windows android -- --phone ==> 'windows', 'android' * taco build --local browser -- ios ==> 'browser' */ PlatformHelper.parseRequestedPlatforms = function (options) { var optionsToIgnore = options.original.indexOf("--") === -1 ? [] : options.original.slice(options.original.indexOf("--")); return options.remain.filter(function (platform) { return optionsToIgnore.indexOf(platform) === -1; }); }; /** * Given the command line options, determine what platforms we wish to operate on. * * This function determines the platforms to work with, as well as whether they are local or remote. * If the command line options specify any platforms, then we will return exactly those platforms, with * appropriate settings for local/remote. * * If the command line options do not specify platforms, then we use all configured remote platforms as remote, * and all added local platforms as local. If a platform is both added locally and has a remote configured, we will * use the remote, unless an override is specified. */ PlatformHelper.determinePlatformsFromOptions = function (options) { return Settings.loadSettingsOrReturnEmpty().then(function (settings) { // Enumerate all installed/configured platforms var remotePlatforms = []; if (!options.options["local"]) { // If we are not only building locally, then we need to consider any remote-only builds we need to do remotePlatforms = Object.keys(settings.remotePlatforms || {}); } var localPlatforms = []; if (!options.options["remote"] && fs.existsSync("platforms")) { // Check for local platforms to try building localPlatforms = fs.readdirSync("platforms").filter(function (entry) { return fs.statSync(path.join("platforms", entry)).isDirectory() && remotePlatforms.indexOf(entry) === -1; }); } return remotePlatforms.map(function (platform) { return { location: PlatformHelper.BuildLocationType.Remote, platform: platform }; }).concat(localPlatforms.map(function (platform) { return { location: PlatformHelper.BuildLocationType.Local, platform: platform }; })); }).then(function (platforms) { var requestedPlatforms = PlatformHelper.parseRequestedPlatforms(options); if (requestedPlatforms.length > 0) { // Filter down to user-requested platforms if appropriate return requestedPlatforms.map(function (platform) { if (!options.options["local"] && platforms.some(function (p) { return p.platform === platform && p.location === PlatformHelper.BuildLocationType.Remote; })) { // If we found a remote configuration for the platform default to using that return { platform: platform, location: PlatformHelper.BuildLocationType.Remote }; } else { // Otherwise if the --local flag was given or no remote was configured, use the platform locally return { platform: platform, location: PlatformHelper.BuildLocationType.Local }; } }); } // Otherwise return all the platforms we found. return platforms; }).then(function (platforms) { return platforms.filter(function (platform) { // If the user specified --remote, then any local platforms at this point // Must be user-specified and non-configured, so warn about them. if (options.options["remote"] && platform.location === PlatformHelper.BuildLocationType.Local) { logger.logWarning(resources.getString("NoRemoteConfigurationFoundForPlatform", platform.platform)); return false; } return true; }); }); }; /** * Apply functions to all local and remote platforms. * Local platforms are batched into one list because Cordova does not cope with multiple concurrent invocations * Remote platforms are done individually (but concurrently with each other and local platforms) since they may * go to completely different servers. */ PlatformHelper.operateOnPlatforms = function (platforms, localFunction, remoteFunction) { var localPlatforms = platforms.filter(function (platform) { return platform.location === PlatformHelper.BuildLocationType.Local; }).map(function (platform) { return platform.platform; }); var remotePlatforms = platforms.filter(function (platform) { return platform.location === PlatformHelper.BuildLocationType.Remote; }).map(function (platform) { return platform.platform; }); // We batch all local platforms together so we make one cordova.raw.build(["foo", "bar", "baz"]) invocation, // because these raw functions are not safe to invoke concurrently. var buildLocalPlatforms = localPlatforms.length > 0 ? localFunction(localPlatforms) : Q({}); var buildRemotePlatforms = remotePlatforms.map(remoteFunction); return Q.all([buildLocalPlatforms].concat(buildRemotePlatforms)); }; /** * Determine whether the given target platform can be built on the local machine * * @targetPlatform {string} target platform to build, e.g. ios, windows * @return {boolean} true if target platform can be built on local machine */ PlatformHelper.canBuildLocally = function (targetPlatform) { switch (os.platform()) { case "darwin": return targetPlatform !== "windows"; // can be android, ios case "win32": return targetPlatform !== "ios"; // can be android, wp*, or windows } return false; }; return PlatformHelper; }()); var PlatformHelper; (function (PlatformHelper) { (function (BuildLocationType) { BuildLocationType[BuildLocationType["Local"] = 0] = "Local"; BuildLocationType[BuildLocationType["Remote"] = 1] = "Remote"; })(PlatformHelper.BuildLocationType || (PlatformHelper.BuildLocationType = {})); var BuildLocationType = PlatformHelper.BuildLocationType; })(PlatformHelper || (PlatformHelper = {})); module.exports = PlatformHelper; //# sourceMappingURL=platformHelper.js.map