mavensmate
Version:
Core APIs that drive MavensMate IDEs for Salesforce1/Force.com
195 lines (179 loc) • 6.41 kB
JavaScript
/**
* @file Responsible for deletion of Salesforce metadata (Custom Objects, Apex Classes, Lightning files, etc.)
* @author Joseph Ferraro <@joeferraro>
*/
;
var Promise = require('bluebird');
var _ = require('lodash');
var logger = require('winston');
var LightningService = require('./lightning');
var Deploy = require('./deploy');
var fs = require('fs-extra');
var util = require('../util');
var path = require('path');
var MetadataHelper = require('../metadata').MetadataHelper;
var mavensMateFile = require('../file');
var config = require('../../config');
/**
* Responsible for deleting server and local copies of files/directories
* @param {Project} project - project instance (required)
* @param {Array} paths - array of path strings [ 'foo/bar/src/classes', 'foo/bar/src/pages/foo.page' ]
*/
var DeleteDelegate = function(project, paths) {
if (!project || !paths) {
throw new Error('DeleteDelegate requires a valid project instance and an array of paths to delete.');
}
this.project = project;
this.paths = paths;
this.metadataHelper = new MetadataHelper({ sfdcClient : this.project.sfdcClient });
};
/**
* Executes local and server delete for all delegate paths
* @return {Promise}
*/
DeleteDelegate.prototype.execute = function() {
// TODO: implement stash
var self = this;
var deleteResult;
return new Promise(function(resolve, reject) {
_.each(self.paths, function(p) {
if (!fs.existsSync(p)) {
return reject(new Error('Invalid delete request. Path does not exist: '+p));
}
});
self._performDelete()
.then(function(res) {
deleteResult = res;
return self._deleteEmptyProjectDirectories();
})
.then(function() {
resolve(deleteResult);
})
.catch(function(err) {
// TODO: revert via stash
reject(err);
});
});
};
DeleteDelegate.prototype._deleteEmptyProjectDirectories = function() {
var self = this;
return new Promise(function(resolve, reject) {
try {
fs.readdirSync(path.join(self.project.path, 'src'))
.filter(function(res) {
if (fs.statSync(path.join(self.project.path, 'src', res)).isDirectory()) {
if (util.isDirectoryEmptySync(path.join(self.project.path, 'src', res))) {
fs.removeSync(path.join(self.project.path, 'src', res));
}
}
});
resolve();
} catch(e) {
reject(e);
}
});
};
DeleteDelegate.prototype._performDelete = function() {
var self = this;
return new Promise(function(resolve, reject) {
if (self.paths.length === 0) {
return resolve();
}
var files = mavensMateFile.createFileInstances(self.paths);
var lightningBundleItemFiles = mavensMateFile.getLightningBundleItemFiles(files);
var deleteSubscription = mavensMateFile.createPackageSubscription(files, self.project.packageXml);
logger.silly('files to delete', files);
logger.silly('lightningBundleItemFiles to delete', lightningBundleItemFiles);
logger.silly('deleteSubscription', deleteSubscription);
var result = {};
var deployOptions = {
purgeOnDelete: config.get('mm_purge_on_delete') || false
};
var deploy = new Deploy({ project: self.project });
deploy.stageDelete(deleteSubscription)
.then(function(zipStream) {
return deploy.executeStream(zipStream, deployOptions);
})
.then(function(res) {
result = res;
logger.debug('Deletion result via metadata API: '+ JSON.stringify(result));
if (result.success && result.status === 'Succeeded') {
logger.debug('deleting paths locally');
_.each(files, function(sp) {
logger.debug('deleting: '+sp.path);
sp.deleteLocally();
});
}
if (!result.details.componentSuccesses) {
result.details.componentSuccesses = [];
} else if (!_.isArray(result.details.componentSuccesses)) {
result.details.componentSuccesses = [result.details.componentSuccesses];
}
if (!result.details.componentFailures) {
result.details.componentFailures = [];
} else if (!_.isArray(result.details.componentFailures)) {
result.details.componentFailures = [result.details.componentFailures];
}
logger.warn('---->', result);
return self._deleteLightningBundleItemFiles(lightningBundleItemFiles);
})
.then(function(res) {
if (res) {
_.each(res, function(r) {
if (!r.success) {
result.numberComponentErrors++;
result.details.componentFailures.push(r);
} else {
result.numberComponentsDeployed++;
result.details.componentSuccesses.push(r);
}
result.numberComponentsTotal++;
});
if (!_.find(res, { 'success': false })) {
_.each(lightningBundleItemFiles, function(sp) {
sp.deleteLocally();
});
if (res.status === 'Succeeded' && res.success) {
res.status = 'Failed';
res.success = false;
}
}
}
// console.log(result);
logger.debug(JSON.stringify(result));
resolve(result);
})
.catch(function(error) {
reject(error);
})
.done();
});
};
/**
* Retrieves source of lightning bundle items, overwrite local copies
* @param {Array} lightningMetadata - array of Metadata of type Lightning
* @return {Promise}
* TODO: overwrite local copies
*/
DeleteDelegate.prototype._deleteLightningBundleItemFiles = function(lightningFiles) {
var self = this;
return new Promise(function(resolve, reject) {
if (lightningFiles.length === 0) {
return resolve();
}
logger.debug('deleting lightning components');
logger.debug(lightningFiles[0].path);
var lightningService = new LightningService(self.project);
lightningService.deleteBundleItems(lightningFiles)
.then(function(result) {
logger.debug('delete result: ');
logger.debug(result);
resolve(result);
})
.catch(function(error) {
reject(error);
})
.done();
});
};
module.exports = DeleteDelegate;