@corekraft/flow-linter-core

中文文档
1.1.0发布于 2025/09/07MITTypeScriptCommonJS近 30 天下载 2073

A rule engine capable of conducting static analysis on the metadata associated with Salesforce Flows, Process Builders, and Workflows.

此软件包已被标记为弃用

Package deprecated due to licensing issues, please support the new product 'flow-lint' https://github.com/corekraft/flow-lint this version is of MIT license and completely restarted

原始使用文档
文档目录34 节
  1. Default Rules
  2. Action Calls In Loop
  3. Outdated API Version
  4. Auto Layout
  5. Copy API Name
  6. Cyclomatic Complexity
  7. DML Statement In A Loop
  8. Duplicate DML Operation
  9. Flow Naming Convention
  10. Get Record All Fields
  11. Hardcoded Id
  12. Hardcoded Url
  13. Inactive Flow
  14. Missing Fault Path
  15. Missing Flow Description
  16. Missing Null Handler
  17. Process Builder
  18. Recursive After Update
  19. Same Record Field Updates
  20. SOQL Query In A Loop
  21. Trigger Order
  22. Unconnected Element
  23. Unsafe Running Context
  24. Unused Variable
  25. Core Functions
  26. getRules(ruleNames?: string[]): IRuleDefinition[]
  27. parse(selectedUris: any): Promise<ParsedFlow[]>
  28. scan(parsedFlows: ParsedFlow[], ruleOptions?: IRulesConfig)…
  29. fix(results: ScanResult[]): ScanResult[]
  30. Configurations
  31. Rule Configuration
  32. Custom Rule Interface
  33. Exception Configuration
  34. Development Setup

flow-linter is a static configuration analysis tool that enforces Flow best practices.

Salesforce Flows are a powerful way to automate processes, but without proper guardrails, they can quickly become hard to maintain, error-prone, and inconsistent.

JavaScript has ESLint, Apex has PMD, but what about Flows? flow-linter brings the same rigor of linting and static code analysis—familiar to developers working with JavaScript or Apex—to Salesforce Flows.


Default Rules

Action Calls In Loop

ActionCallsInLoop - To prevent exceeding Apex governor limits, it is advisable to consolidate and bulkify your apex calls, utilizing a single action call containing a collection variable at the end of the loop.

Outdated API Version

APIVersion - Introducing newer API components may lead to unexpected issues with older versions of Flows, as they might not align with the underlying mechanics. Starting from API version 50.0, the Api Version attribute has been readily available on the Flow Object. To ensure smooth operation and reduce discrepancies between API versions, it is strongly advised to regularly update and maintain them.

Auto Layout

AutoLayout - With Canvas Mode set to Auto‑Layout, elements are spaced, connected, and aligned automatically, keeping your Flow neatly organized—saving you time.

Copy API Name

CopyAPIName - Maintaining multiple elements with a similar name, like Copy_X_Of_Element, can diminish the overall readability of your Flow. When copying and pasting these elements, remember to update the API name of the newly created copy.

Cyclomatic Complexity

CyclomaticComplexity - The number of loops and decision rules, plus the number of decisions. Use a combination of 1) subflows and 2) breaking flows into multiple concise trigger‑ordered flows to reduce cyclomatic complexity within a single flow, ensuring maintainability and simplicity.

DML Statement In A Loop

DMLStatementInLoop - To prevent exceeding Apex governor limits, consolidate all your database operations—record creation, updates, or deletions—at the conclusion of the flow.

Duplicate DML Operation

DuplicateDMLOperation - When a flow executes database changes or actions between two screens, prevent users from navigating backward between screens; otherwise, duplicate database operations may be performed.

Flow Naming Convention

FlowName - The readability of a flow is paramount. Establishing a naming convention significantly enhances findability, searchability, and overall consistency. Include at least a domain and a brief description of the flow’s actions, for example Service_OrderFulfillment.

Get Record All Fields

GetRecordAllFields - Following the principle of least privilege (PoLP), avoid using Get Records with “Automatically store all fields” unless necessary.

Hardcoded Id

HardcodedId - Avoid hard‑coding IDs because they are org specific. Instead, pass them into variables at the start of the flow—via merge‑field URL parameters or a Get Records element.

Hardcoded Url

HardcodedUrl - Avoid hard‑coding URLs because they are environment specific. Use an $API formula (preferred) or environment‑specific sources like custom labels, metadata, or settings.

Inactive Flow

InactiveFlow - Like cleaning out your closet: deleting unused flows is essential. Inactive flows can still cause trouble—such as accidentally deleting records during testing, or being activated as subflows.

Missing Fault Path

MissingFaultPath - A flow may fail to execute an operation as intended. By default, the flow displays an error to the user and emails the creator. Customize this behavior by incorporating a Fault Path.

Missing Flow Description

FlowDescription - Descriptions play a vital role in documentation. We highly recommend including details about where flows are used and their intended purpose.

Missing Null Handler

MissingNullHandler - When a Get Records operation finds no data, it returns null. Validate data by using a Decision element to check for a non‑null result.

Process Builder

ProcessBuilder - Salesforce is transitioning away from Workflow Rules and Process Builder in favor of Flow. Begin migrating your organization’s automation to Flow.

Recursive After Update

RecursiveAfterUpdate - After‑update flows are meant for modifying other records. Using them on the same record can cause recursion. Consider before‑save flows for same‑record updates.

Same Record Field Updates

SameRecordFieldUpdates - Similar to triggers, before‑save contexts can update the same record via $Record without invoking DML.

SOQL Query In A Loop

SOQLQueryInLoop - To prevent exceeding Apex governor limits, consolidate all SOQL queries at the end of the flow.

Trigger Order

TriggerOrder - Guarantee your flow execution order with the Trigger Order property introduced in Spring ’22.

Unconnected Element

UnconnectedElement - Avoid unconnected elements that are not used by the flow to keep flows efficient and maintainable.

Unsafe Running Context

UnsafeRunningContext - This flow is configured to run in System Mode without Sharing, granting all users permission to view and edit all data. This can lead to unsafe data access.

Unused Variable

UnusedVariable - To maintain efficiency and manageability, avoid including variables that are never referenced.


Core Functions

getRules(ruleNames?: string[]): IRuleDefinition[]

Retrieves rule definitions used in the scanner.

parse(selectedUris: any): Promise<ParsedFlow[]>

Parses metadata from selected Flow files.

scan(parsedFlows: ParsedFlow[], ruleOptions?: IRulesConfig): ScanResult[]

Runs rules against parsed flows and returns scan results.

fix(results: ScanResult[]): ScanResult[]

Attempts to apply automatic fixes where available.


Configurations

Rule Configuration

Advanced rules provide granular control by allowing rules to be intentionally disabled at the rule level, ensuring consistent application across all flows. Additionally, the concept of suppressions is introduced, enabling users to "whitelist" specific components. This mechanism allows for exceptions to be defined, offering flexibility in rule enforcement while maintaining overall governance and compliance.

JSON

{
  "rules": {
    "<RuleName>": {
      "path": "local_path_of_your_js_file", // optional: when defined, this configuration will be used for the engine to recognize your custom rule
      "severity": "error",
      "expression": ">=58",
      "disabled": "true", // optional: when true, rule will not be applied to all flows being scanned
      "suppressions": ["LogACall"] // optional: when defined, takes an array of suppressed elements (not based on name but on specific type)
    }
  }
}

YAML

rules:
  MissingFaultPath: # User Defined Rule configuration
    path: "local_path_of_your_js_file" # Optional: when defined, this configuration will be used for the engine to recognize your rule
    severity: error # Optional: User Defined severity, can be `info`, `warn`, `error`
    expression: ">=58" # Optional: User defined expression, only applies if rule is Configurable=true
    disabled: "true" # Optional: when true, rule will not be applied to all flows being scanned
    suppressions: # Optional: when defined, takes an array of elements to be suppressed, keys can be found on suppressionElements on the rule definition
      - LogACall # Optional: when defined, rule engine will look at suppressionElement defined on the rule to match against this list
  • Severity:

    • Optional values for severity are "error", "warning", and "note".
    • If severity is provided, it overwrites the default severity, which is "error".
  • Expression:

    • Expression is used to overwrite standard values in configurable rules.
  • Path:

    • If a path is provided, it can either replace an existing rule with a new rule definition or load a custom rule.
    • Ensure that the rule name used in the path matches the exported class name of the rule.

Custom Rule Interface

To create custom rules that can be loaded using the path attribute of the rule configurations, they need to adhere to the IRuleInterface. Please refer to the Custom Rule Creation Guide for detailed instructions.

Exception Configuration

Specifying exceptions allows you to exclude specific scenarios from rule enforcement. Exceptions can be specified at the flow, rule, or result level to provide fine-grained control. Below is a breakdown of the available attributes of exception configuration:

{
  "exceptions": {
    "<FlowName>": {
      "<RuleName>": [
        "<ResultName>",
        "<ResultName>",
        ...
      ]
    },
    ...
  }
}
  • FlowName:

    • The name of the flow where exceptions apply.
  • RuleName:

    • The name of the rule for which exceptions are defined.
  • ResultName:

    • The specific result or condition within the rule for which exceptions are specified.

Development Setup

  1. Clone the repo:

    git clone https://github.com/corekraft/flow-linter-core.git
    
  2. Install dependencies:

    npm install
    
  3. Build the project:

    npm run build
    
  4. Run tests:

    npm run test
    
  5. (Optional) Deploy sample flows:

    npm run deploy:flows -- -o
    

版本与发布记录

@corekraft/flow-linter-core 共发布 5 个版本,首次发布于 2025/08/22;过去 12 个月发布了 0 个版本。

版本发布日期距今
1.1.0latest2025/09/071.2 年前
1.0.3beta2025/09/071.2 年前
1.0.22025/09/071.2 年前
1.0.12025/08/221.2 年前
1.0.02025/08/221.2 年前

关于 @corekraft/flow-linter-core 的常见问题

@corekraft/flow-linter-core 是什么?

A rule engine capable of conducting static analysis on the metadata associated with Salesforce Flows, Process Builders, and Workflows.注意:该包已被作者标记为弃用——Package deprecated due to licensing issues, please support the new product 'flow-lint' https://github.com/corekraft/flow-lint this version is of MIT license and completely restarted

如何安装 @corekraft/flow-linter-core?

在项目目录运行 npm install @corekraft/flow-linter-core,或使用 pnpm add / yarn add / bun add。

@corekraft/flow-linter-core 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@corekraft/flow-linter-core 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@corekraft/flow-linter-core 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js ^20 || ^22 || ^24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@corekraft/flow-linter-core 可以商用吗?

@corekraft/flow-linter-core 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@corekraft/flow-linter-core 的下载量有多少?

根据 npm 官方下载统计,@corekraft/flow-linter-core 在 2026/10/11 – 2026/11/09 这 30 天内被下载 2,073 次,日均约 69 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@corekraft/flow-linter-core 还在维护吗?

最新版本 1.1.0 发布于 2025/09/07(1.2 年前);至今共发布 5 个版本,其中过去 12 个月发布了 0 个;首次发布于 2025/08/22。作者已将其标记为弃用,新项目建议寻找替代方案。