sf-plugin-permission-sets 0.0.0-dev.6 → 0.0.0-dev.60
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.md +28 -0
- package/README.md +243 -85
- package/lib/adapters/connection-org-client.d.ts +21 -0
- package/lib/adapters/connection-org-client.d.ts.map +1 -0
- package/lib/adapters/connection-org-client.js +265 -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 +41 -0
- package/lib/commands/ps/apply.d.ts.map +1 -0
- package/lib/commands/ps/apply.js +178 -0
- package/lib/commands/ps/apply.js.map +1 -0
- package/lib/commands/ps/check.d.ts +21 -0
- package/lib/commands/ps/check.d.ts.map +1 -0
- package/lib/commands/ps/check.js +55 -0
- package/lib/commands/ps/check.js.map +1 -0
- package/lib/commands/ps/export.d.ts +26 -0
- package/lib/commands/ps/export.d.ts.map +1 -0
- package/lib/commands/ps/export.js +74 -0
- package/lib/commands/ps/export.js.map +1 -0
- package/lib/commands/ps/plan.d.ts +61 -0
- package/lib/commands/ps/plan.d.ts.map +1 -0
- package/lib/commands/ps/plan.js +212 -0
- package/lib/commands/ps/plan.js.map +1 -0
- package/lib/commands/ps/validate.d.ts +21 -0
- package/lib/commands/ps/validate.d.ts.map +1 -0
- package/lib/commands/ps/validate.js +56 -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 +76 -0
- package/lib/core/finding.js.map +1 -0
- package/lib/core/index.d.ts +10 -0
- package/lib/core/index.d.ts.map +1 -0
- package/lib/core/index.js +9 -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/mode.d.ts +18 -0
- package/lib/core/mode.d.ts.map +1 -0
- package/lib/core/mode.js +16 -0
- package/lib/core/mode.js.map +1 -0
- package/lib/core/model.d.ts +78 -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 +17 -0
- package/lib/core/normalize.d.ts.map +1 -0
- package/lib/core/normalize.js +72 -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 +122 -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 +36 -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 +85 -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 +19 -0
- package/lib/services/export.d.ts.map +1 -0
- package/lib/services/export.js +29 -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 +51 -0
- package/lib/services/plan.js.map +1 -0
- package/lib/services/resolution.d.ts +17 -0
- package/lib/services/resolution.d.ts.map +1 -0
- package/lib/services/resolution.js +48 -0
- package/lib/services/resolution.js.map +1 -0
- package/lib/services/validate.d.ts +21 -0
- package/lib/services/validate.d.ts.map +1 -0
- package/lib/services/validate.js +50 -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 +45 -0
- package/messages/ps.plan.md +85 -0
- package/messages/ps.validate.md +29 -0
- package/package.json +115 -180
- 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,76 @@
|
|
|
1
|
+
/** Construct an error-level finding. Private: callers use the named constructors below. */
|
|
2
|
+
function error(code, message, where = {}) {
|
|
3
|
+
return { level: 'error', code, message, ...where };
|
|
4
|
+
}
|
|
5
|
+
/** Construct a warning-level finding. Private: callers use the named constructors below. */
|
|
6
|
+
function warning(code, message, where = {}) {
|
|
7
|
+
return { level: 'warning', code, message, ...where };
|
|
8
|
+
}
|
|
9
|
+
// Findings raised while reading and structurally checking a file.
|
|
10
|
+
/** Invalid YAML: the parser rejected the document. */
|
|
11
|
+
export function yamlError(message, file, line) {
|
|
12
|
+
return error('YAML', message, { file, line });
|
|
13
|
+
}
|
|
14
|
+
/** The document parsed to nothing. */
|
|
15
|
+
export function emptyFileWarning(file) {
|
|
16
|
+
return warning('EMPTY_FILE', 'file is empty', { file });
|
|
17
|
+
}
|
|
18
|
+
/** The file violates the schema at `path`. */
|
|
19
|
+
export function schemaError(path, message, file) {
|
|
20
|
+
return error('SCHEMA', `${path}: ${message}`, { file });
|
|
21
|
+
}
|
|
22
|
+
/** A scope key is present but its list is empty. */
|
|
23
|
+
export function emptyListWarning(username, scopeKey, file) {
|
|
24
|
+
return warning('EMPTY_LIST', `${username}: ${scopeKey} is empty`, { file });
|
|
25
|
+
}
|
|
26
|
+
/** A target appears more than once under one scope for one user. */
|
|
27
|
+
export function dupTargetWarning(username, target, scopeKey, file) {
|
|
28
|
+
return warning('DUP_TARGET', `${username}: ${target} is listed twice under ${scopeKey}`, { file });
|
|
29
|
+
}
|
|
30
|
+
/** A user declares no scopes at all. */
|
|
31
|
+
export function emptyUserWarning(username, file) {
|
|
32
|
+
return warning('EMPTY_USER', `${username}: no scopes declared`, { file });
|
|
33
|
+
}
|
|
34
|
+
/** No file on disk matched the given glob patterns. */
|
|
35
|
+
export function noFilesError(patterns) {
|
|
36
|
+
return error('NO_FILES', `no files matched: ${patterns.join(', ')}`);
|
|
37
|
+
}
|
|
38
|
+
// Org-side findings, raised while resolving declarations against the org. No file or line.
|
|
39
|
+
/** A declared user does not exist in the org. */
|
|
40
|
+
export function userNotFoundError(username) {
|
|
41
|
+
return error('USER_NOT_FOUND', `${username}: user not found in org`);
|
|
42
|
+
}
|
|
43
|
+
/** A declared user exists but is inactive. */
|
|
44
|
+
export function userInactiveError(username) {
|
|
45
|
+
return error('USER_INACTIVE', `${username}: user is inactive`);
|
|
46
|
+
}
|
|
47
|
+
/** A declared target does not exist in the org. `label` is the kind's human name. */
|
|
48
|
+
export function targetNotFoundError(target, label) {
|
|
49
|
+
return error('TARGET_NOT_FOUND', `${target}: ${label} not found in org`);
|
|
50
|
+
}
|
|
51
|
+
/** A declared target resolves to more than one record in the org. */
|
|
52
|
+
export function targetAmbiguousError(target, label) {
|
|
53
|
+
return error('TARGET_AMBIGUOUS', `${target}: ${label} is not unique in org`);
|
|
54
|
+
}
|
|
55
|
+
/** The trailing-space location prefix for a finding: `file:line `, `file `, or empty. */
|
|
56
|
+
function locationPrefix(finding) {
|
|
57
|
+
if (!finding.file)
|
|
58
|
+
return '';
|
|
59
|
+
if (!finding.line)
|
|
60
|
+
return `${finding.file} `;
|
|
61
|
+
return `${finding.file}:${finding.line} `;
|
|
62
|
+
}
|
|
63
|
+
/** Render findings as human-readable lines. Shared by check, validate, and apply. */
|
|
64
|
+
export function formatFindings(findings) {
|
|
65
|
+
return findings.map((finding) => {
|
|
66
|
+
const where = locationPrefix(finding);
|
|
67
|
+
return `${finding.level}: ${where}${finding.message}`;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/** Count findings by level. */
|
|
71
|
+
export function countFindings(findings) {
|
|
72
|
+
const errors = findings.filter((finding) => finding.level === 'error');
|
|
73
|
+
const warnings = findings.filter((finding) => finding.level === 'warning');
|
|
74
|
+
return { errors: errors.length, warnings: warnings.length };
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=finding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding.js","sourceRoot":"","sources":["../../src/core/finding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { diffAssignments } from './diff.js';
|
|
2
|
+
export { Finding, formatFindings, countFindings } from './finding.js';
|
|
3
|
+
export { loadFiles } from './load.js';
|
|
4
|
+
export { ActualAssignment, AssignmentFilter, AssignmentOutcome, AssignmentUpdate, DesiredAssignment, Diff, Kind, OrgTarget, OrgUser, ReconcileMode, ResolvedAddition, TargetRef, } from './model.js';
|
|
5
|
+
export { scopeToMode, ScopedChange } from './mode.js';
|
|
6
|
+
export { kindForScopeKey } from './normalize.js';
|
|
7
|
+
export { formatDiff } from './report.js';
|
|
8
|
+
export { kinds, distinctAssignees, distinctTargets, evaluateUsers, evaluateTargets, indexUsersById, indexTargetsById, } from './resolve.js';
|
|
9
|
+
export { serializeAssignments } from './serialize.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,OAAO,EACP,aAAa,EACb,gBAAgB,EAChB,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,KAAK,EACL,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { diffAssignments } from './diff.js';
|
|
2
|
+
export { formatFindings, countFindings } from './finding.js';
|
|
3
|
+
export { loadFiles } from './load.js';
|
|
4
|
+
export { scopeToMode } from './mode.js';
|
|
5
|
+
export { kindForScopeKey } from './normalize.js';
|
|
6
|
+
export { formatDiff } from './report.js';
|
|
7
|
+
export { kinds, distinctAssignees, distinctTargets, evaluateUsers, evaluateTargets, indexUsersById, indexTargetsById, } from './resolve.js';
|
|
8
|
+
export { serializeAssignments } from './serialize.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAW,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAetC,OAAO,EAAE,WAAW,EAAgB,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,KAAK,EACL,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,EACd,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/core/load.ts"],"names":[],"mappings":"AAKA,OAAO,EAAqB,UAAU,EAAE,MAAM,YAAY,CAAC;AAgC3D,oFAAoF;AACpF,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CA+BvE"}
|
package/lib/core/load.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { globby } from 'globby';
|
|
3
|
+
import { parseFile } from './parse.js';
|
|
4
|
+
import { validateFile } from './schema.js';
|
|
5
|
+
import { normalize } from './normalize.js';
|
|
6
|
+
import { noFilesError } from './finding.js';
|
|
7
|
+
/** Process one file's text through parse, validate, and normalize. Pure, no disk. */
|
|
8
|
+
function checkContent(text, file) {
|
|
9
|
+
const parsed = parseFile(text, file);
|
|
10
|
+
if (!parsed.data) {
|
|
11
|
+
return { assignments: [], findings: parsed.findings };
|
|
12
|
+
}
|
|
13
|
+
const validated = validateFile(parsed.data, file);
|
|
14
|
+
if (!validated.data) {
|
|
15
|
+
return {
|
|
16
|
+
assignments: [],
|
|
17
|
+
findings: [
|
|
18
|
+
...parsed.findings,
|
|
19
|
+
...validated.findings,
|
|
20
|
+
],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const normalized = normalize(validated.data, file);
|
|
24
|
+
return {
|
|
25
|
+
assignments: normalized.assignments,
|
|
26
|
+
findings: [
|
|
27
|
+
...parsed.findings,
|
|
28
|
+
...validated.findings,
|
|
29
|
+
...normalized.findings,
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** Expand the globs, read every matched file, and merge into one model by union. */
|
|
34
|
+
export async function loadFiles(patterns) {
|
|
35
|
+
const files = await globby(patterns);
|
|
36
|
+
if (files.length === 0) {
|
|
37
|
+
return {
|
|
38
|
+
files,
|
|
39
|
+
assignments: [],
|
|
40
|
+
findings: [noFilesError(patterns)],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const checked = await Promise.all(files.map(async (file) => {
|
|
44
|
+
const text = await readFile(file, 'utf8');
|
|
45
|
+
return checkContent(text, file);
|
|
46
|
+
}));
|
|
47
|
+
const findings = checked.flatMap((entry) => entry.findings);
|
|
48
|
+
const collected = checked.flatMap((entry) => entry.assignments);
|
|
49
|
+
const seen = new Set();
|
|
50
|
+
const assignments = [];
|
|
51
|
+
for (const assignment of collected) {
|
|
52
|
+
const dedupeKey = `${assignment.assignee} ${assignment.kind} ${assignment.target}`;
|
|
53
|
+
if (seen.has(dedupeKey))
|
|
54
|
+
continue;
|
|
55
|
+
seen.add(dedupeKey);
|
|
56
|
+
assignments.push(assignment);
|
|
57
|
+
}
|
|
58
|
+
return { files, assignments, findings };
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/core/load.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ActualAssignment, AssignmentUpdate, DesiredAssignment, Diff, ReconcileMode } from './model.js';
|
|
2
|
+
/** A diff scoped to one mode: what it acts on, and the drift it deliberately leaves alone. */
|
|
3
|
+
export type ScopedChange = {
|
|
4
|
+
additions: DesiredAssignment[];
|
|
5
|
+
updates: AssignmentUpdate[];
|
|
6
|
+
removals: ActualAssignment[];
|
|
7
|
+
drift: {
|
|
8
|
+
adds: number;
|
|
9
|
+
updates: number;
|
|
10
|
+
removes: number;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Split a diff into what the chosen mode acts on versus the drift it leaves alone.
|
|
15
|
+
* additive skips removals, destructive skips adds and updates, sync acts on all.
|
|
16
|
+
*/
|
|
17
|
+
export declare function scopeToMode(diff: Diff, mode: ReconcileMode): ScopedChange;
|
|
18
|
+
//# sourceMappingURL=mode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mode.d.ts","sourceRoot":"","sources":["../../src/core/mode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAExG,8FAA8F;AAC9F,MAAM,MAAM,YAAY,GAAG;IACvB,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,GAAG,YAAY,CAWzE"}
|
package/lib/core/mode.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Split a diff into what the chosen mode acts on versus the drift it leaves alone.
|
|
3
|
+
* additive skips removals, destructive skips adds and updates, sync acts on all.
|
|
4
|
+
*/
|
|
5
|
+
export function scopeToMode(diff, mode) {
|
|
6
|
+
const additions = mode === 'destructive' ? [] : diff.toAdd;
|
|
7
|
+
const updates = mode === 'destructive' ? [] : diff.toUpdate;
|
|
8
|
+
const removals = mode === 'additive' ? [] : diff.toRemove;
|
|
9
|
+
const drift = {
|
|
10
|
+
adds: mode === 'destructive' ? diff.toAdd.length : 0,
|
|
11
|
+
updates: mode === 'destructive' ? diff.toUpdate.length : 0,
|
|
12
|
+
removes: mode === 'additive' ? diff.toRemove.length : 0,
|
|
13
|
+
};
|
|
14
|
+
return { additions, updates, removals, drift };
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=mode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mode.js","sourceRoot":"","sources":["../../src/core/mode.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAU,EAAE,IAAmB;IACvD,MAAM,SAAS,GAAG,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IAC3D,MAAM,OAAO,GAAG,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC;IAC5D,MAAM,QAAQ,GAAG,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC;IAC1D,MAAM,KAAK,GAAG;QACV,IAAI,EAAE,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACpD,OAAO,EAAE,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1D,OAAO,EAAE,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;KAC1D,CAAC;IAEF,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Finding } from './finding.js';
|
|
2
|
+
export type Kind = 'permissionSet' | 'permissionSetGroup' | 'permissionSetLicense';
|
|
3
|
+
/** Which half of the reconcile a run acts on. Shared by plan, apply, and the report. */
|
|
4
|
+
export type ReconcileMode = 'additive' | 'destructive' | 'sync';
|
|
5
|
+
/** Narrows which assignments a read pulls from the org. An absent field means no limit on it. */
|
|
6
|
+
export type AssignmentFilter = {
|
|
7
|
+
usernames?: string[];
|
|
8
|
+
kinds?: Kind[];
|
|
9
|
+
};
|
|
10
|
+
export type DesiredAssignment = {
|
|
11
|
+
assignee: string;
|
|
12
|
+
kind: Kind;
|
|
13
|
+
target: string;
|
|
14
|
+
/** ISO 8601 datetime the grant should expire; null for no expiration. Only permission sets and groups support it. */
|
|
15
|
+
expiration: string | null;
|
|
16
|
+
};
|
|
17
|
+
/** A user as it exists in the org, in domain terms (no SObject field names). */
|
|
18
|
+
export type OrgUser = {
|
|
19
|
+
id: string;
|
|
20
|
+
username: string;
|
|
21
|
+
isActive: boolean;
|
|
22
|
+
};
|
|
23
|
+
/** A target (permission set, group, or license) as it exists in the org. */
|
|
24
|
+
export type OrgTarget = {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
};
|
|
28
|
+
/** An assignment that currently exists in the org, carrying its record id for deletion. */
|
|
29
|
+
export type ActualAssignment = {
|
|
30
|
+
recordId: string;
|
|
31
|
+
assignee: string;
|
|
32
|
+
kind: Kind;
|
|
33
|
+
target: string;
|
|
34
|
+
/** The expiration the org has on record; null for none. */
|
|
35
|
+
expiration: string | null;
|
|
36
|
+
};
|
|
37
|
+
/** An existing assignment whose expiration should change. `expiration` null clears it. */
|
|
38
|
+
export type AssignmentUpdate = {
|
|
39
|
+
recordId: string;
|
|
40
|
+
assignee: string;
|
|
41
|
+
kind: Kind;
|
|
42
|
+
target: string;
|
|
43
|
+
expiration: string | null;
|
|
44
|
+
/** The expiration the org has now, before the update. Null means it had none. */
|
|
45
|
+
previousExpiration: string | null;
|
|
46
|
+
};
|
|
47
|
+
/** A resolved managed target: its kind and the org id it resolved to. */
|
|
48
|
+
export type TargetRef = {
|
|
49
|
+
kind: Kind;
|
|
50
|
+
id: string;
|
|
51
|
+
};
|
|
52
|
+
/** A desired assignment resolved to the ids needed to insert it. */
|
|
53
|
+
export type ResolvedAddition = DesiredAssignment & {
|
|
54
|
+
assigneeId: string;
|
|
55
|
+
targetId: string;
|
|
56
|
+
};
|
|
57
|
+
/** The change set between the desired model and the org's current state. */
|
|
58
|
+
export type Diff = {
|
|
59
|
+
toAdd: DesiredAssignment[];
|
|
60
|
+
toUpdate: AssignmentUpdate[];
|
|
61
|
+
toRemove: ActualAssignment[];
|
|
62
|
+
unchanged: ActualAssignment[];
|
|
63
|
+
};
|
|
64
|
+
/** The per-record result of one add or remove, for partial-success reporting. */
|
|
65
|
+
export type AssignmentOutcome = {
|
|
66
|
+
assignee: string;
|
|
67
|
+
kind: Kind;
|
|
68
|
+
target: string;
|
|
69
|
+
operation: 'add' | 'update' | 'remove';
|
|
70
|
+
success: boolean;
|
|
71
|
+
message?: string;
|
|
72
|
+
};
|
|
73
|
+
export type LoadResult = {
|
|
74
|
+
files: string[];
|
|
75
|
+
assignments: DesiredAssignment[];
|
|
76
|
+
findings: Finding[];
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,MAAM,IAAI,GAAG,eAAe,GAAG,oBAAoB,GAAG,sBAAsB,CAAC;AAEnF,wFAAwF;AACxF,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,aAAa,GAAG,MAAM,CAAC;AAEhE,iGAAiG;AACjG,MAAM,MAAM,gBAAgB,GAAG;IAC3B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,qHAAqH;IACrH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,gFAAgF;AAChF,MAAM,MAAM,OAAO,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,4EAA4E;AAC5E,MAAM,MAAM,SAAS,GAAG;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,2FAA2F;AAC3F,MAAM,MAAM,gBAAgB,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,0FAA0F;AAC1F,MAAM,MAAM,gBAAgB,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iFAAiF;IACjF,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,CAAC;AAEF,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG;IACpB,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,oEAAoE;AACpE,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,4EAA4E;AAC5E,MAAM,MAAM,IAAI,GAAG;IACf,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,SAAS,EAAE,gBAAgB,EAAE,CAAC;CACjC,CAAC;AAEF,iFAAiF;AACjF,MAAM,MAAM,iBAAiB,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,QAAQ,EAAE,OAAO,EAAE,CAAC;CACvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FileShape } from './schema.js';
|
|
2
|
+
import { DesiredAssignment, Kind } from './model.js';
|
|
3
|
+
import { Finding } from './finding.js';
|
|
4
|
+
export type ScopeKey = 'permissionSets' | 'permissionSetGroups' | 'permissionSetLicenses';
|
|
5
|
+
/** The (kind, file scope key) pairing, in canonical order. Shared with serialize. */
|
|
6
|
+
export declare const kindKeys: Array<[Kind, ScopeKey]>;
|
|
7
|
+
/** Map a file scope key back to its internal kind, so the CLI never leaks SObject names. */
|
|
8
|
+
export declare function kindForScopeKey(key: ScopeKey): Kind;
|
|
9
|
+
/**
|
|
10
|
+
* Turn a validated file into canonical (assignee, kind, target) tuples, and
|
|
11
|
+
* emit the structural findings: duplicate targets, empty lists, empty users.
|
|
12
|
+
*/
|
|
13
|
+
export declare function normalize(data: FileShape, file: string): {
|
|
14
|
+
assignments: DesiredAssignment[];
|
|
15
|
+
findings: Finding[];
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/core/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,OAAO,EAAwD,MAAM,cAAc,CAAC;AAE7F,MAAM,MAAM,QAAQ,GAAG,gBAAgB,GAAG,qBAAqB,GAAG,uBAAuB,CAAC;AAE1F,qFAAqF;AACrF,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAI5C,CAAC;AAEF,4FAA4F;AAC5F,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI,CAKnD;AAkED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,CAWlH"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { emptyListWarning, dupTargetWarning, emptyUserWarning } from './finding.js';
|
|
2
|
+
/** The (kind, file scope key) pairing, in canonical order. Shared with serialize. */
|
|
3
|
+
export const kindKeys = [
|
|
4
|
+
['permissionSet', 'permissionSets'],
|
|
5
|
+
['permissionSetGroup', 'permissionSetGroups'],
|
|
6
|
+
['permissionSetLicense', 'permissionSetLicenses'],
|
|
7
|
+
];
|
|
8
|
+
/** Map a file scope key back to its internal kind, so the CLI never leaks SObject names. */
|
|
9
|
+
export function kindForScopeKey(key) {
|
|
10
|
+
const pair = kindKeys.find(([, scopeKey]) => scopeKey === key);
|
|
11
|
+
if (!pair)
|
|
12
|
+
throw new Error(`Unknown scope key: ${key}`);
|
|
13
|
+
return pair[0];
|
|
14
|
+
}
|
|
15
|
+
/** A scope item in canonical form: the bare string is a target with no expiration. */
|
|
16
|
+
function scopeItemFields(item) {
|
|
17
|
+
if (typeof item === 'string')
|
|
18
|
+
return { target: item, expiration: null };
|
|
19
|
+
return { target: item.name, expiration: item.expiration };
|
|
20
|
+
}
|
|
21
|
+
function normalizeScope(username, kind, key, list, file) {
|
|
22
|
+
const items = list.map(scopeItemFields);
|
|
23
|
+
const assignments = [];
|
|
24
|
+
const findings = [];
|
|
25
|
+
const seen = new Set();
|
|
26
|
+
for (const { target, expiration } of items) {
|
|
27
|
+
if (seen.has(target)) {
|
|
28
|
+
findings.push(dupTargetWarning(username, target, key, file));
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
seen.add(target);
|
|
32
|
+
assignments.push({ assignee: username, kind, target, expiration });
|
|
33
|
+
}
|
|
34
|
+
return { assignments, findings };
|
|
35
|
+
}
|
|
36
|
+
function normalizeUser(username, entry, file) {
|
|
37
|
+
const assignments = [];
|
|
38
|
+
const findings = [];
|
|
39
|
+
let scopeCount = 0;
|
|
40
|
+
for (const [kind, key] of kindKeys) {
|
|
41
|
+
const list = entry[key];
|
|
42
|
+
if (!list)
|
|
43
|
+
continue;
|
|
44
|
+
if (list.length === 0) {
|
|
45
|
+
findings.push(emptyListWarning(username, key, file));
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
scopeCount += 1;
|
|
49
|
+
const scope = normalizeScope(username, kind, key, list, file);
|
|
50
|
+
assignments.push(...scope.assignments);
|
|
51
|
+
findings.push(...scope.findings);
|
|
52
|
+
}
|
|
53
|
+
if (scopeCount === 0) {
|
|
54
|
+
findings.push(emptyUserWarning(username, file));
|
|
55
|
+
}
|
|
56
|
+
return { assignments, findings };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Turn a validated file into canonical (assignee, kind, target) tuples, and
|
|
60
|
+
* emit the structural findings: duplicate targets, empty lists, empty users.
|
|
61
|
+
*/
|
|
62
|
+
export function normalize(data, file) {
|
|
63
|
+
const assignments = [];
|
|
64
|
+
const findings = [];
|
|
65
|
+
for (const [username, entry] of Object.entries(data.users)) {
|
|
66
|
+
const user = normalizeUser(username, entry, file);
|
|
67
|
+
assignments.push(...user.assignments);
|
|
68
|
+
findings.push(...user.findings);
|
|
69
|
+
}
|
|
70
|
+
return { assignments, findings };
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/core/normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Finding } from './finding.js';
|
|
2
|
+
/**
|
|
3
|
+
* Read one file's text into a plain object. Reports invalid YAML and duplicate
|
|
4
|
+
* keys (uniqueKeys), and treats an empty document as a warning.
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseFile(text: string, file: string): {
|
|
7
|
+
data?: unknown;
|
|
8
|
+
findings: Finding[];
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/core/parse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAA+B,MAAM,cAAc,CAAC;AAEpE;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,CAe7F"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { parseDocument } from 'yaml';
|
|
2
|
+
import { yamlError, emptyFileWarning } from './finding.js';
|
|
3
|
+
/**
|
|
4
|
+
* Read one file's text into a plain object. Reports invalid YAML and duplicate
|
|
5
|
+
* keys (uniqueKeys), and treats an empty document as a warning.
|
|
6
|
+
*/
|
|
7
|
+
export function parseFile(text, file) {
|
|
8
|
+
const doc = parseDocument(text, { uniqueKeys: true });
|
|
9
|
+
if (doc.errors.length > 0) {
|
|
10
|
+
return {
|
|
11
|
+
findings: doc.errors.map((err) => yamlError(err.message, file, err.linePos?.[0]?.line)),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const data = doc.toJS();
|
|
15
|
+
if (data == null) {
|
|
16
|
+
return { findings: [emptyFileWarning(file)] };
|
|
17
|
+
}
|
|
18
|
+
return { data, findings: [] };
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/core/parse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAW,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEpE;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,IAAY;IAChD,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IAEtD,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO;YACH,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;SAC1F,CAAC;IACN,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAa,CAAC;IACnC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;QACf,OAAO,EAAE,QAAQ,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;IAClD,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Diff, ReconcileMode } from './model.js';
|
|
2
|
+
/** What the report shows: the mode selects which operations, plus whether to list unchanged. */
|
|
3
|
+
type ReportOptions = {
|
|
4
|
+
mode: ReconcileMode;
|
|
5
|
+
showUnchanged: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Render a diff as a plan body, grouped by kind then target, with `+` adds, `~` expiration
|
|
9
|
+
* updates, `-` removes, and `=` unchanged. The mode scopes which operations appear (additive
|
|
10
|
+
* hides removes, destructive hides adds and updates), unchanged lines appear only when asked,
|
|
11
|
+
* and targets with nothing to show are omitted. Shared by plan and apply.
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatDiff(diff: Diff, options: ReportOptions): string[];
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/core/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAQ,aAAa,EAAE,MAAM,YAAY,CAAC;AAiBvD,gGAAgG;AAChG,KAAK,aAAa,GAAG;IACjB,IAAI,EAAE,aAAa,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;CAC1B,CAAC;AAqGF;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,EAAE,CAoBvE"}
|
|
@@ -0,0 +1,122 @@
|
|
|
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
|
+
if (!expiration)
|
|
35
|
+
return assignee;
|
|
36
|
+
return `${assignee} expires ${canonicalExpiration(expiration)}`;
|
|
37
|
+
}
|
|
38
|
+
/** A canonical expiration for display, with `never` standing in for no expiration. */
|
|
39
|
+
function expiryOrNever(expiration) {
|
|
40
|
+
if (!expiration)
|
|
41
|
+
return 'never';
|
|
42
|
+
return canonicalExpiration(expiration);
|
|
43
|
+
}
|
|
44
|
+
/** An update line showing the expiration transition, with `never` standing in for no expiration. */
|
|
45
|
+
function withTransition(assignee, previous, next) {
|
|
46
|
+
const from = expiryOrNever(previous);
|
|
47
|
+
const to = expiryOrNever(next);
|
|
48
|
+
return `${assignee} expires ${from} → ${to}`;
|
|
49
|
+
}
|
|
50
|
+
/** Group a diff into per-kind, per-target buckets, keeping only the operations the mode shows. */
|
|
51
|
+
function collectBuckets(diff, options) {
|
|
52
|
+
const showAdditive = options.mode !== 'destructive';
|
|
53
|
+
const showDestructive = options.mode !== 'additive';
|
|
54
|
+
const byKind = new Map();
|
|
55
|
+
if (showAdditive) {
|
|
56
|
+
for (const assignment of diff.toAdd) {
|
|
57
|
+
bucketFor(byKind, assignment.kind, assignment.target).adds.set(assignment.assignee, assignment.expiration);
|
|
58
|
+
}
|
|
59
|
+
for (const update of diff.toUpdate) {
|
|
60
|
+
bucketFor(byKind, update.kind, update.target).updates.set(update.assignee, {
|
|
61
|
+
previous: update.previousExpiration,
|
|
62
|
+
next: update.expiration,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (showDestructive) {
|
|
67
|
+
for (const assignment of diff.toRemove) {
|
|
68
|
+
bucketFor(byKind, assignment.kind, assignment.target).removes.add(assignment.assignee);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (options.showUnchanged) {
|
|
72
|
+
for (const assignment of diff.unchanged) {
|
|
73
|
+
bucketFor(byKind, assignment.kind, assignment.target).unchanged.set(assignment.assignee, assignment.expiration);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return byKind;
|
|
77
|
+
}
|
|
78
|
+
/** The `+`/`~`/`-`/`=` lines for one target, each group sorted by assignee. Empty when nothing shows. */
|
|
79
|
+
function renderBucket(bucket) {
|
|
80
|
+
const entries = [];
|
|
81
|
+
for (const assignee of [...bucket.adds.keys()].sort()) {
|
|
82
|
+
entries.push(` + ${withExpiry(assignee, bucket.adds.get(assignee) ?? null)}`);
|
|
83
|
+
}
|
|
84
|
+
for (const assignee of [...bucket.updates.keys()].sort()) {
|
|
85
|
+
const change = bucket.updates.get(assignee);
|
|
86
|
+
entries.push(` ~ ${withTransition(assignee, change.previous, change.next)}`);
|
|
87
|
+
}
|
|
88
|
+
for (const assignee of [...bucket.removes].sort())
|
|
89
|
+
entries.push(` - ${assignee}`);
|
|
90
|
+
for (const assignee of [...bucket.unchanged.keys()].sort()) {
|
|
91
|
+
entries.push(` = ${withExpiry(assignee, bucket.unchanged.get(assignee) ?? null)}`);
|
|
92
|
+
}
|
|
93
|
+
return entries;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Render a diff as a plan body, grouped by kind then target, with `+` adds, `~` expiration
|
|
97
|
+
* updates, `-` removes, and `=` unchanged. The mode scopes which operations appear (additive
|
|
98
|
+
* hides removes, destructive hides adds and updates), unchanged lines appear only when asked,
|
|
99
|
+
* and targets with nothing to show are omitted. Shared by plan and apply.
|
|
100
|
+
*/
|
|
101
|
+
export function formatDiff(diff, options) {
|
|
102
|
+
const byKind = collectBuckets(diff, options);
|
|
103
|
+
const lines = [];
|
|
104
|
+
for (const [kind] of kindKeys) {
|
|
105
|
+
const byTarget = byKind.get(kind);
|
|
106
|
+
if (!byTarget)
|
|
107
|
+
continue;
|
|
108
|
+
const sorted = [...byTarget].sort((left, right) => left[0].localeCompare(right[0]));
|
|
109
|
+
const targetLines = [];
|
|
110
|
+
for (const [target, bucket] of sorted) {
|
|
111
|
+
const entries = renderBucket(bucket);
|
|
112
|
+
if (entries.length === 0)
|
|
113
|
+
continue;
|
|
114
|
+
targetLines.push(` ${target}`, ...entries);
|
|
115
|
+
}
|
|
116
|
+
if (targetLines.length === 0)
|
|
117
|
+
continue;
|
|
118
|
+
lines.push(kindLabels[kind], ...targetLines);
|
|
119
|
+
}
|
|
120
|
+
return lines;
|
|
121
|
+
}
|
|
122
|
+
//# 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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"}
|