@flxbl-io/sfp
Version:
sfp is a CLI tool to help you manage your Salesforce projects in an artifact centric model
165 lines • 16.7 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path = require('path');
const fs = __importStar(require("fs-extra"));
const sfp_logger_1 = __importStar(require("@flxbl-io/sfp-logger"));
const core_1 = require("@salesforce/core");
const SFPOrg_1 = __importDefault(require("../../org/SFPOrg"));
const source_tracking_1 = require("@salesforce/source-tracking");
const ProjectConfig_1 = __importDefault(require("../../project/ProjectConfig"));
const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
const os_1 = require("os");
const SfpPackage_1 = require("../../package/SfpPackage");
const Git_1 = __importDefault(require("../../git/Git"));
const tmp = require('tmp');
class ClientSourceTracking {
constructor() { }
static async create(conn, logger) {
const clientSourceTracking = new ClientSourceTracking();
clientSourceTracking.conn = conn;
clientSourceTracking.org = await SFPOrg_1.default.create({ connection: clientSourceTracking.conn });
clientSourceTracking.logger = logger;
clientSourceTracking.sfdxOrgIdDir = `.sf/orgs/${clientSourceTracking.org.getOrgId()}`;
return clientSourceTracking;
}
async creatSourceTrackingFiles() {
await this.createRemoteSourceTracking();
await this.createLocalSourceTracking();
}
async createRemoteSourceTracking() {
const project = await core_1.SfProject.resolve();
const tracking = await source_tracking_1.SourceTracking.create({
org: this.org,
project: project,
});
await tracking.resetRemoteTracking();
await tracking.ensureLocalTracking();
}
/**
* Create local source tracking from sfp artifacts installed in scratch org
*/
async createLocalSourceTracking() {
let git;
try {
git = await Git_1.default.initiateRepoAtTempLocation(this.logger);
const sfpArtifacts = await this.org.getInstalledArtifacts();
if (sfpArtifacts.length == 0) {
throw new Error(`Unable to find any artifacts in the org`);
}
//clean up MPD to just one package, so that source tracking lib
//does do a full scan and break
this.cleanupSFDXProjectJsonTonOnePackage(git.getRepositoryPath(), sfpArtifacts[0].Name);
const project = await core_1.SfProject.resolve(git.getRepositoryPath());
// Create local source tracking files in temp repo
const tracking = await source_tracking_1.SourceTracking.create({
org: this.org,
project: project,
});
sfp_logger_1.default.log(`Total Artifacts to Analyze: ${sfpArtifacts.length}`, sfp_logger_1.LoggerLevel.INFO, this.logger);
let count = 1;
for (const artifact of sfpArtifacts) {
sfp_logger_1.default.log(os_1.EOL, sfp_logger_1.LoggerLevel.INFO, this.logger);
sfp_logger_1.default.log((0, sfp_logger_1.COLOR_HEADER)(`Package ${count} of ${sfpArtifacts.length}`), sfp_logger_1.LoggerLevel.INFO, this.logger);
sfp_logger_1.default.log(`Analyzing package ${(0, sfp_logger_1.COLOR_KEY_MESSAGE)(artifact.Name)}`, sfp_logger_1.LoggerLevel.INFO, this.logger);
// Checkout version of source code from which artifact was created
await git.checkout(artifact.CommitId__c, true);
sfp_logger_1.default.log(`Version pushed while preparing this org is ${artifact.Version__c} with SHA ${artifact.CommitId__c}`, sfp_logger_1.LoggerLevel.INFO, this.logger);
//clean up MPD to per package, to speed up
this.cleanupSFDXProjectJsonTonOnePackage(git.getRepositoryPath(), artifact.Name);
const projectConfig = ProjectConfig_1.default.getSFDXProjectConfig(git.getRepositoryPath());
try {
const packageType = ProjectConfig_1.default.getPackageType(projectConfig, artifact.Name);
if (packageType === SfpPackage_1.PackageType.Unlocked || packageType === SfpPackage_1.PackageType.Source) {
let componentSet = source_deploy_retrieve_1.ComponentSet.fromSource(path.join(git.getRepositoryPath(), ProjectConfig_1.default.getPackageDescriptorFromConfig(artifact.Name, projectConfig).path));
let components = componentSet.getSourceComponents();
//Get all components in the directory
//Count for logging purposes. dont have to waste processing convering
//a lazy collection to array once again
let componentCount = 1;
let componentPaths = [];
for (const component of components) {
componentCount++;
componentPaths.push(component.xml);
if (component.content)
componentPaths.push(component.content);
}
await tracking.updateLocalTracking({
files: componentPaths,
});
sfp_logger_1.default.log(`Updated source tracking for package: ${artifact.Name} with ${componentCount} items`, sfp_logger_1.LoggerLevel.INFO, this.logger);
}
else
sfp_logger_1.default.log(`Encountered data package... skipping`, sfp_logger_1.LoggerLevel.INFO, this.logger);
}
catch (error) {
if (error.message.includes) {
sfp_logger_1.default.log(` sfp is unable to sync the package ${artifact.Name}${os_1.EOL},
as it not able to find the find equivalent git references`, sfp_logger_1.LoggerLevel.ERROR, this.logger);
}
else
sfp_logger_1.default.log(`Unable to update local source tracking due to ${error.message}`, sfp_logger_1.LoggerLevel.INFO, this.logger);
sfp_logger_1.default.log(`Skipping package.. ${artifact.Name}`, sfp_logger_1.LoggerLevel.WARN, this.logger);
}
count++;
}
sfp_logger_1.default.log(os_1.EOL, sfp_logger_1.LoggerLevel.INFO, this.logger);
sfp_logger_1.default.log(`Copying the temporary repository over to original location`, sfp_logger_1.LoggerLevel.INFO, this.logger);
// Copy source tracking files from temp repo to actual repo
fs.mkdirpSync(path.join(this.sfdxOrgIdDir, 'localSourceTracking'));
fs.copySync(path.join(git.getRepositoryPath(), this.sfdxOrgIdDir, 'localSourceTracking'), path.join(this.sfdxOrgIdDir, 'localSourceTracking'));
}
catch (error) {
if (error.message.includes(`reference is not a tree`)) {
sfp_logger_1.default.log(`sfp is unable to sync this repository,
as it not able to find the matching git references${os_1.EOL}
Are you sure this pool was created from the same repository?`, sfp_logger_1.LoggerLevel.ERROR, this.logger);
}
else
sfp_logger_1.default.log(`Unable to update local source tracking due to ${error}`, sfp_logger_1.LoggerLevel.ERROR, this.logger);
}
finally {
if (git) {
git.deleteTempoRepoIfAny();
}
}
}
cleanupSFDXProjectJsonTonOnePackage(projectDir, packageName) {
try {
let cleanedUpProjectManifest = ProjectConfig_1.default.cleanupMPDFromProjectDirectory(projectDir, packageName);
fs.writeJSONSync(path.join(projectDir, 'sfdx-project.json'), cleanedUpProjectManifest, {
spaces: 4,
});
}
catch (error) {
sfp_logger_1.default.log(`sfdx-project.json not found/unable to write, skipping..` + error.message, sfp_logger_1.LoggerLevel.DEBUG, this.logger);
}
}
}
exports.default = ClientSourceTracking;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2xpZW50U291cmNlVHJhY2tpbmcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29yZS9zY3JhdGNob3JnL3Bvb2wvQ2xpZW50U291cmNlVHJhY2tpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUM3Qiw2Q0FBK0I7QUFDL0IsbUVBQXVHO0FBQ3ZHLDJDQUF5RDtBQUN6RCw4REFBc0M7QUFDdEMsaUVBQTZEO0FBQzdELGdGQUF3RDtBQUN4RCwrRUFBa0U7QUFDbEUsMkJBQXlCO0FBQ3pCLHlEQUF1RDtBQUN2RCx3REFBZ0M7QUFFaEMsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBRTNCLE1BQXFCLG9CQUFvQjtJQU9yQyxnQkFBdUIsQ0FBQztJQUV4QixNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFnQixFQUFFLE1BQWM7UUFDaEQsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLG9CQUFvQixFQUFFLENBQUM7UUFFeEQsb0JBQW9CLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUVqQyxvQkFBb0IsQ0FBQyxHQUFHLEdBQUcsTUFBTSxnQkFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLFVBQVUsRUFBRSxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzFGLG9CQUFvQixDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFFckMsb0JBQW9CLENBQUMsWUFBWSxHQUFHLFlBQVksb0JBQW9CLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUM7UUFFdEYsT0FBTyxvQkFBb0IsQ0FBQztJQUNoQyxDQUFDO0lBRUQsS0FBSyxDQUFDLHdCQUF3QjtRQUMxQixNQUFNLElBQUksQ0FBQywwQkFBMEIsRUFBRSxDQUFDO1FBQ3hDLE1BQU0s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