https://github.com/mcarvin8/sf-decomposer
Break down large Salesforce metadata files into smaller, more manageable files for version control and then recreate deployment-compatible files.
https://github.com/mcarvin8/sf-decomposer
continuous-integration decomposition deployments salesforce version-control
Last synced: 23 days ago
JSON representation
Break down large Salesforce metadata files into smaller, more manageable files for version control and then recreate deployment-compatible files.
- Host: GitHub
- URL: https://github.com/mcarvin8/sf-decomposer
- Owner: mcarvin8
- License: mit
- Created: 2024-01-25T22:23:19.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-03-30T22:51:46.000Z (about 1 month ago)
- Last Synced: 2025-03-30T22:55:15.927Z (about 1 month ago)
- Topics: continuous-integration, decomposition, deployments, salesforce, version-control
- Language: TypeScript
- Homepage:
- Size: 3.02 MB
- Stars: 16
- Watchers: 1
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
Awesome Lists containing this project
README
# `sf-decomposer`
[](https://www.npmjs.com/package/sf-decomposer) [](https://npmjs.org/package/sf-decomposer) [](https://raw.githubusercontent.com/mcarvin8/sf-decomposer/main/LICENSE.md)
Table of Contents
- [Quick Start](#quick-start)
- [Why Choose `sf-decomposer`](#why-choose-sf-decomposer)
- [Commands](#commands)
- [`sf decomposer decompose`](#sf-decomposer-decompose)
- [`sf decomposer recompose`](#sf-decomposer-recompose)
- [Decompose Structure](#decompose-structure)
- [Supported Metadata](#supported-metadata)
- [Metadata Exceptions](#metadata-exceptions)
- [Troubleshooting](#troubleshooting)
- [Hooks](#hooks)
- [Ignore Files](#ignore-files)
- [`.forceignore`](#.forceignore)
- [`.sfdecomposerignore`](#.sfdecomposerignore)
- [`.gitignore`](#.gitignore)
- [Issues](#issues)
- [Built With](#built-with)
- [Contributing](#contributing)
- [License](#license)Break down large Salesforce metadata files (XML) into smaller, more manageable files (XML/JSON/YAML/JSON5) for version control and then recreate deployment-compatible files.
## Quick Start
1. Install plugin using `sf`
```bash
sf plugins install [email protected]
```2. [Decompose](#sf-decomposer-decompose) the metadata type(s) in your Salesforce DX project
```bash
sf decomposer decompose -m "flow" -m "labels"
```3. Add decomposed files to [`.forceignore`](#.forceignore)
> This is **REQUIRED** to avoid errors when running `sf`commands
4. Stage decomposed files in version control
5. [Recompose](#sf-decomposer-recompose) the metadata type(s) before deployment
```bash
sf decomposer recompose -m "flow" -m "labels"
```6. Deploy recomposed metadata
## Why Choose `sf-decomposer`
Salesforce's built-in decomposition has limitations. `sf-decomposer` offers more control, flexibility, and versioning benefits for Admins and Developers.
### Key Advantages
- **Supports More Metadata** – Works with most Metadata API types, unlike Salesforce’s limited decomposition.
- **Selective Decomposition** – Decompose only what you need, avoiding Salesforce’s all-or-nothing approach.
- See [.sfdecomposerignore](#.sfdecomposerignore)
- **Fully Decomposes Metadata** – Ensures complete decomposition for types that Salesforce only partially decomposes (e.g., `decomposePermissionSetBeta2`).
- **Consistent Sorting** – Keeps elements in a predictable order to reduce unnecessary version control noise.
- **Multiple Output Formats** – Supports XML, JSON, JSON5, and YAML for greater flexibility.
- **CI/CD Integration** – Hooks enable seamless decomposition and recomposition in automated workflows.
- **Improved Version Control** – Smaller, structured files make pull requests easier to review and reduce merge conflicts.### How It Helps Salesforce Teams
- **Better Peer Reviews** – More readable diffs for large metadata in GitHub and other CI/CD platforms.
- **Safer Deployments** – Ensures only intended changes are deployed, improving release quality.## Commands
The `sf-decomposer` supports 2 commands:
- `sf decomposer decompose`
- `sf decomposer recompose`## `sf decomposer decompose`
Decomposes the original metadata files in all local package directories into smaller files for version control.
```
USAGE
$ sf decomposer decompose -m -f -i [--prepurge --postpurge --debug --json]FLAGS
-m, --metadata-type= The metadata suffix to process, such as 'flow', 'labels', etc.
Can be declared multiple times.
-f, --format= The file type for the decomposed files.
Must match what format you provide for recompose.
Options: ['xml', 'yaml', 'json', 'json5']
[default: 'xml']
-i, --ignore-package-directory= Package directory to ignore.
Should be as they appear in the "sfdx-project.json".
Can be declared multiple times.
--prepurge Purgd directories of pre-existing decomposed files.
[default: false]
--postpurge Purge the original files after decomposing them.
[default: false]
--debug Log debugging results to a text file (disassemble.log).
[default: false]GLOBAL FLAGS
--json Format output as json.EXAMPLES
Decompose all flows in XML format:$ sf decomposer decompose -m "flow" -f "xml" --prepurge --postpurge --debug
Decompose all flows and custom labels in YAML format
$ sf decomposer decompose -m "flow" -m "labels" -f "yaml" --prepurge --postpurge --debug
Decompose flows except for those in the "force-app" package directory.
$ sf decomposer decompose -m "flow" -i "force-app"
```
## `sf decomposer recompose`
Recompose decomposed files into deployment-compatible files.
```
USAGE
$ sf decomposer recompose -m -f -i [--postpurge --debug --json]FLAGS
-m, --metadata-type= The metadata suffix to process, such as 'flow', 'labels', etc.
Can be declared multiple times.
-f, --format= The file format for the decomposed files.
Must match what format you provide for decompose.
Options: ['xml', 'yaml', 'json', 'json5']
[default: 'xml']
-i, --ignore-package-directory= Package directory to ignore.
Should be as they appear in the "sfdx-project.json".
Can be declared multiple times.
--postpurge Purge the decomposed files after recomposing them.
[default: false]
--debug Log debugging results to a text file (disassemble.log).
[default: false]GLOBAL FLAGS
--json Format output as json.EXAMPLES
Recompose all flows:$ sf decomposer recompose -m "flow" -f "xml" --postpurge --debug
Recompose all decomposed flows and custom labels YAMLs into XMLs
$ sf decomposer recompose -m "flow" -m "labels" -f "yaml" --postpurge --debug
Recompose flows except for those in the "force-app" package directory.
$ sf decomposer recompose -m "flow" -i "force-app"
```
## Decompose Structure
When the original metadata files are decomposed, this structure is followed for all metadata types except for custom labels:
- Leaf elements (i.e. `Salesforce`) will be decomposed in the same file in the root of the decomposed directory. The leaf file-name will match the original file-name.
- Nested elements will be decomposed into their own files under sub-directories by the element type, i.e. custom permissions in a permission set will have their own decomposed file under a custom permissions sub-folder.
- If unique ID elements are found, the decomposed nested files will be named using them.
- Otherwise, the decomposed nested files will be named with the SHA-256 hash of the element contents.
- See [Contributing](#contributing) for more information on unique ID elements.
![]()
Decomposed Permission Sets named using unique ID elements
![]()
Decomposed Application named using SHA-256 hashes of elements
When custom labels are decomposed, each custom label will have its own file in the original labels directory.
![]()
Decomposed Custom Labels
## Supported Metadata
All parent metadata types imported from this plugin's version of `@salesforce/source-deploy-retrieve` (SDR) toolkit are supported except for certain types.
The `--metadata-type`/`-m` flag should be the metadata's `suffix` value as listed in the [metadataRegistry.json](https://github.com/forcedotcom/source-deploy-retrieve/blob/main/src/registry/metadataRegistry.json). You can also infer the suffix by looking at the original XML file-name, i.e. `*.{suffix}-meta.xml`.
Here are some examples:
- Custom Labels (`--metadata-type "labels"`)
- Workflows (`--metadata-type "workflow"`)
- Profiles (`--metadata-type "profile"`)
- Permission Sets (`--metadata-type "permissionset"`)
- AI Scoring Model Definition (`--metadata-type "aiScoringModelDefinition"`)
- Decision Matrix Definition (`--metadata-type "decisionMatrixDefinition"`)
- Bot (`--metadata-type "bot"`)
- Marketing App Extension (`--metadata-type "marketingappextension"`)### Metadata Exceptions
- `botVersion` is blocked from being ran directly. Please use the `bot` meta suffix to decompose and recompose bots and bot versions.
```
Error (1): `botVersion` suffix should not be used. Please use `bot` to decompose/recompose bot and bot version files.
```
- Custom Objects are not supported by this plugin as they already are decomposed by default.
```
Error (1): Custom Objects are not supported by this plugin.
```
- Metadata types such as Apex Classes, Apex Components, Triggers, etc. with certain SDR adapter strategies (`matchingContentFile`, `digitalExperience`, `mixedContent`, `bundle`) are not supported by this plugin.
```
Error (1): Metadata types with [matchingContentFile, digitalExperience, mixedContent, bundle] strategies are not supported by this plugin.
```
- Children metadata types (i.e. custom fields) are not supported and will result in this general error:
```
Error (1): Metadata type not found for the given suffix: field.
```## Troubleshooting
`sf-decomposer` searches the current working directory for the `sfdx-project.json`, and if it's not found in the current working directory, it will search upwards for it until it hits your root drive. If the `sfdx-project.json` file isn't found, the plugin will fail with:
```
Error (1): sfdx-project.json not found in any parent directory.
```The `xml-disassembler` package will create a log file, `disassemble.log`, at all times. By default, the log will only contain XML decomposing/recomposing errors. XML decomposing/recomposing errors do not cause the Salesforce CLI to fail. The CLI will proceed to decompose/recompose all remaining metadata.
The Salesforce CLI will print XML errors as warnings in the terminal:
```
Warning: C:\Users\matth\Documents\sf-decomposer\test\baselines\flows\Get_Info\actionCalls\Get_Info.actionCalls-meta.xml was unabled to be parsed and will not be processed. Confirm formatting and try again.
```To add debugging to the log, provide the `--debug` flag to the decompose or recompose command.
```
[2024-03-30T14:28:37.959] [DEBUG] default - Created disassembled file: mock\no-nested-elements\HR_Admin\HR_Admin.permissionset-meta.xml
```## Hooks
> **NOTE:** In order to avoid errors when running `sf` commands, you must configure your `.forceignore` file to have the Salesforce CLI ignore the decomposed files. See [Ignore Files](#ignore-files).
`sf-decomposer` supports automatic decomposition and recomposition by defining a `.sfdecomposer.config.json` file in your project root.
You can copy and update the sample [.sfdecomposer.config.json](https://raw.githubusercontent.com/mcarvin8/sf-decomposer/main/samples/.sfdecomposer.config.json).
- `metadataSuffixes` is required and should be a comma-separated string of metadata suffixes to decompose and recompose based on the CLI command.
- `ignorePackageDirectories` is optional and should be a comma-separated string of package directories to ignore.
- `prePurge` is optional and should be `true` or `false`. If true, this will delete any existing decomposed files before decomposing the files. This defauls to `false`.
- `postPurge` is optional and should be `true` or `false`. If true, this will delete the retrieval file after decomposing it or delete the decomposed files after recomposing them. This defauls to `false`.
- `decomposedFormat` is optional and should be either `xml`, `json`, `json5`, or `yaml`, depending on the decomposed file format. This defaults to `xml`.If `.sfdecomposer.config.json` is found, the hooks will run:
- the decompose command **after** a `sf project retrieve start` command completes successfully (post-run)
- the recompose command **before** a `sf project deploy [start/validate]` command starts (pre-run)If `.sfdecomposer.config.json` isn't found, the hooks will be skipped.
## Ignore Files
### `.forceignore`
The Salesforce CLI **must** ignore the decomposed files and allow the recomposed files.
You can use the sample [.forceignore](https://raw.githubusercontent.com/mcarvin8/sf-decomposer/main/samples/.forceignore). Update the decomposed file extensions based on what format you're using (`.xml`, `.json`, `.json5`, or `.yaml`).
### `.sfdecomposerignore`
Optionally, you can create a `.sfdecomposerignore` file in the root of your Salesforce DX project to ignore specific XMLs when decomposing. The `.sfdecomposerignore` file should follow [.gitignore spec 2.22.1](https://git-scm.com/docs/gitignore).
When you run `sf decomposer decompose --debug` and it processes a file that matches an entry in `.sfdecomposerignore`, a warning will be printed to the `disassemble.log`:
```
[2024-05-22T09:32:12.078] [WARN] default - File ignored by .sfdecomposerignore: C:\Users\matth\Documents\sf-decomposer\test\baselines\bots\Assessment_Bot\v1.botVersion-meta.xml
````.sfdecomposerignore` is not read when recomposing metadata.
### `.gitignore`
Optionally, git can ignore the recomposed files so you don't stage those in your repositories. You can also have git ignore the `disassemble.log` created by the `xml-disassembler` package.
You can use the sample [.gitignore](https://raw.githubusercontent.com/mcarvin8/sf-decomposer/main/samples/.gitignore).
## Issues
If you encounter any bugs or would like to request features, please create an [issue](https://github.com/mcarvin8/sf-decomposer/issues).
## Built With
- [`xml-disassembler`](https://github.com/mcarvin8/xml-disassembler)
- [`xml2json-disassembler`](https://github.com/mcarvin8/xml2json-disassembler)
- [`xml2yaml-disassembler`](https://github.com/mcarvin8/xml2yaml-disassembler)
- [`xml2json5-disassembler`](https://github.com/mcarvin8/xml2json5-disassembler)## Contributing
Contributions are welcome! See [Contributing](https://github.com/mcarvin8/sf-decomposer/blob/main/CONTRIBUTING.md).
## License
This project is licensed under the MIT license. Please see the [LICENSE](https://raw.githubusercontent.com/mcarvin8/sf-decomposer/main/LICENSE.md) file for details.