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

refactor: type consolidation #590

Merged
merged 22 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7253116
chore: lockfile and linter styling
mshanemc Jun 10, 2024
14c0187
refactor: types from other libraries
mshanemc Jun 10, 2024
a79d2cd
refactor: reorganize types and const
mshanemc Jun 10, 2024
3ac5631
test: assertion and expect refactoring
mshanemc Jun 10, 2024
db684c6
refactor: logger and type fixes
mshanemc Jun 10, 2024
c832da0
refactor: throw if no sourceApiVersion
mshanemc Jun 10, 2024
0d3e37f
refactor: type assertion cleanup
mshanemc Jun 10, 2024
1b4cf1c
chore: dep bumps, remove unused ts-sinon
mshanemc Jun 11, 2024
4116e32
refactor: type cleanup
mshanemc Jun 11, 2024
6cb366c
test: use qa-tag for xnuts
mshanemc Jun 11, 2024
add5bcd
refactor: mutation avoidance
mshanemc Jun 11, 2024
dc81194
chore: second round of sfdx-core changes
mshanemc Jun 11, 2024
2879d43
test: split 2 unrelated nuts
mshanemc Jun 11, 2024
9b13c0f
Merge remote-tracking branch 'origin/main' into sm/type-consolidation
mshanemc Jun 11, 2024
f070a34
fix(types): convertPackageOptions type matches the library's prop req…
mshanemc Jun 18, 2024
12b00ab
style: typos
mshanemc Jun 18, 2024
10bdca0
refactor: types from schemas, not sfdx-core
mshanemc Jun 18, 2024
8b32922
refactor: pr feedback on conditional
mshanemc Jun 19, 2024
38c7dc5
chore: merge main, resolve conflicts, bump core
WillieRuemmele Jun 19, 2024
ac927e8
chore: more library bumps
mshanemc Jun 19, 2024
078817b
feat!: bump major core/sdr versions
mshanemc Jun 20, 2024
51732c5
Merge remote-tracking branch 'origin/main' into sm/type-consolidation
mshanemc Jun 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,921 changes: 525 additions & 1,396 deletions CHANGELOG.md

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@
],
"dependencies": {
"@jsforce/jsforce-node": "^3.2.0",
"@salesforce/core": "^7.3.12",
"@salesforce/kit": "^3.1.2",
"@salesforce/core": "7.3.12-qa.1",
"@salesforce/kit": "^3.1.6",
"@salesforce/schemas": "^1.9.0",
"@salesforce/source-deploy-retrieve": "^11.6.5",
"@salesforce/source-deploy-retrieve": "^11.6.6",
"@salesforce/ts-types": "^2.0.9",
"@salesforce/types": "^1.1.0",
"fast-xml-parser": "^4.4.0",
Expand All @@ -59,7 +59,6 @@
"devDependencies": {
"@salesforce/cli-plugins-testkit": "^5.3.8",
"@salesforce/dev-scripts": "^9.1.2",
"@salesforce/ts-sinon": "^1.4.19",
"@types/globby": "^9.1.0",
"@types/jszip": "^3.4.1",
"eslint-plugin-sf-plugin": "^1.18.5",
Expand Down
12 changes: 7 additions & 5 deletions src/interfaces/packagingInterfacesAndType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import { Duration } from '@salesforce/kit';
import { Connection, NamedPackageDir, SfProject } from '@salesforce/core';
import { Connection } from '@salesforce/core';
import { NamedPackagingDir, SfProject } from '@salesforce/core/project';
import type { SaveResult } from '@jsforce/jsforce-node';
import { Attributes } from 'graphology-types';
import { Optional } from '@salesforce/ts-types';
Expand Down Expand Up @@ -170,7 +171,7 @@ export type PackageCreateOptions = {
path: string;
};

export type PackageDescriptorJson = Partial<NamedPackageDir> &
export type PackageDescriptorJson = Partial<NamedPackagingDir> &
Partial<{
id: string;
features: string[];
Expand Down Expand Up @@ -294,11 +295,12 @@ export type SubscriberPackageVersionOptions = {
};

export type ConvertPackageOptions = {
installationKey: string;
definitionfile: string;
installationKey?: string;
definitionfile?: string;
/** @deprecated stop using it*/
installationKeyBypass: boolean;
wait: Duration;
buildInstance: string;
buildInstance?: string;
frequency?: Duration;
seedMetadata?: string;
};
Expand Down
34 changes: 14 additions & 20 deletions src/package/packageConvert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,7 @@ import Package2VersionStatus = PackagingSObjects.Package2VersionStatus;
Messages.importMessagesDirectory(__dirname);
const messages = Messages.loadMessages('@salesforce/packaging', 'package_version_create');

let logger: Logger;
const getLogger = (): Logger => {
if (!logger) {
logger = Logger.childFromRoot('packageConvert');
}
return logger;
};
const POLL_INTERVAL_SECONDS = 30;

export async function findOrCreatePackage2(
seedPackage: string,
Expand Down Expand Up @@ -104,15 +98,12 @@ export async function convertPackage(
options: ConvertPackageOptions,
project?: SfProject
): Promise<PackageVersionCreateRequestResult> {
let maxRetries = 0;
const maxRetries = options.wait ? (60 / POLL_INTERVAL_SECONDS) * options.wait.minutes : 0;
const branch = 'main';
if (options.wait) {
maxRetries = (60 / pkgUtils.POLL_INTERVAL_SECONDS) * options.wait.minutes;
}

const packageId = await findOrCreatePackage2(pkg, connection, project);

const apiVersion = project?.getSfProjectJson()?.get('sourceApiVersion') as string;
const apiVersion = project?.getSfProjectJson()?.get('sourceApiVersion');

const request = await createPackageVersionCreateRequest(
{
Expand All @@ -122,7 +113,9 @@ export async function convertPackage(
seedmetadata: options.seedMetadata,
},
packageId,
apiVersion
// TODO: createPackageVersionCreateRequest requires apiVersion exist.
// UT fail if we validate that it exists (there might not even be a project)
apiVersion as string
);

// TODO: a lot of this is duplicated from PC, PVC, and PVCR.
Expand All @@ -142,7 +135,7 @@ export async function convertPackage(
branch,
project,
connection,
options.frequency ?? Duration.seconds(pkgUtils.POLL_INTERVAL_SECONDS)
options.frequency ?? Duration.seconds(POLL_INTERVAL_SECONDS)
);
} else {
results = await byId(packageId, connection);
Expand Down Expand Up @@ -211,7 +204,9 @@ export async function createPackageVersionCreateRequest(

if (hasSeedMetadata) {
// Zip the seedMetadataFolder folder and put the zip in {packageVersBlobDirectory}/{seedMetadataZipFile}
getLogger().debug(`Including metadata found in '${context.seedmetadata}'.`);
Logger.childFromRoot('packageConvert:pollForStatusWithInterval').debug(
`Including metadata found in '${context.seedmetadata}'.`
);
await pkgUtils.zipDir(seedMetadataFolder, seedMetadataZipFile);
}

Expand Down Expand Up @@ -263,6 +258,7 @@ async function pollForStatusWithInterval(
connection: Connection,
interval: Duration
): Promise<PackageVersionCreateRequestResult> {
const logger = Logger.childFromRoot('packageConvert:pollForStatusWithInterval');
let remainingRetries = retries;
const pollingClient = await PollingClient.create({
poll: async (): Promise<StatusResult> => {
Expand Down Expand Up @@ -328,7 +324,7 @@ async function pollForStatusWithInterval(
timeRemaining: remainingTime,
});

getLogger().info(
logger.info(
`Request in progress. Sleeping ${interval.seconds} seconds. Will wait a total of ${
remainingTime.seconds
} more seconds before timing out. Current Status='${camelCaseToTitleCase(results[0]?.Status)}'`
Expand Down Expand Up @@ -358,9 +354,7 @@ async function addPackageAlias(project: SfProject, packageName: string, packageI
* @param statuses array of statuses to look for
* @returns {boolean} if one of the values in status is found.
*/
function isStatusEqualTo(
const isStatusEqualTo = (
results: PackageVersionCreateRequestResult[],
statuses: Package2VersionStatus[] = []
): boolean {
return !results?.length ? false : statuses.some((status) => results[0].Status === status);
}
): boolean => (!results?.length ? false : statuses.some((status) => results[0].Status === status));
63 changes: 26 additions & 37 deletions src/package/packageCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import { Connection, NamedPackageDir, PackageDir, SfError, SfProject } from '@salesforce/core';
import { Connection, SfError, SfProject } from '@salesforce/core';
import { env } from '@salesforce/kit';
import { PackagePackageDir, PackageDir } from '@salesforce/schemas';
import * as pkgUtils from '../utils/packageUtils';
import { applyErrorAction, massageErrorMessage, replaceIfEmpty } from '../utils/packageUtils';
import { applyErrorAction, massageErrorMessage } from '../utils/packageUtils';
import { PackageCreateOptions, PackagingSObjects } from '../interfaces';

type Package2Request = Pick<
Expand Down Expand Up @@ -36,46 +37,28 @@ export function createPackageRequestFromContext(project: SfProject, options: Pac
* @private
*/

export function createPackageDirEntry(project: SfProject, options: PackageCreateOptions): PackageDir | NamedPackageDir {
export function createPackageDirEntry(project: SfProject, options: PackageCreateOptions): PackagePackageDir {
const packageDirs: PackageDir[] = project.getSfProjectJson().getContents().packageDirectories ?? [];
let isNew = false;

// see if package exists (exists means it has an id or package)
let packageDir: PackageDir | undefined = packageDirs
.map((pd: PackageDir) => pd as NamedPackageDir & { id: string })
.find((pd: NamedPackageDir & { id: string }) => pd.path === options.path && !pd.id && !pd.package);

if (!packageDir) {
// no match - create a new one
isNew = true;
packageDir = { ...pkgUtils.DEFAULT_PACKAGE_DIR } as NamedPackageDir;
packageDir.path = replaceIfEmpty(packageDir.path, options.path);
}

if (packageDirs.length === 0) {
packageDir.default = true;
} else if (isNew) {
packageDir.default = !packageDirs.find((pd: PackageDir) => pd.default);
}

packageDir.package = replaceIfEmpty(packageDir.package, options.name);
packageDir.versionName = replaceIfEmpty(packageDir.versionName, pkgUtils.DEFAULT_PACKAGE_DIR.versionName);
packageDir.versionNumber = replaceIfEmpty(packageDir.versionNumber, pkgUtils.DEFAULT_PACKAGE_DIR.versionNumber);
packageDir.versionDescription = replaceIfEmpty(packageDir.versionDescription, options.description);

return packageDir;
return {
package: options.name,
versionName: 'ver 0.1',
versionNumber: '0.1.0.NEXT',
...(packageDirs.filter((pd: PackageDir) => pd.path === options.path).find((pd) => !('id' in pd)) ?? {
// no match - create a new one
path: options.path,
default: packageDirs.length === 0 ? true : !packageDirs.some((pd) => pd.default === true),
}),
versionDescription: options.description,
};
}

export async function createPackage(
connection: Connection,
project: SfProject,
options: PackageCreateOptions
): Promise<{ Id: string }> {
// strip trailing slash from path param
options.path = options.path.replace(/\/$/, '');

const request = createPackageRequestFromContext(project, options);

const cleanOptions = sanitizePackageCreateOptions(options);
const request = createPackageRequestFromContext(project, cleanOptions);
const createResult = await connection.tooling
.sobject('Package2')
.create(request)
Expand All @@ -89,11 +72,17 @@ export async function createPackage(
}

if (!env.getBoolean('SF_PROJECT_AUTOUPDATE_DISABLE_FOR_PACKAGE_CREATE')) {
const packageDirectory = createPackageDirEntry(project, options);
project.getSfProjectJson().addPackageDirectory(packageDirectory as NamedPackageDir);
project.getSfProjectJson().addPackageAlias(options.name, createResult.id);
const packageDirectory = createPackageDirEntry(project, cleanOptions);
project.getSfProjectJson().addPackageDirectory(packageDirectory);
project.getSfProjectJson().addPackageAlias(cleanOptions.name, createResult.id);
await project.getSfProjectJson().write();
}

return { Id: createResult.id };
}

/** strip trailing slash from path param */
const sanitizePackageCreateOptions = (options: PackageCreateOptions): PackageCreateOptions => ({
...options,
path: options.path.replace(/\/$/, ''),
});
5 changes: 1 addition & 4 deletions src/package/packageDelete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ export async function deletePackage(
const packageId = project.getPackageIdFromAlias(idOrAlias) ?? idOrAlias;
validateId(BY_LABEL.PACKAGE_ID, packageId);

const request = {} as { Id: string; IsDeprecated: boolean };
request.Id = packageId;
const isUndelete = undelete;
request.IsDeprecated = !isUndelete;
const request = { Id: packageId, IsDeprecated: !undelete };

const updateResult = await connection.tooling.update('Package2', request).catch((err) => {
if (err instanceof Error) {
Expand Down
3 changes: 1 addition & 2 deletions src/package/packageVersion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import { Connection, Lifecycle, Messages, PollingClient, SfError, SfProject, StatusResult } from '@salesforce/core';
import { Duration, env } from '@salesforce/kit';
import { Optional } from '@salesforce/ts-types';
import {
PackageSaveResult,
PackageType,
Expand Down Expand Up @@ -120,7 +119,7 @@ export class PackageVersion {
private readonly connection: Connection;

private data?: Package2Version;
private packageType: Optional<PackageType>;
private packageType?: PackageType;
private id: string;

public constructor(private options: PackageVersionOptions) {
Expand Down
20 changes: 13 additions & 7 deletions src/package/packageVersionCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
Logger,
Messages,
NamedPackageDir,
PackageDir,
ScratchOrgInfo,
SfdcUrl,
SfProject,
Expand All @@ -27,10 +26,11 @@ import {
ConvertResult,
MetadataConverter,
} from '@salesforce/source-deploy-retrieve';
import { PackageDirDependency } from '@salesforce/core/project';
import { isNamedPackagingDirectory, isPackagingDirectory } from '@salesforce/core/project';
import { ensureArray, env } from '@salesforce/kit';
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
import { isString } from '@salesforce/ts-types';
import { PackagePackageDir, PackageDirDependency } from '@salesforce/schemas';
import * as pkgUtils from '../utils/packageUtils';
import {
BY_LABEL,
Expand Down Expand Up @@ -330,7 +330,7 @@ export class PackageVersionCreate {
const mdOptions: MDFolderForArtifactOptions = {
deploydir: packageVersMetadataFolder,
sourceDir: sourceBaseDir,
sourceApiVersion: (this.project?.getSfProjectJson()?.get('sourceApiVersion') as string) ?? undefined,
sourceApiVersion: this.project?.getSfProjectJson()?.get('sourceApiVersion'),
};

await fs.promises.mkdir(packageVersBlobDirectory, { recursive: true });
Expand Down Expand Up @@ -525,6 +525,7 @@ export class PackageVersionCreate {
// don't package the profiles from any un-packagedMetadata dir in the project
profileExcludeDirs = this.project
.getPackageDirectories()
.filter(isNamedPackagingDirectory)
.map((packageDir) => packageDir.unpackagedMetadata?.path)
.filter(isString);

Expand Down Expand Up @@ -649,16 +650,19 @@ export class PackageVersionCreate {
if (!packageName) throw messages.createError('errorMissingPackage', [this.options.packageId]);
}
packageObject = this.project.findPackage(
(namedPackageDir) => namedPackageDir.package === packageName || namedPackageDir.name === packageName
(namedPackageDir) =>
(isPackagingDirectory(namedPackageDir) && namedPackageDir.package === packageName) ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this logic matches, should it be
isPackagingDirectory(namedPackageDir) &&(namedPackageDir.package === packageName || namedPackageDir.name === packageName)?

namedPackageDir.name === packageName
);
} else {
// We'll either have a package ID or alias, or a directory path
if (!this.options.path) {
throw messages.createError('errorMissingPackagePath', [JSON.stringify(this.options)]);
}
packageObject = this.project.getPackageFromPath(this.options.path);
if (!packageObject || !isPackagingDirectory(packageObject))
throw messages.createError('errorCouldNotFindPackageUsingPath', [this.options.path]);
packageName = packageObject?.package;
if (!packageName) throw messages.createError('errorCouldNotFindPackageUsingPath', [this.options.path]);
}

if (!packageObject) {
Expand Down Expand Up @@ -711,9 +715,11 @@ export class PackageVersionCreate {
return (await byId(createResult.id, this.connection))[0];
}

private async getPackageDirFromId(pkg: string): Promise<PackageDir | undefined> {
private async getPackageDirFromId(pkg: string): Promise<PackagePackageDir | undefined> {
if (pkg.startsWith('0Ho')) {
const dir = (await this.project.getSfProjectJson().getPackageDirectories()).filter((p) => p.package === pkg);
const dir = (await this.project.getSfProjectJson().getPackageDirectories())
.filter(isPackagingDirectory)
.filter((p) => p.package === pkg);
if (dir.length === 1) {
return dir[0];
}
Expand Down
Loading
Loading