Building Massive Angular Applications

I gave a talk in 2014 about creating massive angular applications. The talk focuses on how to structure your angular code and use a build system to enable the project to stay highly organized and easy to understand as the code base grows. It also enables a team of developers to all work on the code in unison without stepping all over each other. While the underlying technology has continued to sprint forward, all the concepts in the talk are still valid today. The video is from the Thunder Plains Javascript conference in 2014. This is an awesome conference in Oklahoma City. I had a great time, learned a lot, and would encourage you to attend if given the opportunity.

jsForce In Action

What is jsforce?

jsforce is a javascript library provided by Salesforce that utilizes the Force.com REST API. It can be used pretty much anywhere you can execute javascipt:

  • node module
  • loaded directly the browser
  • in a VisualForce Page
  • in a Canvas Application
  • interacted with directly on the command line
[Using jsforce on the command line]

What’s this action you speak of?

The jsforce library is very well written and documented, but it’s always simpler to write a one line example than to actually wrap your head around how to build an application that makes use of the library. In order to demonstrate a more complex use case for the library, I created a sample project that can be explored and executed locally. Find the project on Github. Follow the instructions in the README.md to download and run the project on your machine.

The project origin

Now that you’ve seen the sfExplorer project I’m sure you are wondering where all that code came from. I used a tool call Yeoman along with the angular full stack generator to generate the basic project structure. This provided an angular web app and express server to host the static resources from the angular application plus provide REST endpoints. This post is focusing specifically on the SalesforceService that is used on the server, but feel free to explore the entire application.

SalesforceService.js

The use of the jsforce library is limited to the SalesforceService

1
jsForceInAction/server/services/SalesforceService.js

The first two functions deal specifically with utilizing the authorization support that is built into jsforce. Note this isn’t a good production solution and it is only an example of how to do it using jsforce. You will need a much more robust solution for a real application. I’m also using a local redis datastore to save the auth information that is used to make the salesforce connection.

The code below is the handler for creating a connection object using jsforce. The connection object is what understands how to talk to a specific salesforce instance. You must first log into salesforce in order to acquire the access token necessary to interact with Salesforce via jsforce. The bluebird promise library is used to ‘promisify’ the connection object after it is created. More on promises in a bit.

[OAuth2 callback handler]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var conn;
if (!AuthInfo) {
conn = new jsforce.Connection({oauth2: self.getOAuth2()});
} else {

conn = new jsforce.Connection({
oauth2 : {
clientId : config.app.key,
clientSecret : config.app.secret,
redirectUri : config.app.callbackURL
},
instanceUrl : AuthInfo.instanceUrl,
accessToken : AuthInfo.accessToken
});
}

// Promisify all standard node functions from the connection.
bluebird.promisifyAll(Object.getPrototypeOf(conn));
return conn;

This is one example of how jsforce can be used to make interacting with Salesforce super simple. The rest of the functions in the service are used to query data from salesforce. The first gets all object types from the salesforce instance.

[getObjectTypes]
1
2
3
4
5
6
7
8
9
10
11
/**
* Get the list of object types for the SF instance.
*
* @returns {Promise} - A promise that resolves to a list of object types.
*/

function getObjectTypes() {
return this.getConnection()
.then(function(conn) {
return conn.describeGlobalAsync();
});
}

The really interesting line from this function is
return conn.describeGlobalAsync();
which uses the promisified top level describeGlobal jsforce function to get all object types from the domain.

describeObject is a function that uses an alternative syntax. It gets all fields for the passed object type.

[describeObject]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Get the description of an sObject from Salesforce.
*
* @param {String} objectName - The name of the sObject for which to retireve
* the description.
* @returns {Promise} - A promise that resolves to an object describing the requested
* sObject type.
*/

function describeObject(objectName) {
return this.getConnection()
.then(function(conn) {
return bluebird.promisify(conn.sobject(objectName).describe)();
});
}

Note that the top level sobject function is used to get an object that has functions for querying against that specific object type. We have to get creative with bluebird in order to return a promise from the instance of the object returned by sobject.

Promises Promises Promises

The reason I’ve gone to all the trouble promisifying the jsforce functions with bluebird promise wrappers is to make the code as a whole easier to understand and utilize. There is some debate around using promises when developing in node, but in my experience after you commit to using promises and find a good promise library there’s really no better way to think of asynchronous function execution. jsforce actually has promise support built into the library, but it is a common pitfall to use various different promise implementations across your code base. With promises playing such a key role in your application you want them to always behave the same way and have the same utility functions available. The simplest example of where you can run into trouble when you don’t use a common promise library is in error handling. Some promises use .catch while others use .error or pass a second function parameter for the error handling. When you are using a service you don’t want to have to think about what specific kind of promise is being returned.

I hope you find the sfExplorer project interesting and useful. I suggest forking it and getting it running on your local system. Then let’s see what you can do with it.