Merge pull request #12 from vladimir-kotikov/cordova-lib-refactoring

Cordova-lib refactoring proposal
diff --git a/proposals/cordova-lib refactoring/Cordova-lib refactoring proposal.md b/proposals/cordova-lib refactoring/Cordova-lib refactoring proposal.md
new file mode 100644
index 0000000..16c2d69
--- /dev/null
+++ b/proposals/cordova-lib refactoring/Cordova-lib refactoring proposal.md
@@ -0,0 +1,190 @@
+The proposal describes the way how we can improve current cordova lib design and interaction between cordova lib and platforms. The document contains high-level descriptions of proposed interfaces only. Fo more details on methods signatures see *.js files in this pull request.
+
+The most important points of this proposal are:
+
+## 1. The PlatformApi class
+
+PlatformApi (or CordovaPlatform) class - an abstraction around particular platform that exposes all the actions for this platform (such as build/run), so they're accessible programmatically. It also knows how to install/uninstall plugins with all source files, web assets and js files, so this is no more responsibility of cordova-lib. It also exposes single 'prepare' method to provide a way for cordova-lib to apply project's settings/www content to platform.
+
+The PlatformApi class needs to be implemented by each platform, that wants to use new API flow. For those platforms, which doesn't provide own PlatformApi, there will be a polyfill in cordova-lib.
+
+There is a PR to cordova-lib, which implements the polyfill: https://github.com/MSOpenTech/cordova-lib/pull/2
+
+### Proposed class structure
+
+#### Constructor
+
+    function PlatformApi() {}
+
+#### Static methods
+
+    PlatformApi.createPlatform = function (cordovaProject, options) {};
+    PlatformApi.updatePlatform = function (cordovaProject, options) {};
+
+These methods are equal to bin/create and bin/update scripts. Installs/updates platform to specified directory and creates a platform project. Accepts a CordovaProject instance, that defines a project structure and configuration, that should be applied to new platform, and an options object.
+
+#### Platform-specific information
+
+    PlatformApi.prototype.getPlatformInfo = function () {};
+
+Gets a CordovaPlatform object, that represents the platform structure:
+Platform's directories/main files locations (config.xml, www, etc.)
+
+#### CLI workflow integration
+
+    PlatformApi.prototype.prepare = function (cordovaProject) {};
+
+Updates installed platform with provided www assets and new app configuration. This method is required for CLI workflow and will be called each time before build, so the changes, made to app configuration and www code, will be applied to platform. 
+
+__NOTE:__ The `prepare` method doesn't rebuild `cordova_plugins` file and doesn't reapply assets and js files, installed by plugins, to platform's www directory. Accepts a `CordovaProject` instance, that defines a project structure and configuration, that should be applied to platform
+
+#### Plugin management
+
+    PlatformApi.prototype.addPlugin = function (plugin, installOptions) {};
+    PlatformApi.prototype.removePlugin = function (plugin) {};
+
+Installs/uninstalls a plugin into platform. These methods handles all the files, shipped by plugin (sources, libs, assets, js-files). Accepts a `PluginInfo` instance that represents plugin that will be installed/uninstalled, and an `options` object.
+
+__NOTE:__ The methods doesn't resolve the dependencies of plugin. Resolving dependencies is still the responsibility of caller.
+
+__NOTE:__ Since `uninstall` method accepts PluginInfo instance as input parameter instead of plugin id, the caller should take care of managing/storing PluginInfo instances for future uninstalls.
+
+##### Platform's 'actions'
+
+    PlatformApi.prototype.build = function(buildOptions) {};
+    PlatformApi.prototype.run = function(runOptions) {};
+    PlatformApi.prototype.clean = function() {};
+    PlatformApi.prototype.requirements = function() {};
+
+These methods are equal to platform's executable scripts. The main difference is that they accepts a structured `options` object instead of array of command line arguments. The `options` structure is highly depends on platform's specific. The detailed list of common options see [PlatformApi reference](PlatformApi.js)
+
+## 2. The ProjectAPI class
+
+ProjectAPI (or CordovaProject) class - an abstraction of cordova project with multiple platforms/plugins installed. Manages the platforms and delegates the responsibilities to corresponding platform:
+
+    Project.run -> this.platforms.foreach(platform.run);
+
+It also does some additional job:
+
+  * fetches plugins/platforms from any sources (git/npm/web)
+  * resolves plugin dependencies
+  * handles platform's restrictions (<engine> tag)
+
+### Proposed class structure
+
+#### Constructor
+
+    function ProjectApi () {}
+
+#### Static methods
+
+    ProjectApi.getProjectAt = function (projectDir) {};
+
+'Static' method, that gets a ProjectApi instance for specified directory. Returns a `ProjectApi` instance.
+
+    ProjectApi.createProject = function (targetDir, appName, appId, options) {};
+
+Initializes an empty cordova project at specified directory. Returns a promise fulfilled with a `ProjectAPI` instance.
+
+#### Project-specific information
+
+    ProjectApi.prototype.getProjectInfo = function () {};
+
+Gets a ProjectInfo structure that describes the project. Similar to `PlatformApi.getPlatformInfo`
+
+#### Platform management
+
+    ProjectApi.prototype.addPlatform = function (platformSpec, options) {};
+
+Adds a new platform to project. Accepts a platform spec that should be one of following:
+
+  - valid platform name: 'android', 'windows', etc.
+  - valid npm identifier, that resolves to valid platform: cordova-android@4.0
+  - git url, that points to repo with valid platform: http://github.com/apache/cordova-android.git#4.0.0
+  - path to local repo of valid platform: /my/cordova/repositories/cordova-android
+
+Does all of the job, related to acquiring the platform code from NPM/git/other sources.
+
+    ProjectApi.prototype.removePlatform = function (platformName, options) {};
+
+Removes a platform from project.
+
+    ProjectApi.prototype.getPlatforms = function () {};
+    ProjectApi.prototype.getPlatform = function (platformName) {};
+
+Gets all/single platform, installed into project. Returns an array of/single `PlatformApi` instance.
+
+#### Plugins management
+
+    ProjectApi.prototype.addPlugin = function (pluginSpec, options) {};
+    ProjectApi.prototype.removePlugin = function (pluginId, options) {};
+
+Adds/removes a plugin into/from project. Also installs/uninstalls it to/from each platform in project. Accepts a plugin spec that should be one of following:
+
+  - valid plugin id that can be resolved through either cordova plugin registry or npm: 'org.apache.cordova.globalization', 'cordova-plugin-globalization'
+  - valid npm identifier, that resolves to valid plugin: `cordova-plugin-globalization@1.0.0`
+  - git url, that points to repo with valid plugin: `http://github.com/apache/cordova-plugin-globalization.git#r1.0.0`
+  - path to local repo of valid plugin: `/my/cordova/repositories/cordova-plugin-globalization`
+
+These methods also responsible for fetching plugin's source from available distribution channels and resolving plugin's dependencies.
+
+    ProjectApi.prototype.getPlugins = function () {};
+    ProjectApi.prototype.getPlugin = function (pluginId) {};
+
+Gets all/single the plugin, installed into project. Returns an array of/single `PluginInfo` instance.
+
+#### Project-platform integration
+
+    ProjectApi.prototype.prepare = function (platform, prepareOptions) {};
+
+'Prepares' a project for building specified platform/platforms. The prepare step is need to be performed to update configuration and www assets for each platform from application's ones before the application will be built. The prepare step isn't required if no configuration changes or www assets changes was made.
+
+#### Project's 'actions'
+
+    ProjectApi.prototype.build = function (platform, buildOptions) {};
+    ProjectApi.prototype.run = function (platform, runOptions) {};
+    ProjectApi.prototype.serve = function (platform, serveOptions) {};
+    ProjectApi.prototype.clean = function(platform, cleanOptions) {};
+    ProjectApi.prototype.requirements = function(platform) {};
+
+These methods works as project-level platform's actions.
+
+    PlatformApi.getPlatform(platform).build(buildOptions)
+
+etc. The `platform` parameter is optional, and if not specified, the command works just as
+
+    PlatformApi.getPlatforms().forEach(function (platform){
+        platform.build(buildOptions);
+    })
+
+For `options` reference see [ProjectAPI](ProjectApi.js)
+
+## `cordova-common` module
+
+'cordova-common' module - required to share similar code between platforms and lib. Currently there are following candidates for moving to `cordova-common`:
+
+    `superspawn`
+    `ActionStack`
+    `CordovaError`
+    `PlatformJson`
+    `ConfigParser`
+    `PluginInfo`
+    `PluginInfoProvider`
+    `ConfigChanges`
+    `ConfigKeeper`
+    `ConfigFile`
+    `mungeUtil`
+    `xmlHelpers`
+
+The PR for `cordova-common` module is ready and published here: https://github.com/MSOpenTech/cordova-lib/pull/3.
+
+## Links:
+PlatformApi proposal with APIs' definitions: https://github.com/cordova/cordova-discuss/pull/9
+PlatformApi polyfill implementation for cordova-lib: https://github.com/MSOpenTech/cordova-lib/pull/2
+`cordova-common` implementation: https://github.com/MSOpenTech/cordova-lib/pull/3
+
+Pull requests:
+
+- `PlatformApi` polyfill: https://github.com/MSOpenTech/cordova-lib/pull/2
+- `cordova-common` implementation: https://github.com/MSOpenTech/cordova-lib/pull/3
+
diff --git a/proposals/cordova-lib refactoring/CordovaPlatform.js b/proposals/cordova-lib refactoring/CordovaPlatform.js
new file mode 100644
index 0000000..4d23414
--- /dev/null
+++ b/proposals/cordova-lib refactoring/CordovaPlatform.js
@@ -0,0 +1,56 @@
+/* jshint node:true, unused:false */
+
+var path = require('path');
+var BuildConfig = require('cordova-common').BuildConfig;
+var ConfigParser = require('cordova-common').ConfigParser;
+
+/**
+ * Encapsulates and stores platform's information.
+ *
+ * @class
+ */
+function CordovaPlatform(root) {
+    /**
+     * Simple object that exposes platform's filesystem locations, such as www
+     *   directory.
+     *
+     * @type  {Object}
+     */
+    this.locations = {
+        /** @type {String} Platform's www directory location */
+        www: path.join(root, 'www'),
+        /** @type {String} Platform's config.xml file location  */
+        configXml: path.join(root, 'config.xml'),
+        /**
+         * Location of cordova.js that shipped with platform.
+         *   NOTE: THIS PATH IS NOT ABSOLUTE. IT IS RELATIVE TO PLATFORM'S
+         *   ORIGINAL PACKAGE DIRECTORY, NOT THE INSTALLED PLATFORM'S LOCATION.
+         *
+         * @type  {String}
+         */
+        cordovaJs: path.join('bin', 'template', 'www', 'cordova.js'),
+        /**
+         * Location of platform's cordova.js sources, shipped with platform.
+         *   NOTE: THIS PATH IS NOT ABSOLUTE. IT IS RELATIVE TO PLATFORM'S
+         *   ORIGINAL PACKAGE DIRECTORY, NOT THE INSTALLED PLATFORM'S LOCATION.
+         *
+         * @type  {String}
+         */
+        cordovaJsSrc: 'cordova-js-src'
+    };
+
+    /**
+     * The installed platform's root location.
+     *
+     * @type {String}
+     */
+    this.root = root;
+
+    /**
+     * Represents the platform's design-time and runtime configuration which
+     *   stored in config.xml file.
+     *
+     * @type  {ConfigParser}
+     */
+    this.projectConfig = new ConfigParser(this.locations.configXml);
+}
diff --git a/proposals/cordova-lib refactoring/CordovaProject.js b/proposals/cordova-lib refactoring/CordovaProject.js
new file mode 100644
index 0000000..56c0dcd
--- /dev/null
+++ b/proposals/cordova-lib refactoring/CordovaProject.js
@@ -0,0 +1,53 @@
+/* jshint node:true, unused:false */
+
+var path = require('path');
+var BuildConfig = require('cordova-common').BuildConfig;
+var ConfigParser = require('cordova-common').ConfigParser;
+
+/**
+ * Encapsulates and stores project information.
+ *
+ * @class
+ */
+function CordovaProject(root) {
+    /**
+     * Simple object that exposes this project's filesystem locations, such as www
+     *   directory.
+     *
+     * @type  {Object}
+     */
+    this.locations = {
+        /** @type {String} Www directory location */
+        www: path.join(root, 'www'),
+        /** @type {String} config.xml file location  */
+        configXml: path.join(root, 'config.xml'),
+        /** @type {String} Installed platforms location */
+        platforms: path.join(root, 'platforms'),
+        /** @type {String} Installed plugins location */
+        plugins: path.join(root, 'plugins')
+    };
+
+    /**
+     * The project's root location.
+     *
+     * @type {String}
+     */
+    this.root = root;
+
+    /**
+     * Represents the configuration, used for building project. Populated with
+     *   values from build.json, if exists, or with some default values,
+     *   if not.
+     *
+     * @type {BuildConfig}
+     */
+    this.buildConfig = new BuildConfig(root);
+
+    /**
+     * Represents the project design-time and runtime configuration which stored in
+     *   project's config.xml file.
+     *
+     * @type  {ConfigParser}
+     */
+    this.projectConfig = new ConfigParser(this.locations.configXml);
+}
diff --git a/proposals/cordova-lib refactoring/PlatformApi.js b/proposals/cordova-lib refactoring/PlatformApi.js
new file mode 100644
index 0000000..cbbb724
--- /dev/null
+++ b/proposals/cordova-lib refactoring/PlatformApi.js
@@ -0,0 +1,201 @@
+
+/*jshint node:true, unused:false */
+
+var ConfigParser  = require('cordova-common').ConfigParser;
+var PluginInfo  = require('cordova-common').PluginInfo;
+var Requirement  = require('cordova-common').Requirement;
+
+/**
+ * Class, that acts as abstraction over particular platform. Encapsulates the
+ *   platform's properties and methods.
+ *
+ * Platform that implements own PlatformApi instance _should implement all
+ *   prototype methods_ of this class to be fully compatible with cordova-lib.
+ *
+ * The PlatformApi instance also should define the following field:
+ *
+ * * platform: String that defines a platform name.
+ */
+function PlatformApi() {}
+
+/**
+ * Installs platform to specified directory and creates a platform project.
+ *
+ * @param  {CordovaProject} cordovaProject A CordovaProject instance, that defines a
+ *   project structure and configuration, that should be applied to new platform
+ *   (contains platform's target location and ConfigParser instance for
+ *   project's config). This argument is optional and if not defined, this means
+ *   that platform is used as standalone project and is not a part of cordova
+ *   project.
+ * @param  {Object}  options  An options object. The most common options are:
+ * @param  {String}  options.customTemplate  A path to custom template, that
+ *   should override the default one from platform.
+ * @param  {Boolean}  options.link  Flag that indicates that platform's sources
+ *   will be linked to installed platform instead of copying.
+ *
+ * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
+ *   instance or rejected with CordovaError.
+ */
+PlatformApi.createPlatform = function (cordovaProject, options) {};
+
+/**
+ * Updates already installed platform.
+ *
+ * @param   {CordovaProject}  cordovaProject  A CordovaProject instance, that
+ *   defines a project structure and configuration, that should be applied to
+ *   new platform (contains platform's target location and ConfigParser instance
+ *   for project's config). This argument is optional and if not defined, this
+ *   means that platform is used as standalone project and is not a part of
+ *   cordova project.
+ * @param  {Object}  options  An options object. The most common options are:
+ * @param  {String}  options.customTemplate  A path to custom template, that
+ *   should override the default one from platform.
+ * @param  {Boolean}  options.link  Flag that indicates that platform's sources
+ *   will be linked to installed platform instead of copying.
+ *
+ * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
+ *   instance or rejected with CordovaError.
+ */
+PlatformApi.updatePlatform = function (cordovaProject, options) {};
+
+/**
+ * Gets a CordovaPlatform object, that represents the platform structure.
+ *
+ * @return  {CordovaPlatform}  A structure that contains the description of
+ *   platform's file structure and other properties of platform.
+ */
+PlatformApi.prototype.getPlatformInfo = function () {};
+
+/**
+ * Updates installed platform with provided www assets and new app
+ *   configuration. This method is required for CLI workflow and will be called
+ *   each time before build, so the changes, made to app configuration and www
+ *   code, will be applied to platform.
+ *
+ * @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a
+ *   project structure and configuration, that should be applied to platform
+ *   (contains project's www location and ConfigParser instance for project's
+ *   config).
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+PlatformApi.prototype.prepare = function (cordovaProject) {};
+
+/**
+ * Installs a new plugin into platform. This method only copies non-www files
+ *   (sources, libs, etc.) to platform. It also doesn't resolves the
+ *   dependencies of plugin. Both of handling of www files, such as assets and
+ *   js-files and resolving dependencies are the responsibility of caller.
+ *
+ * @param  {PluginInfo}  plugin  A PluginInfo instance that represents plugin
+ *   that will be installed.
+ * @param  {Object}  installOptions  An options object. Possible options below:
+ * @param  {Boolean}  installOptions.link: Flag that specifies that plugin
+ *   sources will be symlinked to app's directory instead of copying (if
+ *   possible).
+ * @param  {Object}  installOptions.variables  An object that represents
+ *   variables that will be used to install plugin. See more details on plugin
+ *   variables in documentation:
+ *   https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+PlatformApi.prototype.addPlugin = function (plugin, installOptions) {};
+
+/**
+ * Removes an installed plugin from platform.
+ *
+ * Since method accepts PluginInfo instance as input parameter instead of plugin
+ *   id, caller shoud take care of managing/storing PluginInfo instances for
+ *   future uninstalls.
+ *
+ * @param  {PluginInfo}  plugin  A PluginInfo instance that represents plugin
+ *   that will be installed.
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError instance.
+ */
+PlatformApi.prototype.removePlugin = function (plugin) {};
+
+/**
+ * Builds an application package for current platform.
+ *
+ * @param  {Object}  buildOptions  A build options. This object's structure is
+ *   highly depends on platform's specific. The most common options are:
+ * @param  {Boolean}  buildOptions.debug  Indicates that packages should be
+ *   built with debug configuration. This is set to true by default unless the
+ *   'release' option is not specified.
+ * @param  {Boolean}  buildOptions.release  Indicates that packages should be
+ *   built with release configuration. If not set to true, debug configuration
+ *   will be used.
+ * @param   {Boolean}  buildOptions.device  Specifies that built app is intended
+ *   to run on device
+ * @param   {Boolean}  buildOptions.emulator: Specifies that built app is
+ *   intended to run on emulator
+ * @param   {String}  buildOptions.target  Specifies the device id that will be
+ *   used to run built application.
+ * @param   {Boolean}  buildOptions.nobuild  Indicates that this should be a
+ *   dry-run call, so no build artifacts will be produced.
+ * @param   {String[]}  buildOptions.archs  Specifies chip architectures which
+ *   app packages should be built for. List of valid architectures is depends on
+ *   platform.
+ * @param   {String}  buildOptions.buildConfig  The path to build configuration
+ *   file. The format of this file is depends on platform.
+ * @param   {String[]} buildOptions.argv Raw array of command-line arguments,
+ *   passed to `build` command. The purpose of this property is to pass a
+ *   platform-specific arguments, and eventually let platform define own
+ *   arguments processing logic.
+ *
+ * @return {Promise<Object[]>} A promise either fulfilled with an array of build
+ *   artifacts (application packages) if package was built successfully,
+ *   or rejected with CordovaError. The resultant build artifact objects is not
+ *   strictly typed and may conatin arbitrary set of fields as in sample below.
+ *
+ * ```
+ * {
+ *   architecture: 'x86',
+ *   buildType: 'debug',
+ *   path: '/path/to/build',
+ *   type: 'app'
+ * }
+ * ```
+ *
+ * The return value in most cases will contain only one item but in some cases
+ *   there could be multiple items in output array, e.g. when multiple
+ *   arhcitectures is specified.
+ */
+PlatformApi.prototype.build = function(buildOptions) {};
+
+/**
+ * Builds an application package for current platform and runs it on
+ *   specified/default device. If no 'device'/'emulator'/'target' options are
+ *   specified, then tries to run app on default device if connected, otherwise
+ *   runs the app on emulator.
+ *
+ * @param   {Object}  runOptions  An options object. The structure is the same
+ *   as for build options.
+ *
+ * @return {Promise} A promise either fulfilled if package was built and ran
+ *   successfully, or rejected with CordovaError.
+ */
+PlatformApi.prototype.run = function(runOptions) {};
+
+/**
+ * Cleans out the build artifacts from platform's directory.
+ *
+ * @return  {Promise}  Return a promise either fulfilled, or rejected with
+ *   CordovaError.
+ */
+PlatformApi.prototype.clean = function() {};
+
+/**
+ * Performs a requirements check for current platform. Each platform defines its
+ *   own set of requirements, which should be resolved before platform can be
+ *   built successfully.
+ *
+ * @return  {Promise<Requirement[]>}  Promise, resolved with set of Requirement
+ *   objects for current platform.
+ */
+PlatformApi.prototype.requirements = function() {};
diff --git a/proposals/cordova-lib refactoring/ProjectApi.js b/proposals/cordova-lib refactoring/ProjectApi.js
new file mode 100644
index 0000000..06a1f65
--- /dev/null
+++ b/proposals/cordova-lib refactoring/ProjectApi.js
@@ -0,0 +1,281 @@
+
+/*jshint node:true, unused:false */
+
+/**
+ * @class Class, that acts as abstract on top of Cordova project. Encapsulates the
+ *   basic properties, that represents project configuration and methods for
+ *   managing the project.
+ */
+function ProjectApi () {}
+
+/**
+ * Gets a ProjectApi instance for specified directory.
+ *
+ * @param   {String}  projectDir  Path to cordova project.
+ *
+ * @return  {Promise<ProjectApi>}  Returns a promise either fulfilled with a
+ *   Cordova project instance or rejected with CordovaError.
+ */
+ProjectApi.getProjectAt = function (projectDir) {};
+
+/**
+ * Initializes an empty cordova project at specified directory. Copies
+ *
+ * @param  {String} targetDir Path to directory, where new project will be
+ *   created.
+ * @param  {String} [appName = 'HelloCordova']   Application name, that will be
+ *   used for '<name>' element in config.xml. If not specified, 'HelloCordova'
+ *   will be used.
+ * @param  {String} [appId = 'io.cordova.hellocordova']     Application id in
+ *   form of reverse domain style identifier, that will be used for 'id'
+ *   attribute of '<widget>' element. If not specified 'io.cordova.hellocordova'
+ *   will be used.
+ * @param  {Object} [options]   An options object. The most common options are:
+ * @param  {String} options.wwwSource  Specifies the www assets source for new
+ *   application instead of default one. If not specified, the Cordova
+ *   HelloWorld assets will be used.
+ * @param  {Boolean}  options.link  Specifies that www source will be symlinked
+ *   to app's directory instead of copying.
+ *
+ * @return {Promise<ProjectApi>} Returns a promise either fulfilled with a
+ *   Cordova project instance or rejected with CordovaError.
+ */
+ProjectApi.createProject = function (targetDir, appName, appId, options) {};
+
+/**
+ * Gets a ProjectInfo structure that describes the project.
+ *
+ * @return  {CordovaProject}  A CordovaProject object.
+ */
+ProjectApi.prototype.getProjectInfo = function () {};
+
+/**
+ * Adds a new platform to project.
+ *
+ * @param  {String}  platformSpec  A platform spec that should be one of
+ *   following:
+ *
+ * - valid platform name: 'android', 'windows', etc.
+ * - valid npm identifier, that resolves to valid platform: cordova-android@4.0
+ * - git url, that points to repo with valid platform:
+ *       http://github.com/apache/cordova-android.git#4.0.0
+ * - path to local repo of valid platform:
+ *     /my/cordova/repositories/cordova-android
+ *
+ * @param {Object}  [options] The options object. Supported properties:
+ * @param {Boolean} [options.saveToProject = false]  Flag that indicates, that added platform
+ *   should be saved into project configuration to be easily restored after. The
+ *   approach is similar to 'npm install --save' command.
+ *
+ * @return {Promise} A promise either fulfilled if platform is installed
+ *   successfully, or rejected with CordovaError.
+ */
+ProjectApi.prototype.addPlatform = function (platformSpec, options) {};
+
+/**
+ * Removes a platform from project.
+ *
+ * @param  {String}  platformName  A name of platform that should be removed
+ *   from project.
+ * @param {Object}   [options] The options object. Supported properties:
+ * @param {Boolean}  [options.saveToProject = false]  Flag that indicates, that
+ *   platform also should be removed from project configuration.
+ *
+ * @return {Promise} A promise either fulfilled if platform is removed
+ *   successfully, or rejected with CordovaError.
+ */
+ProjectApi.prototype.removePlatform = function (platformName, options) {};
+
+/**
+ * Adds a new plugin into project. Installs it to each platform in project.
+ *
+ * @param  {String}  pluginSpec  A plugin spec that should be one of following:
+ *
+ *   - valid plugin id that can be resolved through either cordova
+ *   plugin registry or npm:
+ *       'org.apache.cordova.globalization', 'cordova-plugin-globalization'
+ *   - valid npm identifier, that resolves to valid plugin:
+ *       cordova-plugin-globalization@1.0.0
+ *   - git url, that points to repo with valid plugin:
+ *       http://github.com/apache/cordova-plugin-globalization.git#r1.0.0
+ *   - path to local repo of valid plugin:
+ *       /my/cordova/repositories/cordova-plugin-globalization
+ *
+ * @param  {Object}  [options]    An options object. Possible options are:
+ * @param  {Boolean} saveToProject Flag that indicates, that added plugin should
+ *   be saved into project configuration.
+ * @param  {Boolean} link       Flag that specifies that plugin sources will be
+ *   symlinked to app's directory instead of copying if possible.
+ * @param  {String}  searchPath Valid path, that will be used to search for
+ *   plugin in local filesystem.
+ * @param  {Object}  variables  An object that represents variables that will be
+ *   used to install plugin. See more details on plugin variables in
+ *   documentation:
+ *   https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html
+ *
+ * @return {Promise} A promise either fulfilled if plugin is installed
+ *   successfully, or rejected with CordovaError.
+ */
+ProjectApi.prototype.addPlugin = function (pluginSpec, options) {};
+
+/**
+ * Removes a plugin from project.
+ *
+ * @param  {String}  pluginId  An id of plugin that should be removed from
+ *   project.
+ * @param {Object} [options] The options object. Supported properties:
+ * @param {Boolean}  options.saveToProject  Flag that indicates, that plugin
+ *   also should be removed from project configuration.
+ *
+ * @return {Promise} A promise either fulfilled if platform is removed
+ *   successfully, or rejected with CordovaError.
+ */
+ProjectApi.prototype.removePlugin = function (pluginId, options) {};
+
+/**
+ * Gets all platforms, installed into project.
+ *
+ * @return  {PlatformApi[]}  An array of PlatformApi instances.
+ */
+ProjectApi.prototype.getPlatforms = function () {};
+
+/**
+ * Gets a platform by name
+ *
+ * @param   {String}  platformName  The platform name.
+ *
+ * @return  {PlatformApi}  PlatformApi instance for specified platform.
+ */
+ProjectApi.prototype.getPlatform = function (platformName) {};
+
+/**
+ * Gets all the plugins, installed into project.
+ *
+ * @return  {Array<PluginInfo>}  An array of PluginInfo instances.
+ */
+ProjectApi.prototype.getPlugins = function () {};
+
+/**
+ * Gets plugins, specified by id.
+ *
+ * @return  {PluginInfo}  A PluginInfo instance for specified plugin.
+ */
+ProjectApi.prototype.getPlugin = function (pluginId) {};
+
+/**
+ * Prepares a project for building specified platform/platforms. The prepare
+ *   step is need to be performed to update configuration and www assets for
+ *   each platform from application's ones before the application will be built.
+ *   The prepare step isn't required if no configuration changes or www assets
+ *   changes was made.
+ *
+ * @param   {String|String[]}  [platform]  Single platform or array of platform
+ *   names, that needs to be prepared. If omitted, all platform, added to
+ *   project will be prepared.
+ * @param   {Object}  [prepareOptions]  An options object with following fields:
+ * @param   {Boolean} prepareOptions.browserify Specifies that project should be
+ *   prepared with 'browserify' flow to embed all plugins' JS files and cordova
+ *   JS sources into one single file.
+ *
+ * @return  {Promise}  A promise either fulfilled, if platform/platforms
+ *   prepared successfully, or rejected with CordovaError otherwise.
+ */
+ProjectApi.prototype.prepare = function (platform, prepareOptions) {};
+
+/**
+ * Builds an application package for specified platform/platforms.
+ *
+ * @param   {String|String[]}  [platform]  A list of platform names/single name.
+ *   If not specified, builds packages for all platforms, installed into
+ *   project.
+ *
+ * @param  {Object}  [buildOptions]  A build options. This object's structure is
+ *   highly depends on platform's specific. The most common options are:
+ * @param  {Boolean}  buildOptions.debug  Indicates that packages should be
+ *   built with debug configuration. This is set to true by default unless the
+ *   'release' option is not specified.
+ * @param  {Boolean}  buildOptions.release  Indicates that packages should be
+ *   built with release configuration. If not set to true, debug configuration
+ *   will be used.
+ * @param   {Boolean}  buildOptions.device  Specifies that built app is intended
+ *   to run on device
+ * @param   {Boolean}  buildOptions.emulator: Specifies that built app is
+ *   intended to run on emulator
+ * @param   {String}  buildOptions.target  Specifies the device id that will be
+ *   used to run built application.
+ * @param   {Boolean}  buildOptions.nobuild  Indicates that this should be a
+ *   dry-run call, so no build artifacts will be produced.
+ * @param   {String[]}  buildOptions.archs  Specifies chip architectures which
+ *   app packages should be built for. List of valid architectures is depends on
+ *   platform.
+ * @param   {String}  buildOptions.buildConfig  The path to build configuration
+ *   file. The format of this file is depends on platform.
+ * @param   {String[]} buildOptions.argv Raw array of command-line arguments,
+ *   passed to `build` command. The purpose of this property is to pass a
+ *   platform-specific arguments, and eventually let platform define own
+ *   arguments processing logic.
+ *
+ * @return {Promise<Object>} A promise either fulfilled with an array of build
+ *   artifacts for each platform, if package was built successfully, or rejected
+ *   with CordovaError. The keys of resultant object is a platform names, and
+ *   values - arrays of build artifact objects. The structure of build artifacts
+ *   is descriped in PlatformApi reference.
+ */
+ProjectApi.prototype.build = function (platform, buildOptions) {};
+
+/**
+ * Builds and runs an application package for specified platform on specified
+ *   device/emulator.
+ *
+ * @param   {String|String[]}  [platform]  A list of platform names/single name.
+ *   If omitted, method runs packages for all platforms, installed into project.
+ * @param   {Object}  [runOptions]  An options object. The structure is the same
+ *   as for build options.
+ *
+ * @return {Promise} A promise either fulfilled if application ran successfully,
+ *   or rejected with CordovaError.
+ */
+ProjectApi.prototype.run = function (platform, runOptions) {};
+
+/**
+ * Runs an application on a local web-server and launches a browser to display
+ *   application content.
+ *
+ * @param   {String}  [platform]      A platform to run server for.
+ * @param   {Object}  [serveOptions]  A set of options to pass to serve command.
+ *   Available options are:
+ * @param   {Number}  serveOptions.port  A port to bind server to.
+ * @param   {String}  serveOptions.target  A browser name. Available targets
+ *   depends on platform. Most common are: 'chrome', 'safari', 'opera', 'firefox'.s
+ *
+ * @return  {Promise}  A promise either fulfilled, if server ran successfully,
+ *   or rejected with CordovaError otherwise.
+ */
+ProjectApi.prototype.serve = function (platform, serveOptions) {};
+
+/**
+ * Cleans out the build artifacts for specified platform.
+ *
+ * @param   {String|String[]}  [platform]  A list of platform names/single
+ *   platform, which needs to be cleaned. If not specified, run clean for all
+ *   platforms, installed into project.
+ * @param   {Object}  [cleanOptions]  An options object. The structure is not
+ *   defined explicitly, so it can be used to pass some platfom specific vaues
+ *   to platform.
+ *
+ * @return {Promise} A promise either fulfilled or rejected with CordovaError.
+ */
+ProjectApi.prototype.clean = function(platform, cleanOptions) {};
+
+/**
+ * Performs a requirements check for each platforms installed. Each platform
+ *   defines its own set of requirements, which should be resolved before
+ *   platform can be built successfully.
+ *
+ * @param   {String|String[]}  [platform]  A list of platform names/single
+ *   platform, which requirements needs to be checked for.
+ *
+ * @return  {Promise<Requirement[]>}  Promise resolved with set of Requirement
+ *   objects for each platform.
+ */
+ProjectApi.prototype.requirements = function(platform) {};