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
111 lines (104 loc) • 5.29 kB
JavaScript
/* jscpd:ignore-start */
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
import { Messages } from '@salesforce/core';
import c from 'chalk';
import { glob } from 'glob';
import * as path from 'path';
import { uxLog } from '../../../../common/utils/index.js';
import fs from 'fs-extra';
import { GLOB_IGNORE_PATTERNS } from '../../../../common/utils/projectUtils.js';
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('sfdx-hardis', 'org');
export default class CleanSystemDebug extends SfCommand {
static title = 'Clean System debug';
static description = `
## Command Behavior
**Removes or comments out \`System.debug()\` statements from Apex classes and triggers in your Salesforce DX project.**
This command helps maintain clean and optimized Apex code by eliminating debug statements that are often left in production code. While \`System.debug()\` is invaluable during development, it can impact performance and expose sensitive information if left in deployed code.
Key functionalities:
- **Targeted File Scan:** Scans all Apex class (.cls) and trigger (.trigger) files within the specified root folder (defaults to \`force-app\`).
- **Conditional Action:**
- **Comment Out (default):** By default, it comments out \`System.debug()\` lines by prepending // to them.
- **Delete (\`--delete\` flag):** If the \`--delete\` flag is used, it completely removes the lines containing \`System.debug()\`.
- **Exclusion:** Lines containing \`NOPMD\` are ignored, allowing developers to intentionally keep specific debug statements.
<details markdown="1">
<summary>Technical explanations</summary>
The command's technical implementation involves:
- **File Discovery:** Uses \`glob\` to find all Apex class and trigger files.
- **Content Reading:** Reads the content of each Apex file line by line.
- **Pattern Matching:** Checks each line for the presence of \`System.debug\` (case-insensitive).
- **Line Modification:**
- If \`System.debug\` is found and the \`--delete\` flag is not used, it modifies the line to comment out the debug statement.
- If \`System.debug\` is found and the \`--delete\` flag is used, it removes the line entirely.
- **File Writing:** If any changes are made to a file, the modified content is written back to the file using \`fs.writeFile\`.
- **Logging:** Provides a summary of how many files were cleaned.
</details>
`;
static examples = ['$ sf hardis:project:clean:systemdebug'];
static flags = {
folder: Flags.string({
char: 'f',
default: 'force-app',
description: 'Root folder',
}),
websocket: Flags.string({
description: messages.getMessage('websocket'),
}),
skipauth: Flags.boolean({
description: 'Skip authentication check when a default username is required',
}),
delete: Flags.boolean({
char: 'd',
default: false,
description: 'Delete lines with System.debug',
}),
};
// Set this to true if your command requires a project workspace; 'requiresProject' is false by default
static requiresProject = true;
folder;
del = false;
async run() {
const { flags } = await this.parse(CleanSystemDebug);
this.folder = flags.folder || './force-app';
this.del = flags.delete || false;
// Delete standard files when necessary
uxLog("action", this, c.cyan(`Comment or delete System.debug line in apex classes and triggers`));
/* jscpd:ignore-end */
const rootFolder = path.resolve(this.folder);
const findManagedPattern = rootFolder + `/**/*.{cls,trigger}`;
const matchingFiles = await glob(findManagedPattern, { cwd: process.cwd(), ignore: GLOB_IGNORE_PATTERNS });
let countFiles = 0;
for (const apexFile of matchingFiles) {
const fileText = await fs.readFile(apexFile, 'utf8');
const fileLines = fileText.split('\n');
let counter = 0;
let writeF = false;
for (const line of fileLines) {
if ((line.includes('System.debug') || line.includes('system.debug')) && !line.includes('NOPMD')) {
if (!this.del && line.trim().substring(0, 2) != '//') {
fileLines[counter] = line
.replace('System.debug', '// System.debug')
.replace('system.debug', '// system.debug');
writeF = true;
}
else if (this.del) {
delete fileLines[counter];
writeF = true;
}
}
counter++;
}
if (writeF) {
const joinLines = fileLines.join('\n');
await fs.writeFile(apexFile, joinLines, 'utf8');
countFiles++;
}
}
// Summary
const msg = `Cleaned ${c.green(c.bold(countFiles))} class(es) and trigger(s)`;
uxLog("action", this, c.cyan(msg));
// Return an object to be displayed with --json
return { outputString: msg };
}
}
//# sourceMappingURL=systemdebug.js.map