Skip to content

Commit

Permalink
feat: add directory flag to read XMLs in immediate directory
Browse files Browse the repository at this point in the history
  • Loading branch information
mcarvin8 committed Nov 20, 2024
1 parent b6b2791 commit f43ae18
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 4 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ Combine Salesforce manifest files together.

```
USAGE
$ sf sfpc combine [--json] [-f <value>]
$ sf sfpc combine [-f <value>] [-d <value>] [-c <value>] [--json]
FLAGS
-f, --package-file=<value> The path to an existing package.xml file. This flag can be specified multiple times.
-d, --directory=<value> The path to an existing directory with package.xml files. Only XML files in the immediate directory will be scanned.
This flag can be specified multiple times.
-c, --combined-package=<value> The path to save the combined package.xml to.
Default name is "combinedPackage.xml" in the running directory.
Expand All @@ -58,6 +60,10 @@ EXAMPLES
Combine pack1.xml and pack2.xml into package.xml
$ sf sfpc combine -f pack1.xml -f pack2.xml -c package.xml
Combine pack1.xml, pack2.xml, and a directory with package XML files into package.xml
$ sf sfpc combine -f pack1.xml -f pack2.xml -d "test/sample_dir" -c package.xml
```

<!-- commandsstop -->
Expand Down
5 changes: 5 additions & 0 deletions messages/sfpc.combine.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Read multiple package.xml files, then parse them and combine them to create 1 fi
# examples

- sf sfpc combine -f pack1.xml -f pack2.xml -c package.xml
- sf sfpc combine -f pack1.xml -d "test/directory" -c package.xml

# flags.package-file.summary

Expand All @@ -17,3 +18,7 @@ Path to a package.xml file.
# flags.combined-package.summary

Combined package file path.

# flags.directory.summary

Directory to look for package.xml files in.
22 changes: 19 additions & 3 deletions src/commands/sfpc/combine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Messages } from '@salesforce/core';
import { PackageXmlObject, SfpcCombineResult } from '../../helpers/types.js';
import { buildPackage } from '../../helpers/buildPackage.js';
import { readPackageFiles } from '../../helpers/readPackageFiles.js';
import { findFilesInDirectory } from '../../helpers/findFilesinDirectory.js';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('sf-package-combiner', 'sfpc.combine');
Expand All @@ -28,22 +29,37 @@ export default class SfpcCombine extends SfCommand<SfpcCombineResult> {
exists: false,
default: 'combinedPackage.xml',
}),
directory: Flags.directory({
summary: messages.getMessage('flags.directory.summary'),
char: 'd',
multiple: true,
exists: true,
}),
};

public async run(): Promise<SfpcCombineResult> {
const { flags } = await this.parse(SfpcCombine);

const files = flags['package-file'] ?? null;
const files = flags['package-file'] ?? [];
const combinedPackage = flags['combined-package'];
const directories = flags['directory'] ?? null;
let packageContents: PackageXmlObject[] = [];
let apiVersions: string[] = [];
let warnings: string[] = [];
const warnings: string[] = [];

// Search directories for XML files
// Process directories to find XML files
if (directories && directories.length > 0) {
const { files: dirFiles, warnings: dirWarnings } = await findFilesInDirectory(directories);
files.push(...dirFiles);
warnings.push(...dirWarnings);
}

// Load XML content from each file
const result = await readPackageFiles(files);
packageContents = result.packageContents;
apiVersions = result.apiVersions;
warnings = result.warnings;
warnings.push(...result.warnings);

// Print warnings if any
if (warnings.length > 0) {
Expand Down
21 changes: 21 additions & 0 deletions src/helpers/findFilesinDirectory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* eslint-disable no-await-in-loop */
import { readdir } from 'node:fs/promises';
import { join } from 'node:path';

export async function findFilesInDirectory(directories: string[]): Promise<{ files: string[]; warnings: string[] }> {
const files: string[] = [];
const warnings: string[] = [];
for (const dir of directories) {
try {
const dirFiles = await readdir(dir, { withFileTypes: true });
const xmlFiles = dirFiles
.filter((file) => file.isFile() && file.name.endsWith('.xml'))
.map((file) => join(dir, file.name));
files.push(...xmlFiles);
} catch (error) {
warnings.push(`Failed to read directory ${dir}`);
}
}

return { files, warnings };
}
21 changes: 21 additions & 0 deletions test/commands/sfpc/combine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ describe('sfpc combine', () => {
const outputPackage = resolve('package.xml');
const baseline = resolve('test/samples/combinedPackage.xml');
const emptyPackageBaseline = resolve('test/samples/emptyPackage.xml');
const packageDir = resolve('test/samples/dir_sample');
const invalidDirPackage = resolve('test/samples/dir_sample/invalid1.xml');
const dirBaseline = resolve('test/samples/combinedPackageDir.xml');

beforeEach(() => {
sfCommandStubs = stubSfCommandUx($$.SANDBOX);
Expand Down Expand Up @@ -111,4 +114,22 @@ describe('sfpc combine', () => {
`File content is different between ${outputPackage} and ${emptyPackageBaseline}`
);
});
it('combine the valid packages together including the ones in a directory.', async () => {
await SfpcCombine.run(['-f', package1, '-f', package2, '-f', package3, '-d', packageDir, '-c', outputPackage]);
const output = sfCommandStubs.log
.getCalls()
.flatMap((c) => c.args)
.join('\n');
expect(output).to.include(`Combined package.xml written to: ${outputPackage}`);
const warnings = sfCommandStubs.warn
.getCalls()
.flatMap((c) => c.args)
.join('\n');
expect(warnings).to.include(`File ${invalidDirPackage} does not match expected Salesforce package structure.`);
});
it('confirm the package created in the previous test using a directory is the same as the baseline.', async () => {
const testPackage = await readFile(outputPackage, 'utf-8');
const baselinePackage = await readFile(dirBaseline, 'utf-8');
strictEqual(testPackage, baselinePackage, `File content is different between ${outputPackage} and ${dirBaseline}`);
});
});
19 changes: 19 additions & 0 deletions test/samples/combinedPackageDir.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>Auto</members>
<name>customlabel</name>
</types>
<types>
<members>ABC</members>
<members>Account</members>
<members>Case</members>
<name>customobject</name>
</types>
<types>
<members>Glengarry_Leadz</members>
<members>Industry</members>
<name>standardvalueset</name>
</types>
<version>59.0</version>
</Package>
10 changes: 10 additions & 0 deletions test/samples/dir_sample/invalid1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<type>
<members>Lead.Always_Be_Closing__c</members>
<members>Account.Coffee_is_for_closers__c</members>
<name>CustomField</name>
</type>
<version>59.0</version>
<version>57.0</version>
</Package>
8 changes: 8 additions & 0 deletions test/samples/dir_sample/pack1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>ABC</members>
<name>CustomObject</name>
</types>
<version>57.0</version>
</Package>
8 changes: 8 additions & 0 deletions test/samples/dir_sample/pack2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>Glengarry_Leadz</members>
<name>StandardValueSet</name>
</types>
<version>59.0</version>
</Package>

0 comments on commit f43ae18

Please sign in to comment.