Subscribe

Subscribes to a platform event

Now it is time to build the most complex command so far, subscribe, for that we will rely on the Pub/Sub API.

sf events subscribe /event/NAME

Gladly, our good friend Philippe Ozil created a pub-sub-api-client for Node.js.

Let's install the dependencies we need by running:

yarn add pino pub-sub-api-node-client

Before generating the subscribe command, let's create an utility method to connect to the Pub/Sub API using the Node.js client, this will be located at src/lib/pubsub.ts.

import PubSubApiClient from 'salesforce-pubsub-api-client';
import pino from 'pino';

type pubSubClientOpts = {
  accessToken: string;
  instanceUrl: string;
  orgId: string;
  username: string;
};

// Configure and returns an authenticated Pub/Sub API Client
export const createPubSubClient = async ({
  accessToken,
  instanceUrl,
  orgId: organizationId,
  username,
}: pubSubClientOpts): Promise<PubSubApiClient> => {
  // Setup Configuration parameters
  process.env.SALESFORCE_AUTH_TYPE = 'user-supplied';
  process.env.PUB_SUB_ENDPOINT = 'api.pubsub.salesforce.com:7443';

  const client = new PubSubApiClient(
    pino({
      level: 'silent',
    })
  );
  await client.connectWithAuth(accessToken, instanceUrl, organizationId, username);

  return client;
};

Now let's generate the subscribe command by running:

sf dev generate command --name events:subscribe

Here is the source code for the subscribe command, what is special is that we can re-use the Authentication Information from the org we are logged in with the Salesforce CLI to perform other more advanced operations, like using the Pub/Sub API client to listen for events.

import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
import { Messages, AuthInfo } from '@salesforce/core';
import { AnyJson } from '@salesforce/ts-types';
import { createPubSubClient } from '../../lib/pubsub';

Messages.importMessagesDirectory(__dirname);
const messages = Messages.load('events-plugin', 'events.subscribe', [
  'summary',
  'description',
  'examples',
  'flags.org.summary',
  'args.name.summary',
]);

export default class EventsSubscribe extends SfCommand<void> {
  public static summary = messages.getMessage('summary');
  public static description = messages.getMessage('description');
  public static examples = messages.getMessages('examples');

  public static args = [
    {
      name: 'name',
      required: true,
    },
  ];

  public static flags = {
    'target-org': Flags.requiredOrg({
      summary: messages.getMessage('flags.org.summary'),
      char: 'o',
      required: true,
    }),
  };
  
  public static enableJsonFlag = false;

  public async run(): Promise<void> {
    const { args, flags } = await this.parse(EventsSubscribe);

    const name = args.name as string;
    const org = flags['target-org'];

    // Get Org Parameters and Authentication Information
    const username = org.getUsername();
    const authInfo = await AuthInfo.create({ username });
    const { accessToken, instanceUrl, orgId } = authInfo.getFields(true);

    // Create PubSub Client using the authentication information from the org
    const client = await createPubSubClient({
      accessToken,
      instanceUrl,
      orgId,
      username,
    });

    // Subscribe to event
    this.log(`Listening for events ${name}, close with Ctrl+C`);
    const emitter = await client.subscribe(name, 100);
    emitter.on('data', (event) => {
      // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
      const payload = event.payload as AnyJson;
      this.styledJSON(payload);
    });
  }
}
# summary

Subscribes to a platform event

# description

It subscribes to a platform event using the Pub/Sub API

# args.name.summary

Event name

# flags.org.summary

Login username or alias for the target org.

# examples

- <%= config.bin %> <%= command.id %> Test_Event__e

Last updated