sfdx-hardis
Version:
Swiss-army-knife Toolbox for Salesforce. Allows you to define a complete CD/CD Pipeline. Orchestrate base commands and assist users with interactive wizards
140 lines (138 loc) • 6.8 kB
JavaScript
/* jscpd:ignore-start */
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
import { Messages } from '@salesforce/core';
import c from "chalk";
import * as path from "path";
import { ensureGitRepository, git, isCI, uxLog, } from '../../../../common/utils/index.js';
import { prompts } from '../../../../common/utils/prompts.js';
import moment from 'moment';
import { generateFlowVisualGitDiff, generateHistoryDiffMarkdown } from '../../../../common/utils/mermaidUtils.js';
import { MetadataUtils } from '../../../../common/metadata-utils/index.js';
import { WebSocketClient } from '../../../../common/websocketClient.js';
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('sfdx-hardis', 'org');
export default class GenerateFlowGitDiff extends SfCommand {
static title = 'Generate Flow Visual Gif Diff';
static description = `Generate Flow Visual Git Diff markdown between 2 commits
Note: This command might requires -js/mermaid-cli to be installed.
Run \`npm install -js/mermaid-cli --global\`
`;
static examples = [
'$ sf hardis:project:generate:flow-git-diff',
'$ sf hardis:project:generate:flow-git-diff --flow "force-app/main/default/flows/Opportunity_AfterUpdate_Cloudity.flow-meta.xml" --commit-before 8bd290e914c9dbdde859dad7e3c399776160d704 --commit-after e0835251bef6e400fb91e42f3a31022f37840f65'
];
static flags = {
flow: Flags.string({
description: 'Path to flow file (will be prompted if not set)',
}),
"commit-before": Flags.string({
description: 'Hash of the commit of the previous flow state, or "allStates" (will be prompted if not set)',
default: ""
}),
"commit-after": Flags.string({
description: 'Hash of the commit of the new flow state (will be prompted if not set)',
default: "",
}),
debug: Flags.boolean({
char: 'd',
default: false,
description: messages.getMessage('debugMode'),
}),
websocket: Flags.string({
description: messages.getMessage('websocket'),
}),
skipauth: Flags.boolean({
description: 'Skip authentication check when a default username is required',
}),
};
// Set this to true if your command requires a project workspace; 'requiresProject' is false by default
static requiresProject = true;
flowFile;
flowLabel;
commitBefore = "";
commitAfter = "";
debugMode = false;
/* jscpd:ignore-end */
async run() {
const { flags } = await this.parse(GenerateFlowGitDiff);
this.flowFile = flags.flow || "";
this.commitBefore = flags["commit-before"] || "";
this.commitAfter = flags["commit-after"] || "";
this.debugMode = flags.debug || false;
// Check git repo
await ensureGitRepository();
// Prompt flow file if not send as input param
if (this.flowFile == "" && !isCI) {
this.flowFile = await MetadataUtils.promptFlow();
}
this.flowLabel = path.basename(this.flowFile, ".flow-meta.xml");
// List states of flow file using git
const fileHistory = await git().log({ file: this.flowFile });
if (fileHistory.all.length === 1) {
uxLog("success", this, c.green(`There is only one state for Flow ${this.flowFile}`));
return {};
}
// Build prompt choices
let allChoices = [];
if ((this.commitBefore === "" || this.commitAfter === "") && !isCI) {
allChoices = fileHistory.all.map(log => {
return {
value: log.hash,
title: `${moment(log.date).format("ll")}: ${log.message}`,
description: `By ${log.author_name}(${log.author_email}) in ${log.refs}`
};
});
}
// Prompt commits if not sent as input parameter
if (this.commitBefore === "" && !isCI) {
const commitBeforeSelectRes = await prompts({
type: 'select',
name: 'before',
message: 'Please select BEFORE UPDATE commit',
description: 'Choose the commit representing the state before your changes',
placeholder: 'Select a commit',
choices: [...allChoices, ...[
{
title: "Calculate for all Flow states",
value: "allStates",
description: "Requires mkdocs-material to be read correctly. If you do not have it, we advise to select 2 commits for comparison."
}
]]
});
this.commitBefore = commitBeforeSelectRes.before;
}
let diffMdFile;
if (this.commitBefore === "allStates") {
diffMdFile = await generateHistoryDiffMarkdown(this.flowFile, this.debugMode);
}
else {
if (this.commitAfter === "" && !isCI) {
// Compute between 2 commits: prompt for the second one
const commitAfterSelectRes = await prompts({
type: 'select',
name: 'after',
message: 'Please select AFTER UPDATE commit',
description: 'Choose the commit representing the state after your changes',
placeholder: 'Select a commit',
choices: allChoices
});
this.commitAfter = commitAfterSelectRes.after;
}
// Generate diff
const { outputDiffMdFile } = await generateFlowVisualGitDiff(this.flowFile, this.commitBefore, this.commitAfter, { svgMd: true, pngMd: false, mermaidMd: this.debugMode, debug: this.debugMode });
diffMdFile = outputDiffMdFile;
}
// Open file in a new VS Code tab if available
WebSocketClient.requestOpenFile(path.relative(process.cwd(), diffMdFile));
WebSocketClient.sendReportFileMessage(diffMdFile, path.basename(diffMdFile).replace(".md", "") + " Documentation", 'report');
uxLog("action", this, c.green(`Markdown Flow diff documentation generated for ${path.basename(diffMdFile).replace(".md", "")}.`));
if (this.commitBefore === "allStates") {
uxLog("warning", this, c.yellow(`It is recommended to use mkdocs-material to read it correctly (see https://sfdx-hardis.cloudity.com/hardis/doc/project2markdown/#doc-html-pages)`));
}
// Return an object to be displayed with --json
return {
diffMdFile: diffMdFile
};
}
}
//# sourceMappingURL=flow-git-diff.js.map