diff --git a/package.json b/package.json index e78ca556..84b4e94e 100644 --- a/package.json +++ b/package.json @@ -43,9 +43,6 @@ "/oclif.manifest.json" ], "dependencies": { - "@salesforce/core": "^3.36.0", - "@salesforce/kit": "^1.9.2", - "@salesforce/source-deploy-retrieve": "^8.4.0", "@salesforce/core": "^3.36.1", "@salesforce/kit": "^1.9.2", "@salesforce/source-deploy-retrieve": "^8.4.0", @@ -60,6 +57,7 @@ "@salesforce/dev-scripts": "^4.3.0", "@salesforce/prettier-config": "^0.0.2", "@salesforce/ts-sinon": "^1.4.6", + "@types/graceful-fs": "^4.1.6", "@types/shelljs": "^0.8.11", "@typescript-eslint/eslint-plugin": "^5.59.0", "@typescript-eslint/parser": "^5.59.0", diff --git a/src/shared/functions.ts b/src/shared/functions.ts index 0e23fdfc..dbf71635 100644 --- a/src/shared/functions.ts +++ b/src/shared/functions.ts @@ -49,20 +49,28 @@ export const chunkArray = (arr: T[], size: number): T[][] => export const ensureRelative = (filePath: string, projectPath: string): string => isAbsolute(filePath) ? relative(projectPath, filePath) : filePath; +export type ParsedCustomLabels = { + CustomLabels: { labels: Array<{ fullName: string }> }; +}; + /** * A method to help delete custom labels from a file, or the entire file if there are no more labels * * @param filename - a path to a custom labels file * @param customLabels - an array of SourceComponents representing the custom labels to delete + * @returns -json equivalent of the custom labels file's contents OR undefined if the file was deleted/not written */ -export const deleteCustomLabels = (filename: string, customLabels: SourceComponent[]): Promise => { +export const deleteCustomLabels = async ( + filename: string, + customLabels: SourceComponent[] +): Promise => { const customLabelsToDelete = customLabels .filter((label) => label.type.id === 'customlabel') .map((change) => change.fullName); // if we don't have custom labels, we don't need to do anything if (!customLabelsToDelete.length) { - return Promise.resolve(); + return undefined; } // for custom labels, we need to remove the individual label from the xml file // so we'll parse the xml @@ -71,9 +79,7 @@ export const deleteCustomLabels = (filename: string, customLabels: SourceCompone ignoreAttributes: false, attributeNamePrefix: '@_', }); - const cls = parser.parse(fs.readFileSync(filename, 'utf8')) as { - CustomLabels: { labels: Array<{ fullName: string }> }; - }; + const cls = parser.parse(fs.readFileSync(filename, 'utf8')) as ParsedCustomLabels; // delete the labels from the json based on their fullName's cls.CustomLabels.labels = ensureArray(cls.CustomLabels.labels).filter( @@ -82,7 +88,8 @@ export const deleteCustomLabels = (filename: string, customLabels: SourceCompone if (cls.CustomLabels.labels.length === 0) { // we've deleted everything, so let's delete the file - return fs.promises.unlink(filename); + await fs.promises.unlink(filename); + return undefined; } else { // we need to write the file json back to xml back to the fs const builder = new XMLBuilder({ @@ -93,6 +100,7 @@ export const deleteCustomLabels = (filename: string, customLabels: SourceCompone }); // and then write that json back to xml and back to the fs const xml = builder.build(cls) as string; - return fs.promises.writeFile(filename, xml); + await fs.promises.writeFile(filename, xml); + return cls; } }; diff --git a/test/unit/deleteCustomLabels.test.ts b/test/unit/deleteCustomLabels.test.ts index 314a3d70..ddee8e9b 100644 --- a/test/unit/deleteCustomLabels.test.ts +++ b/test/unit/deleteCustomLabels.test.ts @@ -54,7 +54,7 @@ describe('deleteCustomLabels', () => { }); describe('deleteCustomLabels', () => { - it('will delete a singular custom label from a file', () => { + it('will delete a singular custom label from a file', async () => { const labels = [ { type: { id: 'customlabel', name: 'CustomLabel' }, @@ -62,13 +62,12 @@ describe('deleteCustomLabels', () => { } as SourceComponent, ]; - void deleteCustomLabels('labels/CustomLabels.labels-meta.xml', labels); - expect(fsWriteStub.firstCall.args[1]).to.not.include('DeleteMe'); - expect(fsWriteStub.firstCall.args[1]).to.include('KeepMe1'); - expect(fsWriteStub.firstCall.args[1]).to.include('KeepMe2'); + const result = await deleteCustomLabels('labels/CustomLabels.labels-meta.xml', labels); + const resultLabels = result?.CustomLabels.labels.map((label) => label.fullName); + expect(resultLabels).to.deep.equal(['KeepMe1', 'KeepMe2']); expect(fsReadStub.callCount).to.equal(1); }); - it('will delete a multiple custom labels from a file', () => { + it('will delete a multiple custom labels from a file', async () => { const labels = [ { type: { id: 'customlabel', name: 'CustomLabel' }, @@ -80,14 +79,13 @@ describe('deleteCustomLabels', () => { }, ] as SourceComponent[]; - void deleteCustomLabels('labels/CustomLabels.labels-meta.xml', labels); - expect(fsWriteStub.firstCall.args[1]).to.include('DeleteMe'); - expect(fsWriteStub.firstCall.args[1]).to.not.include('KeepMe1'); - expect(fsWriteStub.firstCall.args[1]).to.not.include('KeepMe2'); + const result = await deleteCustomLabels('labels/CustomLabels.labels-meta.xml', labels); + const resultLabels = result?.CustomLabels.labels.map((label) => label.fullName); + expect(resultLabels).to.deep.equal(['DeleteMe']); expect(fsReadStub.callCount).to.equal(1); }); - it('will delete the file when everything is deleted', () => { + it('will delete the file when everything is deleted', async () => { const labels = [ { type: { id: 'customlabel', name: 'CustomLabel' }, @@ -103,12 +101,13 @@ describe('deleteCustomLabels', () => { }, ] as SourceComponent[]; - void deleteCustomLabels('labels/CustomLabels.labels-meta.xml', labels); + const result = await deleteCustomLabels('labels/CustomLabels.labels-meta.xml', labels); + expect(result).to.equal(undefined); expect(fsUnlinkStub.callCount).to.equal(1); expect(fsReadStub.callCount).to.equal(1); }); - it('will delete the file when only a single label is present and deleted', () => { + it('will delete the file when only a single label is present and deleted', async () => { fsReadStub.returns( '\n' + '\n' + @@ -128,12 +127,13 @@ describe('deleteCustomLabels', () => { }, ] as SourceComponent[]; - void deleteCustomLabels('labels/CustomLabels.labels-meta.xml', labels); + const result = await deleteCustomLabels('labels/CustomLabels.labels-meta.xml', labels); + expect(result).to.equal(undefined); expect(fsUnlinkStub.callCount).to.equal(1); expect(fsReadStub.callCount).to.equal(1); }); - it('no custom labels, quick exit and do nothing', () => { + it('no custom labels, quick exit and do nothing', async () => { const labels = [ { type: { id: 'apexclass', name: 'ApexClass' }, @@ -141,7 +141,8 @@ describe('deleteCustomLabels', () => { }, ] as SourceComponent[]; - void deleteCustomLabels('labels/CustomLabels.labels-meta.xml', labels); + const result = await deleteCustomLabels('labels/CustomLabels.labels-meta.xml', labels); + expect(result).to.equal(undefined); expect(fsUnlinkStub.callCount).to.equal(0); expect(fsWriteStub.callCount).to.equal(0); expect(fsReadStub.callCount).to.equal(0); diff --git a/yarn.lock b/yarn.lock index 03f2ec8d..25eb2a00 100644 --- a/yarn.lock +++ b/yarn.lock @@ -890,30 +890,7 @@ strip-ansi "6.0.1" ts-retry-promise "^0.7.0" -"@salesforce/core@^3.34.6": - version "3.34.7" - resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-3.34.7.tgz#445efe5c76fbab53e6c891563aa9b0dc5dd24179" - integrity sha512-C4zyXzLAV5ITMChC8dCP+6Kk3t5vloyP2eXpqBOw96OzF5OaCiN5/TayNN8YJl64pvFFny7FgAQPKk7omFXNSA== - dependencies: - "@salesforce/bunyan" "^2.0.0" - "@salesforce/kit" "^1.9.2" - "@salesforce/schemas" "^1.5.1" - "@salesforce/ts-types" "^1.7.2" - "@types/graceful-fs" "^4.1.6" - "@types/semver" "^7.3.13" - ajv "^8.12.0" - archiver "^5.3.0" - change-case "^4.1.2" - debug "^3.2.7" - faye "^1.4.0" - form-data "^4.0.0" - graceful-fs "^4.2.11" - js2xmlparser "^4.0.1" - jsforce "^2.0.0-beta.21" - jsonwebtoken "9.0.0" - ts-retry-promise "^0.7.0" - -"@salesforce/core@^3.34.8", "@salesforce/core@^3.36.0", "@salesforce/core@^3.36.1": +"@salesforce/core@^3.34.6", "@salesforce/core@^3.34.8", "@salesforce/core@^3.36.0", "@salesforce/core@^3.36.1": version "3.36.1" resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-3.36.1.tgz#053a5e1079b9749b62e461e6ac3e630b5689694a" integrity sha512-kcjyr9bj35nnL8Bqv8U39xeho3CrZYXJiS/X5X1eEHVNZLd9zckrmKrh1V7z8ElCFpsJrewT989SJsdvi9kE8w== @@ -934,48 +911,6 @@ jsonwebtoken "9.0.0" ts-retry-promise "^0.7.0" -"@salesforce/core@^3.34.8": - version "3.36.1" - resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-3.36.1.tgz#053a5e1079b9749b62e461e6ac3e630b5689694a" - integrity sha512-kcjyr9bj35nnL8Bqv8U39xeho3CrZYXJiS/X5X1eEHVNZLd9zckrmKrh1V7z8ElCFpsJrewT989SJsdvi9kE8w== - dependencies: - "@salesforce/bunyan" "^2.0.0" - "@salesforce/kit" "^1.9.2" - "@salesforce/schemas" "^1.5.1" - "@salesforce/ts-types" "^1.7.2" - "@types/semver" "^7.3.13" - ajv "^8.12.0" - archiver "^5.3.0" - change-case "^4.1.2" - debug "^3.2.7" - faye "^1.4.0" - form-data "^4.0.0" - js2xmlparser "^4.0.1" - jsforce "^2.0.0-beta.21" - jsonwebtoken "9.0.0" - ts-retry-promise "^0.7.0" - -"@salesforce/core@^3.36.0": - version "3.36.0" - resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-3.36.0.tgz#cbff147d888eee0b921e368c1fdc1a1a3c2eacab" - integrity sha512-LOeSJgozf5B1S8C98/K3afewRsathfEm+HrXxaFXJjITFfIhxqcIDB5xC1cw0VikfRUlq7dQocmVsvezcK0Ghw== - dependencies: - "@salesforce/bunyan" "^2.0.0" - "@salesforce/kit" "^1.9.2" - "@salesforce/schemas" "^1.5.1" - "@salesforce/ts-types" "^1.7.2" - "@types/semver" "^7.3.13" - ajv "^8.12.0" - archiver "^5.3.0" - change-case "^4.1.2" - debug "^3.2.7" - faye "^1.4.0" - form-data "^4.0.0" - js2xmlparser "^4.0.1" - jsforce "^2.0.0-beta.21" - jsonwebtoken "9.0.0" - ts-retry-promise "^0.7.0" - "@salesforce/dev-config@^3.0.0", "@salesforce/dev-config@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@salesforce/dev-config/-/dev-config-3.1.0.tgz#8eb5b35860ff60d1c1dc3fd9329b01a28475d5b9" @@ -4617,32 +4552,6 @@ jsforce@^2.0.0-beta.21: strip-ansi "^6.0.0" xml2js "^0.5.0" -jsforce@^2.0.0-beta.21: - version "2.0.0-beta.21" - resolved "https://registry.yarnpkg.com/jsforce/-/jsforce-2.0.0-beta.21.tgz#04c94d762d2536bf1af3062d5cca206656f5b12b" - integrity sha512-74GUF/96vYBNZo3SUccXtt4CmfvZ0iqTSc0Z3OB940Ec7oU6coOAGhlCZ+XprXaHOMMhXMXrZQ1PCd16yjIA7A== - dependencies: - "@babel/runtime" "^7.12.5" - "@babel/runtime-corejs3" "^7.12.5" - "@types/node" "^12.19.9" - abort-controller "^3.0.0" - base64url "^3.0.1" - commander "^4.0.1" - core-js "^3.6.4" - csv-parse "^4.8.2" - csv-stringify "^5.3.4" - faye "^1.4.0" - form-data "^4.0.0" - fs-extra "^8.1.0" - https-proxy-agent "^5.0.0" - inquirer "^7.0.0" - multistream "^3.1.0" - node-fetch "^2.6.1" - open "^7.0.0" - regenerator-runtime "^0.13.3" - strip-ansi "^6.0.0" - xml2js "^0.5.0" - json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"