Skip to content

Commit

Permalink
feat: combine trigger-framework commands, add custom templates (#23)
Browse files Browse the repository at this point in the history
* feat: combine trigger-framework commands, add template overriding

* docs: update build heading

* feat: streamline creating custom templates
  • Loading branch information
k-capehart authored May 30, 2024
1 parent f8a65ed commit 351d7b1
Show file tree
Hide file tree
Showing 28 changed files with 600 additions and 410 deletions.
113 changes: 87 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,72 @@ This plugin is bundled with the [Salesforce CLI](https://developer.salesforce.co
sf plugins install [email protected]
```

### Build

To build the plugin locally, make sure to have yarn installed and run the following commands:

```bash
# Clone the repository
git clone [email protected]:salesforcecli/kc-sf-plugin

# Install the dependencies and compile
yarn && yarn build
## Trigger-Framework

The trigger-framework command covers auto generating triggers, handlers, and other components used in relation to Apex Triggers.

First, use the `--init` flag to initialize the framework for a given template. This generates files that should only be created once, like interfaces or custom setting objects.

After initializing, use the `--sobject` flag to generate Apex Triggers (and its handler classes) for a given object.

The `--template` flag is used to choose which template to generate the apex code from. The available templates are:

- 1 (default): https://github.com/k-capehart/kc-sf-plugin/tree/main/src/templates/template-1
- An extendable Apex Trigger Handler virtual class: https://github.com/k-capehart/sfdc-trigger-framework
- A Custom Setting called BypassAutomation\_\_c
- A checkbox field on BypassAutomation for the given Salesforce object
- An Apex trigger that calls a handler class
- An Apex handler class that extends the virtual class and uses the BypassAutomation\_\_c object to determine if logic should be skipped
- An Apex helper class
- An Apex test class for the helper class

If you want to create a custom template, then use the `--custom-template` flag. The value given to the flag should be the path to a directory containing templates for classes, triggers, objects, and/or fields. The directory should contain a `init.json` and `sobject.json` that provide instructions on which files to use, what their final name should be, and what type of file they are. `init.json` is used with the `--init` flag. `sobject.json` is used with the `--sobject` flag.

For example, imagine the following JSON file is stored at the relative path of `templates/sobject.json`. It is assumed that within this directory are also 5 other files called `BypassCustomField.txt`, `SObjectTrigger.txt`, `SObjectTriggerHandler.txt`, `SObjectTriggerHelper.txt`, and `SObjectTriggerHelper_Test.txt`. The `{{sobject}}` token is replaced with the value given in the `--sobject` flag.

```json
{
"BypassCustomField.txt": {
"type": "field",
"name": "{{sobject}}__c",
"object": "BypassAutomation__c"
},
"SObjectTrigger.txt": {
"type": "trigger",
"name": "{{sobject}}Trigger"
},
"SObjectTriggerHandler.txt": {
"type": "class",
"name": "{{sobject}}TriggerHandler"
},
"SObjectTriggerHelper.txt": {
"type": "class",
"name": "{{sobject}}Helper"
},
"SObjectTriggerHelper_Test.txt": {
"type": "class",
"name": "{{sobject}}Helper_Test"
}
}
```

To use your plugin, run using the local `./bin/dev` or `./bin/dev.cmd` file.

```bash
# Run using local run file.
./bin/dev kc diff
```
Running the command: `sf kc trigger-framework --custom-template templates/ --sobject Account` will create a 5 files:

There should be no differences when running via the Salesforce CLI or using the local run file. However, it can be useful to link the plugin to do some additional testing or run your commands from anywhere on your machine.
- Account\_\_c.field-meta.xml
- AccountTrigger.trigger
- AccountTriggerHandler.cls
- AccountTriggerHelper.cls
- AccountTriggerHelper_Test.cls

```bash
# Link your plugin to the sf cli
sf plugins link .
# To verify
sf plugins
```
For more template examples: https://github.com/k-capehart/kc-sf-plugin/tree/main/src/templates/

## Commands

<!-- commands -->
* [`sf kc diff`](#sf-kc-diff)
* [`sf kc trigger-framework init`](#sf-kc-trigger-framework-init)
* [`sf kc trigger-framework trigger`](#sf-kc-trigger-framework-trigger)

- [`sf kc diff`](#sf-kc-diff)
- [`sf kc trigger-framework init`](#sf-kc-trigger-framework-init)
- [`sf kc trigger-framework trigger`](#sf-kc-trigger-framework-trigger)

## `sf kc diff`

Expand Down Expand Up @@ -161,4 +193,33 @@ EXAMPLES
```

_See code: [src/commands/kc/trigger-framework/trigger.ts](https://github.com/k-capehart/kc-sf-plugin/blob/1.3.1/src/commands/kc/trigger-framework/trigger.ts)_

<!-- commandsstop -->

## Build

To build the plugin locally, make sure to have yarn installed and run the following commands:

```bash
# Clone the repository
git clone [email protected]:salesforcecli/kc-sf-plugin

# Install the dependencies and compile
yarn && yarn build
```

To use your plugin, run using the local `./bin/dev` or `./bin/dev.cmd` file.

```bash
# Run using local run file.
./bin/dev kc diff
```

There should be no differences when running via the Salesforce CLI or using the local run file. However, it can be useful to link the plugin to do some additional testing or run your commands from anywhere on your machine.

```bash
# Link your plugin to the sf cli
sf plugins link .
# To verify
sf plugins
```
23 changes: 0 additions & 23 deletions messages/kc.trigger-framework.init.md

This file was deleted.

43 changes: 43 additions & 0 deletions messages/kc.trigger-framework.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# summary

Generate apex trigger frameworks based on templates.

# description

Given an SObject, creates a Trigger and accompaning handler classes and components.

Use the `--init` flag to initialize the framework, then the `--sobject` flag to create triggers based on the framework.

# examples

Initialize a trigger framework using template-1.

<%= config.bin %> <%= command.id %> --template 1 --init

Create a new trigger and related components for the Account and Contact object using template-1.

<%= config.bin %> <%= command.id %> --template 1 --sobject Account --sobject Contact

Create a new trigger and related components with a custom template by providing the path to the locally stored templates.

<%= config.bin %> <%= command.id %> --custom-template templates/ --sobject Account

# flags.target-dir.summary

The target directory for your salesforce project.

# flags.sobject.summary

The name of the SObject that the trigger and classes will be created for.

# flags.template.summary

The template that should be used to generate the trigger framework.

# flags.custom-template.summary

The directory in which the custom templates are located. View docs for more information on creating templates: https://github.com/k-capehart/kc-sf-plugin

# flags.init.summary

Initialize the trigger framework for the given template.
25 changes: 0 additions & 25 deletions messages/kc.trigger-framework.trigger.md

This file was deleted.

7 changes: 1 addition & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,7 @@
],
"topics": {
"kc": {
"description": "custom commands built by github.com/k-capehart",
"subtopics": {
"trigger-framework": {
"description": "commands for auto generating trigger frameworks"
}
}
"description": "custom commands built by github.com/k-capehart"
}
},
"flexibleTaxonomy": true
Expand Down
81 changes: 81 additions & 0 deletions src/commands/kc/trigger-framework.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import * as path from 'node:path';
import { fileURLToPath } from 'node:url';
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
import { Messages } from '@salesforce/core';
import { generateTemplates } from '../../utils/triggerFactory.js';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('kc-sf-plugin', 'kc.trigger-framework');

export type KcTriggerFrameworkResult = {
createdFiles: string[];
};

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

public static readonly flags = {
'target-dir': Flags.directory({
summary: messages.getMessage('flags.target-dir.summary'),
char: 'd',
exists: true,
default: 'force-app/main/default',
}),
init: Flags.boolean({
summary: messages.getMessage('flags.init.summary'),
char: 'i',
exactlyOne: ['init', 'sobject'],
}),
sobject: Flags.string({
summary: messages.getMessage('flags.sobject.summary'),
char: 's',
multiple: true,
exactlyOne: ['init', 'sobject'],
}),
template: Flags.option({
summary: messages.getMessage('flags.template.summary'),
char: 't',
options: ['1'] as const,
exactlyOne: ['template', 'custom-template'],
})(),
'custom-template': Flags.directory({
summary: messages.getMessage('flags.custom-template.summary'),
exists: true,
exactlyOne: ['template', 'custom-template'],
}),
};

public async run(): Promise<KcTriggerFrameworkResult> {
const { flags } = await this.parse(KcTriggerFramework);
const targetDir = flags['target-dir'];
const init = flags['init'];
const sobjects = flags['sobject'];
const template = flags['template'];
let createdFiles: string[] = [];

const customTemplateDir = flags['custom-template'];
const defaultTemplateDir = '../../templates/';
const filename = fileURLToPath(import.meta.url);
const dirname = path.dirname(filename);
let templateDir: string;

switch (template) {
case undefined:
if (customTemplateDir !== undefined) {
createdFiles = generateTemplates(targetDir, customTemplateDir, init, sobjects);
}
break;
case '1':
templateDir = path.resolve(dirname, defaultTemplateDir.concat('template-1/'));
createdFiles = generateTemplates(targetDir, templateDir, init, sobjects);
break;

default:
break;
}

return { createdFiles };
}
}
44 changes: 0 additions & 44 deletions src/commands/kc/trigger-framework/init.ts

This file was deleted.

Loading

0 comments on commit 351d7b1

Please sign in to comment.