refactor: use es6 class (#911)

Refactored to Classes:
* Api
* AndroidManifest
* AndroidProject
This commit is contained in:
Sukant Pal 2020-02-01 03:34:51 -05:00 committed by GitHub
parent de105e8651
commit c56cd4d5a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 540 additions and 535 deletions

View File

@ -51,8 +51,10 @@ function setupEvents (externalEventEmitter) {
* The PlatformApi instance also should define the following field:
*
* * platform: String that defines a platform name.
* @class Api
*/
function Api (platform, platformRootDir, events) {
class Api {
constructor (platform, platformRootDir, events) {
this.platform = PLATFORM;
this.root = path.resolve(__dirname, '..');
@ -73,77 +75,15 @@ function Api (platform, platformRootDir, events) {
build: path.join(this.root, 'build'),
javaSrc: path.join(appMain, 'java')
};
}
/**
* Installs platform to specified directory and creates a platform project.
*
* @param {String} destination Destination directory, where insatll platform to
* @param {ConfigParser} [config] ConfgiParser instance, used to retrieve
* project creation options, such as package id and project name.
* @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.
* @param {EventEmitter} [events] An EventEmitter instance that will be used for
* logging purposes. If no EventEmitter provided, all events will be logged to
* console
*
* @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
* instance or rejected with CordovaError.
*/
Api.createPlatform = function (destination, config, options, events) {
events = setupEvents(events);
var result;
try {
result = require('../../lib/create').create(destination, config, options, events).then(function (destination) {
return new Api(PLATFORM, destination, events);
});
} catch (e) {
events.emit('error', 'createPlatform is not callable from the android project API.');
throw (e);
}
return result;
};
/**
* Updates already installed platform.
*
* @param {String} destination Destination directory, where platform installed
* @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.
* @param {EventEmitter} [events] An EventEmitter instance that will be used for
* logging purposes. If no EventEmitter provided, all events will be logged to
* console
*
* @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
* instance or rejected with CordovaError.
*/
Api.updatePlatform = function (destination, options, events) {
events = setupEvents(events);
var result;
try {
result = require('../../lib/create').update(destination, options, events).then(function (destination) {
return new Api(PLATFORM, destination, events);
});
} catch (e) {
events.emit('error', 'updatePlatform is not callable from the android project API, you will need to do this manually.');
throw (e);
}
return result;
};
/**
/**
* 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.
*/
Api.prototype.getPlatformInfo = function () {
getPlatformInfo () {
var result = {};
result.locations = this.locations;
result.root = this.root;
@ -152,9 +92,9 @@ Api.prototype.getPlatformInfo = function () {
result.projectConfig = this._config;
return result;
};
}
/**
/**
* 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
@ -168,13 +108,13 @@ Api.prototype.getPlatformInfo = function () {
* @return {Promise} Return a promise either fulfilled, or rejected with
* CordovaError instance.
*/
Api.prototype.prepare = function (cordovaProject, prepareOptions) {
prepare (cordovaProject, prepareOptions) {
cordovaProject.projectConfig = new ConfigParser(cordovaProject.locations.rootConfigXml || cordovaProject.projectConfig.path);
return require('./lib/prepare').prepare.call(this, cordovaProject, prepareOptions);
};
}
/**
/**
* 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
@ -194,7 +134,7 @@ Api.prototype.prepare = function (cordovaProject, prepareOptions) {
* @return {Promise} Return a promise either fulfilled, or rejected with
* CordovaError instance.
*/
Api.prototype.addPlugin = function (plugin, installOptions) {
addPlugin (plugin, installOptions) {
var project = AndroidProject.getProjectFile(this.root);
var self = this;
@ -215,9 +155,9 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
}.bind(this))
// CB-11022 Return truthy value to prevent running prepare after
.then(() => true);
};
}
/**
/**
* Removes an installed plugin from platform.
*
* Since method accepts PluginInfo instance as input parameter instead of plugin
@ -230,7 +170,7 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
* @return {Promise} Return a promise either fulfilled, or rejected with
* CordovaError instance.
*/
Api.prototype.removePlugin = function (plugin, uninstallOptions) {
removePlugin (plugin, uninstallOptions) {
var project = AndroidProject.getProjectFile(this.root);
if (uninstallOptions && uninstallOptions.usePlatformWww === true) {
@ -247,9 +187,9 @@ Api.prototype.removePlugin = function (plugin, uninstallOptions) {
}.bind(this))
// CB-11022 Return truthy value to prevent running prepare after
.then(() => true);
};
}
/**
/**
* Builds an application package for current platform.
*
* @param {Object} buildOptions A build options. This object's structure is
@ -294,7 +234,7 @@ Api.prototype.removePlugin = function (plugin, uninstallOptions) {
* there could be multiple items in output array, e.g. when multiple
* arhcitectures is specified.
*/
Api.prototype.build = function (buildOptions) {
build (buildOptions) {
var self = this;
return require('./lib/check_reqs').run().then(function () {
@ -310,9 +250,9 @@ Api.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
@ -324,21 +264,21 @@ Api.prototype.build = function (buildOptions) {
* @return {Promise} A promise either fulfilled if package was built and ran
* successfully, or rejected with CordovaError.
*/
Api.prototype.run = function (runOptions) {
run (runOptions) {
var self = this;
return require('./lib/check_reqs').run().then(function () {
return require('./lib/run').run.call(self, runOptions);
});
};
}
/**
/**
* Cleans out the build artifacts from platform's directory, and also
* cleans out the platform www directory if called without options specified.
*
* @return {Promise} Return a promise either fulfilled, or rejected with
* CordovaError.
*/
Api.prototype.clean = function (cleanOptions) {
clean (cleanOptions) {
var self = this;
// This will lint, checking for null won't
if (typeof cleanOptions === 'undefined') {
@ -350,9 +290,9 @@ Api.prototype.clean = function (cleanOptions) {
}).then(function () {
return require('./lib/prepare').clean.call(self, cleanOptions);
});
};
}
/**
/**
* 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.
@ -360,8 +300,71 @@ Api.prototype.clean = function (cleanOptions) {
* @return {Promise<Requirement[]>} Promise, resolved with set of Requirement
* objects for current platform.
*/
Api.prototype.requirements = function () {
requirements () {
return require('./lib/check_reqs').check_all();
};
}
/**
* Installs platform to specified directory and creates a platform project.
*
* @param {String} destination Destination directory, where insatll platform to
* @param {ConfigParser} [config] ConfgiParser instance, used to retrieve
* project creation options, such as package id and project name.
* @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.
* @param {EventEmitter} [events] An EventEmitter instance that will be used for
* logging purposes. If no EventEmitter provided, all events will be logged to
* console
*
* @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
* instance or rejected with CordovaError.
*/
static createPlatform (destination, config, options, events) {
events = setupEvents(events);
var result;
try {
result = require('../../lib/create').create(destination, config, options, events).then(function (destination) {
return new Api(PLATFORM, destination, events);
});
} catch (e) {
events.emit('error', 'createPlatform is not callable from the android project API.');
throw (e);
}
return result;
}
/**
* Updates already installed platform.
*
* @param {String} destination Destination directory, where platform installed
* @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.
* @param {EventEmitter} [events] An EventEmitter instance that will be used for
* logging purposes. If no EventEmitter provided, all events will be logged to
* console
*
* @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
* instance or rejected with CordovaError.
*/
static updatePlatform (destination, options, events) {
events = setupEvents(events);
var result;
try {
result = require('../../lib/create').update(destination, options, events).then(function (destination) {
return new Api(PLATFORM, destination, events);
});
} catch (e) {
events.emit('error', 'updatePlatform is not callable from the android project API, you will need to do this manually.');
throw (e);
}
return result;
}
}
module.exports = Api;

View File

@ -23,42 +23,43 @@ var xml = require('cordova-common').xmlHelpers;
var DEFAULT_ORIENTATION = 'default';
/** Wraps an AndroidManifest file */
function AndroidManifest (path) {
class AndroidManifest {
constructor (path) {
this.path = path;
this.doc = xml.parseElementtreeSync(path);
if (this.doc.getroot().tag !== 'manifest') {
throw new Error('AndroidManifest at ' + path + ' has incorrect root node name (expected "manifest")');
}
}
}
AndroidManifest.prototype.getVersionName = function () {
getVersionName () {
return this.doc.getroot().attrib['android:versionName'];
};
}
AndroidManifest.prototype.setVersionName = function (versionName) {
setVersionName (versionName) {
this.doc.getroot().attrib['android:versionName'] = versionName;
return this;
};
}
AndroidManifest.prototype.getVersionCode = function () {
getVersionCode () {
return this.doc.getroot().attrib['android:versionCode'];
};
}
AndroidManifest.prototype.setVersionCode = function (versionCode) {
setVersionCode (versionCode) {
this.doc.getroot().attrib['android:versionCode'] = versionCode;
return this;
};
}
AndroidManifest.prototype.getPackageId = function () {
getPackageId () {
return this.doc.getroot().attrib['package'];
};
}
AndroidManifest.prototype.setPackageId = function (pkgId) {
setPackageId (pkgId) {
this.doc.getroot().attrib['package'] = pkgId;
return this;
};
}
AndroidManifest.prototype.getActivity = function () {
getActivity () {
var activity = this.doc.getroot().find('./application/activity');
return {
getName: function () {
@ -95,13 +96,13 @@ AndroidManifest.prototype.getActivity = function () {
return this;
}
};
};
}
AndroidManifest.prototype.getDebuggable = function () {
getDebuggable () {
return this.doc.getroot().find('./application').attrib['android:debuggable'] === 'true';
};
}
AndroidManifest.prototype.setDebuggable = function (value) {
setDebuggable (value) {
var application = this.doc.getroot().find('./application');
if (value) {
application.attrib['android:debuggable'] = 'true';
@ -110,17 +111,18 @@ AndroidManifest.prototype.setDebuggable = function (value) {
delete application.attrib['android:debuggable'];
}
return this;
};
}
/**
/**
* Writes manifest to disk syncronously. If filename is specified, then manifest
* will be written to that file
*
* @param {String} [destPath] File to write manifest to. If omitted,
* manifest will be written to file it has been read from.
*/
AndroidManifest.prototype.write = function (destPath) {
write (destPath) {
fs.writeFileSync(destPath || this.path, this.doc.write({ indent: 4 }), 'utf-8');
};
}
}
module.exports = AndroidManifest;

View File

@ -55,44 +55,28 @@ function getRelativeLibraryPath (parentDir, subDir) {
return (path.sep === '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
}
function AndroidProject (projectDir) {
class AndroidProject {
constructor (projectDir) {
this._propertiesEditors = {};
this._subProjectDirs = {};
this._dirty = false;
this.projectDir = projectDir;
this.platformWww = path.join(this.projectDir, 'platform_www');
this.www = path.join(this.projectDir, 'app/src/main/assets/www');
}
AndroidProject.getProjectFile = function (projectDir) {
if (!projectFileCache[projectDir]) {
projectFileCache[projectDir] = new AndroidProject(projectDir);
}
return projectFileCache[projectDir];
};
AndroidProject.purgeCache = function (projectDir) {
if (projectDir) {
delete projectFileCache[projectDir];
} else {
projectFileCache = {};
}
};
/**
/**
* Reads the package name out of the Android Manifest file
*
* @param {String} projectDir The absolute path to the directory containing the project
*
* @return {String} The name of the package
*/
AndroidProject.prototype.getPackageName = function () {
getPackageName () {
var manifestPath = path.join(this.projectDir, 'app/src/main/AndroidManifest.xml');
return new AndroidManifest(manifestPath).getPackageId();
};
}
AndroidProject.prototype.getCustomSubprojectRelativeDir = function (plugin_id, src) {
getCustomSubprojectRelativeDir (plugin_id, src) {
// All custom subprojects are prefixed with the last portion of the package id.
// This is to avoid collisions when opening multiple projects in Eclipse that have subprojects with the same name.
var packageName = this.getPackageName();
@ -100,9 +84,9 @@ AndroidProject.prototype.getCustomSubprojectRelativeDir = function (plugin_id, s
var prefix = packageName.substring(lastDotIndex + 1);
var subRelativeDir = path.join(plugin_id, prefix + '-' + path.basename(src));
return subRelativeDir;
};
}
AndroidProject.prototype.addSubProject = function (parentDir, subDir) {
addSubProject (parentDir, subDir) {
var parentProjectFile = path.resolve(parentDir, 'project.properties');
var subProjectFile = path.resolve(subDir, 'project.properties');
var parentProperties = this._getPropertiesFile(parentProjectFile);
@ -116,45 +100,45 @@ AndroidProject.prototype.addSubProject = function (parentDir, subDir) {
addToPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir));
this._dirty = true;
};
}
AndroidProject.prototype.removeSubProject = function (parentDir, subDir) {
removeSubProject (parentDir, subDir) {
var parentProjectFile = path.resolve(parentDir, 'project.properties');
var parentProperties = this._getPropertiesFile(parentProjectFile);
removeFromPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir));
delete this._subProjectDirs[subDir];
this._dirty = true;
};
}
AndroidProject.prototype.addGradleReference = function (parentDir, subDir) {
addGradleReference (parentDir, subDir) {
var parentProjectFile = path.resolve(parentDir, 'project.properties');
var parentProperties = this._getPropertiesFile(parentProjectFile);
addToPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir));
this._dirty = true;
};
}
AndroidProject.prototype.removeGradleReference = function (parentDir, subDir) {
removeGradleReference (parentDir, subDir) {
var parentProjectFile = path.resolve(parentDir, 'project.properties');
var parentProperties = this._getPropertiesFile(parentProjectFile);
removeFromPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir));
this._dirty = true;
};
}
AndroidProject.prototype.addSystemLibrary = function (parentDir, value) {
addSystemLibrary (parentDir, value) {
var parentProjectFile = path.resolve(parentDir, 'project.properties');
var parentProperties = this._getPropertiesFile(parentProjectFile);
addToPropertyList(parentProperties, 'cordova.system.library', value);
this._dirty = true;
};
}
AndroidProject.prototype.removeSystemLibrary = function (parentDir, value) {
removeSystemLibrary (parentDir, value) {
var parentProjectFile = path.resolve(parentDir, 'project.properties');
var parentProperties = this._getPropertiesFile(parentProjectFile);
removeFromPropertyList(parentProperties, 'cordova.system.library', value);
this._dirty = true;
};
}
AndroidProject.prototype.write = function () {
write () {
if (!this._dirty) {
return;
}
@ -167,9 +151,26 @@ AndroidProject.prototype.write = function () {
editor.dirty = false;
}
}
};
}
AndroidProject.prototype._getPropertiesFile = function (filename) {
getInstaller (type) {
return pluginHandlers.getInstaller(type);
}
getUninstaller (type) {
return pluginHandlers.getUninstaller(type);
}
/*
* This checks if an Android project is clean or has old build artifacts
*/
isClean () {
var build_path = path.join(this.projectDir, 'build');
// If the build directory doesn't exist, it's clean
return !(fs.existsSync(build_path));
}
_getPropertiesFile (filename) {
if (!this._propertiesEditors[filename]) {
if (fs.existsSync(filename)) {
this._propertiesEditors[filename] = properties_parser.createEditor(filename);
@ -179,24 +180,23 @@ AndroidProject.prototype._getPropertiesFile = function (filename) {
}
return this._propertiesEditors[filename];
};
}
AndroidProject.prototype.getInstaller = function (type) {
return pluginHandlers.getInstaller(type);
};
static getProjectFile (projectDir) {
if (!projectFileCache[projectDir]) {
projectFileCache[projectDir] = new AndroidProject(projectDir);
}
AndroidProject.prototype.getUninstaller = function (type) {
return pluginHandlers.getUninstaller(type);
};
return projectFileCache[projectDir];
}
/*
* This checks if an Android project is clean or has old build artifacts
*/
AndroidProject.prototype.isClean = function () {
var build_path = path.join(this.projectDir, 'build');
// If the build directory doesn't exist, it's clean
return !(fs.existsSync(build_path));
};
static purgeCache (projectDir) {
if (projectDir) {
delete projectFileCache[projectDir];
} else {
projectFileCache = {};
}
}
}
module.exports = AndroidProject;