@flow-scanner/lightning-flow-scanner-core 6.0.3 → 6.1.0
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 +52 -16
- package/index.d.ts +2 -1
- package/index.js +4 -0
- package/main/libs/ExportSarif.d.ts +2 -0
- package/main/libs/ExportSarif.js +136 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,18 +4,23 @@
|
|
|
4
4
|
</a>
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
|
-
<p align="center"><i>
|
|
7
|
+
<p align="center"><i>UMD-compatible Flow metadata engine for Node.js & browsers—20+ rules to catch common issues.</i></p>
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Table of contens
|
|
12
|
+
|
|
13
|
+
- **[Default Rules](#default-rules)**
|
|
14
|
+
- **[Configuration](#configuration)**
|
|
11
15
|
- [Defining Severity Levels](#defining-severity-levels)
|
|
12
16
|
- [Configuring Expressions](#configuring-expressions)
|
|
13
17
|
- [Specifying Exceptions](#specifying-exceptions)
|
|
14
18
|
- [Include Beta Rules](#include-beta-rules)
|
|
15
|
-
- [Usage](#Usage)
|
|
16
|
-
- [
|
|
17
|
-
- [
|
|
18
|
-
- [
|
|
19
|
+
- **[Usage](#Usage)**
|
|
20
|
+
- [Examples](#examples)
|
|
21
|
+
- [Functions](#core-functions)
|
|
22
|
+
- **[Installation](#installation)**
|
|
23
|
+
- **[Development](#development)**
|
|
19
24
|
|
|
20
25
|
---
|
|
21
26
|
|
|
@@ -24,7 +29,7 @@
|
|
|
24
29
|
<p>📌 <strong>Tip:</strong> To link directly to a specific rule, use the full GitHub anchor link format. Example:</p>
|
|
25
30
|
<p><em><a href="https://github.com/Flow-Scanner/lightning-flow-scanner-core#unsafe-running-context">https://github.com/Flow-Scanner/lightning-flow-scanner-core#unsafe-running-context</a></em></i></p>
|
|
26
31
|
|
|
27
|
-
### Action Calls In Loop
|
|
32
|
+
### Action Calls In Loop(Beta)
|
|
28
33
|
|
|
29
34
|
_[ActionCallsInLoop](https://github.com/Flow-Scanner/lightning-flow-scanner-core/tree/main/src/main/rules/ActionCallsInLoop.ts)_ - 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.
|
|
30
35
|
|
|
@@ -226,15 +231,28 @@ New rules are introduced in Beta mode before being added to the default ruleset.
|
|
|
226
231
|
|
|
227
232
|
## Usage
|
|
228
233
|
|
|
229
|
-
|
|
234
|
+
The Lightning Flow Scanner Core can be used as a dependency in Node.js and browser environments, or used as a standalone UMD module.
|
|
230
235
|
|
|
231
|
-
|
|
236
|
+
### Examples
|
|
232
237
|
|
|
233
|
-
```
|
|
234
|
-
|
|
238
|
+
```js
|
|
239
|
+
// Basic
|
|
240
|
+
import { parse, scan } from "@flow-scanner/lightning-flow-scanner-core";
|
|
241
|
+
parse("flows/*.xml").then(scan);
|
|
242
|
+
|
|
243
|
+
// Apply fixes automatically
|
|
244
|
+
import { parse, scan, fix } from "@flow-scanner/lightning-flow-scanner-core";
|
|
245
|
+
parse("flows/*.xml").then(scan).then(fix);
|
|
246
|
+
|
|
247
|
+
// Get SARIF output
|
|
248
|
+
import { parse, scan, exportSarif } from "@flow-scanner/lightning-flow-scanner-core";
|
|
249
|
+
parse("flows/*.xml")
|
|
250
|
+
.then(scan)
|
|
251
|
+
.then(exportSarif)
|
|
252
|
+
.then((sarif) => save("results.sarif", sarif));
|
|
235
253
|
```
|
|
236
254
|
|
|
237
|
-
###
|
|
255
|
+
### Functions
|
|
238
256
|
|
|
239
257
|
#### [`getRules(ruleNames?: string[]): IRuleDefinition[]`](https://github.com/Flow-Scanner/lightning-flow-scanner-core/tree/main/src/main/libs/GetRuleDefinitions.ts)
|
|
240
258
|
|
|
@@ -242,15 +260,33 @@ _Retrieves rule definitions used in the scanner._
|
|
|
242
260
|
|
|
243
261
|
#### [`parse(selectedUris: any): Promise<ParsedFlow[]>`](https://github.com/Flow-Scanner/lightning-flow-scanner-core/tree/main/src/main/libs/ParseFlows.ts)
|
|
244
262
|
|
|
245
|
-
|
|
263
|
+
_Loads Flow XML files into in-memory models._
|
|
246
264
|
|
|
247
265
|
#### [`scan(parsedFlows: ParsedFlow[], ruleOptions?: IRulesConfig): ScanResult[]`](https://github.com/Flow-Scanner/lightning-flow-scanner-core/tree/main/src/main/libs/ScanFlows.ts)
|
|
248
266
|
|
|
249
|
-
_Runs
|
|
267
|
+
_Runs all enabled rules and returns detailed violations._
|
|
250
268
|
|
|
251
269
|
#### [`fix(results: ScanResult[]): ScanResult[]`](https://github.com/Flow-Scanner/lightning-flow-scanner-core/tree/main/src/main/libs/FixFlows.ts)
|
|
252
270
|
|
|
253
|
-
|
|
271
|
+
_Automatically applies available fixes(removing variables and unconnected elements)._
|
|
272
|
+
|
|
273
|
+
#### [`exportSarif(results: ScanResult[]): string`](https://github.com/Flow-Scanner/lightning-flow-scanner-core/tree/main/src/main/libs/ExportSarif.ts)
|
|
274
|
+
|
|
275
|
+
_Generates SARIF output with paths and exact line numbers._
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Installation
|
|
280
|
+
|
|
281
|
+
`lightning-flow-scanner-core` is published to **npm** only.
|
|
282
|
+
|
|
283
|
+
[](https://www.npmjs.com/package/@flow-scanner/lightning-flow-scanner-core)
|
|
284
|
+
|
|
285
|
+
**To install with npm:**
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
npm install @flow-scanner/lightning-flow-scanner-core
|
|
289
|
+
```
|
|
254
290
|
|
|
255
291
|
---
|
|
256
292
|
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { IRuleDefinition } from "./main/interfaces/IRuleDefinition";
|
|
2
2
|
import type { IRulesConfig } from "./main/interfaces/IRulesConfig";
|
|
3
3
|
import { Compiler } from "./main/libs/Compiler";
|
|
4
|
+
import { exportSarif } from "./main/libs/ExportSarif";
|
|
4
5
|
import { fix } from "./main/libs/FixFlows";
|
|
5
6
|
import { getBetaRules, getRules } from "./main/libs/GetRuleDefinitions";
|
|
6
7
|
import { parse } from "./main/libs/ParseFlows";
|
|
@@ -17,5 +18,5 @@ import { ParsedFlow } from "./main/models/ParsedFlow";
|
|
|
17
18
|
import { ResultDetails } from "./main/models/ResultDetails";
|
|
18
19
|
import { RuleResult } from "./main/models/RuleResult";
|
|
19
20
|
import { ScanResult } from "./main/models/ScanResult";
|
|
20
|
-
export { AdvancedRule, Compiler, fix, Flow, FlowAttribute, FlowElement, FlowNode, FlowResource, FlowType, FlowVariable, getBetaRules, getRules, parse, ParsedFlow, ResultDetails, RuleResult, scan, ScanResult, };
|
|
21
|
+
export { AdvancedRule, Compiler, exportSarif, fix, Flow, FlowAttribute, FlowElement, FlowNode, FlowResource, FlowType, FlowVariable, getBetaRules, getRules, parse, ParsedFlow, ResultDetails, RuleResult, scan, ScanResult, };
|
|
21
22
|
export type { IRuleDefinition, IRulesConfig };
|
package/index.js
CHANGED
|
@@ -48,6 +48,9 @@ _export(exports, {
|
|
|
48
48
|
get ScanResult () {
|
|
49
49
|
return _ScanResult.ScanResult;
|
|
50
50
|
},
|
|
51
|
+
get exportSarif () {
|
|
52
|
+
return _ExportSarif.exportSarif;
|
|
53
|
+
},
|
|
51
54
|
get fix () {
|
|
52
55
|
return _FixFlows.fix;
|
|
53
56
|
},
|
|
@@ -65,6 +68,7 @@ _export(exports, {
|
|
|
65
68
|
}
|
|
66
69
|
});
|
|
67
70
|
const _Compiler = require("./main/libs/Compiler");
|
|
71
|
+
const _ExportSarif = require("./main/libs/ExportSarif");
|
|
68
72
|
const _FixFlows = require("./main/libs/FixFlows");
|
|
69
73
|
const _GetRuleDefinitions = require("./main/libs/GetRuleDefinitions");
|
|
70
74
|
const _ParseFlows = require("./main/libs/ParseFlows");
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// src/main/libs/exportSarif.ts
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "exportSarif", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function() {
|
|
9
|
+
return exportSarif;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
function _define_property(obj, key, value) {
|
|
13
|
+
if (key in obj) {
|
|
14
|
+
Object.defineProperty(obj, key, {
|
|
15
|
+
value: value,
|
|
16
|
+
enumerable: true,
|
|
17
|
+
configurable: true,
|
|
18
|
+
writable: true
|
|
19
|
+
});
|
|
20
|
+
} else {
|
|
21
|
+
obj[key] = value;
|
|
22
|
+
}
|
|
23
|
+
return obj;
|
|
24
|
+
}
|
|
25
|
+
function _object_spread(target) {
|
|
26
|
+
for(var i = 1; i < arguments.length; i++){
|
|
27
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
28
|
+
var ownKeys = Object.keys(source);
|
|
29
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
30
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
31
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
ownKeys.forEach(function(key) {
|
|
35
|
+
_define_property(target, key, source[key]);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return target;
|
|
39
|
+
}
|
|
40
|
+
function exportSarif(results) {
|
|
41
|
+
const runs = results.map((result)=>{
|
|
42
|
+
const flow = result.flow;
|
|
43
|
+
const uri = getUri(flow);
|
|
44
|
+
return {
|
|
45
|
+
artifacts: [
|
|
46
|
+
{
|
|
47
|
+
location: {
|
|
48
|
+
uri
|
|
49
|
+
},
|
|
50
|
+
sourceLanguage: "xml"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
results: result.ruleResults.filter((r)=>r.occurs).flatMap((r)=>r.details.map((d)=>({
|
|
54
|
+
level: mapSeverity(r.severity),
|
|
55
|
+
locations: [
|
|
56
|
+
{
|
|
57
|
+
physicalLocation: {
|
|
58
|
+
artifactLocation: {
|
|
59
|
+
index: 0,
|
|
60
|
+
uri
|
|
61
|
+
},
|
|
62
|
+
region: mapRegion(d, result.flow.toXMLString() || "")
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
message: {
|
|
67
|
+
text: r.errorMessage || `${r.ruleName} in ${d.name}`
|
|
68
|
+
},
|
|
69
|
+
properties: _object_spread({
|
|
70
|
+
element: d.name,
|
|
71
|
+
flow: flow.name,
|
|
72
|
+
type: d.type
|
|
73
|
+
}, d.details),
|
|
74
|
+
ruleId: r.ruleName
|
|
75
|
+
}))),
|
|
76
|
+
tool: {
|
|
77
|
+
driver: {
|
|
78
|
+
informationUri: "https://github.com/Flow-Scanner/lightning-flow-scanner-core",
|
|
79
|
+
name: "Lightning Flow Scanner",
|
|
80
|
+
rules: result.ruleResults.filter((r)=>r.occurs).map((r)=>({
|
|
81
|
+
defaultConfiguration: {
|
|
82
|
+
level: mapSeverity(r.severity)
|
|
83
|
+
},
|
|
84
|
+
fullDescription: {
|
|
85
|
+
text: r.ruleDefinition.description || ""
|
|
86
|
+
},
|
|
87
|
+
id: r.ruleName,
|
|
88
|
+
shortDescription: {
|
|
89
|
+
text: r.ruleDefinition.description || r.ruleName
|
|
90
|
+
}
|
|
91
|
+
})),
|
|
92
|
+
version: "1.0.0"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
return JSON.stringify({
|
|
98
|
+
$schema: "https://json.schemastore.org/sarif-2.1.0.json",
|
|
99
|
+
runs,
|
|
100
|
+
version: "2.1.0"
|
|
101
|
+
}, null, 2);
|
|
102
|
+
}
|
|
103
|
+
function getUri(flow) {
|
|
104
|
+
return flow.fsPath ? flow.fsPath.replace(/\\/g, "/") : `flows/${flow.name}.flow-meta.xml`;
|
|
105
|
+
}
|
|
106
|
+
function mapRegion(detail, rawXml = "") {
|
|
107
|
+
if (!rawXml) return {
|
|
108
|
+
startLine: 1,
|
|
109
|
+
startColumn: 1
|
|
110
|
+
};
|
|
111
|
+
const lines = rawXml.split("\n");
|
|
112
|
+
const name = detail.name;
|
|
113
|
+
for(let i = 0; i < lines.length; i++){
|
|
114
|
+
if (lines[i].includes(`<name>${name}</name>`)) {
|
|
115
|
+
return {
|
|
116
|
+
startLine: i + 1,
|
|
117
|
+
startColumn: lines[i].indexOf(name) + 1
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
startLine: 1,
|
|
123
|
+
startColumn: 1
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function mapSeverity(sev) {
|
|
127
|
+
switch(sev === null || sev === void 0 ? void 0 : sev.toLowerCase()){
|
|
128
|
+
case "info":
|
|
129
|
+
case "note":
|
|
130
|
+
return "note";
|
|
131
|
+
case "warning":
|
|
132
|
+
return "warning";
|
|
133
|
+
default:
|
|
134
|
+
return "error";
|
|
135
|
+
}
|
|
136
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flow-scanner/lightning-flow-scanner-core",
|
|
3
|
-
"description": "A purpose-built engine for Flow metadata in Node.js
|
|
4
|
-
"version": "6.0
|
|
3
|
+
"description": "A lightweight, purpose-built engine for parsing and analyzing Salesforce Flow metadata in Node.js or browser environments. Scan, validate, and optimize Flow automations for security risks, best practices, governor limits, and performance bottlenecks.",
|
|
4
|
+
"version": "6.1.0",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"engines": {
|