node-salesforce-connection v2.3.1
node-salesforce-connection
node-salesforce-connection is a minimal library for connecting to Salesforce from Node.js. It provides an absolute minimal wrapper that allows you to call any Salesforce API. It tries hard to not get in the way between you and Salesforce. It has no dependencies.
This library works in Node.js. There is an almost identical library that works in browsers, but that it not yet published as a stand-alone package.
Introduction
This documentation explains how the node-salesforce-connection library works, but you need to read this in combination with the official Salesforce API documentation, since this document does not explain how the Salesforce APIs themselves work.
Create your own project using npm init
and then add this library as a dependency using npm install node-salesforce-connection --save
.
Use it like this in your JS file:
let SalesforceConnection = require("node-salesforce-connection");
(async () => {
let sfConn = new SalesforceConnection();
await sfConn.soapLogin({
hostname: "login.salesforce.com",
apiVersion: "39.0",
username: "example@example.com",
password: "MyPasswordMySecurityToken",
});
let recentAccounts = await sfConn.rest("/services/data/v39.0/query/?q="
+ encodeURIComponent("select Id, Name from Account where CreatedDate = LAST_WEEK"));
for (let account of recentAccounts.records) {
console.log("Account " + account.Name + " was created recently.");
}
})().catch(ex => console.error(ex.stack));
The examples use the JavaScript await
keyword.
This assumes the examples are placed in an async function like the one above.
You don't have to use async functions, if you prefer using the traditional promise.then(handler)
syntax.
Logging in
The first thing you need to do is log in to Salesforce.
Logging in using the SOAP API
You can use the soapLogin
function to log in using a username and password:
let sfConn = new SalesforceConnection();
await sfConn.soapLogin({
hostname: "login.salesforce.com",
apiVersion: "39.0",
username: "example@example.com",
password: "MyPasswordMySecurityToken",
});
The function calls the SOAP login method.
The function returns a promise
that behaves identically to the promise returned from the soap
function.
When the promise resolves successfully, sfConn
will be ready to use.
Logging in using OAuth
You can log in using OAuth. Here is an example of the Username-Password OAuth Authentication Flow:
let sfConn = new SalesforceConnection();
let tokenRequest = {
grant_type: "password",
client_id: "MyConsumerKey",
client_secret: "MyConsumerSecret",
username: "example@example.com",
password: "MyPasswordMySecurityToken",
};
let hostname = "login.salesforce.com";
await sfConn.oauthToken(hostname, tokenRequest);
The function makes a POST
request to /services/oauth2/token
.
The function returns a promise
that behaves identically to the promise returned from the rest
function.
When the promise resolves successfully, sfConn
will be ready to use.
Use the oauthToken
function with the
Web Server,
Username-Password and
Refresh Token
OAuth authentication flows. Use the manual approach described below for the User-Agent flow.
Logging in manually
If SOAP or OAuth login does not work for you, you can manually initialize the connection with your own questionably obtained session information:
let sfConn = new SalesforceConnection();
sfConn.instanceHostname = "na1.salesforce.com";
sfConn.sessionId = ".....";
REST
The best way to make API calls is using any Salesforce REST API. Use for example the Bulk, Chatter, REST, Tooling or Reports and Dashboards API.
Example using query:
let recentAccounts = await sfConn.rest("/services/data/v39.0/query/?q="
+ encodeURIComponent("select Id, Name from Account where CreatedDate = LAST_WEEK"));
for (let account of recentAccounts.records) {
console.log("Account " + account.Name + " was created recently.");
}
Example creating a record:
let myNewAccount = {Name: "test"};
let result = await sfConn.rest("/services/data/v39.0/sobjects/Account",
{method: "POST", body: myNewAccount});
console.log("Created Account with ID " + result.id
+ (result.success ? " successfully." : " failed."));
The rest
function accepts the following parameters:
sfConn.rest(path, {method, api, body, bodyType, headers, responseType});
The rest
function returns a promise.
If the request succeeds, the promise will resolve with the HTTP response parsed according to the responseType
parameter.
If the request fails because Salesforce returned an error response (such as HTTP 400), the promise will reject with an Error
with these properties:
If the request fails because Node.js could not connect to Salesforce, the promise will reject with a Node.js System Error.
A SalesforceResponse
object has these properties:
SOAP
If the functionality you are looking for is not available via any of the Salesforce REST APIs, you might be able to find a Salesforce SOAP API that does what you need. However, this being JavaScript, you should probably avoid SOAP when possible.
Example using upsert:
let enterpriseWsdl = sfConn.wsdl("39.0", "Enterprise");
let contacts = [
{$type: "Contact", FirstName: "John", LastName: "Smith", Email: "john.smith@example.com"},
{$type: "Contact", FirstName: "Jane", LastName: "Smith", Email: "jane.smith@example.com"},
];
let upsertResults = await sfConn.soap(enterpriseWsdl, "upsert",
{externalIdFieldName: "Email", sObjects: contacts});
for (let r of sfConn.asArray(upsertResults)) {
console.log((r.created == "true" ? "Created" : "Updated")
+ " Contact with ID " + r.id + " "
+ (r.success == "true" ? "successfully" : "failed") + ".");
}
Before you make a SOAP API request, you need a WSDL, which you get using the wsdl
function.
Well, you don't actually get the full WSDL file.
You only get the absolute minimum information needed to make SOAP API calls from JavaScript.
The wsdl
function accepts the following parameters:
sfConn.wsdl(apiVersion, apiName);
The wsdl
function returns an object containing information from the WSDL that is needed to make SOAP requests.
Alternatively, you can call the wsdl
function with only one parameter to get an object with all the WSDL's we know:
let wsdlSet = sfConn.wsdl(apiVersion);
let myWsdl = wsdlSet[apiName];
With the WSDL information at hand, you can make your SOAP API request using the soap
function.
The soap
function accepts the following parameters:
sfConn.soap(wsdl, method, args, {headers});
sObjects are a bit special in the SOAP API. You always need to specify the type of an sObject.
In the Partner WSDL, use the type
property (Example: {type: "Account", Name: "Example"}
).
In the Enterprise WSDL and others, use the $type
property (Example: {$type: "Account", Name: "Example"}
).
The soap
function returns a promise.
If the request succeeds, the promise will resolve with the SOAP method's return value.
When you get the return value from a SOAP API call, you won't get the precise type of the returned data, since that information is only available in the WSDL. You have to convert the type yourself using these rules:
- If you expect a string, you will get a string.
- If you expect a number, you will get a string. Convert it to a number using for example
let myNumber = Number(myValue)
. - If you expect a boolean, you will get a string. Convert it to a boolean using for example
let myBoolean = myValue == "true"
. - If you expect null, you will get null.
- If you expect an object, you will get an object.
- If you expect an array, you will get different things if your array has zero, one or more elements. Convert it to an array using the
asArray
utility function, for examplelet myArray = sfConn.asArray(mvValue);
.
If the request fails because Salesforce returned a SOAP fault,
the promise will reject with an Error
with these properties:
If the request fails because Node.js could not connect to Salesforce, the promise will reject with a Node.js System Error.
Error handling
The rest
and soap
functions return promises you can use in error handling like any other promise.
Example:
try {
let result = await sfConn.rest("/services/data/v39.0/query/?q="
+ encodeURIComponent("select Id from UnknownObject"));
console.log(result);
} catch (ex) {
if (ex.name == "SalesforceRestError") {
console.log("Salesforce returned an error: " + ex.message);
} else if (ex.syscall == "getaddrinfo") {
console.log("Could not make request. Are you offline?");
} else {
throw ex; // Unknown type of error
}
}
Same example with an older JavaScript syntax:
sfConn.rest("/services/data/v39.0/query/?q="
+ encodeURIComponent("select Id from UnknownObject"))
.then(function(result) {
console.log(result);
}, function(ex) {
if (ex.name == "SalesforceRestError") {
console.log("Salesforce returned an error: " + ex.message);
} else if (ex.syscall == "getaddrinfo") {
console.log("Could not make request. Are you offline?");
} else {
throw ex; // Unknown type of error
}
});
History
Before I made this library, I used JSForce. It is a nice library, but I ran into a few bugs, and I needed a specific new Salesforce APIs that was not yet added to JSForce at the time. So I made this library instead, which aims to give you access to any current or future Salesforce API without needing to update the library. It aims to provide 95% of the convenience for 5% of the size/complexity.