@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
JavaScript
// 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" />
;
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