@flow-scanner/lightning-flow-scanner-core 6.0.4 → 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 CHANGED
@@ -4,18 +4,23 @@
4
4
  </a>
5
5
  </p>
6
6
 
7
- <p align="center"><i>A plug-and-play engine for Flow metadata in Node.js & browsers—with 20+ rules to catch unsafe contexts, loop queries, hardcoded IDs, and more.</i></p>
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
- - [Default Rules](#default-rules)
10
- - [Configuration](#configuration)
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
- - [Installation](#installation)
17
- - [Core Functions](#core-functions)
18
- - [Development](#development)
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
- ### Installation
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
- The Lightning Flow Scanner Core can be used as a dependency in Node.js and browser environments, or used as a standalone UMD module. To install:
236
+ ### Examples
232
237
 
233
- ```bash
234
- npm install @flow-scanner/lightning-flow-scanner-core
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
- ### Core Functions
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
- _Parses metadata from selected Flow files._
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 rules against parsed flows and returns scan results._
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
- _Attempts to apply automatic fixes where available._
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
+ [![npm version](https://img.shields.io/npm/v/@flow-scanner/lightning-flow-scanner-core?label=npm)](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,2 @@
1
+ import { ScanResult } from "../models/ScanResult";
2
+ export declare function exportSarif(results: ScanResult[]): string;
@@ -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
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.0.4",
4
+ "version": "6.1.0",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
7
  "engines": {