@syntax-syllogism/warden-core 0.2.0

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.
Files changed (191) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE +21 -0
  3. package/README.md +111 -0
  4. package/lib/access/assignees.d.ts +27 -0
  5. package/lib/access/assignees.js +139 -0
  6. package/lib/access/assignees.js.map +1 -0
  7. package/lib/access/messages.d.ts +1 -0
  8. package/lib/access/messages.js +24 -0
  9. package/lib/access/messages.js.map +1 -0
  10. package/lib/access/metadata.d.ts +41 -0
  11. package/lib/access/metadata.js +168 -0
  12. package/lib/access/metadata.js.map +1 -0
  13. package/lib/access/muting.d.ts +7 -0
  14. package/lib/access/muting.js +22 -0
  15. package/lib/access/muting.js.map +1 -0
  16. package/lib/access/output.d.ts +12 -0
  17. package/lib/access/output.js +108 -0
  18. package/lib/access/output.js.map +1 -0
  19. package/lib/access/resolvers/field.d.ts +2 -0
  20. package/lib/access/resolvers/field.js +93 -0
  21. package/lib/access/resolvers/field.js.map +1 -0
  22. package/lib/access/resolvers/index.d.ts +2 -0
  23. package/lib/access/resolvers/index.js +22 -0
  24. package/lib/access/resolvers/index.js.map +1 -0
  25. package/lib/access/resolvers/object.d.ts +2 -0
  26. package/lib/access/resolvers/object.js +101 -0
  27. package/lib/access/resolvers/object.js.map +1 -0
  28. package/lib/access/resolvers/recordType.d.ts +2 -0
  29. package/lib/access/resolvers/recordType.js +181 -0
  30. package/lib/access/resolvers/recordType.js.map +1 -0
  31. package/lib/access/resolvers/setupEntity.d.ts +4 -0
  32. package/lib/access/resolvers/setupEntity.js +43 -0
  33. package/lib/access/resolvers/setupEntity.js.map +1 -0
  34. package/lib/access/resolvers/tab.d.ts +2 -0
  35. package/lib/access/resolvers/tab.js +36 -0
  36. package/lib/access/resolvers/tab.js.map +1 -0
  37. package/lib/access/reverse.d.ts +9 -0
  38. package/lib/access/reverse.js +429 -0
  39. package/lib/access/reverse.js.map +1 -0
  40. package/lib/access/soql.d.ts +6 -0
  41. package/lib/access/soql.js +31 -0
  42. package/lib/access/soql.js.map +1 -0
  43. package/lib/access/targetValidation.d.ts +7 -0
  44. package/lib/access/targetValidation.js +110 -0
  45. package/lib/access/targetValidation.js.map +1 -0
  46. package/lib/access/types.d.ts +88 -0
  47. package/lib/access/types.js +20 -0
  48. package/lib/access/types.js.map +1 -0
  49. package/lib/errors.d.ts +18 -0
  50. package/lib/errors.js +39 -0
  51. package/lib/errors.js.map +1 -0
  52. package/lib/index.d.ts +37 -0
  53. package/lib/index.js +33 -0
  54. package/lib/index.js.map +1 -0
  55. package/lib/lifecycle/assignmentState.d.ts +62 -0
  56. package/lib/lifecycle/assignmentState.js +89 -0
  57. package/lib/lifecycle/assignmentState.js.map +1 -0
  58. package/lib/lifecycle/conformance.d.ts +10 -0
  59. package/lib/lifecycle/conformance.js +59 -0
  60. package/lib/lifecycle/conformance.js.map +1 -0
  61. package/lib/lifecycle/diffOutput.d.ts +7 -0
  62. package/lib/lifecycle/diffOutput.js +94 -0
  63. package/lib/lifecycle/diffOutput.js.map +1 -0
  64. package/lib/lifecycle/dmlRunner.d.ts +30 -0
  65. package/lib/lifecycle/dmlRunner.js +45 -0
  66. package/lib/lifecycle/dmlRunner.js.map +1 -0
  67. package/lib/lifecycle/errors.d.ts +5 -0
  68. package/lib/lifecycle/errors.js +8 -0
  69. package/lib/lifecycle/errors.js.map +1 -0
  70. package/lib/lifecycle/freezeState.d.ts +28 -0
  71. package/lib/lifecycle/freezeState.js +88 -0
  72. package/lib/lifecycle/freezeState.js.map +1 -0
  73. package/lib/lifecycle/messages.d.ts +1 -0
  74. package/lib/lifecycle/messages.js +20 -0
  75. package/lib/lifecycle/messages.js.map +1 -0
  76. package/lib/lifecycle/output.d.ts +23 -0
  77. package/lib/lifecycle/output.js +148 -0
  78. package/lib/lifecycle/output.js.map +1 -0
  79. package/lib/lifecycle/snapshotState.d.ts +12 -0
  80. package/lib/lifecycle/snapshotState.js +353 -0
  81. package/lib/lifecycle/snapshotState.js.map +1 -0
  82. package/lib/lifecycle/stripApply.d.ts +3 -0
  83. package/lib/lifecycle/stripApply.js +17 -0
  84. package/lib/lifecycle/stripApply.js.map +1 -0
  85. package/lib/lifecycle/stripPlan.d.ts +75 -0
  86. package/lib/lifecycle/stripPlan.js +192 -0
  87. package/lib/lifecycle/stripPlan.js.map +1 -0
  88. package/lib/lifecycle/targeting.d.ts +32 -0
  89. package/lib/lifecycle/targeting.js +195 -0
  90. package/lib/lifecycle/targeting.js.map +1 -0
  91. package/lib/lifecycle/types.d.ts +88 -0
  92. package/lib/lifecycle/types.js +2 -0
  93. package/lib/lifecycle/types.js.map +1 -0
  94. package/lib/lifecycle/userDiff.d.ts +70 -0
  95. package/lib/lifecycle/userDiff.js +393 -0
  96. package/lib/lifecycle/userDiff.js.map +1 -0
  97. package/lib/matching/index.d.ts +53 -0
  98. package/lib/matching/index.js +181 -0
  99. package/lib/matching/index.js.map +1 -0
  100. package/lib/provisioning/assignmentPlan.d.ts +53 -0
  101. package/lib/provisioning/assignmentPlan.js +90 -0
  102. package/lib/provisioning/assignmentPlan.js.map +1 -0
  103. package/lib/provisioning/definitionReader.d.ts +38 -0
  104. package/lib/provisioning/definitionReader.js +77 -0
  105. package/lib/provisioning/definitionReader.js.map +1 -0
  106. package/lib/provisioning/errors.d.ts +9 -0
  107. package/lib/provisioning/errors.js +14 -0
  108. package/lib/provisioning/errors.js.map +1 -0
  109. package/lib/provisioning/licenseUsage.d.ts +15 -0
  110. package/lib/provisioning/licenseUsage.js +53 -0
  111. package/lib/provisioning/licenseUsage.js.map +1 -0
  112. package/lib/provisioning/messages.d.ts +4 -0
  113. package/lib/provisioning/messages.js +72 -0
  114. package/lib/provisioning/messages.js.map +1 -0
  115. package/lib/provisioning/planner.d.ts +63 -0
  116. package/lib/provisioning/planner.js +407 -0
  117. package/lib/provisioning/planner.js.map +1 -0
  118. package/lib/provisioning/provisionUserUseCase.d.ts +52 -0
  119. package/lib/provisioning/provisionUserUseCase.js +200 -0
  120. package/lib/provisioning/provisionUserUseCase.js.map +1 -0
  121. package/lib/provisioning/referenceResolution.d.ts +4 -0
  122. package/lib/provisioning/referenceResolution.js +173 -0
  123. package/lib/provisioning/referenceResolution.js.map +1 -0
  124. package/lib/provisioning/userPlan.d.ts +85 -0
  125. package/lib/provisioning/userPlan.js +162 -0
  126. package/lib/provisioning/userPlan.js.map +1 -0
  127. package/lib/provisioning/userSave.d.ts +24 -0
  128. package/lib/provisioning/userSave.js +119 -0
  129. package/lib/provisioning/userSave.js.map +1 -0
  130. package/lib/relatedRecords/apply.d.ts +18 -0
  131. package/lib/relatedRecords/apply.js +121 -0
  132. package/lib/relatedRecords/apply.js.map +1 -0
  133. package/lib/relatedRecords/catalog.d.ts +7 -0
  134. package/lib/relatedRecords/catalog.js +108 -0
  135. package/lib/relatedRecords/catalog.js.map +1 -0
  136. package/lib/relatedRecords/errors.d.ts +5 -0
  137. package/lib/relatedRecords/errors.js +8 -0
  138. package/lib/relatedRecords/errors.js.map +1 -0
  139. package/lib/relatedRecords/messages.d.ts +1 -0
  140. package/lib/relatedRecords/messages.js +2 -0
  141. package/lib/relatedRecords/messages.js.map +1 -0
  142. package/lib/relatedRecords/plan.d.ts +22 -0
  143. package/lib/relatedRecords/plan.js +271 -0
  144. package/lib/relatedRecords/plan.js.map +1 -0
  145. package/lib/relatedRecords/preflight.d.ts +29 -0
  146. package/lib/relatedRecords/preflight.js +164 -0
  147. package/lib/relatedRecords/preflight.js.map +1 -0
  148. package/lib/relatedRecords/sources.d.ts +25 -0
  149. package/lib/relatedRecords/sources.js +65 -0
  150. package/lib/relatedRecords/sources.js.map +1 -0
  151. package/lib/relatedRecords/types.d.ts +46 -0
  152. package/lib/relatedRecords/types.js +2 -0
  153. package/lib/relatedRecords/types.js.map +1 -0
  154. package/lib/shared/csv.d.ts +26 -0
  155. package/lib/shared/csv.js +237 -0
  156. package/lib/shared/csv.js.map +1 -0
  157. package/lib/shared/output.d.ts +25 -0
  158. package/lib/shared/output.js +74 -0
  159. package/lib/shared/output.js.map +1 -0
  160. package/lib/shared/prompt.d.ts +4 -0
  161. package/lib/shared/prompt.js +15 -0
  162. package/lib/shared/prompt.js.map +1 -0
  163. package/lib/shared/sfUtils.d.ts +19 -0
  164. package/lib/shared/sfUtils.js +42 -0
  165. package/lib/shared/sfUtils.js.map +1 -0
  166. package/lib/shared/userFields.d.ts +23 -0
  167. package/lib/shared/userFields.js +41 -0
  168. package/lib/shared/userFields.js.map +1 -0
  169. package/lib/spec/index.d.ts +10 -0
  170. package/lib/spec/index.js +6 -0
  171. package/lib/spec/index.js.map +1 -0
  172. package/lib/spec/parse.d.ts +32 -0
  173. package/lib/spec/parse.js +77 -0
  174. package/lib/spec/parse.js.map +1 -0
  175. package/lib/spec/personaDefinitions.d.ts +56 -0
  176. package/lib/spec/personaDefinitions.js +25 -0
  177. package/lib/spec/personaDefinitions.js.map +1 -0
  178. package/lib/spec/relatedCatalog.d.ts +61 -0
  179. package/lib/spec/relatedCatalog.js +32 -0
  180. package/lib/spec/relatedCatalog.js.map +1 -0
  181. package/lib/spec/snapshot.d.ts +42 -0
  182. package/lib/spec/snapshot.js +32 -0
  183. package/lib/spec/snapshot.js.map +1 -0
  184. package/lib/spec/usersDefinition.d.ts +19 -0
  185. package/lib/spec/usersDefinition.js +21 -0
  186. package/lib/spec/usersDefinition.js.map +1 -0
  187. package/package.json +78 -0
  188. package/schemas/persona-definitions.schema.json +108 -0
  189. package/schemas/related-catalog.schema.json +141 -0
  190. package/schemas/snapshot.schema.json +128 -0
  191. package/schemas/users-definition.schema.json +36 -0
@@ -0,0 +1,200 @@
1
+ import { runBatches } from '../shared/sfUtils.js';
2
+ import { resolveExistingUsers, usableMatchValue } from '../matching/index.js';
3
+ import { describeUserFields } from '../shared/userFields.js';
4
+ import { assertValidRelatedCatalog } from '../relatedRecords/catalog.js';
5
+ import { applyRelatedPhase } from '../relatedRecords/apply.js';
6
+ import { buildRelatedPlans } from '../relatedRecords/plan.js';
7
+ import { emptyPreflightResult, runRelatedPreflight } from '../relatedRecords/preflight.js';
8
+ import { deriveMyDomain, validateAndCanonicalizeUsers, validateExternalIdFieldForFlag, validatePersonaModes, } from './planner.js';
9
+ import { loadValidatedDefinitions, } from './definitionReader.js';
10
+ import { calculateUserLicenseUsage } from './licenseUsage.js';
11
+ import { resolveReferences } from './referenceResolution.js';
12
+ import { provisioningMessage } from './messages.js';
13
+ import { appendCrossReferenceCandidates, buildUserPlans, identityFromTarget, summarize, toUserResult, } from './userPlan.js';
14
+ import { applySavedPlan, executeBulkUserSaves, markRelatedUnapplied, planDryRunResult } from './userSave.js';
15
+ const provisionDefinitionMessages = {
16
+ invalidPersonaDefinition: () => provisioningMessage('errorInvalidPersonaDefinition'),
17
+ personasWithoutDefinition: (userKey) => provisioningMessage('errorPersonasWithoutDefinition', [userKey]),
18
+ invalidJson: (path, error) => provisioningMessage('errorInvalidJson', [path, error]),
19
+ };
20
+ const addSourceContext = (source, errors) => source ? errors.map((error) => `${source.path}:${source.line} — ${error}`) : errors;
21
+ const USER_PROCESS_CONCURRENCY = 10;
22
+ export const getExistingUsers = async (conn, users, options) => {
23
+ const requests = users.flatMap((user) => {
24
+ const field = user.matchField ?? options.defaultExternalIdField;
25
+ const value = field ? usableMatchValue(user.fields[field]) : null;
26
+ return field && value !== null
27
+ ? [{ field, value, fuzzy: field === 'Username' && (user.fuzzyUsername ?? options.defaultFuzzyUsername ?? false) }]
28
+ : [];
29
+ });
30
+ const { existingByField, duplicates } = await resolveExistingUsers(conn, requests, options.fieldMap);
31
+ return { existingByField, duplicates };
32
+ };
33
+ const message = provisioningMessage;
34
+ const loadAndValidate = async (request, describeCache) => {
35
+ if (request.usersDoc) {
36
+ const definitions = await loadValidatedDefinitions(request, new Map(), provisionDefinitionMessages);
37
+ return { fieldMap: await describeUserFields(request.connection, describeCache), definitions };
38
+ }
39
+ const fieldMap = await describeUserFields(request.connection, describeCache);
40
+ const definitions = await loadValidatedDefinitions(request, fieldMap, provisionDefinitionMessages);
41
+ return { fieldMap, definitions };
42
+ };
43
+ const validationResultsFor = (validationFailureUsers) => validationFailureUsers.map(({ user, order }) => {
44
+ const matchedBy = user.matchField ?? null;
45
+ const matchValue = matchedBy ? usableMatchValue(user.fields[matchedBy]) : null;
46
+ return {
47
+ planId: `${order}:${user.inputKey}:${user.personas.join('+')}:validation`,
48
+ order,
49
+ key: user.inputKey,
50
+ ...identityFromTarget(user.fields),
51
+ personas: user.personas,
52
+ matchedBy,
53
+ matchValue,
54
+ // These users never reached matching, so nothing was matched.
55
+ matched: false,
56
+ status: 'failed',
57
+ actions: [],
58
+ errors: (user.validationErrors ?? []).map((error) => message(error.code, error.messageArgs)),
59
+ source: user.source,
60
+ };
61
+ });
62
+ const assembleResult = (resultsWithOrder, refs, licenseUsage, dryRun) => {
63
+ const results = resultsWithOrder
64
+ .sort((a, b) => a.order - b.order)
65
+ .map((result) => ({
66
+ key: result.key,
67
+ id: result.id,
68
+ userName: result.userName,
69
+ username: result.username,
70
+ personas: result.personas,
71
+ matchedBy: result.matchedBy ?? null,
72
+ matchValue: result.matchValue,
73
+ matched: result.matched,
74
+ status: result.status,
75
+ actions: result.actions,
76
+ errors: addSourceContext(result.source, result.errors),
77
+ ...(result.relatedRecords ? { relatedRecords: result.relatedRecords } : {}),
78
+ }));
79
+ const result = {
80
+ summary: summarize(results, refs.warnings.length + (licenseUsage?.filter((license) => license.shortfall > 0).length ?? 0)),
81
+ users: results,
82
+ };
83
+ if (dryRun) {
84
+ result.licenses = licenseUsage;
85
+ result.permissionSetLicenses = { evaluated: false, note: 'not evaluated' };
86
+ }
87
+ return result;
88
+ };
89
+ const selectedRelationships = (validUsers) => [
90
+ ...new Set(validUsers.flatMap(({ user }) => user.related ?? [])),
91
+ ];
92
+ const loadRelatedCatalog = (definitions, fieldMap) => definitions.relatedDoc ? assertValidRelatedCatalog(definitions.relatedDoc, fieldMap, message) : undefined;
93
+ export class ProvisionUserUseCase {
94
+ userProcessConcurrency = USER_PROCESS_CONCURRENCY;
95
+ async runDryRun(conn, plans, refs, validationResults) {
96
+ const plannedResults = await runBatches(plans, this.userProcessConcurrency, (plan) => planDryRunResult({ conn, plan, refs }));
97
+ return validationResults.concat(plannedResults);
98
+ }
99
+ async runLive(conn, plans, refs, validationResults) {
100
+ const invalidResults = plans
101
+ .filter((plan) => plan.errors.length > 0)
102
+ .map((plan) => toUserResult(markRelatedUnapplied(plan), 'failed', { includeExistingId: false }));
103
+ const outcomes = await executeBulkUserSaves(conn, plans);
104
+ const saveFailures = outcomes
105
+ .filter((outcome) => !outcome.success)
106
+ .map((outcome) => toUserResult(markRelatedUnapplied(outcome.plan), 'failed', {
107
+ errors: appendCrossReferenceCandidates(outcome.errors, outcome.plan.target),
108
+ includeExistingId: false,
109
+ }));
110
+ const savedOutcomes = outcomes.filter((outcome) => outcome.success);
111
+ // Related records are written between the User save and the per-user post-save work,
112
+ // as one bulk stage per sObject. `executeBulkUserSaves` above is untouched.
113
+ const relatedByPlanId = await applyRelatedPhase(conn, savedOutcomes
114
+ .filter((outcome) => outcome.plan.relatedPlans && outcome.id)
115
+ .map((outcome) => ({
116
+ planId: outcome.plan.planId,
117
+ relatedPlans: outcome.plan.relatedPlans,
118
+ savedUserId: outcome.id,
119
+ })), 'after');
120
+ for (const outcome of savedOutcomes) {
121
+ const related = relatedByPlanId.get(outcome.plan.planId);
122
+ if (related) {
123
+ outcome.plan.relatedResults = related;
124
+ outcome.plan.errors.push(...related
125
+ .filter((result) => result.status === 'failed' && result.error)
126
+ .map((result) => result.error));
127
+ }
128
+ }
129
+ const postSaveResults = await runBatches(savedOutcomes, this.userProcessConcurrency, (outcome) => applySavedPlan({ conn, outcome, refs, message }));
130
+ return validationResults.concat(invalidResults, saveFailures, postSaveResults);
131
+ }
132
+ // eslint-disable-next-line @typescript-eslint/member-ordering
133
+ async execute(request) {
134
+ const conn = request.connection;
135
+ // Per-run describe cache: shared by User and every relationship sObject, never module-level.
136
+ const describeCache = new Map();
137
+ const { fieldMap, definitions } = await loadAndValidate(request, describeCache);
138
+ const { usersDoc, personasDoc } = definitions;
139
+ const personasSupplied = request.personasSupplied ?? definitions.personasSupplied;
140
+ const personas = personasDoc.personas;
141
+ validatePersonaModes(personas);
142
+ validateExternalIdFieldForFlag(request.externalId, fieldMap);
143
+ const catalog = loadRelatedCatalog(definitions, fieldMap);
144
+ const users = validateAndCanonicalizeUsers(usersDoc.users, personas, fieldMap, personasSupplied, {
145
+ catalogSupplied: Boolean(catalog),
146
+ names: new Set(Object.keys(catalog?.relationships ?? {})),
147
+ });
148
+ const myDomain = deriveMyDomain(conn.instanceUrl);
149
+ const defaultExternalIdField = request.externalId
150
+ ? fieldMap.get(request.externalId.toLowerCase())?.name
151
+ : undefined;
152
+ const userEntries = users.map((user, order) => ({ user, order }));
153
+ const validationFailureUsers = userEntries.filter(({ user }) => user.validationErrors && user.validationErrors.length > 0);
154
+ const validUsers = userEntries.filter(({ user }) => !user.validationErrors || user.validationErrors.length === 0);
155
+ const [refs, existingResolution, preflight] = await Promise.all([
156
+ resolveReferences(conn, personas, validUsers.map(({ user }) => user)),
157
+ getExistingUsers(conn, validUsers.map(({ user }) => user), {
158
+ defaultExternalIdField,
159
+ defaultFuzzyUsername: request.fuzzyUsername,
160
+ fieldMap,
161
+ }),
162
+ catalog
163
+ ? runRelatedPreflight({
164
+ conn,
165
+ catalog,
166
+ selected: selectedRelationships(validUsers),
167
+ cache: describeCache,
168
+ message,
169
+ })
170
+ : Promise.resolve(emptyPreflightResult()),
171
+ ]);
172
+ // Ineligible relationships join the same warning list, so operators still see exactly
173
+ // one confirmation and declining exits before any DML.
174
+ refs.warnings.push(...preflight.warnings);
175
+ // TODO(wdc-command-use-cases): replace this prompt-shaped callback with plan/apply.
176
+ if (refs.warnings.length > 0)
177
+ await request.acknowledgeWarnings?.(refs.warnings);
178
+ const relatedPlansByOrder = catalog
179
+ ? await buildRelatedPlans({ conn, users: validUsers, catalog, preflight, userFieldMap: fieldMap, message })
180
+ : undefined;
181
+ const plans = buildUserPlans({
182
+ validUsers,
183
+ refs,
184
+ existing: existingResolution,
185
+ fieldMap,
186
+ defaultExternalIdField,
187
+ myDomain,
188
+ dryRun: request.dryRun,
189
+ message,
190
+ relatedPlansByOrder,
191
+ });
192
+ const licenseUsage = request.dryRun ? await calculateUserLicenseUsage(conn, plans) : undefined;
193
+ const validationResults = validationResultsFor(validationFailureUsers);
194
+ const results = request.dryRun
195
+ ? await this.runDryRun(conn, plans, refs, validationResults)
196
+ : await this.runLive(conn, plans, refs, validationResults);
197
+ return assembleResult(results, refs, licenseUsage, request.dryRun);
198
+ }
199
+ }
200
+ //# sourceMappingURL=provisionUserUseCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provisionUserUseCase.js","sourceRoot":"","sources":["../../src/provisioning/provisionUserUseCase.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Connection } from '@salesforce/core';
2
+ import type { ResolvedRefs } from './assignmentPlan.js';
3
+ import { type CanonicalizedUser, type PersonaDefinition } from './planner.js';
4
+ export declare const resolveReferences: (conn: Connection, personas: Record<string, PersonaDefinition>, users: CanonicalizedUser[]) => Promise<ResolvedRefs>;
@@ -0,0 +1,173 @@
1
+ import { soqlIn } from '../shared/sfUtils.js';
2
+ import { isSalesforceId } from './planner.js';
3
+ import { provisioningMessage } from './messages.js';
4
+ const collectPersonaRefs = (personas) => {
5
+ const refs = {
6
+ profiles: new Set(),
7
+ roles: new Set(),
8
+ permissionSets: new Set(),
9
+ permissionSetGroups: new Set(),
10
+ publicGroups: new Set(),
11
+ queues: new Set(),
12
+ };
13
+ for (const persona of Object.values(personas)) {
14
+ if (persona.profile)
15
+ refs.profiles.add(persona.profile);
16
+ if (persona.role)
17
+ refs.roles.add(persona.role);
18
+ for (const value of persona.permissionSets ?? [])
19
+ refs.permissionSets.add(value);
20
+ for (const value of persona.permissionSetGroups ?? [])
21
+ refs.permissionSetGroups.add(value);
22
+ for (const value of persona.publicGroups ?? [])
23
+ refs.publicGroups.add(value);
24
+ for (const value of persona.queues ?? [])
25
+ refs.queues.add(value);
26
+ }
27
+ return refs;
28
+ };
29
+ const addReferenceLabel = (labels, row, apiNameField, labelField, type) => {
30
+ const apiName = row[apiNameField];
31
+ const label = labelField ? row[labelField] : apiName;
32
+ labels[row.Id] = {
33
+ id: row.Id,
34
+ ...(apiName ? { apiName } : {}),
35
+ ...(label ? { label } : {}),
36
+ type,
37
+ };
38
+ };
39
+ const resolveByIdOrName = async ({ conn, table, idOrNameRefs, nameField, whereClause, warnings, idPrefixes, labelField, type, labels, }) => {
40
+ const resolved = new Map();
41
+ const fields = ['Id', nameField, labelField].filter((field) => Boolean(field));
42
+ const ids = [...idOrNameRefs].filter((ref) => isSalesforceId(ref) && (!idPrefixes || idPrefixes.includes(ref.slice(0, 3))));
43
+ const names = [...idOrNameRefs].filter((ref) => !isSalesforceId(ref));
44
+ if (ids.length > 0) {
45
+ const where = [`Id IN (${soqlIn(ids)})`, whereClause].filter(Boolean).join(' AND ');
46
+ const rows = (await conn.query(`SELECT ${fields.join(', ')} FROM ${table} WHERE ${where}`)).records;
47
+ for (const row of rows) {
48
+ resolved.set(row.Id, row.Id);
49
+ addReferenceLabel(labels, row, nameField, labelField, type);
50
+ }
51
+ }
52
+ if (names.length > 0) {
53
+ const where = [`${nameField} IN (${soqlIn(names)})`, whereClause].filter(Boolean).join(' AND ');
54
+ const rows = (await conn.query(`SELECT ${fields.join(', ')} FROM ${table} WHERE ${where}`)).records;
55
+ for (const row of rows) {
56
+ resolved.set(row[nameField], row.Id);
57
+ addReferenceLabel(labels, row, nameField, labelField, type);
58
+ }
59
+ }
60
+ for (const ref of idOrNameRefs) {
61
+ if (!resolved.has(ref))
62
+ warnings.push(provisioningMessage('warningReferenceMissing', [table, ref]));
63
+ }
64
+ return resolved;
65
+ };
66
+ const resolveByRoleRef = async (conn, refs, warnings, labels) => {
67
+ const resolved = new Map();
68
+ const ids = [...refs].filter((ref) => isSalesforceId(ref) && ref.startsWith('00E'));
69
+ const names = [...refs].filter((ref) => !isSalesforceId(ref));
70
+ if (ids.length > 0) {
71
+ const rows = (await conn.query(`SELECT Id, DeveloperName, Name FROM UserRole WHERE Id IN (${soqlIn(ids)})`)).records;
72
+ for (const row of rows) {
73
+ resolved.set(row.Id, row.Id);
74
+ addReferenceLabel(labels, row, 'DeveloperName', 'Name', 'UserRole');
75
+ }
76
+ }
77
+ if (names.length > 0) {
78
+ const rows = (await conn.query(`SELECT Id, DeveloperName, Name FROM UserRole WHERE DeveloperName IN (${soqlIn(names)}) OR Name IN (${soqlIn(names)})`)).records;
79
+ for (const row of rows) {
80
+ if (row.DeveloperName && names.includes(row.DeveloperName))
81
+ resolved.set(row.DeveloperName, row.Id);
82
+ if (row.Name && names.includes(row.Name))
83
+ resolved.set(row.Name, row.Id);
84
+ addReferenceLabel(labels, row, 'DeveloperName', 'Name', 'UserRole');
85
+ }
86
+ }
87
+ for (const ref of refs) {
88
+ if (!resolved.has(ref))
89
+ warnings.push(provisioningMessage('warningReferenceMissing', ['UserRole', ref]));
90
+ }
91
+ return resolved;
92
+ };
93
+ export const resolveReferences = async (conn, personas, users) => {
94
+ const warnings = [];
95
+ const labels = {};
96
+ const refs = collectPersonaRefs(personas);
97
+ for (const user of users) {
98
+ if (user.profileRef)
99
+ refs.profiles.add(user.profileRef);
100
+ if (user.roleRef)
101
+ refs.roles.add(user.roleRef);
102
+ }
103
+ const [profilesByRef, rolesByRef, permissionSetIdsByRef, permissionSetGroupIdsByRef, publicGroupIdsByRef, queueIdsByRef,] = await Promise.all([
104
+ resolveByIdOrName({
105
+ conn,
106
+ table: 'Profile',
107
+ idOrNameRefs: refs.profiles,
108
+ nameField: 'Name',
109
+ warnings,
110
+ idPrefixes: ['00e'],
111
+ type: 'Profile',
112
+ labels,
113
+ }),
114
+ resolveByRoleRef(conn, refs.roles, warnings, labels),
115
+ resolveByIdOrName({
116
+ conn,
117
+ table: 'PermissionSet',
118
+ idOrNameRefs: refs.permissionSets,
119
+ nameField: 'Name',
120
+ warnings,
121
+ idPrefixes: ['0PS'],
122
+ labelField: 'Label',
123
+ type: 'PermissionSet',
124
+ labels,
125
+ }),
126
+ resolveByIdOrName({
127
+ conn,
128
+ table: 'PermissionSetGroup',
129
+ idOrNameRefs: refs.permissionSetGroups,
130
+ nameField: 'DeveloperName',
131
+ warnings,
132
+ idPrefixes: ['0PG'],
133
+ labelField: 'MasterLabel',
134
+ type: 'PermissionSetGroup',
135
+ labels,
136
+ }),
137
+ resolveByIdOrName({
138
+ conn,
139
+ table: 'Group',
140
+ idOrNameRefs: refs.publicGroups,
141
+ nameField: 'DeveloperName',
142
+ whereClause: "Type = 'Regular'",
143
+ warnings,
144
+ idPrefixes: ['00G'],
145
+ labelField: 'Name',
146
+ type: 'PublicGroup',
147
+ labels,
148
+ }),
149
+ resolveByIdOrName({
150
+ conn,
151
+ table: 'Group',
152
+ idOrNameRefs: refs.queues,
153
+ nameField: 'DeveloperName',
154
+ whereClause: "Type = 'Queue'",
155
+ warnings,
156
+ idPrefixes: ['00G'],
157
+ labelField: 'Name',
158
+ type: 'Queue',
159
+ labels,
160
+ }),
161
+ ]);
162
+ return {
163
+ profilesByRef,
164
+ rolesByRef,
165
+ permissionSetIdsByRef,
166
+ permissionSetGroupIdsByRef,
167
+ publicGroupIdsByRef,
168
+ queueIdsByRef,
169
+ labels,
170
+ warnings,
171
+ };
172
+ };
173
+ //# sourceMappingURL=referenceResolution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"referenceResolution.js","sourceRoot":"","sources":["../../src/provisioning/referenceResolution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import { type ExistingUser } from '../matching/index.js';
2
+ import type { RelatedRecordPlan, RelatedRecordResult } from '../relatedRecords/types.js';
3
+ import type { CsvRowInfo } from '../shared/csv.js';
4
+ import { type CanonicalizedUser, type PersonaDefinition, type UserFieldMeta } from './planner.js';
5
+ import type { ResolvedRefs } from './assignmentPlan.js';
6
+ type JsonRecord = Record<string, unknown>;
7
+ export type UserPlan = {
8
+ planId: string;
9
+ order: number;
10
+ key: string;
11
+ personas: string[];
12
+ effectivePersona: PersonaDefinition;
13
+ matchedBy: string | null;
14
+ /** The value looked up under `matchedBy`; null when no lookup was issued under it. */
15
+ matchValue: string | null;
16
+ target: JsonRecord;
17
+ existing?: ExistingUser;
18
+ actions: string[];
19
+ errors: string[];
20
+ source?: CsvRowInfo;
21
+ /** `after`-phase related-record plans for this user, when `--related-def` is in play. */
22
+ relatedPlans?: RelatedRecordPlan[];
23
+ /** Reported related-record outcomes, filled in by the dry-run or live related stage. */
24
+ relatedResults?: RelatedRecordResult[];
25
+ };
26
+ export type UserResult = {
27
+ key: string;
28
+ id?: string;
29
+ userName?: string;
30
+ username?: string;
31
+ personas: string[];
32
+ matchedBy: string | null;
33
+ /** The value looked up under `matchedBy`; null when no lookup was issued under it. */
34
+ matchValue: string | null;
35
+ /**
36
+ * Whether an existing user was actually found. `matchedBy` only reports that a match
37
+ * field was configured, so it cannot stand in for this on a net-new user.
38
+ */
39
+ matched: boolean;
40
+ status: 'created' | 'updated' | 'failed' | 'planned';
41
+ actions: string[];
42
+ errors: string[];
43
+ relatedRecords?: RelatedRecordResult[];
44
+ };
45
+ export type OrderedUserResult = UserResult & {
46
+ order: number;
47
+ planId: string;
48
+ source?: CsvRowInfo;
49
+ };
50
+ export declare const identityFromTarget: (target: JsonRecord, existing?: ExistingUser) => {
51
+ userName?: string;
52
+ username?: string;
53
+ };
54
+ export declare const buildTarget: (user: CanonicalizedUser, refs: ResolvedRefs, errors: string[]) => JsonRecord;
55
+ export declare const appendCrossReferenceCandidates: (errors: string[], target: JsonRecord) => string[];
56
+ export declare const buildUserPlans: (options: {
57
+ validUsers: Array<{
58
+ user: CanonicalizedUser;
59
+ order: number;
60
+ }>;
61
+ refs: ResolvedRefs;
62
+ existing: {
63
+ existingByField: Map<string, Map<string, ExistingUser>>;
64
+ duplicates: Set<string>;
65
+ };
66
+ fieldMap: Map<string, UserFieldMeta>;
67
+ defaultExternalIdField?: string;
68
+ myDomain?: string;
69
+ dryRun: boolean;
70
+ message?: (key: string, args?: string[]) => string;
71
+ relatedPlansByOrder?: Map<number, RelatedRecordPlan[]>;
72
+ }) => UserPlan[];
73
+ export declare const toUserResult: (plan: UserPlan, status: UserResult["status"], overrides?: {
74
+ id?: string;
75
+ errors?: string[];
76
+ includeExistingId?: boolean;
77
+ }) => OrderedUserResult;
78
+ export declare const summarize: (results: UserResult[], globalWarningCount: number) => {
79
+ total: number;
80
+ created: number;
81
+ updated: number;
82
+ failed: number;
83
+ warnings: number;
84
+ };
85
+ export {};
@@ -0,0 +1,162 @@
1
+ import { matchKey, usableMatchValue } from '../matching/index.js';
2
+ import { buildDefaultAlias, buildDefaultUsername, missingRequiredFieldsForInsert, } from './planner.js';
3
+ import { provisioningMessage } from './messages.js';
4
+ export const identityFromTarget = (target, existing) => ({
5
+ userName: existing?.Name ??
6
+ (typeof target.Name === 'string'
7
+ ? target.Name
8
+ : [target.FirstName, target.LastName]
9
+ .filter((value) => typeof value === 'string' && value.length > 0)
10
+ .join(' ') || undefined),
11
+ username: existing?.Username ?? (typeof target.Username === 'string' ? target.Username : undefined),
12
+ });
13
+ const ensureWritableFields = (target, existing, fieldMap, errors) => {
14
+ for (const field of Object.keys(target)) {
15
+ if (field === 'Id')
16
+ continue;
17
+ const meta = fieldMap.get(field.toLowerCase());
18
+ if (!meta)
19
+ continue;
20
+ if (existing ? !meta.updateable : !meta.createable) {
21
+ errors.push(provisioningMessage('errorFieldNotWritable', [field, existing ? 'updateable' : 'createable']));
22
+ }
23
+ }
24
+ };
25
+ export const buildTarget = (user, refs, errors) => {
26
+ const persona = user.effectivePersona;
27
+ const target = { ...user.fields, IsActive: true };
28
+ // Profile: user profileRef > user raw ProfileId (already in target) > persona profile
29
+ if (user.profileRef) {
30
+ const profileId = refs.profilesByRef.get(user.profileRef);
31
+ if (!profileId)
32
+ errors.push(provisioningMessage('errorReferenceRequiredMissing', ['Profile', user.profileRef]));
33
+ else
34
+ target.ProfileId = profileId;
35
+ }
36
+ else if (!target.ProfileId && persona.profile) {
37
+ const profileId = refs.profilesByRef.get(persona.profile);
38
+ if (!profileId)
39
+ errors.push(provisioningMessage('errorReferenceRequiredMissing', ['Profile', persona.profile]));
40
+ else
41
+ target.ProfileId = profileId;
42
+ }
43
+ // Role: user roleRef > user raw UserRoleId (already in target) > persona role
44
+ if (user.roleRef) {
45
+ const roleId = refs.rolesByRef.get(user.roleRef);
46
+ if (!roleId)
47
+ errors.push(provisioningMessage('errorReferenceRequiredMissing', ['UserRole', user.roleRef]));
48
+ else
49
+ target.UserRoleId = roleId;
50
+ }
51
+ else if (!target.UserRoleId && persona.role) {
52
+ const roleId = refs.rolesByRef.get(persona.role);
53
+ if (!roleId)
54
+ errors.push(provisioningMessage('errorReferenceRequiredMissing', ['UserRole', persona.role]));
55
+ else
56
+ target.UserRoleId = roleId;
57
+ }
58
+ return target;
59
+ };
60
+ const applyInsertDefaults = (target, myDomain) => {
61
+ if (!target.Username && myDomain) {
62
+ const username = buildDefaultUsername(target.Email, myDomain);
63
+ if (username)
64
+ target.Username = username;
65
+ }
66
+ if (!target.Alias) {
67
+ const alias = buildDefaultAlias(target.FirstName, target.LastName);
68
+ if (alias)
69
+ target.Alias = alias;
70
+ }
71
+ };
72
+ export const appendCrossReferenceCandidates = (errors, target) => {
73
+ const hasCrossRefError = errors.some((error) => error.includes('INVALID_CROSS_REFERENCE_KEY'));
74
+ if (!hasCrossRefError)
75
+ return errors;
76
+ const candidateFields = Object.entries(target)
77
+ .filter(([field]) => field.endsWith('Id') && field !== 'Id')
78
+ .map(([field, value]) => `${field}=${String(value)}`);
79
+ if (candidateFields.length === 0)
80
+ return errors;
81
+ return errors.concat(provisioningMessage('errorCrossReferenceCandidates', [candidateFields.join(', ')]));
82
+ };
83
+ const resolveExistingUser = (matchedBy, target, existing) => {
84
+ const matchValue = matchedBy ? target[matchedBy] : undefined;
85
+ if (!matchedBy || typeof matchValue !== 'string')
86
+ return { matchValue };
87
+ return { matchValue, existingUser: existing.existingByField.get(matchedBy)?.get(matchValue) };
88
+ };
89
+ export const buildUserPlans = (options) => {
90
+ const { validUsers, refs, existing, fieldMap, defaultExternalIdField, myDomain, dryRun, message = provisioningMessage, } = options;
91
+ return validUsers.map(({ user, order }) => {
92
+ const effectivePersona = user.effectivePersona;
93
+ const errors = [];
94
+ const target = buildTarget(user, refs, errors);
95
+ const matchedBy = user.matchField ?? defaultExternalIdField ?? null;
96
+ const { matchValue, existingUser } = resolveExistingUser(matchedBy, target, existing);
97
+ if (matchedBy && typeof matchValue === 'string' && existing.duplicates.has(matchKey(matchedBy, matchValue))) {
98
+ errors.push(message('errorDuplicateExternalIdMatch', [matchedBy, matchValue]));
99
+ }
100
+ if (!existingUser) {
101
+ applyInsertDefaults(target, myDomain);
102
+ const profileIntended = Boolean(user.profileRef) || Boolean(effectivePersona.profile);
103
+ const missing = missingRequiredFieldsForInsert(target, profileIntended);
104
+ if (missing.length > 0)
105
+ errors.push(message('errorMissingRequiredFields', [missing.join(', ')]));
106
+ }
107
+ ensureWritableFields(target, existingUser, fieldMap, errors);
108
+ const actions = [existingUser ? (dryRun ? 'wouldUpdate' : 'updated') : dryRun ? 'wouldCreate' : 'created'];
109
+ if (!existingUser || existingUser.IsActive !== true)
110
+ actions.push(dryRun ? 'wouldActivate' : 'activated');
111
+ const relatedPlans = options.relatedPlansByOrder?.get(order);
112
+ // A related planning failure (ambiguity, collision, unresolvable source) fails the user
113
+ // before any DML, which is exactly what a non-empty `errors` list already means here.
114
+ for (const relatedPlan of relatedPlans ?? [])
115
+ errors.push(...relatedPlan.errors);
116
+ return {
117
+ planId: `${order}:${user.inputKey}:${user.personas.join('+')}`,
118
+ order,
119
+ key: user.inputKey,
120
+ personas: user.personas,
121
+ effectivePersona,
122
+ matchedBy,
123
+ matchValue: usableMatchValue(matchValue),
124
+ target,
125
+ existing: existingUser,
126
+ actions,
127
+ errors,
128
+ source: user.source,
129
+ ...(relatedPlans ? { relatedPlans } : {}),
130
+ };
131
+ });
132
+ };
133
+ export const toUserResult = (plan, status, overrides) => ({
134
+ planId: plan.planId,
135
+ order: plan.order,
136
+ key: plan.key,
137
+ ...identityFromTarget(plan.target, plan.existing),
138
+ ...(overrides?.id
139
+ ? { id: overrides.id }
140
+ : overrides?.includeExistingId === false
141
+ ? {}
142
+ : plan.existing
143
+ ? { id: plan.existing.Id }
144
+ : {}),
145
+ personas: plan.personas,
146
+ matchedBy: plan.matchedBy,
147
+ matchValue: plan.matchValue,
148
+ matched: Boolean(plan.existing),
149
+ status,
150
+ actions: plan.actions,
151
+ errors: overrides?.errors ?? plan.errors,
152
+ ...(plan.relatedResults && plan.relatedResults.length > 0 ? { relatedRecords: plan.relatedResults } : {}),
153
+ source: plan.source,
154
+ });
155
+ export const summarize = (results, globalWarningCount) => ({
156
+ total: results.length,
157
+ created: results.filter((result) => result.status === 'created').length,
158
+ updated: results.filter((result) => result.status === 'updated').length,
159
+ failed: results.filter((result) => result.status === 'failed').length,
160
+ warnings: globalWarningCount,
161
+ });
162
+ //# sourceMappingURL=userPlan.js.map