@salesforce/source-tracking
Version:
API for tracking local and remote Salesforce metadata changes
122 lines • 5.9 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getComponentSets = exports.getGroupedFiles = void 0;
/*
* Copyright 2025, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = require("node:path");
const core_1 = require("@salesforce/core");
const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
const guards_1 = require("./guards");
const functions_1 = require("./functions");
const getGroupedFiles = (input, byPackageDir = false) => (byPackageDir ? getSequential(input) : getNonSequential(input)).filter((group) => group.deletes.length || group.nonDeletes.length);
exports.getGroupedFiles = getGroupedFiles;
const getSequential = ({ packageDirs, nonDeletes, deletes }) => {
const nonDeletesByPkgDir = groupByPkgDir(nonDeletes, packageDirs);
const deletesByPkgDir = groupByPkgDir(deletes, packageDirs);
return packageDirs.map((pkgDir) => {
const { name } = pkgDir;
return {
path: name,
nonDeletes: nonDeletesByPkgDir.get(name) ?? [],
deletes: deletesByPkgDir.get(name) ?? [],
};
});
};
const groupByPkgDir = (filePaths, pkgDirs) => {
const groups = new Map();
pkgDirs.forEach((pkgDir) => {
groups.set(pkgDir.name, []);
});
filePaths.forEach((filePath) => {
pkgDirs.forEach((pkgDir) => {
const { name } = pkgDir;
if ((0, functions_1.pathIsInFolder)(name)(filePath)) {
groups.get(name)?.push(filePath);
return;
}
});
});
return groups;
};
const getNonSequential = ({ packageDirs, nonDeletes: nonDeletes, deletes: deletes, }) => [
{
nonDeletes,
deletes,
path: packageDirs.map((dir) => dir.name).join(';'),
},
];
const getComponentSets = ({ groupings, sourceApiVersion, registry, projectPath, }) => {
const logger = core_1.Logger.childFromRoot('localComponentSetArray');
// optimistic resolution...some files may not be possible to resolve
const resolverForNonDeletes = new source_deploy_retrieve_1.MetadataResolver(registry, (0, functions_1.maybeGetTreeContainer)(projectPath));
return groupings
.map((grouping) => {
logger.debug(`building componentSet for ${grouping.path} (deletes: ${grouping.deletes.length} nonDeletes: ${grouping.nonDeletes.length})`);
const componentSet = new source_deploy_retrieve_1.ComponentSet(undefined, registry);
if (sourceApiVersion) {
componentSet.sourceApiVersion = sourceApiVersion;
}
// we need virtual components for the deletes.
// TODO: could we use the same for the non-deletes?
const resolverForDeletes = new source_deploy_retrieve_1.MetadataResolver(registry, source_deploy_retrieve_1.VirtualTreeContainer.fromFilePaths(grouping.deletes));
grouping.deletes
.flatMap((filename) => resolverForDeletes.getComponentsFromPath(filename))
.filter(guards_1.isDefined)
.map((component) => {
// if the component supports partial delete AND there are files that are not deleted,
// set the component for deploy, not for delete.
if ((0, functions_1.supportsPartialDelete)(component) && component.content && node_fs_1.default.existsSync(component.content)) {
// all bundle types have a directory name
try {
resolverForNonDeletes
.getComponentsFromPath((0, node_path_1.resolve)(projectPath, component.content))
.filter(guards_1.isDefined)
.map((nonDeletedComponent) => componentSet.add(nonDeletedComponent));
}
catch (e) {
logger.warn(`unable to find component at ${component.content}. That's ok if it was supposed to be deleted`);
}
}
else {
componentSet.add(component, source_deploy_retrieve_1.DestructiveChangesType.POST);
}
});
grouping.nonDeletes
.flatMap((filename) => {
try {
return resolverForNonDeletes.getComponentsFromPath((0, node_path_1.resolve)(projectPath, filename));
}
catch (e) {
logger.warn(`unable to resolve ${filename}`);
return undefined;
}
})
.filter(guards_1.isDefined)
.map((component) => componentSet.add(component));
// there may have been ignored files, but componentSet.add doesn't automatically track them.
// We'll manually set the ignored paths from what the resolver has been tracking
componentSet.forceIgnoredPaths = new Set([...(componentSet.forceIgnoredPaths ?? [])].concat(Array.from(resolverForNonDeletes.forceIgnoredPaths)));
componentSet.projectDirectory = projectPath;
return componentSet;
})
.filter((componentSet) => componentSet.size > 0 || componentSet.forceIgnoredPaths?.size);
};
exports.getComponentSets = getComponentSets;
//# sourceMappingURL=localComponentSetArray.js.map