sf-plugin-permission-sets 0.0.0-dev.17 → 0.0.0-dev.19
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 +9 -5
- package/lib/adapters/connection-org-client.d.ts +11 -0
- package/lib/adapters/{org-client.js → connection-org-client.js} +3 -3
- package/lib/adapters/connection-org-client.js.map +1 -0
- package/lib/commands/ps/validate.js +1 -1
- package/lib/commands/ps/validate.js.map +1 -1
- package/lib/core/normalize.js +2 -2
- package/lib/core/normalize.js.map +1 -1
- package/lib/core/report.js +3 -4
- package/lib/core/report.js.map +1 -1
- package/lib/core/resolve.d.ts +1 -1
- package/lib/core/resolve.js +3 -3
- package/lib/core/resolve.js.map +1 -1
- package/lib/services/org-client.d.ts +11 -0
- package/lib/services/org-client.js +2 -0
- package/lib/services/org-client.js.map +1 -0
- package/lib/services/validate.d.ts +1 -1
- package/lib/services/validate.js +2 -2
- package/lib/services/validate.js.map +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +2 -2
- package/lib/adapters/org-client.d.ts +0 -20
- package/lib/adapters/org-client.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# sf-plugin-permission-sets
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/sf-plugin-permission-sets) [](https://npmjs.org/package/sf-plugin-permission-sets) [](https://raw.githubusercontent.com/zaclummys/sf-plugin-permission-sets/main/LICENSE.txt)
|
|
3
|
+
[](https://www.npmjs.com/package/sf-plugin-permission-sets) [](https://npmjs.org/package/sf-plugin-permission-sets) [](https://semver.org/#spec-item-4) [](https://raw.githubusercontent.com/zaclummys/sf-plugin-permission-sets/main/LICENSE.txt)
|
|
4
4
|
|
|
5
5
|
> Declarative, GitOps-style management of **permission set assignments** for Salesforce orgs.
|
|
6
6
|
> Define who gets what in version-controlled YAML. The plugin reconciles your org to match it: `plan` then `apply`, just like Terraform.
|
|
7
7
|
|
|
8
|
+
> ⚠️ **Under active development.** This plugin is `0.x`. Per [semver's major-version-zero rule](https://semver.org/#spec-item-4), anything (commands, flags, the YAML schema) may change in a breaking way between `0.x` releases. Pin a version in CI. The public API stabilizes at `v1.0.0`.
|
|
9
|
+
|
|
8
10
|
Stop clicking through Setup to grant access. Commit a YAML file, open a PR, let CI show the diff, and merge to apply. Your git history becomes the audit log of who-had-access-when.
|
|
9
11
|
|
|
10
12
|
---
|
|
@@ -321,6 +323,8 @@ Releases follow [semantic versioning](https://semver.org). Snapshots are automat
|
|
|
321
323
|
- Choosing the version bump (patch, minor, or major).
|
|
322
324
|
- Creating the GitHub Release, which is what triggers the publish above.
|
|
323
325
|
|
|
326
|
+
**While on `0.x`:** breaking changes may ship in **any** release, including minor bumps. The plugin is under active development and the public API is not yet stable. The table below describes the contract that takes effect at `v1.0.0`.
|
|
327
|
+
|
|
324
328
|
| Bump | When | Example tag |
|
|
325
329
|
| --- | --- | --- |
|
|
326
330
|
| patch | bug fix, no behavior change | `v0.1.1` |
|
|
@@ -346,9 +350,9 @@ The `next` tag is selected whenever the version contains a hyphen, not by GitHub
|
|
|
346
350
|
The plugin is layered so every command reuses the same core. Commands stay thin, services hold the orchestration, core holds the reusable primitives, and a thin adapter layer isolates the Salesforce SDK.
|
|
347
351
|
|
|
348
352
|
- **Commands** (`src/commands/ps/`): oclif only. They parse flags, construct the service (wiring in the org adapter when the command needs one), render output, and set the exit code.
|
|
349
|
-
- **Services** (`src/services/`): one per command (`check` and `validate` today, then `plan`, `apply`, `export`). Each is a class built from its dependencies and inputs, with a parameterless `run()` that turns the core into a command's behavior.
|
|
353
|
+
- **Services** (`src/services/`): one per command (`check` and `validate` today, then `plan`, `apply`, `export`). Each is a class built from its dependencies and inputs, with a parameterless `run()` that turns the core into a command's behavior. A service also declares the ports it needs from the outside, like the `OrgClient` interface its adapter implements.
|
|
350
354
|
- **Core** (`src/core/`): the reusable building blocks. Pure, with no `@salesforce/*` imports, so every piece is unit-testable on its own.
|
|
351
|
-
- **Adapters** (`src/adapters/`): the boundary to the outside world.
|
|
355
|
+
- **Adapters** (`src/adapters/`): the boundary to the outside world. `ConnectionOrgClient` implements the `OrgClient` port (declared in services) with a Salesforce `Connection`, and owns all the SOQL and SObject detail. Services depend on the port, not the SDK, so they test against a fake and stay free of connection detail.
|
|
352
356
|
|
|
353
357
|
| Core module | Responsibility |
|
|
354
358
|
| --- | --- |
|
|
@@ -357,10 +361,10 @@ The plugin is layered so every command reuses the same core. Commands stay thin,
|
|
|
357
361
|
| `parse` | File text to an object, with YAML and duplicate-key errors. |
|
|
358
362
|
| `normalize` | A validated file to canonical `(assignee, kind, target)` tuples, plus structural findings. |
|
|
359
363
|
| `load` | Expand globs, run parse then validate then normalize per file, and merge by union. |
|
|
360
|
-
| `resolve` |
|
|
364
|
+
| `resolve` | Pure rules that turn declared references and the org's answers into findings. No SOQL: the adapter owns that. |
|
|
361
365
|
| `report` | Format and count findings. |
|
|
362
366
|
|
|
363
|
-
Commands are slices of one pipeline. `check` runs the offline **load** stage only. `validate` adds **resolve**: it
|
|
367
|
+
Commands are slices of one pipeline. `check` runs the offline **load** stage only. `validate` adds **resolve**: it looks the declared references up through the `OrgClient` port (the adapter builds the SOQL) and evaluates the org's answers with resolve's pure rules. The remaining online commands layer **fetch** (current org state), **diff** (desired vs actual), and **apply** (DML) on top, reusing load, resolve, report, model, and schema unchanged.
|
|
364
368
|
|
|
365
369
|
## License
|
|
366
370
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Connection } from '@salesforce/core';
|
|
2
|
+
import { Kind, OrgUser } from '../core/model.js';
|
|
3
|
+
import { OrgClient } from '../services/org-client.js';
|
|
4
|
+
/** Adapter backing OrgClient with a Salesforce Connection. autoFetchQuery pages past 2000 rows. */
|
|
5
|
+
export declare class ConnectionOrgClient implements OrgClient {
|
|
6
|
+
private readonly connection;
|
|
7
|
+
constructor(connection: Connection);
|
|
8
|
+
findUsers(usernames: string[]): Promise<OrgUser[]>;
|
|
9
|
+
findTargets(kind: Kind, names: string[]): Promise<string[]>;
|
|
10
|
+
private query;
|
|
11
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** SObject + naming field per kind. The Salesforce schema knowledge lives here, not in core. */
|
|
2
|
-
const
|
|
2
|
+
const targetObjects = {
|
|
3
3
|
permissionSet: { sobject: 'PermissionSet', field: 'Name' },
|
|
4
4
|
permissionSetGroup: { sobject: 'PermissionSetGroup', field: 'DeveloperName' },
|
|
5
5
|
permissionSetLicense: { sobject: 'PermissionSetLicense', field: 'DeveloperName' },
|
|
@@ -23,7 +23,7 @@ export class ConnectionOrgClient {
|
|
|
23
23
|
return records.map((record) => ({ username: record.Username, isActive: record.IsActive }));
|
|
24
24
|
}
|
|
25
25
|
async findTargets(kind, names) {
|
|
26
|
-
const { sobject, field } =
|
|
26
|
+
const { sobject, field } = targetObjects[kind];
|
|
27
27
|
const records = await this.query(`SELECT ${field} FROM ${sobject} WHERE ${field} IN (${inList(names)})`);
|
|
28
28
|
return records.map((record) => record[field]);
|
|
29
29
|
}
|
|
@@ -32,4 +32,4 @@ export class ConnectionOrgClient {
|
|
|
32
32
|
return result.records;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
//# sourceMappingURL=org-client.js.map
|
|
35
|
+
//# sourceMappingURL=connection-org-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-org-client.js","sourceRoot":"","sources":["../../src/adapters/connection-org-client.ts"],"names":[],"mappings":"AAMA,gGAAgG;AAChG,MAAM,aAAa,GAA+B;IAC9C,aAAa,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE;IAC1D,kBAAkB,EAAE,EAAE,OAAO,EAAE,oBAAoB,EAAE,KAAK,EAAE,eAAe,EAAE;IAC7E,oBAAoB,EAAE,EAAE,OAAO,EAAE,sBAAsB,EAAE,KAAK,EAAE,eAAe,EAAE;CACpF,CAAC;AAEF,kEAAkE;AAClE,SAAS,WAAW,CAAC,KAAa;IAC9B,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC;AAED,+DAA+D;AAC/D,SAAS,MAAM,CAAC,MAAgB;IAC5B,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC;AAED,mGAAmG;AACnG,MAAM,OAAO,mBAAmB;IACQ;IAApC,YAAoC,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAEvD,KAAK,CAAC,SAAS,CAAC,SAAmB;QACtC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAC5B,0DAA0D,MAAM,CAAC,SAAS,CAAC,GAAG,CACjF,CAAC;QAEF,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC/F,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,IAAU,EAAE,KAAe;QAChD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAC5B,UAAU,KAAK,SAAS,OAAO,UAAU,KAAK,QAAQ,MAAM,CAAC,KAAK,CAAC,GAAG,CACzE,CAAC;QAEF,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAClD,CAAC;IAEO,KAAK,CAAC,KAAK,CAAI,IAAY;QAC/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC1D,OAAO,MAAM,CAAC,OAAyB,CAAC;IAC5C,CAAC;CACJ"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
2
2
|
import { Messages } from '@salesforce/core';
|
|
3
|
-
import { ConnectionOrgClient } from '../../adapters/org-client.js';
|
|
3
|
+
import { ConnectionOrgClient } from '../../adapters/connection-org-client.js';
|
|
4
4
|
import { ValidateService } from '../../services/validate.js';
|
|
5
5
|
import { formatFindings } from '../../core/report.js';
|
|
6
6
|
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/commands/ps/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/commands/ps/validate.ts"],"names":[],"mappings":"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"}
|
package/lib/core/normalize.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const kindKeys = [
|
|
2
2
|
['permissionSet', 'permissionSets'],
|
|
3
3
|
['permissionSetGroup', 'permissionSetGroups'],
|
|
4
4
|
['permissionSetLicense', 'permissionSetLicenses'],
|
|
@@ -12,7 +12,7 @@ export function normalize(data, file) {
|
|
|
12
12
|
const findings = [];
|
|
13
13
|
for (const [username, entry] of Object.entries(data.users)) {
|
|
14
14
|
let scopeCount = 0;
|
|
15
|
-
for (const [kind, key] of
|
|
15
|
+
for (const [kind, key] of kindKeys) {
|
|
16
16
|
const list = entry[key];
|
|
17
17
|
if (list === undefined)
|
|
18
18
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/core/normalize.ts"],"names":[],"mappings":"AAKA,MAAM,
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/core/normalize.ts"],"names":[],"mappings":"AAKA,MAAM,QAAQ,GAA4B;IACtC,CAAC,eAAe,EAAE,gBAAgB,CAAC;IACnC,CAAC,oBAAoB,EAAE,qBAAqB,CAAC;IAC7C,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;CACpD,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAe,EAAE,IAAY;IACnD,MAAM,WAAW,GAAwB,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAAc,EAAE,CAAC;IAE/B,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,QAAQ,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;YACxB,IAAI,IAAI,KAAK,SAAS;gBAAE,SAAS;YACjC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,QAAQ,KAAK,GAAG,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvG,SAAS;YACb,CAAC;YAED,UAAU,IAAI,CAAC,CAAC;YAChB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;YAC/B,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE,CAAC;gBACxB,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;oBACnB,QAAQ,CAAC,IAAI,CAAC;wBACV,KAAK,EAAE,SAAS;wBAChB,IAAI,EAAE,YAAY;wBAClB,OAAO,EAAE,GAAG,QAAQ,KAAK,MAAM,0BAA0B,GAAG,EAAE;wBAC9D,IAAI;qBACP,CAAC,CAAC;oBACH,SAAS;gBACb,CAAC;gBACD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACjB,WAAW,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YAC3D,CAAC;QACL,CAAC;QAED,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,QAAQ,sBAAsB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9G,CAAC;IACL,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;AACrC,CAAC"}
|
package/lib/core/report.js
CHANGED
|
@@ -7,9 +7,8 @@ export function formatFindings(findings) {
|
|
|
7
7
|
}
|
|
8
8
|
/** Count findings by level. */
|
|
9
9
|
export function countFindings(findings) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
};
|
|
10
|
+
const errors = findings.filter((finding) => finding.level === 'error');
|
|
11
|
+
const warnings = findings.filter((finding) => finding.level === 'warning');
|
|
12
|
+
return { errors: errors.length, warnings: warnings.length };
|
|
14
13
|
}
|
|
15
14
|
//# sourceMappingURL=report.js.map
|
package/lib/core/report.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/core/report.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,MAAM,UAAU,cAAc,CAAC,QAAmB;IAC9C,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9F,OAAO,GAAG,OAAO,CAAC,KAAK,KAAK,KAAK,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1D,CAAC,CAAC,CAAC;AACP,CAAC;AAED,+BAA+B;AAC/B,MAAM,UAAU,aAAa,CAAC,QAAmB;IAC7C,
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/core/report.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,MAAM,UAAU,cAAc,CAAC,QAAmB;IAC9C,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9F,OAAO,GAAG,OAAO,CAAC,KAAK,KAAK,KAAK,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1D,CAAC,CAAC,CAAC;AACP,CAAC;AAED,+BAA+B;AAC/B,MAAM,UAAU,aAAa,CAAC,QAAmB;IAC7C,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IAE3E,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;AAChE,CAAC"}
|
package/lib/core/resolve.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DesiredAssignment, Finding, Kind, OrgUser } from './model.js';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const kinds: Kind[];
|
|
3
3
|
/** The distinct usernames assigned across all assignments. */
|
|
4
4
|
export declare function distinctAssignees(assignments: DesiredAssignment[]): string[];
|
|
5
5
|
/** The distinct targets of one kind across all assignments. */
|
package/lib/core/resolve.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/** Human label per kind, used in findings. Domain wording, not SObject names. */
|
|
2
|
-
const
|
|
2
|
+
const kindLabels = {
|
|
3
3
|
permissionSet: 'permission set',
|
|
4
4
|
permissionSetGroup: 'permission set group',
|
|
5
5
|
permissionSetLicense: 'permission set license',
|
|
6
6
|
};
|
|
7
|
-
export const
|
|
7
|
+
export const kinds = Object.keys(kindLabels);
|
|
8
8
|
function distinct(values) {
|
|
9
9
|
return [...new Set(values)];
|
|
10
10
|
}
|
|
@@ -40,7 +40,7 @@ export function evaluateUsers(declared, found) {
|
|
|
40
40
|
* case-insensitive, mirroring how the org compares them.
|
|
41
41
|
*/
|
|
42
42
|
export function evaluateTargets(kind, declared, found) {
|
|
43
|
-
const label =
|
|
43
|
+
const label = kindLabels[kind];
|
|
44
44
|
const counts = new Map();
|
|
45
45
|
for (const name of found) {
|
|
46
46
|
const key = name.toLowerCase();
|
package/lib/core/resolve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/core/resolve.ts"],"names":[],"mappings":"AAEA,iFAAiF;AACjF,MAAM,
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/core/resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Kind, OrgUser } from '../core/model.js';
|
|
2
|
+
/**
|
|
3
|
+
* Port: the org lookups a service needs, in domain terms. Declared here, by the
|
|
4
|
+
* consumer, so services depend on the abstraction and the adapter implements it.
|
|
5
|
+
*/
|
|
6
|
+
export interface OrgClient {
|
|
7
|
+
/** The users that exist in the org, among the given usernames. */
|
|
8
|
+
findUsers(usernames: string[]): Promise<OrgUser[]>;
|
|
9
|
+
/** The identifiers that exist in the org, among the given targets of one kind. */
|
|
10
|
+
findTargets(kind: Kind, names: string[]): Promise<string[]>;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-client.js","sourceRoot":"","sources":["../../src/services/org-client.ts"],"names":[],"mappings":""}
|
package/lib/services/validate.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { loadFiles } from '../core/load.js';
|
|
2
2
|
import { countFindings } from '../core/report.js';
|
|
3
|
-
import {
|
|
3
|
+
import { kinds, distinctAssignees, distinctTargets, evaluateUsers, evaluateTargets } from '../core/resolve.js';
|
|
4
4
|
/** Online validate: run the offline load, then resolve every reference against the org. */
|
|
5
5
|
export class ValidateService {
|
|
6
6
|
org;
|
|
@@ -30,7 +30,7 @@ export class ValidateService {
|
|
|
30
30
|
if (usernames.length > 0) {
|
|
31
31
|
tasks.push(this.org.findUsers(usernames).then((found) => evaluateUsers(usernames, found)));
|
|
32
32
|
}
|
|
33
|
-
for (const kind of
|
|
33
|
+
for (const kind of kinds) {
|
|
34
34
|
const targets = distinctTargets(assignments, kind);
|
|
35
35
|
if (targets.length > 0) {
|
|
36
36
|
tasks.push(this.org.findTargets(kind, targets).then((found) => evaluateTargets(kind, targets, found)));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/services/validate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/services/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAa/G,2FAA2F;AAC3F,MAAM,OAAO,eAAe;IACY;IAAiC;IAArE,YAAoC,GAAc,EAAmB,KAAe;QAAhD,QAAG,GAAH,GAAG,CAAW;QAAmB,UAAK,GAAL,KAAK,CAAU;IAAG,CAAC;IAEjF,KAAK,CAAC,GAAG;QACZ,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEtD,MAAM,QAAQ,GAAG,CAAC,GAAG,MAAM,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,CAAC;QACjD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QAErD,OAAO;YACH,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,QAAQ;YACR,MAAM;YACN,QAAQ;YACR,MAAM,EAAE,MAAM,GAAG,CAAC;SACrB,CAAC;IACN,CAAC;IAED,iFAAiF;IACzE,KAAK,CAAC,OAAO,CAAC,WAAgC;QAClD,MAAM,KAAK,GAA8B,EAAE,CAAC;QAE5C,MAAM,SAAS,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACjD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/F,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,eAAe,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YACnD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;YAC3G,CAAC;QACL,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;CACJ"}
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sf-plugin-permission-sets",
|
|
3
|
-
"description": "",
|
|
3
|
+
"description": "Declarative permission set assignment management for Salesforce. Under active development, with breaking changes possible until v1.0.0.",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/zaclummys/sf-plugin-permission-sets.git"
|
|
@@ -133,5 +133,5 @@
|
|
|
133
133
|
"exports": "./lib/index.js",
|
|
134
134
|
"type": "module",
|
|
135
135
|
"author": "Isaac Ferreira",
|
|
136
|
-
"version": "0.0.0-dev.
|
|
136
|
+
"version": "0.0.0-dev.19"
|
|
137
137
|
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { Connection } from '@salesforce/core';
|
|
2
|
-
import { Kind, OrgUser } from '../core/model.js';
|
|
3
|
-
/**
|
|
4
|
-
* Port: the org lookups the app needs, in domain terms. Services depend on this,
|
|
5
|
-
* not on @salesforce/core or SOQL, so they stay easy to test and persistence-ignorant.
|
|
6
|
-
*/
|
|
7
|
-
export interface OrgClient {
|
|
8
|
-
/** The users that exist in the org, among the given usernames. */
|
|
9
|
-
findUsers(usernames: string[]): Promise<OrgUser[]>;
|
|
10
|
-
/** The identifiers that exist in the org, among the given targets of one kind. */
|
|
11
|
-
findTargets(kind: Kind, names: string[]): Promise<string[]>;
|
|
12
|
-
}
|
|
13
|
-
/** Adapter backing OrgClient with a Salesforce Connection. autoFetchQuery pages past 2000 rows. */
|
|
14
|
-
export declare class ConnectionOrgClient implements OrgClient {
|
|
15
|
-
private readonly connection;
|
|
16
|
-
constructor(connection: Connection);
|
|
17
|
-
findUsers(usernames: string[]): Promise<OrgUser[]>;
|
|
18
|
-
findTargets(kind: Kind, names: string[]): Promise<string[]>;
|
|
19
|
-
private query;
|
|
20
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"org-client.js","sourceRoot":"","sources":["../../src/adapters/org-client.ts"],"names":[],"mappings":"AAgBA,gGAAgG;AAChG,MAAM,cAAc,GAA+B;IAC/C,aAAa,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE;IAC1D,kBAAkB,EAAE,EAAE,OAAO,EAAE,oBAAoB,EAAE,KAAK,EAAE,eAAe,EAAE;IAC7E,oBAAoB,EAAE,EAAE,OAAO,EAAE,sBAAsB,EAAE,KAAK,EAAE,eAAe,EAAE;CACpF,CAAC;AAEF,kEAAkE;AAClE,SAAS,WAAW,CAAC,KAAa;IAC9B,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC;AAED,+DAA+D;AAC/D,SAAS,MAAM,CAAC,MAAgB;IAC5B,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC;AAED,mGAAmG;AACnG,MAAM,OAAO,mBAAmB;IACQ;IAApC,YAAoC,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAEvD,KAAK,CAAC,SAAS,CAAC,SAAmB;QACtC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAC5B,0DAA0D,MAAM,CAAC,SAAS,CAAC,GAAG,CACjF,CAAC;QAEF,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC/F,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,IAAU,EAAE,KAAe;QAChD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAC5B,UAAU,KAAK,SAAS,OAAO,UAAU,KAAK,QAAQ,MAAM,CAAC,KAAK,CAAC,GAAG,CACzE,CAAC;QAEF,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAClD,CAAC;IAEO,KAAK,CAAC,KAAK,CAAI,IAAY;QAC/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC1D,OAAO,MAAM,CAAC,OAAyB,CAAC;IAC5C,CAAC;CACJ"}
|