An open API service indexing awesome lists of open source software.

https://github.com/varun-verma-code/salesforce-streams-cds-nodejs

Service using Node and Express, that subscribes to Change Data Source events from Salesforce
https://github.com/varun-verma-code/salesforce-streams-cds-nodejs

Last synced: about 1 year ago
JSON representation

Service using Node and Express, that subscribes to Change Data Source events from Salesforce

Awesome Lists containing this project

README

          

# salesforce-streams-cds-nodejs

Service using Node and Express, that subscribes to Change Data Source events from Salesforce

**This example app displays a feed of changes happening within a Salesforce org.**

🤐🚫🙅‍♀️ _Do not connect this app with a production Salesforce org without proper security review. This app receives potentially confidental data from the Salesforce org via Streaming API._

[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)

![Screenshot of the web interface](doc/salesforce-activity-ui-v01.png)

## Architecture

This app is composed of two server-side processes and a web UI:

- [stream-consumer.js](stream-consumer.js), the Salesforce Streaming API consumer
- [server.js](server.js), serves the web app and API feed of Account changes to web browsers
- [pages/index.js](pages/index.js), the Next/React.js web UI

![Diagram: reactive apps with Salesforce streaming](doc/salesforce-streams-nodejs-v03.png)

Messages [flow](lib/subscribe-salesforce-streams.js#L108) from Salesforce into the stream consumer via [Bayeux/CometD](https://developer.salesforce.com/docs/atlas.en-us.api_streaming.meta/api_streaming/BayeauxProtocolAndCometD.htm#!), and then are [pushed](stream-consumer.js#L35) into [Redis pub/sub](https://redis.io/topics/pubsub) so [requests](https://github.com/heroku-examples/salesforce-streams-nodejs/blob/master/server.js#L86) from each independent web client may [subscribe](pages/index.js#L156) to them via [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events).

The stream consumer is a single, single-threaded process to reliably ingest the ordered stream from Salesforce. Redis acts as a bridge to support scalable processing of the messages by multiple clients. In this example, we use Redis [`PUBLISH`/`SUBSCRIBE`](https://redis.io/topics/pubsub) to send every web client the complete stream. To instead provide a reliable queue of messages for scalable processing, pub/sub could be replaced with Redis [`LPUSH`/`RPOPLPUSH`/`LREM`](https://redis.io/commands/rpoplpush#pattern-reliable-queue).

This example app uses the [Change Data Capture (CDC)](https://developer.salesforce.com/docs/atlas.en-us.216.0.change_data_capture.meta/change_data_capture/cdc_intro.htm) stream for **Accounts**, which must be enabled for each desired object in Salesforce Setup:

![Navigate to Salesforce Setup, then Integrations, then Change Data Capture](doc/Salesforce-setup-CDC.png "Salesforce Setup: Change Data Capture")

## Local development

### Requires

- Salesforce
- [a free Developer Edition org](https://developer.salesforce.com/signup)
- Heroku
- [a free account](https://signup.heroku.com)
- [command-line tools (CLI)](https://devcenter.heroku.com/articles/heroku-command-line)
- [redis server](https://redis.io/download) (installed and listening on the default local port)
- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
- [Node.js](https://nodejs.org) 10.x (**Make sure you have nvm installed to use Node v10.24.1**)

### Setup

In your shell terminal, clone this repo to become the working directory:

```bash
git clone https://github.com/heroku-examples/salesforce-streams-nodejs
cd salesforce-streams-nodejs
```

Install Node packages:

```bash
npm install
```

Copy the local dev environment variables template, and then open `.env` in your editor:

```
cp .env.sample .env
```

✏️ _In `.env` [configure Salesforce authentication](#user-content-salesforce-authentication)._

### Salesforce

Login to the Salesforce org.

In **Salesforce Setup** → **Integrations** → **Change Data Capture**, select which entities (objects) should produce change messages.

For this example app, **Account** is selected.

### Running

The app is composed of two processes, declared in the [`Procfile`](Procfile). It may be start using the follow commands:

```bash
web: node server.js
stream_consumer: node stream-consumer.js
```

### Demo

▶️ in a browser view the web UI [http://localhost:3000/](http://localhost:3000/).

▶️ in a separate browser window, login to the associated Salesforce org. Create or update entities (example: Accounts) that are [configured](#user-content-salesforce) for CDC events.

👀 observe the changes appearing in the web UI.

⚡️☁ notice the bolt & cloud emojis in the web UI. The ⚡️ indicates the web browser's on-line status, while the ☁️ indicates the backend Salesforce streaming connection status. These indicators fade out when off-line. Hover over them to see a textual description of the current state.

### Testing

Tested with [ava](https://github.com/avajs/ava):

```bash
npm test
```

## Configuration

Configured via environment variables.

For local development, set these values in `.env` file.

For Heroku deployment, set these values via [Config Vars](https://devcenter.heroku.com/articles/config-vars).

### Salesforce Authentication

**required**

Any one of the following authentication methods must be used by setting its variables:

- Username + password
- `SALESFORCE_USERNAME`
- `SALESFORCE_PASSWORD` (the password and security token combined without spaces)
- `SALESFORCE_LOGIN_URL` (optional; defaults to **login.salesforce.com**)
- Existing OAuth token
- `SALESFORCE_INSTANCE_URL`
- `SALESFORCE_ACCESS_TOKEN`
- Retrieve from an [sfdx](https://developer.salesforce.com/docs/atlas.en-us.212.0.sfdx_dev.meta/sfdx_dev/sfdx_dev_intro.htm) scratch org with `sfdx force:org:display`
- OAuth client
- `SALESFORCE_URL`
- _Must include oAuth client ID, secret, & refresh token_
- Example: `force://{client-id}:{secret}:{refresh-token}@{instance-name}.salesforce.com`

### Runtime Behavior

- `FORCE_API_VERSION`
- Salesforce API version
- `OBSERVE_SALESFORCE_TOPIC_NAMES`
- **required**
- the path part of a Streaming API URL
- a comma-delimited list
- example: `OBSERVE_SALESFORCE_TOPIC_NAMES=/event/Heroku_Function_Generate_UUID_Invoke__e`
- `REDIS_URL`
- **required**
- connection config to Redis datastore
- example: `REDIS_URL=redis://localhost:6379`
- default: should be set from Heroku Redis add-on
- `REPLAY_ID`
- force a specific replayId for Salesforce Streaming API
- ensure to unset this after usage to prevent the stream from sticking
- example: `REPLAY_ID=5678` (or `-2` for all possible events)
- default: unset, receive all new events