@flow-scanner/lightning-flow-scanner-core 6.10.6 → 6.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -60
- package/index.d.ts +5 -2
- package/index.js +19 -0
- package/main/config/NodeIcons.d.ts +24 -0
- package/main/config/NodeIcons.js +122 -0
- package/main/config/VariableIcons.d.ts +25 -0
- package/main/config/VariableIcons.js +53 -0
- package/main/libs/Compiler.d.ts +1 -2
- package/main/libs/Compiler.js +10 -16
- package/main/libs/ExportDiagram.d.ts +41 -0
- package/main/libs/ExportDiagram.js +40 -0
- package/main/models/Flow.d.ts +8 -0
- package/main/models/Flow.js +57 -2
- package/main/models/FlowGraph.d.ts +85 -0
- package/main/models/FlowGraph.js +532 -0
- package/main/models/FlowNode.d.ts +58 -2
- package/main/models/FlowNode.js +161 -3
- package/main/models/FlowVariable.d.ts +59 -1
- package/main/models/FlowVariable.js +118 -1
- package/main/models/LoopRuleCommon.js +11 -12
- package/main/rules/DuplicateDMLOperation.d.ts +1 -1
- package/main/rules/DuplicateDMLOperation.js +36 -67
- package/main/rules/MissingFaultPath.js +4 -14
- package/main/rules/TransformInsteadOfLoop.js +15 -16
- package/main/rules/UnconnectedElement.js +2 -9
- package/package.json +2 -2
- package/CONTRIBUTING.md +0 -31
- package/SECURITY.md +0 -55
- package/docs/media/banner.png +0 -0
package/README.md
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<a href="https://github.com/Flow-Scanner/lightning-flow-scanner/
|
|
3
|
-
<img src="https://img.shields.io/github/
|
|
4
|
-
</a>
|
|
5
|
-
<a href="https://github.com/Flow-Scanner/lightning-flow-scanner/graphs/contributors">
|
|
6
|
-
<img src="https://img.shields.io/github/contributors/Flow-Scanner/lightning-flow-scanner.svg?style=flat-square" alt="Contributors">
|
|
2
|
+
<a href="https://github.com/Flow-Scanner/lightning-flow-scanner/stargazers">
|
|
3
|
+
<img src="https://img.shields.io/github/stars/Flow-Scanner/lightning-flow-scanner?label=Stargazers&style=flat-square" alt="GitHub stars">
|
|
7
4
|
</a>
|
|
8
|
-
|
|
9
|
-
<img src="https://img.shields.io/npm/v/@flow-scanner/lightning-flow-scanner-core?label=
|
|
5
|
+
<a href="https://www.npmjs.com/package/@flow-scanner/lightning-flow-scanner-core">
|
|
6
|
+
<img src="https://img.shields.io/npm/v/@flow-scanner/lightning-flow-scanner-core?label=Core&style=flat-square" alt="Core version">
|
|
10
7
|
</a>
|
|
11
8
|
<a href="https://www.npmjs.com/package/lightning-flow-scanner">
|
|
12
|
-
<img src="https://img.shields.io/npm/v/lightning-flow-scanner?label=
|
|
9
|
+
<img src="https://img.shields.io/npm/v/lightning-flow-scanner?label=CLI&style=flat-square" alt="CLI version">
|
|
13
10
|
</a>
|
|
14
11
|
<a href="https://open-vsx.org/extension/ForceConfigControl/lightning-flow-scanner-vsx">
|
|
15
|
-
<img src="https://img.shields.io/open-vsx/v/ForceConfigControl/lightning-flow-scanner-vsx?label=
|
|
16
|
-
</a>
|
|
17
|
-
<a href="https://github.com/Flow-Scanner/lightning-flow-scanner/stargazers">
|
|
18
|
-
<img src="https://img.shields.io/github/stars/Flow-Scanner/lightning-flow-scanner?style=flat-square" alt="GitHub stars">
|
|
12
|
+
<img src="https://img.shields.io/open-vsx/v/ForceConfigControl/lightning-flow-scanner-vsx?label=VS%20Code&style=flat-square" alt="VS Code version">
|
|
19
13
|
</a>
|
|
20
14
|
<a href="https://www.npmjs.com/package/lightning-flow-scanner-core">
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
<img src="https://img.shields.io/npm/dt/lightning-flow-scanner-core?label=Downloads%3Cv6&style=flat-square" alt="Downloads <v6">
|
|
16
|
+
</a>
|
|
17
|
+
<a href="https://www.npmjs.com/package/@flow-scanner/lightning-flow-scanner-core">
|
|
18
|
+
<img src="https://img.shields.io/npm/dt/@flow-scanner/lightning-flow-scanner-core?label=Downloads%3Ev6&style=flat-square" alt="Downloads >v6">
|
|
19
|
+
</a>
|
|
23
20
|
</p>
|
|
24
21
|
|
|
25
22
|
<p align="center">
|
|
@@ -36,11 +33,10 @@
|
|
|
36
33
|
|
|
37
34
|
- **[Default Rules](#default-rules)**
|
|
38
35
|
- **[Configuration](#configuration)**
|
|
39
|
-
- [
|
|
40
|
-
- [
|
|
41
|
-
- [
|
|
42
|
-
- [
|
|
43
|
-
- [Rule Mode](#rule-mode)
|
|
36
|
+
- [Configure Severity Levels](#configure-severity-levels)
|
|
37
|
+
- [Overwrite Expressions](#overwrite-expressions)
|
|
38
|
+
- [Define Exceptions](#define-exceptions)
|
|
39
|
+
- [Scan Modes](#scan-modes)
|
|
44
40
|
- **[Installation](#installation)**
|
|
45
41
|
- [Distributions](#distributions)
|
|
46
42
|
- [CICD Templates](#cicd-templates)
|
|
@@ -202,9 +198,9 @@ By default, all default rules are executed. You can customize individual rules a
|
|
|
202
198
|
}
|
|
203
199
|
```
|
|
204
200
|
|
|
205
|
-
###
|
|
201
|
+
### Configure Severity Levels
|
|
206
202
|
|
|
207
|
-
When the severity is not provided it will be `warning` by default. Other available values for severity are `error` and `note`.
|
|
203
|
+
When the severity is not provided it will be `warning` by default. Other available values for severity are `error` and `note`. Configure the severity per rule as shown below:
|
|
208
204
|
|
|
209
205
|
```json
|
|
210
206
|
{
|
|
@@ -219,9 +215,9 @@ When the severity is not provided it will be `warning` by default. Other availab
|
|
|
219
215
|
}
|
|
220
216
|
```
|
|
221
217
|
|
|
222
|
-
###
|
|
218
|
+
### Overwrite Expressions
|
|
223
219
|
|
|
224
|
-
Some rules have
|
|
220
|
+
Some rules have an expression to configure, such as the expression, that will overwrite default values. These can be configured in the same way as severity as shown in the following example.
|
|
225
221
|
|
|
226
222
|
```json
|
|
227
223
|
{
|
|
@@ -236,9 +232,9 @@ Some rules have additional attributes to configure, such as the expression, that
|
|
|
236
232
|
}
|
|
237
233
|
```
|
|
238
234
|
|
|
239
|
-
###
|
|
235
|
+
### Define Exceptions
|
|
240
236
|
|
|
241
|
-
|
|
237
|
+
Defining 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:
|
|
242
238
|
|
|
243
239
|
```json
|
|
244
240
|
{
|
|
@@ -268,7 +264,9 @@ _Example_
|
|
|
268
264
|
}
|
|
269
265
|
```
|
|
270
266
|
|
|
271
|
-
###
|
|
267
|
+
### Scan Modes
|
|
268
|
+
|
|
269
|
+
#### Beta Mode
|
|
272
270
|
|
|
273
271
|
New rules are introduced in Beta mode before being added to the default ruleset. To include current Beta rules, enable the optional betamode parameter in your configuration:
|
|
274
272
|
|
|
@@ -278,7 +276,7 @@ New rules are introduced in Beta mode before being added to the default ruleset.
|
|
|
278
276
|
}
|
|
279
277
|
```
|
|
280
278
|
|
|
281
|
-
|
|
279
|
+
#### Rule Mode
|
|
282
280
|
|
|
283
281
|
By default, Lightning Flow Scanner runs **all** default rules and merges any custom configurations you provide. This means you can override specific rules without having to list every rule to be executed. If instead, you want to run **only** the rules you explicitly specify, use `"ruleMode": "isolated"`:
|
|
284
282
|
```json
|
|
@@ -287,44 +285,28 @@ By default, Lightning Flow Scanner runs **all** default rules and merges any cus
|
|
|
287
285
|
}
|
|
288
286
|
```
|
|
289
287
|
|
|
290
|
-
|
|
291
288
|
## Installation
|
|
292
289
|
|
|
293
290
|
### Distributions
|
|
294
291
|
|
|
295
|
-
| Distribution | Best for | Install
|
|
292
|
+
| Distribution | Best for | Install |
|
|
296
293
|
|----------------------------------------------------------------|-----------------------------------------------|---------------------------------------------------------------------------------------------------------|
|
|
297
|
-
| **[Salesforce CLI Plugin](https://
|
|
298
|
-
| **[VS Code Extension](https://
|
|
294
|
+
| **[Salesforce CLI Plugin](https://www.npmjs.com/package/lightning-flow-scanner)** | Local development, scratch orgs, CI/CD | `sf plugins install lightning-flow-scanner` |
|
|
295
|
+
| **[VS Code Extension](https://open-vsx.org/extension/ForceConfigControl/lightning-flow-scanner-vsx)** | Real-time scanning inside VS Code | `code --install-extension ForceConfigControl.lightning-flow-scanner-vsx` |
|
|
299
296
|
| **[Salesforce App (Managed Package)](https://github.com/Flow-Scanner/lightning-flow-scanner-app)** | Run scans directly inside a Salesforce org | `sf package install --package 04tgK0000007M73QAE` |
|
|
300
|
-
| **[
|
|
297
|
+
| **[GitHub Action](https://github.com/marketplace/actions/lightning-flow-scan)** | Native PR checks | `uses: Flow-Scanner/lightning-flow-scanner@action-v2.6.0` |
|
|
298
|
+
| **[Core Library](https://www.npmjs.com/package/@flow-scanner/lightning-flow-scanner-core)** (Node.js + Browser) | Custom tools, scripts, extensions, web apps | `npm install -g @flow-scanner/lightning-flow-scanner-core` |
|
|
301
299
|
|
|
302
300
|
**Privacy:** Zero user data collected. All processing is client-side. → See our [Security Policy](https://github.com/Flow-Scanner/lightning-flow-scanner?tab=security-ov-file).
|
|
303
301
|
|
|
304
302
|
### CICD Templates
|
|
305
|
-
Ready-to-use CI/CD templates and a **
|
|
303
|
+
Ready-to-use CI/CD templates and a **Copado Plugin**.
|
|
306
304
|
|
|
307
|
-
| Platform |
|
|
305
|
+
| Platform | Type | Link |
|
|
308
306
|
|----------------|-----------------------------------|------|
|
|
309
307
|
| [Azure DevOps](https://github.com/Flow-Scanner/lightning-flow-scanner/blob/main/docs/azure-templates.md) | Full Project Scan | [`azure-pipelines-flow-FullScan.yml`](https://github.com/Flow-Scanner/lightning-flow-scanner/blob/main/docs/templates/azure-devops/azure-pipelines-flow-FullScan.yml) |
|
|
310
308
|
| [Azure DevOps](https://github.com/Flow-Scanner/lightning-flow-scanner/blob/main/docs/azure-templates.md) | Change-Based Scan | [`azure-pipelines-flow-changedFiles.yml`](https://github.com/Flow-Scanner/lightning-flow-scanner/blob/main/docs/templates/azure-devops/azure-pipelines-flow-changedFiles.yml) |
|
|
311
|
-
| **[
|
|
312
|
-
| **[Copado Plugin](https://github.com/Flow-Scanner/lightning-flow-scanner-copado)** | Copado CI/CD pipelines | [Copado Marketplace](https://success.copado.com/s/listing-detail?language=en_US&recordId=a54P7000003G3gBIAS) |
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
GitHub Action Snippet:
|
|
316
|
-
```yaml
|
|
317
|
-
- name: Lightning Flow Scan
|
|
318
|
-
id: flowscanner
|
|
319
|
-
uses: Flow-Scanner/lightning-flow-scanner@main
|
|
320
|
-
|
|
321
|
-
- name: Upload SARIF to Code Scanning
|
|
322
|
-
uses: github/codeql-action/upload-sarif@v3
|
|
323
|
-
with:
|
|
324
|
-
sarif_file: ${{ steps.flowscanner.outputs.sarifPath }}
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
To see the full example, see [`scan-flows.yml`](https://github.com/Flow-Scanner/lightning-flow-scanner/blob/main/docs/templates/github-action/scan-flows.yml).
|
|
309
|
+
| **[Copado Plugin](https://github.com/Flow-Scanner/lightning-flow-scanner-copado)** | Copado Plugin | [Copado Marketplace](https://success.copado.com/s/listing-detail?language=en_US&recordId=a54P7000003G3gBIAS) |
|
|
328
310
|
|
|
329
311
|
## Quick Start
|
|
330
312
|
|
|
@@ -333,19 +315,42 @@ To see the full example, see [`scan-flows.yml`](https://github.com/Flow-Scanner/
|
|
|
333
315
|
Use `lightning-flow-scanner` in the Salesforce CLI:
|
|
334
316
|
|
|
335
317
|
```bash
|
|
336
|
-
sf flow:scan #
|
|
337
|
-
sf flow:
|
|
338
|
-
sf flow
|
|
339
|
-
sf flow
|
|
318
|
+
sf flow:scan # Scan flows in the current directory
|
|
319
|
+
sf flow:scan --sarif > report.sarif # Export scan results as SARIF
|
|
320
|
+
sf flow scan --csv > results.csv # Export scan results as CSV
|
|
321
|
+
sf flow doc > flow-docs.md # Generate flow documentation (Single markdown file)
|
|
322
|
+
sf flow doc --output flow-docs --separate # Generate one Markdown file per flow
|
|
323
|
+
sf flow:fix -d src/force-app # Fix flows in a specific directory
|
|
340
324
|
```
|
|
341
325
|
|
|
326
|
+
For full details, see the [CLI Readme](https://github.com/Flow-Scanner/lightning-flow-scanner/blob/main/packages/cli/README.md).
|
|
327
|
+
|
|
342
328
|
### VS Code Extension
|
|
343
|
-
Use our side bar or the **Command Palette** and type `
|
|
329
|
+
Use our side bar or the **Command Palette** and type `flow scanner` to see the list of all available commands.
|
|
344
330
|
|
|
345
|
-
* `Configure
|
|
331
|
+
* `Configure Scanner` - Set up rules in `.flow-scanner.yml`
|
|
346
332
|
* `Scan Flows` - Analyze a directory or selected flow files
|
|
347
333
|
* `Fix Flows` - Automatically apply available fixes
|
|
348
|
-
* `Flow
|
|
334
|
+
* `Generate Flow Documentation` - Generate flow documentation
|
|
335
|
+
* `Open Scanner Documentation` - Open the rules reference guide
|
|
336
|
+
|
|
337
|
+
For full details, see the [VSX Readme](https://github.com/Flow-Scanner/lightning-flow-scanner/blob/main/packages/vsx/README.md).
|
|
338
|
+
|
|
339
|
+
### GitHub Action
|
|
340
|
+
Add a GitHub workflow file `.github/workflows/scan-flows.yml` to detect issues directly in pull requests:
|
|
341
|
+
|
|
342
|
+
```yaml
|
|
343
|
+
- name: Lightning Flow Scan
|
|
344
|
+
id: flowscanner
|
|
345
|
+
uses: Flow-Scanner/lightning-flow-scanner@action-v2.6.0
|
|
346
|
+
|
|
347
|
+
- name: Upload SARIF to Code Scanning
|
|
348
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
349
|
+
with:
|
|
350
|
+
sarif_file: ${{ steps.flowscanner.outputs.sarifPath }}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
For full details, see the [Action Readme](https://github.com/Flow-Scanner/lightning-flow-scanner/blob/main/packages/action/README.md).
|
|
349
354
|
|
|
350
355
|
### Core Module
|
|
351
356
|
Use `lightning-flow-scanner-core` as a Node.js/browser dependency:
|
|
@@ -355,9 +360,15 @@ Use `lightning-flow-scanner-core` as a Node.js/browser dependency:
|
|
|
355
360
|
import { parse, scan } from "@flow-scanner/lightning-flow-scanner-core";
|
|
356
361
|
parse("flows/*.xml").then(scan);
|
|
357
362
|
|
|
358
|
-
// Get SARIF output
|
|
363
|
+
// Get SARIF output (e.g. for GitHub Code Scanning)
|
|
359
364
|
import { parse, scan, exportSarif } from "@flow-scanner/lightning-flow-scanner-core";
|
|
360
|
-
parse("flows
|
|
365
|
+
parse("flows/**/*.flow-meta.xml").then(scan).then(exportSarif)
|
|
366
|
+
// .then(sarif => fs.writeFile("results.sarif", sarif))
|
|
367
|
+
|
|
368
|
+
// Generate Markdown documentation with Mermaid flow diagrams
|
|
369
|
+
import { parse, exportDiagram } from "@flow-scanner/lightning-flow-scanner-core";
|
|
370
|
+
parse("flows/**/*.flow-meta.xml").then(exportDiagram)
|
|
371
|
+
// .then(md => fs.writeFile("flow-docs.md", md))
|
|
361
372
|
|
|
362
373
|
// Browser Usage (Tooling API)
|
|
363
374
|
const { Flow, scan } = window.lightningflowscanner;
|
|
@@ -370,6 +381,8 @@ const results = scan(
|
|
|
370
381
|
);
|
|
371
382
|
```
|
|
372
383
|
|
|
384
|
+
For more on Programmatic API, types, and advanced usage of `@flow-scanner/lightning-flow-scanner-core`, see the [Core Library Reference](https://github.com/Flow-Scanner/lightning-flow-scanner/blob/main/docs/core-reference.md).
|
|
385
|
+
|
|
373
386
|
## Development
|
|
374
387
|
|
|
375
388
|
> This project optionally uses [Volta](https://volta.sh) to guarantee the exact same Node.js and tool versions for every contributor.
|
package/index.d.ts
CHANGED
|
@@ -19,5 +19,8 @@ import { ParsedFlow } from "./main/models/ParsedFlow";
|
|
|
19
19
|
import { RuleResult } from "./main/models/RuleResult";
|
|
20
20
|
import { ScanResult } from "./main/models/ScanResult";
|
|
21
21
|
import { Violation } from "./main/models/Violation";
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
import { DEFAULT_ICONS, ASCII_ICONS, type NodeIconConfig } from "./main/config/NodeIcons";
|
|
23
|
+
import { DEFAULT_VARIABLE_ICONS, ASCII_VARIABLE_ICONS, type VariableIconConfig } from "./main/config/VariableIcons";
|
|
24
|
+
import { exportDiagram, type DiagramOptions } from "./main/libs/ExportDiagram";
|
|
25
|
+
export { Compiler, exportDetails, exportDiagram, exportSarif, fix, Flow, FlowAttribute, FlowElement, FlowNode, FlowResource, FlowType, FlowVariable, getRules, parse, ParsedFlow, Violation, RuleResult, scan, ScanResult, DEFAULT_ICONS, ASCII_ICONS, DEFAULT_VARIABLE_ICONS, ASCII_VARIABLE_ICONS, };
|
|
26
|
+
export type { FlatViolation, IRuleDefinition, IRulesConfig, NodeIconConfig, DiagramOptions, VariableIconConfig };
|
package/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Updated exports in index.ts
|
|
1
2
|
"use strict";
|
|
2
3
|
Object.defineProperty(exports, "__esModule", {
|
|
3
4
|
value: true
|
|
@@ -9,9 +10,21 @@ function _export(target, all) {
|
|
|
9
10
|
});
|
|
10
11
|
}
|
|
11
12
|
_export(exports, {
|
|
13
|
+
get ASCII_ICONS () {
|
|
14
|
+
return _NodeIcons.ASCII_ICONS;
|
|
15
|
+
},
|
|
16
|
+
get ASCII_VARIABLE_ICONS () {
|
|
17
|
+
return _VariableIcons.ASCII_VARIABLE_ICONS;
|
|
18
|
+
},
|
|
12
19
|
get Compiler () {
|
|
13
20
|
return _Compiler.Compiler;
|
|
14
21
|
},
|
|
22
|
+
get DEFAULT_ICONS () {
|
|
23
|
+
return _NodeIcons.DEFAULT_ICONS;
|
|
24
|
+
},
|
|
25
|
+
get DEFAULT_VARIABLE_ICONS () {
|
|
26
|
+
return _VariableIcons.DEFAULT_VARIABLE_ICONS;
|
|
27
|
+
},
|
|
15
28
|
get Flow () {
|
|
16
29
|
return _Flow.Flow;
|
|
17
30
|
},
|
|
@@ -48,6 +61,9 @@ _export(exports, {
|
|
|
48
61
|
get exportDetails () {
|
|
49
62
|
return _ExportDetails.exportDetails;
|
|
50
63
|
},
|
|
64
|
+
get exportDiagram () {
|
|
65
|
+
return _ExportDiagram.exportDiagram;
|
|
66
|
+
},
|
|
51
67
|
get exportSarif () {
|
|
52
68
|
return _ExportSarif.exportSarif;
|
|
53
69
|
},
|
|
@@ -82,3 +98,6 @@ const _ParsedFlow = require("./main/models/ParsedFlow");
|
|
|
82
98
|
const _RuleResult = require("./main/models/RuleResult");
|
|
83
99
|
const _ScanResult = require("./main/models/ScanResult");
|
|
84
100
|
const _Violation = require("./main/models/Violation");
|
|
101
|
+
const _NodeIcons = require("./main/config/NodeIcons");
|
|
102
|
+
const _VariableIcons = require("./main/config/VariableIcons");
|
|
103
|
+
const _ExportDiagram = require("./main/libs/ExportDiagram");
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon configuration for flow node types.
|
|
3
|
+
* Emoji are safe in UTF-8 encoded source files and will work in all modern builds.
|
|
4
|
+
* If you need ASCII fallback, use FlowNode.setIconConfig(ASCII_ICONS)
|
|
5
|
+
*/
|
|
6
|
+
export interface NodeIconConfig {
|
|
7
|
+
[nodeType: string]: {
|
|
8
|
+
[subtype: string]: string;
|
|
9
|
+
} | {
|
|
10
|
+
default: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Default icons using emoji (recommended for modern environments)
|
|
15
|
+
*/
|
|
16
|
+
export declare const DEFAULT_ICONS: NodeIconConfig;
|
|
17
|
+
/**
|
|
18
|
+
* ASCII fallback icons (for environments without emoji support)
|
|
19
|
+
*/
|
|
20
|
+
export declare const ASCII_ICONS: NodeIconConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Get default icon config (can be overridden at runtime)
|
|
23
|
+
*/
|
|
24
|
+
export declare function getDefaultIconConfig(): NodeIconConfig;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon configuration for flow node types.
|
|
3
|
+
* Emoji are safe in UTF-8 encoded source files and will work in all modern builds.
|
|
4
|
+
* If you need ASCII fallback, use FlowNode.setIconConfig(ASCII_ICONS)
|
|
5
|
+
*/ "use strict";
|
|
6
|
+
Object.defineProperty(exports, "__esModule", {
|
|
7
|
+
value: true
|
|
8
|
+
});
|
|
9
|
+
function _export(target, all) {
|
|
10
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
_export(exports, {
|
|
16
|
+
get ASCII_ICONS () {
|
|
17
|
+
return ASCII_ICONS;
|
|
18
|
+
},
|
|
19
|
+
get DEFAULT_ICONS () {
|
|
20
|
+
return DEFAULT_ICONS;
|
|
21
|
+
},
|
|
22
|
+
get getDefaultIconConfig () {
|
|
23
|
+
return getDefaultIconConfig;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
const DEFAULT_ICONS = {
|
|
27
|
+
actionCalls: {
|
|
28
|
+
apex: '\u2699\uFE0F',
|
|
29
|
+
emailAlert: '\uD83D\uDCE7',
|
|
30
|
+
emailSimple: '\uD83D\uDCE7',
|
|
31
|
+
submit: '\u26A1',
|
|
32
|
+
default: '\u26A1' // HIGH VOLTAGE
|
|
33
|
+
},
|
|
34
|
+
assignments: {
|
|
35
|
+
default: '\uD83D\uDFF0' // 🟰 HEAVY EQUALS SIGN
|
|
36
|
+
},
|
|
37
|
+
collectionProcessors: {
|
|
38
|
+
FilterCollectionProcessor: '\uD83D\uDD3D',
|
|
39
|
+
SortCollectionProcessor: '\uD83D\uDD03',
|
|
40
|
+
default: '\uD83D\uDCE6' // PACKAGE
|
|
41
|
+
},
|
|
42
|
+
customErrors: {
|
|
43
|
+
default: '\uD83D\uDEAB' // PROHIBITED
|
|
44
|
+
},
|
|
45
|
+
decisions: {
|
|
46
|
+
default: '\uD83D\uDD00' // TWISTED ARROWS
|
|
47
|
+
},
|
|
48
|
+
loops: {
|
|
49
|
+
default: '\uD83D\uDD01' // REPEAT BUTTON
|
|
50
|
+
},
|
|
51
|
+
recordCreates: {
|
|
52
|
+
default: '\u2795' // PLUS
|
|
53
|
+
},
|
|
54
|
+
recordDeletes: {
|
|
55
|
+
default: '\uD83D\uDDD1\uFE0F' // WASTEBASKET
|
|
56
|
+
},
|
|
57
|
+
recordLookups: {
|
|
58
|
+
default: '\uD83D\uDD0D' // MAGNIFYING GLASS
|
|
59
|
+
},
|
|
60
|
+
recordUpdates: {
|
|
61
|
+
default: '\uD83D\uDEE0\uFE0F' // HAMMER AND WRENCH
|
|
62
|
+
},
|
|
63
|
+
screens: {
|
|
64
|
+
default: '\uD83D\uDCBB' // LAPTOP
|
|
65
|
+
},
|
|
66
|
+
subflows: {
|
|
67
|
+
default: '\uD83D\uDD17' // LINK
|
|
68
|
+
},
|
|
69
|
+
transforms: {
|
|
70
|
+
default: '\u267B\uFE0F'
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const ASCII_ICONS = {
|
|
74
|
+
actionCalls: {
|
|
75
|
+
apex: '[A]',
|
|
76
|
+
emailAlert: '[E]',
|
|
77
|
+
emailSimple: '[E]',
|
|
78
|
+
submit: '[!]',
|
|
79
|
+
default: '[!]'
|
|
80
|
+
},
|
|
81
|
+
assignments: {
|
|
82
|
+
default: '[=]'
|
|
83
|
+
},
|
|
84
|
+
collectionProcessors: {
|
|
85
|
+
FilterCollectionProcessor: '[F]',
|
|
86
|
+
SortCollectionProcessor: '[S]',
|
|
87
|
+
default: '[C]'
|
|
88
|
+
},
|
|
89
|
+
customErrors: {
|
|
90
|
+
default: '[X]'
|
|
91
|
+
},
|
|
92
|
+
decisions: {
|
|
93
|
+
default: '[?]'
|
|
94
|
+
},
|
|
95
|
+
loops: {
|
|
96
|
+
default: '[L]'
|
|
97
|
+
},
|
|
98
|
+
recordCreates: {
|
|
99
|
+
default: '[+]'
|
|
100
|
+
},
|
|
101
|
+
recordDeletes: {
|
|
102
|
+
default: '[-]'
|
|
103
|
+
},
|
|
104
|
+
recordLookups: {
|
|
105
|
+
default: '[S]'
|
|
106
|
+
},
|
|
107
|
+
recordUpdates: {
|
|
108
|
+
default: '[U]'
|
|
109
|
+
},
|
|
110
|
+
screens: {
|
|
111
|
+
default: '[#]'
|
|
112
|
+
},
|
|
113
|
+
subflows: {
|
|
114
|
+
default: '[>]'
|
|
115
|
+
},
|
|
116
|
+
transforms: {
|
|
117
|
+
default: '[T]'
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
function getDefaultIconConfig() {
|
|
121
|
+
return DEFAULT_ICONS;
|
|
122
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon configuration for flow variable types.
|
|
3
|
+
* Includes icons for variable subtypes and boolean states.
|
|
4
|
+
*/
|
|
5
|
+
export interface VariableIconConfig {
|
|
6
|
+
subtypes: {
|
|
7
|
+
[subtype: string]: string;
|
|
8
|
+
};
|
|
9
|
+
boolean: {
|
|
10
|
+
true: string;
|
|
11
|
+
false: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Default icons using emoji (recommended for modern environments)
|
|
16
|
+
*/
|
|
17
|
+
export declare const DEFAULT_VARIABLE_ICONS: VariableIconConfig;
|
|
18
|
+
/**
|
|
19
|
+
* ASCII fallback icons (for environments without emoji support)
|
|
20
|
+
*/
|
|
21
|
+
export declare const ASCII_VARIABLE_ICONS: VariableIconConfig;
|
|
22
|
+
/**
|
|
23
|
+
* Get default variable icon config
|
|
24
|
+
*/
|
|
25
|
+
export declare function getDefaultVariableIconConfig(): VariableIconConfig;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon configuration for flow variable types.
|
|
3
|
+
* Includes icons for variable subtypes and boolean states.
|
|
4
|
+
*/ "use strict";
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
function _export(target, all) {
|
|
9
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
_export(exports, {
|
|
15
|
+
get ASCII_VARIABLE_ICONS () {
|
|
16
|
+
return ASCII_VARIABLE_ICONS;
|
|
17
|
+
},
|
|
18
|
+
get DEFAULT_VARIABLE_ICONS () {
|
|
19
|
+
return DEFAULT_VARIABLE_ICONS;
|
|
20
|
+
},
|
|
21
|
+
get getDefaultVariableIconConfig () {
|
|
22
|
+
return getDefaultVariableIconConfig;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const DEFAULT_VARIABLE_ICONS = {
|
|
26
|
+
subtypes: {
|
|
27
|
+
variables: '\uD83D\uDCCA',
|
|
28
|
+
constants: '\uD83D\uDD12',
|
|
29
|
+
formulas: '\uD83E\uDDEE',
|
|
30
|
+
choices: '\uD83D\uDCCB',
|
|
31
|
+
dynamicChoiceSets: '\uD83D\uDD04'
|
|
32
|
+
},
|
|
33
|
+
boolean: {
|
|
34
|
+
true: '\u2705',
|
|
35
|
+
false: '\u2B1C'
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const ASCII_VARIABLE_ICONS = {
|
|
39
|
+
subtypes: {
|
|
40
|
+
variables: '[V]',
|
|
41
|
+
constants: '[C]',
|
|
42
|
+
formulas: '[F]',
|
|
43
|
+
choices: '[CH]',
|
|
44
|
+
dynamicChoiceSets: '[D]'
|
|
45
|
+
},
|
|
46
|
+
boolean: {
|
|
47
|
+
true: '[X]',
|
|
48
|
+
false: '[ ]'
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
function getDefaultVariableIconConfig() {
|
|
52
|
+
return DEFAULT_VARIABLE_ICONS;
|
|
53
|
+
}
|
package/main/libs/Compiler.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { Flow } from "../models/Flow";
|
|
2
1
|
import { FlowNode } from "../models/FlowNode";
|
|
3
2
|
export declare class Compiler {
|
|
4
3
|
visitedElements: Set<string>;
|
|
5
4
|
constructor();
|
|
6
|
-
traverseFlow(
|
|
5
|
+
traverseFlow(startElementName: string, visitCallback: (element: FlowNode) => void, nodeMap: Map<string, FlowNode>, allConnectors: Map<string, Set<string>>, endElementName?: string): void;
|
|
7
6
|
private findNextElements;
|
|
8
7
|
}
|
package/main/libs/Compiler.js
CHANGED
|
@@ -22,7 +22,7 @@ function _define_property(obj, key, value) {
|
|
|
22
22
|
return obj;
|
|
23
23
|
}
|
|
24
24
|
let Compiler = class Compiler {
|
|
25
|
-
traverseFlow(
|
|
25
|
+
traverseFlow(startElementName, visitCallback, nodeMap, allConnectors, endElementName) {
|
|
26
26
|
// Iterative Deepening Depth-First Search (IDDFS)
|
|
27
27
|
let elementsToVisit = [
|
|
28
28
|
startElementName
|
|
@@ -31,12 +31,11 @@ let Compiler = class Compiler {
|
|
|
31
31
|
const nextElements = [];
|
|
32
32
|
for (const elementName of elementsToVisit){
|
|
33
33
|
if (!this.visitedElements.has(elementName)) {
|
|
34
|
-
|
|
35
|
-
const currentElement = (_flow_elements = flow.elements) === null || _flow_elements === void 0 ? void 0 : _flow_elements.find((element)=>element.name === elementName);
|
|
34
|
+
const currentElement = nodeMap.get(elementName);
|
|
36
35
|
if (currentElement) {
|
|
37
36
|
visitCallback(currentElement);
|
|
38
37
|
this.visitedElements.add(elementName);
|
|
39
|
-
nextElements.push(...this.findNextElements(
|
|
38
|
+
nextElements.push(...this.findNextElements(elementName, allConnectors, nodeMap, endElementName));
|
|
40
39
|
}
|
|
41
40
|
}
|
|
42
41
|
}
|
|
@@ -46,19 +45,14 @@ let Compiler = class Compiler {
|
|
|
46
45
|
elementsToVisit = nextElements;
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
|
-
findNextElements(
|
|
48
|
+
findNextElements(elementName, allConnectors, nodeMap, endElementName) {
|
|
50
49
|
const nextElements = [];
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const targetReference = (_connector_connectorTargetReference_targetReference = connector === null || connector === void 0 ? void 0 : (_connector_connectorTargetReference = connector.connectorTargetReference) === null || _connector_connectorTargetReference === void 0 ? void 0 : _connector_connectorTargetReference.targetReference) !== null && _connector_connectorTargetReference_targetReference !== void 0 ? _connector_connectorTargetReference_targetReference : connector.reference;
|
|
58
|
-
// Check if the reference exists in the flow elements
|
|
59
|
-
const nextElement = (_flow_elements = flow.elements) === null || _flow_elements === void 0 ? void 0 : _flow_elements.find((element)=>element.metaType === "node" && element.name === targetReference);
|
|
60
|
-
if (nextElement && nextElement.metaType === "node" && nextElement.name !== endElementName) {
|
|
61
|
-
nextElements.push(nextElement.name);
|
|
50
|
+
const targets = allConnectors.get(elementName);
|
|
51
|
+
if (targets) {
|
|
52
|
+
for (const targetReference of targets){
|
|
53
|
+
if (targetReference !== endElementName && nodeMap.has(targetReference)) {
|
|
54
|
+
nextElements.push(targetReference);
|
|
55
|
+
}
|
|
62
56
|
}
|
|
63
57
|
}
|
|
64
58
|
return nextElements;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ParsedFlow } from "../models/ParsedFlow";
|
|
2
|
+
export interface DiagramOptions {
|
|
3
|
+
includeDetails?: boolean;
|
|
4
|
+
includeMarkdownDocs?: boolean;
|
|
5
|
+
collapsedDetails?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Generate Markdown documentation for parsed flows, including Mermaid diagrams for valid flows.
|
|
9
|
+
*
|
|
10
|
+
* This function can be chained after parse() to generate documentation.
|
|
11
|
+
* It filters out errored parses and only documents valid flows.
|
|
12
|
+
*
|
|
13
|
+
* @param parsedFlows Array of ParsedFlow objects from parse()
|
|
14
|
+
* @param options Visualization options for Mermaid diagrams
|
|
15
|
+
*
|
|
16
|
+
* @returns Markdown string with documentation
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // Node.js usage
|
|
21
|
+
* import { parse, exportFlowMarkdown } from "@flow-scanner/lightning-flow-scanner-core";
|
|
22
|
+
* import fs from "fs/promises";
|
|
23
|
+
*
|
|
24
|
+
* const parsed = await parse(["flows/*.xml"]);
|
|
25
|
+
* const md = exportFlowMarkdown(parsed, {
|
|
26
|
+
* includeDetails: true,
|
|
27
|
+
* includeMarkdownDocs: true,
|
|
28
|
+
* collapsedDetails: true
|
|
29
|
+
* });
|
|
30
|
+
* await fs.writeFile("flow-doc.md", md);
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* // Chained (async/await)
|
|
36
|
+
* const md = await parse(["flows/*.xml"]).then(parsed =>
|
|
37
|
+
* exportFlowMarkdown(parsed, { includeDetails: true })
|
|
38
|
+
* );
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function exportDiagram(parsedFlows: ParsedFlow[], options?: DiagramOptions): string;
|