salesforce-alm
Version:
This package contains tools, and APIs, for an improved salesforce.com developer experience.
169 lines (167 loc) • 7.75 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SourceLocations = void 0;
/*
* 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
*/
const util_1 = require("util");
const core_1 = require("@salesforce/core");
const kit_1 = require("@salesforce/kit");
const metadataTypeFactory_1 = require("./metadataTypeFactory");
const MetadataRegistry = require("./metadataRegistry");
const nonDecomposedElementsIndex_1 = require("./nonDecomposedElementsIndex");
/**
* SourceLocations maintains 2 different indices: `filePathsIndex` and `metadataPathsIndex`.
*
* The `filePathsIndex` is a map of metadata keys to the file locations, e.g.
* ```
* {
* ApexClass__myClass: [~/workspace/my-project/classes/myClass.cls],
* CustomObject__myObject__c.myField: [~/workspace/my-project/objects/myObject/fields/myField__c.field-meta.xml]
* }
* ```
* The `metadataPathsIndex` is a map of metadata keys to the meta file locations, e.g.
* ```
* {
* ApexClass__myClass: [~/workspace/my-project/classes/myClass.cls-meta.xml]
* CustomObject__myObject__c: [~/workspace/my-project/objects/myObject/myObject__c.object-meta.xml]
* }
* ```
* The main difference between these two indices is that `filePathsIndex` contains entries for all workspace elements,
* whereas the `metadataPathsIndex` ONLY contains the entries for the aggregate workspace elements.
*
* We allow multiple file paths per metadata key because the same metadata could live in multiple packages, e.g. CustomLabels.
* When getting a file path based on a given key, we use SfdxProject.getActivePackage() to determine which path to return.
*
*/
class SourceLocations extends kit_1.AsyncCreatable {
constructor(options) {
super(options);
this.metadataRegistry = options.metadataRegistry;
this.sourcePathInfos = options.sourcePathInfos;
this.shouldBuildIndices = options.shouldBuildIndices;
this.username = options.username;
}
async init() {
this.logger = await core_1.Logger.child(this.constructor.name);
// No need to build indices in some cases, e.g., mdapi:convert and source:convert
if (this.shouldBuildIndices) {
await this.buildIndices();
}
}
getMetadataPath(metadataType, fullName) {
const key = MetadataRegistry.getMetadataKey(metadataType, fullName);
const paths = SourceLocations.metadataPathsIndex.get(key);
if (paths) {
return this.getPathByActivePackage(paths);
}
else {
this.logger.debug(`No metadata path found for ${key}`);
}
}
addMetadataPath(metadataType, fullName, metadataPath) {
const key = MetadataRegistry.getMetadataKey(metadataType, fullName);
if (SourceLocations.metadataPathsIndex.has(key)) {
const existing = SourceLocations.metadataPathsIndex.get(key);
SourceLocations.metadataPathsIndex.set(key, existing.concat(metadataPath));
}
else {
SourceLocations.metadataPathsIndex.set(key, [metadataPath]);
}
}
getFilePath(metadataType, fullName) {
const key = MetadataRegistry.getMetadataKey(metadataType, fullName);
// We search both indices since nondecomposed elements (e.g. CustomLabel) are not
// included in the filePathsIndex
let paths = SourceLocations.filePathsIndex.get(key);
if (!paths && SourceLocations.nonDecomposedElementsIndex) {
paths = [SourceLocations.nonDecomposedElementsIndex.getMetadataFilePath(key)];
}
if (paths) {
return this.getPathByActivePackage(paths);
}
else {
this.logger.debug(`No file path found for ${key}`);
}
}
addFilePath(pathMetadataType, sourcePath) {
const aggregateMetadataType = pathMetadataType.getAggregateMetadataName();
const fullName = decodeURIComponent(pathMetadataType.getFullNameFromFilePath(sourcePath));
const key = MetadataRegistry.getMetadataKey(aggregateMetadataType, fullName);
if (SourceLocations.filePathsIndex.has(key)) {
const existing = SourceLocations.filePathsIndex.get(key);
SourceLocations.filePathsIndex.set(key, existing.concat(sourcePath));
}
else {
SourceLocations.filePathsIndex.set(key, [sourcePath]);
}
}
getPathByActivePackage(paths) {
if (paths.length === 1) {
return paths[0];
}
const activePackage = core_1.SfdxProject.getInstance().getActivePackage();
const match = paths.find((p) => {
const pkgName = core_1.SfdxProject.getInstance().getPackageNameFromPath(p);
return pkgName === (activePackage && activePackage.name);
});
return match || paths[0];
}
async buildIndices() {
SourceLocations._nonDecomposedElementsIndex = await nonDecomposedElementsIndex_1.NonDecomposedElementsIndex.getInstance({
username: this.username,
metadataRegistry: this.metadataRegistry,
});
for (const sourcePathInfo of this.sourcePathInfos) {
const pathMetadataType = sourcePathInfo.metadataType
? metadataTypeFactory_1.MetadataTypeFactory.getMetadataTypeFromMetadataName(sourcePathInfo.metadataType, this.metadataRegistry)
: null;
if (pathMetadataType) {
metadataTypeFactory_1.MetadataTypeCache.sourcePaths.set(sourcePathInfo.sourcePath, pathMetadataType);
if (sourcePathInfo.isMetadataFile) {
const aggregateFullName = pathMetadataType.getAggregateFullNameFromFilePath(sourcePathInfo.sourcePath);
if (this.isInvalidPath(sourcePathInfo.sourcePath)) {
throw new Error(`Invalid source path for metadataType: ${pathMetadataType}`);
}
if (SourceLocations.nonDecomposedElementsIndex.isNonDecomposedElement(sourcePathInfo.metadataType)) {
await SourceLocations.nonDecomposedElementsIndex.handleDecomposedElements(sourcePathInfo);
}
const aggregateMetadataPath = pathMetadataType.getAggregateMetadataFilePathFromWorkspacePath(sourcePathInfo.sourcePath);
this.addMetadataPath(pathMetadataType.getMetadataName(), aggregateFullName, aggregateMetadataPath);
this.addFilePath(pathMetadataType, sourcePathInfo.sourcePath);
}
else if (!sourcePathInfo.isDirectory) {
this.addFilePath(pathMetadataType, sourcePathInfo.sourcePath);
}
}
}
}
isInvalidPath(sourcePath) {
return kit_1.isEmpty(sourcePath) || !util_1.isString(sourcePath);
}
static get filePathsIndex() {
return this._filePathsIndex;
}
static set filePathsIndex(newIndex) {
this._filePathsIndex = newIndex;
}
static get metadataPathsIndex() {
return this._metadataPathsIndex;
}
static set metadataPathsIndex(newIndex) {
this._metadataPathsIndex = newIndex;
}
static get nonDecomposedElementsIndex() {
return this._nonDecomposedElementsIndex;
}
static set nonDecomposedElementsIndex(newIndex) {
this._nonDecomposedElementsIndex = newIndex;
}
}
exports.SourceLocations = SourceLocations;
SourceLocations._metadataPathsIndex = new Map();
SourceLocations._filePathsIndex = new Map();
//# sourceMappingURL=sourceLocations.js.map