Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions packages/orgcheck-api/src/api/core/orgcheck-api-globalparameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ const GROUP_TYPE_QUEUE = 'queue';
const OBJECTS_MODE = 'objectsmode';
const OBJECTS_MODE_FULL = 'full';
const OBJECTS_MODE_LITE = 'lite';
const LFS_BETA_MODE = 'lfsbetamode';
const LFS_MIN_SEVERITY = 'lfsminseverity';
const LFS_SEVERITY_ALL = '*';

export class OrgCheckGlobalParameter {

Expand Down Expand Up @@ -196,4 +199,47 @@ export class OrgCheckGlobalParameter {
static getObjectsMode(parameters: Map<string, string>): string {
return parameters?.get(OBJECTS_MODE) ?? OBJECTS_MODE_FULL;
}

/**
* @description Key to enable Lightning Flow Scanner beta rules
* @returns {string} The value of the constant
* @static
*/
static get LFS_BETA_MODE(): string { return LFS_BETA_MODE; }

/**
* @description Key for the minimum LFS violation severity to display ('error', 'warning', 'note', or '*' for all)
* @returns {string} The value of the constant
* @static
*/
static get LFS_MIN_SEVERITY(): string { return LFS_MIN_SEVERITY; }

/**
* @description Wildcard value meaning all severities
* @returns {string} The value of the constant
* @static
*/
static get LFS_SEVERITY_ALL(): string { return LFS_SEVERITY_ALL; }

/**
* @description Get the LFS beta mode setting from the parameters
* @param {Map<string, unknown>} parameters - Map of parameters
* @returns {boolean} true if beta rules should be included
* @static
* @public
*/
static getLfsBetaMode(parameters: Map<string, unknown>): boolean {
return (parameters?.get(LFS_BETA_MODE) as boolean) ?? false;
}

/**
* @description Get the LFS minimum severity from the parameters
* @param {Map<string, unknown>} parameters - Map of parameters
* @returns {string} The minimum severity or '*' (all)
* @static
* @public
*/
static getLfsMinSeverity(parameters: Map<string, unknown>): string {
return (parameters?.get(LFS_MIN_SEVERITY) as string) ?? LFS_SEVERITY_ALL;
}
}
48 changes: 24 additions & 24 deletions packages/orgcheck-api/src/api/core/orgcheck-api-secretsauce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -738,191 +738,191 @@ const ALL_SCORE_RULES: ScoreRule[] = [
{
id: 100,
description: '[LFS] Inactive Flow',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('InactiveFlow') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'InactiveFlow') || false) as (data: unknown) => boolean,
errorMessage: `This flow is inactive. Consider activating it or removing it from your org.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.USELESS
}, {
id: 101,
description: '[LFS] Process Builder',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('ProcessBuilder') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'ProcessBuilder') || false) as (data: unknown) => boolean,
errorMessage: `Time to migrate this process builder to flow!`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.USELESS
}, {
id: 102,
description: '[LFS] Missing Flow Description',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('FlowDescription') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'FlowDescription') || false) as (data: unknown) => boolean,
errorMessage: `This flow does not have a description. Add documentation about its purpose and usage.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.DOCUMENTATION
}, {
id: 103,
description: '[LFS] Outdated API Version',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('APIVersion') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'APIVersion') || false) as (data: unknown) => boolean,
errorMessage: `The API version of this flow is outdated. Update it to the newest version.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.API_VERSION
}, {
id: 104,
description: '[LFS] Unsafe Running Context',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('UnsafeRunningContext') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'UnsafeRunningContext') || false) as (data: unknown) => boolean,
errorMessage: `This flow runs in System Mode without Sharing, which can lead to unsafe data access.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.SECURITY
}, {
id: 105,
description: '[LFS] SOQL Query In Loop',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('SOQLQueryInLoop') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'SOQLQueryInLoop') || false) as (data: unknown) => boolean,
errorMessage: `This flow has SOQL queries inside loops. Consolidate queries at the end of the flow to avoid governor limits.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.CODE_QUALITY
}, {
id: 106,
description: '[LFS] DML Statement In Loop',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('DMLStatementInLoop') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'DMLStatementInLoop') || false) as (data: unknown) => boolean,
errorMessage: `This flow has DML operations inside loops. Consolidate DML at the end to avoid governor limits.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.CODE_QUALITY
}, {
id: 107,
description: '[LFS] Action Calls In Loop',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('ActionCallsInLoop') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'ActionCallsInLoop') || false) as (data: unknown) => boolean,
errorMessage: `This flow has action calls inside loops. Bulkify apex calls using collection variables.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.CODE_QUALITY
}, {
id: 108,
description: '[LFS] Hardcoded Id',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('HardcodedId') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'HardcodedId') || false) as (data: unknown) => boolean,
errorMessage: `This flow contains hardcoded IDs which are org-specific. Use variables or merge fields instead.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.HARDCODED_ID
}, {
id: 109,
description: '[LFS] Hardcoded Url',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('HardcodedUrl') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'HardcodedUrl') || false) as (data: unknown) => boolean,
errorMessage: `This flow contains hardcoded URLs. Use $API formulas or custom labels instead.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.HARDCODED_URL
}, {
id: 110,
description: '[LFS] Missing Null Handler',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('MissingNullHandler') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'MissingNullHandler') || false) as (data: unknown) => boolean,
errorMessage: `This flow has Get Records operations without null checks. Use decision elements to validate results.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.CODE_QUALITY
}, {
id: 111,
description: '[LFS] Missing Fault Path',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('MissingFaultPath') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'MissingFaultPath') || false) as (data: unknown) => boolean,
errorMessage: `This flow has DML or action operations without fault handlers. Add fault paths for better error handling.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.CODE_QUALITY
}, {
id: 112,
description: '[LFS] Recursive After Update',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('RecursiveAfterUpdate') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'RecursiveAfterUpdate') || false) as (data: unknown) => boolean,
errorMessage: `This after-update flow modifies the same record that triggered it, risking recursion. Use before-save flows instead.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.CODE_QUALITY
}, {
id: 113,
description: '[LFS] Duplicate DML Operation',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('DuplicateDMLOperation') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'DuplicateDMLOperation') || false) as (data: unknown) => boolean,
errorMessage: `This flow allows navigation back after DML operations, which may cause duplicate changes.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.CODE_QUALITY
}, {
id: 114,
description: '[LFS] Get Record All Fields',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('GetRecordAllFields') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'GetRecordAllFields') || false) as (data: unknown) => boolean,
errorMessage: `This flow uses Get Records with "all fields". Specify only needed fields for better performance.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.CODE_QUALITY
}, {
id: 115,
description: '[LFS] Record ID as String',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('RecordIdAsString') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'RecordIdAsString') || false) as (data: unknown) => boolean,
errorMessage: `This flow uses a String recordId variable. Modern flows can receive the entire record object, eliminating Get Records queries.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.CODE_QUALITY
}, {
id: 116,
description: '[LFS] Unconnected Element',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('UnconnectedElement') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'UnconnectedElement') || false) as (data: unknown) => boolean,
errorMessage: `This flow has unconnected elements that are not in use. Remove them to maintain clarity.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.USELESS
}, {
id: 117,
description: '[LFS] Unused Variable',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('UnusedVariable') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'UnusedVariable') || false) as (data: unknown) => boolean,
errorMessage: `This flow has unused variables. Remove them to maintain efficiency.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.USELESS
}, {
id: 118,
description: '[LFS] Copy API Name',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('CopyAPIName') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'CopyAPIName') || false) as (data: unknown) => boolean,
errorMessage: `This flow has elements with copy-paste naming patterns like "Copy_X_Of_Element". Update API names for readability.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.DOCUMENTATION
}, {
id: 120,
description: '[LFS] Same Record Field Updates',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('SameRecordFieldUpdates') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'SameRecordFieldUpdates') || false) as (data: unknown) => boolean,
errorMessage: `This before-save flow uses Update Records on $Record. Use direct assignment instead for better performance.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.CODE_QUALITY
}, {
id: 122,
description: '[LFS] Missing Metadata Description',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('MissingMetadataDescription') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'MissingMetadataDescription') || false) as (data: unknown) => boolean,
errorMessage: `This flow has elements or variables without descriptions. Add documentation for better maintainability.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.DOCUMENTATION
}, {
id: 123,
description: '[LFS] Missing Filter Record Trigger',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('MissingFilterRecordTrigger') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'MissingFilterRecordTrigger') || false) as (data: unknown) => boolean,
errorMessage: `This record-triggered flow lacks filters on changed fields or entry conditions, causing unnecessary executions.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.CODE_QUALITY
}, {
id: 124,
description: '[LFS] Transform Instead of Loop',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('TransformInsteadOfLoop') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'TransformInsteadOfLoop') || false) as (data: unknown) => boolean,
errorMessage: `This flow uses Loop + Assignment which could be replaced with Transform element (10x faster).`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
category: SCORE_RULE_CATEGORIES.CODE_QUALITY
}, {
id: 125,
description: '[LFS] Missing Auto Layout',
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.includes('AutoLayout') || false) as (data: unknown) => boolean,
formula: ((d: SfdcFlow) => d?.currentVersionRef?.lfsViolations?.some(v => v.name === 'AutoLayout') || false) as (data: unknown) => boolean,
errorMessage: `This flow doesn't use Auto-Layout mode. Enable it to keep your flow organized automatically.`,
badField: 'currentVersionRef.lfsViolations',
applicable: [ DataAliases.SfdcFlow ],
Expand Down
Loading