From 92423e699d620d7dad1dfc817261c4d24ae5b936 Mon Sep 17 00:00:00 2001 From: Ken Lewis <46458081+klewis-sfdc@users.noreply.github.com> Date: Thu, 6 Apr 2023 10:59:21 -0700 Subject: [PATCH] feat: upgrade fast-xml-parser (#926) * feat: bump fast-xml-parser * feat: trying String() * chore: update fast xml parser options * fix: change xmlParser to xmlBuilder when building * fix: final two unit tests * refactor: rename variables * chore: remove updates committed unintentionally * refactor: use padEnd() Co-authored-by: Shane McLaughlin * Revert "refactor: use padEnd()" This reverts commit 72df5817e34c025575e51a7ad86d4268336cd8b5. * Revert "Revert "refactor: use padEnd()"" This reverts commit 675840f7b529b5782b72c2023df134ed60c65537. --------- Co-authored-by: Gordon Bockus Co-authored-by: Shane McLaughlin --- package.json | 2 +- src/collections/componentSet.ts | 10 ++++++---- src/convert/streams.ts | 13 ++++++++++--- src/resolve/manifestResolver.ts | 14 ++++++++------ src/resolve/sourceComponent.ts | 16 ++++++++++------ test/convert/streams.test.ts | 2 +- yarn.lock | 12 ++++++------ 7 files changed, 42 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 7b8e5d84ee..0572a13970 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@salesforce/kit": "^1.9.2", "@salesforce/ts-types": "^1.7.2", "archiver": "^5.3.1", - "fast-xml-parser": "^3.21.1", + "fast-xml-parser": "^4.1.3", "got": "^11.8.6", "graceful-fs": "^4.2.11", "ignore": "^5.2.4", diff --git a/src/collections/componentSet.ts b/src/collections/componentSet.ts index 8aaf7998cf..0e8f33a74b 100644 --- a/src/collections/componentSet.ts +++ b/src/collections/componentSet.ts @@ -5,7 +5,7 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ /* eslint @typescript-eslint/unified-signatures:0 */ -import { j2xParser } from 'fast-xml-parser'; +import { XMLBuilder } from 'fast-xml-parser'; import { AuthInfo, Connection, Logger, Messages, SfError } from '@salesforce/core'; import { MetadataApiDeploy, @@ -453,14 +453,16 @@ export class ComponentSet extends LazyCollection { * @param forDestructiveChanges Whether to build a manifest for destructive changes. */ public async getPackageXml(indentation = 4, destructiveType?: DestructiveChangesType): Promise { - const j2x = new j2xParser({ + const builder = new XMLBuilder({ format: true, - indentBy: new Array(indentation + 1).join(' '), + indentBy: ''.padEnd(indentation, ' '), + ignoreAttributes: false, }); const toParse = await this.getObject(destructiveType); toParse.Package[XML_NS_KEY] = XML_NS_URL; - return XML_DECL.concat(j2x.parse(toParse) as string); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + return XML_DECL.concat(builder.build(toParse)); } /** diff --git a/src/convert/streams.ts b/src/convert/streams.ts index 2b89e10411..e2d2e87f2c 100644 --- a/src/convert/streams.ts +++ b/src/convert/streams.ts @@ -11,7 +11,7 @@ import { Messages, SfError } from '@salesforce/core'; import { Archiver, create as createArchive } from 'archiver'; import { createWriteStream, existsSync } from 'graceful-fs'; import { JsonMap } from '@salesforce/ts-types'; -import { j2xParser } from 'fast-xml-parser'; +import { XMLBuilder } from 'fast-xml-parser'; import { Logger } from '@salesforce/core'; import { MetadataResolver, SourceComponent } from '../resolve'; import { SourcePath, XML_DECL } from '../common'; @@ -261,8 +261,15 @@ export class JsToXml extends Readable { } public _read(): void { - const js2Xml = new j2xParser({ format: true, indentBy: ' ', ignoreAttributes: false, cdataTagName: '__cdata' }); - const xmlContent = XML_DECL.concat(js2Xml.parse(this.xmlObject) as string); + const builder = new XMLBuilder({ + format: true, + indentBy: ' ', + ignoreAttributes: false, + cdataPropName: '__cdata', + }); + + const builtXml = String(builder.build(this.xmlObject)); + const xmlContent = XML_DECL.concat(builtXml); this.push(xmlContent); this.push(null); } diff --git a/src/resolve/manifestResolver.ts b/src/resolve/manifestResolver.ts index 37293ed8b9..8b0ee54554 100644 --- a/src/resolve/manifestResolver.ts +++ b/src/resolve/manifestResolver.ts @@ -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 { parse as parseXml } from 'fast-xml-parser'; +import { XMLParser } from 'fast-xml-parser'; import { ensureArray } from '@salesforce/kit'; import { MetadataType, RegistryAccess } from '../registry'; import { NodeFSTreeContainer, TreeContainer } from './treeContainers'; @@ -54,11 +54,13 @@ export class ManifestResolver { const file = await this.tree.readFile(manifestPath); - const parsedManifest: ParsedPackageManifest = ( - parseXml(file.toString(), { - stopNodes: ['version'], - }) as { Package: ParsedPackageManifest } - ).Package; + 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 packageTypeMembers = ensureArray(parsedManifest.types); const apiVersion = parsedManifest.version; diff --git a/src/resolve/sourceComponent.ts b/src/resolve/sourceComponent.ts index ce8f942817..02e38b277f 100644 --- a/src/resolve/sourceComponent.ts +++ b/src/resolve/sourceComponent.ts @@ -6,7 +6,7 @@ */ import { basename, join, dirname } from 'path'; import { Messages, SfError } from '@salesforce/core'; -import { parse, validate } from 'fast-xml-parser'; +import { XMLParser, XMLValidator } from 'fast-xml-parser'; import { get, getString, JsonMap } from '@salesforce/ts-types'; import { ensureArray } from '@salesforce/kit'; import { replacementIterations } from '../../src/convert/replacements'; @@ -286,11 +286,15 @@ export class SourceComponent implements MetadataComponent { private parse(contents: string): T { // include tag attributes and don't parse text node as number - const parsed = parse(contents.toString(), { + const parser = new XMLParser({ ignoreAttributes: false, - parseNodeValue: false, - cdataTagName: '__cdata', - }) as T; + parseTagValue: false, + parseAttributeValue: false, + cdataPropName: '__cdata', + ignoreDeclaration: true, + numberParseOptions: { leadingZeros: false, hex: false }, + }); + const parsed = parser.parse(String(contents)) as T; const [firstElement] = Object.keys(parsed); if (firstElement === this.type.name) { return parsed; @@ -306,7 +310,7 @@ export class SourceComponent implements MetadataComponent { return this.parse(contents); } catch (e) { // only attempt validating once there's an error to avoid the performance hit of validating every file - const validation = validate(contents); + const validation = XMLValidator.validate(contents); if (validation !== true) { throw new SfError( messages.getMessage('invalid_xml_parsing', [ diff --git a/test/convert/streams.test.ts b/test/convert/streams.test.ts index 082d038ec4..eb516260c8 100644 --- a/test/convert/streams.test.ts +++ b/test/convert/streams.test.ts @@ -536,7 +536,7 @@ describe('Streams', () => { expectedBody += `\n`; expectedBody += ' bar\n'; expectedBody += ' \n'; - expectedBody += 'Hello

]]>\n'; + expectedBody += ' Hello

]]>\n'; expectedBody += '
\n'; expectedBody += '
\n'; diff --git a/yarn.lock b/yarn.lock index cef4301c88..dd1b7d2247 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3262,12 +3262,12 @@ fast-levenshtein@^3.0.0: dependencies: fastest-levenshtein "^1.0.7" -fast-xml-parser@^3.21.1: - version "3.21.1" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz#152a1d51d445380f7046b304672dd55d15c9e736" - integrity sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg== +fast-xml-parser@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.1.3.tgz#0254ad0d4d27f07e6b48254b068c0c137488dd97" + integrity sha512-LsNDahCiCcJPe8NO7HijcnukHB24tKbfDDA5IILx9dmW3Frb52lhbeX6MPNUSvyGNfav2VTYpJ/OqkRoVLrh2Q== dependencies: - strnum "^1.0.4" + strnum "^1.0.5" fastest-levenshtein@^1.0.7: version "1.0.16" @@ -6921,7 +6921,7 @@ strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1. resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strnum@^1.0.4: +strnum@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==