Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sm/core6 #446

Merged
merged 11 commits into from
Nov 15, 2023
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"packaging"
],
"engines": {
"node": ">=16.0.0"
"node": ">=18.0.0"
},
"files": [
"docs",
Expand All @@ -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",
Expand Down
2 changes: 0 additions & 2 deletions src/interfaces/packagingInterfacesAndType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,6 @@ export type PackageDescriptorJson = Partial<NamedPackageDir> &
features: string[];
orgPreferences: string[];
snapshot: string;
unpackagedMetadata: NamedPackageDir;
seedMetadata: NamedPackageDir;
apexTestAccess: { permissionSets: string[] | string; permissionSetLicenses: string[] | string };
permissionSetNames: string[];
permissionSetLicenseDeveloperNames: string[];
Expand Down
16 changes: 10 additions & 6 deletions src/package/packageVersion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -634,12 +634,16 @@ export class PackageVersion {
}`;
const build = versionResult.BuildNumber ? `-${versionResult.BuildNumber}` : '';
const branch = versionResult.Branch ? `-${versionResult.Branch}` : '';
// set packageAliases entry '<package>@<major>.<minor>.<patch>-<build>-<branch>: <result.subscriberPackageVersionId>'
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 '<package>@<major>.<minor>.<patch>-<build>-<branch>: <result.subscriberPackageVersionId>'
{ [`${version}${build}${branch}`]: results.SubscriberPackageVersionId }
: {}),
};

this.project.getSfProjectJson().set('packageAliases', updatedPackageAliases);
await this.project.getSfProjectJson().write();
}
}
Expand Down
263 changes: 125 additions & 138 deletions src/package/packageVersionCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 });
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -691,9 +691,8 @@ export class PackageVersionCreate {
}

private async getPackageDirFromId(pkg: string): Promise<PackageDir | undefined> {
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];
}
Expand Down Expand Up @@ -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<void> {
const query = `SELECT ContainerOptions FROM Package2 WHERE id ='${packageId}'`;
const queryResult = await this.connection.tooling.query(query);
Expand Down Expand Up @@ -950,7 +855,7 @@ export class PackageVersionCreate {
origSpecifiedAncestor = packageDescriptorJson.ancestorVersion;
}

return this.validateAncestorId(
return validateAncestorId(
ancestorId,
highestReleasedVersion,
explicitUseNoAncestor,
Expand All @@ -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,
Expand Down Expand Up @@ -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)));
};
Loading
Loading