diff --git a/package.json b/package.json index 809beecde..f6fcb93f8 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "packaging" ], "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "files": [ "docs", @@ -42,10 +42,10 @@ ], "dependencies": { "@oclif/core": "^2.15.0", - "@salesforce/core": "^5.3.14", + "@salesforce/core": "^6.1.2", "@salesforce/kit": "^3.0.15", "@salesforce/schemas": "^1.6.1", - "@salesforce/source-deploy-retrieve": "^9.8.5", + "@salesforce/source-deploy-retrieve": "^10.0.0", "@salesforce/ts-types": "^2.0.9", "fast-xml-parser": "^4.3.1", "globby": "^11", diff --git a/src/interfaces/packagingInterfacesAndType.ts b/src/interfaces/packagingInterfacesAndType.ts index 86cd19858..5f964da68 100644 --- a/src/interfaces/packagingInterfacesAndType.ts +++ b/src/interfaces/packagingInterfacesAndType.ts @@ -172,8 +172,6 @@ export type PackageDescriptorJson = Partial & features: string[]; orgPreferences: string[]; snapshot: string; - unpackagedMetadata: NamedPackageDir; - seedMetadata: NamedPackageDir; apexTestAccess: { permissionSets: string[] | string; permissionSetLicenses: string[] | string }; permissionSetNames: string[]; permissionSetLicenseDeveloperNames: string[]; diff --git a/src/package/packageVersion.ts b/src/package/packageVersion.ts index b17ce4961..a9d6ec692 100644 --- a/src/package/packageVersion.ts +++ b/src/package/packageVersion.ts @@ -634,12 +634,16 @@ export class PackageVersion { }`; const build = versionResult.BuildNumber ? `-${versionResult.BuildNumber}` : ''; const branch = versionResult.Branch ? `-${versionResult.Branch}` : ''; - // set packageAliases entry '@..--: ' - const packageAliases = this.project.getSfProjectJson().getContents().packageAliases ?? {}; - if (results.SubscriberPackageVersionId) { - packageAliases[`${version}${build}${branch}`] = results.SubscriberPackageVersionId; - } - this.project.getSfProjectJson().getContents().packageAliases = packageAliases; + const originalPackageAliases = this.project.getSfProjectJson().get('packageAliases') ?? {}; + const updatedPackageAliases = { + ...originalPackageAliases, + ...(results.SubscriberPackageVersionId + ? // set packageAliases entry '@..--: ' + { [`${version}${build}${branch}`]: results.SubscriberPackageVersionId } + : {}), + }; + + this.project.getSfProjectJson().set('packageAliases', updatedPackageAliases); await this.project.getSfProjectJson().write(); } } diff --git a/src/package/packageVersionCreate.ts b/src/package/packageVersionCreate.ts index ea4a2c67c..6f953b698 100644 --- a/src/package/packageVersionCreate.ts +++ b/src/package/packageVersionCreate.ts @@ -30,6 +30,7 @@ import SettingsGenerator from '@salesforce/core/lib/org/scratchOrgSettingsGenera import { PackageDirDependency } from '@salesforce/core/lib/sfProject'; import { cloneJson, ensureArray, env } from '@salesforce/kit'; import { XMLParser, XMLBuilder } from 'fast-xml-parser'; +import { isString } from '@salesforce/ts-types'; import * as pkgUtils from '../utils/packageUtils'; import { BY_LABEL, @@ -122,7 +123,7 @@ export class PackageVersionCreate { dependency.packageId = packageIdFromAlias; pkgUtils.validateId(pkgUtils.BY_LABEL.PACKAGE_ID, dependency.packageId); - this.validateVersionNumber( + validateVersionNumber( dependency.versionNumber, BuildNumberToken.LATEST_BUILD_NUMBER_TOKEN, BuildNumberToken.RELEASED_BUILD_NUMBER_TOKEN @@ -402,9 +403,8 @@ export class PackageVersionCreate { if (resultValues.length > 0) { packageDescriptorJson.dependencies = resultValues as PackageDirDependency[]; } - - this.cleanPackageDescriptorJson(packageDescriptorJson); - this.setPackageDescriptorJsonValues(packageDescriptorJson); + packageDescriptorJson = cleanPackageDescriptorJson(packageDescriptorJson); + packageDescriptorJson = setPackageDescriptorJsonValues(packageDescriptorJson, this.options, this.logger); await fs.promises.mkdir(packageVersTmpRoot, { recursive: true }); await fs.promises.mkdir(packageVersBlobDirectory, { recursive: true }); @@ -522,8 +522,8 @@ export class PackageVersionCreate { // don't package the profiles from any un-packagedMetadata dir in the project profileExcludeDirs = this.project .getPackageDirectories() - .map((packageDir) => (packageDir as PackageDescriptorJson).unpackagedMetadata?.path) - .filter((packageDirPath) => packageDirPath) as string[]; + .map((packageDir) => packageDir.unpackagedMetadata?.path) + .filter(isString); let debugMsg = 'Searching for profiles to include from all packageDirectories'; if (profileExcludeDirs?.length) { @@ -618,7 +618,7 @@ export class PackageVersionCreate { // establish the package Id (0ho) and load the package directory let packageName: string | undefined; - let packageObject: PackageDir | undefined; + let packageObject: NamedPackageDir | undefined; if (this.options.packageId) { const pkg = this.options.packageId; // for backward compatibility allow for a packageDirectory package property to be an id (0Ho) instead of an alias. @@ -646,7 +646,7 @@ export class PackageVersionCreate { this.options.packageId ?? this.options.path, ]); } else { - this.packageObject = packageObject as NamedPackageDir; + this.packageObject = packageObject; } this.packageId = this.project.getPackageIdFromAlias(packageName) ?? packageName; @@ -691,9 +691,8 @@ export class PackageVersionCreate { } private async getPackageDirFromId(pkg: string): Promise { - let dir: PackageDir[]; if (pkg.startsWith('0Ho')) { - dir = (await this.project.getSfProjectJson().getPackageDirectories()).filter((p) => p.package === pkg); + const dir = (await this.project.getSfProjectJson().getPackageDirectories()).filter((p) => p.package === pkg); if (dir.length === 1) { return dir[0]; } @@ -726,100 +725,6 @@ export class PackageVersionCreate { } } - /** - * Cleans invalid attribute(s) from the packageDescriptorJSON - */ - // eslint-disable-next-line class-methods-use-this - private cleanPackageDescriptorJson(packageDescriptorJson: PackageDescriptorJson): PackageDescriptorJson { - delete packageDescriptorJson.default; // for client-side use only, not needed - delete packageDescriptorJson.includeProfileUserLicenses; // for client-side use only, not needed - delete packageDescriptorJson.unpackagedMetadata; // for client-side use only, not needed - delete packageDescriptorJson.seedMetadata; // for client-side use only, not needed - delete packageDescriptorJson.branch; // for client-side use only, not needed - delete packageDescriptorJson.fullPath; // for client-side use only, not needed - delete packageDescriptorJson.name; // for client-side use only, not needed - delete packageDescriptorJson.scopeProfiles; // for client-side use only, not needed - return packageDescriptorJson; - } - - /** - * Sets default or override values for packageDescriptorJSON attribs - */ - private setPackageDescriptorJsonValues(packageDescriptorJson: PackageDescriptorJson): void { - const options = this.options; - if (options.versionname) { - packageDescriptorJson.versionName = options.versionname; - } - if (options.versiondescription) { - packageDescriptorJson.versionDescription = options.versiondescription; - } - if (options.versionnumber) { - packageDescriptorJson.versionNumber = options.versionnumber; - } - - // default versionName to versionNumber if unset, stripping .NEXT if present - if (!packageDescriptorJson.versionName) { - const versionNumber = packageDescriptorJson.versionNumber; - packageDescriptorJson.versionName = - versionNumber?.split(pkgUtils.VERSION_NUMBER_SEP)[3] === BuildNumberToken.NEXT_BUILD_NUMBER_TOKEN - ? versionNumber.substring( - 0, - versionNumber.indexOf(pkgUtils.VERSION_NUMBER_SEP + BuildNumberToken.NEXT_BUILD_NUMBER_TOKEN) - ) - : versionNumber; - - this.logger.warn(messages.getMessage('defaultVersionName', [packageDescriptorJson.versionName])); - } - - if (options.releasenotesurl) { - packageDescriptorJson.releaseNotesUrl = options.releasenotesurl; - } - if (packageDescriptorJson.releaseNotesUrl && !SfdcUrl.isValidUrl(packageDescriptorJson.releaseNotesUrl)) { - throw messages.createError('malformedUrl', ['releaseNotesUrl', packageDescriptorJson.releaseNotesUrl]); - } - - if (options.postinstallurl) { - packageDescriptorJson.postInstallUrl = options.postinstallurl; - } - if (packageDescriptorJson.postInstallUrl && !SfdcUrl.isValidUrl(packageDescriptorJson.postInstallUrl)) { - throw messages.createError('malformedUrl', ['postInstallUrl', packageDescriptorJson.postInstallUrl]); - } - - if (options.postinstallscript) { - packageDescriptorJson.postInstallScript = options.postinstallscript; - } - if (options.uninstallscript) { - packageDescriptorJson.uninstallScript = options.uninstallscript; - } - } - - // eslint-disable-next-line class-methods-use-this - private validateVersionNumber( - versionNumberString: string, - supportedBuildNumberToken: string, - supportedBuildNumberToken2?: string - ): string { - const versionNumber = VersionNumber.from(versionNumberString); - // build number can be a number or valid token - if ( - Number.isNaN(parseInt(`${versionNumber.build}`, 10)) && - versionNumber.build !== supportedBuildNumberToken && - versionNumber.build !== supportedBuildNumberToken2 - ) { - if (supportedBuildNumberToken2) { - throw messages.createError('errorInvalidBuildNumberForKeywords', [ - versionNumberString, - supportedBuildNumberToken, - supportedBuildNumberToken2, - ]); - } else { - throw messages.createError('errorInvalidBuildNumber', [versionNumberString, supportedBuildNumberToken]); - } - } - - return versionNumberString; - } - private async validatePatchVersion(versionNumberString: string, packageId: string): Promise { const query = `SELECT ContainerOptions FROM Package2 WHERE id ='${packageId}'`; const queryResult = await this.connection.tooling.query(query); @@ -950,7 +855,7 @@ export class PackageVersionCreate { origSpecifiedAncestor = packageDescriptorJson.ancestorVersion; } - return this.validateAncestorId( + return validateAncestorId( ancestorId, highestReleasedVersion, explicitUseNoAncestor, @@ -960,39 +865,6 @@ export class PackageVersionCreate { ); } - // eslint-disable-next-line class-methods-use-this - private validateAncestorId( - ancestorId: string, - highestReleasedVersion: PackagingSObjects.Package2Version | null | undefined, - explicitUseNoAncestor: boolean, - isPatch: boolean, - skipAncestorCheck: boolean, - origSpecifiedAncestor: string - ): string { - if (explicitUseNoAncestor) { - if (!highestReleasedVersion) { - return ''; - } else { - // the explicitUseNoAncestor && skipAncestorCheck case is handled above - throw messages.createError('errorAncestorNoneNotAllowed', [getPackageVersionNumber(highestReleasedVersion)]); - } - } - if (!isPatch && !skipAncestorCheck) { - if (highestReleasedVersion) { - if (highestReleasedVersion.Id !== ancestorId) { - throw messages.createError('errorAncestorNotHighest', [ - origSpecifiedAncestor, - getPackageVersionNumber(highestReleasedVersion), - ]); - } - } else { - // looks like the initial version:create - allow - ancestorId = ''; - } - } - return ancestorId; - } - private async getAncestorIdHighestRelease( packageId: string | undefined, versionNumberString: string, @@ -1185,3 +1057,118 @@ export const packageXmlJsonToXmlString = (packageXmlJson: PackageXml): string => }) ); }; + +// exported for UT +export const validateAncestorId = ( + ancestorId: string, + highestReleasedVersion: PackagingSObjects.Package2Version | null | undefined, + explicitUseNoAncestor: boolean, + isPatch: boolean, + skipAncestorCheck: boolean, + origSpecifiedAncestor: string +): string => { + if (explicitUseNoAncestor) { + if (!highestReleasedVersion) { + return ''; + } else { + // the explicitUseNoAncestor && skipAncestorCheck case is handled above + throw messages.createError('errorAncestorNoneNotAllowed', [getPackageVersionNumber(highestReleasedVersion)]); + } + } + if (!isPatch && !skipAncestorCheck) { + if (highestReleasedVersion) { + if (highestReleasedVersion.Id !== ancestorId) { + throw messages.createError('errorAncestorNotHighest', [ + origSpecifiedAncestor, + getPackageVersionNumber(highestReleasedVersion), + ]); + } + } else { + // looks like the initial version:create - allow + ancestorId = ''; + } + } + return ancestorId; +}; + +export const validateVersionNumber = ( + versionNumberString: string, + supportedBuildNumberToken: string, + supportedBuildNumberToken2?: string +): string => { + const versionNumber = VersionNumber.from(versionNumberString); + // build number can be a number or valid token + if ( + Number.isNaN(parseInt(`${versionNumber.build}`, 10)) && + versionNumber.build !== supportedBuildNumberToken && + versionNumber.build !== supportedBuildNumberToken2 + ) { + if (supportedBuildNumberToken2) { + throw messages.createError('errorInvalidBuildNumberForKeywords', [ + versionNumberString, + supportedBuildNumberToken, + supportedBuildNumberToken2, + ]); + } else { + throw messages.createError('errorInvalidBuildNumber', [versionNumberString, supportedBuildNumberToken]); + } + } + + return versionNumberString; +}; + +/** + * Sets default or override values for packageDescriptorJSON attribs + */ +const setPackageDescriptorJsonValues = ( + packageDescriptorJson: PackageDescriptorJson, + options: PackageVersionCreateOptions, + logger: Logger +): PackageDescriptorJson => { + const merged = { + ...packageDescriptorJson, + ...(options.versionname ? { versionName: options.versionname } : {}), + ...(options.versiondescription ? { versionDescription: options.versiondescription } : {}), + ...(options.versionnumber ? { versionNumber: options.versionnumber } : {}), + ...(options.releasenotesurl ? { releaseNotesUrl: options.releasenotesurl } : {}), + ...(options.postinstallurl ? { postInstallUrl: options.postinstallurl } : {}), + ...(options.postinstallscript ? { postInstallScript: options.postinstallscript } : {}), + ...(options.postinstallurl ? { postInstallUrl: options.postinstallurl } : {}), + }; + if (merged.postInstallUrl && !SfdcUrl.isValidUrl(merged.postInstallUrl)) { + throw messages.createError('malformedUrl', ['postInstallUrl', merged.postInstallUrl]); + } + + // default versionName to versionNumber if unset, stripping .NEXT if present + if (!merged.versionName) { + const versionNumber = merged.versionNumber; + merged.versionName = + versionNumber?.split(pkgUtils.VERSION_NUMBER_SEP)[3] === BuildNumberToken.NEXT_BUILD_NUMBER_TOKEN + ? versionNumber.substring( + 0, + versionNumber.indexOf(pkgUtils.VERSION_NUMBER_SEP + BuildNumberToken.NEXT_BUILD_NUMBER_TOKEN) + ) + : versionNumber; + + logger.warn(messages.getMessage('defaultVersionName', [merged.versionName])); + } + return merged; +}; + +/** + * Cleans client-side-only attribute(s) from the packageDescriptorJSON so it can go to API + */ +const cleanPackageDescriptorJson = (packageDescriptorJson: PackageDescriptorJson): PackageDescriptorJson => { + // properties only used by the client side + const clientOnlyProps = [ + 'default', + 'includeProfileUserLicenses', + 'unpackagedMetadata', + 'seedMetadata', + 'branch', + 'fullPath', + 'name', + 'scopeProfiles', + ]; + return Object.fromEntries(Object.entries(packageDescriptorJson).filter(([key]) => !clientOnlyProps.includes(key))); +}; diff --git a/src/package/packageVersionRetrieve.ts b/src/package/packageVersionRetrieve.ts index a09d02013..4820f522f 100644 --- a/src/package/packageVersionRetrieve.ts +++ b/src/package/packageVersionRetrieve.ts @@ -201,8 +201,8 @@ async function attemptToUpdateProjectJson( ); project.getSfProjectJson().addPackageAlias(alias, writtenId); - if (pkgData.ContainerOptions === 'Managed' && !project.getSfProjectJson().getContents().namespace) { - project.getSfProjectJson().getContents().namespace = pkgData.NamespacePrefix; + if (pkgData.ContainerOptions === 'Managed' && !project.getSfProjectJson().get('namespace')) { + project.getSfProjectJson().set('namespace', pkgData.NamespacePrefix); } await project.getSfProjectJson().write(); diff --git a/test/package/packageTest.nut.ts b/test/package/packageTest.nut.ts index 004e7d9c0..ad62336e1 100644 --- a/test/package/packageTest.nut.ts +++ b/test/package/packageTest.nut.ts @@ -611,7 +611,7 @@ describe('ancestry tests', () => { ]) as { [alias: string]: string }; pjson.set('packageAliases', aliases); pjson.set('namespace', pvRecords[0].Package2.NamespacePrefix); - pjson.writeSync(); + await pjson.write(); }); after(async () => { diff --git a/test/package/packageVersion.test.ts b/test/package/packageVersion.test.ts index a027ed472..1302a3f3b 100644 --- a/test/package/packageVersion.test.ts +++ b/test/package/packageVersion.test.ts @@ -24,39 +24,38 @@ describe('Package Version', () => { beforeEach(async () => { $$.inProject(true); project = SfProject.getInstance(); - await project.getSfProjectJson().write({ - packageDirectories: [ - { - path: 'pkg', - package: 'dep', - versionName: 'ver 0.1', - versionNumber: '0.1.0.NEXT', - default: false, - name: 'pkg', + project.getSfProjectJson().set('packageDirectories', [ + { + path: 'pkg', + package: 'dep', + versionName: 'ver 0.1', + versionNumber: '0.1.0.NEXT', + default: false, + }, + { + path: 'force-app', + package: 'TEST', + versionName: 'ver 0.1', + versionNumber: '0.1.0.NEXT', + default: true, + ancestorId: 'TEST2', + unpackagedMetadata: { + path: 'unpackaged', }, - { - path: 'force-app', - package: 'TEST', - versionName: 'ver 0.1', - versionNumber: '0.1.0.NEXT', - default: true, - ancestorId: 'TEST2', - unpackagedMetadata: { - path: 'unpackaged', + dependencies: [ + { + package: 'DEP@0.1.0-1', }, - dependencies: [ - { - package: 'DEP@0.1.0-1', - }, - ], - }, - ], - packageAliases: { - dupPkg1: packageId, - dupPkg2: packageId, - uniquePkg: uniquePackageId, + ], }, + ]); + project.getSfProjectJson().set('packageAliases', { + dupPkg1: packageId, + dupPkg2: packageId, + uniquePkg: uniquePackageId, }); + await project.getSfProjectJson().write(); + await fs.promises.mkdir(path.join(project.getPath(), 'force-app')); stubContext($$); await $$.stubAuths(testOrg); diff --git a/test/package/packageVersionCreate.test.ts b/test/package/packageVersionCreate.test.ts index e19f15fe5..4f551ad4d 100644 --- a/test/package/packageVersionCreate.test.ts +++ b/test/package/packageVersionCreate.test.ts @@ -14,6 +14,8 @@ import { PackageVersionCreate, packageXmlStringToPackageXmlJson, packageXmlJsonToXmlString, + validateAncestorId, + validateVersionNumber, } from '../../src/package/packageVersionCreate'; import * as PVCStubs from '../../src/package/packageVersionCreate'; import { PackagingSObjects } from '../../src/interfaces'; @@ -47,43 +49,45 @@ describe('Package Version Create', () => { beforeEach(async () => { $$.inProject(true); project = SfProject.getInstance(); - await project.getSfProjectJson().write({ - packageDirectories: [ - { - path: 'pkg', - package: 'DEP', - versionName: 'ver 0.1', - versionNumber: '0.1.0.NEXT', - default: false, - name: 'pkg', + project.getSfProjectJson().set('packageDirectories', [ + { + path: 'pkg', + package: 'DEP', + versionName: 'ver 0.1', + versionNumber: '0.1.0.NEXT', + default: false, + }, + { + path: 'force-app', + package: 'TEST', + versionName: 'ver 0.1', + versionNumber: '0.1.0.NEXT', + default: true, + ancestorId: 'TEST2', + unpackagedMetadata: { + path: 'unpackaged', }, - { - path: 'force-app', - package: 'TEST', - versionName: 'ver 0.1', - versionNumber: '0.1.0.NEXT', - default: true, - ancestorId: 'TEST2', - unpackagedMetadata: { - path: 'unpackaged', - }, - seedMetadata: { - path: 'seed', - }, - dependencies: [ - { - package: 'DEP@0.1.0-1', - }, - ], + seedMetadata: { + path: 'seed', }, - ], - packageAliases: { + dependencies: [ + { + package: 'DEP@0.1.0-1', + }, + ], + }, + ]); + project.getSfProjectJson().set( + 'packageAliases', + + { TEST: packageId, TEST2: '05i3i000000Gmj6XXX', DEP: '0Ho4J000000TNmPXXX', 'DEP@0.1.0-1': '04t3i000002eyYXXXX', - }, - }); + } + ); + await project.getSfProjectJson().write(); await fs.promises.mkdir(path.join(project.getPath(), 'force-app')); stubContext($$); await $$.stubAuths(testOrg); @@ -113,10 +117,10 @@ describe('Package Version Create', () => { }); it('should throw an error when no package directories exist in the sfdx-project.json', async () => { - await project.getSfProjectJson().write({ - packageDirectories: [], - packageAliases: {}, - }); + project.getSfProjectJson().set('packageDirectories', []); + project.getSfProjectJson().set('packageAliases', {}); + + await project.getSfProjectJson().write(); const pvc = new PackageVersionCreate({ connection, project, packageId }); try { await pvc.createPackageVersion(); @@ -362,7 +366,9 @@ describe('Package Version Create', () => { config.packageDirectories[1].dependencies[0].package = 'DEP'; config.packageDirectories[1].dependencies[0].versionNumber = '0.1.0.1'; } - await project.getSfProjectJson().write(config); + + project.getSfProjectJson().set('packageDirectories', config.packageDirectories); + await project.getSfProjectJson().write(); const pvc = new PackageVersionCreate({ connection, project, branch: 'main', packageId, skipancestorcheck: true }); stubConvert(); @@ -406,7 +412,8 @@ describe('Package Version Create', () => { config.packageDirectories[1].dependencies[0].versionNumber = '0.1.0.1'; config.packageDirectories[1].dependencies[0].branch = 'dev'; } - await project.getSfProjectJson().write(config); + project.getSfProjectJson().set('packageDirectories', config.packageDirectories); + await project.getSfProjectJson().write(); const pvc = new PackageVersionCreate({ connection, project, branch: 'main', packageId, skipancestorcheck: true }); stubConvert(); @@ -450,7 +457,8 @@ describe('Package Version Create', () => { config.packageDirectories[1].dependencies[0].versionNumber = '0.1.0.1'; config.packageDirectories[1].dependencies[0].branch = ''; } - await project.getSfProjectJson().write(config); + project.getSfProjectJson().set('packageDirectories', config.packageDirectories); + await project.getSfProjectJson().write(); const pvc = new PackageVersionCreate({ connection, project, branch: 'main', packageId, skipancestorcheck: true }); stubConvert(); @@ -610,21 +618,22 @@ describe('Package Version Create', () => { }); it('should validate options when package type = unlocked (ancestors)', async () => { - await project.getSfProjectJson().write({ - packageDirectories: [ - { - path: 'force-app', - package: 'TEST', - versionName: 'ver 0.1', - versionNumber: '0.1.0.NEXT', - default: true, - ancestorId: '123', - }, - ], - packageAliases: { - TEST: '0Ho3i000000Gmj6XXX', + project.getSfProjectJson().set('packageDirectories', [ + { + path: 'force-app', + package: 'TEST', + versionName: 'ver 0.1', + versionNumber: '0.1.0.NEXT', + default: true, + ancestorId: '123', }, + ]); + project.getSfProjectJson().set('packageAliases', { + TEST: '0Ho3i000000Gmj6XXX', }); + + await project.getSfProjectJson().write(); + packageTypeQuery.restore(); packageTypeQuery = $$.SANDBOX.stub(connection.tooling, 'query') .onFirstCall() // @ts-ignore @@ -645,21 +654,21 @@ describe('Package Version Create', () => { } // check ancestorVersion - await project.getSfProjectJson().write({ - packageDirectories: [ - { - path: 'force-app', - package: 'TEST', - versionName: 'ver 0.1', - versionNumber: '0.1.0.NEXT', - default: true, - ancestorVersion: '123', - }, - ], - packageAliases: { - TEST: '0Ho3i000000Gmj6XXX', + project.getSfProjectJson().set('packageDirectories', [ + { + path: 'force-app', + package: 'TEST', + versionName: 'ver 0.1', + versionNumber: '0.1.0.NEXT', + default: true, + ancestorVersion: '123', }, + ]); + project.getSfProjectJson().set('packageAliases', { + TEST: '0Ho3i000000Gmj6XXX', }); + await project.getSfProjectJson().write(); + try { await pvc.createPackageVersion(); } catch (e) { @@ -699,52 +708,50 @@ describe('Package Version Create', () => { }); it('should not package the profiles from unpackaged metadata dirs', async () => { - await project.getSfProjectJson().write({ - packageDirectories: [ - { - path: 'pkg', - package: 'dep', - versionName: 'ver 0.1', - versionNumber: '0.1.0.NEXT', - default: false, - name: 'pkg', - unpackagedMetadata: { - path: 'unpackaged-pkg', - }, - }, - { - path: 'force-app', - package: 'TEST', - versionName: 'ver 0.1', - versionNumber: '0.1.0.NEXT', - default: true, - ancestorId: 'TEST2', - unpackagedMetadata: { - path: 'unpackaged-force-app', - }, - seedMetadata: { - path: 'seed', - }, - dependencies: [ - { - package: 'DEP@0.1.0-1', - }, - ], - }, - { + project.getSfProjectJson().set('packageDirectories', [ + { + path: 'pkg', + package: 'dep', + versionName: 'ver 0.1', + versionNumber: '0.1.0.NEXT', + default: false, + unpackagedMetadata: { path: 'unpackaged-pkg', }, - { + }, + { + path: 'force-app', + package: 'TEST', + versionName: 'ver 0.1', + versionNumber: '0.1.0.NEXT', + default: true, + ancestorId: 'TEST2', + unpackagedMetadata: { path: 'unpackaged-force-app', }, - ], - packageAliases: { - TEST: packageId, - TEST2: '05i3i000000Gmj6XXX', - DEP: '05i3i000000Gmj6XXX', - 'DEP@0.1.0-1': '04t3i000002eyYXXXX', + seedMetadata: { + path: 'seed', + }, + dependencies: [ + { + package: 'DEP@0.1.0-1', + }, + ], }, + { + path: 'unpackaged-pkg', + }, + { + path: 'unpackaged-force-app', + }, + ]); + project.getSfProjectJson().set('packageAliases', { + TEST: packageId, + TEST2: '05i3i000000Gmj6XXX', + DEP: '05i3i000000Gmj6XXX', + 'DEP@0.1.0-1': '04t3i000002eyYXXXX', }); + await project.getSfProjectJson().write(); const pvc = new PackageVersionCreate({ connection, project, codecoverage: true, packageId }); const profileSpyGenerate = $$.SANDBOX.spy(PackageProfileApi.prototype, 'generateProfiles'); const profileSpyFilter = $$.SANDBOX.spy(PackageProfileApi.prototype, 'filterAndGenerateProfilesForManifest'); @@ -776,53 +783,51 @@ describe('Package Version Create', () => { }); it('should only package profiles in the package dir when scopeProfiles = true', async () => { - await project.getSfProjectJson().write({ - packageDirectories: [ - { - path: 'pkg', - package: 'dep', - versionName: 'ver 0.1', - versionNumber: '0.1.0.NEXT', - default: false, - name: 'pkg', - unpackagedMetadata: { - path: 'unpackaged-pkg', - }, - }, - { - path: 'force-app', - package: 'TEST', - versionName: 'ver 0.1', - versionNumber: '0.1.0.NEXT', - default: true, - ancestorId: 'TEST2', - scopeProfiles: true, - unpackagedMetadata: { - path: 'unpackaged-force-app', - }, - seedMetadata: { - path: 'seed', - }, - dependencies: [ - { - package: 'DEP@0.1.0-1', - }, - ], - }, - { + project.getSfProjectJson().set('packageDirectories', [ + { + path: 'pkg', + package: 'dep', + versionName: 'ver 0.1', + versionNumber: '0.1.0.NEXT', + default: false, + unpackagedMetadata: { path: 'unpackaged-pkg', }, - { + }, + { + path: 'force-app', + package: 'TEST', + versionName: 'ver 0.1', + versionNumber: '0.1.0.NEXT', + default: true, + ancestorId: 'TEST2', + scopeProfiles: true, + unpackagedMetadata: { path: 'unpackaged-force-app', }, - ], - packageAliases: { - TEST: packageId, - TEST2: '05i3i000000Gmj6XXX', - DEP: '05i3i000000Gmj6XXX', - 'DEP@0.1.0-1': '04t3i000002eyYXXXX', + seedMetadata: { + path: 'seed', + }, + dependencies: [ + { + package: 'DEP@0.1.0-1', + }, + ], + }, + { + path: 'unpackaged-pkg', }, + { + path: 'unpackaged-force-app', + }, + ]); + project.getSfProjectJson().set('packageAliases', { + TEST: packageId, + TEST2: '05i3i000000Gmj6XXX', + DEP: '05i3i000000Gmj6XXX', + 'DEP@0.1.0-1': '04t3i000002eyYXXXX', }); + await project.getSfProjectJson().write(); const loggerSpy = $$.SANDBOX.spy(Logger.prototype, 'debug'); const pvc = new PackageVersionCreate({ connection, project, packageId }); const profileSpyGenerate = $$.SANDBOX.spy(PackageProfileApi.prototype, 'generateProfiles'); @@ -875,10 +880,6 @@ describe('Package Version Create', () => { }); describe('validateAncestorId', () => { - let pvc: PackageVersionCreate; - beforeEach(() => { - pvc = new PackageVersionCreate({ connection, project, packageId }); - }); it('should throw if the explicitUseNoAncestor is true and highestReleasedVersion is not undefined', () => { const ancestorId = 'ancestorId'; const highestReleasedVersion = { @@ -892,7 +893,7 @@ describe('Package Version Create', () => { const skipAncestorCheck = false; const origSpecifiedAncestor = 'orgAncestorId'; expect(() => - pvc['validateAncestorId']( + validateAncestorId( ancestorId, highestReleasedVersion, explicitUseNoAncestor, @@ -915,7 +916,7 @@ describe('Package Version Create', () => { const skipAncestorCheck = false; const origSpecifiedAncestor = 'orgAncestorId'; expect(() => - pvc['validateAncestorId']( + validateAncestorId( ancestorId, highestReleasedVersion, explicitUseNoAncestor, @@ -934,7 +935,7 @@ describe('Package Version Create', () => { const isPatch = false; const skipAncestorCheck = false; const origSpecifiedAncestor = 'orgAncestorId'; - const result = pvc['validateAncestorId']( + const result = validateAncestorId( ancestorId, highestReleasedVersion, explicitUseNoAncestor, @@ -951,7 +952,7 @@ describe('Package Version Create', () => { const isPatch = true; const skipAncestorCheck = true; const origSpecifiedAncestor = 'orgAncestorId'; - const result = pvc['validateAncestorId']( + const result = validateAncestorId( ancestorId, highestReleasedVersion, explicitUseNoAncestor, @@ -963,17 +964,13 @@ describe('Package Version Create', () => { }); }); describe('validateVersionNumber', () => { - let pvc: PackageVersionCreate; - beforeEach(() => { - pvc = new PackageVersionCreate({ connection, project, packageId }); - }); it('should return version number as valid', () => { - const versionNumber = pvc['validateVersionNumber']('1.2.3.NEXT', 'NEXT', 'LATEST'); + const versionNumber = validateVersionNumber('1.2.3.NEXT', 'NEXT', 'LATEST'); expect(versionNumber).to.be.equal('1.2.3.NEXT'); }); it('should throw error if version number is invalid', () => { expect(() => { - pvc['validateVersionNumber']('1.2.3.NEXT', 'foo', 'bar'); + validateVersionNumber('1.2.3.NEXT', 'foo', 'bar'); }).to.throw( Error, /The provided VersionNumber '1.2.3.NEXT' is invalid. Provide an integer value or use the keyword/ @@ -981,7 +978,7 @@ describe('Package Version Create', () => { }); it('should throw error if build2 is undefined', () => { expect(() => { - pvc['validateVersionNumber']('1.2.3.NEXT', 'foo', undefined); + validateVersionNumber('1.2.3.NEXT', 'foo', undefined); }).to.throw( Error, /The provided VersionNumber '1.2.3.NEXT' is invalid. Provide an integer value or use the keyword/ diff --git a/test/package/packageVersionMetadataRetrieve.test.ts b/test/package/packageVersionMetadataRetrieve.test.ts index baa98af96..3b93463df 100644 --- a/test/package/packageVersionMetadataRetrieve.test.ts +++ b/test/package/packageVersionMetadataRetrieve.test.ts @@ -107,14 +107,13 @@ describe('Package Version Retrieve', () => { beforeEach(async () => { $$.inProject(true); project = SfProject.getInstance(); - await project.getSfProjectJson().write({ - packageDirectories: [ - { - path: 'force-app', - default: true, - }, - ], - }); + project.getSfProjectJson().set('packageDirectories', [ + { + path: 'force-app', + default: true, + }, + ]); + await project.getSfProjectJson().write(); stubContext($$); await $$.stubAuths(testOrg); connection = await testOrg.getConnection(); @@ -167,6 +166,7 @@ describe('Package Version Retrieve', () => { afterEach(async () => { restoreContext($$); $$.restore(); + project.getSfProjectJson().unsetAll(['namespace', 'packageAliases']); const pathToClean = path.join(project.getPath(), destinationFolder); if (fs.existsSync(pathToClean)) { await fs.promises.rm(pathToClean, { recursive: true }); @@ -190,15 +190,14 @@ describe('Package Version Retrieve', () => { }); it('should not change the namespace in sfdx-project.json if it is already set', async () => { - await project.getSfProjectJson().write({ - packageDirectories: [ - { - path: 'force-app', - default: true, - }, - ], - namespace: 'existingNS', - }); + project.getSfProjectJson().set('packageDirectories', [ + { + path: 'force-app', + default: true, + }, + ]); + project.getSfProjectJson().set('namespace', 'existingNS'); + await project.getSfProjectJson().write(); const result = await Package.downloadPackageVersionMetadata(project, downloadOptions2GP, connection); expect(result.converted).to.not.be.undefined; diff --git a/yarn.lock b/yarn.lock index b9e463f3e..ddf1285f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -573,7 +573,7 @@ strip-ansi "6.0.1" ts-retry-promise "^0.7.1" -"@salesforce/core@^5.3.10", "@salesforce/core@^5.3.14", "@salesforce/core@^5.3.17": +"@salesforce/core@^5.3.10", "@salesforce/core@^5.3.17": version "5.3.20" resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-5.3.20.tgz#4e934d4551bb70423cb1c4115615bc41cffca41e" integrity sha512-y+O6O2c8OYFDrAy2qsG+pAcNxoyL14nmBXcBRRcYA7Huj8ikK+aLJK84PuVAYdQz+hNwImQF+69IWtDkpK4Irg== @@ -597,6 +597,54 @@ semver "^7.5.4" ts-retry-promise "^0.7.1" +"@salesforce/core@^6.1.0": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-6.1.1.tgz#ef55ca6a1f16304ebe3826c6974a30c489772f79" + integrity sha512-hmvgF6/y04i/lP4Qspg6tmmApdJ6QR2vs9PNsl08rUwwePvHtI0fzjqEFZEMOMYSyKdFrSZYY6U3CAO1CLyTKg== + dependencies: + "@salesforce/kit" "^3.0.15" + "@salesforce/schemas" "^1.6.1" + "@salesforce/ts-types" "^2.0.9" + "@types/semver" "^7.5.4" + ajv "^8.12.0" + change-case "^4.1.2" + faye "^1.4.0" + form-data "^4.0.0" + js2xmlparser "^4.0.1" + jsforce "^2.0.0-beta.28" + jsonwebtoken "9.0.2" + jszip "3.10.1" + pino "^8.16.1" + pino-abstract-transport "^1.1.0" + pino-pretty "^10.2.3" + proper-lockfile "^4.1.2" + semver "^7.5.4" + ts-retry-promise "^0.7.1" + +"@salesforce/core@^6.1.2": + version "6.1.2" + resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-6.1.2.tgz#604c0cd3e3858e2f51c37b1a0904825015a07765" + integrity sha512-h1sGWUfAMVtBvh+wXlSA+e2aJAJ/DnkUD+GLgRje6qUsgxKRNJcoKBCNZgjwAf+xAqJ5IprUZ+arTkU5ME86Mw== + dependencies: + "@salesforce/kit" "^3.0.15" + "@salesforce/schemas" "^1.6.1" + "@salesforce/ts-types" "^2.0.9" + "@types/semver" "^7.5.4" + ajv "^8.12.0" + change-case "^4.1.2" + faye "^1.4.0" + form-data "^4.0.0" + js2xmlparser "^4.0.1" + jsforce "^2.0.0-beta.28" + jsonwebtoken "9.0.2" + jszip "3.10.1" + pino "^8.16.1" + pino-abstract-transport "^1.1.0" + pino-pretty "^10.2.3" + proper-lockfile "^4.1.2" + semver "^7.5.4" + ts-retry-promise "^0.7.1" + "@salesforce/dev-config@^4.0.1": version "4.1.0" resolved "https://registry.yarnpkg.com/@salesforce/dev-config/-/dev-config-4.1.0.tgz#e529576466d074e7a5f1441236510fef123da01e" @@ -651,12 +699,12 @@ resolved "https://registry.yarnpkg.com/@salesforce/schemas/-/schemas-1.6.1.tgz#7d1c071e1e509ca9d2d8a6e48ac7447dd67a534d" integrity sha512-eVy947ZMxCJReKJdgfddUIsBIbPTa/i8RwQGwxq4/ss38H5sLOAeSTaun9V7HpJ1hkpDznWKfgzYvjsst9K6ig== -"@salesforce/source-deploy-retrieve@^9.8.5": - version "9.8.5" - resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-9.8.5.tgz#0cdcdd94894fd30c4923fbdcbd3f35f33bef7ecc" - integrity sha512-6mkyKLz00M0cB/44w93/k9N2EEJeO7oUkCGPzfcxGOABdoqwQUZ15FetIuSKqfAWSbV5wFrw6TxGJ5Du8HrO6A== +"@salesforce/source-deploy-retrieve@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-10.0.0.tgz#572642bb3bfb1d7421afb201d7dc7de0a43271d9" + integrity sha512-6d9F1jTkD4fXYd5i+xowTey//Vns3ZlOhNNNqkQv7UlfZA8ttoxY5aYQAsAv8A/q/IcMx3UoeIKJZxUE2zNgPQ== dependencies: - "@salesforce/core" "^5.3.17" + "@salesforce/core" "^6.1.0" "@salesforce/kit" "^3.0.15" "@salesforce/ts-types" "^2.0.9" fast-levenshtein "^3.0.0" @@ -4491,7 +4539,7 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.1.0: +pino-abstract-transport@^1.0.0, pino-abstract-transport@^1.1.0, pino-abstract-transport@v1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz#083d98f966262164504afb989bccd05f665937a8" integrity sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA== @@ -4524,7 +4572,7 @@ pino-std-serializers@^6.0.0: resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz#d9a9b5f2b9a402486a5fc4db0a737570a860aab3" integrity sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA== -pino@^8.16.0: +pino@^8.16.0, pino@^8.16.1: version "8.16.1" resolved "https://registry.yarnpkg.com/pino/-/pino-8.16.1.tgz#dcaf82764b1a27f24101317cdd6453e96290f1d9" integrity sha512-3bKsVhBmgPjGV9pyn4fO/8RtoVDR8ssW1ev819FsRXlRNgW8gR/9Kx+gCK4UPWd4JjrRDLWpzd/pb1AyWm3MGA==