@flow-scanner/lightning-flow-scanner-core 6.5.1 → 6.6.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/CONTRIBUTING.md +31 -31
- package/LICENSE.md +21 -21
- package/README.md +428 -409
- package/SECURITY.md +37 -23
- package/index.d.ts +2 -2
- package/index.js +0 -3
- package/main/libs/DynamicRule.d.ts +1 -1
- package/main/libs/DynamicRule.js +2 -2
- package/main/libs/GetRuleDefinitions.d.ts +0 -1
- package/main/libs/GetRuleDefinitions.js +8 -18
- package/main/libs/ScanFlows.js +2 -2
- package/main/models/Flow.js +8 -8
- package/main/models/FlowType.js +13 -13
- package/main/models/RuleCommon.js +4 -4
- package/main/models/RuleInfo.js +26 -26
- package/main/rules/MissingMetadataDescription.d.ts +7 -0
- package/main/rules/MissingMetadataDescription.js +77 -0
- package/main/store/DefaultRuleStore.js +4 -1
- package/package.json +9 -53
- /package/assets/media/{bannerslim.png → banner.png} +0 -0
package/SECURITY.md
CHANGED
|
@@ -1,23 +1,37 @@
|
|
|
1
|
-
# Security Policy for Lightning Flow Scanner
|
|
2
|
-
|
|
3
|
-
## Security Practices
|
|
4
|
-
|
|
5
|
-
- Code is open-source and peer-reviewed by the community.
|
|
6
|
-
- Vulnerabilities can be reported privately via [GitHub vulnerability reporting](https://github.com/Flow-Scanner/lightning-flow-scanner
|
|
7
|
-
- All changes are scanned with [Snyk](https://github.com/snyk/cli) prior to publication.
|
|
8
|
-
- Releases are published to npm using **GitHub Actions Trusted Publishing (OIDC)**.
|
|
9
|
-
- Tags (`v*`) trigger automated `npm publish`, providing a full audit trail.
|
|
10
|
-
|
|
11
|
-
## Data Handling
|
|
12
|
-
|
|
13
|
-
This tool collects zero user data. No credentials, PII, payment info, health data, or user content is ever stored, transmitted, or shared. All analysis runs 100% client-side with no network calls to external services.
|
|
14
|
-
|
|
15
|
-
We temporarily use metadata (e.g., Flow metadata, timestamps) in-memory only for real-time functionality during your session. This data is never stored, logged, or transmitted and is discarded immediately when the session ends.
|
|
16
|
-
|
|
17
|
-
## Dependencies
|
|
18
|
-
|
|
19
|
-
We actively track and maintain an up-to-date inventory of all third-party dependencies to ensure security and compatibility. Our dependencies include:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
|
1
|
+
# Security Policy for Lightning Flow Scanner
|
|
2
|
+
|
|
3
|
+
## Security Practices
|
|
4
|
+
|
|
5
|
+
- Code is open-source and peer-reviewed by the community.
|
|
6
|
+
- Vulnerabilities can be reported privately via [GitHub vulnerability reporting](https://github.com/Flow-Scanner/lightning-flow-scanner/security).
|
|
7
|
+
- All changes are scanned with [Snyk](https://github.com/snyk/cli) prior to publication.
|
|
8
|
+
- Releases are published to npm using **GitHub Actions Trusted Publishing (OIDC)**.
|
|
9
|
+
- Tags (`v*`) trigger automated `npm publish`, providing a full audit trail.
|
|
10
|
+
|
|
11
|
+
## Data Handling
|
|
12
|
+
|
|
13
|
+
This tool collects zero user data. No credentials, PII, payment info, health data, or user content is ever stored, transmitted, or shared. All analysis runs 100% client-side with no network calls to external services.
|
|
14
|
+
|
|
15
|
+
We temporarily use metadata (e.g., Flow metadata, timestamps) in-memory only for real-time functionality during your session. This data is never stored, logged, or transmitted and is discarded immediately when the session ends.
|
|
16
|
+
|
|
17
|
+
## Dependencies
|
|
18
|
+
|
|
19
|
+
We actively track and maintain an up-to-date inventory of all third-party dependencies to ensure security and compatibility. Our dependencies include:
|
|
20
|
+
|
|
21
|
+
### Core
|
|
22
|
+
|
|
23
|
+
| Package | License | Purpose |
|
|
24
|
+
| ----------------- | --------------------------------------------------------------------------------- | ---------------------------------------------- |
|
|
25
|
+
| `fast-xml-parser` | [MIT](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/LICENSE) | Validate XML, Parse XML and Build XML rapidly. |
|
|
26
|
+
|
|
27
|
+
### CLI
|
|
28
|
+
|
|
29
|
+
| Package | License | Purpose |
|
|
30
|
+
| ----------------------------------- | ------- | ------- |
|
|
31
|
+
| `@oclif/core` | [MIT](https://github.com/oclif/oclif/blob/main/LICENSE) | CLI framework core utilities |
|
|
32
|
+
| `@salesforce/core` | [BSD-3-Clause](https://github.com/salesforce/core/blob/main/LICENSE) | Salesforce core library for CLI plugins |
|
|
33
|
+
| `@salesforce/sf-plugins-core` | [BSD-3-Clause](https://github.com/salesforce/sf-plugins-core/blob/main/LICENSE) | Base library for Salesforce CLI plugins |
|
|
34
|
+
| `chalk` | [MIT](https://github.com/chalk/chalk/blob/main/license) | Terminal string styling (colors) |
|
|
35
|
+
| `cosmiconfig` | [MIT](https://github.com/davidtheclark/cosmiconfig/blob/main/LICENSE) | Config file loader for JavaScript/Node |
|
|
36
|
+
| `glob` | [MIT](https://github.com/isaacs/node-glob/blob/master/LICENSE) | File pattern matching |
|
|
37
|
+
| `lightning-flow-scanner-core` | [MIT](https://github.com/Flow-Scanner/lightning-flow-scanner-core/blob/main/LICENSE.md) | Salesforce Flow scanning utilities |
|
package/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { Compiler } from "./main/libs/Compiler";
|
|
|
5
5
|
import { exportDetails } from "./main/libs/exportAsDetails";
|
|
6
6
|
import { exportSarif } from "./main/libs/exportAsSarif";
|
|
7
7
|
import { fix } from "./main/libs/FixFlows";
|
|
8
|
-
import {
|
|
8
|
+
import { getRules } from "./main/libs/GetRuleDefinitions";
|
|
9
9
|
import { parse } from "./main/libs/ParseFlows";
|
|
10
10
|
import { scan } from "./main/libs/ScanFlows";
|
|
11
11
|
import { Flow } from "./main/models/Flow";
|
|
@@ -19,5 +19,5 @@ 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
|
-
export { Compiler, exportDetails, exportSarif, fix, Flow, FlowAttribute, FlowElement, FlowNode, FlowResource, FlowType, FlowVariable,
|
|
22
|
+
export { Compiler, exportDetails, exportSarif, fix, Flow, FlowAttribute, FlowElement, FlowNode, FlowResource, FlowType, FlowVariable, getRules, parse, ParsedFlow, Violation, RuleResult, scan, ScanResult, };
|
|
23
23
|
export type { FlatViolation, IRuleDefinition, IRulesConfig };
|
package/index.js
CHANGED
package/main/libs/DynamicRule.js
CHANGED
|
@@ -10,8 +10,8 @@ Object.defineProperty(exports, "DynamicRule", {
|
|
|
10
10
|
});
|
|
11
11
|
const _DefaultRuleStore = require("../store/DefaultRuleStore");
|
|
12
12
|
let DynamicRule = class DynamicRule {
|
|
13
|
-
constructor(className){
|
|
14
|
-
if (
|
|
13
|
+
constructor(className, betaMode = false){
|
|
14
|
+
if (betaMode && _DefaultRuleStore.BetaRuleStore.hasOwnProperty(className)) {
|
|
15
15
|
return new _DefaultRuleStore.BetaRuleStore[className]();
|
|
16
16
|
}
|
|
17
17
|
return new _DefaultRuleStore.DefaultRuleStore[className]();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { IRuleDefinition } from "../interfaces/IRuleDefinition";
|
|
2
2
|
import { IRulesConfig } from "../interfaces/IRulesConfig";
|
|
3
|
-
export declare function getBetaRules(): IRuleDefinition[];
|
|
4
3
|
export declare function GetRuleDefinitions(ruleConfig?: Map<string, unknown>, options?: IRulesConfig): IRuleDefinition[];
|
|
5
4
|
export declare function getRules(ruleNames?: string[], options?: IRulesConfig): IRuleDefinition[];
|
|
@@ -12,18 +12,12 @@ _export(exports, {
|
|
|
12
12
|
get GetRuleDefinitions () {
|
|
13
13
|
return GetRuleDefinitions;
|
|
14
14
|
},
|
|
15
|
-
get getBetaRules () {
|
|
16
|
-
return getBetaRules;
|
|
17
|
-
},
|
|
18
15
|
get getRules () {
|
|
19
16
|
return getRules;
|
|
20
17
|
}
|
|
21
18
|
});
|
|
22
19
|
const _DefaultRuleStore = require("../store/DefaultRuleStore");
|
|
23
20
|
const _DynamicRule = require("./DynamicRule");
|
|
24
|
-
function getBetaRules() {
|
|
25
|
-
return getBetaDefinition();
|
|
26
|
-
}
|
|
27
21
|
function GetRuleDefinitions(ruleConfig, options) {
|
|
28
22
|
const selectedRules = [];
|
|
29
23
|
const includeBeta = (options === null || options === void 0 ? void 0 : options.betaMode) === true || (options === null || options === void 0 ? void 0 : options.betamode) === true;
|
|
@@ -36,10 +30,9 @@ function GetRuleDefinitions(ruleConfig, options) {
|
|
|
36
30
|
if (configuredSeverity && (configuredSeverity === "error" || configuredSeverity === "warning" || configuredSeverity === "note")) {
|
|
37
31
|
severity = configuredSeverity;
|
|
38
32
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
33
|
+
// Pass betaMode to DynamicRule
|
|
34
|
+
const matchedRule = new _DynamicRule.DynamicRule(ruleName, includeBeta);
|
|
35
|
+
if (configuredSeverity) matchedRule.severity = severity;
|
|
43
36
|
selectedRules.push(matchedRule);
|
|
44
37
|
} catch (error) {
|
|
45
38
|
console.log(error.message);
|
|
@@ -48,14 +41,15 @@ function GetRuleDefinitions(ruleConfig, options) {
|
|
|
48
41
|
} else {
|
|
49
42
|
// Load all defaults
|
|
50
43
|
for(const rule in _DefaultRuleStore.DefaultRuleStore){
|
|
51
|
-
const matchedRule = new _DynamicRule.DynamicRule(rule);
|
|
44
|
+
const matchedRule = new _DynamicRule.DynamicRule(rule, includeBeta);
|
|
52
45
|
selectedRules.push(matchedRule);
|
|
53
46
|
}
|
|
54
47
|
}
|
|
55
|
-
|
|
48
|
+
// Optionally add beta-only rules that are not in defaults
|
|
49
|
+
if (includeBeta) {
|
|
56
50
|
for(const betaRuleName in _DefaultRuleStore.BetaRuleStore){
|
|
57
51
|
if (!selectedRules.some((r)=>r.name === betaRuleName)) {
|
|
58
|
-
const betaRule = new _DynamicRule.DynamicRule(betaRuleName);
|
|
52
|
+
const betaRule = new _DynamicRule.DynamicRule(betaRuleName, true);
|
|
59
53
|
selectedRules.push(betaRule);
|
|
60
54
|
}
|
|
61
55
|
}
|
|
@@ -71,10 +65,6 @@ function getRules(ruleNames, options) {
|
|
|
71
65
|
}
|
|
72
66
|
]));
|
|
73
67
|
return GetRuleDefinitions(ruleSeverityMap, options);
|
|
74
|
-
} else {
|
|
75
|
-
return GetRuleDefinitions(undefined, options);
|
|
76
68
|
}
|
|
77
|
-
|
|
78
|
-
function getBetaDefinition() {
|
|
79
|
-
return Object.values(_DefaultRuleStore.BetaRuleStore).map((rule)=>new rule());
|
|
69
|
+
return GetRuleDefinitions(undefined, options);
|
|
80
70
|
}
|
package/main/libs/ScanFlows.js
CHANGED
|
@@ -40,9 +40,9 @@ function ScanFlows(flows, ruleOptions) {
|
|
|
40
40
|
for (const [ruleName, config] of Object.entries(ruleOptions.rules)){
|
|
41
41
|
ruleMap.set(ruleName, config);
|
|
42
42
|
}
|
|
43
|
-
selectedRules = (0, _GetRuleDefinitions.GetRuleDefinitions)(ruleMap);
|
|
43
|
+
selectedRules = (0, _GetRuleDefinitions.GetRuleDefinitions)(ruleMap, ruleOptions);
|
|
44
44
|
} else {
|
|
45
|
-
selectedRules = (0, _GetRuleDefinitions.GetRuleDefinitions)();
|
|
45
|
+
selectedRules = (0, _GetRuleDefinitions.GetRuleDefinitions)(undefined, ruleOptions);
|
|
46
46
|
}
|
|
47
47
|
const flowXmlCache = new Map();
|
|
48
48
|
for (const flowInput of flows){
|
package/main/models/Flow.js
CHANGED
|
@@ -199,8 +199,8 @@ let Flow = class Flow {
|
|
|
199
199
|
return builder.build(rootObj);
|
|
200
200
|
}
|
|
201
201
|
constructor(path, data){
|
|
202
|
-
/**
|
|
203
|
-
* Categorized flow contents that should be used in the rule implementation
|
|
202
|
+
/**
|
|
203
|
+
* Categorized flow contents that should be used in the rule implementation
|
|
204
204
|
*/ _define_property(this, "elements", void 0);
|
|
205
205
|
_define_property(this, "fsPath", void 0);
|
|
206
206
|
_define_property(this, "uri", void 0); // General source URI/path (file or virtual); set from constructor input
|
|
@@ -216,8 +216,8 @@ let Flow = class Flow {
|
|
|
216
216
|
_define_property(this, "status", void 0);
|
|
217
217
|
_define_property(this, "triggerOrder", void 0);
|
|
218
218
|
_define_property(this, "type", void 0);
|
|
219
|
-
/**
|
|
220
|
-
* XML to JSON conversion in raw format
|
|
219
|
+
/**
|
|
220
|
+
* XML to JSON conversion in raw format
|
|
221
221
|
*/ _define_property(this, "xmldata", void 0);
|
|
222
222
|
if (path) {
|
|
223
223
|
this.uri = path; // Always set general URI from input (file path or virtual)
|
|
@@ -241,8 +241,8 @@ let Flow = class Flow {
|
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
243
|
};
|
|
244
|
-
/**
|
|
245
|
-
* Metadata Tags of Salesforce Flow Elements
|
|
244
|
+
/**
|
|
245
|
+
* Metadata Tags of Salesforce Flow Elements
|
|
246
246
|
*/ _define_property(Flow, "FLOW_METADATA_TAGS", [
|
|
247
247
|
"description",
|
|
248
248
|
"apiVersion",
|
|
@@ -262,8 +262,8 @@ let Flow = class Flow {
|
|
|
262
262
|
"environments",
|
|
263
263
|
"segment"
|
|
264
264
|
]);
|
|
265
|
-
/**
|
|
266
|
-
* Categorized flow contents that should be used in the rule implementation
|
|
265
|
+
/**
|
|
266
|
+
* Categorized flow contents that should be used in the rule implementation
|
|
267
267
|
*/ _define_property(Flow, "FLOW_NODES", [
|
|
268
268
|
"actionCalls",
|
|
269
269
|
"apexPluginCalls",
|
package/main/models/FlowType.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Represents the different types of Salesforce Flows and provides utility methods
|
|
3
|
-
* to categorize and retrieve them.
|
|
4
|
-
*
|
|
5
|
-
* @remarks
|
|
6
|
-
* This class defines static properties for various flow types, including backend,
|
|
7
|
-
* process builder, survey, visual, and unsupported types. It also provides a method
|
|
8
|
-
* to retrieve all supported flow types.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```typescript
|
|
12
|
-
* const allFlowTypes = FlowType.allTypes();
|
|
13
|
-
* ```
|
|
1
|
+
/**
|
|
2
|
+
* Represents the different types of Salesforce Flows and provides utility methods
|
|
3
|
+
* to categorize and retrieve them.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* This class defines static properties for various flow types, including backend,
|
|
7
|
+
* process builder, survey, visual, and unsupported types. It also provides a method
|
|
8
|
+
* to retrieve all supported flow types.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const allFlowTypes = FlowType.allTypes();
|
|
13
|
+
* ```
|
|
14
14
|
*/ "use strict";
|
|
15
15
|
Object.defineProperty(exports, "__esModule", {
|
|
16
16
|
value: true
|
|
@@ -64,8 +64,8 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
64
64
|
return newObj;
|
|
65
65
|
}
|
|
66
66
|
let RuleCommon = class RuleCommon {
|
|
67
|
-
/**
|
|
68
|
-
* execute() – automatic suppression
|
|
67
|
+
/**
|
|
68
|
+
* execute() – automatic suppression
|
|
69
69
|
*/ execute(flow, options, suppressions = []) {
|
|
70
70
|
// Wildcard suppression disables entire rule
|
|
71
71
|
if (suppressions.includes("*")) {
|
|
@@ -80,8 +80,8 @@ let RuleCommon = class RuleCommon {
|
|
|
80
80
|
// Wrap into RuleResult
|
|
81
81
|
return new _internals.RuleResult(this, violations);
|
|
82
82
|
}
|
|
83
|
-
/**
|
|
84
|
-
* Legacy/manual suppression helper (still available for early exits)
|
|
83
|
+
/**
|
|
84
|
+
* Legacy/manual suppression helper (still available for early exits)
|
|
85
85
|
*/ isSuppressed(name, suppressions) {
|
|
86
86
|
return suppressions.has(name);
|
|
87
87
|
}
|
package/main/models/RuleInfo.js
CHANGED
|
@@ -23,39 +23,39 @@ function _define_property(obj, key, value) {
|
|
|
23
23
|
}
|
|
24
24
|
let RuleInfo = class RuleInfo {
|
|
25
25
|
constructor(){
|
|
26
|
-
/**
|
|
27
|
-
* Indicates whether the rule can be automatically fixed.
|
|
28
|
-
* When the rule is autofixable, implement @see {AutoFixable}
|
|
26
|
+
/**
|
|
27
|
+
* Indicates whether the rule can be automatically fixed.
|
|
28
|
+
* When the rule is autofixable, implement @see {AutoFixable}
|
|
29
29
|
*/ _define_property(this, "autoFixable", void 0);
|
|
30
|
-
/**
|
|
31
|
-
* A human-readable description of the rule.
|
|
30
|
+
/**
|
|
31
|
+
* A human-readable description of the rule.
|
|
32
32
|
*/ _define_property(this, "description", void 0);
|
|
33
|
-
/**
|
|
34
|
-
* An array of documentation references related to the rule.
|
|
33
|
+
/**
|
|
34
|
+
* An array of documentation references related to the rule.
|
|
35
35
|
*/ _define_property(this, "docRefs", void 0);
|
|
36
|
-
/**
|
|
37
|
-
* Specifies if the rule's behavior can be configured.
|
|
38
|
-
* When configurable, execute should take in a second parameter @see RuleDefinitionExpression
|
|
39
|
-
* @example
|
|
40
|
-
* ```typescript
|
|
41
|
-
* public execute(flow: core.Flow, options?: { expression: string }): core.RuleResult {
|
|
42
|
-
* // your rule
|
|
43
|
-
* }
|
|
36
|
+
/**
|
|
37
|
+
* Specifies if the rule's behavior can be configured.
|
|
38
|
+
* When configurable, execute should take in a second parameter @see RuleDefinitionExpression
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* public execute(flow: core.Flow, options?: { expression: string }): core.RuleResult {
|
|
42
|
+
* // your rule
|
|
43
|
+
* }
|
|
44
44
|
*/ _define_property(this, "isConfigurable", void 0);
|
|
45
|
-
/**
|
|
46
|
-
* The display label for the rule.
|
|
47
|
-
* This property is being displayed on sf cli and on vsce
|
|
45
|
+
/**
|
|
46
|
+
* The display label for the rule.
|
|
47
|
+
* This property is being displayed on sf cli and on vsce
|
|
48
48
|
*/ _define_property(this, "label", void 0);
|
|
49
|
-
/**
|
|
50
|
-
* The unique name identifier for the rule.
|
|
49
|
+
/**
|
|
50
|
+
* The unique name identifier for the rule.
|
|
51
51
|
*/ _define_property(this, "name", void 0);
|
|
52
|
-
/**
|
|
53
|
-
* The types supported by this rule (e.g., Flow, Process).
|
|
54
|
-
* Use defined types in @see FlowType
|
|
52
|
+
/**
|
|
53
|
+
* The types supported by this rule (e.g., Flow, Process).
|
|
54
|
+
* Use defined types in @see FlowType
|
|
55
55
|
*/ _define_property(this, "supportedTypes", void 0);
|
|
56
|
-
/**
|
|
57
|
-
* (Optional) The element that can be used to suppress this rule.
|
|
58
|
-
* @see AdvancedSuppression
|
|
56
|
+
/**
|
|
57
|
+
* (Optional) The element that can be used to suppress this rule.
|
|
58
|
+
* @see AdvancedSuppression
|
|
59
59
|
*/ _define_property(this, "suppressionElement", void 0);
|
|
60
60
|
}
|
|
61
61
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { IRuleDefinition } from "../interfaces/IRuleDefinition";
|
|
2
|
+
import * as core from "../internals/internals";
|
|
3
|
+
import { RuleCommon } from "../models/RuleCommon";
|
|
4
|
+
export declare class MissingMetadataDescription extends RuleCommon implements IRuleDefinition {
|
|
5
|
+
constructor();
|
|
6
|
+
protected check(flow: core.Flow, _options: object | undefined, _suppression: Set<string>): core.Violation[];
|
|
7
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "MissingMetadataDescription", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return MissingMetadataDescription;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _internals = /*#__PURE__*/ _interop_require_wildcard(require("../internals/internals"));
|
|
12
|
+
const _RuleCommon = require("../models/RuleCommon");
|
|
13
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
14
|
+
if (typeof WeakMap !== "function") return null;
|
|
15
|
+
var cacheBabelInterop = new WeakMap();
|
|
16
|
+
var cacheNodeInterop = new WeakMap();
|
|
17
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
18
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
19
|
+
})(nodeInterop);
|
|
20
|
+
}
|
|
21
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
22
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
23
|
+
return obj;
|
|
24
|
+
}
|
|
25
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
26
|
+
return {
|
|
27
|
+
default: obj
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
31
|
+
if (cache && cache.has(obj)) {
|
|
32
|
+
return cache.get(obj);
|
|
33
|
+
}
|
|
34
|
+
var newObj = {
|
|
35
|
+
__proto__: null
|
|
36
|
+
};
|
|
37
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
38
|
+
for(var key in obj){
|
|
39
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
40
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
41
|
+
if (desc && (desc.get || desc.set)) {
|
|
42
|
+
Object.defineProperty(newObj, key, desc);
|
|
43
|
+
} else {
|
|
44
|
+
newObj[key] = obj[key];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
newObj.default = obj;
|
|
49
|
+
if (cache) {
|
|
50
|
+
cache.set(obj, newObj);
|
|
51
|
+
}
|
|
52
|
+
return newObj;
|
|
53
|
+
}
|
|
54
|
+
let MissingMetadataDescription = class MissingMetadataDescription extends _RuleCommon.RuleCommon {
|
|
55
|
+
check(flow, _options, _suppression) {
|
|
56
|
+
const violations = [];
|
|
57
|
+
flow.elements.filter((elem)=>{
|
|
58
|
+
if (elem.metaType !== "metadata" && !elem.element["description"] && elem.subtype !== "start") {
|
|
59
|
+
return elem;
|
|
60
|
+
}
|
|
61
|
+
}).forEach((elem)=>{
|
|
62
|
+
return violations.push(new _internals.Violation(elem));
|
|
63
|
+
});
|
|
64
|
+
return violations;
|
|
65
|
+
}
|
|
66
|
+
constructor(){
|
|
67
|
+
super({
|
|
68
|
+
autoFixable: false,
|
|
69
|
+
description: "Every element must have a meaningful description",
|
|
70
|
+
docRefs: [],
|
|
71
|
+
isConfigurable: false,
|
|
72
|
+
label: "Missing Metadata Description",
|
|
73
|
+
name: "MissingMetadataDescription",
|
|
74
|
+
supportedTypes: _internals.FlowType.allTypes()
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
};
|
|
@@ -39,6 +39,7 @@ const _TriggerOrder = require("../rules/TriggerOrder");
|
|
|
39
39
|
const _UnconnectedElement = require("../rules/UnconnectedElement");
|
|
40
40
|
const _UnsafeRunningContext = require("../rules/UnsafeRunningContext");
|
|
41
41
|
const _UnusedVariable = require("../rules/UnusedVariable");
|
|
42
|
+
const _MissingMetadataDescription = require("../rules/MissingMetadataDescription");
|
|
42
43
|
const DefaultRuleStore = {
|
|
43
44
|
ActionCallsInLoop: _ActionCallsInLoop.ActionCallsInLoop,
|
|
44
45
|
APIVersion: _APIVersion.APIVersion,
|
|
@@ -64,4 +65,6 @@ const DefaultRuleStore = {
|
|
|
64
65
|
UnsafeRunningContext: _UnsafeRunningContext.UnsafeRunningContext,
|
|
65
66
|
UnusedVariable: _UnusedVariable.UnusedVariable
|
|
66
67
|
};
|
|
67
|
-
const BetaRuleStore = {
|
|
68
|
+
const BetaRuleStore = {
|
|
69
|
+
MissingMetadataDescription: _MissingMetadataDescription.MissingMetadataDescription
|
|
70
|
+
};
|
package/package.json
CHANGED
|
@@ -1,76 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flow-scanner/lightning-flow-scanner-core",
|
|
3
3
|
"description": "A lightweight engine for Flow metadata in Node.js, and browser environments. Assess and enhance Salesforce Flow automations for best practices, security, governor limits, and performance issues.",
|
|
4
|
-
"version": "6.
|
|
4
|
+
"version": "6.6.1",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./index.js",
|
|
10
|
+
"types": "./index.d.ts"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
7
13
|
"engines": {
|
|
8
14
|
"node": "^18 || ^20 || ^22 || ^23"
|
|
9
15
|
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"clean": "rimraf out dist",
|
|
12
|
-
"build:js": "swc src --out-dir out --copy-files --strip-leading-paths --config-file .swcrc",
|
|
13
|
-
"build:types": "tsc -p tsconfig.types.json --declaration --emitDeclarationOnly --outDir out",
|
|
14
|
-
"copy:media": "node -e \"require('fs').cpSync('assets/media','out/assets/media',{recursive:true,force:true}) || require('fs').mkdirSync('out/assets/media',{recursive:true})\"",
|
|
15
|
-
"copy:root-files:out": "node -e \"['README.md','LICENSE.md','SECURITY.md','CONTRIBUTING.md','package.json'].forEach(f=>require('fs').copyFileSync(f,'out/'+f))\"",
|
|
16
|
-
"copy:root-files:dist": "node -e \"require('fs').copyFileSync('LICENSE.md','dist/LICENSE.md')\"",
|
|
17
|
-
"____main____": "__DEVELOPER COMMANDS__",
|
|
18
|
-
"build": "npm run clean && npm run build:js && npm run build:types && npm run copy:media && npm run copy:root-files:out",
|
|
19
|
-
"test": "npm run test:umd",
|
|
20
|
-
"test:node": "jest",
|
|
21
|
-
"test:umd": "npm run build:js && vite build && npm run copy:root-files:dist && cross-env UMD_PATH=dist/lightning-flow-scanner-core.umd.js jest",
|
|
22
|
-
"link": "npm run build && npm link ./out",
|
|
23
|
-
"____pack____": "PACKAGING COMMANDS__",
|
|
24
|
-
"swc:sim:pack": "npm run build",
|
|
25
|
-
"vite:dist": "npm run build:js && vite build && npm run copy:root-files:dist",
|
|
26
|
-
"prepare": "husky",
|
|
27
|
-
"precommit": "lint-staged",
|
|
28
|
-
"prepush": "npm run build && npm test",
|
|
29
|
-
"stryker": "npm i -g @stryker-mutator/core @stryker-mutator/jest-runner && stryker run"
|
|
30
|
-
},
|
|
31
16
|
"license": "MIT",
|
|
32
17
|
"repository": {
|
|
33
18
|
"type": "git",
|
|
34
|
-
"url": "git+https://github.com/Flow-Scanner/lightning-flow-scanner
|
|
19
|
+
"url": "git+https://github.com/Flow-Scanner/lightning-flow-scanner.git",
|
|
20
|
+
"directory": "packages/core"
|
|
35
21
|
},
|
|
36
22
|
"dependencies": {
|
|
37
23
|
"fast-xml-parser": "^5.3.0"
|
|
38
24
|
},
|
|
39
|
-
"devDependencies": {
|
|
40
|
-
"@jest/types": "30.0.1",
|
|
41
|
-
"@swc-node/jest": "1.9.1",
|
|
42
|
-
"@swc/cli": "0.7.7",
|
|
43
|
-
"@swc/core": "1.13.5",
|
|
44
|
-
"@swc/helpers": "0.5.17",
|
|
45
|
-
"@types/jest": "29.5.14",
|
|
46
|
-
"@types/node": "22.15.30",
|
|
47
|
-
"@types/semantic-release": "20.0.6",
|
|
48
|
-
"cross-env": "^10.1.0",
|
|
49
|
-
"eslint": "9.30.0",
|
|
50
|
-
"eslint-plugin-de-morgan": "1.3.0",
|
|
51
|
-
"eslint-plugin-github": "6.0.0",
|
|
52
|
-
"eslint-plugin-jest": "29.0.1",
|
|
53
|
-
"eslint-plugin-perfectionist": "4.15.0",
|
|
54
|
-
"eslint-plugin-sonarjs": "3.0.4",
|
|
55
|
-
"husky": "9.1.7",
|
|
56
|
-
"jest": "30.0.3",
|
|
57
|
-
"lint-staged": "^16.1.2",
|
|
58
|
-
"prettier": "3.6.2",
|
|
59
|
-
"rimraf": "^6.1.0",
|
|
60
|
-
"ts-node": "10.9.2",
|
|
61
|
-
"typescript": "5.8.3",
|
|
62
|
-
"typescript-eslint": "8.35.0",
|
|
63
|
-
"vite": "6.4.1",
|
|
64
|
-
"vite-plugin-node-polyfills": "0.23.0"
|
|
65
|
-
},
|
|
66
25
|
"homepage": "https://dev.lightningflowscanner.org",
|
|
67
26
|
"author": {
|
|
68
27
|
"name": "Ruben Halman",
|
|
69
28
|
"url": "https://github.com/RubenHalman"
|
|
70
29
|
},
|
|
71
|
-
"volta": {
|
|
72
|
-
"node": "20.13.1"
|
|
73
|
-
},
|
|
74
30
|
"keywords": [
|
|
75
31
|
"best-practices",
|
|
76
32
|
"code-quality",
|
|
File without changes
|