salesforce-alm
Version:
This package contains tools, and APIs, for an improved salesforce.com developer experience.
244 lines (242 loc) • 13.3 kB
JavaScript
"use strict";
/*
* Copyright (c) 2020, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SrcStatusApi = void 0;
// Local
const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
const kit_1 = require("@salesforce/kit");
const core_1 = require("@salesforce/core");
const MetadataRegistry = require("./metadataRegistry");
const workspaceFileState_1 = require("./workspaceFileState");
const aggregateSourceElement_1 = require("./aggregateSourceElement");
const metadataTypeFactory_1 = require("./metadataTypeFactory");
const sourceWorkspaceAdapter_1 = require("./sourceWorkspaceAdapter");
const remoteSourceTrackingService_1 = require("./remoteSourceTrackingService");
class SrcStatusApi extends kit_1.AsyncCreatable {
constructor(options) {
super(options);
this.scratchOrg = options.org;
this.force = this.scratchOrg.force;
this.swa = options.adapter;
this.locallyChangedWorkspaceElements = [];
this.localChanges = [];
this.remoteChanges = [];
this.forceIgnore = source_deploy_retrieve_1.ForceIgnore.findAndCreate(core_1.SfdxProject.resolveProjectPathSync());
}
async init() {
this.logger = await core_1.Logger.child(this.constructor.name);
this.remoteSourceTrackingService = await remoteSourceTrackingService_1.RemoteSourceTrackingService.getInstance({
username: this.scratchOrg.name,
});
if (!this.swa) {
const options = {
org: this.scratchOrg,
metadataRegistryImpl: MetadataRegistry,
defaultPackagePath: this.force.getConfig().getAppConfig().defaultPackagePath,
};
this.swa = await sourceWorkspaceAdapter_1.SourceWorkspaceAdapter.create(options);
}
}
async doStatus(options) {
this.populateLocalChanges(options);
await this.populateServerChanges(options);
return this.markConflicts(options);
}
populateLocalChanges(options) {
if (!options.local) {
return [];
}
const localSourceElementsMapByPkg = this.swa.changedSourceElementsCache;
return localSourceElementsMapByPkg.forEach((localSourceElementsMap) => localSourceElementsMap.forEach((value) => {
value.getWorkspaceElements().forEach((workspaceElement) => {
value.validateIfDeletedWorkspaceElement(workspaceElement);
if (options.local && !options.remote) {
this.localChanges.push(workspaceElement.toObject());
}
else {
// if we want to find source conflicts between the workspace and the server,
// then pass along the locally changed workspace elements and
// populate this.localChanges during the _markConflicts() step
this.locallyChangedWorkspaceElements.push(workspaceElement);
}
});
}));
}
// Retrieve metadata CRUD changes from the org, filtering any forceignored metadata,
// then assign remote changes for conflict detection and status reporting.
async populateServerChanges(options) {
if (!options.remote) {
return [];
}
// Returns false when a changeElement matches a forceignore rule
const forceIgnoreAllows = (changeElement) => {
const sourceMemberMetadataType = metadataTypeFactory_1.MetadataTypeFactory.getMetadataTypeFromMetadataName(changeElement.type, this.swa.metadataRegistry);
// if user wants to ignore a permissionset with fullname abc then we check if forceignore denies abc.permissionset
if (sourceMemberMetadataType) {
const fullName = sourceMemberMetadataType.getAggregateFullNameFromSourceMemberName(changeElement.name);
const filename = `${fullName}.${sourceMemberMetadataType.getExt()}`;
return this.forceIgnore.accepts(filename);
}
return true;
};
const changeElements = await this.remoteSourceTrackingService.retrieveUpdates();
// Create an array of remote changes from the retrieved updates
for (const changeElement of changeElements) {
if (forceIgnoreAllows(changeElement)) {
const remoteChange = await this.createRemoteChangeElements(changeElement);
this.remoteChanges = [...this.remoteChanges, ...remoteChange];
}
}
}
async createRemoteChangeElements(changeElement) {
const remoteChangeElements = [];
const sourceMemberMetadataType = metadataTypeFactory_1.MetadataTypeFactory.getMetadataTypeFromMetadataName(changeElement.type, this.swa.metadataRegistry);
if (sourceMemberMetadataType) {
if (sourceMemberMetadataType.trackRemoteChangeForSourceMemberName(changeElement.name)) {
const correspondingWorkspaceElements = await this.getCorrespondingWorkspaceElements(changeElement, sourceMemberMetadataType);
const state = this.getRemoteChangeState(changeElement, correspondingWorkspaceElements);
const metadataType = sourceMemberMetadataType.getMetadataName();
if (this.swa.metadataRegistry.isSupported(metadataType)) {
if (correspondingWorkspaceElements &&
correspondingWorkspaceElements.length > 0 &&
!sourceMemberMetadataType.displayAggregateRemoteChangesOnly()) {
correspondingWorkspaceElements.forEach((workspaceElement) => {
const remoteChangeElement = {
state,
fullName: workspaceElement.getFullName(),
type: sourceMemberMetadataType.getDisplayNameForRemoteChange(changeElement.type),
filePath: workspaceElement.getSourcePath(),
};
remoteChangeElements.push(remoteChangeElement);
});
}
else {
if (state !== workspaceFileState_1.WorkspaceFileState.DELETED) {
const remoteChangeElement = {
state,
fullName: changeElement.name,
type: sourceMemberMetadataType.getDisplayNameForRemoteChange(changeElement.type),
};
remoteChangeElements.push(remoteChangeElement);
}
else {
this.logger.debug(`${changeElement.type}.${changeElement.name} was not locally tracked but deleted in the org.`);
}
}
}
}
}
return remoteChangeElements;
}
getRemoteChangeState(changeElement, correspondingLocalWorkspaceElements) {
if (changeElement.deleted) {
return workspaceFileState_1.WorkspaceFileState.DELETED;
}
else if (correspondingLocalWorkspaceElements && correspondingLocalWorkspaceElements.length > 0) {
return workspaceFileState_1.WorkspaceFileState.CHANGED;
}
else {
return workspaceFileState_1.WorkspaceFileState.NEW;
}
}
async getCorrespondingWorkspaceElements(changeElement, sourceMemberMetadataType) {
const allLocalAggregateElements = await this.swa.getAggregateSourceElements(false);
if (!allLocalAggregateElements.isEmpty()) {
if (sourceMemberMetadataType) {
const aggregateFullName = sourceMemberMetadataType.getAggregateFullNameFromSourceMemberName(changeElement.name);
const aggregateMetadataName = sourceMemberMetadataType.getAggregateMetadataName();
const key = aggregateSourceElement_1.AggregateSourceElement.getKeyFromMetadataNameAndFullName(aggregateMetadataName, aggregateFullName);
const fileLocation = this.swa.sourceLocations.getFilePath(aggregateMetadataName, changeElement.name);
// if we cannot find an existing fileLocation, it means that the SourceMember has been deleted or the metadata
// hasn't been retrieved from the org yet.
if (!fileLocation) {
this.logger.debug(`getCorrespondingWorkspaceElements: Did not find any existing source files for member ${changeElement.name}. Returning empty array...`);
return [];
}
const pkgName = core_1.SfdxProject.getInstance().getPackageNameFromPath(fileLocation);
const localAggregateSourceElement = allLocalAggregateElements.getSourceElement(pkgName, key);
if (localAggregateSourceElement) {
const workspaceElements = localAggregateSourceElement.getWorkspaceElements();
if (workspaceElements.length > 0) {
return workspaceElements.filter((workspaceElement) => {
const workspaceElementMetadataType = metadataTypeFactory_1.MetadataTypeFactory.getMetadataTypeFromMetadataName(workspaceElement.getMetadataName(), this.swa.metadataRegistry);
return (workspaceElementMetadataType.sourceMemberFullNameCorrespondsWithWorkspaceFullName(changeElement.name, workspaceElement.getFullName()) ||
workspaceElementMetadataType.sourceMemberFullNameCorrespondsWithWorkspaceFullName(`${changeElement.type}s`, // for nonDecomposedTypesWithChildrenMetadataTypes we need to check their type
workspaceElement.getFullName()));
});
}
}
}
}
return [];
}
markConflicts(options) {
if (options.local && options.remote) {
return this.locallyChangedWorkspaceElements.forEach((workspaceElement) => {
// a metadata element with same name and type modified both locally and in the server is considered a conflict
const localChange = {
state: workspaceElement.getState(),
fullName: workspaceElement.getFullName(),
type: workspaceElement.getMetadataName(),
filePath: workspaceElement.getSourcePath(),
deleteSupported: workspaceElement.getDeleteSupported(),
};
const workspaceElementMetadataType = metadataTypeFactory_1.MetadataTypeFactory.getMetadataTypeFromMetadataName(workspaceElement.getMetadataName(), this.swa.metadataRegistry);
const remoteChanges = this.remoteChanges.filter((remoteChange) => workspaceElementMetadataType.conflictDetected(remoteChange.type, remoteChange.fullName, workspaceElement.getFullName()));
if (remoteChanges && remoteChanges.length > 0) {
localChange.isConflict = true;
remoteChanges.forEach((remoteChange) => {
remoteChange.isConflict = true;
});
}
this.localChanges.push(localChange);
});
}
else {
return [];
}
}
getLocalChanges() {
return this.localChanges;
}
getRemoteChanges() {
return this.remoteChanges;
}
getLocalConflicts() {
const aggregateKeys = new Set();
return this.localChanges
.filter((item) => {
const metadataType = metadataTypeFactory_1.MetadataTypeFactory.getMetadataTypeFromMetadataName(item.type, this.swa.metadataRegistry);
if (item.isConflict && metadataType.onlyDisplayOneConflictPerAggregate()) {
const aggregateFullName = metadataType.getAggregateFullNameFromWorkspaceFullName(item.fullName);
const key = `${metadataType.getMetadataName()}#${aggregateFullName}`;
if (!aggregateKeys.has(key)) {
aggregateKeys.add(key);
return true;
}
return false;
}
return item.isConflict;
})
.map((item) => {
const metadataType = metadataTypeFactory_1.MetadataTypeFactory.getMetadataTypeFromMetadataName(item.type, this.swa.metadataRegistry);
if (metadataType.onlyDisplayOneConflictPerAggregate()) {
return {
state: item.state,
fullName: metadataType.getAggregateFullNameFromWorkspaceFullName(item.fullName),
type: item.type,
filePath: metadataType.getDisplayPathForLocalConflict(item.filePath),
deleteSupported: item.deleteSupported,
};
}
return item;
});
}
}
exports.SrcStatusApi = SrcStatusApi;
//# sourceMappingURL=srcStatusApi.js.map