Skip to content

Instantly share code, notes, and snippets.

@jeffdonthemic jeffdonthemic/tooling.js
Last active Jan 2, 2016

Embed
What would you like to do?
Sample script for with Promises for updating an Apex class in Force.com using the Tooling API with node.
var Q = require("q"),
request = require('request');
// call with the following
// var apexClassId = "01pi0000004kbvAAAQ"; // the id of the apex class to update
// var newCode = "public class Test1 { public void sayHelloOnceAgain() { } }"; // pass in some code
// var connetion = resp object from nforce org.authenticate
function updateApex(apexClassId, newCode, connection) {
var deferred = Q.defer();
var bearer = connection.access_token;
console.log("==== STARTING NEW DEPLOY ====");
createContainer()
.then(addUpdatedCode)
.then(deploy)
.then(function(results) {
deferred.resolve(results);
})
.fail(function(err) {
console.log("== failure: " + err);
deferred.reject(err);
});
function deleteContainer(metadataContainerId) {
var deferred = Q.defer();
var options = {
url: connection.instance_url + '/services/data/v28.0/tooling/sobjects/MetadataContainer/' + metadataContainerId,
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + bearer
}
};
function callback(error, response, body) {
if (!error && response.statusCode == 204) {
console.log("Deleted deployment container: " + metadataContainerId);
deferred.resolve("Deployment complete!");
} else {
console.log(response.statusCode);
var result = JSON.parse(body);
deferred.reject("Failed to delete metadata container.");
console.log(result);
}
}
// make the request
request(options, callback);
return deferred.promise;
}
function checkDeployState(containerAsyncRequestId) {
var options = {
url: connection.instance_url + '/services/data/v28.0/tooling/sobjects/ContainerAsyncRequest/' + containerAsyncRequestId,
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + bearer
}
};
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
var result = JSON.parse(body);
if (result.State === "Queued") {
console.log("Status is currently queued. Checking deploy state again.");
checkDeployState(containerAsyncRequestId);
} else {
if (result.State === "Completed") {
console.log("W00t! Code successfully deployed");
} else if (result.State === "Failed") {
console.log("Deployment failed with: ");
console.log(result.CompilerErrors);
} else if (result.State === "Error") {
console.log("Deployment failed with error: ");
console.log(result.ErrorMsg);
} else {
console.log("Deploy finished with a status of: " + result.State);
console.log(result);
}
deleteContainer(result.MetadataContainerId);
}
} else {
var result = JSON.parse(body);
console.log(result);
}
}
// make the request
request(options, callback);
}
function createContainer() {
var deferred = Q.defer();
var options = {
url: connection.instance_url + '/services/data/v28.0/tooling/sobjects/MetadataContainer',
method: 'POST',
body: '{"Name":"AwesomeContainer"}',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + bearer
}
};
function callback(error, response, body) {
if (!error && response.statusCode == 201) {
var result = JSON.parse(body);
console.log("Created MetadataContainer: " + result.id)
deferred.resolve(result.id);
} else {
console.log(response.statusCode);
var result = JSON.parse(body);
deferred.reject("Failed to create a metadata container.");
console.log(result);
}
}
// make the request
request(options, callback);
return deferred.promise;
}
function addUpdatedCode(metadataContainerId) {
var deferred = Q.defer();
var options = {
url: connection.instance_url + '/services/data/v28.0/tooling/sobjects/ApexClassMember',
method: 'POST',
body: '{"MetadataContainerId":"'+metadataContainerId+'", "ContentEntityId":"'+apexClassId+'", "body": "'+newCode+'"}',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + bearer
}
};
function callback(error, response, body) {
if (!error && response.statusCode == 201) {
var result = JSON.parse(body);
console.log("Created ApexClassMember: " + result.id)
deferred.resolve(metadataContainerId);
} else {
console.log(response.statusCode);
var result = JSON.parse(body);
deferred.reject("Failed to add updated code.");
console.log(result);
}
}
// make the request
request(options, callback);
return deferred.promise;
}
function deploy(metadataContainerId) {
var deferred = Q.defer();
var options = {
url: connection.instance_url + '/services/data/v28.0/tooling/sobjects/ContainerAsyncRequest',
method: 'POST',
body: '{"MetadataContainerId":"'+metadataContainerId+'", "isCheckOnly": false}',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + bearer
}
};
function callback(error, response, body) {
if (!error && response.statusCode == 201) {
var result = JSON.parse(body);
console.log("Deployed code with id: " + result.id);
// check the state of the deployment
checkDeployState(result.id);
deferred.resolve(metadataContainerId);
} else {
console.log(response.statusCode);
var result = JSON.parse(body);
deferred.reject("Failed to deploy code.");
console.log(result);
}
}
// make the request
request(options, callback);
return deferred.promise;
}
return deferred.promise;
}
exports.updateApex = updateApex;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.