Skip to content

Commit

Permalink
chore: improve docs (#17)
Browse files Browse the repository at this point in the history
* chore(oauth): add client credentials example

* Added section for request

Added section for working with connection#request()
This includes information on how to use the API as well as a number of examples

There are a large number of github issues related to this use-case, so hopefully this PR will reduce
the number of issues/questions that people have in the future

* Fix Salesforrce typo

* chore: doc HTTP headers opts

* chore: add cors section

* chore: improve query builder docs

* chore: update request examples

* Update src/partials/document/cors.html.md

Co-authored-by: Steve Hetzel <[email protected]>

---------

Co-authored-by: Austin Turner <[email protected]>
Co-authored-by: Andrew Plummer <[email protected]>
Co-authored-by: Steve Hetzel <[email protected]>
  • Loading branch information
4 people authored Jul 3, 2024
1 parent 420013d commit f54f96d
Show file tree
Hide file tree
Showing 7 changed files with 208 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/documents/document/index.html.eco
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,8 @@ These docs are for jsforce v3.

<%- @partial('document/tooling') %>

<%- @partial('document/request') %>

<%- @partial('document/cors') %>

<%- @partial('document/advanced') %>
4 changes: 2 additions & 2 deletions src/partials/document/connection.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const jsforce = require('jsforce');

const conn = new jsforce.Connection({
instanceUrl : '<your Salesforce server URL (e.g. https://na1.salesforce.com) is here>',
accessToken : '<your Salesforrce OAuth2 access token is here>'
accessToken : '<your Salesforce OAuth2 access token is here>'
});
```

Expand All @@ -97,7 +97,7 @@ const conn = new jsforce.Connection({
redirectUri : '<your Salesforce OAuth2 redirect URI is here>'
},
instanceUrl : '<your Salesforce server URL (e.g. https://na1.salesforce.com) is here>',
accessToken : '<your Salesforrce OAuth2 access token is here>',
accessToken : '<your Salesforce OAuth2 access token is here>',
refreshToken : '<your Salesforce OAuth2 refresh token is here>'
});
conn.on("refresh", (accessToken, res) => {
Expand Down
7 changes: 7 additions & 0 deletions src/partials/document/cors.html.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## CORS

If you're getting CORS-related errors when using jsforce in the browser it might be that the API being used doesn't support CORS, see:
https://help.salesforce.com/s/articleView?id=sf.extend_code_cors.htm&type=5

For those cases you'll need to use the `jsforce-ajax-proxy` proxy server, check the README for setup instructions:
https://github.com/jsforce/jsforce-ajax-proxy/
20 changes: 20 additions & 0 deletions src/partials/document/crud.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,26 @@ const rets = await conn.sobject('Account')
console.log('processed: ' + rets.length);
```

### HTTP headers

You can pass a `headers` object containing REST API headers on any CRUD operation:

```javascript
const rets = await conn.sobject('Account')
.create(
accounts,
{
allowRecursive: true,
headers: {
'Sforce-Duplicate-Rule-Header': 'allowSave=true'
}
}
);
```

For more info about supported headers, see:
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/headers.htm

### Update / Delete Queried Records

If you want to update/delete records in Salesforce that match a specific condition in bulk,
Expand Down
20 changes: 20 additions & 0 deletions src/partials/document/oauth2.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,23 @@ console.log("User ID: " + userInfo.id);
console.log("Org ID: " + userInfo.organizationId);
```

### Client Credentials Flow (OAuth 2.0 Client Credentials Flow)

Similar to the JWT example, just pass the client id and secret from your connected app and use the `client_credentials` grant type.

For more information about the setup, see: https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_client_credentials_flow.htm&type=5

```javascript
import { Connection } from 'jsforce';

const conn = new jsforce.Connection({
instanceUrl: '<org instance URL>',
oauth2: {
clientId : '<your Salesforce OAuth2 client ID is here>',
clientSecret : '<your Salesforce OAuth2 client secret is here>',
loginUrl
},
});

const userInfo = await conn.authorize({ grant_type: "client_credentials" })
```
58 changes: 58 additions & 0 deletions src/partials/document/query.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,61 @@ await conn.sobject("Contact")
});
```

#### Conditionals

You can define multiple `AND`/`OR` conditional expressions by passing them in an array:
```javascript
// The following code gets translated to this soql query:
// SELECT Name FROM Contact WHERE LastName LIKE 'A%' OR LastName LIKE 'B%'
//
const contacts = await conn.sobject("Contact")
.find({
$or: [{ LastName: { $like : 'A%' }}, { LastName: { $like : 'B%'} }]
}, ['Name'])

console.log(contacts);
```

#### Dates

`jsforce.Sfdate` provides some utilities to help working dates in SOQL:
https://jsforce.github.io/jsforce/classes/date.SfDate.html

Literals like `YESTERDAY`, `TODAY`, `TOMORROW`:

```javascript
// SELECT Name FROM Account WHERE PersonBirthDate = TODAY
//
const accounts = await conn.sobject("Account")
.find({
PersonBirthDate: jsforce.SfDate.TODAY
}, ['Name']);

console.log(accounts);
```

Dynamic N days/weeks/month/quarter functions:

```javascript
// SELECT Name FROM Account WHERE PersonBirthDate = LAST_N_WEEKS:5
//
const accounts = await conn.sobject("Account")
.find({
PersonBirthDate: jsforce.SfDate.LAST_N_WEEKS(5)
}, ['Name']);

console.log(accounts);
```

Even parse a JS `Date` object:
```javascript
// SELECT Name FROM Account WHERE PersonBirthDate = 2024-06-27
//
const accounts = await conn.sobject("Account")
.find({
PersonBirthDate: jsforce.SfDate.toDateLiteral(new Date())
}, ['Name']);

console.log(accounts);
```

97 changes: 97 additions & 0 deletions src/partials/document/request.html.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
---

## Request

Make REST api calls to APIs that are not explicitly supported by JSForce.

### Setting the URL

The Endpoint URL can be in one of the following formats:

- Absolute URL: `https://na1.salesforce.com/services/data/v32.0/sobjects/Account/describe`.
- Relative path from root: `/services/data/v32.0/sobjects/Account/describe`.
- Relative path from version root: `/sobjects/Account/describe`.
- This is only supported if you have explicitly set a default version.

### Making Requests

You can use `Connection.request()` to make api requests.

For GET requests, you can pass in a string URL.

```javascript
/* @interactive */
const res = await conn.request('/services/data/v47.0/ui-api/object-info');
console.log(res)
```

If you prefer to use callbacks instead of promises, pass a callback as the second parameter.

```javascript
const res = await conn.request('/services/data/v47.0/ui-api/object-info');
console.log(res)
```

For other HTTP methods, you can pass an object to the request method. Ensure that you serialize the body of the request.

```javascript
/* @interactive */
// Bulk API 2.0 - Query
const requestBody = {
operation: 'query',
query: 'SELECT Id, Name FROM Account LIMIT 1000',
};

const res = await conn
.request({
method: 'POST',
url: '/services/data/v47.0/jobs/query',
body: JSON.stringify(requestBody),
headers: {
'content-type': 'application/json',
},
});
console.log(res)
```

#### Request Helper Methods

In addition to `Connection.request()`, JSForce provides the following helper methods that can also be used:

- `Connection.requestGet()`
- `Connection.requestPatch()`
- `Connection.requestPost()`
- `Connection.requestPut()`
- `Connection.requestDelete()`

For `requestPatch`, `requestPost` and `requestPut`, these will be serialized automatically and the `content-type` will be set to `application/json`.

```javascript
/* @interactive */
const requestBody = {
operation: 'query',
query: 'SELECT Id, Name FROM Account LIMIT 1000',
};

const res = await conn.requestPost('/services/data/v47.0/jobs/query', requestBody);
console.log(res);
```

#### Request HTTP Options

All request methods allow setting HTTP options to be passed to the HTTP request.

| Name | Type | Description |
| ----------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| responseType | string | overrides the content-type from the response to change how the response is parsed. Valid values are `text/xml`, `application/xml`, `application/json`, `text/csv`. If you do not want JSForce to auto-parse the response, set this to any other value, e.x. `text`. |
| noContentResponse | any | Alternative response when no content returned in response (= HTTP 204) |
| transport | Transport | Transport for http api - you should not need to set this option. |

If you would like to opt-out of parsing, you can set the `responseType` to text. This is useful if you want the raw response from Salesforce instead of having the results automatically parsed.

```javascript
// Get raw CSV data instead of allowing JSForce to parse the CSV to JSON
const res = await conn.requestGet('/services/data/v47.0/jobs/query/7502J00000LYZC4QAP/results', { responseType: 'text' });
console.log(res);
```

0 comments on commit f54f96d

Please sign in to comment.