@j-schreiber/sf-cli-security-audit 0.11.3 → 0.12.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/LICENSE +117 -0
- package/README.md +23 -4
- package/lib/commands/org/audit/run.d.ts +1 -0
- package/lib/commands/org/audit/run.js +22 -10
- package/lib/commands/org/audit/run.js.map +1 -1
- package/lib/salesforce/mdapi/genericSettingsMetadata.js +2 -1
- package/lib/salesforce/mdapi/genericSettingsMetadata.js.map +1 -1
- package/lib/salesforce/mdapi/metadataRegistryEntry.d.ts +8 -4
- package/lib/salesforce/mdapi/metadataRegistryEntry.js +23 -10
- package/lib/salesforce/mdapi/metadataRegistryEntry.js.map +1 -1
- package/lib/salesforce/mdapi/namedMetadataType.js +9 -5
- package/lib/salesforce/mdapi/namedMetadataType.js.map +1 -1
- package/lib/salesforce/mdapi/singletonMetadataType.js +6 -3
- package/lib/salesforce/mdapi/singletonMetadataType.js.map +1 -1
- package/lib/ux/environment.d.ts +25 -0
- package/lib/ux/environment.js +35 -0
- package/lib/ux/environment.js.map +1 -0
- package/messages/org.audit.run.md +12 -0
- package/oclif.manifest.json +9 -1
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Preamble
|
|
2
|
+
|
|
3
|
+
This license covers the **COMMUNITY EDITION** of the SAE. If
|
|
4
|
+
you are interested in a commercial-use license, please reach
|
|
5
|
+
out to business@jannis-schreiber.me.
|
|
6
|
+
|
|
7
|
+
## Acceptance
|
|
8
|
+
|
|
9
|
+
In order to get any license under these terms, you must agree
|
|
10
|
+
to them as both strict obligations and conditions to all
|
|
11
|
+
your licenses.
|
|
12
|
+
|
|
13
|
+
## Copyright License
|
|
14
|
+
|
|
15
|
+
The licensor grants you a copyright license for the software
|
|
16
|
+
to do everything you might do with the software that would
|
|
17
|
+
otherwise infringe the licensor's copyright in it for any
|
|
18
|
+
permitted purpose. However, you may only make changes or
|
|
19
|
+
new works based on the software according to [Changes and New
|
|
20
|
+
Works License](#changes-and-new-works-license), and you may
|
|
21
|
+
not distribute the software.
|
|
22
|
+
|
|
23
|
+
## Changes and New Works License
|
|
24
|
+
|
|
25
|
+
The licensor grants you an additional copyright license to
|
|
26
|
+
make changes and new works based on the software for any
|
|
27
|
+
permitted purpose.
|
|
28
|
+
|
|
29
|
+
## Patent License
|
|
30
|
+
|
|
31
|
+
The licensor grants you a patent license for the software that
|
|
32
|
+
covers patent claims the licensor can license, or becomes able
|
|
33
|
+
to license, that you would infringe by using the software.
|
|
34
|
+
|
|
35
|
+
## Allowed Use
|
|
36
|
+
|
|
37
|
+
The licensor grants you the rights to use this software for
|
|
38
|
+
the following permitted purposes.
|
|
39
|
+
|
|
40
|
+
### Internal Business Use
|
|
41
|
+
|
|
42
|
+
Use of the software for the internal business operations of
|
|
43
|
+
you and your company is use for a permitted purpose. Internal
|
|
44
|
+
business operations must be non-commercial, which means not
|
|
45
|
+
primarily intended for or directed towards commercial advantage
|
|
46
|
+
or monetary compensation.
|
|
47
|
+
|
|
48
|
+
### Personal Uses
|
|
49
|
+
|
|
50
|
+
Personal use for research, experiment, and testing for
|
|
51
|
+
the benefit of public knowledge, personal study, private
|
|
52
|
+
entertainment, hobby projects, amateur pursuits, or religious
|
|
53
|
+
observance, without any anticipated commercial application,
|
|
54
|
+
is use for a permitted purpose.
|
|
55
|
+
|
|
56
|
+
## Fair Use
|
|
57
|
+
|
|
58
|
+
You may have "fair use" rights for the software under the
|
|
59
|
+
law. These terms do not limit them.
|
|
60
|
+
|
|
61
|
+
## No Other Rights
|
|
62
|
+
|
|
63
|
+
These terms do not allow you to sublicense or transfer any of
|
|
64
|
+
your licenses to anyone else, or prevent the licensor from
|
|
65
|
+
granting licenses to anyone else. These terms do not imply
|
|
66
|
+
any other licenses.
|
|
67
|
+
|
|
68
|
+
## Patent Defense
|
|
69
|
+
|
|
70
|
+
If you make any written claim that the software infringes or
|
|
71
|
+
contributes to infringement of any patent, your patent license
|
|
72
|
+
for the software granted under these terms ends immediately. If
|
|
73
|
+
your company makes such a claim, your patent license ends
|
|
74
|
+
immediately for work on behalf of your company.
|
|
75
|
+
|
|
76
|
+
## Violations
|
|
77
|
+
|
|
78
|
+
The first time you are notified in writing that you have
|
|
79
|
+
violated any of these terms, or done anything with the software
|
|
80
|
+
not covered by your licenses, your licenses can nonetheless
|
|
81
|
+
continue if you come into full compliance with these terms,
|
|
82
|
+
and take practical steps to correct past violations, within
|
|
83
|
+
32 days of receiving notice. Otherwise, all your licenses
|
|
84
|
+
end immediately.
|
|
85
|
+
|
|
86
|
+
## No Liability
|
|
87
|
+
|
|
88
|
+
**_As far as the law allows, the software comes as is, without
|
|
89
|
+
any warranty or condition, and the licensor will not be liable
|
|
90
|
+
to you for any damages arising out of these terms or the use
|
|
91
|
+
or nature of the software, under any kind of legal claim._**
|
|
92
|
+
|
|
93
|
+
## Definitions
|
|
94
|
+
|
|
95
|
+
The **licensor** is the individual or entity offering these
|
|
96
|
+
terms, and the **software** is the software the licensor makes
|
|
97
|
+
available under these terms.
|
|
98
|
+
|
|
99
|
+
**You** refers to the individual or entity agreeing to these
|
|
100
|
+
terms.
|
|
101
|
+
|
|
102
|
+
**Your company** is any legal entity, sole proprietorship,
|
|
103
|
+
or other kind of organization that you work for, plus all
|
|
104
|
+
organizations that have control over, are under the control of,
|
|
105
|
+
or are under common control with that organization. **Control**
|
|
106
|
+
means ownership of substantially all the assets of an entity,
|
|
107
|
+
or the power to direct its management and policies by vote,
|
|
108
|
+
contract, or otherwise. Control can be direct or indirect.
|
|
109
|
+
|
|
110
|
+
**Your licenses** are all the licenses granted to you for the
|
|
111
|
+
software under these terms.
|
|
112
|
+
|
|
113
|
+
**Use** means anything you do with the software requiring one
|
|
114
|
+
of your licenses.
|
|
115
|
+
|
|
116
|
+
Copyright (c) 2026, Jannis Schreiber.
|
|
117
|
+
All rights reserved.
|
package/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# @j-schreiber/sf-cli-security-audit
|
|
2
2
|
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://www.npmjs.com/package/@j-schreiber/sf-cli-security-audit"><img src="https://img.shields.io/npm/v/@j-schreiber/sf-cli-security-audit.svg?logo=npm" alt="NPM version"/></a>
|
|
5
|
+
<a href="https://github.com/j-schreiber/js-sf-cli-security-audit/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-blue" alt="License"></a>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
3
8
|
> This plugin is still in beta and under active development. Command signatures and directory structures can change.
|
|
4
9
|
|
|
5
10
|
To go beyond command signatures and learn about the concepts, design decisions, and a variety of use cases [see the official docs](https://securityauditengine.org/docs).
|
|
@@ -79,7 +84,7 @@ FLAG DESCRIPTIONS
|
|
|
79
84
|
essentially control, if a permission is allowed in a certain profile / permission set.
|
|
80
85
|
```
|
|
81
86
|
|
|
82
|
-
_See code: [src/commands/org/audit/init.ts](https://github.com/j-schreiber/js-sf-cli-security-audit/blob/v0.
|
|
87
|
+
_See code: [src/commands/org/audit/init.ts](https://github.com/j-schreiber/js-sf-cli-security-audit/blob/v0.12.1/src/commands/org/audit/init.ts)_
|
|
83
88
|
|
|
84
89
|
## `sf org audit run`
|
|
85
90
|
|
|
@@ -87,12 +92,13 @@ Audit your org with an existing config.
|
|
|
87
92
|
|
|
88
93
|
```
|
|
89
94
|
USAGE
|
|
90
|
-
$ sf org audit run -o <value> [--json] [--flags-dir <value>] [-d <value>] [--api-version <value>]
|
|
95
|
+
$ sf org audit run -o <value> [--json] [--flags-dir <value>] [-d <value>] [--api-version <value>] [--verbose]
|
|
91
96
|
|
|
92
97
|
FLAGS
|
|
93
98
|
-d, --source-dir=<value> Source directory of the audit config to run.
|
|
94
99
|
-o, --target-org=<value> (required) The org that is audited.
|
|
95
100
|
--api-version=<value> Override the api version used for api requests made by this command
|
|
101
|
+
--verbose Don't truncate rule violation tables.
|
|
96
102
|
|
|
97
103
|
GLOBAL FLAGS
|
|
98
104
|
--flags-dir=<value> Import flag values from a directory.
|
|
@@ -108,9 +114,22 @@ EXAMPLES
|
|
|
108
114
|
Audit the org MyTargetOrg with the config in configs/prod
|
|
109
115
|
|
|
110
116
|
$ sf org audit run -o MyTargetOrg -d configs/prod
|
|
117
|
+
|
|
118
|
+
FLAG DESCRIPTIONS
|
|
119
|
+
-d, --source-dir=<value> Source directory of the audit config to run.
|
|
120
|
+
|
|
121
|
+
Loads all classifications and policies from the directory and uses them to audit the org. Only policies that are
|
|
122
|
+
enabled and that exist in the directory are executed.
|
|
123
|
+
|
|
124
|
+
--verbose Don't truncate rule violation tables.
|
|
125
|
+
|
|
126
|
+
The default behavior truncates result tables of rule violations in terminal output, when they exceed a certain
|
|
127
|
+
length. The default maximum length is 30 rows and can be configured in the environment variable
|
|
128
|
+
`SAE_MAX_RESULT_VIOLATION_ROWS`. If this flag is present, the full violations table is printed. The JSON report is
|
|
129
|
+
never truncated.
|
|
111
130
|
```
|
|
112
131
|
|
|
113
|
-
_See code: [src/commands/org/audit/run.ts](https://github.com/j-schreiber/js-sf-cli-security-audit/blob/v0.
|
|
132
|
+
_See code: [src/commands/org/audit/run.ts](https://github.com/j-schreiber/js-sf-cli-security-audit/blob/v0.12.1/src/commands/org/audit/run.ts)_
|
|
114
133
|
|
|
115
134
|
## `sf org scan user-perms`
|
|
116
135
|
|
|
@@ -149,7 +168,7 @@ FLAG DESCRIPTIONS
|
|
|
149
168
|
retun 0 results).
|
|
150
169
|
```
|
|
151
170
|
|
|
152
|
-
_See code: [src/commands/org/scan/user-perms.ts](https://github.com/j-schreiber/js-sf-cli-security-audit/blob/v0.
|
|
171
|
+
_See code: [src/commands/org/scan/user-perms.ts](https://github.com/j-schreiber/js-sf-cli-security-audit/blob/v0.12.1/src/commands/org/scan/user-perms.ts)_
|
|
153
172
|
|
|
154
173
|
<!-- commandsstop -->
|
|
155
174
|
|
|
@@ -13,6 +13,7 @@ export default class OrgAuditRun extends SfCommand<OrgAuditRunResult> {
|
|
|
13
13
|
'target-org': Interfaces.OptionFlag<import("@salesforce/core").Org, Interfaces.CustomOptions>;
|
|
14
14
|
'source-dir': Interfaces.OptionFlag<string, Interfaces.CustomOptions>;
|
|
15
15
|
'api-version': Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
16
|
+
verbose: Interfaces.BooleanFlag<boolean>;
|
|
16
17
|
};
|
|
17
18
|
run(): Promise<OrgAuditRunResult>;
|
|
18
19
|
private printResults;
|
|
@@ -5,6 +5,7 @@ import { Messages } from '@salesforce/core';
|
|
|
5
5
|
import AuditRunMultiStageOutput from '../../../ux/auditRunMultiStage.js';
|
|
6
6
|
import { capitalize, formatToLocale } from '../../../utils.js';
|
|
7
7
|
import { startAuditRun } from '../../../libs/audit-engine/index.js';
|
|
8
|
+
import { envVars } from '../../../ux/environment.js';
|
|
8
9
|
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
9
10
|
const messages = Messages.loadMessages('@j-schreiber/sf-cli-security-audit', 'org.audit.run');
|
|
10
11
|
export const MERGE_CHAR = ' \u2022 ';
|
|
@@ -22,9 +23,14 @@ export default class OrgAuditRun extends SfCommand {
|
|
|
22
23
|
required: false,
|
|
23
24
|
char: 'd',
|
|
24
25
|
summary: messages.getMessage('flags.source-dir.summary'),
|
|
26
|
+
description: messages.getMessage('flags.source-dir.description'),
|
|
25
27
|
default: '',
|
|
26
28
|
}),
|
|
27
29
|
'api-version': Flags.orgApiVersion(),
|
|
30
|
+
verbose: Flags.boolean({
|
|
31
|
+
summary: messages.getMessage('flags.verbose.summary'),
|
|
32
|
+
description: messages.getMessage('flags.verbose.description'),
|
|
33
|
+
}),
|
|
28
34
|
};
|
|
29
35
|
async run() {
|
|
30
36
|
const { flags } = await this.parse(OrgAuditRun);
|
|
@@ -41,15 +47,15 @@ export default class OrgAuditRun extends SfCommand {
|
|
|
41
47
|
const partialResult = await auditRun.execute(flags['target-org'].getConnection(flags['api-version']));
|
|
42
48
|
const result = { orgId: flags['target-org'].getOrgId(), ...partialResult };
|
|
43
49
|
stageOutput.finish();
|
|
44
|
-
this.printResults(result);
|
|
50
|
+
this.printResults(result, flags['verbose']);
|
|
45
51
|
const filePath = this.writeReport(result, flags);
|
|
46
52
|
return { ...result, filePath };
|
|
47
53
|
}
|
|
48
|
-
printResults(result) {
|
|
54
|
+
printResults(result, isVerbose) {
|
|
49
55
|
this.printPoliciesSummary(result);
|
|
50
56
|
for (const [policyName, policyDetails] of Object.entries(result.policies)) {
|
|
51
57
|
this.printExecutedRulesSummary(policyName, policyDetails);
|
|
52
|
-
this.printRuleViolations(policyDetails.executedRules);
|
|
58
|
+
this.printRuleViolations(policyDetails.executedRules, isVerbose);
|
|
53
59
|
}
|
|
54
60
|
}
|
|
55
61
|
printPoliciesSummary(result) {
|
|
@@ -77,17 +83,23 @@ export default class OrgAuditRun extends SfCommand {
|
|
|
77
83
|
});
|
|
78
84
|
}
|
|
79
85
|
}
|
|
80
|
-
printRuleViolations(executedRules) {
|
|
86
|
+
printRuleViolations(executedRules, isVerbose) {
|
|
87
|
+
const maxLength = envVars.resolve('SAE_MAX_RESULT_VIOLATION_ROWS');
|
|
81
88
|
for (const uncompliantRule of Object.values(executedRules).filter((ruleDetails) => !ruleDetails.isCompliant)) {
|
|
89
|
+
const data = uncompliantRule.violations.map((viol) => ({
|
|
90
|
+
...viol,
|
|
91
|
+
identifier: typeof viol.identifier === 'string'
|
|
92
|
+
? formatToLocale(viol.identifier)
|
|
93
|
+
: viol.identifier.map((id) => formatToLocale(id)).join(MERGE_CHAR),
|
|
94
|
+
}));
|
|
82
95
|
this.table({
|
|
83
|
-
data:
|
|
84
|
-
...viol,
|
|
85
|
-
identifier: typeof viol.identifier === 'string'
|
|
86
|
-
? formatToLocale(viol.identifier)
|
|
87
|
-
: viol.identifier.map((id) => formatToLocale(id)).join(MERGE_CHAR),
|
|
88
|
-
})),
|
|
96
|
+
data: isVerbose ? data : data.slice(0, maxLength),
|
|
89
97
|
title: `Violations for ${uncompliantRule.ruleName}`,
|
|
90
98
|
});
|
|
99
|
+
if (data.length > maxLength && !isVerbose) {
|
|
100
|
+
this.info(messages.getMessage('info.RemovedViolationRows', [maxLength, data.length]));
|
|
101
|
+
this.info('');
|
|
102
|
+
}
|
|
91
103
|
}
|
|
92
104
|
}
|
|
93
105
|
writeReport(result, flags) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../src/commands/org/audit/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAM5C,OAAO,wBAAwB,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../src/commands/org/audit/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,8 +31,9 @@ export default class GenericSettingsMetadata {
|
|
|
31
31
|
const result = this.parseSettingsContent(retrieveResult.retrievedComponents, settingNames);
|
|
32
32
|
return result;
|
|
33
33
|
}
|
|
34
|
-
parseSettingsContent(
|
|
34
|
+
parseSettingsContent(cmps, settingNames) {
|
|
35
35
|
const result = {};
|
|
36
|
+
const settings = cmps[this.retrieveType] ? Object.values(cmps[this.retrieveType]) : [];
|
|
36
37
|
for (const setting of settings) {
|
|
37
38
|
if (!settingNames.includes(setting.identifier)) {
|
|
38
39
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"genericSettingsMetadata.js","sourceRoot":"","sources":["../../../src/salesforce/mdapi/genericSettingsMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAA2B,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAQ/E;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAClC,YAAY,CAAC;IACJ,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;IAE1C;QACE,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC;IACjC,CAAC;IAED;;;;;;;;OAQG;IACI,KAAK,CAAC,OAAO,CAAC,GAAe,EAAE,YAAsB;QAC1D,MAAM,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAClC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,oBAAoB,CAAC,cAAc,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;QAC3F,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,oBAAoB,CAAC,
|
|
1
|
+
{"version":3,"file":"genericSettingsMetadata.js","sourceRoot":"","sources":["../../../src/salesforce/mdapi/genericSettingsMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAA2B,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAQ/E;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAClC,YAAY,CAAC;IACJ,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;IAE1C;QACE,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC;IACjC,CAAC;IAED;;;;;;;;OAQG;IACI,KAAK,CAAC,OAAO,CAAC,GAAe,EAAE,YAAsB;QAC1D,MAAM,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAClC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,oBAAoB,CAAC,cAAc,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;QAC3F,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,oBAAoB,CAAC,IAAmB,EAAE,YAAsB;QACtE,MAAM,MAAM,GAAsC,EAAE,CAAC;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/C,SAAS;YACX,CAAC;YACD,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,OAAO,CAAC,UAAU,UAAU,CAAC,CAAC;YAClG,IAAI,eAAe,EAAE,CAAC;gBACpB,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,eAAe,CAAC;YAC/C,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,cAAc,CAAC,OAAe,EAAE,YAAoB;QAC1D,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;QAC5E,OAAO,aAAa,CAAC,YAAY,CAA4B,CAAC;IAChE,CAAC;CACF"}
|
|
@@ -31,8 +31,9 @@ export type ComponentRetrieveResult = {
|
|
|
31
31
|
packageName: string;
|
|
32
32
|
retrievePath: string;
|
|
33
33
|
mdapiRetrieveResult: RetrieveResult;
|
|
34
|
-
retrievedComponents:
|
|
34
|
+
retrievedComponents: MdapiComponentDictionary;
|
|
35
35
|
};
|
|
36
|
+
type MdapiComponentDictionary = Record<string, Record<string, MdapiComponent>>;
|
|
36
37
|
type MdapiComponent = {
|
|
37
38
|
/**
|
|
38
39
|
* Original path to the temporary file
|
|
@@ -46,6 +47,10 @@ type MdapiComponent = {
|
|
|
46
47
|
* Unique identifier of the retrieved metadata type
|
|
47
48
|
*/
|
|
48
49
|
identifier: string;
|
|
50
|
+
/**
|
|
51
|
+
* Type of the metadata, identical to "retrieveType"
|
|
52
|
+
*/
|
|
53
|
+
metadataType: string;
|
|
49
54
|
};
|
|
50
55
|
export default abstract class MetadataRegistryEntry<Type, Key extends keyof Type> {
|
|
51
56
|
private opts;
|
|
@@ -53,9 +58,8 @@ export default abstract class MetadataRegistryEntry<Type, Key extends keyof Type
|
|
|
53
58
|
retrieveType: string;
|
|
54
59
|
rootNodeName: Key;
|
|
55
60
|
constructor(opts: MetadataRegistryEntryOpts<Type, Key>);
|
|
56
|
-
parse(filePath: string): Type[Key];
|
|
57
|
-
extract(rawFileContent: string): Type[Key];
|
|
61
|
+
parse(filePath: string): Type[Key] | undefined;
|
|
62
|
+
extract(rawFileContent: string): Type[Key] | undefined;
|
|
58
63
|
}
|
|
59
64
|
export declare function retrieve(compSet: ComponentSet, con: Connection): Promise<ComponentRetrieveResult>;
|
|
60
|
-
export declare function parseRetrievedComponents(retrievePath: string): Promise<MdapiComponent[]>;
|
|
61
65
|
export {};
|
|
@@ -2,6 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { XMLParser } from 'fast-xml-parser';
|
|
4
4
|
import { ComponentSet } from '@salesforce/source-deploy-retrieve';
|
|
5
|
+
import { isNullish } from '../../utils.js';
|
|
5
6
|
import { RETRIEVE_CACHE } from './constants.js';
|
|
6
7
|
export default class MetadataRegistryEntry {
|
|
7
8
|
opts;
|
|
@@ -20,10 +21,14 @@ export default class MetadataRegistryEntry {
|
|
|
20
21
|
}
|
|
21
22
|
extract(rawFileContent) {
|
|
22
23
|
const parsedContent = this.parser.parse(rawFileContent);
|
|
24
|
+
const metadataBody = parsedContent[this.rootNodeName];
|
|
25
|
+
if (isNullish(metadataBody)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
23
28
|
if (this.opts.parsePostProcessor) {
|
|
24
|
-
return this.opts.parsePostProcessor(
|
|
29
|
+
return this.opts.parsePostProcessor(metadataBody);
|
|
25
30
|
}
|
|
26
|
-
return
|
|
31
|
+
return metadataBody;
|
|
27
32
|
}
|
|
28
33
|
}
|
|
29
34
|
export async function retrieve(compSet, con) {
|
|
@@ -48,17 +53,25 @@ export async function retrieve(compSet, con) {
|
|
|
48
53
|
retrievePath,
|
|
49
54
|
};
|
|
50
55
|
}
|
|
51
|
-
|
|
56
|
+
async function parseRetrievedComponents(retrievePath) {
|
|
52
57
|
const cmpSet = await ComponentSet.fromManifest(path.join(retrievePath, 'package.xml'));
|
|
53
|
-
const parsedComponents =
|
|
58
|
+
const parsedComponents = {};
|
|
54
59
|
for (const mdcmp of cmpSet.toArray()) {
|
|
60
|
+
if (!parsedComponents[mdcmp.type.name]) {
|
|
61
|
+
parsedComponents[mdcmp.type.name] = {};
|
|
62
|
+
}
|
|
55
63
|
const filePath = path.join(retrievePath, mdcmp.type.directoryName, mdcmp.type.suffix ? `${mdcmp.fullName}.${mdcmp.type.suffix}` : mdcmp.fullName);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
64
|
+
if (fs.existsSync(filePath)) {
|
|
65
|
+
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
66
|
+
if (fileContent && fileContent.length > 1) {
|
|
67
|
+
parsedComponents[mdcmp.type.name][mdcmp.fullName] = {
|
|
68
|
+
metadataType: mdcmp.type.name,
|
|
69
|
+
filePath,
|
|
70
|
+
identifier: mdcmp.fullName,
|
|
71
|
+
fileContent,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
62
75
|
}
|
|
63
76
|
return parsedComponents;
|
|
64
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadataRegistryEntry.js","sourceRoot":"","sources":["../../../src/salesforce/mdapi/metadataRegistryEntry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAkB,MAAM,oCAAoC,CAAC;AAElF,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"metadataRegistryEntry.js","sourceRoot":"","sources":["../../../src/salesforce/mdapi/metadataRegistryEntry.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,16 +23,20 @@ export default class NamedMetadata extends MetadataRegistryEntry {
|
|
|
23
23
|
const resolvedFiles = this.parseSourceFiles(retrieveResult.retrievedComponents, componentNames);
|
|
24
24
|
return resolvedFiles;
|
|
25
25
|
}
|
|
26
|
-
parseSourceFiles(components,
|
|
26
|
+
parseSourceFiles(components, requestedNames) {
|
|
27
27
|
const result = {};
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
for (const requestedName of requestedNames) {
|
|
29
|
+
const retrievedType = components[this.retrieveType]?.[requestedName];
|
|
30
|
+
if (retrievedType?.filePath) {
|
|
30
31
|
// the available method parseXmlSync on source component does not
|
|
31
32
|
// resolve the "rootNodeProblem" from XML. Therefore, we implement
|
|
32
33
|
// our own method to parse and return the "inner xml".
|
|
33
|
-
|
|
34
|
+
const contents = this.extract(retrievedType.fileContent);
|
|
35
|
+
if (contents) {
|
|
36
|
+
result[retrievedType.identifier] = contents;
|
|
37
|
+
}
|
|
34
38
|
}
|
|
35
|
-
}
|
|
39
|
+
}
|
|
36
40
|
return result;
|
|
37
41
|
}
|
|
38
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"namedMetadataType.js","sourceRoot":"","sources":["../../../src/salesforce/mdapi/namedMetadataType.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,qBAAqB,EAAE,EAG5B,QAAQ,GACT,MAAM,4BAA4B,CAAC;AAEpC;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,aAA4C,SAAQ,qBAAgC;IACvG,YAAmB,IAA0C;QAC3D,KAAK,CAAC,IAAI,CAAC,CAAC;IACd,CAAC;IACD;;;;;;;OAOG;IACI,KAAK,CAAC,OAAO,CAAC,GAAe,EAAE,cAAwB;QAC5D,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/G,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACnD,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC,mBAAmB,EAAE,cAAc,CAAC,CAAC;QAChG,OAAO,aAAa,CAAC;IACvB,CAAC;IAEO,gBAAgB,CACtB,UAA0D,EAC1D,cAAwB;QAExB,MAAM,MAAM,GAA8B,EAAE,CAAC;QAC7C,
|
|
1
|
+
{"version":3,"file":"namedMetadataType.js","sourceRoot":"","sources":["../../../src/salesforce/mdapi/namedMetadataType.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,qBAAqB,EAAE,EAG5B,QAAQ,GACT,MAAM,4BAA4B,CAAC;AAEpC;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,aAA4C,SAAQ,qBAAgC;IACvG,YAAmB,IAA0C;QAC3D,KAAK,CAAC,IAAI,CAAC,CAAC;IACd,CAAC;IACD;;;;;;;OAOG;IACI,KAAK,CAAC,OAAO,CAAC,GAAe,EAAE,cAAwB;QAC5D,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/G,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACnD,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC,mBAAmB,EAAE,cAAc,CAAC,CAAC;QAChG,OAAO,aAAa,CAAC;IACvB,CAAC;IAEO,gBAAgB,CACtB,UAA0D,EAC1D,cAAwB;QAExB,MAAM,MAAM,GAA8B,EAAE,CAAC;QAC7C,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;YAC3C,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC;YACrE,IAAI,aAAa,EAAE,QAAQ,EAAE,CAAC;gBAC5B,iEAAiE;gBACjE,kEAAkE;gBAClE,sDAAsD;gBACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;gBACzD,IAAI,QAAQ,EAAE,CAAC;oBACb,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC;gBAC9C,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
|
@@ -28,9 +28,12 @@ export default class SingletonMetadata extends MetadataRegistryEntry {
|
|
|
28
28
|
return this.returnRetrieveType(result.retrievedComponents);
|
|
29
29
|
}
|
|
30
30
|
returnRetrieveType(components) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
const retrievedComponent = components[this.retrieveType]?.[this.retrieveName];
|
|
32
|
+
if (retrievedComponent) {
|
|
33
|
+
const contents = this.extract(retrievedComponent.fileContent);
|
|
34
|
+
if (contents) {
|
|
35
|
+
return contents;
|
|
36
|
+
}
|
|
34
37
|
}
|
|
35
38
|
throw messages.createError('error.FailedToRetrieveComponent', [`${this.retrieveName}.${this.retrieveType}`]);
|
|
36
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"singletonMetadataType.js","sourceRoot":"","sources":["../../../src/salesforce/mdapi/singletonMetadataType.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,qBAAqB,EAAE,EAG5B,QAAQ,GACT,MAAM,4BAA4B,CAAC;AAEpC,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,oCAAoC,EAAE,kBAAkB,CAAC,CAAC;AAEjG;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAgD,SAAQ,qBAAgC;IACpG,YAAY,CAAS;IAC5B,YAAmB,IAA0C;QAC3D,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACrE,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,OAAO,CAAC,GAAe;QAClC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC5F,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC7D,CAAC;IAEO,kBAAkB,CAAC,UAA0D;QACnF,
|
|
1
|
+
{"version":3,"file":"singletonMetadataType.js","sourceRoot":"","sources":["../../../src/salesforce/mdapi/singletonMetadataType.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,qBAAqB,EAAE,EAG5B,QAAQ,GACT,MAAM,4BAA4B,CAAC;AAEpC,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,oCAAoC,EAAE,kBAAkB,CAAC,CAAC;AAEjG;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAgD,SAAQ,qBAAgC;IACpG,YAAY,CAAS;IAC5B,YAAmB,IAA0C;QAC3D,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACrE,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,OAAO,CAAC,GAAe;QAClC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC5F,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC7D,CAAC;IAEO,kBAAkB,CAAC,UAA0D;QACnF,MAAM,kBAAkB,GAAG,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9E,IAAI,kBAAkB,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;YAC9D,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QACD,MAAM,QAAQ,CAAC,WAAW,CAAC,iCAAiC,EAAE,CAAC,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;IAC/G,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Dictionary } from '@salesforce/ts-types';
|
|
2
|
+
import { Env } from '@salesforce/kit';
|
|
3
|
+
export declare const SUPPORTED_ENV_VARS: {
|
|
4
|
+
readonly SAE_MAX_RESULT_VIOLATION_ROWS: {
|
|
5
|
+
readonly description: "Maximum number of rows that are displayed for violation tables.";
|
|
6
|
+
readonly expectedType: "number";
|
|
7
|
+
readonly defaultValue: 30;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
type EnvironmentVariable = keyof typeof SUPPORTED_ENV_VARS;
|
|
11
|
+
type EnvironmentConfig = typeof SUPPORTED_ENV_VARS;
|
|
12
|
+
type TypeMap = {
|
|
13
|
+
string: string;
|
|
14
|
+
number: number;
|
|
15
|
+
boolean: boolean;
|
|
16
|
+
};
|
|
17
|
+
type InferType<K extends EnvironmentVariable> = TypeMap[EnvironmentConfig[K]['expectedType']];
|
|
18
|
+
export default class EnvVars extends Env {
|
|
19
|
+
constructor(env?: NodeJS.ProcessEnv);
|
|
20
|
+
resolve<P extends EnvironmentVariable>(property: P): InferType<P> | undefined;
|
|
21
|
+
asDictionary(): Dictionary<unknown>;
|
|
22
|
+
asMap(): Map<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
export declare const envVars: EnvVars;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Env } from '@salesforce/kit';
|
|
2
|
+
export const SUPPORTED_ENV_VARS = {
|
|
3
|
+
SAE_MAX_RESULT_VIOLATION_ROWS: {
|
|
4
|
+
description: 'Maximum number of rows that are displayed for violation tables.',
|
|
5
|
+
expectedType: 'number',
|
|
6
|
+
defaultValue: 30,
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
export default class EnvVars extends Env {
|
|
10
|
+
constructor(env = process.env) {
|
|
11
|
+
super(env);
|
|
12
|
+
}
|
|
13
|
+
resolve(property) {
|
|
14
|
+
const conf = SUPPORTED_ENV_VARS[property];
|
|
15
|
+
switch (conf.expectedType) {
|
|
16
|
+
case 'number':
|
|
17
|
+
return (this.getNumber(property) ?? conf.defaultValue);
|
|
18
|
+
// case 'boolean':
|
|
19
|
+
// return (this.getBoolean(property) ?? conf.defaultValue) as InferType<P>;
|
|
20
|
+
// case 'string':
|
|
21
|
+
// return (this.getString(property) ?? conf.defaultValue) as InferType<P>;
|
|
22
|
+
default:
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
asDictionary() {
|
|
28
|
+
return Object.fromEntries(this.entries());
|
|
29
|
+
}
|
|
30
|
+
asMap() {
|
|
31
|
+
return new Map(this.entries());
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export const envVars = new EnvVars();
|
|
35
|
+
//# sourceMappingURL=environment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/ux/environment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAgBtC,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,6BAA6B,EAAE;QAC7B,WAAW,EAAE,iEAAiE;QAC9E,YAAY,EAAE,QAAQ;QACtB,YAAY,EAAE,EAAE;KACjB;CAC6D,CAAC;AAajE,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,GAAG;IACtC,YAAmB,GAAG,GAAG,OAAO,CAAC,GAAG;QAClC,KAAK,CAAC,GAAG,CAAC,CAAC;IACb,CAAC;IAEM,OAAO,CAAgC,QAAW;QACvD,MAAM,IAAI,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAC1C,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;YAC1B,KAAK,QAAQ;gBACX,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,YAAY,CAAiB,CAAC;YACzE,kBAAkB;YAClB,6EAA6E;YAC7E,iBAAiB;YACjB,4EAA4E;YAC5E;gBACE,MAAM;QACV,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEM,YAAY;QACjB,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5C,CAAC;IAEM,KAAK;QACV,OAAO,IAAI,GAAG,CAAkB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAClD,CAAC;CACF;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC"}
|
|
@@ -18,6 +18,14 @@ Source directory of the audit config to run.
|
|
|
18
18
|
|
|
19
19
|
Loads all classifications and policies from the directory and uses them to audit the org. Only policies that are enabled and that exist in the directory are executed.
|
|
20
20
|
|
|
21
|
+
# flags.verbose.summary
|
|
22
|
+
|
|
23
|
+
Don't truncate rule violation tables.
|
|
24
|
+
|
|
25
|
+
# flags.verbose.description
|
|
26
|
+
|
|
27
|
+
The default behavior truncates result tables of rule violations in terminal output, when they exceed a certain length. The default maximum length is 30 rows and can be configured in the environment variable `SAE_MAX_RESULT_VIOLATION_ROWS`. If this flag is present, the full violations table is printed. The JSON report is never truncated.
|
|
28
|
+
|
|
21
29
|
# examples
|
|
22
30
|
|
|
23
31
|
- Audit the org MyTargetOrg with the config in configs/prod
|
|
@@ -59,3 +67,7 @@ Failed to parse %s: %s.
|
|
|
59
67
|
# error.InvalidConfigFileSchema.actions
|
|
60
68
|
|
|
61
69
|
Verify that your config matches the expected schema.
|
|
70
|
+
|
|
71
|
+
# info.RemovedViolationRows
|
|
72
|
+
|
|
73
|
+
%s out of %s violations shown. See report for full results or use --verbose flag.
|
package/oclif.manifest.json
CHANGED
|
@@ -129,6 +129,7 @@
|
|
|
129
129
|
},
|
|
130
130
|
"source-dir": {
|
|
131
131
|
"char": "d",
|
|
132
|
+
"description": "Loads all classifications and policies from the directory and uses them to audit the org. Only policies that are enabled and that exist in the directory are executed.",
|
|
132
133
|
"name": "source-dir",
|
|
133
134
|
"required": false,
|
|
134
135
|
"summary": "Source directory of the audit config to run.",
|
|
@@ -143,6 +144,13 @@
|
|
|
143
144
|
"hasDynamicHelp": false,
|
|
144
145
|
"multiple": false,
|
|
145
146
|
"type": "option"
|
|
147
|
+
},
|
|
148
|
+
"verbose": {
|
|
149
|
+
"description": "The default behavior truncates result tables of rule violations in terminal output, when they exceed a certain length. The default maximum length is 30 rows and can be configured in the environment variable `SAE_MAX_RESULT_VIOLATION_ROWS`. If this flag is present, the full violations table is printed. The JSON report is never truncated.",
|
|
150
|
+
"name": "verbose",
|
|
151
|
+
"summary": "Don't truncate rule violation tables.",
|
|
152
|
+
"allowNo": false,
|
|
153
|
+
"type": "boolean"
|
|
146
154
|
}
|
|
147
155
|
},
|
|
148
156
|
"hasDynamicHelp": true,
|
|
@@ -251,5 +259,5 @@
|
|
|
251
259
|
]
|
|
252
260
|
}
|
|
253
261
|
},
|
|
254
|
-
"version": "0.
|
|
262
|
+
"version": "0.12.1"
|
|
255
263
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@j-schreiber/sf-cli-security-audit",
|
|
3
3
|
"description": "Salesforce CLI plugin to automate highly configurable security audits",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.12.1",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/j-schreiber/js-sf-cli-security-audit"
|