sf-plugin-permission-sets 0.0.0-dev.4 → 0.0.0-dev.41
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 +157 -93
- package/lib/adapters/connection-org-client.d.ts +17 -0
- package/lib/adapters/connection-org-client.d.ts.map +1 -0
- package/lib/adapters/connection-org-client.js +248 -0
- package/lib/adapters/connection-org-client.js.map +1 -0
- package/lib/adapters/index.d.ts +2 -0
- package/lib/adapters/index.d.ts.map +1 -0
- package/lib/adapters/index.js +2 -0
- package/lib/adapters/index.js.map +1 -0
- package/lib/commands/ps/apply.d.ts +30 -0
- package/lib/commands/ps/apply.d.ts.map +1 -0
- package/lib/commands/ps/apply.js +153 -0
- package/lib/commands/ps/apply.js.map +1 -0
- package/lib/commands/ps/check.d.ts +19 -0
- package/lib/commands/ps/check.d.ts.map +1 -0
- package/lib/commands/ps/check.js +49 -0
- package/lib/commands/ps/check.js.map +1 -0
- package/lib/commands/ps/export.d.ts +17 -0
- package/lib/commands/ps/export.d.ts.map +1 -0
- package/lib/commands/ps/export.js +32 -0
- package/lib/commands/ps/export.js.map +1 -0
- package/lib/commands/ps/plan.d.ts +51 -0
- package/lib/commands/ps/plan.d.ts.map +1 -0
- package/lib/commands/ps/plan.js +181 -0
- package/lib/commands/ps/plan.js.map +1 -0
- package/lib/commands/ps/validate.d.ts +19 -0
- package/lib/commands/ps/validate.d.ts.map +1 -0
- package/lib/commands/ps/validate.js +50 -0
- package/lib/commands/ps/validate.js.map +1 -0
- package/lib/core/diff.d.ts +10 -0
- package/lib/core/diff.d.ts.map +1 -0
- package/lib/core/diff.js +54 -0
- package/lib/core/diff.js.map +1 -0
- package/lib/core/finding.d.ts +41 -0
- package/lib/core/finding.d.ts.map +1 -0
- package/lib/core/finding.js +68 -0
- package/lib/core/finding.js.map +1 -0
- package/lib/core/index.d.ts +8 -0
- package/lib/core/index.d.ts.map +1 -0
- package/lib/core/index.js +7 -0
- package/lib/core/index.js.map +1 -0
- package/lib/core/load.d.ts +4 -0
- package/lib/core/load.d.ts.map +1 -0
- package/lib/core/load.js +60 -0
- package/lib/core/load.js.map +1 -0
- package/lib/core/model.d.ts +73 -0
- package/lib/core/model.d.ts.map +1 -0
- package/lib/core/model.js +2 -0
- package/lib/core/model.js.map +1 -0
- package/lib/core/normalize.d.ts +15 -0
- package/lib/core/normalize.d.ts.map +1 -0
- package/lib/core/normalize.js +62 -0
- package/lib/core/normalize.js.map +1 -0
- package/lib/core/parse.d.ts +10 -0
- package/lib/core/parse.d.ts.map +1 -0
- package/lib/core/parse.js +20 -0
- package/lib/core/parse.js.map +1 -0
- package/lib/core/report.d.ts +15 -0
- package/lib/core/report.d.ts.map +1 -0
- package/lib/core/report.js +114 -0
- package/lib/core/report.js.map +1 -0
- package/lib/core/resolve.d.ts +20 -0
- package/lib/core/resolve.d.ts.map +1 -0
- package/lib/core/resolve.js +88 -0
- package/lib/core/resolve.js.map +1 -0
- package/lib/core/schema.d.ts +23 -0
- package/lib/core/schema.d.ts.map +1 -0
- package/lib/core/schema.js +35 -0
- package/lib/core/schema.js.map +1 -0
- package/lib/core/serialize.d.ts +9 -0
- package/lib/core/serialize.d.ts.map +1 -0
- package/lib/core/serialize.js +34 -0
- package/lib/core/serialize.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/services/adapters/index.d.ts +2 -0
- package/lib/services/adapters/index.d.ts.map +1 -0
- package/lib/services/adapters/index.js +2 -0
- package/lib/services/adapters/index.js.map +1 -0
- package/lib/services/adapters/org-client.d.ts +22 -0
- package/lib/services/adapters/org-client.d.ts.map +1 -0
- package/lib/services/adapters/org-client.js +2 -0
- package/lib/services/adapters/org-client.js.map +1 -0
- package/lib/services/apply.d.ts +39 -0
- package/lib/services/apply.d.ts.map +1 -0
- package/lib/services/apply.js +102 -0
- package/lib/services/apply.js.map +1 -0
- package/lib/services/check.d.ts +14 -0
- package/lib/services/check.d.ts.map +1 -0
- package/lib/services/check.js +18 -0
- package/lib/services/check.js.map +1 -0
- package/lib/services/export.d.ts +13 -0
- package/lib/services/export.d.ts.map +1 -0
- package/lib/services/export.js +23 -0
- package/lib/services/export.js.map +1 -0
- package/lib/services/index.d.ts +6 -0
- package/lib/services/index.d.ts.map +1 -0
- package/lib/services/index.js +6 -0
- package/lib/services/index.js.map +1 -0
- package/lib/services/plan.d.ts +29 -0
- package/lib/services/plan.d.ts.map +1 -0
- package/lib/services/plan.js +45 -0
- package/lib/services/plan.js.map +1 -0
- package/lib/services/resolution.d.ts +15 -0
- package/lib/services/resolution.d.ts.map +1 -0
- package/lib/services/resolution.js +37 -0
- package/lib/services/resolution.js.map +1 -0
- package/lib/services/validate.d.ts +19 -0
- package/lib/services/validate.d.ts.map +1 -0
- package/lib/services/validate.js +42 -0
- package/lib/services/validate.js.map +1 -0
- package/messages/ps.apply.md +85 -0
- package/messages/ps.check.md +33 -0
- package/messages/ps.export.md +25 -0
- package/messages/ps.plan.md +85 -0
- package/messages/ps.validate.md +29 -0
- package/package.json +112 -181
- package/lib/commands/ps/info.d.ts +0 -11
- package/lib/commands/ps/info.js +0 -17
- package/lib/commands/ps/info.js.map +0 -1
- package/messages/ps.info.md +0 -17
- package/oclif.lock +0 -7781
- package/oclif.manifest.json +0 -51
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { kindKeys } from './normalize.js';
|
|
2
|
+
/** Human labels for the section headers, so the plan reads as prose, not YAML keys. */
|
|
3
|
+
const kindLabels = {
|
|
4
|
+
permissionSet: 'Permission Sets',
|
|
5
|
+
permissionSetGroup: 'Permission Set Groups',
|
|
6
|
+
permissionSetLicense: 'Permission Set Licenses',
|
|
7
|
+
};
|
|
8
|
+
function bucketFor(byKind, kind, target) {
|
|
9
|
+
let byTarget = byKind.get(kind);
|
|
10
|
+
if (!byTarget) {
|
|
11
|
+
byTarget = new Map();
|
|
12
|
+
byKind.set(kind, byTarget);
|
|
13
|
+
}
|
|
14
|
+
let bucket = byTarget.get(target);
|
|
15
|
+
if (!bucket) {
|
|
16
|
+
bucket = { adds: new Map(), updates: new Map(), removes: new Set(), unchanged: new Map() };
|
|
17
|
+
byTarget.set(target, bucket);
|
|
18
|
+
}
|
|
19
|
+
return bucket;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A canonical, readable form of an expiration instant, so values from the org and from the
|
|
23
|
+
* files display identically side by side. Falls back to the raw value if it cannot be parsed.
|
|
24
|
+
*/
|
|
25
|
+
function canonicalExpiration(value) {
|
|
26
|
+
const parsed = Date.parse(value);
|
|
27
|
+
if (Number.isNaN(parsed))
|
|
28
|
+
return value;
|
|
29
|
+
const instant = new Date(parsed);
|
|
30
|
+
return instant.toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
31
|
+
}
|
|
32
|
+
/** An assignee line suffixed with its expiration when there is one. */
|
|
33
|
+
function withExpiry(assignee, expiration) {
|
|
34
|
+
return expiration ? `${assignee} expires ${canonicalExpiration(expiration)}` : assignee;
|
|
35
|
+
}
|
|
36
|
+
/** An update line showing the expiration transition, with `never` standing in for no expiration. */
|
|
37
|
+
function withTransition(assignee, previous, next) {
|
|
38
|
+
const from = previous ? canonicalExpiration(previous) : 'never';
|
|
39
|
+
const to = next ? canonicalExpiration(next) : 'never';
|
|
40
|
+
return `${assignee} expires ${from} → ${to}`;
|
|
41
|
+
}
|
|
42
|
+
/** Group a diff into per-kind, per-target buckets, keeping only the operations the mode shows. */
|
|
43
|
+
function collectBuckets(diff, options) {
|
|
44
|
+
const showAdditive = options.mode !== 'destructive';
|
|
45
|
+
const showDestructive = options.mode !== 'additive';
|
|
46
|
+
const byKind = new Map();
|
|
47
|
+
if (showAdditive) {
|
|
48
|
+
for (const assignment of diff.toAdd) {
|
|
49
|
+
bucketFor(byKind, assignment.kind, assignment.target).adds.set(assignment.assignee, assignment.expiration);
|
|
50
|
+
}
|
|
51
|
+
for (const update of diff.toUpdate) {
|
|
52
|
+
bucketFor(byKind, update.kind, update.target).updates.set(update.assignee, {
|
|
53
|
+
previous: update.previousExpiration,
|
|
54
|
+
next: update.expiration,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (showDestructive) {
|
|
59
|
+
for (const assignment of diff.toRemove) {
|
|
60
|
+
bucketFor(byKind, assignment.kind, assignment.target).removes.add(assignment.assignee);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (options.showUnchanged) {
|
|
64
|
+
for (const assignment of diff.unchanged) {
|
|
65
|
+
bucketFor(byKind, assignment.kind, assignment.target).unchanged.set(assignment.assignee, assignment.expiration);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return byKind;
|
|
69
|
+
}
|
|
70
|
+
/** The `+`/`~`/`-`/`=` lines for one target, each group sorted by assignee. Empty when nothing shows. */
|
|
71
|
+
function renderBucket(bucket) {
|
|
72
|
+
const entries = [];
|
|
73
|
+
for (const assignee of [...bucket.adds.keys()].sort()) {
|
|
74
|
+
entries.push(` + ${withExpiry(assignee, bucket.adds.get(assignee))}`);
|
|
75
|
+
}
|
|
76
|
+
for (const assignee of [...bucket.updates.keys()].sort()) {
|
|
77
|
+
const change = bucket.updates.get(assignee);
|
|
78
|
+
entries.push(` ~ ${withTransition(assignee, change.previous, change.next)}`);
|
|
79
|
+
}
|
|
80
|
+
for (const assignee of [...bucket.removes].sort())
|
|
81
|
+
entries.push(` - ${assignee}`);
|
|
82
|
+
for (const assignee of [...bucket.unchanged.keys()].sort()) {
|
|
83
|
+
entries.push(` = ${withExpiry(assignee, bucket.unchanged.get(assignee))}`);
|
|
84
|
+
}
|
|
85
|
+
return entries;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Render a diff as a plan body, grouped by kind then target, with `+` adds, `~` expiration
|
|
89
|
+
* updates, `-` removes, and `=` unchanged. The mode scopes which operations appear (additive
|
|
90
|
+
* hides removes, destructive hides adds and updates), unchanged lines appear only when asked,
|
|
91
|
+
* and targets with nothing to show are omitted. Shared by plan and apply.
|
|
92
|
+
*/
|
|
93
|
+
export function formatDiff(diff, options) {
|
|
94
|
+
const byKind = collectBuckets(diff, options);
|
|
95
|
+
const lines = [];
|
|
96
|
+
for (const [kind] of kindKeys) {
|
|
97
|
+
const byTarget = byKind.get(kind);
|
|
98
|
+
if (!byTarget)
|
|
99
|
+
continue;
|
|
100
|
+
const sorted = [...byTarget].sort((left, right) => left[0].localeCompare(right[0]));
|
|
101
|
+
const targetLines = [];
|
|
102
|
+
for (const [target, bucket] of sorted) {
|
|
103
|
+
const entries = renderBucket(bucket);
|
|
104
|
+
if (entries.length === 0)
|
|
105
|
+
continue;
|
|
106
|
+
targetLines.push(` ${target}`, ...entries);
|
|
107
|
+
}
|
|
108
|
+
if (targetLines.length === 0)
|
|
109
|
+
continue;
|
|
110
|
+
lines.push(kindLabels[kind], ...targetLines);
|
|
111
|
+
}
|
|
112
|
+
return lines;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/core/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DesiredAssignment, Kind, OrgTarget, OrgUser } from './model.js';
|
|
2
|
+
import { Finding } from './finding.js';
|
|
3
|
+
export declare const kinds: Kind[];
|
|
4
|
+
/** The distinct usernames assigned across all assignments. */
|
|
5
|
+
export declare function distinctAssignees(assignments: DesiredAssignment[]): string[];
|
|
6
|
+
/** The distinct targets of one kind across all assignments. */
|
|
7
|
+
export declare function distinctTargets(assignments: DesiredAssignment[], kind: Kind): string[];
|
|
8
|
+
/** Every declared user must exist in the org and be active. */
|
|
9
|
+
export declare function evaluateUsers(declared: string[], found: OrgUser[]): Finding[];
|
|
10
|
+
/**
|
|
11
|
+
* Every declared target of one kind must resolve to exactly one record in the
|
|
12
|
+
* org. `found` is the list of matching identifiers the org returned; matching is
|
|
13
|
+
* case-insensitive, mirroring how the org compares them.
|
|
14
|
+
*/
|
|
15
|
+
export declare function evaluateTargets(kind: Kind, declared: string[], found: string[]): Finding[];
|
|
16
|
+
/** Index active users by lowercased username to their org id, for building assignments. */
|
|
17
|
+
export declare function indexUsersById(found: OrgUser[]): Map<string, string>;
|
|
18
|
+
/** Index targets by lowercased name to their org id, skipping names that resolve ambiguously. */
|
|
19
|
+
export declare function indexTargetsById(found: OrgTarget[]): Map<string, string>;
|
|
20
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/core/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,OAAO,EAAmF,MAAM,cAAc,CAAC;AASxH,eAAO,MAAM,KAAK,EAA8B,IAAI,EAAE,CAAC;AAMvD,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,iBAAiB,EAAE,GAAG,MAAM,EAAE,CAE5E;AAED,+DAA+D;AAC/D,wBAAgB,eAAe,CAAC,WAAW,EAAE,iBAAiB,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAItF;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAgB7E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAmB1F;AAED,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAQpE;AAED,iGAAiG;AACjG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAexE"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { userNotFoundError, userInactiveError, targetNotFoundError, targetAmbiguousError } from './finding.js';
|
|
2
|
+
/** Human label per kind, used in findings. Domain wording, not SObject names. */
|
|
3
|
+
const kindLabels = {
|
|
4
|
+
permissionSet: 'permission set',
|
|
5
|
+
permissionSetGroup: 'permission set group',
|
|
6
|
+
permissionSetLicense: 'permission set license',
|
|
7
|
+
};
|
|
8
|
+
export const kinds = Object.keys(kindLabels);
|
|
9
|
+
function distinct(values) {
|
|
10
|
+
return [...new Set(values)];
|
|
11
|
+
}
|
|
12
|
+
/** The distinct usernames assigned across all assignments. */
|
|
13
|
+
export function distinctAssignees(assignments) {
|
|
14
|
+
return distinct(assignments.map((assignment) => assignment.assignee));
|
|
15
|
+
}
|
|
16
|
+
/** The distinct targets of one kind across all assignments. */
|
|
17
|
+
export function distinctTargets(assignments, kind) {
|
|
18
|
+
return distinct(assignments.filter((assignment) => assignment.kind === kind).map((assignment) => assignment.target));
|
|
19
|
+
}
|
|
20
|
+
/** Every declared user must exist in the org and be active. */
|
|
21
|
+
export function evaluateUsers(declared, found) {
|
|
22
|
+
const byName = new Map();
|
|
23
|
+
for (const user of found) {
|
|
24
|
+
byName.set(user.username.toLowerCase(), user);
|
|
25
|
+
}
|
|
26
|
+
const findings = [];
|
|
27
|
+
for (const username of declared) {
|
|
28
|
+
const user = byName.get(username.toLowerCase());
|
|
29
|
+
if (!user) {
|
|
30
|
+
findings.push(userNotFoundError(username));
|
|
31
|
+
}
|
|
32
|
+
else if (!user.isActive) {
|
|
33
|
+
findings.push(userInactiveError(username));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return findings;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Every declared target of one kind must resolve to exactly one record in the
|
|
40
|
+
* org. `found` is the list of matching identifiers the org returned; matching is
|
|
41
|
+
* case-insensitive, mirroring how the org compares them.
|
|
42
|
+
*/
|
|
43
|
+
export function evaluateTargets(kind, declared, found) {
|
|
44
|
+
const label = kindLabels[kind];
|
|
45
|
+
const counts = new Map();
|
|
46
|
+
for (const name of found) {
|
|
47
|
+
const key = name.toLowerCase();
|
|
48
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
49
|
+
}
|
|
50
|
+
const findings = [];
|
|
51
|
+
for (const target of declared) {
|
|
52
|
+
const count = counts.get(target.toLowerCase()) ?? 0;
|
|
53
|
+
if (count === 0) {
|
|
54
|
+
findings.push(targetNotFoundError(target, label));
|
|
55
|
+
}
|
|
56
|
+
else if (count > 1) {
|
|
57
|
+
findings.push(targetAmbiguousError(target, label));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return findings;
|
|
61
|
+
}
|
|
62
|
+
/** Index active users by lowercased username to their org id, for building assignments. */
|
|
63
|
+
export function indexUsersById(found) {
|
|
64
|
+
const byName = new Map();
|
|
65
|
+
for (const user of found) {
|
|
66
|
+
if (user.isActive) {
|
|
67
|
+
byName.set(user.username.toLowerCase(), user.id);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return byName;
|
|
71
|
+
}
|
|
72
|
+
/** Index targets by lowercased name to their org id, skipping names that resolve ambiguously. */
|
|
73
|
+
export function indexTargetsById(found) {
|
|
74
|
+
const counts = new Map();
|
|
75
|
+
for (const target of found) {
|
|
76
|
+
const key = target.name.toLowerCase();
|
|
77
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
78
|
+
}
|
|
79
|
+
const byName = new Map();
|
|
80
|
+
for (const target of found) {
|
|
81
|
+
const key = target.name.toLowerCase();
|
|
82
|
+
if (counts.get(key) === 1) {
|
|
83
|
+
byName.set(key, target.id);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return byName;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/core/resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { Finding } from './finding.js';
|
|
3
|
+
declare const fileSchema: z.ZodObject<{
|
|
4
|
+
users: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
5
|
+
permissionSets: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
6
|
+
name: z.ZodString;
|
|
7
|
+
expiration: z.ZodISODateTime;
|
|
8
|
+
}, z.core.$strict>]>>>;
|
|
9
|
+
permissionSetGroups: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
10
|
+
name: z.ZodString;
|
|
11
|
+
expiration: z.ZodISODateTime;
|
|
12
|
+
}, z.core.$strict>]>>>;
|
|
13
|
+
permissionSetLicenses: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
14
|
+
}, z.core.$strict>>;
|
|
15
|
+
}, z.core.$strict>;
|
|
16
|
+
export type FileShape = z.infer<typeof fileSchema>;
|
|
17
|
+
/** Validate a parsed object against the file contract, turning issues into findings. */
|
|
18
|
+
export declare function validateFile(data: unknown, file: string): {
|
|
19
|
+
data?: FileShape;
|
|
20
|
+
findings: Finding[];
|
|
21
|
+
};
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAe,MAAM,cAAc,CAAC;AA4BpD,QAAA,MAAM,UAAU;;;;;;;;;;;;kBAEd,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEnD,wFAAwF;AACxF,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,CAUnG"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { schemaError } from './finding.js';
|
|
3
|
+
// The permission set name
|
|
4
|
+
const name = z.string().min(1);
|
|
5
|
+
// The permission set expiration date
|
|
6
|
+
const expiration = z.iso.datetime({ offset: true });
|
|
7
|
+
/** An entry is either a bare target name or a name with an expiration. */
|
|
8
|
+
const expiringList = z.array(z.union([
|
|
9
|
+
name,
|
|
10
|
+
z.strictObject({
|
|
11
|
+
name,
|
|
12
|
+
expiration,
|
|
13
|
+
}),
|
|
14
|
+
]));
|
|
15
|
+
/** Licenses cannot expire (PermissionSetLicenseAssign has no ExpirationDate), so names only. */
|
|
16
|
+
const plainList = z.array(name);
|
|
17
|
+
const userEntrySchema = z.strictObject({
|
|
18
|
+
permissionSets: expiringList.optional(),
|
|
19
|
+
permissionSetGroups: expiringList.optional(),
|
|
20
|
+
permissionSetLicenses: plainList.optional(),
|
|
21
|
+
});
|
|
22
|
+
const fileSchema = z.strictObject({
|
|
23
|
+
users: z.record(z.string().min(1), userEntrySchema),
|
|
24
|
+
});
|
|
25
|
+
/** Validate a parsed object against the file contract, turning issues into findings. */
|
|
26
|
+
export function validateFile(data, file) {
|
|
27
|
+
const parsed = fileSchema.safeParse(data);
|
|
28
|
+
if (parsed.success) {
|
|
29
|
+
return { data: parsed.data, findings: [] };
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
findings: parsed.error.issues.map((issue) => schemaError(issue.path.join('.') || '(root)', issue.message, file)),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAW,WAAW,EAAE,MAAM,cAAc,CAAC;AAEpD,0BAA0B;AAC1B,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAE/B,qCAAqC;AACrC,MAAM,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAEpD,0EAA0E;AAC1E,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CACxB,CAAC,CAAC,KAAK,CAAC;IACJ,IAAI;IACJ,CAAC,CAAC,YAAY,CAAC;QACX,IAAI;QACJ,UAAU;KACb,CAAC;CACL,CAAC,CACL,CAAC;AAEF,gGAAgG;AAChG,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAEhC,MAAM,eAAe,GAAG,CAAC,CAAC,YAAY,CAAC;IACnC,cAAc,EAAE,YAAY,CAAC,QAAQ,EAAE;IACvC,mBAAmB,EAAE,YAAY,CAAC,QAAQ,EAAE;IAC5C,qBAAqB,EAAE,SAAS,CAAC,QAAQ,EAAE;CAC9C,CAAC,CAAC;AAEH,MAAM,UAAU,GAAG,CAAC,CAAC,YAAY,CAAC;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC;CACtD,CAAC,CAAC;AAIH,wFAAwF;AACxF,MAAM,UAAU,YAAY,CAAC,IAAa,EAAE,IAAY;IACpD,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC/C,CAAC;IACD,OAAO;QACH,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACxC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CACrE;KACJ,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DesiredAssignment } from './model.js';
|
|
2
|
+
/**
|
|
3
|
+
* Emit canonical assignments back to a user-keyed YAML document: the inverse of
|
|
4
|
+
* normalize. Usernames and targets are sorted and de-duplicated so the output is
|
|
5
|
+
* deterministic, empty scopes are omitted, and an assignment with an expiration
|
|
6
|
+
* is written as the object form so it round-trips through the schema.
|
|
7
|
+
*/
|
|
8
|
+
export declare function serializeAssignments(assignments: DesiredAssignment[]): string;
|
|
9
|
+
//# sourceMappingURL=serialize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/core/serialize.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAS/C;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAiC7E"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { stringify } from 'yaml';
|
|
2
|
+
import { kindKeys } from './normalize.js';
|
|
3
|
+
/**
|
|
4
|
+
* Emit canonical assignments back to a user-keyed YAML document: the inverse of
|
|
5
|
+
* normalize. Usernames and targets are sorted and de-duplicated so the output is
|
|
6
|
+
* deterministic, empty scopes are omitted, and an assignment with an expiration
|
|
7
|
+
* is written as the object form so it round-trips through the schema.
|
|
8
|
+
*/
|
|
9
|
+
export function serializeAssignments(assignments) {
|
|
10
|
+
const usernames = [...new Set(assignments.map((assignment) => assignment.assignee))].sort();
|
|
11
|
+
const users = {};
|
|
12
|
+
for (const username of usernames) {
|
|
13
|
+
const entry = {};
|
|
14
|
+
for (const [kind, key] of kindKeys) {
|
|
15
|
+
const matching = assignments.filter((assignment) => assignment.assignee === username && assignment.kind === kind);
|
|
16
|
+
const expirationByTarget = new Map();
|
|
17
|
+
for (const assignment of matching) {
|
|
18
|
+
if (!expirationByTarget.has(assignment.target)) {
|
|
19
|
+
expirationByTarget.set(assignment.target, assignment.expiration);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const entries = [...expirationByTarget.keys()].sort().map((target) => {
|
|
23
|
+
const expiration = expirationByTarget.get(target);
|
|
24
|
+
return expiration ? { name: target, expiration } : target;
|
|
25
|
+
});
|
|
26
|
+
if (entries.length > 0) {
|
|
27
|
+
entry[key] = entries;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
users[username] = entry;
|
|
31
|
+
}
|
|
32
|
+
return stringify({ users });
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=serialize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize.js","sourceRoot":"","sources":["../../src/core/serialize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,EAAE,QAAQ,EAAY,MAAM,gBAAgB,CAAC;AAQpD;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAgC;IACjE,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5F,MAAM,KAAK,GAAwB,EAAE,CAAC;IAEtC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAgC,EAAE,CAAC;QAE9C,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,QAAQ,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAC/B,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,KAAK,IAAI,CAC/E,CAAC;YAEF,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAA8B,CAAC;YACjE,KAAK,MAAM,UAAU,IAAI,QAAQ,EAAE,CAAC;gBAChC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC7C,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;gBACrE,CAAC;YACL,CAAC;YAED,MAAM,OAAO,GAAsB,CAAC,GAAG,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;gBACpF,MAAM,UAAU,GAAG,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAClD,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;YAC9D,CAAC,CAAC,CAAC;YAEH,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;YACzB,CAAC;QACL,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC;IAC5B,CAAC;IAED,OAAO,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAChC,CAAC"}
|
package/lib/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,wBAAkB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/adapters/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ActualAssignment, AssignmentOutcome, AssignmentUpdate, DesiredAssignment, Kind, OrgTarget, OrgUser, ResolvedAddition, TargetRef } from '../../core/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Port: the org operations 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 targets (with ids) that exist in the org, among the given names of one kind. */
|
|
10
|
+
findTargets(kind: Kind, names: string[]): Promise<OrgTarget[]>;
|
|
11
|
+
/** Every assignable permission set, group, and license assignment held by active users. */
|
|
12
|
+
listAssignments(): Promise<DesiredAssignment[]>;
|
|
13
|
+
/** The current assignments of the given managed targets, with their record ids. */
|
|
14
|
+
currentAssignments(targets: TargetRef[]): Promise<ActualAssignment[]>;
|
|
15
|
+
/** Insert the given assignments, reporting per-record success or failure. */
|
|
16
|
+
addAssignments(additions: ResolvedAddition[]): Promise<AssignmentOutcome[]>;
|
|
17
|
+
/** Update the expiration of the given assignments, reporting per-record success or failure. */
|
|
18
|
+
updateAssignments(updates: AssignmentUpdate[]): Promise<AssignmentOutcome[]>;
|
|
19
|
+
/** Delete the given assignments by record id, reporting per-record success or failure. */
|
|
20
|
+
removeAssignments(removals: ActualAssignment[]): Promise<AssignmentOutcome[]>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=org-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-client.d.ts","sourceRoot":"","sources":["../../../src/services/adapters/org-client.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,IAAI,EACJ,SAAS,EACT,OAAO,EACP,gBAAgB,EAChB,SAAS,EACZ,MAAM,qBAAqB,CAAC;AAE7B;;;GAGG;AACH,MAAM,WAAW,SAAS;IACtB,kEAAkE;IAClE,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACnD,uFAAuF;IACvF,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAC/D,2FAA2F;IAC3F,eAAe,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAChD,mFAAmF;IACnF,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACtE,6EAA6E;IAC7E,cAAc,CAAC,SAAS,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC5E,+FAA+F;IAC/F,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC7E,0FAA0F;IAC1F,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC;CACjF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-client.js","sourceRoot":"","sources":["../../../src/services/adapters/org-client.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { AssignmentOutcome, Diff, Finding } from '../core/index.js';
|
|
2
|
+
import { OrgClient } from './adapters/index.js';
|
|
3
|
+
export type ApplyMode = 'additive' | 'destructive' | 'sync';
|
|
4
|
+
/** How the service asks its caller to approve a destructive batch before applying it. */
|
|
5
|
+
export type ConfirmDeletions = (count: number) => Promise<boolean>;
|
|
6
|
+
export type ApplyInput = {
|
|
7
|
+
mode: ApplyMode;
|
|
8
|
+
maxDeletes: number;
|
|
9
|
+
dryRun: boolean;
|
|
10
|
+
};
|
|
11
|
+
/** How a run ended, so the command can report and set the exit code. */
|
|
12
|
+
export type ApplyStatus = 'applied' | 'dry-run' | 'declined' | 'max-deletes-exceeded' | 'invalid';
|
|
13
|
+
export type ApplyResult = {
|
|
14
|
+
files: string[];
|
|
15
|
+
findings: Finding[];
|
|
16
|
+
diff: Diff;
|
|
17
|
+
/** What the chosen mode did not act on (surfaced as drift). */
|
|
18
|
+
drift: {
|
|
19
|
+
adds: number;
|
|
20
|
+
updates: number;
|
|
21
|
+
removes: number;
|
|
22
|
+
};
|
|
23
|
+
outcomes: AssignmentOutcome[];
|
|
24
|
+
status: ApplyStatus;
|
|
25
|
+
failed: boolean;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Online apply: load the files, resolve every reference to an org id, diff against
|
|
29
|
+
* the org's current state, then add and/or remove per the mode. Deletions are
|
|
30
|
+
* capped by maxDeletes and gated by an injected confirmation.
|
|
31
|
+
*/
|
|
32
|
+
export declare class ApplyService {
|
|
33
|
+
private readonly org;
|
|
34
|
+
private readonly confirmDeletions;
|
|
35
|
+
constructor(org: OrgClient, confirmDeletions: ConfirmDeletions);
|
|
36
|
+
run(files: string[], input: ApplyInput): Promise<ApplyResult>;
|
|
37
|
+
private execute;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=apply.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/services/apply.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,iBAAiB,EAGjB,IAAI,EAEJ,OAAO,EAEV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,aAAa,GAAG,MAAM,CAAC;AAE5D,yFAAyF;AACzF,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEnE,MAAM,MAAM,UAAU,GAAG;IACrB,IAAI,EAAE,SAAS,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,wEAAwE;AACxE,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,sBAAsB,GAAG,SAAS,CAAC;AAElG,MAAM,MAAM,WAAW,GAAG;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,IAAI,EAAE,IAAI,CAAC;IACX,+DAA+D;IAC/D,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1D,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CACnB,CAAC;AAqCF;;;;GAIG;AACH,qBAAa,YAAY;IAEjB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;gBADhB,GAAG,EAAE,SAAS,EACd,gBAAgB,EAAE,gBAAgB;IAG1C,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;YAqD5D,OAAO;CAwBxB"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { loadFiles, diffAssignments, countFindings, } from '../core/index.js';
|
|
2
|
+
import { ResolutionService, managedTargets } from './resolution.js';
|
|
3
|
+
const emptyDiff = { toAdd: [], toUpdate: [], toRemove: [], unchanged: [] };
|
|
4
|
+
/** An aborted-before-any-change result, carrying the findings that explain why. */
|
|
5
|
+
function invalidResult(files, findings) {
|
|
6
|
+
return {
|
|
7
|
+
files,
|
|
8
|
+
findings,
|
|
9
|
+
diff: emptyDiff,
|
|
10
|
+
drift: { adds: 0, updates: 0, removes: 0 },
|
|
11
|
+
outcomes: [],
|
|
12
|
+
status: 'invalid',
|
|
13
|
+
failed: true,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** Scope a diff to what the mode acts on, plus the drift (what it deliberately leaves alone). */
|
|
17
|
+
function planForMode(diff, mode) {
|
|
18
|
+
const additions = mode === 'destructive' ? [] : diff.toAdd;
|
|
19
|
+
const updates = mode === 'destructive' ? [] : diff.toUpdate;
|
|
20
|
+
const removals = mode === 'additive' ? [] : diff.toRemove;
|
|
21
|
+
const drift = {
|
|
22
|
+
adds: mode === 'destructive' ? diff.toAdd.length : 0,
|
|
23
|
+
updates: mode === 'destructive' ? diff.toUpdate.length : 0,
|
|
24
|
+
removes: mode === 'additive' ? diff.toRemove.length : 0,
|
|
25
|
+
};
|
|
26
|
+
return { additions, updates, removals, drift };
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Online apply: load the files, resolve every reference to an org id, diff against
|
|
30
|
+
* the org's current state, then add and/or remove per the mode. Deletions are
|
|
31
|
+
* capped by maxDeletes and gated by an injected confirmation.
|
|
32
|
+
*/
|
|
33
|
+
export class ApplyService {
|
|
34
|
+
org;
|
|
35
|
+
confirmDeletions;
|
|
36
|
+
constructor(org, confirmDeletions) {
|
|
37
|
+
this.org = org;
|
|
38
|
+
this.confirmDeletions = confirmDeletions;
|
|
39
|
+
}
|
|
40
|
+
async run(files, input) {
|
|
41
|
+
const loaded = await loadFiles(files);
|
|
42
|
+
const loadCounts = countFindings(loaded.findings);
|
|
43
|
+
if (loadCounts.errors > 0) {
|
|
44
|
+
return invalidResult(loaded.files, loaded.findings);
|
|
45
|
+
}
|
|
46
|
+
const resolutionService = new ResolutionService(this.org);
|
|
47
|
+
const resolution = await resolutionService.run(loaded.assignments);
|
|
48
|
+
const findings = [
|
|
49
|
+
...loaded.findings,
|
|
50
|
+
...resolution.findings,
|
|
51
|
+
];
|
|
52
|
+
const findingCounts = countFindings(findings);
|
|
53
|
+
if (findingCounts.errors > 0) {
|
|
54
|
+
return invalidResult(loaded.files, findings);
|
|
55
|
+
}
|
|
56
|
+
const actual = await this.org.currentAssignments(managedTargets(resolution));
|
|
57
|
+
const diff = diffAssignments(loaded.assignments, actual);
|
|
58
|
+
const { mode, maxDeletes, dryRun } = input;
|
|
59
|
+
const { additions, updates, removals, drift } = planForMode(diff, mode);
|
|
60
|
+
if (removals.length > maxDeletes) {
|
|
61
|
+
return {
|
|
62
|
+
files: loaded.files,
|
|
63
|
+
findings,
|
|
64
|
+
diff,
|
|
65
|
+
drift,
|
|
66
|
+
outcomes: [],
|
|
67
|
+
status: 'max-deletes-exceeded',
|
|
68
|
+
failed: true,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (dryRun) {
|
|
72
|
+
return { files: loaded.files, findings, diff, drift, outcomes: [], status: 'dry-run', failed: false };
|
|
73
|
+
}
|
|
74
|
+
if (removals.length > 0) {
|
|
75
|
+
const confirmed = await this.confirmDeletions(removals.length);
|
|
76
|
+
if (!confirmed) {
|
|
77
|
+
return { files: loaded.files, findings, diff, drift, outcomes: [], status: 'declined', failed: false };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const outcomes = await this.execute(additions, updates, removals, resolution);
|
|
81
|
+
const failed = outcomes.some((outcome) => !outcome.success);
|
|
82
|
+
return { files: loaded.files, findings, diff, drift, outcomes, status: 'applied', failed };
|
|
83
|
+
}
|
|
84
|
+
async execute(additions, updates, removals, resolution) {
|
|
85
|
+
const resolved = additions.map((addition) => ({
|
|
86
|
+
...addition,
|
|
87
|
+
assigneeId: resolution.userIds.get(addition.assignee.toLowerCase()) ?? '',
|
|
88
|
+
targetId: resolution.targetIds[addition.kind].get(addition.target.toLowerCase()) ?? '',
|
|
89
|
+
}));
|
|
90
|
+
const [added, updated, removed] = await Promise.all([
|
|
91
|
+
resolved.length > 0 ? this.org.addAssignments(resolved) : Promise.resolve([]),
|
|
92
|
+
updates.length > 0 ? this.org.updateAssignments(updates) : Promise.resolve([]),
|
|
93
|
+
removals.length > 0 ? this.org.removeAssignments(removals) : Promise.resolve([]),
|
|
94
|
+
]);
|
|
95
|
+
return [
|
|
96
|
+
...added,
|
|
97
|
+
...updated,
|
|
98
|
+
...removed,
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/services/apply.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DesiredAssignment, Finding } from '../core/index.js';
|
|
2
|
+
export type CheckResult = {
|
|
3
|
+
files: string[];
|
|
4
|
+
assignments: DesiredAssignment[];
|
|
5
|
+
findings: Finding[];
|
|
6
|
+
errors: number;
|
|
7
|
+
warnings: number;
|
|
8
|
+
failed: boolean;
|
|
9
|
+
};
|
|
10
|
+
/** Offline check: load the files, validate them, and summarize the findings. */
|
|
11
|
+
export declare class CheckService {
|
|
12
|
+
run(files: string[], strict: boolean): Promise<CheckResult>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/services/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,iBAAiB,EAAE,OAAO,EAAiB,MAAM,kBAAkB,CAAC;AAExF,MAAM,MAAM,WAAW,GAAG;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,gFAAgF;AAChF,qBAAa,YAAY;IACR,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;CAc3E"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { loadFiles, countFindings } from '../core/index.js';
|
|
2
|
+
/** Offline check: load the files, validate them, and summarize the findings. */
|
|
3
|
+
export class CheckService {
|
|
4
|
+
async run(files, strict) {
|
|
5
|
+
const loaded = await loadFiles(files);
|
|
6
|
+
const { errors, warnings } = countFindings(loaded.findings);
|
|
7
|
+
const failed = errors > 0 || (strict && warnings > 0);
|
|
8
|
+
return {
|
|
9
|
+
files: loaded.files,
|
|
10
|
+
assignments: loaded.assignments,
|
|
11
|
+
findings: loaded.findings,
|
|
12
|
+
errors,
|
|
13
|
+
warnings,
|
|
14
|
+
failed,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/services/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA8B,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAWxF,gFAAgF;AAChF,MAAM,OAAO,YAAY;IACd,KAAK,CAAC,GAAG,CAAC,KAAe,EAAE,MAAe;QAC7C,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC;QAEtD,OAAO;YACH,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM;YACN,QAAQ;YACR,MAAM;SACT,CAAC;IACN,CAAC;CACJ"}
|