Saturday 4 April 2020

Documenting from the metadata source with a Salesforce CLI Plug-In - Part 1


(This series accompanies the talk that I gave to an empty room and a camera crew at London's Calling 2020 and a revised version to the virtual meetup Helsinki Developer Group the following week)

As regular readers of this blog know, I'm a huge fan of the Salesforce CLI. I reckon getting on for half of the talks/blogs that I've done in the last couple of years have been around using or extending it. I've even wrapped it in a GUI that I use multiple times every day, to open orgs, create scratch orgs or work with packages. I'm always looking for new ways to leverage it, and a year or so ago I was asked to create a document with details of the objects and fields from one of my Salesforce orgs. While I could do this manually, that's a lot of effort for something that will almost certainly be wrong in a couple of days. A better idea would be to automatically generate the document from the metadata.

BP (Before Plug-Ins)

This predated plug-ins, so I wrote a bunch of NodeJS code that behaved as a CLI in it's own right, using the Commander package. While this is fine, it's another tool that needs to be installed and maintained, so once plug-ins came along I added this to my list of things to migrate.

AP (After Plug-Ins)

Now that the Salesforce CLI supports plug-ins, that is always my first choice for anything of this nature. My team all have the CLI installed as that is how we develop and deploy on Salesforce, so distribution is simplified as the container is already on everyone's machine. All they need to do is run the plugins:install command to add a plug-in, and if I push an update they can upgrade via the plugins:update command.

The Metadata

My metadata is in source format and is available in a Github repo.  The object model is based on a bookstore and has the following items:

  • Book - details of a specific book
  • Author - an individual who has written one or more books
  • Publisher - an organisation that publishes books from multiple authors
  • Book Signing - an event where an author signs copies of their book that customers have purchased
  • Author Reading - an event where an author reads from their book to an invited audience 

I want to create an HTML document that pulls information from the metadata and generates an HTML document, separating the objects into two groups - Events (Book Signing and Author Reading) and the rest.

Creating a Plug-In

Creating a plug-in is as simple as executing the plugins:generate command and answering some questions. The following example creates a plug-in named 'sample'. Note that the plug-in is generated in the current working directory, so I create the sample directory first, or everything ends up in the root of my drive!

kbowden@Keirs-MacBook-Pro ~ *$ mkdir sample
kbowden@Keirs-MacBook-Pro ~ *$ cd sample
kbowden@Keirs-MacBook-Pro sample *$ sfdx plugins:generate

     _-----_     ╭──────────────────────────╮
    |       |    │     Time to build an     │
    |--(o)--|    │     sfdx-cli plugin!     │
   `---------´   │      Version: 1.1.2      │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
 ´   `  |° ´ Y `

? npm package name sample
? description Sample plug-in for blog
? author Keir Bowden @keirbowden
? version 0.0.0
? license MIT
? Who is the GitHub owner of repository ( keirbowden
? What is the GitHub name of repository ( sample

Once I've answered the questions, the command creates some files in the directory and installs a bunch of packages. You don't need to worry about the details, just make sure that the following is output when it completes to indicate the command was successful:

Created sample in /Users/kbowden/sample

(replacing sample and the directory with your specific details, obviously!)

Executing a Plug-In Command

When you generate a plug-in, you get a command - hello:org.  This connects to the Salesforce org associated with the default user, or the user that you supply when running the command, and retrieves some information. To test the command, you can use the bin/run script, which avoids having to install into the Salesforce CLI while you are building your plug-in. The output below is from my Mentz code mentoring org:

kbowden@Keirs-MacBook-Pro sample *$ bin/run hello:org -u MENTZLIVE
Hello world! This is org: Bob Buzzard
My hub org id is: 00D30000000J2G8EAK

Creating a New Command

The easiest way to create a new command is to copy the example and change it to your requirements. I'd very much advise taking baby steps when you are doing this for the first time, so try to keep the command working and re-run it when making changes.

The example command lives in the src/commands folder:

the hello folder defines the topic, and org.ts contains the command source code.  Copying this to src/commands/bbdoc/doc.ts adds the bbdoc:doc command:

kbowden@Keirs-MacBook-Pro sample *$ bin/run bbdoc:doc -u MENTZLIVE
Hello world! This is org: Bob Buzzard
My hub org id is: 00D30000000J2G8EAK

So running a couple of commands, answering a few questions and copying a file gives a whole new (if familiar) plug-in and command. At this point the plug-in is complete and can be published to npm. It's unlikely to see much uptake, but there's nothing else that needs to be done to make it distributable.

In the next instalment, I'll start the customisation of the bbdoc:doc command. If you can't wait, you can see the plug-in source on Github or install it yourself from npm.

Related Posts

1 comment:

  1. For anyone having issues with the hello:org command, you need to change the package.json file to point to src/commands, otherwise the command will not work

    See here: