Skip to content

Commit

Permalink
feat: validate manifests (#996)
Browse files Browse the repository at this point in the history
  • Loading branch information
mshanemc authored Jun 5, 2023
1 parent 4902d8b commit 173aba7
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 6 deletions.
18 changes: 13 additions & 5 deletions src/resolve/manifestResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import { XMLParser } from 'fast-xml-parser';
import { XMLParser, XMLValidator } from 'fast-xml-parser';
import { ensureArray } from '@salesforce/kit';
import { SfError } from '@salesforce/core';
import { MetadataType, RegistryAccess } from '../registry';
import { NodeFSTreeContainer, TreeContainer } from './treeContainers';
import { MetadataComponent } from './types';
Expand Down Expand Up @@ -52,15 +53,22 @@ export class ManifestResolver {
public async resolve(manifestPath: string): Promise<ResolveManifestResult> {
const components: MetadataComponent[] = [];

const file = await this.tree.readFile(manifestPath);

const file = (await this.tree.readFile(manifestPath)).toString();
const validateResult = XMLValidator.validate(file);
if (validateResult !== true) {
const error = new SfError(
`Invalid manifest file: ${manifestPath}. ${validateResult.err.code}: ${validateResult.err.msg} (Line ${validateResult.err.line} Column ${validateResult.err.col})`,
'InvalidManifest'
);
error.setData(validateResult.err);
throw error;
}
const parser = new XMLParser({
stopNodes: ['version'],
// In order to preserve the .0 on the apiVersion skip parsing it
numberParseOptions: { leadingZeros: false, hex: false, skipLike: /\.0$/ },
});
const parsedManifest: ParsedPackageManifest = (parser.parse(String(file)) as { Package: ParsedPackageManifest })
.Package;
const parsedManifest: ParsedPackageManifest = (parser.parse(file) as { Package: ParsedPackageManifest }).Package;
const packageTypeMembers = ensureArray(parsedManifest.types);
const apiVersion = parsedManifest.version;

Expand Down
29 changes: 28 additions & 1 deletion test/resolve/manifestResolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import { expect } from 'chai';
import { assert, expect } from 'chai';
import { createSandbox } from 'sinon';
import {
ManifestResolver,
Expand Down Expand Up @@ -80,6 +80,33 @@ describe('ManifestResolver', () => {
expect(result.components).to.deep.equal(expected);
});

it('should throw on invalid xml', async () => {
const badManifest: VirtualFile = {
name: 'bad-package.xml',
data: Buffer.from(`<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<<types>
<members></members>
<name></name>
</types>
<version>52.0</version>
</Package>\n`),
};
const tree = new VirtualTreeContainer([
{
dirPath: '.',
children: [badManifest],
},
]);
const resolver = new ManifestResolver(tree);
try {
await resolver.resolve(badManifest.name);
expect(true, 'expected invalid types definition error').to.be.false;
} catch (error) {
assert(error instanceof Error);
expect(error.name).to.equal('InvalidManifest');
}
});
it('should throw when type is empty', async () => {
const badManifest: VirtualFile = {
name: 'bad-package.xml',
Expand Down

0 comments on commit 173aba7

Please sign in to comment.