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: * The PlatformApi instance also should define the following field:
* *
* * platform: String that defines a platform name. * * platform: String that defines a platform name.
* @class Api
*/ */
function Api (platform, platformRootDir, events) { class Api {
constructor (platform, platformRootDir, events) {
this.platform = PLATFORM; this.platform = PLATFORM;
this.root = path.resolve(__dirname, '..'); this.root = path.resolve(__dirname, '..');
@ -75,75 +77,13 @@ function Api (platform, platformRootDir, events) {
}; };
} }
/**
* 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. * Gets a CordovaPlatform object, that represents the platform structure.
* *
* @return {CordovaPlatform} A structure that contains the description of * @return {CordovaPlatform} A structure that contains the description of
* platform's file structure and other properties of platform. * platform's file structure and other properties of platform.
*/ */
Api.prototype.getPlatformInfo = function () { getPlatformInfo () {
var result = {}; var result = {};
result.locations = this.locations; result.locations = this.locations;
result.root = this.root; result.root = this.root;
@ -152,7 +92,7 @@ Api.prototype.getPlatformInfo = function () {
result.projectConfig = this._config; result.projectConfig = this._config;
return result; return result;
}; }
/** /**
* Updates installed platform with provided www assets and new app * Updates installed platform with provided www assets and new app
@ -168,11 +108,11 @@ Api.prototype.getPlatformInfo = function () {
* @return {Promise} Return a promise either fulfilled, or rejected with * @return {Promise} Return a promise either fulfilled, or rejected with
* CordovaError instance. * CordovaError instance.
*/ */
Api.prototype.prepare = function (cordovaProject, prepareOptions) { prepare (cordovaProject, prepareOptions) {
cordovaProject.projectConfig = new ConfigParser(cordovaProject.locations.rootConfigXml || cordovaProject.projectConfig.path); cordovaProject.projectConfig = new ConfigParser(cordovaProject.locations.rootConfigXml || cordovaProject.projectConfig.path);
return require('./lib/prepare').prepare.call(this, cordovaProject, prepareOptions); return require('./lib/prepare').prepare.call(this, cordovaProject, prepareOptions);
}; }
/** /**
* Installs a new plugin into platform. This method only copies non-www files * Installs a new plugin into platform. This method only copies non-www files
@ -194,7 +134,7 @@ Api.prototype.prepare = function (cordovaProject, prepareOptions) {
* @return {Promise} Return a promise either fulfilled, or rejected with * @return {Promise} Return a promise either fulfilled, or rejected with
* CordovaError instance. * CordovaError instance.
*/ */
Api.prototype.addPlugin = function (plugin, installOptions) { addPlugin (plugin, installOptions) {
var project = AndroidProject.getProjectFile(this.root); var project = AndroidProject.getProjectFile(this.root);
var self = this; var self = this;
@ -215,7 +155,7 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
}.bind(this)) }.bind(this))
// CB-11022 Return truthy value to prevent running prepare after // CB-11022 Return truthy value to prevent running prepare after
.then(() => true); .then(() => true);
}; }
/** /**
* Removes an installed plugin from platform. * Removes an installed plugin from platform.
@ -230,7 +170,7 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
* @return {Promise} Return a promise either fulfilled, or rejected with * @return {Promise} Return a promise either fulfilled, or rejected with
* CordovaError instance. * CordovaError instance.
*/ */
Api.prototype.removePlugin = function (plugin, uninstallOptions) { removePlugin (plugin, uninstallOptions) {
var project = AndroidProject.getProjectFile(this.root); var project = AndroidProject.getProjectFile(this.root);
if (uninstallOptions && uninstallOptions.usePlatformWww === true) { if (uninstallOptions && uninstallOptions.usePlatformWww === true) {
@ -247,7 +187,7 @@ Api.prototype.removePlugin = function (plugin, uninstallOptions) {
}.bind(this)) }.bind(this))
// CB-11022 Return truthy value to prevent running prepare after // CB-11022 Return truthy value to prevent running prepare after
.then(() => true); .then(() => true);
}; }
/** /**
* Builds an application package for current platform. * Builds an application package for current platform.
@ -294,7 +234,7 @@ Api.prototype.removePlugin = function (plugin, uninstallOptions) {
* there could be multiple items in output array, e.g. when multiple * there could be multiple items in output array, e.g. when multiple
* arhcitectures is specified. * arhcitectures is specified.
*/ */
Api.prototype.build = function (buildOptions) { build (buildOptions) {
var self = this; var self = this;
return require('./lib/check_reqs').run().then(function () { return require('./lib/check_reqs').run().then(function () {
@ -310,7 +250,7 @@ Api.prototype.build = function (buildOptions) {
}; };
}); });
}); });
}; }
/** /**
* Builds an application package for current platform and runs it on * Builds an application package for current platform and runs it on
@ -324,12 +264,12 @@ Api.prototype.build = function (buildOptions) {
* @return {Promise} A promise either fulfilled if package was built and ran * @return {Promise} A promise either fulfilled if package was built and ran
* successfully, or rejected with CordovaError. * successfully, or rejected with CordovaError.
*/ */
Api.prototype.run = function (runOptions) { run (runOptions) {
var self = this; var self = this;
return require('./lib/check_reqs').run().then(function () { return require('./lib/check_reqs').run().then(function () {
return require('./lib/run').run.call(self, runOptions); return require('./lib/run').run.call(self, runOptions);
}); });
}; }
/** /**
* Cleans out the build artifacts from platform's directory, and also * Cleans out the build artifacts from platform's directory, and also
@ -338,7 +278,7 @@ Api.prototype.run = function (runOptions) {
* @return {Promise} Return a promise either fulfilled, or rejected with * @return {Promise} Return a promise either fulfilled, or rejected with
* CordovaError. * CordovaError.
*/ */
Api.prototype.clean = function (cleanOptions) { clean (cleanOptions) {
var self = this; var self = this;
// This will lint, checking for null won't // This will lint, checking for null won't
if (typeof cleanOptions === 'undefined') { if (typeof cleanOptions === 'undefined') {
@ -350,7 +290,7 @@ Api.prototype.clean = function (cleanOptions) {
}).then(function () { }).then(function () {
return require('./lib/prepare').clean.call(self, cleanOptions); return require('./lib/prepare').clean.call(self, cleanOptions);
}); });
}; }
/** /**
* Performs a requirements check for current platform. Each platform defines its * Performs a requirements check for current platform. Each platform defines its
@ -360,8 +300,71 @@ Api.prototype.clean = function (cleanOptions) {
* @return {Promise<Requirement[]>} Promise, resolved with set of Requirement * @return {Promise<Requirement[]>} Promise, resolved with set of Requirement
* objects for current platform. * objects for current platform.
*/ */
Api.prototype.requirements = function () { requirements () {
return require('./lib/check_reqs').check_all(); 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; module.exports = Api;

View File

@ -23,7 +23,8 @@ var xml = require('cordova-common').xmlHelpers;
var DEFAULT_ORIENTATION = 'default'; var DEFAULT_ORIENTATION = 'default';
/** Wraps an AndroidManifest file */ /** Wraps an AndroidManifest file */
function AndroidManifest (path) { class AndroidManifest {
constructor (path) {
this.path = path; this.path = path;
this.doc = xml.parseElementtreeSync(path); this.doc = xml.parseElementtreeSync(path);
if (this.doc.getroot().tag !== 'manifest') { if (this.doc.getroot().tag !== 'manifest') {
@ -31,34 +32,34 @@ function AndroidManifest (path) {
} }
} }
AndroidManifest.prototype.getVersionName = function () { getVersionName () {
return this.doc.getroot().attrib['android:versionName']; return this.doc.getroot().attrib['android:versionName'];
}; }
AndroidManifest.prototype.setVersionName = function (versionName) { setVersionName (versionName) {
this.doc.getroot().attrib['android:versionName'] = versionName; this.doc.getroot().attrib['android:versionName'] = versionName;
return this; return this;
}; }
AndroidManifest.prototype.getVersionCode = function () { getVersionCode () {
return this.doc.getroot().attrib['android:versionCode']; return this.doc.getroot().attrib['android:versionCode'];
}; }
AndroidManifest.prototype.setVersionCode = function (versionCode) { setVersionCode (versionCode) {
this.doc.getroot().attrib['android:versionCode'] = versionCode; this.doc.getroot().attrib['android:versionCode'] = versionCode;
return this; return this;
}; }
AndroidManifest.prototype.getPackageId = function () { getPackageId () {
return this.doc.getroot().attrib['package']; return this.doc.getroot().attrib['package'];
}; }
AndroidManifest.prototype.setPackageId = function (pkgId) { setPackageId (pkgId) {
this.doc.getroot().attrib['package'] = pkgId; this.doc.getroot().attrib['package'] = pkgId;
return this; return this;
}; }
AndroidManifest.prototype.getActivity = function () { getActivity () {
var activity = this.doc.getroot().find('./application/activity'); var activity = this.doc.getroot().find('./application/activity');
return { return {
getName: function () { getName: function () {
@ -95,13 +96,13 @@ AndroidManifest.prototype.getActivity = function () {
return this; return this;
} }
}; };
}; }
AndroidManifest.prototype.getDebuggable = function () { getDebuggable () {
return this.doc.getroot().find('./application').attrib['android:debuggable'] === 'true'; return this.doc.getroot().find('./application').attrib['android:debuggable'] === 'true';
}; }
AndroidManifest.prototype.setDebuggable = function (value) { setDebuggable (value) {
var application = this.doc.getroot().find('./application'); var application = this.doc.getroot().find('./application');
if (value) { if (value) {
application.attrib['android:debuggable'] = 'true'; application.attrib['android:debuggable'] = 'true';
@ -110,7 +111,7 @@ AndroidManifest.prototype.setDebuggable = function (value) {
delete application.attrib['android:debuggable']; delete application.attrib['android:debuggable'];
} }
return this; return this;
}; }
/** /**
* Writes manifest to disk syncronously. If filename is specified, then manifest * Writes manifest to disk syncronously. If filename is specified, then manifest
@ -119,8 +120,9 @@ AndroidManifest.prototype.setDebuggable = function (value) {
* @param {String} [destPath] File to write manifest to. If omitted, * @param {String} [destPath] File to write manifest to. If omitted,
* manifest will be written to file it has been read from. * 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'); fs.writeFileSync(destPath || this.path, this.doc.write({ indent: 4 }), 'utf-8');
}; }
}
module.exports = AndroidManifest; module.exports = AndroidManifest;

View File

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